diff --git a/app/css/bootcamp/components/solve-exercise-page.css b/app/css/bootcamp/components/solve-exercise-page.css index 32fbf2f469..04fb497b14 100644 --- a/app/css/bootcamp/components/solve-exercise-page.css +++ b/app/css/bootcamp/components/solve-exercise-page.css @@ -72,6 +72,63 @@ .btn-primary { @apply bg-bootcamp-purple; } + .autorun-button { + @apply btn-primary btn-s; + @apply flex items-stretch; + @apply p-0; + + box-shadow: 0px 3px 6px rgba(var(--shadowColorMain), 0.4); + + .primary-segment, + .autorun-segment { + transition: background 0.1s ease-in; + } + &:not(:disabled):not(.--disabled):hover { + @apply bg-purple !important; + } + + .primary-segment { + @apply flex items-center; + @apply font-semibold; + @apply px-16; + @apply border-r-1 border-borderColor3; + + &.disabled { + @apply bg-purpleDarkened; + opacity: 0.5; + cursor: not-allowed; + } + + &:not(.disabled) { + &:hover { + @apply !bg-purpleDarkened; + } + } + } + .autorun-segment { + @apply grid place-items-center px-12; + @apply rounded-r-3; + & .c-icon { + height: 18px; + width: 18px; + } + + &:hover { + @apply bg-purpleDarkened; + } + &.on { + @apply bg-purpleDarkened; + & .c-icon { + @apply filter-lightGold; + } + } + &.off { + & .c-icon { + @apply filter-white; + } + } + } + } } body.namespace-bootcamp.controller-exercises.action-edit { diff --git a/app/images/bootcamp/autorun.svg b/app/images/bootcamp/autorun.svg new file mode 100644 index 0000000000..cc7b39722c --- /dev/null +++ b/app/images/bootcamp/autorun.svg @@ -0,0 +1 @@ +Ai Redo Spark Streamline Icon: https://streamlinehq.com \ No newline at end of file diff --git a/app/images/bootcamp/edit.svg b/app/images/bootcamp/edit.svg new file mode 100644 index 0000000000..d13605284c --- /dev/null +++ b/app/images/bootcamp/edit.svg @@ -0,0 +1 @@ +Pencil 2 Streamline Icon: https://streamlinehq.com \ No newline at end of file diff --git a/app/javascript/components/bootcamp/DrawingPage/DrawingPage.tsx b/app/javascript/components/bootcamp/DrawingPage/DrawingPage.tsx index 0a865f86b5..5b99cfcf0f 100644 --- a/app/javascript/components/bootcamp/DrawingPage/DrawingPage.tsx +++ b/app/javascript/components/bootcamp/DrawingPage/DrawingPage.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from 'react' +import React, { useCallback, useMemo, useState } from 'react' import { Header, StudentCodeGetter } from './Header/Header' import { Resizer, @@ -11,6 +11,11 @@ import { useLocalStorage } from '@uidotdev/usehooks' import Scrubber from '../SolveExercisePage/Scrubber/Scrubber' import { debounce } from 'lodash' import { useSetupDrawingPage } from './useSetupDrawingPage' +import SolveExercisePageContextWrapper from '../SolveExercisePage/SolveExercisePageContextWrapper' +import useEditorStore from '../SolveExercisePage/store/editorStore' +import { assembleClassNames } from '@/utils/assemble-classnames' +import { Icon } from '@/components/common' +import { StaticTooltip } from '../SolveExercisePage/Scrubber/ScrubberTooltipInformation' export default function DrawingPage({ drawing, @@ -27,9 +32,8 @@ export default function DrawingPage({ } = useResizablePanels({ initialSize: 800, direction: 'horizontal', - localStorageId: 'drawing-page-lhs', + localStorageId: 'solve-exercise-page-lhs', }) - const { handleRunCode, handleEditorDidMount, @@ -61,36 +65,92 @@ export default function DrawingPage({ }, 5000) }, [setEditorLocalStorageValue]) + const { shouldAutoRunCode, toggleShouldAutoRunCode } = useEditorStore() + const handleToggleAutoRun = useCallback( + (shouldAutoRunCode: boolean) => { + if (!shouldAutoRunCode) { + handleRunCode() + } + toggleShouldAutoRunCode() + }, + [shouldAutoRunCode] + ) + return ( -
-
-
-
- - - - -
- - {/* RHS */} -
-
+ +
+
+
+
+ + + +
+
+ + +
+ +
+
+
+ + {/* RHS */} +
+
+
-
+
) } diff --git a/app/javascript/components/bootcamp/DrawingPage/Header/Header.tsx b/app/javascript/components/bootcamp/DrawingPage/Header/Header.tsx index 61eb6f31a9..c3eb5bc721 100644 --- a/app/javascript/components/bootcamp/DrawingPage/Header/Header.tsx +++ b/app/javascript/components/bootcamp/DrawingPage/Header/Header.tsx @@ -18,10 +18,12 @@ function _Header({ setBackgroundImage: ((imageUrl: string | null) => void) | null } & Pick) { const [titleInputValue, setTitleInputValue] = useState(drawing.title) + const [prevTitleInputValue, setPrevTitleInputValue] = useState(drawing.title) const [editMode, setEditMode] = useState(false) const [titleSavingStateLabel, setTitleSavingStateLabel] = useState( DEFAULT_SAVE_BUTTON_LABEL ) + const inputRef = React.useRef(null) const handleSaveTitle = useCallback(() => { setTitleSavingStateLabel('Saving...') @@ -43,6 +45,22 @@ function _Header({ [setBackgroundImage] ) + const handleSwitchToEditMode = useCallback(() => { + setEditMode(true) + setPrevTitleInputValue(titleInputValue) + }, [titleInputValue]) + + const handleCancelEditMode = useCallback(() => { + setTitleInputValue(prevTitleInputValue) + setEditMode(false) + }, [prevTitleInputValue]) + + useEffect(() => { + if (editMode) { + inputRef.current?.focus() + } + }, [editMode]) + // setup the background on mount useEffect(() => { if (setBackgroundImage && drawing.backgroundSlug) { @@ -77,7 +95,8 @@ function _Header({ ) handleBackgroundChange(selectedBackground) }} - value={drawing.backgroundSlug} + className="bg-backgroundColorD rounded-5 py-4 px-8 font-medium" + defaultValue={drawing.backgroundSlug} > {backgrounds.map((background) => (