@aehrc/smart-forms-renderer 0.36.0 → 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.
- package/CHANGELOG.md +40 -0
- package/lib/components/FormComponents/Button.styles.d.ts +4 -0
- package/lib/components/FormComponents/Button.styles.js +10 -0
- package/lib/components/FormComponents/Button.styles.js.map +1 -0
- package/lib/components/FormComponents/GroupItem/GroupHeading.d.ts +1 -0
- package/lib/components/FormComponents/GroupItem/GroupHeading.js +3 -2
- package/lib/components/FormComponents/GroupItem/GroupHeading.js.map +1 -1
- package/lib/components/FormComponents/GroupItem/GroupItem.d.ts +4 -0
- package/lib/components/FormComponents/GroupItem/GroupItem.js +3 -3
- package/lib/components/FormComponents/GroupItem/GroupItem.js.map +1 -1
- package/lib/components/FormComponents/GroupItem/GroupItemView.d.ts +4 -0
- package/lib/components/FormComponents/GroupItem/GroupItemView.js +8 -5
- package/lib/components/FormComponents/GroupItem/GroupItemView.js.map +1 -1
- package/lib/components/FormComponents/GroupItem/NextPageButton.d.ts +7 -0
- package/lib/components/FormComponents/GroupItem/NextPageButton.js +26 -0
- package/lib/components/FormComponents/GroupItem/NextPageButton.js.map +1 -0
- package/lib/components/FormComponents/GroupItem/PageButtonWrapper.d.ts +8 -0
- package/lib/components/FormComponents/GroupItem/PageButtonWrapper.js +46 -0
- package/lib/components/FormComponents/GroupItem/PageButtonWrapper.js.map +1 -0
- package/lib/components/FormComponents/GroupItem/PreviousPageButton.d.ts +7 -0
- package/lib/components/FormComponents/GroupItem/PreviousPageButton.js +26 -0
- package/lib/components/FormComponents/GroupItem/PreviousPageButton.js.map +1 -0
- package/lib/components/Renderer/BaseRenderer.js +8 -0
- package/lib/components/Renderer/BaseRenderer.js.map +1 -1
- package/lib/components/Renderer/FormBodyPage.d.ts +9 -0
- package/lib/components/Renderer/FormBodyPage.js +43 -0
- package/lib/components/Renderer/FormBodyPage.js.map +1 -0
- package/lib/components/Renderer/FormTopLevelItem.js +7 -0
- package/lib/components/Renderer/FormTopLevelItem.js.map +1 -1
- package/lib/components/Renderer/FormTopLevelPage.d.ts +9 -0
- package/lib/components/Renderer/FormTopLevelPage.js +29 -0
- package/lib/components/Renderer/FormTopLevelPage.js.map +1 -0
- package/lib/hooks/useCodingCalculatedExpression.js +11 -0
- package/lib/hooks/useCodingCalculatedExpression.js.map +1 -1
- package/lib/hooks/useNextAndPreviousVisiblePages.d.ts +7 -0
- package/lib/hooks/useNextAndPreviousVisiblePages.js +47 -0
- package/lib/hooks/useNextAndPreviousVisiblePages.js.map +1 -0
- package/lib/interfaces/page.interface.d.ts +16 -0
- package/lib/interfaces/page.interface.js +2 -0
- package/lib/interfaces/page.interface.js.map +1 -0
- package/lib/interfaces/questionnaireStore.interface.d.ts +2 -0
- package/lib/stores/questionnaireStore.d.ts +13 -0
- package/lib/stores/questionnaireStore.js +19 -3
- package/lib/stores/questionnaireStore.js.map +1 -1
- package/lib/utils/calculatedExpression.js +1 -1
- package/lib/utils/calculatedExpression.js.map +1 -1
- package/lib/utils/fhirpath.js +0 -4
- package/lib/utils/fhirpath.js.map +1 -1
- package/lib/utils/initialise.d.ts +3 -0
- package/lib/utils/initialise.js +6 -1
- package/lib/utils/initialise.js.map +1 -1
- package/lib/utils/page.d.ts +43 -0
- package/lib/utils/page.js +101 -0
- package/lib/utils/page.js.map +1 -0
- package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js +4 -0
- package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js.map +1 -1
- package/lib/utils/questionnaireStoreUtils/extractPages.d.ts +3 -0
- package/lib/utils/questionnaireStoreUtils/extractPages.js +18 -0
- package/lib/utils/questionnaireStoreUtils/extractPages.js.map +1 -0
- package/package.json +4 -4
- package/src/components/FormComponents/Button.styles.ts +10 -0
- package/src/components/FormComponents/GroupItem/GroupHeading.tsx +5 -3
- package/src/components/FormComponents/GroupItem/GroupItem.tsx +11 -1
- package/src/components/FormComponents/GroupItem/GroupItemView.tsx +12 -0
- package/src/components/FormComponents/GroupItem/NextPageButton.tsx +37 -0
- package/src/components/FormComponents/GroupItem/PageButtonWrapper.tsx +78 -0
- package/src/components/FormComponents/GroupItem/PreviousPageButton.tsx +41 -0
- package/src/components/Renderer/BaseRenderer.tsx +21 -0
- package/src/components/Renderer/FormBodyPage.tsx +93 -0
- package/src/components/Renderer/FormTopLevelItem.tsx +17 -0
- package/src/components/Renderer/FormTopLevelPage.tsx +70 -0
- package/src/hooks/useCodingCalculatedExpression.ts +14 -1
- package/src/hooks/useNextAndPreviousVisiblePages.ts +69 -0
- package/src/interfaces/page.interface.ts +13 -0
- package/src/interfaces/questionnaireStore.interface.ts +2 -0
- package/src/stores/questionnaireStore.ts +33 -2
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreAllergyIntolerance.json +209 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreCondition.json +220 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreEncounter.json +299 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreImmunization.json +175 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreMedicationRequest.json +229 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationBP.json +359 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationBodyHeight.json +195 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationBodyWeight.json +195 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationHeartRate.json +195 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreObservationSmokingStatus.json +174 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCorePatient.json +495 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCorePractitioner.json +139 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCorePractitionerRole.json +216 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreProcedure.json +199 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreRespirationRate.json +195 -0
- package/src/stories/assets/questionnaires/AuCoreTestingJson/AuCoreWaistCircumference.json +195 -0
- package/src/stories/assets/questionnaires/QAuCoreTesting.ts +3796 -0
- package/src/stories/assets/questionnaires/QItemControlGroup.ts +673 -0
- package/src/stories/assets/questionnaires/QPrePopTester.ts +266 -71
- package/src/stories/sdc/ItemControlGroup.stories.tsx +22 -1
- package/src/stories/testing/AuCoreTester.stories.tsx +196 -0
- package/src/utils/calculatedExpression.ts +1 -1
- package/src/utils/fhirpath.ts +0 -5
- package/src/utils/initialise.ts +11 -0
- package/src/utils/page.ts +134 -0
- package/src/utils/questionnaireStoreUtils/createQuestionaireModel.ts +5 -0
- package/src/utils/questionnaireStoreUtils/extractPages.ts +24 -0
- package/stats.html +0 -4842
- package/stats1.html +0 -4842
- package/stats3.html +0 -4842
package/src/utils/initialise.ts
CHANGED
|
@@ -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
|
+
}
|