diff --git a/frontend/src/components/module-editor/LessonItem.tsx b/frontend/src/components/module-editor/LessonItem.tsx index acd57734..047fe434 100644 --- a/frontend/src/components/module-editor/LessonItem.tsx +++ b/frontend/src/components/module-editor/LessonItem.tsx @@ -1,76 +1,88 @@ import React, { useState } from "react"; import { Button, IconButton, Flex } from "@chakra-ui/react"; import { EditIcon, DeleteIcon } from "@chakra-ui/icons"; +import { Draggable } from "react-beautiful-dnd"; import { ReactComponent as DragHandleIconSvg } from "../../assets/DragHandle.svg"; interface OptionsProps { + id: string; text: string; isFocused: boolean; setFocus: () => void; + index: number; } +/* eslint-disable react/jsx-props-no-spreading */ + const LessonItem = ({ - text = "", + id, + text, isFocused, setFocus, + index, }: OptionsProps): React.ReactElement => { const [isHovered, setIsHovered] = useState(false); - return ( - <> - - + + )} + ); }; diff --git a/frontend/src/components/module-editor/SideBar.tsx b/frontend/src/components/module-editor/SideBar.tsx index db574503..e0b68b9b 100644 --- a/frontend/src/components/module-editor/SideBar.tsx +++ b/frontend/src/components/module-editor/SideBar.tsx @@ -69,6 +69,7 @@ const Sidebar = (): React.ReactElement => { refetchQueries: [ { query: GET_COURSE, + variables: { id: courseID } }, ], }, @@ -124,38 +125,45 @@ const Sidebar = (): React.ReactElement => { oldID: string, changedLesson: LessonRequest, ) => { + console.log(oldID); const { data } = await createLesson({ variables: { lesson: changedLesson }, }); if (!data) throw Error("Failed to create new lesson"); - const lesson = data.createLesson; - const { id: newID } = lesson; + // const lesson = data.createLesson; + // const { id: newID } = lesson; // Update lesson ID in state with response - dispatch({ type: "update-lesson-id", value: { oldID, newID } }); + dispatch({ type: "update-lesson-id", value: { oldID, newID: 'test' } }); }; const saveChanges = async (changeObj: EditorChangeStatuses) => { + console.log(changeObj); Object.entries(changeObj).forEach(async ([doc_id, action]) => { - const changedLesson = formatLessonRequest(state.lessons[doc_id]); + switch (action) { case "CREATE": // Await required so we can get a new ID - await createNewLesson(doc_id, changedLesson); + await createNewLesson(doc_id, formatLessonRequest(state.lessons[doc_id])); break; case "UPDATE": - updateLesson({ variables: { id: doc_id, lesson: changedLesson } }); + updateLesson({ variables: { id: doc_id, lesson: formatLessonRequest(state.lessons[doc_id]) } }); break; case "DELETE": deleteLesson({ variables: { id: doc_id } }); break; + case "COURSE-UPDATE": + // Nothing happens because the updateCourse mutation is already called at the end anyway + break; // Make compiler happy default: break; - } - updateCourse({ - variables: { id: changedLesson.course, course: state.course }, - }); + } }); + return; + updateCourse({ + variables: { id: courseID, course: state.course }, + }); + state.hasChanged = {}; }; diff --git a/frontend/src/components/module-editor/SideBarModuleOverview.tsx b/frontend/src/components/module-editor/SideBarModuleOverview.tsx index ffee03f1..98ceee92 100644 --- a/frontend/src/components/module-editor/SideBarModuleOverview.tsx +++ b/frontend/src/components/module-editor/SideBarModuleOverview.tsx @@ -3,13 +3,41 @@ import { AddIcon } from "@chakra-ui/icons"; import React, { useContext, useState } from "react"; import { useParams } from "react-router-dom"; +import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd"; import EditorContext from "../../contexts/ModuleEditorContext"; -import { ModuleEditorParams } from "../../types/ModuleEditorTypes"; +import { + EditorContextAction, + ModuleEditorParams, +} from "../../types/ModuleEditorTypes"; import { Modal } from "../common/Modal"; import { TextInput } from "../common/TextInput"; import LessonItem from "./LessonItem"; +// Copy drag implementation based on https://github.com/atlassian/react-beautiful-dnd/issues/216#issuecomment-423708497 +const onDragEnd = ( + dispatch: React.Dispatch, + result: DropResult, + moduleID: number, +) => { + const { source, destination } = result; + // dropped outside the list + if ( + source?.droppableId !== "LESSON_EDITOR" || + destination?.droppableId !== "LESSON_EDITOR" + ) { + return; + } + dispatch({ + type: "reorder-lessons", + value: { + moduleID, + oldIndex: source.index, + newIndex: destination.index, + }, + }); +}; + const SideBarModuleOverview = (): React.ReactElement => { const context = useContext(EditorContext); const { isOpen, onOpen, onClose } = useDisclosure(); @@ -25,8 +53,6 @@ const SideBarModuleOverview = (): React.ReactElement => { const { lessons, course, focusedLesson } = state; const module = course.modules[moduleID]; - const orderedLessons = module.lessons.map((id) => lessons[id]); - const setFocus = (index: number) => dispatch({ type: "set-focus", value: module.lessons[index] }); @@ -57,15 +83,29 @@ const SideBarModuleOverview = (): React.ReactElement => { return ( - {focusedLesson && - orderedLessons.map((lesson, index) => ( - setFocus(index)} - /> - ))} + {focusedLesson && ( + onDragEnd(dispatch, result, moduleID)} + > + + {(provided) => ( + + {module.lessons.map((id, index) => ( + setFocus(index)} + index={index} + /> + ))} + {provided.placeholder} + + )} + + + )}