@aehrc/smart-forms-renderer 0.36.1 → 0.37.2

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 (113) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/lib/components/FormComponents/Button.styles.d.ts +4 -0
  3. package/lib/components/FormComponents/Button.styles.js +10 -0
  4. package/lib/components/FormComponents/Button.styles.js.map +1 -0
  5. package/lib/components/FormComponents/GroupItem/GroupHeading.d.ts +1 -0
  6. package/lib/components/FormComponents/GroupItem/GroupHeading.js +3 -2
  7. package/lib/components/FormComponents/GroupItem/GroupHeading.js.map +1 -1
  8. package/lib/components/FormComponents/GroupItem/GroupItem.d.ts +4 -0
  9. package/lib/components/FormComponents/GroupItem/GroupItem.js +3 -3
  10. package/lib/components/FormComponents/GroupItem/GroupItem.js.map +1 -1
  11. package/lib/components/FormComponents/GroupItem/GroupItemView.d.ts +4 -0
  12. package/lib/components/FormComponents/GroupItem/GroupItemView.js +8 -5
  13. package/lib/components/FormComponents/GroupItem/GroupItemView.js.map +1 -1
  14. package/lib/components/FormComponents/GroupItem/NextPageButton.d.ts +7 -0
  15. package/lib/{hooks/useQueryClient.js → components/FormComponents/GroupItem/NextPageButton.js} +9 -12
  16. package/lib/components/FormComponents/GroupItem/NextPageButton.js.map +1 -0
  17. package/lib/components/FormComponents/GroupItem/PageButtonWrapper.d.ts +8 -0
  18. package/lib/components/FormComponents/GroupItem/PageButtonWrapper.js +46 -0
  19. package/lib/components/FormComponents/GroupItem/PageButtonWrapper.js.map +1 -0
  20. package/lib/components/FormComponents/GroupItem/PreviousPageButton.d.ts +7 -0
  21. package/lib/components/FormComponents/GroupItem/PreviousPageButton.js +26 -0
  22. package/lib/components/FormComponents/GroupItem/PreviousPageButton.js.map +1 -0
  23. package/lib/components/Renderer/BaseRenderer.js +8 -0
  24. package/lib/components/Renderer/BaseRenderer.js.map +1 -1
  25. package/lib/components/Renderer/FormBodyPage.d.ts +9 -0
  26. package/lib/components/Renderer/FormBodyPage.js +43 -0
  27. package/lib/components/Renderer/FormBodyPage.js.map +1 -0
  28. package/lib/components/Renderer/FormTopLevelItem.js +7 -0
  29. package/lib/components/Renderer/FormTopLevelItem.js.map +1 -1
  30. package/lib/components/Renderer/FormTopLevelPage.d.ts +9 -0
  31. package/lib/components/Renderer/FormTopLevelPage.js +29 -0
  32. package/lib/components/Renderer/FormTopLevelPage.js.map +1 -0
  33. package/lib/hooks/useNextAndPreviousVisiblePages.d.ts +7 -0
  34. package/lib/hooks/useNextAndPreviousVisiblePages.js +47 -0
  35. package/lib/hooks/useNextAndPreviousVisiblePages.js.map +1 -0
  36. package/lib/interfaces/page.interface.d.ts +16 -0
  37. package/lib/interfaces/page.interface.js +2 -0
  38. package/lib/interfaces/page.interface.js.map +1 -0
  39. package/lib/interfaces/questionnaireStore.interface.d.ts +2 -0
  40. package/lib/stores/questionnaireStore.d.ts +13 -0
  41. package/lib/stores/questionnaireStore.js +19 -3
  42. package/lib/stores/questionnaireStore.js.map +1 -1
  43. package/lib/utils/initialise.d.ts +3 -0
  44. package/lib/utils/initialise.js +6 -1
  45. package/lib/utils/initialise.js.map +1 -1
  46. package/lib/utils/page.d.ts +43 -0
  47. package/lib/utils/page.js +101 -0
  48. package/lib/utils/page.js.map +1 -0
  49. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js +4 -0
  50. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js.map +1 -1
  51. package/lib/utils/questionnaireStoreUtils/extractPages.d.ts +3 -0
  52. package/lib/utils/questionnaireStoreUtils/extractPages.js +18 -0
  53. package/lib/utils/questionnaireStoreUtils/extractPages.js.map +1 -0
  54. package/package.json +4 -4
  55. package/src/components/FormComponents/Button.styles.ts +10 -0
  56. package/src/components/FormComponents/GroupItem/GroupHeading.tsx +5 -3
  57. package/src/components/FormComponents/GroupItem/GroupItem.tsx +11 -1
  58. package/src/components/FormComponents/GroupItem/GroupItemView.tsx +12 -0
  59. package/src/components/FormComponents/GroupItem/NextPageButton.tsx +37 -0
  60. package/src/components/FormComponents/GroupItem/PageButtonWrapper.tsx +78 -0
  61. package/src/components/FormComponents/GroupItem/PreviousPageButton.tsx +41 -0
  62. package/src/components/Renderer/BaseRenderer.tsx +21 -0
  63. package/src/components/Renderer/FormBodyPage.tsx +93 -0
  64. package/src/components/Renderer/FormTopLevelItem.tsx +17 -0
  65. package/src/components/Renderer/FormTopLevelPage.tsx +70 -0
  66. package/src/hooks/useNextAndPreviousVisiblePages.ts +69 -0
  67. package/src/interfaces/page.interface.ts +13 -0
  68. package/src/interfaces/questionnaireStore.interface.ts +2 -0
  69. package/src/stores/questionnaireStore.ts +33 -2
  70. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreAllergyIntolerance.json +1 -1
  71. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreCondition.json +1 -1
  72. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreEncounter.json +137 -58
  73. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreImmunization.json +175 -0
  74. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreMedicationRequest.json +229 -0
  75. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationBP.json +359 -0
  76. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationBodyHeight.json +195 -0
  77. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationBodyWeight.json +195 -0
  78. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationHeartRate.json +195 -0
  79. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationSmokingStatus.json +174 -0
  80. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCorePatient.json +495 -0
  81. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCorePractitioner.json +139 -0
  82. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCorePractitionerRole.json +216 -0
  83. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreProcedure.json +199 -0
  84. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreRespirationRate.json +195 -0
  85. package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreWaistCircumference.json +195 -0
  86. package/src/stories/assets/questionnaires/QAuCoreTesting.ts +3342 -1
  87. package/src/stories/assets/questionnaires/QItemControlGroup.ts +673 -0
  88. package/src/stories/sdc/ItemControlGroup.stories.tsx +22 -1
  89. package/src/stories/testing/AuCoreTester.stories.tsx +140 -1
  90. package/src/utils/initialise.ts +11 -0
  91. package/src/utils/page.ts +134 -0
  92. package/src/utils/questionnaireStoreUtils/createQuestionaireModel.ts +5 -0
  93. package/src/utils/questionnaireStoreUtils/extractPages.ts +24 -0
  94. package/lib/components/FormComponents/DateTimeItem/DateTimeField.d.ts +0 -12
  95. package/lib/components/FormComponents/DateTimeItem/DateTimeField.js +0 -34
  96. package/lib/components/FormComponents/DateTimeItem/DateTimeField.js.map +0 -1
  97. package/lib/components/FormComponents/DateTimeItem/DateTimeItem.d.ts +0 -9
  98. package/lib/components/FormComponents/DateTimeItem/DateTimeItem.js +0 -60
  99. package/lib/components/FormComponents/DateTimeItem/DateTimeItem.js.map +0 -1
  100. package/lib/hooks/useDisplayCalculatedExpression.d.ts +0 -3
  101. package/lib/hooks/useDisplayCalculatedExpression.js +0 -40
  102. package/lib/hooks/useDisplayCalculatedExpression.js.map +0 -1
  103. package/lib/hooks/useInitialiseRenderer.d.ts +0 -4
  104. package/lib/hooks/useInitialiseRenderer.js +0 -85
  105. package/lib/hooks/useInitialiseRenderer.js.map +0 -1
  106. package/lib/hooks/useQueryClient.d.ts +0 -3
  107. package/lib/hooks/useQueryClient.js.map +0 -1
  108. package/lib/utils/buildForm.d.ts +0 -8
  109. package/lib/utils/buildForm.js +0 -26
  110. package/lib/utils/buildForm.js.map +0 -1
  111. package/stats.html +0 -4842
  112. package/stats1.html +0 -4842
  113. package/stats3.html +0 -4842
@@ -22,7 +22,21 @@ import { patSmartForm } from '../assets/patients/PatSmartForm';
22
22
  import { pracPrimaryPeter } from '../assets/practitioners/PracPrimaryPeter';
23
23
  import {
24
24
  QAuCoreAllergyIntolerance,
25
- QAuCoreCondition
25
+ QAuCoreCondition,
26
+ QAuCoreEncounter,
27
+ QAuCoreImmunization,
28
+ QAuCoreMedicationRequest,
29
+ QAuCoreObservationBodyHeight,
30
+ QAuCoreObservationBodyWeight,
31
+ QAuCoreObservationBP,
32
+ QAuCoreObservationHeartRate,
33
+ QAuCoreObservationRespirationRate,
34
+ QAuCoreObservationSmokingStatus,
35
+ QAuCoreObservationWaistCircumference,
36
+ QAuCorePatient,
37
+ QAuCorePractitioner,
38
+ QAuCorePractitionerRole,
39
+ QAuCoreProcedure
26
40
  } from '../assets/questionnaires/QAuCoreTesting';
27
41
 
28
42
  // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
@@ -55,3 +69,128 @@ export const AuCoreCondition: Story = {
55
69
  user: pracPrimaryPeter
56
70
  }
57
71
  };
72
+
73
+ export const AuCoreEncounter: Story = {
74
+ args: {
75
+ questionnaire: QAuCoreEncounter,
76
+ fhirClient: mockFhirClient,
77
+ patient: patSmartForm,
78
+ user: pracPrimaryPeter
79
+ }
80
+ };
81
+
82
+ export const AuCoreImmunization: Story = {
83
+ args: {
84
+ questionnaire: QAuCoreImmunization,
85
+ fhirClient: mockFhirClient,
86
+ patient: patSmartForm,
87
+ user: pracPrimaryPeter
88
+ }
89
+ };
90
+
91
+ export const AuCoreMedicationRequest: Story = {
92
+ args: {
93
+ questionnaire: QAuCoreMedicationRequest,
94
+ fhirClient: mockFhirClient,
95
+ patient: patSmartForm,
96
+ user: pracPrimaryPeter
97
+ }
98
+ };
99
+
100
+ export const AuCorePatient: Story = {
101
+ args: {
102
+ questionnaire: QAuCorePatient,
103
+ fhirClient: mockFhirClient,
104
+ patient: patSmartForm,
105
+ user: pracPrimaryPeter
106
+ }
107
+ };
108
+
109
+ export const AuCorePractitioner: Story = {
110
+ args: {
111
+ questionnaire: QAuCorePractitioner,
112
+ fhirClient: mockFhirClient,
113
+ patient: patSmartForm,
114
+ user: pracPrimaryPeter
115
+ }
116
+ };
117
+
118
+ export const AuCorePractitionerRole: Story = {
119
+ args: {
120
+ questionnaire: QAuCorePractitionerRole,
121
+ fhirClient: mockFhirClient,
122
+ patient: patSmartForm,
123
+ user: pracPrimaryPeter
124
+ }
125
+ };
126
+
127
+ export const AuCoreProcedure: Story = {
128
+ args: {
129
+ questionnaire: QAuCoreProcedure,
130
+ fhirClient: mockFhirClient,
131
+ patient: patSmartForm,
132
+ user: pracPrimaryPeter
133
+ }
134
+ };
135
+
136
+ export const AuCoreObservationBP: Story = {
137
+ args: {
138
+ questionnaire: QAuCoreObservationBP,
139
+ fhirClient: mockFhirClient,
140
+ patient: patSmartForm,
141
+ user: pracPrimaryPeter
142
+ }
143
+ };
144
+
145
+ export const AuCoreObservationBodyHeight: Story = {
146
+ args: {
147
+ questionnaire: QAuCoreObservationBodyHeight,
148
+ fhirClient: mockFhirClient,
149
+ patient: patSmartForm,
150
+ user: pracPrimaryPeter
151
+ }
152
+ };
153
+
154
+ export const AuCoreObservationBodyWeight: Story = {
155
+ args: {
156
+ questionnaire: QAuCoreObservationBodyWeight,
157
+ fhirClient: mockFhirClient,
158
+ patient: patSmartForm,
159
+ user: pracPrimaryPeter
160
+ }
161
+ };
162
+
163
+ export const AuCoreObservationHeartRate: Story = {
164
+ args: {
165
+ questionnaire: QAuCoreObservationHeartRate,
166
+ fhirClient: mockFhirClient,
167
+ patient: patSmartForm,
168
+ user: pracPrimaryPeter
169
+ }
170
+ };
171
+ export const AuCoreObservationRespirationRate: Story = {
172
+ args: {
173
+ questionnaire: QAuCoreObservationRespirationRate,
174
+ fhirClient: mockFhirClient,
175
+ patient: patSmartForm,
176
+ user: pracPrimaryPeter
177
+ }
178
+ };
179
+
180
+ export const AuCoreObservationSmokingStatus: Story = {
181
+ args: {
182
+ questionnaire: QAuCoreObservationSmokingStatus,
183
+ fhirClient: mockFhirClient,
184
+ patient: patSmartForm,
185
+ user: pracPrimaryPeter
186
+ }
187
+ };
188
+
189
+ export const AuCoreObservationWaistCircumference: Story = {
190
+ args: {
191
+ questionnaire: QAuCoreObservationWaistCircumference,
192
+ fhirClient: mockFhirClient,
193
+ patient: patSmartForm,
194
+ user: pracPrimaryPeter
195
+ }
196
+ };
@@ -17,6 +17,7 @@
17
17
 
18
18
  import { evaluateInitialEnableWhenExpressions } from './enableWhenExpression';
19
19
  import { getFirstVisibleTab } from './tabs';
20
+ import { getFirstVisiblePage } from './page';
20
21
  import type {
21
22
  Expression,
22
23
  Questionnaire,
@@ -28,6 +29,7 @@ import type {
28
29
  } from 'fhir/r4';
29
30
  import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces/enableWhen.interface';
30
31
  import type { Tabs } from '../interfaces/tab.interface';
32
+ import type { Pages } from '../interfaces/page.interface';
31
33
  import { assignPopulatedAnswersToEnableWhen } from './enableWhen';
32
34
  import type { CalculatedExpression } from '../interfaces/calculatedExpression.interface';
33
35
  import { evaluateInitialCalculatedExpressions } from './calculatedExpression';
@@ -320,6 +322,7 @@ export interface initialFormFromResponseParams {
320
322
  calculatedExpressions: Record<string, CalculatedExpression[]>;
321
323
  variablesFhirPath: Record<string, Expression[]>;
322
324
  tabs: Tabs;
325
+ pages: Pages;
323
326
  fhirPathContext: Record<string, any>;
324
327
  }
325
328
 
@@ -329,6 +332,7 @@ export function initialiseFormFromResponse(params: initialFormFromResponseParams
329
332
  initialEnableWhenExpressions: EnableWhenExpressions;
330
333
  initialCalculatedExpressions: Record<string, CalculatedExpression[]>;
331
334
  firstVisibleTab: number;
335
+ firstVisiblePage: number;
332
336
  updatedFhirPathContext: Record<string, any>;
333
337
  } {
334
338
  const {
@@ -338,6 +342,7 @@ export function initialiseFormFromResponse(params: initialFormFromResponseParams
338
342
  calculatedExpressions,
339
343
  variablesFhirPath,
340
344
  tabs,
345
+ pages,
341
346
  fhirPathContext
342
347
  } = params;
343
348
  const initialResponseItemMap = createQuestionnaireResponseItemMap(questionnaireResponse);
@@ -373,12 +378,18 @@ export function initialiseFormFromResponse(params: initialFormFromResponseParams
373
378
  ? getFirstVisibleTab(tabs, initialisedItems, initialEnableWhenExpressions)
374
379
  : 0;
375
380
 
381
+ const firstVisiblePage =
382
+ Object.keys(pages).length > 0
383
+ ? getFirstVisiblePage(pages, initialisedItems, initialEnableWhenExpressions)
384
+ : 0;
385
+
376
386
  return {
377
387
  initialEnableWhenItems: initialisedItems,
378
388
  initialEnableWhenLinkedQuestions: linkedQuestions,
379
389
  initialEnableWhenExpressions,
380
390
  initialCalculatedExpressions,
381
391
  firstVisibleTab,
392
+ firstVisiblePage,
382
393
  updatedFhirPathContext
383
394
  };
384
395
  }
@@ -0,0 +1,134 @@
1
+ import type { Pages } from '../interfaces/page.interface';
2
+ import type { EnableWhenExpressions, EnableWhenItems } from '../interfaces/enableWhen.interface';
3
+ import type { QuestionnaireItem } from 'fhir/r4';
4
+ import { isSpecificItemControl } from './itemControl';
5
+ import { isHiddenByEnableWhen } from './qItem';
6
+ import { structuredDataCapture } from 'fhir-sdc-helpers';
7
+
8
+ export function getFirstVisiblePage(
9
+ pages: Pages,
10
+ enableWhenItems: EnableWhenItems,
11
+ enableWhenExpressions: EnableWhenExpressions
12
+ ) {
13
+ // Only singleEnableWhenItems are relevant for page operations
14
+ const { singleItems } = enableWhenItems;
15
+ const { singleExpressions } = enableWhenExpressions;
16
+
17
+ return Object.entries(pages)
18
+ .sort(([, pageA], [, pageB]) => pageA.pageIndex - pageB.pageIndex)
19
+ .findIndex(([pageLinkId, page]) => {
20
+ if (page.isHidden) {
21
+ return false;
22
+ }
23
+
24
+ const singleItem = singleItems[pageLinkId];
25
+ if (singleItem) {
26
+ return singleItem.isEnabled;
27
+ }
28
+
29
+ const singleExpression = singleExpressions[pageLinkId];
30
+ if (singleExpression) {
31
+ return singleExpression.isEnabled;
32
+ }
33
+
34
+ return true;
35
+ });
36
+ }
37
+
38
+ /**
39
+ * Checks if all of the items in a qItem array is a page item
40
+ * Returns true if all items is page item
41
+ * Returns false if only have one item
42
+ *
43
+ * @author Riza Nafis
44
+ */
45
+ export function everyIsPages(topLevelQItem: QuestionnaireItem[] | undefined): boolean {
46
+ if (!topLevelQItem) return false;
47
+
48
+ if (isPageContainer(topLevelQItem)) return false;
49
+
50
+ return topLevelQItem.every((i: QuestionnaireItem) => isPage(i));
51
+ }
52
+
53
+ export function isPageContainer(topLevelQItem: QuestionnaireItem[] | undefined): boolean {
54
+ const anyPage = topLevelQItem?.filter(isPage);
55
+
56
+ if (!anyPage) return false;
57
+
58
+ return anyPage.some((page) => page.item?.every((i) => i.type === 'group') || false);
59
+ }
60
+
61
+ /**
62
+ * Checks if any of the items in a qItem array is a page item
63
+ * Returns true if there is at least one page item
64
+ *
65
+ * @author Riza Nafis
66
+ */
67
+ export function containsPages(topLevelQItem: QuestionnaireItem): boolean {
68
+ if (!topLevelQItem.item) {
69
+ return false;
70
+ }
71
+
72
+ const pages = topLevelQItem.item.filter((i) => isPage(i));
73
+ return pages.length > 0;
74
+ }
75
+
76
+ /**
77
+ * Check if a qItem is a page item
78
+ *
79
+ * @author Riza Nafis
80
+ */
81
+ export function isPage(item: QuestionnaireItem) {
82
+ return isSpecificItemControl(item, 'page');
83
+ }
84
+
85
+ /**
86
+ * Create a `Record<linkId, Pages>` key-value pair for all page items in a qItem array
87
+ *
88
+ * @author Riza Nafis
89
+ */
90
+ export function constructPagesWithProperties(
91
+ qItems: QuestionnaireItem[] | undefined,
92
+ hasPageContainer: boolean
93
+ ): Pages {
94
+ if (!qItems) return {};
95
+
96
+ const qItemPages = hasPageContainer ? qItems : qItems.filter(isPage);
97
+
98
+ const pages: Pages = {};
99
+ for (const [i, qItem] of qItemPages.entries()) {
100
+ pages[qItem.linkId] = {
101
+ pageIndex: i,
102
+ isComplete: false,
103
+ isHidden: structuredDataCapture.getHidden(qItem) ?? false
104
+ };
105
+ }
106
+ return pages;
107
+ }
108
+
109
+ interface contructPagesWithVisibilityParams {
110
+ pages: Pages;
111
+ enableWhenIsActivated: boolean;
112
+ enableWhenItems: EnableWhenItems;
113
+ enableWhenExpressions: EnableWhenExpressions;
114
+ }
115
+
116
+ export function constructPagesWithVisibility(
117
+ params: contructPagesWithVisibilityParams
118
+ ): { linkId: string; isVisible: boolean }[] {
119
+ const { pages, enableWhenIsActivated, enableWhenItems, enableWhenExpressions } = params;
120
+
121
+ return Object.entries(pages).map(([linkId]) => {
122
+ const isVisible = !isHiddenByEnableWhen({
123
+ linkId,
124
+ enableWhenIsActivated,
125
+ enableWhenItems,
126
+ enableWhenExpressions
127
+ });
128
+
129
+ return {
130
+ linkId,
131
+ isVisible
132
+ };
133
+ });
134
+ }
@@ -17,11 +17,13 @@
17
17
 
18
18
  import type { Questionnaire } from 'fhir/r4';
19
19
  import type { Tabs } from '../../interfaces/tab.interface';
20
+ import type { Pages } from '../../interfaces/page.interface';
20
21
  import type { LaunchContext } from '../../interfaces/populate.interface';
21
22
  import type { QuestionnaireModel } from '../../interfaces/questionnaireStore.interface';
22
23
  import { extractLaunchContexts } from './extractLaunchContext';
23
24
  import { extractQuestionnaireLevelVariables } from './extractVariables';
24
25
  import { extractTabs } from './extractTabs';
26
+ import { extractPages } from './extractPages';
25
27
  import { extractContainedValueSets } from './extractContainedValueSets';
26
28
  import { extractOtherExtensions } from './extractOtherExtensions';
27
29
  import type { Variables } from '../../interfaces/variables.interface';
@@ -41,6 +43,7 @@ export async function createQuestionnaireModel(
41
43
 
42
44
  const itemTypes: Record<string, string> = Object.fromEntries(getLinkIdTypeTuples(questionnaire));
43
45
  const tabs: Tabs = extractTabs(questionnaire);
46
+ const pages: Pages = extractPages(questionnaire);
44
47
 
45
48
  const launchContexts: Record<string, LaunchContext> = extractLaunchContexts(questionnaire);
46
49
 
@@ -98,6 +101,7 @@ export async function createQuestionnaireModel(
98
101
  return {
99
102
  itemTypes,
100
103
  tabs,
104
+ pages,
101
105
  variables,
102
106
  launchContexts,
103
107
  enableWhenItems,
@@ -116,6 +120,7 @@ function createEmptyModel(): QuestionnaireModel {
116
120
  return {
117
121
  itemTypes: {},
118
122
  tabs: {},
123
+ pages: {},
119
124
  variables: { fhirPathVariables: {}, xFhirQueryVariables: {} },
120
125
  launchContexts: {},
121
126
  calculatedExpressions: {},
@@ -0,0 +1,24 @@
1
+ import type { Questionnaire } from 'fhir/r4';
2
+ import type { Pages } from '../../interfaces/page.interface';
3
+ import { constructPagesWithProperties, isPage, isPageContainer } from '../page';
4
+
5
+ export function extractPages(questionnaire: Questionnaire): Pages {
6
+ if (!questionnaire.item || questionnaire.item.length === 0) {
7
+ return {};
8
+ }
9
+
10
+ if (!isPageContainer(questionnaire.item)) {
11
+ return constructPagesWithProperties(questionnaire.item, false);
12
+ }
13
+
14
+ let totalPages = {};
15
+ for (const topLevelItem of questionnaire.item) {
16
+ const items = topLevelItem.item;
17
+ const topLevelItemIsPageContainer = isPage(topLevelItem);
18
+
19
+ const pages = constructPagesWithProperties(items, topLevelItemIsPageContainer);
20
+ totalPages = { ...totalPages, ...pages };
21
+ }
22
+
23
+ return totalPages;
24
+ }
@@ -1,12 +0,0 @@
1
- import React from 'react';
2
- import type { PropsWithIsTabledAttribute } from '../../../interfaces/renderProps.interface';
3
- import type { Dayjs } from 'dayjs';
4
- interface DateTimeFieldProps extends PropsWithIsTabledAttribute {
5
- value: Dayjs | null;
6
- displayPrompt: string;
7
- entryFormat: string;
8
- readOnly: boolean;
9
- onDateTimeChange: (newValue: Dayjs | null) => unknown;
10
- }
11
- declare function DateTimeField(props: DateTimeFieldProps): React.JSX.Element;
12
- export default DateTimeField;
@@ -1,34 +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
- import React from 'react';
18
- import { DateTimePicker as MuiDateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';
19
- import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
20
- import Box from '@mui/material/Box';
21
- import { TEXT_FIELD_WIDTH } from '../Textfield.styles';
22
- function DateTimeField(props) {
23
- const { value, displayPrompt, entryFormat, readOnly, isTabled, onDateTimeChange } = props;
24
- return (React.createElement(LocalizationProvider, { dateAdapter: AdapterDayjs },
25
- React.createElement(Box, { "data-test": "q-item-date-time-field" },
26
- React.createElement(MuiDateTimePicker, { format: entryFormat !== '' ? entryFormat : 'DD/MM/YYYY hh:mm A', value: value, disabled: readOnly, label: displayPrompt, sx: { maxWidth: !isTabled ? TEXT_FIELD_WIDTH : 3000, minWidth: 160 }, onChange: onDateTimeChange, slotProps: {
27
- textField: {
28
- size: 'small',
29
- fullWidth: true
30
- }
31
- } }))));
32
- }
33
- export default DateTimeField;
34
- //# sourceMappingURL=DateTimeField.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DateTimeField.js","sourceRoot":"","sources":["../../../../src/components/FormComponents/DateTimeItem/DateTimeField.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,GAAG,MAAM,mBAAmB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAUvD,SAAS,aAAa,CAAC,KAAyB;IAC9C,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;IAE1F,OAAO,CACL,oBAAC,oBAAoB,IAAC,WAAW,EAAE,YAAY;QAC7C,oBAAC,GAAG,iBAAW,wBAAwB;YACrC,oBAAC,iBAAiB,IAChB,MAAM,EAAE,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAoB,EAC/D,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,aAAa,EACpB,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,EACpE,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE;oBACT,SAAS,EAAE;wBACT,IAAI,EAAE,OAAO;wBACb,SAAS,EAAE,IAAI;qBAChB;iBACF,GACD,CACE,CACe,CACxB,CAAC;AACJ,CAAC;AAED,eAAe,aAAa,CAAC"}
@@ -1,9 +0,0 @@
1
- import React from 'react';
2
- import type { PropsWithIsRepeatedAttribute, PropsWithIsTabledAttribute, PropsWithParentIsReadOnlyAttribute, PropsWithQrItemChangeHandler } from '../../../interfaces/renderProps.interface';
3
- import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
4
- interface DateTimeItemProps extends PropsWithQrItemChangeHandler, PropsWithIsRepeatedAttribute, PropsWithIsTabledAttribute, PropsWithParentIsReadOnlyAttribute {
5
- qItem: QuestionnaireItem;
6
- qrItem: QuestionnaireResponseItem | null;
7
- }
8
- declare function DateTimeItem(props: DateTimeItemProps): React.JSX.Element;
9
- export default DateTimeItem;
@@ -1,60 +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
- import React from 'react';
18
- import useRenderingExtensions from '../../../hooks/useRenderingExtensions';
19
- import { createEmptyQrItem } from '../../../utils/qrItem';
20
- import { FullWidthFormComponentBox } from '../../Box.styles';
21
- import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
22
- import DateTimeField from './DateTimeField';
23
- import dayjs from 'dayjs';
24
- import useReadOnly from '../../../hooks/useReadOnly';
25
- import { useQuestionnaireStore } from '../../../stores';
26
- function DateTimeItem(props) {
27
- const { qItem, qrItem, isRepeated, isTabled, parentIsReadOnly, onQrItemChange } = props;
28
- const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
29
- const readOnly = useReadOnly(qItem, parentIsReadOnly);
30
- const { displayPrompt, entryFormat } = useRenderingExtensions(qItem);
31
- // Init input value
32
- let dateTimeString = null;
33
- if (qrItem === null || qrItem === void 0 ? void 0 : qrItem.answer) {
34
- if (qrItem === null || qrItem === void 0 ? void 0 : qrItem.answer[0].valueDate) {
35
- dateTimeString = qrItem.answer[0].valueDate;
36
- }
37
- else if (qrItem === null || qrItem === void 0 ? void 0 : qrItem.answer[0].valueDateTime) {
38
- dateTimeString = qrItem.answer[0].valueDateTime;
39
- }
40
- }
41
- const dateTimeDayJs = dateTimeString ? dayjs(dateTimeString) : null;
42
- // Event handlers
43
- function handleDateTimeChange(newValue) {
44
- const emptyQrItem = createEmptyQrItem(qItem);
45
- if (newValue) {
46
- onQrItemChange(Object.assign(Object.assign({}, emptyQrItem), { answer: [{ valueDateTime: newValue.format() }] }));
47
- }
48
- else {
49
- onQrItemChange(emptyQrItem);
50
- }
51
- }
52
- if (isRepeated) {
53
- return (React.createElement(DateTimeField, { value: dateTimeDayJs, displayPrompt: displayPrompt, entryFormat: entryFormat, readOnly: readOnly, onDateTimeChange: handleDateTimeChange, isTabled: isTabled }));
54
- }
55
- return (React.createElement(FullWidthFormComponentBox, { "data-test": "q-item-date-time-box", "data-linkid": qItem.linkId, onClick: () => onFocusLinkId(qItem.linkId) },
56
- React.createElement(ItemFieldGrid, { qItem: qItem, readOnly: readOnly },
57
- React.createElement(DateTimeField, { value: dateTimeDayJs, displayPrompt: displayPrompt, entryFormat: entryFormat, readOnly: readOnly, onDateTimeChange: handleDateTimeChange, isTabled: isTabled }))));
58
- }
59
- export default DateTimeItem;
60
- //# sourceMappingURL=DateTimeItem.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DateTimeItem.js","sourceRoot":"","sources":["../../../../src/components/FormComponents/DateTimeItem/DateTimeItem.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,sBAAsB,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,aAAa,MAAM,4BAA4B,CAAC;AACvD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,WAAW,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAWxD,SAAS,YAAY,CAAC,KAAwB;IAC5C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAExF,MAAM,aAAa,GAAG,qBAAqB,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAEhE,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACtD,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAErE,mBAAmB;IACnB,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,EAAE;QAClB,IAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE;YAC/B,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;SAC7C;aAAM,IAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,CAAC,EAAE,aAAa,EAAE;YAC1C,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;SACjD;KACF;IACD,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEpE,iBAAiB;IACjB,SAAS,oBAAoB,CAAC,QAAsB;QAClD,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,QAAQ,EAAE;YACZ,cAAc,iCAAM,WAAW,KAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,IAAG,CAAC;SACpF;aAAM;YACL,cAAc,CAAC,WAAW,CAAC,CAAC;SAC7B;IACH,CAAC;IAED,IAAI,UAAU,EAAE;QACd,OAAO,CACL,oBAAC,aAAa,IACZ,KAAK,EAAE,aAAa,EACpB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,gBAAgB,EAAE,oBAAoB,EACtC,QAAQ,EAAE,QAAQ,GAClB,CACH,CAAC;KACH;IAED,OAAO,CACL,oBAAC,yBAAyB,iBACd,sBAAsB,iBACnB,KAAK,CAAC,MAAM,EACzB,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC;QAC1C,oBAAC,aAAa,IAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ;YAC7C,oBAAC,aAAa,IACZ,KAAK,EAAE,aAAa,EACpB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,gBAAgB,EAAE,oBAAoB,EACtC,QAAQ,EAAE,QAAQ,GAClB,CACY,CACU,CAC7B,CAAC;AACJ,CAAC;AAED,eAAe,YAAY,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { QuestionnaireItem } from 'fhir/r4';
2
- declare function useDisplayCalculatedExpression(qItem: QuestionnaireItem): string | null;
3
- export default useDisplayCalculatedExpression;
@@ -1,40 +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
- import { useQuestionnaireStore } from '../stores';
18
- function useDisplayCalculatedExpression(qItem) {
19
- var _a;
20
- const calculatedExpressions = useQuestionnaireStore.use.calculatedExpressions();
21
- const calcExpression = (_a = calculatedExpressions[qItem.linkId]) === null || _a === void 0 ? void 0 : _a.find((exp) => exp.from === 'item._text');
22
- if (!calcExpression) {
23
- return null;
24
- }
25
- if (typeof calcExpression.value === 'string' ||
26
- typeof calcExpression.value === 'number' ||
27
- calcExpression.value === null) {
28
- // calculatedExpression value is null
29
- if (calcExpression.value === null) {
30
- return '';
31
- }
32
- // calculatedExpression value is string or number
33
- return typeof calcExpression.value === 'string'
34
- ? calcExpression.value
35
- : calcExpression.value.toString();
36
- }
37
- return null;
38
- }
39
- export default useDisplayCalculatedExpression;
40
- //# sourceMappingURL=useDisplayCalculatedExpression.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useDisplayCalculatedExpression.js","sourceRoot":"","sources":["../../src/hooks/useDisplayCalculatedExpression.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAGlD,SAAS,8BAA8B,CAAC,KAAwB;;IAC9D,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;IAEhF,MAAM,cAAc,GAAG,MAAA,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,0CAAE,IAAI,CAC9D,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CACnC,CAAC;IAEF,IAAI,CAAC,cAAc,EAAE;QACnB,OAAO,IAAI,CAAC;KACb;IAED,IACE,OAAO,cAAc,CAAC,KAAK,KAAK,QAAQ;QACxC,OAAO,cAAc,CAAC,KAAK,KAAK,QAAQ;QACxC,cAAc,CAAC,KAAK,KAAK,IAAI,EAC7B;QACA,qCAAqC;QACrC,IAAI,cAAc,CAAC,KAAK,KAAK,IAAI,EAAE;YACjC,OAAO,EAAE,CAAC;SACX;QAED,iDAAiD;QACjD,OAAO,OAAO,cAAc,CAAC,KAAK,KAAK,QAAQ;YAC7C,CAAC,CAAC,cAAc,CAAC,KAAK;YACtB,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;KACrC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,eAAe,8BAA8B,CAAC"}
@@ -1,4 +0,0 @@
1
- import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
2
- import type Client from 'fhirclient/lib/Client';
3
- declare function useInitialiseRenderer(questionnaire: Questionnaire, questionnaireResponse?: QuestionnaireResponse, additionalVariables?: Record<string, object>, terminologyServerUrl?: string, fhirClient?: Client, readOnly?: boolean): boolean;
4
- export default useInitialiseRenderer;
@@ -1,85 +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
- import { useLayoutEffect, useState } from 'react';
18
- import { initialiseQuestionnaireResponse } from '../utils';
19
- import { readEncounter, readPatient, readUser } from '../api/smartClient';
20
- import { useQuestionnaireResponseStore, useQuestionnaireStore, useSmartConfigStore, useTerminologyServerStore } from '../stores';
21
- function useInitialiseRenderer(questionnaire, questionnaireResponse, additionalVariables, terminologyServerUrl, fhirClient, readOnly) {
22
- const buildSourceQuestionnaire = useQuestionnaireStore.use.buildSourceQuestionnaire();
23
- const updatePopulatedProperties = useQuestionnaireStore.use.updatePopulatedProperties();
24
- const buildSourceResponse = useQuestionnaireResponseStore.use.buildSourceResponse();
25
- const setUpdatableResponseAsPopulated = useQuestionnaireResponseStore.use.setUpdatableResponseAsPopulated();
26
- const setTerminologyServerUrl = useTerminologyServerStore.use.setUrl();
27
- const resetTerminologyServerUrl = useTerminologyServerStore.use.resetUrl();
28
- const setSmartClient = useSmartConfigStore.use.setClient();
29
- const setPatient = useSmartConfigStore.use.setPatient();
30
- const setUser = useSmartConfigStore.use.setUser();
31
- const setEncounter = useSmartConfigStore.use.setEncounter();
32
- const [loading, setLoading] = useState(true);
33
- useLayoutEffect(() => {
34
- setLoading(true);
35
- // set fhirClient if provided
36
- if (fhirClient) {
37
- setSmartClient(fhirClient);
38
- readPatient(fhirClient).then((patient) => {
39
- setPatient(patient);
40
- });
41
- readUser(fhirClient).then((user) => {
42
- setUser(user);
43
- });
44
- readEncounter(fhirClient).then((encounter) => {
45
- setEncounter(encounter);
46
- });
47
- }
48
- // set terminology server url if provided, otherwise reset it back to ontoserver
49
- if (terminologyServerUrl) {
50
- setTerminologyServerUrl(terminologyServerUrl);
51
- }
52
- else {
53
- resetTerminologyServerUrl();
54
- }
55
- // initialise form including enableWhen, enableWhenExpressions, calculatedExpressions, initialExpressions, answerExpressions, cache answerValueSets
56
- buildSourceQuestionnaire(questionnaire, questionnaireResponse, additionalVariables, terminologyServerUrl, readOnly).then(() => {
57
- buildSourceResponse(initialiseQuestionnaireResponse(questionnaire));
58
- if (questionnaireResponse) {
59
- const updatedResponse = updatePopulatedProperties(questionnaireResponse);
60
- setUpdatableResponseAsPopulated(updatedResponse);
61
- }
62
- setLoading(false);
63
- });
64
- }, [
65
- questionnaire,
66
- questionnaireResponse,
67
- buildSourceQuestionnaire,
68
- buildSourceResponse,
69
- setUpdatableResponseAsPopulated,
70
- updatePopulatedProperties,
71
- additionalVariables,
72
- fhirClient,
73
- setSmartClient,
74
- setPatient,
75
- setUser,
76
- setEncounter,
77
- terminologyServerUrl,
78
- setTerminologyServerUrl,
79
- resetTerminologyServerUrl,
80
- readOnly
81
- ]);
82
- return loading;
83
- }
84
- export default useInitialiseRenderer;
85
- //# sourceMappingURL=useInitialiseRenderer.js.map