@aehrc/smart-forms-renderer 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/FormComponents/GroupItem/GroupAccordion.styles.d.ts +20 -0
- package/lib/components/FormComponents/GroupItem/GroupAccordion.styles.js +12 -0
- package/lib/components/FormComponents/GroupItem/GroupAccordion.styles.js.map +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.js +2 -15
- package/lib/components/FormComponents/GroupItem/GroupItem.js.map +1 -1
- package/lib/components/FormComponents/GroupItem/GroupItem.styles.d.ts +1 -1
- package/lib/components/FormComponents/GroupItem/GroupItemSwitcher.d.ts +1 -2
- package/lib/components/FormComponents/GroupItem/GroupItemSwitcher.js +1 -1
- package/lib/components/FormComponents/GroupItem/GroupItemSwitcher.js.map +1 -1
- package/lib/components/FormComponents/GroupItem/GroupItemView.d.ts +16 -0
- package/lib/components/FormComponents/GroupItem/GroupItemView.js +62 -0
- package/lib/components/FormComponents/GroupItem/GroupItemView.js.map +1 -0
- package/lib/components/FormComponents/ItemParts/ItemLabelText.js +20 -6
- package/lib/components/FormComponents/ItemParts/ItemLabelText.js.map +1 -1
- package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.js +4 -2
- package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.js.map +1 -1
- package/lib/components/FormComponents/RepeatGroup/RepeatGroup.js +2 -37
- package/lib/components/FormComponents/RepeatGroup/RepeatGroup.js.map +1 -1
- package/lib/components/FormComponents/RepeatGroup/RepeatGroupView.d.ts +20 -0
- package/lib/components/FormComponents/RepeatGroup/RepeatGroupView.js +91 -0
- package/lib/components/FormComponents/RepeatGroup/RepeatGroupView.js.map +1 -0
- package/lib/components/FormComponents/SingleItem/SingleItem.js +13 -4
- package/lib/components/FormComponents/SingleItem/SingleItem.js.map +1 -1
- package/lib/components/FormComponents/SingleItem/SingleNestedItems.js +11 -7
- package/lib/components/FormComponents/SingleItem/SingleNestedItems.js.map +1 -1
- package/lib/components/Renderer/FormBodySingleCollapsible.js +5 -4
- package/lib/components/Renderer/FormBodySingleCollapsible.js.map +1 -1
- package/lib/theme/overrides/Accordion.js +1 -1
- package/lib/theme/overrides/Accordion.js.map +1 -1
- package/lib/utils/itemControl.d.ts +1 -0
- package/lib/utils/itemControl.js +9 -0
- package/lib/utils/itemControl.js.map +1 -1
- package/lib/utils/qItem.d.ts +2 -0
- package/lib/utils/qItem.js +14 -0
- package/lib/utils/qItem.js.map +1 -1
- package/package.json +3 -2
- package/src/components/FormComponents/GroupItem/GroupAccordion.styles.ts +12 -0
- package/src/components/FormComponents/GroupItem/GroupHeading.tsx +3 -3
- package/src/components/FormComponents/GroupItem/GroupItem.tsx +15 -39
- package/src/components/FormComponents/GroupItem/GroupItemSwitcher.tsx +2 -2
- package/src/components/FormComponents/GroupItem/GroupItemView.tsx +163 -0
- package/src/components/FormComponents/ItemParts/ItemLabelText.tsx +22 -11
- package/src/components/FormComponents/ItemParts/ItemLabelWrapper.tsx +8 -1
- package/src/components/FormComponents/RepeatGroup/RepeatGroup.tsx +11 -82
- package/src/components/FormComponents/RepeatGroup/RepeatGroupView.tsx +202 -0
- package/src/components/FormComponents/SingleItem/SingleItem.tsx +40 -11
- package/src/components/FormComponents/SingleItem/SingleNestedItems.tsx +24 -19
- package/src/components/Renderer/FormBodySingleCollapsible.tsx +7 -9
- package/src/stories/assets/questionnaires/QAdvancedControlAppearance.ts +333 -3
- package/src/stories/assets/questionnaires/QAdvancedTextApperance.ts +29 -0
- package/src/stories/assets/questionnaires/QDisplay.ts +82 -0
- package/src/stories/assets/questionnaires/QMbs715Tester.ts +32888 -0
- package/src/stories/itemTypes/Display.stories.tsx +11 -1
- package/src/stories/sdc/AdvancedControlAppearance.stories.tsx +26 -1
- package/src/stories/sdc/AdvancedTextAppearance.stories.tsx +7 -0
- package/src/stories/testing/Mbs715Tester.stories.tsx +57 -0
- package/src/theme/overrides/Accordion.ts +1 -1
- package/src/utils/itemControl.ts +14 -0
- package/src/utils/qItem.ts +24 -0
|
@@ -18,11 +18,13 @@
|
|
|
18
18
|
import React, { memo } from 'react';
|
|
19
19
|
import type { QuestionnaireItem } from 'fhir/r4';
|
|
20
20
|
import { getMarkdownString, getXHtmlString } from '../../../utils/itemControl';
|
|
21
|
-
import
|
|
21
|
+
import { default as htmlParse } from 'html-react-parser';
|
|
22
22
|
import Box from '@mui/material/Box';
|
|
23
23
|
import ReactMarkdown from 'react-markdown';
|
|
24
24
|
import Typography from '@mui/material/Typography';
|
|
25
25
|
import useDisplayCqfAndCalculatedExpression from '../../../hooks/useDisplayCqfAndCalculatedExpression';
|
|
26
|
+
import { structuredDataCapture } from 'fhir-sdc-helpers';
|
|
27
|
+
import { default as styleParse } from 'style-to-js';
|
|
26
28
|
|
|
27
29
|
interface ItemLabelTextProps {
|
|
28
30
|
qItem: QuestionnaireItem;
|
|
@@ -32,21 +34,18 @@ interface ItemLabelTextProps {
|
|
|
32
34
|
const ItemLabelText = memo(function ItemLabelText(props: ItemLabelTextProps) {
|
|
33
35
|
const { qItem, readOnly } = props;
|
|
34
36
|
|
|
37
|
+
let labelText = qItem.text ?? '';
|
|
38
|
+
|
|
35
39
|
// Use calculatedExpressionString if available
|
|
36
|
-
const calculatedExpressionString = useDisplayCqfAndCalculatedExpression(qItem);
|
|
40
|
+
const calculatedExpressionString = useDisplayCqfAndCalculatedExpression(qItem) ?? '';
|
|
37
41
|
if (calculatedExpressionString) {
|
|
38
|
-
|
|
39
|
-
<Typography color={readOnly ? 'text.disabled' : 'text.primary'} sx={{ mt: 0.25 }}>
|
|
40
|
-
{calculatedExpressionString}
|
|
41
|
-
</Typography>
|
|
42
|
-
);
|
|
42
|
+
labelText = calculatedExpressionString;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// parse xHTML if found
|
|
46
46
|
const xHtmlString = getXHtmlString(qItem);
|
|
47
|
-
|
|
48
47
|
if (xHtmlString) {
|
|
49
|
-
return <Box>{
|
|
48
|
+
return <Box>{htmlParse(xHtmlString)}</Box>;
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
// parse markdown if found
|
|
@@ -59,14 +58,26 @@ const ItemLabelText = memo(function ItemLabelText(props: ItemLabelTextProps) {
|
|
|
59
58
|
);
|
|
60
59
|
}
|
|
61
60
|
|
|
61
|
+
// labelText is empty, return null
|
|
62
|
+
if (!labelText) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// parse styles if found
|
|
67
|
+
const stylesString = structuredDataCapture.getStyle(qItem._text);
|
|
68
|
+
if (stylesString) {
|
|
69
|
+
const styles = styleParse(stylesString);
|
|
70
|
+
return <div style={styles}>{labelText}</div>;
|
|
71
|
+
}
|
|
72
|
+
|
|
62
73
|
if (qItem.type === 'group') {
|
|
63
|
-
return <>{
|
|
74
|
+
return <>{labelText}</>;
|
|
64
75
|
}
|
|
65
76
|
|
|
66
77
|
// parse regular text
|
|
67
78
|
return (
|
|
68
79
|
<Typography color={readOnly ? 'text.disabled' : 'text.primary'} sx={{ mt: 0.25 }}>
|
|
69
|
-
{
|
|
80
|
+
{labelText}
|
|
70
81
|
</Typography>
|
|
71
82
|
);
|
|
72
83
|
});
|
|
@@ -24,6 +24,7 @@ import ItemLabelText from './ItemLabelText';
|
|
|
24
24
|
import Tooltip from '@mui/material/Tooltip';
|
|
25
25
|
import Typography from '@mui/material/Typography';
|
|
26
26
|
import useRenderingExtensions from '../../../hooks/useRenderingExtensions';
|
|
27
|
+
import Iconify from '../../Iconify/Iconify';
|
|
27
28
|
|
|
28
29
|
interface LabelWrapperProps {
|
|
29
30
|
qItem: QuestionnaireItem;
|
|
@@ -54,13 +55,19 @@ function ItemLabelWrapper(props: LabelWrapperProps) {
|
|
|
54
55
|
}
|
|
55
56
|
}}>
|
|
56
57
|
<span>
|
|
57
|
-
<Box display="flex" columnGap={0.4} justifyContent="space-between">
|
|
58
|
+
<Box display="flex" columnGap={0.4} justifyContent="space-between" alignItems="center">
|
|
58
59
|
{required ? (
|
|
59
60
|
<Typography color="red" sx={{ ml: -1.15 }}>
|
|
60
61
|
*
|
|
61
62
|
</Typography>
|
|
62
63
|
) : null}
|
|
63
64
|
<ItemLabelText qItem={qItem} readOnly={readOnly} />
|
|
65
|
+
{displayFlyover !== '' ? (
|
|
66
|
+
<Iconify
|
|
67
|
+
icon="mdi:information-outline"
|
|
68
|
+
sx={{ height: 16, width: 16, mt: 0.25, ml: 0.25, color: 'text.secondary' }}
|
|
69
|
+
/>
|
|
70
|
+
) : null}
|
|
64
71
|
</Box>
|
|
65
72
|
</span>
|
|
66
73
|
</Tooltip>
|
|
@@ -24,21 +24,11 @@ import type {
|
|
|
24
24
|
} from '../../../interfaces/renderProps.interface';
|
|
25
25
|
import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
|
|
26
26
|
import useInitialiseRepeatGroups from '../../../hooks/useInitialiseRepeatGroups';
|
|
27
|
-
import { QGroupContainerBox } from '../../Box.styles';
|
|
28
|
-
import Card from '@mui/material/Card';
|
|
29
|
-
import Collapse from '@mui/material/Collapse';
|
|
30
|
-
import Divider from '@mui/material/Divider';
|
|
31
|
-
import { TransitionGroup } from 'react-transition-group';
|
|
32
|
-
import { createEmptyQrItem } from '../../../utils/qrItem';
|
|
33
27
|
import { nanoid } from 'nanoid';
|
|
34
|
-
import RepeatGroupItem from './RepeatGroupItem';
|
|
35
|
-
import AddItemButton from './AddItemButton';
|
|
36
|
-
import LabelWrapper from '../ItemParts/ItemLabelWrapper';
|
|
37
28
|
import cloneDeep from 'lodash.clonedeep';
|
|
38
|
-
import useReadOnly from '../../../hooks/useReadOnly';
|
|
39
|
-
import Typography from '@mui/material/Typography';
|
|
40
29
|
import { useQuestionnaireStore } from '../../../stores';
|
|
41
30
|
import useRepeatGroups from '../../../hooks/useRepeatGroups';
|
|
31
|
+
import RepeatGroupView from './RepeatGroupView';
|
|
42
32
|
|
|
43
33
|
interface RepeatGroupProps
|
|
44
34
|
extends PropsWithQrRepeatGroupChangeHandler,
|
|
@@ -68,8 +58,6 @@ function RepeatGroup(props: RepeatGroupProps) {
|
|
|
68
58
|
|
|
69
59
|
const mutateRepeatEnableWhenItems = useQuestionnaireStore.use.mutateRepeatEnableWhenItems();
|
|
70
60
|
|
|
71
|
-
const readOnly = useReadOnly(qItem, parentIsReadOnly);
|
|
72
|
-
|
|
73
61
|
const initialRepeatGroups = useInitialiseRepeatGroups(qItem, qrItems);
|
|
74
62
|
|
|
75
63
|
const [repeatGroups, setRepeatGroups] = useRepeatGroups(initialRepeatGroups);
|
|
@@ -122,76 +110,17 @@ function RepeatGroup(props: RepeatGroupProps) {
|
|
|
122
110
|
]);
|
|
123
111
|
}
|
|
124
112
|
|
|
125
|
-
if (showMinimalView) {
|
|
126
|
-
return (
|
|
127
|
-
<QGroupContainerBox key={qItem.linkId} cardElevation={groupCardElevation} isRepeated={true}>
|
|
128
|
-
<Card elevation={groupCardElevation} sx={{ p: 2 }}>
|
|
129
|
-
{repeatGroups.map(({ nanoId, qrItem: nullableQrItem }, index) => {
|
|
130
|
-
const answeredQrItem = createEmptyQrItem(qItem);
|
|
131
|
-
if (nullableQrItem) {
|
|
132
|
-
answeredQrItem.item = nullableQrItem.item;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return (
|
|
136
|
-
<RepeatGroupItem
|
|
137
|
-
key={nanoId}
|
|
138
|
-
qItem={qItem}
|
|
139
|
-
repeatGroupIndex={index}
|
|
140
|
-
answeredQrItem={answeredQrItem}
|
|
141
|
-
nullableQrItem={nullableQrItem}
|
|
142
|
-
numOfRepeatGroups={repeatGroups.length}
|
|
143
|
-
groupCardElevation={groupCardElevation + 1}
|
|
144
|
-
showMinimalView={showMinimalView}
|
|
145
|
-
parentIsReadOnly={parentIsReadOnly}
|
|
146
|
-
onDeleteItem={() => handleDeleteItem(index)}
|
|
147
|
-
onQrItemChange={(newQrItem) => handleAnswerChange(newQrItem, index)}
|
|
148
|
-
/>
|
|
149
|
-
);
|
|
150
|
-
})}
|
|
151
|
-
</Card>
|
|
152
|
-
</QGroupContainerBox>
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
113
|
return (
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
<TransitionGroup>
|
|
168
|
-
{repeatGroups.map(({ nanoId, qrItem: nullableQrItem }, index) => {
|
|
169
|
-
const answeredQrItem = createEmptyQrItem(qItem);
|
|
170
|
-
if (nullableQrItem) {
|
|
171
|
-
answeredQrItem.item = nullableQrItem.item;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return (
|
|
175
|
-
<Collapse key={nanoId} timeout={200}>
|
|
176
|
-
<RepeatGroupItem
|
|
177
|
-
qItem={qItem}
|
|
178
|
-
repeatGroupIndex={index}
|
|
179
|
-
answeredQrItem={answeredQrItem}
|
|
180
|
-
nullableQrItem={nullableQrItem}
|
|
181
|
-
numOfRepeatGroups={repeatGroups.length}
|
|
182
|
-
groupCardElevation={groupCardElevation + 1}
|
|
183
|
-
parentIsReadOnly={parentIsReadOnly}
|
|
184
|
-
onDeleteItem={() => handleDeleteItem(index)}
|
|
185
|
-
onQrItemChange={(newQrItem) => handleAnswerChange(newQrItem, index)}
|
|
186
|
-
/>
|
|
187
|
-
</Collapse>
|
|
188
|
-
);
|
|
189
|
-
})}
|
|
190
|
-
</TransitionGroup>
|
|
191
|
-
|
|
192
|
-
<AddItemButton repeatGroups={repeatGroups} readOnly={readOnly} onAddItem={handleAddItem} />
|
|
193
|
-
</Card>
|
|
194
|
-
</QGroupContainerBox>
|
|
114
|
+
<RepeatGroupView
|
|
115
|
+
qItem={qItem}
|
|
116
|
+
repeatGroups={repeatGroups}
|
|
117
|
+
groupCardElevation={groupCardElevation}
|
|
118
|
+
showMinimalView={showMinimalView}
|
|
119
|
+
parentIsReadOnly={parentIsReadOnly}
|
|
120
|
+
onAnswerChange={handleAnswerChange}
|
|
121
|
+
onAddItem={handleAddItem}
|
|
122
|
+
onDeleteItem={handleDeleteItem}
|
|
123
|
+
/>
|
|
195
124
|
);
|
|
196
125
|
}
|
|
197
126
|
|
|
@@ -0,0 +1,202 @@
|
|
|
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 React from 'react';
|
|
19
|
+
import type {
|
|
20
|
+
PropsWithParentIsReadOnlyAttribute,
|
|
21
|
+
PropsWithParentIsRepeatGroupAttribute,
|
|
22
|
+
PropsWithShowMinimalViewAttribute
|
|
23
|
+
} from '../../../interfaces/renderProps.interface';
|
|
24
|
+
import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
|
|
25
|
+
import { QGroupContainerBox } from '../../Box.styles';
|
|
26
|
+
import Card from '@mui/material/Card';
|
|
27
|
+
import Collapse from '@mui/material/Collapse';
|
|
28
|
+
import Divider from '@mui/material/Divider';
|
|
29
|
+
import { TransitionGroup } from 'react-transition-group';
|
|
30
|
+
import { createEmptyQrItem } from '../../../utils/qrItem';
|
|
31
|
+
import RepeatGroupItem from './RepeatGroupItem';
|
|
32
|
+
import AddItemButton from './AddItemButton';
|
|
33
|
+
import LabelWrapper from '../ItemParts/ItemLabelWrapper';
|
|
34
|
+
import Typography from '@mui/material/Typography';
|
|
35
|
+
import type { RepeatGroupSingle } from '../../../interfaces/repeatGroup.interface';
|
|
36
|
+
import useReadOnly from '../../../hooks/useReadOnly';
|
|
37
|
+
import { getGroupCollapsible } from '../../../utils/qItem';
|
|
38
|
+
import { GroupAccordion } from '../GroupItem/GroupAccordion.styles';
|
|
39
|
+
import AccordionSummary from '@mui/material/AccordionSummary';
|
|
40
|
+
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
41
|
+
import AccordionDetails from '@mui/material/AccordionDetails';
|
|
42
|
+
|
|
43
|
+
interface RepeatGroupViewProps
|
|
44
|
+
extends PropsWithShowMinimalViewAttribute,
|
|
45
|
+
PropsWithParentIsReadOnlyAttribute,
|
|
46
|
+
PropsWithParentIsRepeatGroupAttribute {
|
|
47
|
+
qItem: QuestionnaireItem;
|
|
48
|
+
repeatGroups: RepeatGroupSingle[];
|
|
49
|
+
groupCardElevation: number;
|
|
50
|
+
onAnswerChange: (newQrItem: QuestionnaireResponseItem, index: number) => void;
|
|
51
|
+
onAddItem: () => void;
|
|
52
|
+
onDeleteItem: (index: number) => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Main component to render a repeating, group Questionnaire item.
|
|
57
|
+
* Store and manages the state of multiple instances of GroupItem in a repeating group.
|
|
58
|
+
*
|
|
59
|
+
* @author Sean Fong
|
|
60
|
+
*/
|
|
61
|
+
function RepeatGroupView(props: RepeatGroupViewProps) {
|
|
62
|
+
const {
|
|
63
|
+
qItem,
|
|
64
|
+
repeatGroups,
|
|
65
|
+
groupCardElevation,
|
|
66
|
+
showMinimalView,
|
|
67
|
+
parentIsReadOnly,
|
|
68
|
+
onAnswerChange,
|
|
69
|
+
onAddItem,
|
|
70
|
+
onDeleteItem
|
|
71
|
+
} = props;
|
|
72
|
+
|
|
73
|
+
const readOnly = useReadOnly(qItem, parentIsReadOnly);
|
|
74
|
+
|
|
75
|
+
if (showMinimalView) {
|
|
76
|
+
return (
|
|
77
|
+
<QGroupContainerBox key={qItem.linkId} cardElevation={groupCardElevation} isRepeated={true}>
|
|
78
|
+
<Card elevation={groupCardElevation} sx={{ p: 2 }}>
|
|
79
|
+
{repeatGroups.map(({ nanoId, qrItem: nullableQrItem }, index) => {
|
|
80
|
+
const answeredQrItem = createEmptyQrItem(qItem);
|
|
81
|
+
if (nullableQrItem) {
|
|
82
|
+
answeredQrItem.item = nullableQrItem.item;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<RepeatGroupItem
|
|
87
|
+
key={nanoId}
|
|
88
|
+
qItem={qItem}
|
|
89
|
+
repeatGroupIndex={index}
|
|
90
|
+
answeredQrItem={answeredQrItem}
|
|
91
|
+
nullableQrItem={nullableQrItem}
|
|
92
|
+
numOfRepeatGroups={repeatGroups.length}
|
|
93
|
+
groupCardElevation={groupCardElevation + 1}
|
|
94
|
+
showMinimalView={showMinimalView}
|
|
95
|
+
parentIsReadOnly={parentIsReadOnly}
|
|
96
|
+
onDeleteItem={() => onDeleteItem(index)}
|
|
97
|
+
onQrItemChange={(newQrItem) => onAnswerChange(newQrItem, index)}
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
})}
|
|
101
|
+
</Card>
|
|
102
|
+
</QGroupContainerBox>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const groupIsCollapsible = getGroupCollapsible(qItem);
|
|
107
|
+
if (groupIsCollapsible) {
|
|
108
|
+
const isDefaultOpen = groupIsCollapsible === 'default-open';
|
|
109
|
+
return (
|
|
110
|
+
<GroupAccordion
|
|
111
|
+
disableGutters
|
|
112
|
+
defaultExpanded={isDefaultOpen}
|
|
113
|
+
elevation={groupCardElevation}
|
|
114
|
+
isRepeated={true}
|
|
115
|
+
slotProps={{
|
|
116
|
+
transition: { unmountOnExit: true, timeout: 250 }
|
|
117
|
+
}}>
|
|
118
|
+
<AccordionSummary expandIcon={<ExpandMoreIcon />} sx={{ minHeight: '28px' }}>
|
|
119
|
+
{qItem.text ? (
|
|
120
|
+
<>
|
|
121
|
+
<Typography variant="h6" color={readOnly ? 'text.secondary' : 'text.primary'}>
|
|
122
|
+
<LabelWrapper qItem={qItem} readOnly={readOnly} />
|
|
123
|
+
</Typography>
|
|
124
|
+
</>
|
|
125
|
+
) : null}
|
|
126
|
+
</AccordionSummary>
|
|
127
|
+
<AccordionDetails sx={{ pt: 0 }}>
|
|
128
|
+
{qItem.text ? <Divider sx={{ mb: 1.5 }} light /> : null}
|
|
129
|
+
<TransitionGroup>
|
|
130
|
+
{repeatGroups.map(({ nanoId, qrItem: nullableQrItem }, index) => {
|
|
131
|
+
const answeredQrItem = createEmptyQrItem(qItem);
|
|
132
|
+
if (nullableQrItem) {
|
|
133
|
+
answeredQrItem.item = nullableQrItem.item;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<Collapse key={nanoId} timeout={200}>
|
|
138
|
+
<RepeatGroupItem
|
|
139
|
+
qItem={qItem}
|
|
140
|
+
repeatGroupIndex={index}
|
|
141
|
+
answeredQrItem={answeredQrItem}
|
|
142
|
+
nullableQrItem={nullableQrItem}
|
|
143
|
+
numOfRepeatGroups={repeatGroups.length}
|
|
144
|
+
groupCardElevation={groupCardElevation + 1}
|
|
145
|
+
parentIsReadOnly={parentIsReadOnly}
|
|
146
|
+
onDeleteItem={() => onDeleteItem(index)}
|
|
147
|
+
onQrItemChange={(newQrItem) => onAnswerChange(newQrItem, index)}
|
|
148
|
+
/>
|
|
149
|
+
</Collapse>
|
|
150
|
+
);
|
|
151
|
+
})}
|
|
152
|
+
</TransitionGroup>
|
|
153
|
+
|
|
154
|
+
<AddItemButton repeatGroups={repeatGroups} readOnly={readOnly} onAddItem={onAddItem} />
|
|
155
|
+
</AccordionDetails>
|
|
156
|
+
</GroupAccordion>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<QGroupContainerBox key={qItem.linkId} cardElevation={groupCardElevation} isRepeated={true}>
|
|
162
|
+
<Card elevation={groupCardElevation} sx={{ p: 3, py: 2.5, mb: 3.5 }}>
|
|
163
|
+
{qItem.text ? (
|
|
164
|
+
<>
|
|
165
|
+
<Typography variant="h6" color={readOnly ? 'text.secondary' : 'text.primary'}>
|
|
166
|
+
<LabelWrapper qItem={qItem} readOnly={readOnly} />
|
|
167
|
+
</Typography>
|
|
168
|
+
<Divider sx={{ mt: 1, mb: 1.5 }} light />
|
|
169
|
+
</>
|
|
170
|
+
) : null}
|
|
171
|
+
<TransitionGroup>
|
|
172
|
+
{repeatGroups.map(({ nanoId, qrItem: nullableQrItem }, index) => {
|
|
173
|
+
const answeredQrItem = createEmptyQrItem(qItem);
|
|
174
|
+
if (nullableQrItem) {
|
|
175
|
+
answeredQrItem.item = nullableQrItem.item;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<Collapse key={nanoId} timeout={200}>
|
|
180
|
+
<RepeatGroupItem
|
|
181
|
+
qItem={qItem}
|
|
182
|
+
repeatGroupIndex={index}
|
|
183
|
+
answeredQrItem={answeredQrItem}
|
|
184
|
+
nullableQrItem={nullableQrItem}
|
|
185
|
+
numOfRepeatGroups={repeatGroups.length}
|
|
186
|
+
groupCardElevation={groupCardElevation + 1}
|
|
187
|
+
parentIsReadOnly={parentIsReadOnly}
|
|
188
|
+
onDeleteItem={() => onDeleteItem(index)}
|
|
189
|
+
onQrItemChange={(newQrItem) => onAnswerChange(newQrItem, index)}
|
|
190
|
+
/>
|
|
191
|
+
</Collapse>
|
|
192
|
+
);
|
|
193
|
+
})}
|
|
194
|
+
</TransitionGroup>
|
|
195
|
+
|
|
196
|
+
<AddItemButton repeatGroups={repeatGroups} readOnly={readOnly} onAddItem={onAddItem} />
|
|
197
|
+
</Card>
|
|
198
|
+
</QGroupContainerBox>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export default RepeatGroupView;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import React, { useCallback } from 'react';
|
|
18
|
+
import React, { useCallback, useMemo } from 'react';
|
|
19
19
|
import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
|
|
20
20
|
import type {
|
|
21
21
|
PropsWithIsRepeatedAttribute,
|
|
@@ -30,6 +30,9 @@ import SingleItemSwitcher from './SingleItemSwitcher';
|
|
|
30
30
|
import useHidden from '../../../hooks/useHidden';
|
|
31
31
|
import useReadOnly from '../../../hooks/useReadOnly';
|
|
32
32
|
import SingleNestedItems from './SingleNestedItems';
|
|
33
|
+
import { GroupCard } from '../GroupItem/GroupItem.styles';
|
|
34
|
+
import { QGroupContainerBox } from '../../Box.styles';
|
|
35
|
+
import { shouldRenderNestedItems } from '../../../utils/itemControl';
|
|
33
36
|
|
|
34
37
|
interface SingleItemProps
|
|
35
38
|
extends PropsWithQrItemChangeHandler,
|
|
@@ -97,7 +100,10 @@ function SingleItem(props: SingleItemProps) {
|
|
|
97
100
|
[qrItem, onQrItemChange]
|
|
98
101
|
);
|
|
99
102
|
|
|
100
|
-
const qItemHasNestedItems =
|
|
103
|
+
const qItemHasNestedItems = useMemo(
|
|
104
|
+
() => !!qItem.item && qItem.item.length > 0 && shouldRenderNestedItems(qItem),
|
|
105
|
+
[qItem]
|
|
106
|
+
);
|
|
101
107
|
|
|
102
108
|
const readOnly = useReadOnly(qItem, parentIsReadOnly);
|
|
103
109
|
const itemIsHidden = useHidden(qItem, parentRepeatGroupIndex);
|
|
@@ -105,6 +111,38 @@ function SingleItem(props: SingleItemProps) {
|
|
|
105
111
|
return null;
|
|
106
112
|
}
|
|
107
113
|
|
|
114
|
+
if (qItemHasNestedItems) {
|
|
115
|
+
return (
|
|
116
|
+
<QGroupContainerBox
|
|
117
|
+
cardElevation={groupCardElevation}
|
|
118
|
+
isRepeated={isRepeated}
|
|
119
|
+
data-test="q-item-group-box">
|
|
120
|
+
<GroupCard elevation={groupCardElevation} isRepeated={isRepeated}>
|
|
121
|
+
<SingleItemSwitcher
|
|
122
|
+
qItem={qItem}
|
|
123
|
+
qrItem={qrItem}
|
|
124
|
+
isRepeated={isRepeated}
|
|
125
|
+
isTabled={isTabled}
|
|
126
|
+
showMinimalView={showMinimalView}
|
|
127
|
+
parentIsReadOnly={readOnly}
|
|
128
|
+
onQrItemChange={handleQrItemChange}
|
|
129
|
+
/>
|
|
130
|
+
{qItemHasNestedItems ? (
|
|
131
|
+
<>
|
|
132
|
+
<SingleNestedItems
|
|
133
|
+
qItem={qItem}
|
|
134
|
+
qrItem={qrItem}
|
|
135
|
+
groupCardElevation={groupCardElevation}
|
|
136
|
+
parentIsReadOnly={readOnly}
|
|
137
|
+
onQrItemChange={handleQrItemChangeWithNestedItems}
|
|
138
|
+
/>
|
|
139
|
+
</>
|
|
140
|
+
) : null}
|
|
141
|
+
</GroupCard>
|
|
142
|
+
</QGroupContainerBox>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
108
146
|
return (
|
|
109
147
|
<>
|
|
110
148
|
<SingleItemSwitcher
|
|
@@ -116,15 +154,6 @@ function SingleItem(props: SingleItemProps) {
|
|
|
116
154
|
parentIsReadOnly={readOnly}
|
|
117
155
|
onQrItemChange={handleQrItemChange}
|
|
118
156
|
/>
|
|
119
|
-
{qItemHasNestedItems ? (
|
|
120
|
-
<SingleNestedItems
|
|
121
|
-
qItem={qItem}
|
|
122
|
-
qrItem={qrItem}
|
|
123
|
-
groupCardElevation={groupCardElevation}
|
|
124
|
-
parentIsReadOnly={readOnly}
|
|
125
|
-
onQrItemChange={handleQrItemChangeWithNestedItems}
|
|
126
|
-
/>
|
|
127
|
-
) : null}
|
|
128
157
|
</>
|
|
129
158
|
);
|
|
130
159
|
}
|
|
@@ -25,6 +25,7 @@ import type {
|
|
|
25
25
|
PropsWithQrItemChangeHandler
|
|
26
26
|
} from '../../../interfaces/renderProps.interface';
|
|
27
27
|
import type { QrRepeatGroup } from '../../../interfaces/repeatGroup.interface';
|
|
28
|
+
import Box from '@mui/material/Box';
|
|
28
29
|
|
|
29
30
|
interface SingleNestedItemsProps
|
|
30
31
|
extends PropsWithQrItemChangeHandler,
|
|
@@ -63,27 +64,31 @@ function SingleNestedItems(props: SingleNestedItemsProps) {
|
|
|
63
64
|
const qrItemsByIndex = getQrItemsIndex(qItems, qrItems, qItemsIndexMap);
|
|
64
65
|
|
|
65
66
|
return (
|
|
66
|
-
|
|
67
|
-
{
|
|
68
|
-
|
|
67
|
+
<Box display="flex">
|
|
68
|
+
<Box ml={1.5} />
|
|
69
|
+
<Box flexGrow={1}>
|
|
70
|
+
{qItems.map((qItem: QuestionnaireItem, i) => {
|
|
71
|
+
const qrItemOrItems = qrItemsByIndex[i];
|
|
69
72
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
if (qItem.type === 'display') {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
return (
|
|
78
|
+
<GroupItemSwitcher
|
|
79
|
+
key={qItem.linkId}
|
|
80
|
+
qItem={qItem}
|
|
81
|
+
qrItemOrItems={qrItemOrItems}
|
|
82
|
+
groupCardElevation={groupCardElevation}
|
|
83
|
+
parentIsReadOnly={parentIsReadOnly}
|
|
84
|
+
onQrItemChange={handleQrItemChange}
|
|
85
|
+
onQrRepeatGroupChange={handleQrRepeatGroupChange}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
})}
|
|
89
|
+
</Box>
|
|
90
|
+
<Box mr={2.25}></Box>
|
|
91
|
+
</Box>
|
|
87
92
|
);
|
|
88
93
|
}
|
|
89
94
|
|
|
@@ -21,7 +21,6 @@ import Accordion from '@mui/material/Accordion';
|
|
|
21
21
|
import AccordionDetails from '@mui/material/AccordionDetails';
|
|
22
22
|
import AccordionSummary from '@mui/material/AccordionSummary';
|
|
23
23
|
import Box from '@mui/material/Box';
|
|
24
|
-
import Tooltip from '@mui/material/Tooltip';
|
|
25
24
|
import Typography from '@mui/material/Typography';
|
|
26
25
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
27
26
|
import { getContextDisplays } from '../../utils/tabs';
|
|
@@ -46,17 +45,16 @@ const FormBodySingleCollapsible = memo(function FormBodySingleCollapsible(
|
|
|
46
45
|
|
|
47
46
|
const collapsibleLabel = getShortText(qItem) ?? qItem.text ?? '';
|
|
48
47
|
|
|
48
|
+
const isExpanded = selectedIndex === index;
|
|
49
|
+
|
|
49
50
|
return (
|
|
50
51
|
<Accordion
|
|
51
|
-
expanded={
|
|
52
|
-
|
|
52
|
+
expanded={isExpanded}
|
|
53
|
+
slotProps={{
|
|
54
|
+
transition: { unmountOnExit: true, timeout: 250 }
|
|
55
|
+
}}
|
|
53
56
|
onChange={() => onToggleExpand(index)}>
|
|
54
|
-
<AccordionSummary
|
|
55
|
-
expandIcon={
|
|
56
|
-
<Tooltip title={'Expand'}>
|
|
57
|
-
<ExpandMoreIcon />
|
|
58
|
-
</Tooltip>
|
|
59
|
-
}>
|
|
57
|
+
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
|
60
58
|
<Box display="flex" alignItems="center" justifyContent="space-between" width="100%" mr={3}>
|
|
61
59
|
<Typography variant="subtitle2">{collapsibleLabel}</Typography>
|
|
62
60
|
<Box display="flex" columnGap={0.5}>
|