@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.
Files changed (85) hide show
  1. package/README.md +43 -17
  2. package/dist/127.js +1 -1
  3. package/dist/127.js.map +1 -1
  4. package/dist/150.js +1 -1
  5. package/dist/150.js.map +1 -1
  6. package/dist/153.js +1 -1
  7. package/dist/153.js.map +1 -1
  8. package/dist/164.js +1 -1
  9. package/dist/256.js +1 -1
  10. package/dist/319.js +1 -1
  11. package/dist/447.js +1 -1
  12. package/dist/447.js.map +1 -1
  13. package/dist/515.js +2 -0
  14. package/dist/{773.js.LICENSE.txt → 515.js.LICENSE.txt} +9 -0
  15. package/dist/515.js.map +1 -0
  16. package/dist/527.js +1 -0
  17. package/dist/527.js.map +1 -0
  18. package/dist/574.js +1 -1
  19. package/dist/757.js +1 -1
  20. package/dist/788.js +1 -1
  21. package/dist/800.js +1 -1
  22. package/dist/800.js.map +1 -1
  23. package/dist/807.js +1 -1
  24. package/dist/833.js +1 -1
  25. package/dist/878.js +2 -0
  26. package/dist/{208.js.LICENSE.txt → 878.js.LICENSE.txt} +2 -1
  27. package/dist/878.js.map +1 -0
  28. package/dist/main.js +1 -1
  29. package/dist/main.js.map +1 -1
  30. package/dist/openmrs-esm-form-builder-app.js +1 -1
  31. package/dist/openmrs-esm-form-builder-app.js.buildmanifest.json +154 -175
  32. package/dist/openmrs-esm-form-builder-app.js.map +1 -1
  33. package/dist/routes.json +1 -1
  34. package/package.json +35 -32
  35. package/src/components/action-buttons/action-buttons.component.tsx +65 -101
  36. package/src/components/dashboard/dashboard.component.tsx +98 -174
  37. package/src/components/dashboard/dashboard.test.tsx +51 -81
  38. package/src/components/empty-state/empty-data-illustration.component.tsx +4 -16
  39. package/src/components/empty-state/empty-state.component.tsx +11 -15
  40. package/src/components/error-state/error-state.component.tsx +11 -13
  41. package/src/components/form-editor/form-editor.component.tsx +97 -128
  42. package/src/components/form-renderer/form-renderer.component.tsx +30 -41
  43. package/src/components/interactive-builder/add-question-modal.component.tsx +129 -167
  44. package/src/components/interactive-builder/delete-page-modal.component.tsx +24 -37
  45. package/src/components/interactive-builder/delete-question-modal.component.tsx +25 -47
  46. package/src/components/interactive-builder/delete-section-modal.component.tsx +24 -37
  47. package/src/components/interactive-builder/draggable-question.component.tsx +21 -34
  48. package/src/components/interactive-builder/droppable-container.component.tsx +5 -5
  49. package/src/components/interactive-builder/edit-question-modal.component.tsx +191 -233
  50. package/src/components/interactive-builder/editable-value.component.tsx +12 -17
  51. package/src/components/interactive-builder/interactive-builder.component.tsx +134 -184
  52. package/src/components/interactive-builder/new-form-modal.component.tsx +35 -49
  53. package/src/components/interactive-builder/page-modal.component.tsx +29 -45
  54. package/src/components/interactive-builder/question-modal.scss +7 -0
  55. package/src/components/interactive-builder/section-modal.component.tsx +29 -40
  56. package/src/components/interactive-builder/value-editor.component.tsx +11 -16
  57. package/src/components/modals/save-form-modal.component.tsx +112 -165
  58. package/src/components/pagination/index.ts +2 -2
  59. package/src/components/pagination/pagination.component.tsx +8 -13
  60. package/src/components/pagination/usePaginationInfo.ts +4 -9
  61. package/src/components/schema-editor/schema-editor.component.tsx +11 -17
  62. package/src/config-schema.ts +28 -30
  63. package/src/declarations.d.ts +4 -3
  64. package/src/form-builder-admin-card-link.component.tsx +7 -11
  65. package/src/forms.resource.ts +66 -87
  66. package/src/hooks/useClobdata.ts +10 -12
  67. package/src/hooks/useConceptLookup.ts +5 -8
  68. package/src/hooks/useConceptName.ts +6 -9
  69. package/src/hooks/useEncounterTypes.ts +8 -8
  70. package/src/hooks/useForm.ts +7 -7
  71. package/src/hooks/useForms.ts +5 -8
  72. package/src/index.ts +11 -23
  73. package/src/root.component.tsx +4 -4
  74. package/src/setup-tests.ts +1 -9
  75. package/src/test-helpers.tsx +8 -15
  76. package/src/types.ts +16 -8
  77. package/dist/208.js +0 -2
  78. package/dist/208.js.map +0 -1
  79. package/dist/536.js +0 -1
  80. package/dist/536.js.map +0 -1
  81. package/dist/62.js +0 -1
  82. package/dist/62.js.map +0 -1
  83. package/dist/773.js +0 -2
  84. package/dist/773.js.map +0 -1
  85. package/src/constants.ts +0 -3
@@ -1,5 +1,6 @@
1
- import React, { useState } from "react";
2
- import { useTranslation } from "react-i18next";
1
+ import React, { useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import flattenDeep from 'lodash-es/flattenDeep';
3
4
  import {
4
5
  Button,
5
6
  ComposedModal,
@@ -21,23 +22,16 @@ import {
21
22
  Tag,
22
23
  TextInput,
23
24
  Tile,
24
- } from "@carbon/react";
25
- import { ArrowUpRight } from "@carbon/react/icons";
26
- import flattenDeep from "lodash-es/flattenDeep";
27
- import { showNotification, showToast, useConfig } from "@openmrs/esm-framework";
28
- import { RenderType } from "@openmrs/openmrs-form-engine-lib";
25
+ } from '@carbon/react';
26
+ import { ArrowUpRight } from '@carbon/react/icons';
27
+ import { showNotification, showToast, useConfig } from '@openmrs/esm-framework';
28
+ import type { RenderType } from '@openmrs/openmrs-form-engine-lib';
29
29
 
30
- import type {
31
- Answer,
32
- Concept,
33
- ConceptMapping,
34
- Question,
35
- Schema,
36
- } from "../../types";
37
- import { useConceptLookup } from "../../hooks/useConceptLookup";
38
- import styles from "./question-modal.scss";
30
+ import type { Answer, Concept, ConceptMapping, Question, Schema } from '../../types';
31
+ import { useConceptLookup } from '../../hooks/useConceptLookup';
32
+ import styles from './question-modal.scss';
39
33
 
40
- type AddQuestionModalProps = {
34
+ interface AddQuestionModalProps {
41
35
  onModalChange: (showModal: boolean) => void;
42
36
  onQuestionEdit: (question: Question) => void;
43
37
  onSchemaChange: (schema: Schema) => void;
@@ -47,7 +41,16 @@ type AddQuestionModalProps = {
47
41
  schema: Schema;
48
42
  sectionIndex: number;
49
43
  showModal: boolean;
50
- };
44
+ }
45
+
46
+ interface Config {
47
+ fieldTypes: Array<RenderType>;
48
+ questionTypes: Array<string>;
49
+ }
50
+
51
+ interface Item {
52
+ text: string;
53
+ }
51
54
 
52
55
  const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
53
56
  schema,
@@ -60,43 +63,49 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
60
63
  onModalChange,
61
64
  }) => {
62
65
  const { t } = useTranslation();
63
- const { fieldTypes, questionTypes } = useConfig();
64
- const [max, setMax] = useState("");
65
- const [min, setMin] = useState("");
66
- const [questionLabel, setQuestionLabel] = useState("");
67
- const [questionType, setQuestionType] = useState("");
66
+ const { fieldTypes, questionTypes }: Config = useConfig();
67
+
68
+ const [answers, setAnswers] = useState<Array<Answer>>([]);
69
+ const [conceptMappings, setConceptMappings] = useState<Array<ConceptMapping>>([]);
70
+ const [conceptToLookup, setConceptToLookup] = useState('');
71
+ const [fieldType, setFieldType] = useState<RenderType | null>(null);
68
72
  const [isQuestionRequired, setIsQuestionRequired] = useState(false);
69
- const [fieldType, setFieldType] = useState<RenderType>(null);
70
- const [questionId, setQuestionId] = useState("");
71
- const [answers, setAnswers] = useState<Answer[]>([]);
72
- const [selectedConcept, setSelectedConcept] = useState(null);
73
- const [conceptMappings, setConceptMappings] = useState<ConceptMapping[]>([]);
74
- const [rows, setRows] = useState(2);
75
- const [conceptToLookup, setConceptToLookup] = useState("");
76
- const [selectedAnswers, setSelectedAnswers] = useState([]);
73
+ const [max, setMax] = useState('');
74
+ const [min, setMin] = useState('');
75
+ const [questionId, setQuestionId] = useState('');
76
+ const [questionLabel, setQuestionLabel] = useState('');
77
+ const [questionType, setQuestionType] = useState<string | null>(null);
78
+ const [rows, setRows] = useState('');
79
+ const [selectedConcept, setSelectedConcept] = useState<Concept | null>(null);
80
+ const [selectedAnswers, setSelectedAnswers] = useState<
81
+ Array<{
82
+ id: string;
83
+ text: string;
84
+ }>
85
+ >([]);
86
+
77
87
  const { concepts, isLoadingConcepts } = useConceptLookup(conceptToLookup);
78
88
 
79
- const handleConceptChange = (event: React.ChangeEvent<HTMLInputElement>) =>
80
- setConceptToLookup(event.target.value);
89
+ const handleConceptChange = (event: React.ChangeEvent<HTMLInputElement>) => setConceptToLookup(event.target.value);
81
90
 
82
91
  const handleConceptSelect = (concept: Concept) => {
83
- setConceptToLookup("");
92
+ setConceptToLookup('');
84
93
  setSelectedConcept(concept);
85
94
  setAnswers(
86
95
  concept?.answers?.map((answer) => ({
87
96
  concept: answer?.uuid,
88
97
  label: answer?.display,
89
- }))
98
+ })),
90
99
  );
91
100
  setConceptMappings(
92
101
  concept?.mappings?.map((conceptMapping) => {
93
- const data = conceptMapping.display.split(": ");
102
+ const data = conceptMapping.display.split(': ');
94
103
  return {
95
104
  relationship: conceptMapping.conceptMapType.display,
96
105
  type: data[0],
97
106
  value: data[1],
98
107
  };
99
- })
108
+ }),
100
109
  );
101
110
  };
102
111
 
@@ -109,7 +118,7 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
109
118
  });
110
119
  });
111
120
 
112
- const questionIds = flattenDeep(nestedIds);
121
+ const questionIds: Array<string> = flattenDeep(nestedIds);
113
122
 
114
123
  return questionIds.includes(idToTest);
115
124
  };
@@ -121,9 +130,7 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
121
130
 
122
131
  const createQuestion = () => {
123
132
  try {
124
- const computedQuestionId = `question${questionIndex + 1}Section${
125
- sectionIndex + 1
126
- }Page-${pageIndex + 1}`;
133
+ const computedQuestionId = `question${questionIndex + 1}Section${sectionIndex + 1}Page-${pageIndex + 1}`;
127
134
 
128
135
  schema.pages[pageIndex]?.sections?.[sectionIndex]?.questions?.push({
129
136
  label: questionLabel,
@@ -132,9 +139,9 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
132
139
  id: questionId ?? computedQuestionId,
133
140
  questionOptions: {
134
141
  rendering: fieldType,
135
- concept: selectedConcept.uuid,
142
+ concept: selectedConcept?.uuid,
136
143
  conceptMappings: conceptMappings,
137
- answers: selectedAnswers.map((answer) => ({
144
+ answers: selectedAnswers?.map((answer) => ({
138
145
  concept: answer.id,
139
146
  label: answer.text,
140
147
  })),
@@ -145,8 +152,8 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
145
152
  onSchemaChange({ ...schema });
146
153
 
147
154
  resetIndices();
148
- setQuestionLabel("");
149
- setQuestionId("");
155
+ setQuestionLabel('');
156
+ setQuestionId('');
150
157
  setIsQuestionRequired(false);
151
158
  setQuestionType(null);
152
159
  setFieldType(null);
@@ -156,62 +163,51 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
156
163
  setSelectedAnswers([]);
157
164
 
158
165
  showToast({
159
- title: t("success", "Success!"),
160
- kind: "success",
166
+ title: t('success', 'Success!'),
167
+ kind: 'success',
161
168
  critical: true,
162
- description: t("questionCreated", "New question created"),
169
+ description: t('questionCreated', 'New question created'),
163
170
  });
164
171
  } catch (error) {
165
- showNotification({
166
- title: t("errorCreatingQuestion", "Error creating question"),
167
- kind: "error",
168
- critical: true,
169
- description: error?.message,
170
- });
172
+ if (error instanceof Error) {
173
+ showNotification({
174
+ title: t('errorCreatingQuestion', 'Error creating question'),
175
+ kind: 'error',
176
+ critical: true,
177
+ description: error?.message,
178
+ });
179
+ }
171
180
  }
172
181
  };
173
182
 
174
183
  return (
175
- <ComposedModal
176
- open={showModal}
177
- onClose={() => onModalChange(false)}
178
- preventCloseOnClickOutside
179
- >
180
- <ModalHeader title={t("createNewQuestion", "Create a new question")} />
181
- <Form
182
- className={styles.form}
183
- onSubmit={(event) => event.preventDefault()}
184
- >
184
+ <ComposedModal open={showModal} onClose={() => onModalChange(false)} preventCloseOnClickOutside>
185
+ <ModalHeader title={t('createNewQuestion', 'Create a new question')} />
186
+ <Form className={styles.form} onSubmit={(event: React.SyntheticEvent) => event.preventDefault()}>
185
187
  <ModalBody hasScrollingContent>
186
- <FormGroup legendText={""}>
188
+ <FormGroup legendText={''}>
187
189
  <Stack gap={5}>
188
190
  <TextInput
189
191
  id="questionLabel"
190
- labelText={t("questionLabel", "Label")}
191
- placeholder={t("labelPlaceholder", "e.g. Type of Anaesthesia")}
192
+ labelText={t('questionLabel', 'Label')}
193
+ placeholder={t('labelPlaceholder', 'e.g. Type of Anaesthesia')}
192
194
  value={questionLabel}
193
- onChange={(event) => setQuestionLabel(event.target.value)}
195
+ onChange={(event: React.ChangeEvent<HTMLInputElement>) => setQuestionLabel(event.target.value)}
194
196
  required
195
197
  />
196
198
 
197
199
  <TextInput
198
200
  id="questionId"
199
201
  invalid={questionIdExists(questionId)}
200
- invalidText={t(
201
- "questionIdExists",
202
- "This question ID already exists in your schema"
203
- )}
204
- labelText={t(
205
- "questionId",
206
- "Question ID (prefer using camel-case for IDs)"
207
- )}
202
+ invalidText={t('questionIdExists', 'This question ID already exists in your schema')}
203
+ labelText={t('questionId', 'Question ID (prefer using camel-case for IDs)')}
208
204
  value={questionId}
209
- onChange={(event) => {
205
+ onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
210
206
  setQuestionId(event.target.value);
211
207
  }}
212
208
  placeholder={t(
213
- "questionIdPlaceholder",
214
- 'Enter a unique ID e.g. "anaesthesiaType" for a question asking about the type of anaesthesia.'
209
+ 'questionIdPlaceholder',
210
+ 'Enter a unique ID e.g. "anaesthesiaType" for a question asking about the type of anaesthesia.',
215
211
  )}
216
212
  required
217
213
  />
@@ -220,21 +216,21 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
220
216
  defaultSelected="optional"
221
217
  name="isQuestionRequired"
222
218
  legendText={t(
223
- "isQuestionRequiredOrOptional",
224
- "Is this question a required or optional field? Required fields must be answered before the form can be submitted."
219
+ 'isQuestionRequiredOrOptional',
220
+ 'Is this question a required or optional field? Required fields must be answered before the form can be submitted.',
225
221
  )}
226
222
  >
227
223
  <RadioButton
228
224
  id="questionIsNotRequired"
229
225
  defaultChecked={true}
230
- labelText={t("optional", "Optional")}
226
+ labelText={t('optional', 'Optional')}
231
227
  onClick={() => setIsQuestionRequired(false)}
232
228
  value="optional"
233
229
  />
234
230
  <RadioButton
235
231
  id="questionIsRequired"
236
232
  defaultChecked={false}
237
- labelText={t("required", "Required")}
233
+ labelText={t('required', 'Required')}
238
234
  onClick={() => setIsQuestionRequired(true)}
239
235
  value="required"
240
236
  />
@@ -242,93 +238,72 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
242
238
 
243
239
  <Select
244
240
  value={questionType}
245
- onChange={(event) => setQuestionType(event.target.value)}
241
+ onChange={(event: React.ChangeEvent<HTMLSelectElement>) => setQuestionType(event.target.value)}
246
242
  id="questionType"
247
- invalidText={t("typeRequired", "Type is required")}
248
- labelText={t("questionType", "Question type")}
243
+ invalidText={t('typeRequired', 'Type is required')}
244
+ labelText={t('questionType', 'Question type')}
249
245
  required
250
246
  >
251
- {!questionType && (
252
- <SelectItem
253
- text={t("chooseQuestionType", "Choose a question type")}
254
- value=""
255
- />
256
- )}
247
+ {!questionType && <SelectItem text={t('chooseQuestionType', 'Choose a question type')} value="" />}
257
248
  {questionTypes.map((questionType, key) => (
258
- <SelectItem
259
- text={questionType}
260
- value={questionType}
261
- key={key}
262
- />
249
+ <SelectItem text={questionType} value={questionType} key={key} />
263
250
  ))}
264
251
  </Select>
265
252
 
266
253
  <Select
267
254
  value={fieldType}
268
- onChange={(event) => setFieldType(event.target.value)}
255
+ onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
256
+ setFieldType(event.target.value as RenderType)
257
+ }
269
258
  id="renderingType"
270
- invalidText={t(
271
- "validFieldTypeRequired",
272
- "A valid field type value is required"
273
- )}
274
- labelText={t("fieldType", "Field type")}
259
+ invalidText={t('validFieldTypeRequired', 'A valid field type value is required')}
260
+ labelText={t('fieldType', 'Field type')}
275
261
  required
276
262
  >
277
- {!fieldType && (
278
- <SelectItem
279
- text={t("chooseFieldType", "Choose a field type")}
280
- value=""
281
- />
282
- )}
263
+ {!fieldType && <SelectItem text={t('chooseFieldType', 'Choose a field type')} value="" />}
283
264
  {fieldTypes.map((fieldType, key) => (
284
265
  <SelectItem text={fieldType} value={fieldType} key={key} />
285
266
  ))}
286
267
  </Select>
287
268
 
288
- {fieldType === "number" ? (
269
+ {fieldType === 'number' ? (
289
270
  <>
290
271
  <TextInput
291
272
  id="min"
292
273
  labelText="Min"
293
- value={min || ""}
294
- onChange={(event) => setMin(event.target.value)}
274
+ value={min || ''}
275
+ onChange={(event: React.ChangeEvent<HTMLInputElement>) => setMin(event.target.value)}
295
276
  required
296
277
  />
297
278
  <TextInput
298
279
  id="max"
299
280
  labelText="Max"
300
- value={max || ""}
301
- onChange={(event) => setMax(event.target.value)}
281
+ value={max || ''}
282
+ onChange={(event: React.ChangeEvent<HTMLInputElement>) => setMax(event.target.value)}
302
283
  required
303
284
  />
304
285
  </>
305
- ) : fieldType === "textarea" ? (
286
+ ) : fieldType === 'textarea' ? (
306
287
  <TextInput
307
288
  id="textAreaRows"
308
- labelText={t("rows", "Rows")}
309
- value={rows || ""}
310
- onChange={(event) => setRows(event.target.value)}
289
+ labelText={t('rows', 'Rows')}
290
+ value={rows || ''}
291
+ onChange={(event: React.ChangeEvent<HTMLInputElement>) => setRows(event.target.value)}
311
292
  required
312
293
  />
313
294
  ) : null}
314
295
 
315
- {fieldType !== "ui-select-extended" && (
296
+ {fieldType !== 'ui-select-extended' && (
316
297
  <div>
317
298
  <FormLabel className={styles.label}>
318
- {t(
319
- "searchForBackingConcept",
320
- "Search for a backing concept"
321
- )}
299
+ {t('searchForBackingConcept', 'Search for a backing concept')}
322
300
  </FormLabel>
323
301
  <Search
324
302
  size="md"
325
303
  id="conceptLookup"
326
304
  onClear={() => setSelectedConcept(null)}
327
305
  onChange={handleConceptChange}
328
- placeholder={t(
329
- "searchConcept",
330
- "Search using a concept name or UUID"
331
- )}
306
+ placeholder={t('searchConcept', 'Search using a concept name or UUID')}
332
307
  value={(() => {
333
308
  if (conceptToLookup) {
334
309
  return conceptToLookup;
@@ -336,7 +311,7 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
336
311
  if (selectedConcept) {
337
312
  return selectedConcept.display;
338
313
  }
339
- return "";
314
+ return '';
340
315
  })()}
341
316
  required
342
317
  />
@@ -344,12 +319,9 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
344
319
  if (!conceptToLookup) return null;
345
320
  if (isLoadingConcepts)
346
321
  return (
347
- <InlineLoading
348
- className={styles.loader}
349
- description={t("searching", "Searching") + "..."}
350
- />
322
+ <InlineLoading className={styles.loader} description={t('searching', 'Searching') + '...'} />
351
323
  );
352
- if (concepts && concepts?.length && !isLoadingConcepts) {
324
+ if (concepts?.length && !isLoadingConcepts) {
353
325
  return (
354
326
  <ul className={styles.conceptList}>
355
327
  {concepts?.map((concept, index) => (
@@ -369,30 +341,20 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
369
341
  <Layer>
370
342
  <Tile className={styles.emptyResults}>
371
343
  <span>
372
- {t(
373
- "noMatchingConcepts",
374
- "No concepts were found that match"
375
- )}{" "}
344
+ {t('noMatchingConcepts', 'No concepts were found that match')}{' '}
376
345
  <strong>"{conceptToLookup}".</strong>
377
346
  </span>
378
347
  </Tile>
379
348
 
380
349
  <div className={styles.oclLauncherBanner}>
381
- {
382
- <p className={styles.bodyShort01}>
383
- {t(
384
- "conceptSearchHelpText",
385
- "Can't find a concept?"
386
- )}
387
- </p>
388
- }
350
+ {<p className={styles.bodyShort01}>{t('conceptSearchHelpText', "Can't find a concept?")}</p>}
389
351
  <a
390
352
  className={styles.oclLink}
391
353
  target="_blank"
392
354
  rel="noopener noreferrer"
393
- href={"https://app.openconceptlab.org/"}
355
+ href={'https://app.openconceptlab.org/'}
394
356
  >
395
- {t("searchInOCL", "Search in OCL")}
357
+ {t('searchInOCL', 'Search in OCL')}
396
358
  <ArrowUpRight size={16} />
397
359
  </a>
398
360
  </div>
@@ -402,17 +364,15 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
402
364
  </div>
403
365
  )}
404
366
 
405
- {conceptMappings && conceptMappings.length ? (
367
+ {conceptMappings?.length ? (
406
368
  <FormGroup>
407
- <FormLabel className={styles.label}>
408
- {t("mappings", "Mappings")}
409
- </FormLabel>
369
+ <FormLabel className={styles.label}>{t('mappings', 'Mappings')}</FormLabel>
410
370
  <table className={styles.tableStriped}>
411
371
  <thead>
412
372
  <tr>
413
- <th>{t("relationship", "Relationship")}</th>
414
- <th>{t("source", "Source")}</th>
415
- <th>{t("code", "Code")}</th>
373
+ <th>{t('relationship', 'Relationship')}</th>
374
+ <th>{t('source', 'Source')}</th>
375
+ <th>{t('code', 'Code')}</th>
416
376
  </tr>
417
377
  </thead>
418
378
  <tbody>
@@ -428,31 +388,33 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
428
388
  </FormGroup>
429
389
  ) : null}
430
390
 
431
- {answers && answers.length ? (
391
+ {answers?.length ? (
432
392
  <MultiSelect
433
393
  className={styles.multiSelect}
434
394
  direction="top"
435
395
  id="selectAnswers"
436
- itemToString={(item) => item.text}
396
+ itemToString={(item: Item) => item.text}
437
397
  items={answers.map((answer) => ({
438
398
  id: answer.concept,
439
399
  text: answer.label,
440
400
  }))}
441
- onChange={({ selectedItems }) =>
442
- setSelectedAnswers(selectedItems.sort())
443
- }
401
+ onChange={({
402
+ selectedItems,
403
+ }: {
404
+ selectedItems: Array<{
405
+ id: string;
406
+ text: string;
407
+ }>;
408
+ }) => setSelectedAnswers(selectedItems.sort())}
444
409
  size="md"
445
- titleText={t(
446
- "selectAnswersToDisplay",
447
- "Select answers to display"
448
- )}
410
+ titleText={t('selectAnswersToDisplay', 'Select answers to display')}
449
411
  />
450
412
  ) : null}
451
413
 
452
414
  {selectedAnswers.length ? (
453
415
  <div>
454
416
  {selectedAnswers.map((answer) => (
455
- <Tag className={styles.tag} key={answer.id} type={"blue"}>
417
+ <Tag className={styles.tag} key={answer.id} type={'blue'}>
456
418
  {answer.text}
457
419
  </Tag>
458
420
  ))}
@@ -464,7 +426,7 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
464
426
  </Form>
465
427
  <ModalFooter>
466
428
  <Button onClick={() => onModalChange(false)} kind="secondary">
467
- {t("cancel", "Cancel")}
429
+ {t('cancel', 'Cancel')}
468
430
  </Button>
469
431
  <Button
470
432
  disabled={
@@ -472,11 +434,11 @@ const AddQuestionModal: React.FC<AddQuestionModalProps> = ({
472
434
  !questionId ||
473
435
  questionIdExists(questionId) ||
474
436
  !fieldType ||
475
- (fieldType !== "ui-select-extended" && !selectedConcept)
437
+ (fieldType !== 'ui-select-extended' && !selectedConcept)
476
438
  }
477
439
  onClick={handleCreateQuestion}
478
440
  >
479
- <span>{t("save", "Save")}</span>
441
+ <span>{t('save', 'Save')}</span>
480
442
  </Button>
481
443
  </ModalFooter>
482
444
  </ComposedModal>
@@ -1,23 +1,17 @@
1
- import React from "react";
2
- import { useTranslation } from "react-i18next";
3
- import {
4
- Button,
5
- ComposedModal,
6
- ModalBody,
7
- ModalFooter,
8
- ModalHeader,
9
- } from "@carbon/react";
10
- import { showNotification, showToast } from "@openmrs/esm-framework";
11
- import type { Schema } from "../../types";
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Button, ComposedModal, ModalBody, ModalFooter, ModalHeader } from '@carbon/react';
4
+ import { showNotification, showToast } from '@openmrs/esm-framework';
5
+ import type { Schema } from '../../types';
12
6
 
13
- type DeletePageModalProps = {
7
+ interface DeletePageModalProps {
14
8
  onModalChange: (showModal: boolean) => void;
15
9
  onSchemaChange: (schema: Schema) => void;
16
10
  resetIndices: () => void;
17
11
  pageIndex: number;
18
12
  schema: Schema;
19
13
  showModal: boolean;
20
- };
14
+ }
21
15
 
22
16
  const DeletePageModal: React.FC<DeletePageModalProps> = ({
23
17
  onModalChange,
@@ -37,44 +31,37 @@ const DeletePageModal: React.FC<DeletePageModalProps> = ({
37
31
  resetIndices();
38
32
 
39
33
  showToast({
40
- title: t("success", "Success!"),
41
- kind: "success",
34
+ title: t('success', 'Success!'),
35
+ kind: 'success',
42
36
  critical: true,
43
- description: t("pageDeleted", "Page deleted"),
37
+ description: t('pageDeleted', 'Page deleted'),
44
38
  });
45
39
  } catch (error) {
46
- showNotification({
47
- title: t("errorDeletingPage", "Error deleting page"),
48
- kind: "error",
49
- critical: true,
50
- description: error?.message,
51
- });
40
+ if (error instanceof Error) {
41
+ showNotification({
42
+ title: t('errorDeletingPage', 'Error deleting page'),
43
+ kind: 'error',
44
+ critical: true,
45
+ description: error?.message,
46
+ });
47
+ }
52
48
  }
53
49
  };
54
50
 
55
51
  return (
56
- <ComposedModal
57
- open={showModal}
58
- onClose={() => onModalChange(false)}
59
- preventCloseOnClickOutside
60
- >
61
- <ModalHeader
62
- title={t(
63
- "deletePageConfirmation",
64
- "Are you sure you want to delete this page?"
65
- )}
66
- />
52
+ <ComposedModal open={showModal} onClose={() => onModalChange(false)} preventCloseOnClickOutside>
53
+ <ModalHeader title={t('deletePageConfirmation', 'Are you sure you want to delete this page?')} />
67
54
  <ModalBody>
68
55
  <p>
69
56
  {t(
70
- "deletePageExplainerText",
71
- "Deleting this page will delete all the sections and questions associated with it. This action cannot be undone."
57
+ 'deletePageExplainerText',
58
+ 'Deleting this page will delete all the sections and questions associated with it. This action cannot be undone.',
72
59
  )}
73
60
  </p>
74
61
  </ModalBody>
75
62
  <ModalFooter>
76
63
  <Button kind="secondary" onClick={() => onModalChange(false)}>
77
- {t("cancel", "Cancel")}
64
+ {t('cancel', 'Cancel')}
78
65
  </Button>
79
66
  <Button
80
67
  kind="danger"
@@ -83,7 +70,7 @@ const DeletePageModal: React.FC<DeletePageModalProps> = ({
83
70
  onModalChange(false);
84
71
  }}
85
72
  >
86
- <span>{t("deletePage", "Delete page")}</span>
73
+ <span>{t('deletePage', 'Delete page')}</span>
87
74
  </Button>
88
75
  </ModalFooter>
89
76
  </ComposedModal>