diff --git a/src/components/interactive-builder/draggable/draggable-question.component.tsx b/src/components/interactive-builder/draggable/draggable-question.component.tsx index 8987ffb70..5fe12a70e 100644 --- a/src/components/interactive-builder/draggable/draggable-question.component.tsx +++ b/src/components/interactive-builder/draggable/draggable-question.component.tsx @@ -6,14 +6,15 @@ import { IconButton } from '@carbon/react'; import { Draggable, Edit, TrashCan, Copy } from '@carbon/react/icons'; import { showModal, ChevronDownIcon, ChevronUpIcon } from '@openmrs/esm-framework'; import MarkdownWrapper from '../markdown-wrapper/markdown-wrapper'; -import type { Question, Schema } from '@types'; +import type { FormField } from '@openmrs/esm-form-engine-lib'; +import type { Schema } from '@types'; import styles from './draggable-question.scss'; interface DraggableQuestionProps { - handleDuplicateQuestion: (question: Question, pageId: number, sectionId: number, questionId?: number) => void; + handleDuplicateQuestion: (question: FormField, pageId: number, sectionId: number, questionId?: number) => void; onSchemaChange: (schema: Schema) => void; pageIndex: number; - question: Question; + question: FormField; questionCount: number; questionIndex: number; schema: Schema; diff --git a/src/components/interactive-builder/interactive-builder.component.tsx b/src/components/interactive-builder/interactive-builder.component.tsx index c7ba27794..956f8b1a7 100644 --- a/src/components/interactive-builder/interactive-builder.component.tsx +++ b/src/components/interactive-builder/interactive-builder.component.tsx @@ -19,8 +19,8 @@ import { showModal, showSnackbar } from '@openmrs/esm-framework'; import DraggableQuestion from './draggable/draggable-question.component'; import EditableValue from './editable/editable-value.component'; import type { DragEndEvent } from '@dnd-kit/core'; -import type { FormSchema } from '@openmrs/esm-form-engine-lib'; -import type { Schema, Question } from '@types'; +import type { FormSchema, FormField } from '@openmrs/esm-form-engine-lib'; +import type { Schema } from '@types'; import styles from './interactive-builder.scss'; interface ValidationError { @@ -37,7 +37,7 @@ interface InteractiveBuilderProps { } interface SubQuestionProps { - question: Question; + question: FormField; pageIndex: number; sectionIndex: number; questionIndex: number; @@ -257,9 +257,9 @@ const InteractiveBuilder: React.FC = ({ ); const duplicateQuestion = useCallback( - (question: Question, pageId: number, sectionId: number, questionId?: number) => { + (question: FormField, pageId: number, sectionId: number, questionId?: number) => { try { - const questionToDuplicate: Question = JSON.parse(JSON.stringify(question)); + const questionToDuplicate: FormField = JSON.parse(JSON.stringify(question)); questionToDuplicate.id = questionToDuplicate.id + 'Duplicate'; if (Number.isInteger(questionId)) { @@ -340,7 +340,7 @@ const InteractiveBuilder: React.FC = ({ pageIndex: number, sectionIndex: number, questionId: string | number, - newQuestion: Question, + newQuestion: FormField, ): Schema { if (activeQuestion.type === 'question') { const newSchema = { ...schema }; @@ -419,7 +419,7 @@ const InteractiveBuilder: React.FC = ({ return errors || []; }; - const getValidationError = (question: Question) => { + const getValidationError = (question: FormField) => { const errorField: ValidationError = validationResponse.find( (error) => error.field.label === question.label && error.field.id === question.id && error.field.type === question.type, diff --git a/src/components/interactive-builder/modals/add-form-reference/add-form-reference.modal.tsx b/src/components/interactive-builder/modals/add-form-reference/add-form-reference.modal.tsx index dab8cd731..6388a38b3 100644 --- a/src/components/interactive-builder/modals/add-form-reference/add-form-reference.modal.tsx +++ b/src/components/interactive-builder/modals/add-form-reference/add-form-reference.modal.tsx @@ -19,7 +19,8 @@ import { import { showSnackbar } from '@openmrs/esm-framework'; import { useForms } from '@hooks/useForms'; import { useClobdata } from '@hooks/useClobdata'; -import { type Form as FormType, type Schema, type Page, type Section, type Question } from '@types'; +import type { FormPage, FormSection, FormField } from '@openmrs/esm-form-engine-lib'; +import type { Form as FormType, Schema } from '@types'; import styles from './add-form-reference.scss'; interface AddFormReferenceModalProps { @@ -41,9 +42,9 @@ const AddFormReferenceModal: React.FC = ({ }) => { const { t } = useTranslation(); const [selectedForm, setSelectedForm] = useState(null); - const [pages, setPages] = useState([]); - const [selectedPage, setSelectedPage] = useState(null); - const [selectedSection, setSelectedSection] = useState
(null); + const [pages, setPages] = useState([]); + const [selectedPage, setSelectedPage] = useState(null); + const [selectedSection, setSelectedSection] = useState(null); const [excludedQuestions, setExcludedQuestions] = useState([]); const { forms, error, isLoading } = useForms(); const { clobdata, isLoadingClobdata, clobdataError } = useClobdata(selectedForm); @@ -61,18 +62,18 @@ const AddFormReferenceModal: React.FC = ({ } }, [clobdata]); - const handleSelectedPage = useCallback(({ selectedItem }: { selectedItem: Page }) => { + const handleSelectedPage = useCallback(({ selectedItem }: { selectedItem: FormPage }) => { setSelectedPage(selectedItem); setSelectedSection(null); setExcludedQuestions([]); }, []); - const handleSelectedSections = useCallback((section: Section) => { + const handleSelectedSections = useCallback((section: FormSection) => { setSelectedSection(section); setExcludedQuestions([]); }, []); - const handleExcludedQuestions = useCallback((question: Question, checked: Boolean) => { + const handleExcludedQuestions = useCallback((question: FormField, checked: Boolean) => { setExcludedQuestions((prev) => { if (!checked) { return prev.some((q) => q === question.id) ? prev : [...prev, question.id]; @@ -211,7 +212,7 @@ const AddFormReferenceModal: React.FC = ({ label: page.label, sections: page.sections, }))} - itemToString={(item: Page) => (item ? item.label : '')} + itemToString={(item: FormPage) => (item ? item.label : '')} onChange={handleSelectedPage} selectedItem={selectedPage} /> diff --git a/src/components/interactive-builder/modals/delete-question/delete-question.modal.tsx b/src/components/interactive-builder/modals/delete-question/delete-question.modal.tsx index 9fab8dfb1..01058a3a9 100644 --- a/src/components/interactive-builder/modals/delete-question/delete-question.modal.tsx +++ b/src/components/interactive-builder/modals/delete-question/delete-question.modal.tsx @@ -2,13 +2,14 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { Button, ModalBody, ModalFooter, ModalHeader } from '@carbon/react'; import { showSnackbar } from '@openmrs/esm-framework'; -import type { Question, Schema } from '@types'; +import type { FormField } from '@openmrs/esm-form-engine-lib'; +import type { Schema } from '@types'; interface DeleteQuestionModal { closeModal: () => void; onSchemaChange: (schema: Schema) => void; pageIndex: number; - question: Question; + question: FormField; questionIndex: number; schema: Schema; sectionIndex: number; diff --git a/src/resources/form-validator.resource.ts b/src/resources/form-validator.resource.ts index 95ab4af0b..52598812f 100644 --- a/src/resources/form-validator.resource.ts +++ b/src/resources/form-validator.resource.ts @@ -1,5 +1,6 @@ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework'; -import type { Question, Schema } from '@types'; +import type { FormField } from '@openmrs/esm-form-engine-lib'; +import type { Schema } from '@types'; import type { ConfigObject } from '../config-schema'; interface Field { @@ -32,7 +33,7 @@ export const handleFormValidation = async ( const asyncTasks: Array> = []; parsedForm.pages?.forEach((page) => - page.sections?.forEach((section: { questions: Array }) => + page.sections?.forEach((section: { questions: Array }) => section.questions?.forEach((question) => { asyncTasks.push( handleQuestionValidation(question, errors, configObject, warnings), diff --git a/src/types.ts b/src/types.ts index 0a7888b49..6fd008e42 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,16 +1,13 @@ import type { OpenmrsResource } from '@openmrs/esm-framework'; -import type { - OpenmrsFormResource, - FormField, - ProgramState, - ReferencedForm, - RenderType, - RequiredFieldProps, - FormReference, -} from '@openmrs/esm-form-engine-lib'; +import type { FormSchema, ProgramState } from '@openmrs/esm-form-engine-lib'; import type { AuditInfo } from './components/audit-details/audit-details.component'; import type { questionTypes } from '@constants'; +// Extend FormSchema to include description property +export interface FormBuilderSchema extends FormSchema { + description?: string; +} + export interface Form { uuid: string; name: string; @@ -50,117 +47,14 @@ export type QuestionType = (typeof questionTypes)[number]; export type DatePickerType = 'both' | 'calendar' | 'timer'; -export interface Schema { - name: string; - pages: Array<{ - label: string; - sections: Array<{ - label: string; - isExpanded: string; - reference?: FormReference; - questions: Array<{ - id: string; - label?: string; - value?: string; - type: string; - required?: string | boolean | RequiredFieldProps; - questionInfo?: string; - questionOptions: { - type?: string; - concept?: string; - answers?: Array>; - rendering: RenderType; - max?: string; - min?: string; - conceptMappings?: Array>; - }; - questions?: Array; - validators?: Array>; - }>; - }>; - }>; - processor: string; - uuid: string; - encounterType: string; - referencedForms: Array; - version?: string; - description?: string; - encounter?: string | OpenmrsEncounter; - allowUnspecifiedAll?: boolean; - defaultPage?: string; - readonly?: string | boolean; - inlineRendering?: 'single-line' | 'multiline' | 'automatic'; - markdown?: unknown; - postSubmissionActions?: Array<{ actionId: string; config?: Record }>; - formOptions?: { - usePreviousValueDisabled: boolean; - }; - translations?: Record; -} +// Using extended FormBuilderSchema instead of FormSchema +export type Schema = FormBuilderSchema; export interface SchemaContextType { schema: Schema; setSchema: (schema: Schema) => void; } -export interface Page { - label: string; - sections: Array
; -} - -export interface Section { - label: string; - questions: Array; - isExpanded: string | boolean; -} - -export interface Question { - id: string; - label?: string; - value?: any; - type: string; - questionOptions: QuestionOptions; - datePickerFormat?: DatePickerType; - questions?: Array; - required?: string | boolean | RequiredFieldProps; - validators?: Array>; - questionInfo?: string; -} - -export interface QuestionOptions { - rendering: RenderType; - answers?: Array>; - concept?: string; - conceptMappings?: Array; - max?: string; - min?: string; - isSearchable?: boolean; - attributeType?: string; - calculate?: { - calculateExpression: string; - }; - rows?: number; - orderSettingUuid?: string; - orderType?: string; - identifierType?: string; - selectableOrders?: Array< - | { - concept: string; - label: string; - } - | Record - >; - weekList?: []; - showComment?: boolean; - showDate?: string; - programUuid?: string; - workflowUuid?: string; - toggleOptions?: { - labelTrue: string; - labelFalse: string; - }; -} - export interface Answer { concept: string; label: string; @@ -208,54 +102,6 @@ export interface PersonAttributeType { }; } -export interface OpenmrsEncounter { - uuid?: string; - encounterDatetime?: string | Date; - patient?: OpenmrsResource | string; - location?: OpenmrsResource | string; - encounterType?: OpenmrsResource | string; - obs?: Array; - orders?: Array; - voided?: boolean; - visit?: OpenmrsResource | string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - encounterProviders?: Array>; - form?: OpenmrsFormResource; -} - -export type SessionMode = 'edit' | 'enter' | 'view' | 'embedded-view'; - -export interface PostSubmissionAction { - applyAction( - formSession: { - patient: fhir.Patient; - encounters: Array; - sessionMode: SessionMode; - }, - config?: Record, - enabled?: string, - ): void; -} - -export interface OpenmrsObs extends OpenmrsResource { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - concept?: any; - obsDatetime?: string | Date; - obsGroup?: OpenmrsObs; - groupMembers?: Array; - comment?: string; - location?: OpenmrsResource; - order?: OpenmrsResource; - encounter?: OpenmrsResource; - voided?: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - value?: any; - formFieldPath?: string; - formFieldNamespace?: string; - status?: string; - interpretation?: string; -} - export interface Program { uuid: string; name: string;