@aehrc/smart-forms-renderer 0.27.2 → 0.27.4

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 (179) hide show
  1. package/.storybook/main.ts +2 -1
  2. package/.storybook/preview.ts +6 -1
  3. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.d.ts +3 -2
  4. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.js +9 -17
  5. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.js.map +1 -1
  6. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js +12 -9
  7. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js.map +1 -1
  8. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.d.ts +2 -2
  9. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.js +7 -9
  10. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.js.map +1 -1
  11. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js +12 -8
  12. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js.map +1 -1
  13. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.d.ts +2 -1
  14. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js +3 -3
  15. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js.map +1 -1
  16. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js +6 -4
  17. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js.map +1 -1
  18. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.d.ts +2 -1
  19. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.js +3 -3
  20. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.js.map +1 -1
  21. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.d.ts +2 -2
  22. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js +5 -7
  23. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js.map +1 -1
  24. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js +4 -4
  25. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js.map +1 -1
  26. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.d.ts +2 -1
  27. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js +2 -3
  28. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js.map +1 -1
  29. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js +5 -3
  30. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js.map +1 -1
  31. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.d.ts +2 -1
  32. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.js +3 -3
  33. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.js.map +1 -1
  34. package/lib/components/FormComponents/DecimalItem/DecimalItem.js +1 -1
  35. package/lib/components/FormComponents/GroupItem/TabButtonsWrapper.js +20 -20
  36. package/lib/components/FormComponents/GroupItem/TabButtonsWrapper.js.map +1 -1
  37. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.d.ts +3 -2
  38. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.js +7 -19
  39. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.js.map +1 -1
  40. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js +40 -40
  41. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js.map +1 -1
  42. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.js +15 -3
  43. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.js.map +1 -1
  44. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.d.ts +2 -1
  45. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.js +3 -3
  46. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.js.map +1 -1
  47. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js +27 -26
  48. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js.map +1 -1
  49. package/lib/components/FormComponents/StringItem/StringField.js +1 -1
  50. package/lib/components/FormComponents/StringItem/StringField.js.map +1 -1
  51. package/lib/hooks/useInitialiseRenderer.js +1 -1
  52. package/lib/hooks/useInitialiseRenderer.js.map +1 -1
  53. package/lib/hooks/useNextAndPreviousVisibleTabs.d.ts +7 -0
  54. package/lib/hooks/useNextAndPreviousVisibleTabs.js +63 -0
  55. package/lib/hooks/useNextAndPreviousVisibleTabs.js.map +1 -0
  56. package/lib/hooks/useNextPreviousVisibleTabs.d.ts +6 -0
  57. package/lib/hooks/useNextPreviousVisibleTabs.js +63 -0
  58. package/lib/hooks/useNextPreviousVisibleTabs.js.map +1 -0
  59. package/lib/index.d.ts +0 -7
  60. package/lib/index.js +0 -24
  61. package/lib/index.js.map +1 -1
  62. package/lib/utils/choice.d.ts +1 -7
  63. package/lib/utils/choice.js +10 -20
  64. package/lib/utils/choice.js.map +1 -1
  65. package/lib/utils/enableWhen.js +5 -7
  66. package/lib/utils/enableWhen.js.map +1 -1
  67. package/lib/utils/index.d.ts +1 -0
  68. package/lib/utils/index.js +1 -0
  69. package/lib/utils/index.js.map +1 -1
  70. package/lib/utils/openChoice.d.ts +9 -4
  71. package/lib/utils/openChoice.js +47 -78
  72. package/lib/utils/openChoice.js.map +1 -1
  73. package/lib/utils/tabs.d.ts +0 -21
  74. package/lib/utils/tabs.js +0 -51
  75. package/lib/utils/tabs.js.map +1 -1
  76. package/package.json +4 -4
  77. package/src/components/FormComponents/ChoiceItems/CheckboxOptionList.tsx +82 -0
  78. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionFields.tsx +23 -52
  79. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.tsx +15 -9
  80. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.tsx +17 -19
  81. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.tsx +13 -8
  82. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.tsx +5 -4
  83. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.tsx +6 -2
  84. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionView.tsx +5 -1
  85. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.tsx +9 -16
  86. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.tsx +4 -4
  87. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.tsx +4 -3
  88. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.tsx +5 -2
  89. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionView.tsx +5 -1
  90. package/src/components/FormComponents/DecimalItem/DecimalItem.tsx +1 -1
  91. package/src/components/FormComponents/GroupItem/TabButtonsWrapper.tsx +28 -25
  92. package/src/components/FormComponents/ItemParts/{RadioAnswerOptionButtons.tsx → RadioOptionList.tsx} +7 -7
  93. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionFields.tsx +18 -50
  94. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.tsx +70 -68
  95. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetFields.tsx +110 -0
  96. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetItem.tsx +188 -0
  97. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceItemSwitcher.tsx +46 -19
  98. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.tsx +5 -3
  99. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.tsx +37 -29
  100. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetFields.tsx +104 -0
  101. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetItem.tsx +156 -0
  102. package/src/components/FormComponents/StringItem/StringField.tsx +1 -1
  103. package/src/hooks/useInitialiseRenderer.ts +1 -1
  104. package/src/hooks/useNextAndPreviousVisibleTabs.ts +86 -0
  105. package/src/hooks/useOpenLabel.ts +43 -0
  106. package/src/index.ts +0 -21
  107. package/src/stories/BuildFormWrapper.tsx +57 -0
  108. package/src/stories/assets/questionnaires/QAdvancedAdditionalDisplayContent.ts +83 -0
  109. package/src/stories/assets/questionnaires/QAdvancedControlAppearance.ts +294 -0
  110. package/src/stories/assets/questionnaires/QAdvancedOther.ts +495 -0
  111. package/src/stories/assets/questionnaires/QAdvancedTextApperance.ts +188 -0
  112. package/src/stories/assets/questionnaires/QAttachment.ts +38 -0
  113. package/src/stories/assets/questionnaires/QBehaviorCalculations.ts +645 -0
  114. package/src/stories/assets/questionnaires/QBehaviorChoiceRestriction.ts +281 -0
  115. package/src/stories/assets/questionnaires/QBehaviorOther.ts +1149 -0
  116. package/src/stories/assets/questionnaires/QBehaviorValueConstraints.ts +508 -0
  117. package/src/stories/assets/questionnaires/QBoolean.ts +130 -0
  118. package/src/stories/assets/questionnaires/QChoice.ts +137 -0
  119. package/src/stories/assets/questionnaires/QDate.ts +56 -0
  120. package/src/stories/assets/questionnaires/QDateTime.ts +56 -0
  121. package/src/stories/assets/questionnaires/QDecimal.ts +56 -0
  122. package/src/stories/assets/questionnaires/QDisplay.ts +38 -0
  123. package/src/stories/assets/questionnaires/QGroup.ts +52 -0
  124. package/src/stories/assets/questionnaires/QInteger.ts +119 -0
  125. package/src/stories/assets/questionnaires/QItemControlDisplay.ts +114 -0
  126. package/src/stories/assets/questionnaires/QItemControlGroup.ts +419 -0
  127. package/src/stories/assets/questionnaires/QItemControlQuestion.ts +1271 -0
  128. package/src/stories/assets/questionnaires/QOpenChoice.ts +151 -0
  129. package/src/stories/assets/questionnaires/QQuantity.ts +38 -0
  130. package/src/stories/assets/questionnaires/QReference.ts +38 -0
  131. package/src/stories/assets/questionnaires/QSingleItems.ts +251 -0
  132. package/src/stories/assets/questionnaires/QString.ts +131 -0
  133. package/src/stories/assets/questionnaires/QText.ts +169 -0
  134. package/src/stories/assets/questionnaires/QTime.ts +38 -0
  135. package/src/stories/assets/questionnaires/QUrl.ts +38 -0
  136. package/src/stories/assets/questionnaires/index.ts +44 -0
  137. package/src/stories/itemTypes/Attachment.stories.tsx +39 -0
  138. package/src/stories/itemTypes/Boolean.stories.tsx +72 -0
  139. package/src/stories/{MedicalHistoryTable.stories.tsx → itemTypes/Choice.stories.tsx} +32 -26
  140. package/src/stories/itemTypes/Date.stories.tsx +46 -0
  141. package/src/stories/itemTypes/DateTime.stories.tsx +45 -0
  142. package/src/stories/itemTypes/Decimal.stories.tsx +56 -0
  143. package/src/stories/itemTypes/Display.stories.tsx +39 -0
  144. package/src/stories/itemTypes/Group.stories.tsx +39 -0
  145. package/src/stories/itemTypes/Integer.stories.tsx +55 -0
  146. package/src/stories/itemTypes/OpenChoice.stories.tsx +64 -0
  147. package/src/stories/itemTypes/Quantity.stories.tsx +39 -0
  148. package/src/stories/itemTypes/Reference.stories.tsx +39 -0
  149. package/src/stories/itemTypes/String.stories.tsx +51 -0
  150. package/src/stories/itemTypes/Text.stories.tsx +51 -0
  151. package/src/stories/itemTypes/Time.stories.tsx +39 -0
  152. package/src/stories/itemTypes/Url.stories.tsx +39 -0
  153. package/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx +45 -0
  154. package/src/stories/sdc/AdvancedControlAppearance.stories.tsx +51 -0
  155. package/src/stories/sdc/AdvancedOther.stories.tsx +76 -0
  156. package/src/stories/sdc/AdvancedTextAppearance.stories.tsx +69 -0
  157. package/src/stories/sdc/BehaviorCalculations.stories.tsx +69 -0
  158. package/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx +76 -0
  159. package/src/stories/sdc/BehaviorOther.stories.tsx +90 -0
  160. package/src/stories/sdc/BehaviorValueConstraints.stories.tsx +88 -0
  161. package/src/stories/sdc/ItemControlDisplay.stories.tsx +39 -0
  162. package/src/stories/sdc/ItemControlGroup.stories.tsx +55 -0
  163. package/src/stories/sdc/ItemControlQuestion.stories.tsx +118 -0
  164. package/src/utils/buildForm.ts +23 -0
  165. package/src/utils/choice.ts +16 -23
  166. package/src/utils/enableWhen.ts +5 -7
  167. package/src/utils/index.ts +1 -0
  168. package/src/utils/openChoice.ts +83 -98
  169. package/src/utils/tabs.ts +0 -75
  170. package/vite.config.ts +23 -0
  171. package/doctor-storybook.log +0 -18
  172. package/src/stories/SmartFormsRenderer.stories.ts +0 -139
  173. package/src/stories/assets/QItems-and-QRItems/QR_GTableMedicalHistory.json +0 -80
  174. package/src/stories/assets/QItems-and-QRItems/Q_GTableMedicalHistory.json +0 -109
  175. package/src/stories/assets/Qs-and-QRs/Q715.json +0 -15086
  176. package/src/stories/assets/Qs-and-QRs/QDev715.json +0 -16081
  177. package/src/stories/assets/Qs-and-QRs/QTestGrid.json +0 -411
  178. package/src/stories/assets/Qs-and-QRs/R715.json +0 -311
  179. package/src/stories/assets/Qs-and-QRs/RTestGrid.json +0 -34
@@ -16,127 +16,112 @@
16
16
  */
17
17
 
18
18
  import type {
19
- Coding,
20
19
  QuestionnaireItem,
21
20
  QuestionnaireItemAnswerOption,
22
21
  QuestionnaireResponseItem,
23
22
  QuestionnaireResponseItemAnswer
24
23
  } from 'fhir/r4';
25
- import { CheckBoxOption, OpenChoiceItemControl } from '../interfaces/choice.enum';
24
+ import { OpenChoiceItemControl } from '../interfaces/choice.enum';
26
25
  import { isSpecificItemControl } from './itemControl';
27
- import { findInAnswerOptions, findInAnswerValueSetCodings } from './choice';
26
+ import _isEqual from 'lodash/isEqual';
28
27
 
29
28
  /**
30
- * Update open-choice checkbox group answers based on checkbox changes
29
+ * Update open choice answer based on open label value
31
30
  *
32
31
  * @author Sean Fong
33
32
  */
34
- export function updateQrOpenChoiceCheckboxAnswers(
35
- changedOptionAnswer: string | null,
36
- changedOpenLabelAnswer: string | null,
33
+ export function updateOpenLabelAnswer(
34
+ openLabelChecked: boolean,
35
+ changedOpenLabelValue: string,
37
36
  answers: QuestionnaireResponseItemAnswer[],
38
- answerOptions: QuestionnaireItemAnswerOption[] | Coding[],
39
- qrChoiceCheckbox: QuestionnaireResponseItem,
40
- checkboxOptionType: CheckBoxOption,
37
+ options: QuestionnaireItemAnswerOption[],
38
+ oldQrItem: QuestionnaireResponseItem,
41
39
  isMultiSelection: boolean
42
- ): QuestionnaireResponseItem | null {
43
- if (changedOptionAnswer) {
44
- const newAnswer =
45
- checkboxOptionType === CheckBoxOption.AnswerOption
46
- ? findInAnswerOptions(answerOptions, changedOptionAnswer)
47
- : findInAnswerValueSetCodings(answerOptions, changedOptionAnswer);
48
- if (!newAnswer) return null;
49
-
50
- if (isMultiSelection && answers.length > 0) {
51
- // check if new answer exists in existing answers
52
- const newAnswerInAnswers =
53
- checkboxOptionType === CheckBoxOption.AnswerOption
54
- ? findInAnswerOptions(answers, changedOptionAnswer)
55
- : findInAnswerValueSetCodings(answers, changedOptionAnswer);
56
-
57
- if (newAnswerInAnswers) {
58
- // remove new answer from qrAnswers
59
- const newAnswers = [...answers].filter(
60
- (answer) => JSON.stringify(answer) !== JSON.stringify(newAnswerInAnswers)
61
- );
62
- return { ...qrChoiceCheckbox, answer: newAnswers };
63
- } else {
64
- // add new answer to qrAnswers
65
- return { ...qrChoiceCheckbox, answer: [...answers, newAnswer] };
66
- }
67
- } else {
68
- return answers.some((answer) => JSON.stringify(answer) === JSON.stringify(newAnswer))
69
- ? { ...qrChoiceCheckbox, answer: [] }
70
- : { ...qrChoiceCheckbox, answer: [newAnswer] };
71
- }
72
- } else if (changedOpenLabelAnswer !== null) {
73
- const newOpenLabelAnswer = { valueString: changedOpenLabelAnswer };
74
- const oldOpenLabelAnswer: QuestionnaireResponseItemAnswer | null = getOldOpenLabelAnswer(
75
- answers,
76
- answerOptions
77
- );
78
-
79
- if (answers.length === 0) {
80
- if (changedOpenLabelAnswer === '') {
81
- return { linkId: qrChoiceCheckbox.linkId, text: qrChoiceCheckbox.text };
82
- } else {
83
- return { ...qrChoiceCheckbox, answer: [newOpenLabelAnswer] };
84
- }
40
+ ) {
41
+ // Open label is unchecked, search for open label value and remove it
42
+ if (!openLabelChecked) {
43
+ // In single-selection, return empty array because there can only be one answer
44
+ if (!isMultiSelection) {
45
+ return {
46
+ ...oldQrItem,
47
+ answer: []
48
+ };
85
49
  }
86
50
 
87
- if (isMultiSelection) {
88
- if (!oldOpenLabelAnswer) {
89
- // append newOpenLabel if oldOpenLabel doesnt exist
90
- return {
91
- ...qrChoiceCheckbox,
92
- answer: [...answers, newOpenLabelAnswer]
93
- };
94
- } else {
95
- // An oldOpenLabel already exists
96
- // Remove oldOpenLabel from answers
97
- const answersWithoutOpenLabel = [...answers].filter(
98
- (answer) => JSON.stringify(answer) !== JSON.stringify(oldOpenLabelAnswer)
99
- );
100
-
101
- if (
102
- JSON.stringify(newOpenLabelAnswer) === JSON.stringify(oldOpenLabelAnswer) ||
103
- changedOpenLabelAnswer === ''
104
- ) {
105
- // User unchecks openLabel checkbox or clears field
106
- if (answersWithoutOpenLabel.length > 0) {
107
- return { ...qrChoiceCheckbox, answer: answersWithoutOpenLabel };
108
- } else {
109
- return { linkId: qrChoiceCheckbox.linkId, text: qrChoiceCheckbox.text };
110
- }
111
- } else {
112
- // User changes openLabel value
113
- return {
114
- ...qrChoiceCheckbox,
115
- answer: [...answersWithoutOpenLabel, newOpenLabelAnswer]
116
- };
117
- }
118
- }
119
- } else {
120
- if (!oldOpenLabelAnswer || newOpenLabelAnswer !== oldOpenLabelAnswer) {
121
- // set newOpenLabel as sole answer if oldOpenLabel doesnt exist OR if user changed openLabel value
122
- return { ...qrChoiceCheckbox, answer: [newOpenLabelAnswer] };
123
- } else {
124
- // User unchecks openLabel checkbox
125
- return { ...qrChoiceCheckbox, answer: [] };
126
- }
51
+ // The rest of the processing is for multi-selection
52
+ // Get the indexes of answers that match the open label value
53
+ const matchedIndexes = answers
54
+ .filter((answer) => answer.valueString === changedOpenLabelValue)
55
+ .map((matched) => answers.indexOf(matched));
56
+
57
+ // Only remove the last one if there are multiple matches, in case open label value is same as an option
58
+ if (matchedIndexes.length > 0) {
59
+ const lastMatchedIndex = matchedIndexes[matchedIndexes.length - 1];
60
+ const newAnswers = answers.filter((answer, index) => index !== lastMatchedIndex);
61
+
62
+ return {
63
+ ...oldQrItem,
64
+ answer: newAnswers
65
+ };
127
66
  }
128
- } else {
129
- // Default condition which will not happen
130
- return { ...qrChoiceCheckbox };
67
+
68
+ // Return oldQrItem if no matches are found
69
+ return oldQrItem;
70
+ }
71
+
72
+ // Open label is checked, search for open label value and add it
73
+ const newOpenLabelAnswer: QuestionnaireResponseItemAnswer = {
74
+ valueString: changedOpenLabelValue
75
+ };
76
+
77
+ // In single-selection, return only newOpenLabelAnswer in an array because there can only be one answer
78
+ if (!isMultiSelection) {
79
+ return {
80
+ ...oldQrItem,
81
+ answer: [newOpenLabelAnswer]
82
+ };
83
+ }
84
+
85
+ const oldOpenLabelAnswer: QuestionnaireResponseItemAnswer | null = getOldOpenLabelAnswer(
86
+ answers,
87
+ options
88
+ );
89
+
90
+ // No open label answer exists initially, add newOpenLabelAnswer to answers
91
+ if (!oldOpenLabelAnswer) {
92
+ return {
93
+ ...oldQrItem,
94
+ answer: [...answers, newOpenLabelAnswer]
95
+ };
131
96
  }
97
+
98
+ // Old open label answer equals to new open label answer
99
+ // This should not happen, but return oldQrItem
100
+ if (_isEqual(oldOpenLabelAnswer, newOpenLabelAnswer)) {
101
+ return oldQrItem;
102
+ }
103
+
104
+ // New open label answer is different from old open label answer, update it
105
+ oldOpenLabelAnswer.valueString = changedOpenLabelValue;
106
+ return {
107
+ ...oldQrItem,
108
+ answer: oldQrItem.answer
109
+ };
132
110
  }
133
111
 
112
+ /**
113
+ * Get the old open label answer from the list of answers
114
+ *
115
+ * @author Sean Fong
116
+ */
134
117
  export function getOldOpenLabelAnswer(
135
118
  answers: QuestionnaireResponseItemAnswer[],
136
119
  options: QuestionnaireItemAnswerOption[]
137
120
  ): QuestionnaireResponseItemAnswer | null {
138
- const openLabelAnswers = answers.filter((answer) => options.indexOf(answer) === -1);
139
- return openLabelAnswers.length > 0 ? openLabelAnswers[0] : null;
121
+ const openLabelAnswer = answers.find(
122
+ (answer) => !options.some((option) => _isEqual(option, answer))
123
+ );
124
+ return openLabelAnswer ?? null;
140
125
  }
141
126
 
142
127
  /**
package/src/utils/tabs.ts CHANGED
@@ -156,81 +156,6 @@ export function constructTabsWithVisibility(
156
156
  });
157
157
  }
158
158
 
159
- interface getVisibleTabIndexParams {
160
- direction: 'next' | 'previous';
161
- tabs: Tabs;
162
- currentTabIndex: number;
163
- enableWhenIsActivated: boolean;
164
- enableWhenItems: EnableWhenItems;
165
- enableWhenExpressions: EnableWhenExpressions;
166
- }
167
- /**
168
- * Get index of next visible tab
169
- *
170
- * @author Sean Fong
171
- */
172
- export function getVisibleTabIndex(params: getVisibleTabIndexParams): number {
173
- const {
174
- direction,
175
- tabs,
176
- currentTabIndex,
177
- enableWhenIsActivated,
178
- enableWhenItems,
179
- enableWhenExpressions
180
- } = params;
181
-
182
- const tabsWithVisibility = constructTabsWithVisibility({
183
- tabs,
184
- enableWhenIsActivated,
185
- enableWhenItems,
186
- enableWhenExpressions
187
- });
188
-
189
- let visibleTabIndex;
190
- if (direction === 'next') {
191
- visibleTabIndex = currentTabIndex + 1;
192
- const nextTabIndexIsVisible = false;
193
- while (!nextTabIndexIsVisible) {
194
- if (tabsWithVisibility[visibleTabIndex].isVisible) {
195
- return visibleTabIndex;
196
- }
197
- visibleTabIndex++;
198
- }
199
- } else {
200
- visibleTabIndex = currentTabIndex - 1;
201
- const previousTabIndexIsVisible = false;
202
- while (!previousTabIndexIsVisible) {
203
- if (tabsWithVisibility[visibleTabIndex].isVisible) {
204
- return visibleTabIndex;
205
- }
206
- visibleTabIndex--;
207
- }
208
- }
209
-
210
- return visibleTabIndex;
211
- }
212
-
213
- /**
214
- *
215
- * Find number of visible tabs
216
- *
217
- * @author Sean Fong
218
- */
219
- export function findNumOfVisibleTabs(
220
- tabs: Tabs,
221
- enableWhenIsActivated: boolean,
222
- enableWhenItems: EnableWhenItems,
223
- enableWhenExpressions: EnableWhenExpressions
224
- ): number {
225
- const tabsWithVisibility = constructTabsWithVisibility({
226
- tabs,
227
- enableWhenIsActivated,
228
- enableWhenItems,
229
- enableWhenExpressions
230
- });
231
- return tabsWithVisibility.filter((tab) => tab.isVisible).length;
232
- }
233
-
234
159
  export function getContextDisplays(item: QuestionnaireItem): QuestionnaireItem[] {
235
160
  if (!item.item || item.item.length === 0) {
236
161
  return [];
package/vite.config.ts ADDED
@@ -0,0 +1,23 @@
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 { defineConfig } from 'vite';
19
+
20
+ // https://vitejs.dev/config/
21
+ export default defineConfig({
22
+ plugins: []
23
+ });
@@ -1,18 +0,0 @@
1
- 🩺 The doctor is checking the health of your Storybook..
2
- ╭ Incompatible packages found ────────────────────────────────────────────────────────────────────────────────────────────────────────╮
3
- │ │
4
- │ The following packages are incompatible with Storybook 8.0.10 as they depend on different major versions of Storybook packages: │
5
- │ - @storybook/addon-styling@1.3.7 │
6
- │ │
7
- │ │
8
- │ Please consider updating your packages or contacting the maintainers for compatibility details. │
9
- │ For more on Storybook 8 compatibility, see the linked GitHub issue: │
10
- │ https://github.com/storybookjs/storybook/issues/26031 │
11
- │ │
12
- ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
13
-
14
- You can always recheck the health of your project by running:
15
- npx storybook doctor
16
-
17
- Full logs are available in /Users/fon026/IdeaProjects/smart-forms/packages/smart-forms-renderer/doctor-storybook.log
18
-
@@ -1,139 +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 { Meta, StoryObj } from '@storybook/react';
19
- import { SmartFormsRenderer } from '../components';
20
- import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4';
21
- import Q715Json from './assets/Qs-and-QRs/Q715.json';
22
- import R715Json from './assets/Qs-and-QRs/R715.json';
23
- import QTestGridJson from './assets/Qs-and-QRs/QTestGrid.json';
24
- import RTestGridJson from './assets/Qs-and-QRs/RTestGrid.json';
25
- import QDev715Json from './assets/Qs-and-QRs/QDev715.json';
26
-
27
- // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
28
- const meta = {
29
- title: 'Component/SmartFormsRenderer',
30
- component: SmartFormsRenderer,
31
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
32
- tags: []
33
- } satisfies Meta<typeof SmartFormsRenderer>;
34
-
35
- const Q715 = Q715Json as Questionnaire;
36
- const R715 = R715Json as QuestionnaireResponse;
37
-
38
- const QTestGrid = QTestGridJson as Questionnaire;
39
- const RTestGrid = RTestGridJson as QuestionnaireResponse;
40
-
41
- const QDev715 = QDev715Json as Questionnaire;
42
-
43
- export default meta;
44
- type Story = StoryObj<typeof meta>;
45
-
46
- // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
47
-
48
- export const Form715: Story = {
49
- args: {
50
- questionnaire: Q715
51
- }
52
- };
53
-
54
- export const Form715WithResponse: Story = {
55
- args: {
56
- questionnaire: Q715,
57
- questionnaireResponse: R715
58
- }
59
- };
60
-
61
- export const FormDev715: Story = {
62
- args: {
63
- questionnaire: QDev715
64
- }
65
- };
66
-
67
- export const FormTestGrid: Story = {
68
- args: {
69
- questionnaire: QTestGrid
70
- }
71
- };
72
-
73
- export const FormTestGridWithResponse: Story = {
74
- args: {
75
- questionnaire: QTestGrid,
76
- questionnaireResponse: RTestGrid,
77
- additionalVariables: {}
78
- }
79
- };
80
-
81
- export const QTestGridWithResponseAddFhirPath: Story = {
82
- args: {
83
- questionnaire: QTestGrid,
84
- questionnaireResponse: RTestGrid,
85
- additionalVariables: {
86
- addVar1: {
87
- url: 'http://hl7.org/fhir/StructureDefinition/variable',
88
- valueExpression: {
89
- name: 'addVar1',
90
- language: 'text/fhirpath',
91
- expression:
92
- "%resource.item.where(linkId='grid').item.where(linkId='1').item.where(linkId='1.1').item.where(linkId='1.1.1').answer.value"
93
- }
94
- }
95
- }
96
- }
97
- };
98
-
99
- export const QTestGridWithResponseAddXFhirQuery: Story = {
100
- args: {
101
- questionnaire: QTestGrid,
102
- questionnaireResponse: RTestGrid,
103
- additionalVariables: {
104
- addVar1: {
105
- url: 'http://hl7.org/fhir/StructureDefinition/variable',
106
- valueExpression: {
107
- name: 'addVar1',
108
- language: 'text/fhirpath',
109
- expression:
110
- "%resource.item.where(linkId='grid').item.where(linkId='1').item.where(linkId='1.1').item.where(linkId='1.1.1').answer.value"
111
- }
112
- },
113
- addVar2: {
114
- url: 'http://hl7.org/fhir/StructureDefinition/variable',
115
- valueExpression: {
116
- name: 'addVar2',
117
- language: 'application/x-fhir-query',
118
- expression: 'Condition?patient={{%patient.id}}'
119
- }
120
- }
121
- }
122
- }
123
- };
124
-
125
- export const QTestGridWithResponseReadOnly: Story = {
126
- args: {
127
- questionnaire: QTestGrid,
128
- questionnaireResponse: RTestGrid,
129
- readOnly: true
130
- }
131
- };
132
-
133
- export const Form715WithResponseReadOnly: Story = {
134
- args: {
135
- questionnaire: Q715,
136
- questionnaireResponse: R715,
137
- readOnly: true
138
- }
139
- };
@@ -1,80 +0,0 @@
1
- [
2
- {
3
- "linkId": "92bd7d05-9b5e-4cf9-900b-703f361dad9d",
4
- "text": "Medical history and current problems list",
5
- "item": [
6
- {
7
- "linkId": "59b1900a-4f85-4a8c-b9cd-3fe2fd76f27e",
8
- "text": "Condition",
9
- "answer": [
10
- {
11
- "valueString": "Large diffuse B-cell lymphoma of the brain"
12
- }
13
- ]
14
- },
15
- {
16
- "linkId": "88bcfad7-386b-4d87-b34b-2e50482e4d2c",
17
- "text": "Clinical Status",
18
- "answer": [
19
- {
20
- "valueCoding": {
21
- "system": "http://terminology.hl7.org/CodeSystem/condition-clinical",
22
- "code": "active",
23
- "display": "Active"
24
- }
25
- }
26
- ]
27
- },
28
- {
29
- "linkId": "18b9e159-2ed7-4047-82b7-deb2a171de4f",
30
- "text": "Recorded Date",
31
- "answer": [
32
- {
33
- "valueDate": "2021-02-01"
34
- }
35
- ]
36
- }
37
- ]
38
- },
39
- {
40
- "linkId": "92bd7d05-9b5e-4cf9-900b-703f361dad9d",
41
- "text": "Medical history and current problems list",
42
- "item": [
43
- {
44
- "linkId": "59b1900a-4f85-4a8c-b9cd-3fe2fd76f27e",
45
- "text": "Condition",
46
- "answer": [
47
- {
48
- "valueCoding": {
49
- "system": "http://snomed.info/sct",
50
- "code": "56731001",
51
- "display": "Hypertonia"
52
- }
53
- }
54
- ]
55
- },
56
- {
57
- "linkId": "88bcfad7-386b-4d87-b34b-2e50482e4d2c",
58
- "text": "Clinical Status",
59
- "answer": [
60
- {
61
- "valueCoding": {
62
- "system": "http://terminology.hl7.org/CodeSystem/condition-clinical",
63
- "code": "inactive",
64
- "display": "Inactive"
65
- }
66
- }
67
- ]
68
- },
69
- {
70
- "linkId": "18b9e159-2ed7-4047-82b7-deb2a171de4f",
71
- "text": "Recorded Date",
72
- "answer": [
73
- {
74
- "valueDate": "2023-11-08"
75
- }
76
- ]
77
- }
78
- ]
79
- }
80
- ]
@@ -1,109 +0,0 @@
1
- {
2
- "extension": [
3
- {
4
- "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
5
- "valueCodeableConcept": {
6
- "coding": [
7
- {
8
- "system": "http://hl7.org/fhir/questionnaire-item-control",
9
- "code": "gtable"
10
- }
11
- ]
12
- }
13
- },
14
- {
15
- "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemPopulationContext",
16
- "valueExpression": {
17
- "name": "ConditionRepeat",
18
- "language": "text/fhirpath",
19
- "expression": "%Condition.entry.resource"
20
- }
21
- }
22
- ],
23
- "linkId": "92bd7d05-9b5e-4cf9-900b-703f361dad9d",
24
- "text": "Medical history and current problems list",
25
- "type": "group",
26
- "repeats": true,
27
- "item": [
28
- {
29
- "extension": [
30
- {
31
- "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
32
- "valueCodeableConcept": {
33
- "coding": [
34
- {
35
- "system": "http://hl7.org/fhir/questionnaire-item-control",
36
- "code": "autocomplete"
37
- }
38
- ]
39
- }
40
- },
41
- {
42
- "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
43
- "valueExpression": {
44
- "language": "text/fhirpath",
45
- "expression": "%ConditionRepeat.code.select((coding.where(system='http://snomed.info/sct') | coding.where(system!='http://snomed.info/sct').first() | text ).first())"
46
- }
47
- }
48
- ],
49
- "linkId": "59b1900a-4f85-4a8c-b9cd-3fe2fd76f27e",
50
- "text": "Condition",
51
- "type": "open-choice",
52
- "answerValueSet": "https://smartforms.csiro.au/ig/ValueSet/MedicalHistory"
53
- },
54
- {
55
- "extension": [
56
- {
57
- "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
58
- "valueCodeableConcept": {
59
- "coding": [
60
- {
61
- "system": "http://hl7.org/fhir/questionnaire-item-control",
62
- "code": "drop-down"
63
- }
64
- ]
65
- }
66
- },
67
- {
68
- "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
69
- "valueExpression": {
70
- "language": "text/fhirpath",
71
- "expression": "%ConditionRepeat.clinicalStatus.coding"
72
- }
73
- }
74
- ],
75
- "linkId": "88bcfad7-386b-4d87-b34b-2e50482e4d2c",
76
- "text": "Clinical Status",
77
- "type": "choice",
78
- "answerValueSet": "http://hl7.org/fhir/ValueSet/condition-clinical"
79
- },
80
- {
81
- "extension": [
82
- {
83
- "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
84
- "valueExpression": {
85
- "language": "text/fhirpath",
86
- "expression": "%ConditionRepeat.onset.ofType(dateTime)"
87
- }
88
- }
89
- ],
90
- "linkId": "6ae641ad-95bb-4cdc-8910-5a52077e492c",
91
- "text": "Onset Date",
92
- "type": "date"
93
- },
94
- {
95
- "extension": [
96
- {
97
- "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
98
- "valueExpression": {
99
- "language": "text/fhirpath",
100
- "expression": "%ConditionRepeat.recordedDate"
101
- }
102
- }
103
- ],
104
- "linkId": "18b9e159-2ed7-4047-82b7-deb2a171de4f",
105
- "text": "Recorded Date",
106
- "type": "date"
107
- }
108
- ]
109
- }