@openmrs/esm-form-builder-app 2.0.2-pre.574 → 2.0.2-pre.586
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -17
- package/dist/127.js +1 -1
- package/dist/127.js.map +1 -1
- package/dist/150.js +1 -1
- package/dist/150.js.map +1 -1
- package/dist/153.js +1 -1
- package/dist/153.js.map +1 -1
- package/dist/164.js +1 -1
- package/dist/256.js +1 -1
- package/dist/319.js +1 -1
- package/dist/447.js +1 -1
- package/dist/447.js.map +1 -1
- package/dist/515.js +2 -0
- package/dist/{773.js.LICENSE.txt → 515.js.LICENSE.txt} +9 -0
- package/dist/515.js.map +1 -0
- package/dist/527.js +1 -0
- package/dist/527.js.map +1 -0
- package/dist/574.js +1 -1
- package/dist/757.js +1 -1
- package/dist/788.js +1 -1
- package/dist/800.js +1 -1
- package/dist/800.js.map +1 -1
- package/dist/807.js +1 -1
- package/dist/833.js +1 -1
- package/dist/878.js +2 -0
- package/dist/{208.js.LICENSE.txt → 878.js.LICENSE.txt} +2 -1
- package/dist/878.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-form-builder-app.js +1 -1
- package/dist/openmrs-esm-form-builder-app.js.buildmanifest.json +154 -175
- package/dist/openmrs-esm-form-builder-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +35 -32
- package/src/components/action-buttons/action-buttons.component.tsx +65 -101
- package/src/components/dashboard/dashboard.component.tsx +98 -174
- package/src/components/dashboard/dashboard.test.tsx +51 -81
- package/src/components/empty-state/empty-data-illustration.component.tsx +4 -16
- package/src/components/empty-state/empty-state.component.tsx +11 -15
- package/src/components/error-state/error-state.component.tsx +11 -13
- package/src/components/form-editor/form-editor.component.tsx +97 -128
- package/src/components/form-renderer/form-renderer.component.tsx +30 -41
- package/src/components/interactive-builder/add-question-modal.component.tsx +129 -167
- package/src/components/interactive-builder/delete-page-modal.component.tsx +24 -37
- package/src/components/interactive-builder/delete-question-modal.component.tsx +25 -47
- package/src/components/interactive-builder/delete-section-modal.component.tsx +24 -37
- package/src/components/interactive-builder/draggable-question.component.tsx +21 -34
- package/src/components/interactive-builder/droppable-container.component.tsx +5 -5
- package/src/components/interactive-builder/edit-question-modal.component.tsx +191 -233
- package/src/components/interactive-builder/editable-value.component.tsx +12 -17
- package/src/components/interactive-builder/interactive-builder.component.tsx +134 -184
- package/src/components/interactive-builder/new-form-modal.component.tsx +35 -49
- package/src/components/interactive-builder/page-modal.component.tsx +29 -45
- package/src/components/interactive-builder/question-modal.scss +7 -0
- package/src/components/interactive-builder/section-modal.component.tsx +29 -40
- package/src/components/interactive-builder/value-editor.component.tsx +11 -16
- package/src/components/modals/save-form-modal.component.tsx +112 -165
- package/src/components/pagination/index.ts +2 -2
- package/src/components/pagination/pagination.component.tsx +8 -13
- package/src/components/pagination/usePaginationInfo.ts +4 -9
- package/src/components/schema-editor/schema-editor.component.tsx +11 -17
- package/src/config-schema.ts +28 -30
- package/src/declarations.d.ts +4 -3
- package/src/form-builder-admin-card-link.component.tsx +7 -11
- package/src/forms.resource.ts +66 -87
- package/src/hooks/useClobdata.ts +10 -12
- package/src/hooks/useConceptLookup.ts +5 -8
- package/src/hooks/useConceptName.ts +6 -9
- package/src/hooks/useEncounterTypes.ts +8 -8
- package/src/hooks/useForm.ts +7 -7
- package/src/hooks/useForms.ts +5 -8
- package/src/index.ts +11 -23
- package/src/root.component.tsx +4 -4
- package/src/setup-tests.ts +1 -9
- package/src/test-helpers.tsx +8 -15
- package/src/types.ts +16 -8
- package/dist/208.js +0 -2
- package/dist/208.js.map +0 -1
- package/dist/536.js +0 -1
- package/dist/536.js.map +0 -1
- package/dist/62.js +0 -1
- package/dist/62.js.map +0 -1
- package/dist/773.js +0 -2
- package/dist/773.js.map +0 -1
- package/src/constants.ts +0 -3
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
import React, { useState } from
|
|
2
|
-
import { useTranslation } from
|
|
3
|
-
import { Button } from
|
|
4
|
-
import { Edit } from
|
|
5
|
-
import ValueEditor from
|
|
6
|
-
import styles from
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Button } from '@carbon/react';
|
|
4
|
+
import { Edit } from '@carbon/react/icons';
|
|
5
|
+
import ValueEditor from './value-editor.component';
|
|
6
|
+
import styles from './editable-value.scss';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
elementType?:
|
|
8
|
+
interface EditableValueProps {
|
|
9
|
+
elementType?: 'schema' | 'page' | 'section';
|
|
10
10
|
id: string;
|
|
11
11
|
value: string;
|
|
12
12
|
onSave: (value: string) => void;
|
|
13
|
-
}
|
|
13
|
+
}
|
|
14
14
|
|
|
15
|
-
const EditableValue: React.FC<EditableValueProps> = ({
|
|
16
|
-
elementType,
|
|
17
|
-
id,
|
|
18
|
-
value,
|
|
19
|
-
onSave,
|
|
20
|
-
}) => {
|
|
15
|
+
const EditableValue: React.FC<EditableValueProps> = ({ elementType, id, value, onSave }) => {
|
|
21
16
|
const { t } = useTranslation();
|
|
22
17
|
const [editing, setEditing] = useState(false);
|
|
23
18
|
|
|
@@ -41,12 +36,12 @@ const EditableValue: React.FC<EditableValueProps> = ({
|
|
|
41
36
|
|
|
42
37
|
return (
|
|
43
38
|
<>
|
|
44
|
-
<h1 className={styles[`${elementType}` +
|
|
39
|
+
<h1 className={styles[`${elementType}` + 'Label']}>{value}</h1>
|
|
45
40
|
<Button
|
|
46
41
|
kind="ghost"
|
|
47
42
|
size="sm"
|
|
48
43
|
enterDelayMs={300}
|
|
49
|
-
iconDescription={t(
|
|
44
|
+
iconDescription={t('editButton', 'Edit {elementType}', {
|
|
50
45
|
elementType: elementType,
|
|
51
46
|
})}
|
|
52
47
|
onClick={() => setEditing(true)}
|
|
@@ -1,44 +1,34 @@
|
|
|
1
|
-
import React, { useCallback, useState } from
|
|
2
|
-
import { useTranslation } from
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
import { DraggableQuestion } from "./draggable-question.component";
|
|
27
|
-
import { Droppable } from "./droppable-container.component";
|
|
28
|
-
|
|
29
|
-
import styles from "./interactive-builder.scss";
|
|
30
|
-
|
|
31
|
-
type InteractiveBuilderProps = {
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import type { DragEndEvent } from '@dnd-kit/core';
|
|
4
|
+
import { DndContext, KeyboardSensor, MouseSensor, useSensor, useSensors } from '@dnd-kit/core';
|
|
5
|
+
import { Accordion, AccordionItem, Button, InlineLoading } from '@carbon/react';
|
|
6
|
+
import { Add, TrashCan } from '@carbon/react/icons';
|
|
7
|
+
import { useParams } from 'react-router-dom';
|
|
8
|
+
import { showToast, showNotification } from '@openmrs/esm-framework';
|
|
9
|
+
import type { OHRIFormSchema } from '@openmrs/openmrs-form-engine-lib';
|
|
10
|
+
|
|
11
|
+
import type { Schema, Question } from '../../types';
|
|
12
|
+
import AddQuestionModal from './add-question-modal.component';
|
|
13
|
+
import DeleteSectionModal from './delete-section-modal.component';
|
|
14
|
+
import DeletePageModal from './delete-page-modal.component';
|
|
15
|
+
import DeleteQuestionModal from './delete-question-modal.component';
|
|
16
|
+
import EditQuestionModal from './edit-question-modal.component';
|
|
17
|
+
import EditableValue from './editable-value.component';
|
|
18
|
+
import NewFormModal from './new-form-modal.component';
|
|
19
|
+
import PageModal from './page-modal.component';
|
|
20
|
+
import SectionModal from './section-modal.component';
|
|
21
|
+
import { DraggableQuestion } from './draggable-question.component';
|
|
22
|
+
import { Droppable } from './droppable-container.component';
|
|
23
|
+
import styles from './interactive-builder.scss';
|
|
24
|
+
|
|
25
|
+
interface InteractiveBuilderProps {
|
|
32
26
|
isLoading: boolean;
|
|
33
27
|
onSchemaChange: (schema: Schema) => void;
|
|
34
28
|
schema: Schema;
|
|
35
|
-
}
|
|
29
|
+
}
|
|
36
30
|
|
|
37
|
-
const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
38
|
-
isLoading,
|
|
39
|
-
onSchemaChange,
|
|
40
|
-
schema,
|
|
41
|
-
}) => {
|
|
31
|
+
const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({ isLoading, onSchemaChange, schema }) => {
|
|
42
32
|
const mouseSensor = useSensor(MouseSensor, {
|
|
43
33
|
activationConstraint: {
|
|
44
34
|
distance: 10, // Enable sort function when dragging 10px 💡 here!!!
|
|
@@ -48,29 +38,30 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
48
38
|
const sensors = useSensors(mouseSensor, keyboardSensor);
|
|
49
39
|
|
|
50
40
|
const { t } = useTranslation();
|
|
51
|
-
const { formUuid } = useParams<
|
|
52
|
-
const isEditingExistingForm =
|
|
41
|
+
const { formUuid } = useParams<{ formUuid: string }>();
|
|
42
|
+
const isEditingExistingForm = Boolean(formUuid);
|
|
43
|
+
|
|
53
44
|
const [pageIndex, setPageIndex] = useState(0);
|
|
54
|
-
const [sectionIndex, setSectionIndex] = useState(0);
|
|
55
45
|
const [questionIndex, setQuestionIndex] = useState(0);
|
|
56
|
-
const [questionToEdit, setQuestionToEdit] = useState(
|
|
57
|
-
const [
|
|
46
|
+
const [questionToEdit, setQuestionToEdit] = useState<Question>();
|
|
47
|
+
const [sectionIndex, setSectionIndex] = useState(0);
|
|
58
48
|
const [showAddPageModal, setShowAddPageModal] = useState(false);
|
|
59
49
|
const [showAddQuestionModal, setShowAddQuestionModal] = useState(false);
|
|
60
|
-
const [showEditQuestionModal, setShowEditQuestionModal] = useState(false);
|
|
61
50
|
const [showAddSectionModal, setShowAddSectionModal] = useState(false);
|
|
62
51
|
const [showDeletePageModal, setShowDeletePageModal] = useState(false);
|
|
63
|
-
const [showDeleteSectionModal, setShowDeleteSectionModal] = useState(false);
|
|
64
52
|
const [showDeleteQuestionModal, setShowDeleteQuestionModal] = useState(false);
|
|
53
|
+
const [showDeleteSectionModal, setShowDeleteSectionModal] = useState(false);
|
|
54
|
+
const [showEditQuestionModal, setShowEditQuestionModal] = useState(false);
|
|
55
|
+
const [showNewFormModal, setShowNewFormModal] = useState(false);
|
|
65
56
|
|
|
66
57
|
const initializeSchema = useCallback(() => {
|
|
67
58
|
const dummySchema: OHRIFormSchema = {
|
|
68
|
-
name:
|
|
59
|
+
name: '',
|
|
69
60
|
pages: [],
|
|
70
|
-
processor:
|
|
71
|
-
encounterType:
|
|
61
|
+
processor: 'EncounterFormProcessor',
|
|
62
|
+
encounterType: '',
|
|
72
63
|
referencedForms: [],
|
|
73
|
-
uuid:
|
|
64
|
+
uuid: '',
|
|
74
65
|
};
|
|
75
66
|
|
|
76
67
|
if (!schema) {
|
|
@@ -115,21 +106,21 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
115
106
|
onSchemaChange({ ...schema });
|
|
116
107
|
|
|
117
108
|
showToast({
|
|
118
|
-
title: t(
|
|
119
|
-
kind:
|
|
109
|
+
title: t('success', 'Success!'),
|
|
110
|
+
kind: 'success',
|
|
120
111
|
critical: true,
|
|
121
|
-
description: t(
|
|
112
|
+
description: t('formRenamed', 'Form renamed'),
|
|
122
113
|
});
|
|
123
114
|
} catch (error) {
|
|
124
115
|
showNotification({
|
|
125
|
-
title: t(
|
|
126
|
-
kind:
|
|
116
|
+
title: t('errorRenamingForm', 'Error renaming form'),
|
|
117
|
+
kind: 'error',
|
|
127
118
|
critical: true,
|
|
128
119
|
description: error?.message,
|
|
129
120
|
});
|
|
130
121
|
}
|
|
131
122
|
},
|
|
132
|
-
[onSchemaChange, schema, t]
|
|
123
|
+
[onSchemaChange, schema, t],
|
|
133
124
|
);
|
|
134
125
|
|
|
135
126
|
const renamePage = useCallback(
|
|
@@ -142,21 +133,23 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
142
133
|
onSchemaChange({ ...schema });
|
|
143
134
|
|
|
144
135
|
showToast({
|
|
145
|
-
title: t(
|
|
146
|
-
kind:
|
|
136
|
+
title: t('success', 'Success!'),
|
|
137
|
+
kind: 'success',
|
|
147
138
|
critical: true,
|
|
148
|
-
description: t(
|
|
139
|
+
description: t('pageRenamed', 'Page renamed'),
|
|
149
140
|
});
|
|
150
141
|
} catch (error) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
142
|
+
if (error instanceof Error) {
|
|
143
|
+
showNotification({
|
|
144
|
+
title: t('errorRenamingPage', 'Error renaming page'),
|
|
145
|
+
kind: 'error',
|
|
146
|
+
critical: true,
|
|
147
|
+
description: error?.message,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
157
150
|
}
|
|
158
151
|
},
|
|
159
|
-
[onSchemaChange, schema, t]
|
|
152
|
+
[onSchemaChange, schema, t],
|
|
160
153
|
);
|
|
161
154
|
|
|
162
155
|
const renameSection = useCallback(
|
|
@@ -170,70 +163,71 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
170
163
|
resetIndices();
|
|
171
164
|
|
|
172
165
|
showToast({
|
|
173
|
-
title: t(
|
|
174
|
-
kind:
|
|
166
|
+
title: t('success', 'Success!'),
|
|
167
|
+
kind: 'success',
|
|
175
168
|
critical: true,
|
|
176
|
-
description: t(
|
|
169
|
+
description: t('sectionRenamed', 'Section renamed'),
|
|
177
170
|
});
|
|
178
171
|
} catch (error) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
172
|
+
if (error instanceof Error) {
|
|
173
|
+
showNotification({
|
|
174
|
+
title: t('errorRenamingSection', 'Error renaming section'),
|
|
175
|
+
kind: 'error',
|
|
176
|
+
critical: true,
|
|
177
|
+
description: error?.message,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
185
180
|
}
|
|
186
181
|
},
|
|
187
|
-
[onSchemaChange, schema, t]
|
|
182
|
+
[onSchemaChange, schema, t],
|
|
188
183
|
);
|
|
189
184
|
|
|
190
185
|
const duplicateQuestion = useCallback(
|
|
191
|
-
(question, pageId: number, sectionId: number) => {
|
|
186
|
+
(question: Question, pageId: number, sectionId: number) => {
|
|
192
187
|
try {
|
|
193
|
-
const questionToDuplicate = JSON.parse(JSON.stringify(question));
|
|
194
|
-
questionToDuplicate.id = questionToDuplicate.id +
|
|
188
|
+
const questionToDuplicate: Question = JSON.parse(JSON.stringify(question));
|
|
189
|
+
questionToDuplicate.id = questionToDuplicate.id + 'Duplicate';
|
|
195
190
|
|
|
196
|
-
schema.pages[pageId].sections[sectionId].questions.push(
|
|
197
|
-
questionToDuplicate
|
|
198
|
-
);
|
|
191
|
+
schema.pages[pageId].sections[sectionId].questions.push(questionToDuplicate);
|
|
199
192
|
|
|
200
193
|
onSchemaChange({ ...schema });
|
|
201
194
|
resetIndices();
|
|
202
195
|
|
|
203
196
|
showToast({
|
|
204
|
-
title: t(
|
|
205
|
-
kind:
|
|
197
|
+
title: t('success', 'Success!'),
|
|
198
|
+
kind: 'success',
|
|
206
199
|
critical: true,
|
|
207
200
|
description: t(
|
|
208
|
-
|
|
209
|
-
"Question duplicated. Please change the duplicated question's ID to a unique, camelcased value"
|
|
201
|
+
'questionDuplicated',
|
|
202
|
+
"Question duplicated. Please change the duplicated question's ID to a unique, camelcased value",
|
|
210
203
|
),
|
|
211
204
|
});
|
|
212
205
|
} catch (error) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
206
|
+
if (error instanceof Error) {
|
|
207
|
+
showNotification({
|
|
208
|
+
title: t('errorDuplicatingQuestion', 'Error duplicating question'),
|
|
209
|
+
kind: 'error',
|
|
210
|
+
critical: true,
|
|
211
|
+
description: error?.message,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
219
214
|
}
|
|
220
215
|
},
|
|
221
|
-
[onSchemaChange, schema, t]
|
|
216
|
+
[onSchemaChange, schema, t],
|
|
222
217
|
);
|
|
223
218
|
|
|
224
|
-
const handleDragEnd = (event) => {
|
|
219
|
+
const handleDragEnd = (event: DragEndEvent) => {
|
|
225
220
|
const { active, delta } = event;
|
|
226
221
|
|
|
227
222
|
if (active) {
|
|
228
223
|
// Get the source information
|
|
229
|
-
const activeIdParts = active.id.split(
|
|
224
|
+
const activeIdParts = active.id.toString().split('-');
|
|
230
225
|
const sourcePageIndex = parseInt(activeIdParts[1]);
|
|
231
226
|
const sourceSectionIndex = parseInt(activeIdParts[2]);
|
|
232
227
|
const sourceQuestionIndex = parseInt(activeIdParts[3]);
|
|
233
228
|
|
|
234
229
|
// Move the question within the same section
|
|
235
|
-
const questions =
|
|
236
|
-
schema.pages[sourcePageIndex].sections[sourceSectionIndex].questions;
|
|
230
|
+
const questions = schema.pages[sourcePageIndex].sections[sourceSectionIndex].questions;
|
|
237
231
|
const questionToMove = questions[sourceQuestionIndex];
|
|
238
232
|
questions.splice(sourceQuestionIndex, 1);
|
|
239
233
|
questions.splice(sourceQuestionIndex + delta.y, 0, questionToMove);
|
|
@@ -281,11 +275,7 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
281
275
|
|
|
282
276
|
return (
|
|
283
277
|
<div className={styles.container}>
|
|
284
|
-
{isLoading ? (
|
|
285
|
-
<InlineLoading
|
|
286
|
-
description={t("loadingSchema", "Loading schema") + "..."}
|
|
287
|
-
/>
|
|
288
|
-
) : null}
|
|
278
|
+
{isLoading ? <InlineLoading description={t('loadingSchema', 'Loading schema') + '...'} /> : null}
|
|
289
279
|
|
|
290
280
|
{showNewFormModal ? (
|
|
291
281
|
<NewFormModal
|
|
@@ -385,33 +375,19 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
385
375
|
<>
|
|
386
376
|
<div className={styles.header}>
|
|
387
377
|
<div className={styles.explainer}>
|
|
378
|
+
<p>{t('welcomeHeading', 'Welcome to the Interactive Schema builder')}</p>
|
|
388
379
|
<p>
|
|
389
380
|
{t(
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
)}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
{t(
|
|
396
|
-
"welcomeExplainer",
|
|
397
|
-
"Add pages, sections and questions to your form. The Preview tab automatically updates as you build your form. For a detailed explanation of what constitutes an OpenMRS form schema, please read through the "
|
|
398
|
-
)}{" "}
|
|
399
|
-
<a
|
|
400
|
-
target="_blank"
|
|
401
|
-
rel="noopener noreferrer"
|
|
402
|
-
href={"https://ohri-docs.globalhealthapp.net/"}
|
|
403
|
-
>
|
|
404
|
-
{t("formBuilderDocs", "form builder documentation")}.
|
|
381
|
+
'welcomeExplainer',
|
|
382
|
+
'Add pages, sections and questions to your form. The Preview tab automatically updates as you build your form. For a detailed explanation of what constitutes an OpenMRS form schema, please read through the ',
|
|
383
|
+
)}{' '}
|
|
384
|
+
<a target="_blank" rel="noopener noreferrer" href={'https://ohri-docs.globalhealthapp.net/'}>
|
|
385
|
+
{t('formBuilderDocs', 'form builder documentation')}.
|
|
405
386
|
</a>
|
|
406
387
|
</p>
|
|
407
388
|
</div>
|
|
408
|
-
<Button
|
|
409
|
-
|
|
410
|
-
renderIcon={Add}
|
|
411
|
-
onClick={addPage}
|
|
412
|
-
iconDescription={t("addPage", "Add Page")}
|
|
413
|
-
>
|
|
414
|
-
{t("addPage", "Add Page")}
|
|
389
|
+
<Button kind="ghost" renderIcon={Add} onClick={addPage} iconDescription={t('addPage', 'Add Page')}>
|
|
390
|
+
{t('addPage', 'Add Page')}
|
|
415
391
|
</Button>
|
|
416
392
|
</div>
|
|
417
393
|
<div className={styles.editorContainer}>
|
|
@@ -429,26 +405,22 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
429
405
|
<div className={styles.header}>
|
|
430
406
|
<p className={styles.explainer}>
|
|
431
407
|
{t(
|
|
432
|
-
|
|
433
|
-
|
|
408
|
+
'interactiveBuilderHelperText',
|
|
409
|
+
'The Interactive Builder lets you build your form schema without writing JSON code. The Preview tab automatically updates as you build your form. When done, click Save Form to save your form.',
|
|
434
410
|
)}
|
|
435
411
|
</p>
|
|
436
412
|
|
|
437
|
-
<Button
|
|
438
|
-
|
|
439
|
-
className={styles.startButton}
|
|
440
|
-
kind="ghost"
|
|
441
|
-
>
|
|
442
|
-
{t("startBuilding", "Start building")}
|
|
413
|
+
<Button onClick={launchNewFormModal} className={styles.startButton} kind="ghost">
|
|
414
|
+
{t('startBuilding', 'Start building')}
|
|
443
415
|
</Button>
|
|
444
416
|
</div>
|
|
445
417
|
)}
|
|
446
418
|
|
|
447
|
-
<DndContext onDragEnd={(event) => handleDragEnd(event)} sensors={sensors}>
|
|
419
|
+
<DndContext onDragEnd={(event: DragEndEvent) => handleDragEnd(event)} sensors={sensors}>
|
|
448
420
|
{schema?.pages?.length
|
|
449
421
|
? schema.pages.map((page, pageIndex) => (
|
|
450
422
|
<div className={styles.editableFieldsContainer}>
|
|
451
|
-
<div style={{ display:
|
|
423
|
+
<div style={{ display: 'flex', alignItems: 'center' }}>
|
|
452
424
|
<div className={styles.editorContainer}>
|
|
453
425
|
<EditableValue
|
|
454
426
|
elementType="page"
|
|
@@ -460,7 +432,7 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
460
432
|
<Button
|
|
461
433
|
hasIconOnly
|
|
462
434
|
enterDelayMs={300}
|
|
463
|
-
iconDescription={t(
|
|
435
|
+
iconDescription={t('deletePage', 'Delete page')}
|
|
464
436
|
kind="ghost"
|
|
465
437
|
onClick={() => {
|
|
466
438
|
setPageIndex(pageIndex);
|
|
@@ -474,8 +446,8 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
474
446
|
{page?.sections?.length ? (
|
|
475
447
|
<p className={styles.sectionExplainer}>
|
|
476
448
|
{t(
|
|
477
|
-
|
|
478
|
-
|
|
449
|
+
'expandSectionExplainer',
|
|
450
|
+
'Below are the sections linked to this page. Expand each section to add questions to it.',
|
|
479
451
|
)}
|
|
480
452
|
</p>
|
|
481
453
|
) : null}
|
|
@@ -484,70 +456,51 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
484
456
|
<Accordion>
|
|
485
457
|
<AccordionItem title={section.label}>
|
|
486
458
|
<>
|
|
487
|
-
<div
|
|
488
|
-
style={{ display: "flex", alignItems: "center" }}
|
|
489
|
-
>
|
|
459
|
+
<div style={{ display: 'flex', alignItems: 'center' }}>
|
|
490
460
|
<div className={styles.editorContainer}>
|
|
491
461
|
<EditableValue
|
|
492
462
|
elementType="section"
|
|
493
463
|
id="sectionNameInput"
|
|
494
464
|
value={section.label}
|
|
495
|
-
onSave={(name) =>
|
|
496
|
-
renameSection(name, pageIndex, sectionIndex)
|
|
497
|
-
}
|
|
465
|
+
onSave={(name) => renameSection(name, pageIndex, sectionIndex)}
|
|
498
466
|
/>
|
|
499
467
|
</div>
|
|
500
468
|
<Button
|
|
501
469
|
hasIconOnly
|
|
502
470
|
enterDelayMs={300}
|
|
503
|
-
iconDescription={t(
|
|
504
|
-
"deleteSection",
|
|
505
|
-
"Delete section"
|
|
506
|
-
)}
|
|
471
|
+
iconDescription={t('deleteSection', 'Delete section')}
|
|
507
472
|
kind="ghost"
|
|
508
473
|
onClick={() => {
|
|
509
474
|
setPageIndex(pageIndex);
|
|
510
475
|
setSectionIndex(sectionIndex);
|
|
511
476
|
setShowDeleteSectionModal(true);
|
|
512
477
|
}}
|
|
513
|
-
renderIcon={(props) =>
|
|
514
|
-
<TrashCan size={16} {...props} />
|
|
515
|
-
)}
|
|
478
|
+
renderIcon={(props) => <TrashCan size={16} {...props} />}
|
|
516
479
|
size="sm"
|
|
517
480
|
/>
|
|
518
481
|
</div>
|
|
519
482
|
<div>
|
|
520
483
|
{section.questions?.length ? (
|
|
521
|
-
section.questions.map(
|
|
522
|
-
|
|
523
|
-
<
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
handleEditButtonClick
|
|
537
|
-
}
|
|
538
|
-
handleDeleteButtonClick={
|
|
539
|
-
handleDeleteButtonClick
|
|
540
|
-
}
|
|
541
|
-
questionCount={section.questions.length}
|
|
542
|
-
/>
|
|
543
|
-
</Droppable>
|
|
544
|
-
)
|
|
545
|
-
)
|
|
484
|
+
section.questions.map((question, questionIndex) => (
|
|
485
|
+
<Droppable id={`droppable-question-${pageIndex}-${sectionIndex}-${questionIndex}`}>
|
|
486
|
+
<DraggableQuestion
|
|
487
|
+
key={question.id}
|
|
488
|
+
question={question}
|
|
489
|
+
pageIndex={pageIndex}
|
|
490
|
+
sectionIndex={sectionIndex}
|
|
491
|
+
questionIndex={questionIndex}
|
|
492
|
+
handleDuplicateQuestion={duplicateQuestion}
|
|
493
|
+
handleEditButtonClick={handleEditButtonClick}
|
|
494
|
+
handleDeleteButtonClick={handleDeleteButtonClick}
|
|
495
|
+
questionCount={section.questions.length}
|
|
496
|
+
/>
|
|
497
|
+
</Droppable>
|
|
498
|
+
))
|
|
546
499
|
) : (
|
|
547
500
|
<p className={styles.explainer}>
|
|
548
501
|
{t(
|
|
549
|
-
|
|
550
|
-
|
|
502
|
+
'sectionExplainer',
|
|
503
|
+
'A section will typically contain one or more questions. Click the button below to add a question to this section.',
|
|
551
504
|
)}
|
|
552
505
|
</p>
|
|
553
506
|
)}
|
|
@@ -562,12 +515,9 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
562
515
|
setPageIndex(pageIndex);
|
|
563
516
|
setSectionIndex(sectionIndex);
|
|
564
517
|
}}
|
|
565
|
-
iconDescription={t(
|
|
566
|
-
"addQuestion",
|
|
567
|
-
"Add Question"
|
|
568
|
-
)}
|
|
518
|
+
iconDescription={t('addQuestion', 'Add Question')}
|
|
569
519
|
>
|
|
570
|
-
{t(
|
|
520
|
+
{t('addQuestion', 'Add Question')}
|
|
571
521
|
</Button>
|
|
572
522
|
</div>
|
|
573
523
|
</>
|
|
@@ -577,8 +527,8 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
577
527
|
) : (
|
|
578
528
|
<p className={styles.explainer}>
|
|
579
529
|
{t(
|
|
580
|
-
|
|
581
|
-
|
|
530
|
+
'pageExplainer',
|
|
531
|
+
'Pages typically have one or more sections. Click the button below to add a section to your page.',
|
|
582
532
|
)}
|
|
583
533
|
</p>
|
|
584
534
|
)}
|
|
@@ -591,9 +541,9 @@ const InteractiveBuilder: React.FC<InteractiveBuilderProps> = ({
|
|
|
591
541
|
addSection();
|
|
592
542
|
setPageIndex(pageIndex);
|
|
593
543
|
}}
|
|
594
|
-
iconDescription={t(
|
|
544
|
+
iconDescription={t('addSection', 'Add Section')}
|
|
595
545
|
>
|
|
596
|
-
{t(
|
|
546
|
+
{t('addSection', 'Add Section')}
|
|
597
547
|
</Button>
|
|
598
548
|
</div>
|
|
599
549
|
))
|