diff --git a/src/config/constants.ts b/src/config/constants.ts index b228049..2e908ec 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -1,4 +1,3 @@ export const FILE_UPLOAD_MAX_FILES = 1; -export const ADD_LABEL_FRAME_WIDTH = 600; export const ADD_LABEL_FRAME_HEIGHT = 600; diff --git a/src/langs/constants.ts b/src/langs/constants.ts index 6d68d35..d8a0ffc 100644 --- a/src/langs/constants.ts +++ b/src/langs/constants.ts @@ -15,4 +15,5 @@ export const APP = { ADD: 'ADD', DRAG_DROP_EXERCISE_TITLE: 'DRAG_DROP_EXERCISE_TITLE', SAVE: 'SAVE', + PREVIEW_NOTE: 'PREVIEW_NOTE', }; diff --git a/src/langs/en.json b/src/langs/en.json index 0006327..033752b 100644 --- a/src/langs/en.json +++ b/src/langs/en.json @@ -15,5 +15,6 @@ "REPLACE_IMAGE": "Replace the image", "ADD": "Add", "DRAG_DROP_EXERCISE_TITLE": "Drag and drop these labels into the correct frame of the image", - "SAVE": "Save" + "SAVE": "Save", + "PREVIEW_NOTE": "Here is what your application will look like from the player's perspective. To modify any settings, please return to the previous steps." } diff --git a/src/modules/builder/configuration/AddLabelsStep/AddDraggableLabel.tsx b/src/modules/builder/configuration/AddLabelsStep/AddDraggableLabel.tsx index fc84f57..086a78a 100644 --- a/src/modules/builder/configuration/AddLabelsStep/AddDraggableLabel.tsx +++ b/src/modules/builder/configuration/AddLabelsStep/AddDraggableLabel.tsx @@ -14,10 +14,7 @@ import { PermissionLevel } from '@graasp/sdk'; import { v4 } from 'uuid'; import { Label } from '@/@types'; -import { - ADD_LABEL_FRAME_HEIGHT, - ADD_LABEL_FRAME_WIDTH, -} from '@/config/constants'; +import { ADD_LABEL_FRAME_HEIGHT } from '@/config/constants'; import AddLabelForm from './AddLabelForm'; import DraggableLabel from './DraggableLabel'; @@ -27,6 +24,7 @@ type Props = { imageSettingId: string; labels: Label[]; setLabels: (l: Label[]) => void; + saveData: (l: Label[]) => void; }; const TransformContainer = styled(TransformWrapper)(() => ({ @@ -48,6 +46,7 @@ const AddDraggableLabel = ({ labels, setLabels, imageSettingId, + saveData, }: Props): JSX.Element => { const { instance } = useControls(); const { permission } = useLocalContext(); @@ -57,7 +56,6 @@ const AddDraggableLabel = ({ y: 0, x: 0, }); - const [isDragging, setIsDragging] = useState(false); const { scale, positionX, positionY } = instance.transformState; @@ -86,6 +84,7 @@ const AddDraggableLabel = ({ ...labels.slice(editingIndex + 1), ]; setLabels(newLabelGroups); + saveData(newLabelGroups); } else { const id = v4(); const p = { @@ -94,6 +93,7 @@ const AddDraggableLabel = ({ }; const newLabel = { ...p, id, content: labelText }; setLabels([...labels, newLabel]); + saveData([...labels, newLabel]); } setOpenForm(false); setLabelText(''); @@ -114,7 +114,7 @@ const AddDraggableLabel = ({ } }; - const onStop = ( + const onDrag = ( e: DraggableEvent, position: DraggableData, labelId: string, @@ -127,10 +127,9 @@ const AddDraggableLabel = ({ const label = labels[labelInd]; const p = { - left: x, - top: y, + x, + y, }; - const newLabel = { ...label, ...p }; const newLabelGroups = [ ...labels.slice(0, labelInd), @@ -144,6 +143,7 @@ const AddDraggableLabel = ({ const deleteLabel = (labelId: string): void => { const filteredLabels = labels.filter(({ id }) => labelId !== id); setLabels(filteredLabels); + saveData(filteredLabels); }; const editLabel = (labelId: string): void => { @@ -164,7 +164,7 @@ const AddDraggableLabel = ({ {permission === PermissionLevel.Admin && openForm && !isDragging && ( @@ -182,13 +182,14 @@ const AddDraggableLabel = ({ - onStop(e, p, ele.id) + onDrag={(e: DraggableEvent, p: DraggableData) => + onDrag(e, p, ele.id) } deleteLabel={deleteLabel} editLabel={editLabel} scale={scale} setIsDragging={setIsDragging} + onStop={() => saveData(labels)} /> ))} @@ -200,18 +201,21 @@ const AddDraggableLabelWrapper = ({ imageSettingId, labels, setLabels, + saveData, }: Props): JSX.Element => ( diff --git a/src/modules/builder/configuration/AddLabelsStep/AddLabelForm.tsx b/src/modules/builder/configuration/AddLabelsStep/AddLabelForm.tsx index 5f84675..c2828b1 100644 --- a/src/modules/builder/configuration/AddLabelsStep/AddLabelForm.tsx +++ b/src/modules/builder/configuration/AddLabelsStep/AddLabelForm.tsx @@ -28,7 +28,6 @@ const AddLabelForm = ({ { + const saveData = (l: Label[]): void => { if (settingsData && imgRef?.current) { const { width, height } = imgRef.current.getBoundingClientRect(); const imageDimension = { width, height }; - const data = { ...settingsData.data, labels, imageDimension }; + const data = { ...settingsData.data, labels: l, imageDimension }; patchSetting({ id: settingsData?.id, data }); } - moveToNextStep(); + // moveToNextStep(); }; return ( @@ -52,6 +52,7 @@ const AddLabelsStep = ({ imageSettingId={image?.id} labels={labels} setLabels={setLabels} + saveData={saveData} /> )} @@ -61,7 +62,7 @@ const AddLabelsStep = ({ - ); diff --git a/src/modules/builder/configuration/index.tsx b/src/modules/builder/configuration/index.tsx index 3ab188b..9124d87 100644 --- a/src/modules/builder/configuration/index.tsx +++ b/src/modules/builder/configuration/index.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { Stack, Step, StepButton, Stepper } from '@mui/material'; @@ -15,7 +15,6 @@ import PreviewStep from './PreviewStep'; const Configurations = (): JSX.Element => { const { t } = useAppTranslation(); - const [activeStep, setActiveStep] = useState(0); const { data: imageSetting } = hooks.useAppSettings({ name: SettingsKeys.File, @@ -27,6 +26,18 @@ const Configurations = (): JSX.Element => { const image = imageSetting?.[0]; const settingsData = settings?.[0]; + const [activeStep, setActiveStep] = useState(0); + + const initialSetRef = useRef(false); + + useEffect(() => { + if (!initialSetRef.current && settingsData?.data) { + if (settingsData.data.labels) { + setActiveStep(2); + } + initialSetRef.current = true; + } + }, [settingsData]); const steps = [ { diff --git a/src/modules/common/DraggableFrameWithLabels.tsx b/src/modules/common/DraggableFrameWithLabels.tsx index 4eec681..b4d1cd7 100644 --- a/src/modules/common/DraggableFrameWithLabels.tsx +++ b/src/modules/common/DraggableFrameWithLabels.tsx @@ -21,7 +21,11 @@ const DraggableFrameWithLabels = ({ }: Props): JSX.Element => { const renderDraggableLabels = (): JSX.Element | JSX.Element[] => { const Labels = labels.map((label) => ( - + )); return Labels; diff --git a/src/modules/common/DroppableDraggableLabel.tsx b/src/modules/common/DroppableDraggableLabel.tsx index c2e2d24..d3684bd 100644 --- a/src/modules/common/DroppableDraggableLabel.tsx +++ b/src/modules/common/DroppableDraggableLabel.tsx @@ -11,58 +11,71 @@ export const Container = styled('div')<{ left: string; isFilled: boolean; isDraggingOver: boolean; -}>(({ theme, isAllGroup, top, left, isFilled, isDraggingOver }) => ({ - display: 'flex', - gap: theme.spacing(1), - flexWrap: 'wrap', - borderRadius: theme.spacing(1), - background: isDraggingOver ? 'lightgray' : 'white', - ...(isAllGroup - ? { - width: '100%', - height: '40px', - padding: '2px', - border: '1px solid black', - } - : { - position: 'absolute', - top, - left, - [theme.breakpoints.down('sm')]: { - transform: 'scale(0.5)', - transformOrigin: 'top left', - }, + isDragging?: boolean; +}>( + ({ theme, isAllGroup, top, left, isFilled, isDraggingOver, isDragging }) => ({ + display: 'flex', + gap: theme.spacing(1), + flexWrap: 'wrap', + borderRadius: theme.spacing(1), + background: isDraggingOver ? 'lightgray' : 'white', + ...(isAllGroup + ? { + width: '100%', + minHeight: '40px', + padding: '2px', + border: '1px solid black', + } + : { + position: 'absolute', + top, + left, + [theme.breakpoints.down('sm')]: { + transform: 'scale(0.5)', + transformOrigin: 'top left', + }, + }), + ...(!isFilled && + !isAllGroup && { + minHeight: '4ch', + minWidth: '8ch', + border: isDraggingOver ? 'none' : '1px solid black', + }), + ...(isDragging && + !isFilled && { + border: `2px solid ${theme.palette.primary.main}`, + transform: 'scale(1.1)', }), - ...(!isFilled && { - minHeight: '4ch', - minWidth: '8ch', - border: isDraggingOver ? 'none' : '1px solid black', }), -})); +); export const StyledLabel = styled('div')<{ isDraggable: boolean; }>(({ theme, isDraggable }) => ({ - background: theme.palette.primary.main, color: 'white', borderRadius: theme.spacing(1), gap: theme.spacing(1), userSelect: 'none', border: '1px solid white', padding: theme.spacing(0.5), - ...(isDraggable && { - left: 'initial !important', - top: 'initial !important', - background: 'purple', - }), + + ...(isDraggable + ? { + left: 'initial !important', + top: 'initial !important', + background: 'purple', + } + : { + background: theme.palette.primary.main, + }), })); type Props = { label: DraggableLabelType; - draggingOverItem?: boolean; + isDragging?: boolean; }; -const DroppableDraggableLabel = ({ label }: Props): JSX.Element => ( +const DroppableDraggableLabel = ({ label, isDragging }: Props): JSX.Element => ( {(provided, dropSnapshot) => ( ( left={label.x} isFilled={label.choices.length > 0} isDraggingOver={dropSnapshot.isDraggingOver} + isDragging={isDragging} > {label.choices?.map((item, index) => (
@@ -83,6 +97,7 @@ const DroppableDraggableLabel = ({ label }: Props): JSX.Element => ( {...dragProvided.draggableProps} {...dragProvided.dragHandleProps} isDraggable={dragSnapshot.isDragging} + // style={dragProvided.draggableProps.style} > { const appLabels = appSettings?.[0].data.labels; const imageDimension = appSettings?.[0].data.imageDimension; if (imageDimension) { - const wStart = ADD_LABEL_FRAME_WIDTH - imageDimension.width; + const wStart = 0; const hStart = ADD_LABEL_FRAME_HEIGHT - imageDimension.height; if (appLabels) { const labelsP = appLabels.map((l, index) => ({