@aehrc/smart-forms-renderer 0.35.4 → 0.35.6

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 (38) hide show
  1. package/lib/hooks/useStringCalculatedExpression.js +1 -0
  2. package/lib/hooks/useStringCalculatedExpression.js.map +1 -1
  3. package/lib/hooks/useValueSetCodings.js +5 -0
  4. package/lib/hooks/useValueSetCodings.js.map +1 -1
  5. package/lib/interfaces/questionnaireStore.interface.d.ts +2 -1
  6. package/lib/stores/questionnaireStore.js +4 -0
  7. package/lib/stores/questionnaireStore.js.map +1 -1
  8. package/lib/utils/fhirpathAsyncUtils/fhirpath-async.d.ts +15 -0
  9. package/lib/utils/fhirpathAsyncUtils/fhirpath-async.js +433 -0
  10. package/lib/utils/fhirpathAsyncUtils/fhirpath-async.js.map +1 -0
  11. package/lib/utils/fhirpathAsyncUtils/outcome-utils.d.ts +3 -0
  12. package/lib/utils/fhirpathAsyncUtils/outcome-utils.js +42 -0
  13. package/lib/utils/fhirpathAsyncUtils/outcome-utils.js.map +1 -0
  14. package/lib/utils/fhirpathAsyncUtils/test-questionnaire.d.ts +1 -0
  15. package/lib/utils/fhirpathAsyncUtils/test-questionnaire.js +379 -0
  16. package/lib/utils/fhirpathAsyncUtils/test-questionnaire.js.map +1 -0
  17. package/lib/utils/questionnaireStoreUtils/addDisplayToCodings.d.ts +2 -1
  18. package/lib/utils/questionnaireStoreUtils/addDisplayToCodings.js +35 -0
  19. package/lib/utils/questionnaireStoreUtils/addDisplayToCodings.js.map +1 -1
  20. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js +6 -2
  21. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js.map +1 -1
  22. package/lib/utils/questionnaireStoreUtils/extractOtherExtensions.d.ts +2 -1
  23. package/lib/utils/questionnaireStoreUtils/extractOtherExtensions.js +13 -3
  24. package/lib/utils/questionnaireStoreUtils/extractOtherExtensions.js.map +1 -1
  25. package/lib/utils/questionnaireStoreUtils/insertAnswerOptions.d.ts +7 -0
  26. package/lib/utils/questionnaireStoreUtils/insertAnswerOptions.js +44 -0
  27. package/lib/utils/questionnaireStoreUtils/insertAnswerOptions.js.map +1 -0
  28. package/package.json +3 -3
  29. package/src/hooks/useStringCalculatedExpression.ts +1 -0
  30. package/src/hooks/useValueSetCodings.ts +6 -0
  31. package/src/interfaces/questionnaireStore.interface.ts +2 -1
  32. package/src/stores/questionnaireStore.ts +8 -0
  33. package/src/stories/assets/questionnaires/QPrePopTester.ts +117 -0
  34. package/src/utils/fhirpathAsyncUtils/test-questionnaire.ts +383 -0
  35. package/src/utils/questionnaireStoreUtils/addDisplayToCodings.ts +40 -1
  36. package/src/utils/questionnaireStoreUtils/createQuestionaireModel.ts +16 -3
  37. package/src/utils/questionnaireStoreUtils/extractOtherExtensions.ts +15 -0
  38. package/src/utils/questionnaireStoreUtils/insertAnswerOptions.ts +56 -0
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- import type { Coding } from 'fhir/r4';
18
+ import type { Coding, QuestionnaireItemAnswerOption } from 'fhir/r4';
19
19
  import type { CodeSystemLookupPromise } from '../../interfaces/lookup.interface';
20
20
  import * as FHIR from 'fhirclient';
21
21
 
@@ -56,6 +56,45 @@ export async function addDisplayToProcessedCodings(
56
56
  return processedCodings;
57
57
  }
58
58
 
59
+ // Use this for a Record<linkId, answerOption[]>
60
+ export async function addDisplayToAnswerOptions(
61
+ answerOptions: Record<string, QuestionnaireItemAnswerOption[]>,
62
+ terminologyServerUrl: string
63
+ ): Promise<Record<string, QuestionnaireItemAnswerOption[]>> {
64
+ // Store code system lookup promises for codings without displays
65
+ const codeSystemLookupPromises: Record<string, CodeSystemLookupPromise> = {};
66
+ for (const key in answerOptions) {
67
+ const options = answerOptions[key];
68
+ for (const option of options) {
69
+ if (option.valueCoding && !option.valueCoding.display) {
70
+ const query = `system=${option.valueCoding.system}&code=${option.valueCoding.code}`;
71
+ codeSystemLookupPromises[query] = {
72
+ promise: getCodeSystemLookupPromise(query, terminologyServerUrl),
73
+ oldCoding: option.valueCoding
74
+ };
75
+ }
76
+ }
77
+ }
78
+
79
+ // Resolves lookup promises in one go and assign newCodings to processedCodings
80
+ const resolvedCodeSystemLookupPromises = await resolveLookupPromises(codeSystemLookupPromises);
81
+ for (const key in answerOptions) {
82
+ const options = answerOptions[key];
83
+
84
+ for (const option of options) {
85
+ if (option.valueCoding) {
86
+ const lookUpKey = `system=${option.valueCoding.system}&code=${option.valueCoding.code}`;
87
+ const resolvedLookup = resolvedCodeSystemLookupPromises[lookUpKey];
88
+ if (resolvedLookup?.newCoding?.display) {
89
+ option.valueCoding.display = resolvedLookup.newCoding.display;
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ return answerOptions;
96
+ }
97
+
59
98
  // Use this for an array of codings
60
99
  export async function addDisplayToCodingArray(
61
100
  codings: Coding[],
@@ -28,7 +28,7 @@ import type { Variables } from '../../interfaces/variables.interface';
28
28
  import { resolveValueSets } from './resolveValueSets';
29
29
  import { addAdditionalVariables } from './addAdditionalVariables';
30
30
  import { getLinkIdTypeTuples } from '../qItem';
31
- import { addDisplayToProcessedCodings } from './addDisplayToCodings';
31
+ import { addDisplayToAnswerOptions, addDisplayToProcessedCodings } from './addDisplayToCodings';
32
32
 
33
33
  export async function createQuestionnaireModel(
34
34
  questionnaire: Questionnaire,
@@ -62,8 +62,13 @@ export async function createQuestionnaireModel(
62
62
  terminologyServerUrl
63
63
  );
64
64
 
65
- const { enableWhenItems, enableWhenExpressions, calculatedExpressions, answerExpressions } =
66
- extractOtherExtensionsResult;
65
+ const {
66
+ enableWhenItems,
67
+ enableWhenExpressions,
68
+ calculatedExpressions,
69
+ answerExpressions,
70
+ answerOptions
71
+ } = extractOtherExtensionsResult;
67
72
  variables = extractOtherExtensionsResult.variables;
68
73
  valueSetPromises = extractOtherExtensionsResult.valueSetPromises;
69
74
 
@@ -83,6 +88,12 @@ export async function createQuestionnaireModel(
83
88
  terminologyServerUrl
84
89
  );
85
90
 
91
+ // In answerOptions, add display values to codings lacking them
92
+ const completeAnswerOptions = await addDisplayToAnswerOptions(
93
+ answerOptions,
94
+ terminologyServerUrl
95
+ );
96
+
86
97
  return {
87
98
  itemTypes,
88
99
  tabs,
@@ -92,6 +103,7 @@ export async function createQuestionnaireModel(
92
103
  enableWhenExpressions,
93
104
  calculatedExpressions,
94
105
  answerExpressions,
106
+ answerOptions: completeAnswerOptions,
95
107
  processedValueSetCodings,
96
108
  processedValueSetUrls,
97
109
  fhirPathContext: {}
@@ -107,6 +119,7 @@ function createEmptyModel(): QuestionnaireModel {
107
119
  calculatedExpressions: {},
108
120
  enableWhenExpressions: { singleExpressions: {}, repeatExpressions: {} },
109
121
  answerExpressions: {},
122
+ answerOptions: {},
110
123
  enableWhenItems: { singleItems: {}, repeatItems: {} },
111
124
  processedValueSetCodings: {},
112
125
  processedValueSetUrls: {},
@@ -19,6 +19,7 @@ import type {
19
19
  Expression,
20
20
  Questionnaire,
21
21
  QuestionnaireItem,
22
+ QuestionnaireItemAnswerOption,
22
23
  QuestionnaireItemEnableWhen
23
24
  } from 'fhir/r4';
24
25
  import type { CalculatedExpression } from '../../interfaces/calculatedExpression.interface';
@@ -55,6 +56,7 @@ interface ReturnParamsRecursive {
55
56
  calculatedExpressions: Record<string, CalculatedExpression[]>;
56
57
  answerExpressions: Record<string, AnswerExpression>;
57
58
  valueSetPromises: Record<string, ValueSetPromise>;
59
+ answerOptions: Record<string, QuestionnaireItemAnswerOption[]>;
58
60
  }
59
61
 
60
62
  export function extractOtherExtensions(
@@ -70,6 +72,7 @@ export function extractOtherExtensions(
70
72
  };
71
73
  const calculatedExpressions: Record<string, CalculatedExpression[]> = {};
72
74
  const answerExpressions: Record<string, AnswerExpression> = {};
75
+ const answerOptions: Record<string, QuestionnaireItemAnswerOption[]> = {};
73
76
 
74
77
  if (!questionnaire.item || questionnaire.item.length === 0) {
75
78
  return {
@@ -81,6 +84,7 @@ export function extractOtherExtensions(
81
84
  },
82
85
  calculatedExpressions: {},
83
86
  answerExpressions: {},
87
+ answerOptions: {},
84
88
  valueSetPromises: valueSetPromises
85
89
  };
86
90
  }
@@ -95,6 +99,7 @@ export function extractOtherExtensions(
95
99
  enableWhenExpressions,
96
100
  calculatedExpressions,
97
101
  answerExpressions,
102
+ answerOptions,
98
103
  valueSetPromises,
99
104
  defaultTerminologyServerUrl: terminologyServerUrl,
100
105
  parentRepeatGroupLinkId: isRepeatGroup ? topLevelItem.linkId : undefined
@@ -107,6 +112,7 @@ export function extractOtherExtensions(
107
112
  enableWhenExpressions,
108
113
  calculatedExpressions,
109
114
  answerExpressions,
115
+ answerOptions,
110
116
  valueSetPromises
111
117
  };
112
118
  }
@@ -119,6 +125,7 @@ interface extractExtensionsFromItemRecursiveParams {
119
125
  enableWhenExpressions: EnableWhenExpressions;
120
126
  calculatedExpressions: Record<string, CalculatedExpression[]>;
121
127
  answerExpressions: Record<string, AnswerExpression>;
128
+ answerOptions: Record<string, QuestionnaireItemAnswerOption[]>;
122
129
  valueSetPromises: Record<string, ValueSetPromise>;
123
130
  defaultTerminologyServerUrl: string;
124
131
  parentRepeatGroupLinkId?: string;
@@ -135,6 +142,7 @@ function extractExtensionsFromItemRecursive(
135
142
  enableWhenExpressions,
136
143
  calculatedExpressions,
137
144
  answerExpressions,
145
+ answerOptions,
138
146
  valueSetPromises,
139
147
  defaultTerminologyServerUrl,
140
148
  parentRepeatGroupLinkId
@@ -201,6 +209,12 @@ function extractExtensionsFromItemRecursive(
201
209
  };
202
210
  }
203
211
 
212
+ // Get answerOptions
213
+ const options = item.answerOption ?? null;
214
+ if (options) {
215
+ answerOptions[item.linkId] = options;
216
+ }
217
+
204
218
  const valueSetUrl = item.answerValueSet;
205
219
  if (valueSetUrl) {
206
220
  if (!valueSetPromises[valueSetUrl] && !valueSetUrl.startsWith('#')) {
@@ -229,6 +243,7 @@ function extractExtensionsFromItemRecursive(
229
243
  enableWhenExpressions,
230
244
  calculatedExpressions,
231
245
  answerExpressions,
246
+ answerOptions,
232
247
  valueSetPromises
233
248
  };
234
249
  }
@@ -0,0 +1,56 @@
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, QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
19
+
20
+ /**
21
+ * Filter x-fhir-query variables from questionnaire's extensions needed for population
22
+ *
23
+ * @author Sean Fong
24
+ */
25
+ export function insertCompleteAnswerOptionsIntoQuestionnaire(
26
+ questionnaire: Questionnaire,
27
+ completeAnswerOptions: Record<string, QuestionnaireItemAnswerOption[]>
28
+ ): Questionnaire {
29
+ if (questionnaire.item && questionnaire.item.length > 0) {
30
+ for (const qItem of questionnaire.item) {
31
+ insertCompleteAnswerOptionsRecursive(qItem, completeAnswerOptions);
32
+ }
33
+ }
34
+
35
+ return questionnaire;
36
+ }
37
+
38
+ function insertCompleteAnswerOptionsRecursive(
39
+ qItem: QuestionnaireItem,
40
+ completeAnswerOptions: Record<string, QuestionnaireItemAnswerOption[]>
41
+ ) {
42
+ if (qItem.item) {
43
+ for (const childItem of qItem.item) {
44
+ insertCompleteAnswerOptionsRecursive(childItem, completeAnswerOptions);
45
+ }
46
+ }
47
+
48
+ if (qItem.answerOption) {
49
+ const options = completeAnswerOptions[qItem.linkId];
50
+ if (options) {
51
+ qItem.answerOption = options;
52
+ }
53
+ }
54
+
55
+ return;
56
+ }