diff --git a/package.json b/package.json index 56e2c41f..c091dfbc 100644 --- a/package.json +++ b/package.json @@ -64,10 +64,6 @@ "rxjs": "6.x" }, "devDependencies": { - "@dnd-kit/core": "^6.1.0", - "@dnd-kit/modifiers": "^6.0.1", - "@dnd-kit/sortable": "^7.0.2", - "@dnd-kit/utilities": "^3.2.2", "@openmrs/esm-framework": "next", "@openmrs/esm-patient-common-lib": "next", "@openmrs/esm-styleguide": "next", diff --git a/src/components/interactive-builder/droppable-container.component.tsx b/src/components/interactive-builder/droppable-container.component.tsx deleted file mode 100644 index 7ecaf85d..00000000 --- a/src/components/interactive-builder/droppable-container.component.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; -import classNames from 'classnames'; -import { useDroppable } from '@dnd-kit/core'; -import styles from './droppable-container.scss'; - -interface DroppableProps { - id: string; - children: React.ReactNode; -} - -function Droppable({ id, children }: DroppableProps) { - const { isOver, setNodeRef } = useDroppable({ - id: id, - }); - - return ( -
- {children} -
- ); -} - -export default Droppable; diff --git a/src/components/interactive-builder/droppable-container.scss b/src/components/interactive-builder/droppable-container.scss deleted file mode 100644 index 746e8048..00000000 --- a/src/components/interactive-builder/droppable-container.scss +++ /dev/null @@ -1,9 +0,0 @@ -@use '@carbon/colors'; - -.droppable { - border: 1px solid transparent; -} - -.isOver { - border-color: colors.$teal-70; -} diff --git a/src/components/interactive-builder/interactive-builder.component.tsx b/src/components/interactive-builder/interactive-builder.component.tsx index b1f55f01..3487746e 100644 --- a/src/components/interactive-builder/interactive-builder.component.tsx +++ b/src/components/interactive-builder/interactive-builder.component.tsx @@ -1,17 +1,13 @@ import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import type { DragEndEvent } from '@dnd-kit/core'; -import { DndContext, KeyboardSensor, MouseSensor, closestCorners, useSensor, useSensors } from '@dnd-kit/core'; import { Accordion, AccordionItem, Button, InlineLoading } from '@carbon/react'; import { Add, TrashCan } from '@carbon/react/icons'; import { useParams } from 'react-router-dom'; import { showModal, showSnackbar } from '@openmrs/esm-framework'; import type { FormSchema } from '@openmrs/openmrs-form-engine-lib'; - import type { Schema, Question } from '../../types'; -import DraggableQuestion from './draggable-question.component'; -import Droppable from './droppable-container.component'; import EditableValue from './editable-value.component'; +import QuestionBlock from './question-block.component'; import styles from './interactive-builder.scss'; interface ValidationError { @@ -33,14 +29,6 @@ const InteractiveBuilder: React.FC = ({ schema, validationResponse, }) => { - const mouseSensor = useSensor(MouseSensor, { - activationConstraint: { - distance: 10, // Enable sort function when dragging 10px 💡 here!!! - }, - }); - const keyboardSensor = useSensor(KeyboardSensor); - const sensors = useSensors(mouseSensor, keyboardSensor); - const { t } = useTranslation(); const { formUuid } = useParams<{ formUuid: string }>(); const isEditingExistingForm = Boolean(formUuid); @@ -242,48 +230,6 @@ const InteractiveBuilder: React.FC = ({ [onSchemaChange, schema, t], ); - const handleDragEnd = (event: DragEndEvent) => { - const { active, delta } = event; - - if (active) { - // Get the source information - const activeIdParts = active.id.toString().split('-'); - const sourcePageIndex = parseInt(activeIdParts[1]); - const sourceSectionIndex = parseInt(activeIdParts[2]); - const sourceQuestionIndex = parseInt(activeIdParts[3]); - - // Move the question within the same section - const questions = schema.pages[sourcePageIndex].sections[sourceSectionIndex].questions; - const questionToMove = questions[sourceQuestionIndex]; - questions.splice(sourceQuestionIndex, 1); - questions.splice(sourceQuestionIndex + delta.y, 0, questionToMove); - - const updatedSchema = { - ...schema, - pages: schema.pages.map((page, pageIndex) => { - if (pageIndex === sourcePageIndex) { - return { - ...page, - sections: page.sections.map((section, sectionIndex) => { - if (sectionIndex === sourceSectionIndex) { - return { - ...section, - questions: [...questions], - }; - } - return section; - }), - }; - } - return page; - }), - }; - - // Update your state or data structure with the updated schema - onSchemaChange(updatedSchema); - } - }; - const getAnswerErrors = (answers: Array>) => { const answerLabels = answers?.map((answer) => answer.label) || []; const errors: Array = validationResponse.filter((error) => @@ -358,153 +304,146 @@ const InteractiveBuilder: React.FC = ({ )} - handleDragEnd(event)} - sensors={sensors} - > - {schema?.pages?.length - ? schema.pages.map((page, pageIndex) => ( -
-
-
- renamePage(name, pageIndex)} - /> -
-
-
- {section.questions?.length ? ( - section.questions.map((question, questionIndex) => { - return ( - - - {getValidationError(question) && ( -
- {getValidationError(question)} -
- )} - {getAnswerErrors(question.questionOptions.answers)?.length ? ( -
-
Answer Errors
- {getAnswerErrors(question.questionOptions.answers)?.map((error) => ( -
{`${error.field.label}: ${error.errorMessage}`}
- ))} -
- ) : null} -
- ); - }) - ) : ( -

- {t( - 'sectionExplainer', - 'A section will typically contain one or more questions. Click the button below to add a question to this section.', - )} -

- )} - - -
- - - - )) - ) : ( -

- {t( - 'pageExplainer', - 'Pages typically have one or more sections. Click the button below to add a section to your page.', - )} -

- )} -
+ renderIcon={(props) => } + size="sm" + /> - )) - : null} -
+
+ {page?.sections?.length ? ( +

+ {t( + 'expandSectionExplainer', + 'Below are the sections linked to this page. Expand each section to add questions to it.', + )} +

+ ) : null} + {page?.sections?.length ? ( + page.sections?.map((section, sectionIndex) => ( + + + <> +
+
+ renameSection(name, pageIndex, sectionIndex)} + /> +
+
+
+ {section.questions?.length ? ( + section.questions.map((question, questionIndex) => { + return ( + <> + + {getValidationError(question) && ( +
+ {getValidationError(question)} +
+ )} + {getAnswerErrors(question.questionOptions.answers)?.length ? ( +
+
Answer Errors
+ {getAnswerErrors(question.questionOptions.answers)?.map((error) => ( +
{`${error.field.label}: ${error.errorMessage}`}
+ ))} +
+ ) : null} + + ); + }) + ) : ( +

+ {t( + 'sectionExplainer', + 'A section will typically contain one or more questions. Click the button below to add a question to this section.', + )} +

+ )} + + +
+ +
+
+ )) + ) : ( +

+ {t( + 'pageExplainer', + 'Pages typically have one or more sections. Click the button below to add a section to your page.', + )} +

+ )} +
+ + + )) + : null} ); }; diff --git a/src/components/interactive-builder/draggable-question.component.tsx b/src/components/interactive-builder/question-block.component.tsx similarity index 65% rename from src/components/interactive-builder/draggable-question.component.tsx rename to src/components/interactive-builder/question-block.component.tsx index ebfad1b7..96fb58fe 100644 --- a/src/components/interactive-builder/draggable-question.component.tsx +++ b/src/components/interactive-builder/question-block.component.tsx @@ -1,36 +1,31 @@ import React, { useCallback } from 'react'; -import { useDraggable } from '@dnd-kit/core'; -import { CSS } from '@dnd-kit/utilities'; import { useTranslation } from 'react-i18next'; import { Button, CopyButton } from '@carbon/react'; -import { Draggable, Edit, TrashCan } from '@carbon/react/icons'; +import { Edit, TrashCan } from '@carbon/react/icons'; import { showModal } from '@openmrs/esm-framework'; import type { Question, Schema } from '../../types'; -import styles from './draggable-question.scss'; +import styles from './question-block.scss'; -interface DraggableQuestionProps { +interface QuestionBlockProps { handleDuplicateQuestion: (question: Question, pageId: number, sectionId: number) => void; onSchemaChange: (schema: Schema) => void; pageIndex: number; question: Question; - questionCount: number; questionIndex: number; schema: Schema; sectionIndex: number; } -const DraggableQuestion: React.FC = ({ +const QuestionBlock: React.FC = ({ handleDuplicateQuestion, onSchemaChange, pageIndex, question, - questionCount, questionIndex, schema, sectionIndex, }) => { const { t } = useTranslation(); - const draggableId = `question-${pageIndex}-${sectionIndex}-${questionIndex}`; const launchEditQuestionModal = useCallback(() => { const dispose = showModal('edit-question-modal', { @@ -56,31 +51,9 @@ const DraggableQuestion: React.FC = ({ }); }, [onSchemaChange, pageIndex, question, questionIndex, schema, sectionIndex]); - const { attributes, listeners, transform, isDragging, setNodeRef } = useDraggable({ - id: draggableId, - disabled: questionCount <= 1, - }); - - const style = { - transform: CSS.Translate.toString(transform), - }; - - const dragStyles = isDragging ? styles.isDragged : styles.normal; - return ( -
+
-
-

{question.label}

@@ -90,7 +63,7 @@ const DraggableQuestion: React.FC = ({ feedback={t('duplicated', 'Duplicated') + '!'} iconDescription={t('duplicateQuestion', 'Duplicate question')} kind="ghost" - onClick={() => !isDragging && handleDuplicateQuestion(question, pageIndex, sectionIndex)} + onClick={() => handleDuplicateQuestion(question, pageIndex, sectionIndex)} />