@aehrc/smart-forms-renderer 0.30.2 → 0.31.0

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 (255) hide show
  1. package/README.md +6 -6
  2. package/lib/components/FormComponents/BooleanItem/BooleanField.js +5 -4
  3. package/lib/components/FormComponents/BooleanItem/BooleanField.js.map +1 -1
  4. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js +5 -4
  5. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js.map +1 -1
  6. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js +5 -4
  7. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js.map +1 -1
  8. package/lib/components/FormComponents/DateTimeItems/index.d.ts +1 -1
  9. package/lib/components/FormComponents/DateTimeItems/index.js +1 -1
  10. package/lib/components/FormComponents/DateTimeItems/index.js.map +1 -1
  11. package/lib/components/FormComponents/DateTimeItems/utils/parseDate.d.ts +5 -0
  12. package/lib/components/FormComponents/DateTimeItems/utils/parseDate.js +5 -0
  13. package/lib/components/FormComponents/DateTimeItems/utils/parseDate.js.map +1 -1
  14. package/lib/components/FormComponents/GridGroup/GridGroup.d.ts +6 -0
  15. package/lib/components/FormComponents/GridGroup/GridGroup.js +6 -0
  16. package/lib/components/FormComponents/GridGroup/GridGroup.js.map +1 -1
  17. package/lib/components/FormComponents/RepeatGroup/RepeatGroup.d.ts +6 -0
  18. package/lib/components/FormComponents/RepeatGroup/RepeatGroup.js +6 -0
  19. package/lib/components/FormComponents/RepeatGroup/RepeatGroup.js.map +1 -1
  20. package/lib/components/FormComponents/RepeatItem/RepeatItem.d.ts +5 -0
  21. package/lib/components/FormComponents/RepeatItem/RepeatItem.js +5 -0
  22. package/lib/components/FormComponents/RepeatItem/RepeatItem.js.map +1 -1
  23. package/lib/components/FormComponents/SingleItem/SingleItem.d.ts +6 -0
  24. package/lib/components/FormComponents/SingleItem/SingleItem.js +6 -0
  25. package/lib/components/FormComponents/SingleItem/SingleItem.js.map +1 -1
  26. package/lib/components/FormComponents/Tables/GroupTable.d.ts +6 -0
  27. package/lib/components/FormComponents/Tables/GroupTable.js +6 -0
  28. package/lib/components/FormComponents/Tables/GroupTable.js.map +1 -1
  29. package/lib/components/FormComponents/index.d.ts +6 -6
  30. package/lib/components/FormComponents/index.js +6 -6
  31. package/lib/components/FormComponents/index.js.map +1 -1
  32. package/lib/components/Renderer/BaseRenderer.d.ts +7 -0
  33. package/lib/components/Renderer/BaseRenderer.js +7 -0
  34. package/lib/components/Renderer/BaseRenderer.js.map +1 -1
  35. package/lib/components/Renderer/SmartFormsRenderer.d.ts +22 -1
  36. package/lib/components/Renderer/SmartFormsRenderer.js +16 -6
  37. package/lib/components/Renderer/SmartFormsRenderer.js.map +1 -1
  38. package/lib/components/Renderer/index.d.ts +1 -0
  39. package/lib/components/Renderer/index.js.map +1 -1
  40. package/lib/components/index.d.ts +3 -2
  41. package/lib/components/index.js +2 -2
  42. package/lib/components/index.js.map +1 -1
  43. package/lib/hooks/index.d.ts +2 -0
  44. package/lib/hooks/index.js +2 -0
  45. package/lib/hooks/index.js.map +1 -1
  46. package/lib/hooks/useBuildForm.d.ts +15 -0
  47. package/lib/hooks/useBuildForm.js +41 -0
  48. package/lib/hooks/useBuildForm.js.map +1 -0
  49. package/lib/hooks/useHidden.d.ts +6 -0
  50. package/lib/hooks/useHidden.js +6 -0
  51. package/lib/hooks/useHidden.js.map +1 -1
  52. package/lib/hooks/useInitaliseFhirClient.d.ts +1 -0
  53. package/lib/hooks/useInitaliseFhirClient.js +55 -0
  54. package/lib/hooks/useInitaliseFhirClient.js.map +1 -0
  55. package/lib/hooks/useInitialiseForm.d.ts +20 -0
  56. package/lib/hooks/useInitialiseForm.js +72 -0
  57. package/lib/hooks/useInitialiseForm.js.map +1 -0
  58. package/lib/hooks/useInitialiseRenderer.d.ts +1 -1
  59. package/lib/hooks/useInitialiseRenderer.js +8 -31
  60. package/lib/hooks/useInitialiseRenderer.js.map +1 -1
  61. package/lib/hooks/useRendererQueryClient.d.ts +10 -0
  62. package/lib/hooks/useRendererQueryClient.js +36 -0
  63. package/lib/hooks/useRendererQueryClient.js.map +1 -0
  64. package/lib/hooks/useValueSetCodings.js +1 -0
  65. package/lib/hooks/useValueSetCodings.js.map +1 -1
  66. package/lib/index.d.ts +10 -40
  67. package/lib/index.js +8 -77
  68. package/lib/index.js.map +1 -1
  69. package/lib/interfaces/calculatedExpression.interface.d.ts +7 -0
  70. package/lib/interfaces/calculatedExpression.interface.js +16 -0
  71. package/lib/interfaces/calculatedExpression.interface.js.map +1 -1
  72. package/lib/interfaces/enableWhen.interface.d.ts +12 -0
  73. package/lib/interfaces/index.d.ts +4 -1
  74. package/lib/interfaces/index.js +16 -0
  75. package/lib/interfaces/index.js.map +1 -1
  76. package/lib/interfaces/populate.interface.d.ts +6 -0
  77. package/lib/interfaces/repopulateItems.interface.d.ts +0 -0
  78. package/lib/interfaces/repopulateItems.interface.js +2 -0
  79. package/lib/interfaces/repopulateItems.interface.js.map +1 -0
  80. package/lib/interfaces/tab.interface.d.ts +10 -0
  81. package/lib/interfaces/tab.interface.js +16 -0
  82. package/lib/interfaces/tab.interface.js.map +1 -1
  83. package/lib/interfaces/variables.interface.d.ts +12 -0
  84. package/lib/stores/index.d.ts +4 -0
  85. package/lib/stores/index.js.map +1 -1
  86. package/lib/stores/questionnaireResponseStore.d.ts +37 -2
  87. package/lib/stores/questionnaireResponseStore.js +72 -22
  88. package/lib/stores/questionnaireResponseStore.js.map +1 -1
  89. package/lib/stores/questionnaireStore.d.ts +59 -3
  90. package/lib/stores/questionnaireStore.js +18 -0
  91. package/lib/stores/questionnaireStore.js.map +1 -1
  92. package/lib/stores/smartConfigStore.d.ts +37 -0
  93. package/lib/stores/smartConfigStore.js +21 -0
  94. package/lib/stores/smartConfigStore.js.map +1 -1
  95. package/lib/stores/terminologyServerStore.d.ts +28 -2
  96. package/lib/stores/terminologyServerStore.js +16 -0
  97. package/lib/stores/terminologyServerStore.js.map +1 -1
  98. package/lib/stories/InitialiseFormWrapperForStorybook.d.ts +29 -0
  99. package/lib/stories/InitialiseFormWrapperForStorybook.js +65 -0
  100. package/lib/stories/InitialiseFormWrapperForStorybook.js.map +1 -0
  101. package/lib/stories/StorybookWrappers/BuildFormButtonForStorybook.d.ts +8 -0
  102. package/lib/stories/StorybookWrappers/BuildFormButtonForStorybook.js +44 -0
  103. package/lib/stories/StorybookWrappers/BuildFormButtonForStorybook.js.map +1 -0
  104. package/lib/stories/StorybookWrappers/BuildFormButtonTesterWrapperForStorybook.d.ts +18 -0
  105. package/lib/stories/StorybookWrappers/BuildFormButtonTesterWrapperForStorybook.js +48 -0
  106. package/lib/stories/StorybookWrappers/BuildFormButtonTesterWrapperForStorybook.js.map +1 -0
  107. package/lib/stories/StorybookWrappers/InitialiseFormWrapperForStorybook.d.ts +31 -0
  108. package/lib/stories/StorybookWrappers/InitialiseFormWrapperForStorybook.js +67 -0
  109. package/lib/stories/StorybookWrappers/InitialiseFormWrapperForStorybook.js.map +1 -0
  110. package/lib/stories/StorybookWrappers/PrePopButtonForStorybook.d.ts +7 -0
  111. package/lib/stories/StorybookWrappers/PrePopButtonForStorybook.js +32 -0
  112. package/lib/stories/StorybookWrappers/PrePopButtonForStorybook.js.map +1 -0
  113. package/lib/stories/StorybookWrappers/PrePopWrapperForStorybook.d.ts +21 -0
  114. package/lib/stories/StorybookWrappers/PrePopWrapperForStorybook.js +83 -0
  115. package/lib/stories/StorybookWrappers/PrePopWrapperForStorybook.js.map +1 -0
  116. package/lib/stories/StorybookWrappers/index.d.ts +3 -0
  117. package/lib/stories/StorybookWrappers/index.js +20 -0
  118. package/lib/stories/StorybookWrappers/index.js.map +1 -0
  119. package/lib/stories/StorybookWrappers/populateCallbackForStorybook.d.ts +8 -0
  120. package/lib/stories/StorybookWrappers/populateCallbackForStorybook.js +46 -0
  121. package/lib/stories/StorybookWrappers/populateCallbackForStorybook.js.map +1 -0
  122. package/lib/stories/index.d.ts +1 -0
  123. package/lib/stories/index.js +18 -0
  124. package/lib/stories/index.js.map +1 -0
  125. package/lib/theme/Theme.d.ts +8 -2
  126. package/lib/theme/Theme.js +8 -2
  127. package/lib/theme/Theme.js.map +1 -1
  128. package/lib/theme/index.d.ts +1 -0
  129. package/lib/theme/index.js +2 -0
  130. package/lib/theme/index.js.map +1 -0
  131. package/lib/utils/enableWhen.d.ts +1 -1
  132. package/lib/utils/enableWhenExpression.d.ts +1 -1
  133. package/lib/utils/fhirpath.d.ts +1 -1
  134. package/lib/utils/index.d.ts +5 -3
  135. package/lib/utils/index.js +4 -3
  136. package/lib/utils/index.js.map +1 -1
  137. package/lib/utils/initialise.d.ts +2 -2
  138. package/lib/utils/initialise.js +1 -1
  139. package/lib/utils/manageForm.d.ts +45 -0
  140. package/lib/utils/manageForm.js +101 -0
  141. package/lib/utils/manageForm.js.map +1 -0
  142. package/lib/utils/qItem.d.ts +1 -1
  143. package/lib/utils/questionnaireStoreUtils/extractOtherExtensions.d.ts +1 -1
  144. package/lib/utils/removeEmptyAnswers.d.ts +1 -1
  145. package/lib/utils/repopulateIntoResponse.d.ts +6 -0
  146. package/lib/utils/repopulateIntoResponse.js +11 -0
  147. package/lib/utils/repopulateIntoResponse.js.map +1 -1
  148. package/lib/utils/repopulateItems.d.ts +19 -1
  149. package/lib/utils/repopulateItems.js +23 -0
  150. package/lib/utils/repopulateItems.js.map +1 -1
  151. package/lib/utils/tabs.d.ts +2 -2
  152. package/lib/utils/tabs.js +1 -1
  153. package/lib/utils/validateQuestionnaire.d.ts +0 -4
  154. package/lib/utils/validateQuestionnaire.js +9 -5
  155. package/lib/utils/validateQuestionnaire.js.map +1 -1
  156. package/package.json +1 -1
  157. package/src/components/FormComponents/BooleanItem/BooleanField.tsx +11 -9
  158. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.tsx +11 -9
  159. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.tsx +11 -9
  160. package/src/components/FormComponents/DateTimeItems/index.ts +1 -1
  161. package/src/components/FormComponents/DateTimeItems/utils/parseDate.ts +5 -0
  162. package/src/components/FormComponents/GridGroup/GridGroup.tsx +6 -0
  163. package/src/components/FormComponents/RepeatGroup/RepeatGroup.tsx +6 -0
  164. package/src/components/FormComponents/RepeatItem/RepeatItem.tsx +5 -0
  165. package/src/components/FormComponents/SingleItem/SingleItem.tsx +6 -0
  166. package/src/components/FormComponents/Tables/GroupTable.tsx +6 -0
  167. package/src/components/FormComponents/index.ts +6 -6
  168. package/src/components/Renderer/BaseRenderer.tsx +7 -0
  169. package/src/components/Renderer/SmartFormsRenderer.tsx +34 -11
  170. package/src/components/Renderer/index.ts +1 -0
  171. package/src/components/index.ts +10 -2
  172. package/src/hooks/index.ts +2 -0
  173. package/src/hooks/useBuildForm.ts +58 -0
  174. package/src/hooks/useHidden.ts +6 -0
  175. package/src/hooks/useInitialiseForm.ts +93 -0
  176. package/src/hooks/{useQueryClient.ts → useRendererQueryClient.ts} +9 -2
  177. package/src/hooks/useValueSetCodings.ts +1 -0
  178. package/src/index.ts +59 -96
  179. package/src/interfaces/calculatedExpression.interface.ts +24 -0
  180. package/src/interfaces/enableWhen.interface.ts +12 -0
  181. package/src/interfaces/index.ts +21 -10
  182. package/src/interfaces/populate.interface.ts +6 -0
  183. package/src/interfaces/tab.interface.ts +12 -0
  184. package/src/interfaces/variables.interface.ts +12 -0
  185. package/src/stores/index.ts +7 -0
  186. package/src/stores/questionnaireResponseStore.ts +90 -19
  187. package/src/stores/questionnaireStore.ts +62 -2
  188. package/src/stores/smartConfigStore.ts +37 -0
  189. package/src/stores/terminologyServerStore.ts +28 -1
  190. package/src/stories/{BuildFormButtonForStorybook.tsx → StorybookWrappers/BuildFormButtonForStorybook.tsx} +12 -5
  191. package/src/stories/StorybookWrappers/BuildFormButtonTesterWrapperForStorybook.tsx +70 -0
  192. package/src/stories/{BuildFormWrapper.tsx → StorybookWrappers/BuildFormWrapperForStorybook.tsx} +11 -12
  193. package/src/stories/{BuildFormButtonTesterWrapper.tsx → StorybookWrappers/FormValidationTesterWrapperForStorybook.tsx} +22 -19
  194. package/src/stories/{useBuildFormForStorybook.ts → StorybookWrappers/FormValidationViewerForStorybook.tsx} +7 -16
  195. package/src/stories/StorybookWrappers/InitialiseFormWrapperForStorybook.tsx +105 -0
  196. package/src/stories/{PrePopButtonForStorybook.tsx → StorybookWrappers/PrePopButtonForStorybook.tsx} +12 -10
  197. package/src/stories/{PrePopWrapper.tsx → StorybookWrappers/PrePopWrapperForStorybook.tsx} +22 -14
  198. package/src/stories/StorybookWrappers/ValidateFormButtonForStorybook.tsx +41 -0
  199. package/src/stories/StorybookWrappers/index.ts +20 -0
  200. package/src/stories/{populateCallbackForStorybook.ts → StorybookWrappers/populateCallbackForStorybook.ts} +8 -2
  201. package/src/stories/assets/questionnaires/QButtonTester.ts +380 -0
  202. package/src/stories/assets/questionnaires/QValidateTester.ts +118 -0
  203. package/src/stories/itemTypes/Attachment.stories.tsx +3 -3
  204. package/src/stories/itemTypes/Boolean.stories.tsx +3 -3
  205. package/src/stories/itemTypes/Choice.stories.tsx +3 -3
  206. package/src/stories/itemTypes/Date.stories.tsx +3 -3
  207. package/src/stories/itemTypes/DateTime.stories.tsx +3 -3
  208. package/src/stories/itemTypes/Decimal.stories.tsx +3 -3
  209. package/src/stories/itemTypes/Display.stories.tsx +3 -3
  210. package/src/stories/itemTypes/Group.stories.tsx +3 -3
  211. package/src/stories/itemTypes/Integer.stories.tsx +3 -3
  212. package/src/stories/itemTypes/OpenChoice.stories.tsx +3 -3
  213. package/src/stories/itemTypes/Quantity.stories.tsx +3 -3
  214. package/src/stories/itemTypes/Reference.stories.tsx +3 -3
  215. package/src/stories/itemTypes/String.stories.tsx +3 -3
  216. package/src/stories/itemTypes/Text.stories.tsx +3 -3
  217. package/src/stories/itemTypes/Time.stories.tsx +3 -3
  218. package/src/stories/itemTypes/Url.stories.tsx +3 -3
  219. package/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx +3 -3
  220. package/src/stories/sdc/AdvancedControlAppearance.stories.tsx +3 -3
  221. package/src/stories/sdc/AdvancedOther.stories.tsx +3 -3
  222. package/src/stories/sdc/AdvancedTextAppearance.stories.tsx +3 -3
  223. package/src/stories/sdc/BehaviorCalculations.stories.tsx +3 -3
  224. package/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx +3 -3
  225. package/src/stories/sdc/BehaviorOther.stories.tsx +3 -3
  226. package/src/stories/sdc/BehaviorValueConstraints.stories.tsx +3 -3
  227. package/src/stories/sdc/FormPopulation.stories.tsx +3 -3
  228. package/src/stories/sdc/ItemControlDisplay.stories.tsx +3 -3
  229. package/src/stories/sdc/ItemControlGroup.stories.tsx +3 -3
  230. package/src/stories/sdc/ItemControlQuestion.stories.tsx +3 -3
  231. package/src/stories/{rebuildForm/BuildFormTesterWrapper.stories.tsx → testing/BuildFormButtonTesterWrapper.stories.tsx} +6 -9
  232. package/src/stories/testing/PrePopButtonTesterWrapper.stories.tsx +45 -0
  233. package/src/stories/testing/ValidateFormTesterWrapper.stories.tsx +39 -0
  234. package/src/tests/enableWhen.test.ts +6 -2
  235. package/src/theme/Theme.tsx +8 -2
  236. package/src/theme/index.ts +1 -0
  237. package/src/utils/enableWhen.ts +1 -1
  238. package/src/utils/enableWhenExpression.ts +1 -1
  239. package/src/utils/fhirpath.ts +1 -1
  240. package/src/utils/index.ts +5 -7
  241. package/src/utils/initialise.ts +2 -2
  242. package/src/utils/manageForm.ts +110 -0
  243. package/src/utils/qItem.ts +1 -1
  244. package/src/utils/questionnaireStoreUtils/extractOtherExtensions.ts +1 -1
  245. package/src/utils/removeEmptyAnswers.ts +1 -1
  246. package/src/utils/repopulateIntoResponse.ts +17 -0
  247. package/src/utils/repopulateItems.ts +38 -1
  248. package/src/utils/tabs.ts +2 -2
  249. package/src/utils/validateQuestionnaire.ts +12 -17
  250. package/vite.config.ts +1 -1
  251. package/src/hooks/useInitialiseRenderer.ts +0 -114
  252. package/src/stories/assets/questionnaires/QBuildFormButtonTester.ts +0 -270
  253. package/src/stories/populateUtilsForStorybook.ts +0 -545
  254. package/src/utils/buildForm.ts +0 -23
  255. /package/.storybook/{preview.ts → preview.tsx} +0 -0
@@ -26,7 +26,7 @@ import type {
26
26
  QuestionnaireResponseItem,
27
27
  QuestionnaireResponseItemAnswer
28
28
  } from 'fhir/r4';
29
- import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces';
29
+ import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces/enableWhen.interface';
30
30
  import type { Tabs } from '../interfaces/tab.interface';
31
31
  import { assignPopulatedAnswersToEnableWhen } from './enableWhen';
32
32
  import type { CalculatedExpression } from '../interfaces/calculatedExpression.interface';
@@ -34,7 +34,7 @@ import { evaluateInitialCalculatedExpressions } from './calculatedExpression';
34
34
  import { createQuestionnaireResponseItemMap } from './questionnaireResponseStoreUtils/updatableResponseItems';
35
35
 
36
36
  /**
37
- * Initialise a conformant questionnaireResponse from a given questionnaire
37
+ * Initialise a questionnaireResponse from a given questionnaire
38
38
  * optionally takes in an existing questionnaireResponse to be initialised
39
39
  *
40
40
  * @author Sean Fong
@@ -0,0 +1,110 @@
1
+ import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
2
+ import { questionnaireResponseStore, questionnaireStore, smartConfigStore } from '../stores';
3
+ import { initialiseQuestionnaireResponse } from './initialise';
4
+ import { removeEmptyAnswers } from './removeEmptyAnswers';
5
+ import { readEncounter, readPatient, readUser } from '../api/smartClient';
6
+ import type Client from 'fhirclient/lib/Client';
7
+
8
+ /**
9
+ * Build the form with an initial Questionnaire and an optional filled QuestionnaireResponse.
10
+ * If a QuestionnaireResponse is not provided, an empty QuestionnaireResponse is set as the initial QuestionnaireResponse.
11
+ * There are other optional properties such as applying readOnly, providing a terminology server url and additional variables.
12
+ *
13
+ * @param questionnaire - Questionnaire to be rendered
14
+ * @param questionnaireResponse - Pre-populated/draft/loaded QuestionnaireResponse to be rendered (optional)
15
+ * @param readOnly - Applies read-only mode to all items in the form view
16
+ * @param terminologyServerUrl - Terminology server url to fetch terminology. If not provided, the default terminology server will be used. (optional)
17
+ * @param additionalVariables - Additional key-value pair of SDC variables `Record<name, variable extension>` for testing (optional)
18
+ *
19
+ * @author Sean Fong
20
+ */
21
+ export async function buildForm(
22
+ questionnaire: Questionnaire,
23
+ questionnaireResponse?: QuestionnaireResponse,
24
+ readOnly?: boolean,
25
+ terminologyServerUrl?: string,
26
+ additionalVariables?: Record<string, object>
27
+ ): Promise<void> {
28
+ // QR is set to undefined here to prevent it from being initialised twice. This is defined like that for backward compatibility purposes.
29
+ await questionnaireStore
30
+ .getState()
31
+ .buildSourceQuestionnaire(questionnaire, undefined, additionalVariables, terminologyServerUrl);
32
+
33
+ const initialisedQuestionnaireResponse = initialiseQuestionnaireResponse(
34
+ questionnaire,
35
+ questionnaireResponse
36
+ );
37
+ questionnaireResponseStore.getState().buildSourceResponse(initialisedQuestionnaireResponse);
38
+ questionnaireStore.getState().updatePopulatedProperties(initialisedQuestionnaireResponse);
39
+
40
+ if (readOnly) {
41
+ questionnaireStore.getState().setFormAsReadOnly(readOnly);
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Destroy the form to clean up the questionnaire and questionnaireResponse stores.
47
+ *
48
+ * @author Sean Fong
49
+ */
50
+ export function destroyForm(): void {
51
+ questionnaireStore.getState().destroySourceQuestionnaire();
52
+ questionnaireResponseStore.getState().destroySourceResponse();
53
+ }
54
+
55
+ /**
56
+ * Initialise the FHIRClient object to make further FHIR calls in the renderer.
57
+ * Note that this does not provide pre-population capabilities.
58
+ *
59
+ * @param fhirClient - FHIRClient object to perform further FHIR calls. At the moment it's only used in answerExpressions
60
+ *
61
+ * @author Sean Fong
62
+ */
63
+ export async function initialiseFhirClient(fhirClient: Client): Promise<void> {
64
+ smartConfigStore.getState().setClient(fhirClient);
65
+ const patientPromise = readPatient(fhirClient);
66
+ const userPromise = readUser(fhirClient);
67
+ const encounterPromise = readEncounter(fhirClient);
68
+
69
+ const [patient, user, encounter] = await Promise.all([
70
+ patientPromise,
71
+ userPromise,
72
+ encounterPromise
73
+ ]);
74
+ smartConfigStore.getState().setPatient(patient);
75
+ smartConfigStore.getState().setUser(user);
76
+ smartConfigStore.getState().setEncounter(encounter);
77
+ }
78
+
79
+ /**
80
+ * Get the filled QuestionnaireResponse at its current state.
81
+ * If no changes have been made to the form, the initial QuestionnaireResponse is returned.
82
+ *
83
+ * @author Sean Fong
84
+ */
85
+ export function getResponse(): QuestionnaireResponse {
86
+ return questionnaireResponseStore.getState().updatableResponse;
87
+ }
88
+
89
+ /**
90
+ * Remove all hidden answers from the filled QuestionnaireResponse.
91
+ * This takes into account enableWhens, enableWhenExpressions, items without item.answer, empty item.answer arrays and empty strings.
92
+ *
93
+ * @author Sean Fong
94
+ */
95
+ export function removeEmptyAnswersFromResponse(
96
+ questionnaire: Questionnaire,
97
+ questionnaireResponse: QuestionnaireResponse
98
+ ): QuestionnaireResponse {
99
+ const enableWhenIsActivated = questionnaireStore.getState().enableWhenIsActivated;
100
+ const enableWhenItems = questionnaireStore.getState().enableWhenItems;
101
+ const enableWhenExpressions = questionnaireStore.getState().enableWhenExpressions;
102
+
103
+ return removeEmptyAnswers({
104
+ questionnaire,
105
+ questionnaireResponse,
106
+ enableWhenIsActivated,
107
+ enableWhenItems,
108
+ enableWhenExpressions
109
+ });
110
+ }
@@ -19,7 +19,7 @@ import type { Extension, Questionnaire, QuestionnaireItem } from 'fhir/r4';
19
19
  import { getChoiceControlType } from './choice';
20
20
  import { ChoiceItemControl, OpenChoiceItemControl } from '../interfaces/choice.enum';
21
21
  import { getOpenChoiceControlType } from './openChoice';
22
- import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces';
22
+ import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces/enableWhen.interface';
23
23
 
24
24
  interface isHiddenByEnableWhensParams {
25
25
  linkId: string;
@@ -31,7 +31,7 @@ import type {
31
31
  EnableWhenSingleExpression,
32
32
  EnableWhenSingleItemProperties,
33
33
  EnableWhenSingleLinkedItem
34
- } from '../../interfaces';
34
+ } from '../../interfaces/enableWhen.interface';
35
35
  import type { AnswerExpression } from '../../interfaces/answerExpression.interface';
36
36
  import type { ValueSetPromise } from '../../interfaces/valueSet.interface';
37
37
  import { getTerminologyServerUrl, getValueSetPromise } from '../valueSet';
@@ -21,7 +21,7 @@ import type {
21
21
  QuestionnaireResponse,
22
22
  QuestionnaireResponseItem
23
23
  } from 'fhir/r4';
24
- import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces';
24
+ import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces/enableWhen.interface';
25
25
  import { isHiddenByEnableWhen } from './qItem';
26
26
 
27
27
  interface removeEmptyAnswersParams {
@@ -7,6 +7,23 @@ import type {
7
7
  import type { ItemToRepopulate } from './repopulateItems';
8
8
  import { getQrItemsIndex, mapQItemsIndex } from './mapItem';
9
9
  import { isSpecificItemControl } from './itemControl';
10
+ import { questionnaireResponseStore, questionnaireStore } from '../stores';
11
+
12
+ /**
13
+ * Re-populate checked items in the re-population dialog into the current QuestionnaireResponse
14
+ *
15
+ * @author Sean Fong
16
+ */
17
+ export function repopulateResponse(checkedItemsToRepopulate: Record<string, ItemToRepopulate>) {
18
+ const sourceQuestionnaire = questionnaireStore.getState().sourceQuestionnaire;
19
+ const updatableResponse = questionnaireResponseStore.getState().updatableResponse;
20
+
21
+ return repopulateItemsIntoResponse(
22
+ sourceQuestionnaire,
23
+ updatableResponse,
24
+ checkedItemsToRepopulate
25
+ );
26
+ }
10
27
 
11
28
  export function repopulateItemsIntoResponse(
12
29
  questionnaire: Questionnaire,
@@ -26,9 +26,22 @@ import _isEqual from 'lodash/isEqual';
26
26
  import { containsTabs, isTabContainer } from './tabs';
27
27
  import { getShortText, isSpecificItemControl } from './itemControl';
28
28
  import { getQrItemsIndex, mapQItemsIndex } from './mapItem';
29
- import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces';
29
+ import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces/enableWhen.interface';
30
30
  import { isHiddenByEnableWhen } from './qItem';
31
+ import { questionnaireResponseStore, questionnaireStore } from '../stores';
31
32
 
33
+ /**
34
+ * ItemToRepopulate interface
35
+ *
36
+ * @property qItem - The QuestionnaireItem to repopulate
37
+ * @property heading - The heading of the group to repopulate
38
+ * @property newQRItem - The new QuestionnaireResponseItem to replace the old one
39
+ * @property oldQRItem - The old QuestionnaireResponseItem to be replaced
40
+ * @property newQRItems - The new QuestionnaireResponseItems to replace the old ones
41
+ * @property oldQRItems - The old QuestionnaireResponseItems to be replaced
42
+ *
43
+ * @author Sean Fong
44
+ */
32
45
  export interface ItemToRepopulate {
33
46
  qItem: QuestionnaireItem | null;
34
47
  heading: string | null;
@@ -52,6 +65,30 @@ interface getItemsToRepopulateParams {
52
65
  enableWhenExpressions: EnableWhenExpressions;
53
66
  }
54
67
 
68
+ /**
69
+ * Compare latest data from the server with the current QuestionnaireResponse and decide items to re-populate
70
+ *
71
+ * @author Sean Fong
72
+ */
73
+ export function generateItemsToRepopulate(populatedResponse: QuestionnaireResponse) {
74
+ const sourceQuestionnaire = questionnaireStore.getState().sourceQuestionnaire;
75
+ const tabs = questionnaireStore.getState().tabs;
76
+ const updatableResponse = questionnaireResponseStore.getState().updatableResponse;
77
+ const enableWhenIsActivated = questionnaireStore.getState().enableWhenIsActivated;
78
+ const enableWhenItems = questionnaireStore.getState().enableWhenItems;
79
+ const enableWhenExpressions = questionnaireStore.getState().enableWhenExpressions;
80
+
81
+ return getItemsToRepopulate({
82
+ sourceQuestionnaire,
83
+ tabs,
84
+ populatedResponse,
85
+ updatableResponse,
86
+ enableWhenIsActivated,
87
+ enableWhenItems,
88
+ enableWhenExpressions
89
+ });
90
+ }
91
+
55
92
  export function getItemsToRepopulate(
56
93
  params: getItemsToRepopulateParams
57
94
  ): Record<string, ItemToRepopulate> {
package/src/utils/tabs.ts CHANGED
@@ -16,7 +16,7 @@
16
16
  */
17
17
 
18
18
  import type { Tabs } from '../interfaces/tab.interface';
19
- import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces';
19
+ import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces/enableWhen.interface';
20
20
  import type { Coding, QuestionnaireItem } from 'fhir/r4';
21
21
  import { isSpecificItemControl } from './itemControl';
22
22
  import { isHiddenByEnableWhen } from './qItem';
@@ -106,7 +106,7 @@ export function isTab(item: QuestionnaireItem) {
106
106
  }
107
107
 
108
108
  /**
109
- * Create a <linkId, {isComplete: boolean}> key-value pair for all tabbed items in a qItem array
109
+ * Create a `Record<linkId, {isComplete: boolean}>` key-value pair for all tabbed items in a qItem array
110
110
  *
111
111
  * @author Sean Fong
112
112
  */
@@ -25,7 +25,7 @@ import type {
25
25
  QuestionnaireResponseItemAnswer
26
26
  } from 'fhir/r4';
27
27
  import { getQrItemsIndex, mapQItemsIndex } from './mapItem';
28
- import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces';
28
+ import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces/enableWhen.interface';
29
29
  import { isHiddenByEnableWhen } from './qItem';
30
30
  import {
31
31
  getDecimalPrecision,
@@ -39,6 +39,7 @@ import { structuredDataCapture } from 'fhir-sdc-helpers';
39
39
  import type { RegexValidation } from '../interfaces/regex.interface';
40
40
  import { parseDecimalStringToFloat } from './parseInputs';
41
41
  import dayjs from 'dayjs';
42
+ import { questionnaireStore } from '../stores';
42
43
 
43
44
  export enum ValidationResult {
44
45
  unknown = 'unknown', // Unknown validation result
@@ -85,9 +86,6 @@ export enum ValidationResult {
85
86
  interface ValidateQuestionnaireParams {
86
87
  questionnaire: Questionnaire;
87
88
  questionnaireResponse: QuestionnaireResponse;
88
- enableWhenIsActivated: boolean;
89
- enableWhenItems: EnableWhenItems;
90
- enableWhenExpressions: EnableWhenExpressions;
91
89
  }
92
90
 
93
91
  /**
@@ -99,23 +97,20 @@ interface ValidateQuestionnaireParams {
99
97
  export function validateQuestionnaire(
100
98
  params: ValidateQuestionnaireParams
101
99
  ): Record<string, OperationOutcome> {
102
- const {
103
- questionnaire,
104
- questionnaireResponse,
105
- enableWhenIsActivated,
106
- enableWhenItems,
107
- enableWhenExpressions
108
- } = params;
100
+ const { questionnaire, questionnaireResponse } = params;
109
101
 
110
- if (
111
- !questionnaire.item ||
112
- questionnaire.item.length === 0 ||
113
- !questionnaireResponse.item ||
114
- questionnaireResponse.item.length === 0
115
- ) {
102
+ const enableWhenIsActivated = questionnaireStore.getState().enableWhenIsActivated;
103
+ const enableWhenItems = questionnaireStore.getState().enableWhenItems;
104
+ const enableWhenExpressions = questionnaireStore.getState().enableWhenExpressions;
105
+
106
+ if (!questionnaire.item || questionnaire.item.length === 0) {
116
107
  return {};
117
108
  }
118
109
 
110
+ if (!questionnaireResponse.item || questionnaireResponse.item.length === 0) {
111
+ questionnaireResponse.item = [];
112
+ }
113
+
119
114
  const qItemsIndexMap = mapQItemsIndex(questionnaire);
120
115
  const topLevelQRItemsByIndex = getQrItemsIndex(
121
116
  questionnaire.item,
package/vite.config.ts CHANGED
@@ -26,7 +26,7 @@ export default defineConfig({
26
26
  },
27
27
  build: {
28
28
  commonjsOptions: {
29
- include: [/node_modules/, '@aehrc/sdc-populate']
29
+ include: ['@aehrc/sdc-populate']
30
30
  }
31
31
  },
32
32
  resolve: { preserveSymlinks: true }
@@ -1,114 +0,0 @@
1
- /*
2
- * Copyright 2024 Commonwealth Scientific and Industrial Research
3
- * Organisation (CSIRO) ABN 41 687 119 230.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
-
18
- import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
19
- import { useLayoutEffect, useState } from 'react';
20
- import { initialiseQuestionnaireResponse } from '../utils';
21
- import type Client from 'fhirclient/lib/Client';
22
- import { readEncounter, readPatient, readUser } from '../api/smartClient';
23
- import {
24
- useQuestionnaireResponseStore,
25
- useQuestionnaireStore,
26
- useSmartConfigStore,
27
- useTerminologyServerStore
28
- } from '../stores';
29
-
30
- function useInitialiseRenderer(
31
- questionnaire: Questionnaire,
32
- questionnaireResponse?: QuestionnaireResponse,
33
- additionalVariables?: Record<string, object>,
34
- terminologyServerUrl?: string,
35
- fhirClient?: Client,
36
- readOnly?: boolean
37
- ): boolean {
38
- const buildSourceQuestionnaire = useQuestionnaireStore.use.buildSourceQuestionnaire();
39
- const updatePopulatedProperties = useQuestionnaireStore.use.updatePopulatedProperties();
40
- const buildSourceResponse = useQuestionnaireResponseStore.use.buildSourceResponse();
41
- const setUpdatableResponseAsPopulated =
42
- useQuestionnaireResponseStore.use.setUpdatableResponseAsPopulated();
43
-
44
- const setTerminologyServerUrl = useTerminologyServerStore.use.setUrl();
45
- const resetTerminologyServerUrl = useTerminologyServerStore.use.resetUrl();
46
- const setSmartClient = useSmartConfigStore.use.setClient();
47
- const setPatient = useSmartConfigStore.use.setPatient();
48
- const setUser = useSmartConfigStore.use.setUser();
49
- const setEncounter = useSmartConfigStore.use.setEncounter();
50
-
51
- const [loading, setLoading] = useState(true);
52
-
53
- useLayoutEffect(() => {
54
- setLoading(true);
55
- // set fhirClient if provided
56
- if (fhirClient) {
57
- setSmartClient(fhirClient);
58
- readPatient(fhirClient).then((patient) => {
59
- setPatient(patient);
60
- });
61
- readUser(fhirClient).then((user) => {
62
- setUser(user);
63
- });
64
- readEncounter(fhirClient).then((encounter) => {
65
- setEncounter(encounter);
66
- });
67
- }
68
-
69
- // set terminology server url if provided, otherwise reset it back to ontoserver
70
- if (terminologyServerUrl) {
71
- setTerminologyServerUrl(terminologyServerUrl);
72
- } else {
73
- resetTerminologyServerUrl();
74
- }
75
-
76
- // initialise form including enableWhen, enableWhenExpressions, calculatedExpressions, initialExpressions, answerExpressions, cache answerValueSets
77
- buildSourceQuestionnaire(
78
- questionnaire,
79
- questionnaireResponse,
80
- additionalVariables,
81
- terminologyServerUrl,
82
- readOnly
83
- ).then(() => {
84
- buildSourceResponse(initialiseQuestionnaireResponse(questionnaire));
85
-
86
- if (questionnaireResponse) {
87
- const updatedResponse = updatePopulatedProperties(questionnaireResponse);
88
- setUpdatableResponseAsPopulated(updatedResponse);
89
- }
90
- setLoading(false);
91
- });
92
- }, [
93
- questionnaire,
94
- questionnaireResponse,
95
- buildSourceQuestionnaire,
96
- buildSourceResponse,
97
- setUpdatableResponseAsPopulated,
98
- updatePopulatedProperties,
99
- additionalVariables,
100
- fhirClient,
101
- setSmartClient,
102
- setPatient,
103
- setUser,
104
- setEncounter,
105
- terminologyServerUrl,
106
- setTerminologyServerUrl,
107
- resetTerminologyServerUrl,
108
- readOnly
109
- ]);
110
-
111
- return loading;
112
- }
113
-
114
- export default useInitialiseRenderer;