@ltht-react/table 2.0.185 → 2.0.186
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/README.md +15 -15
- package/package.json +8 -8
- package/src/atoms/questionnaire-withdrawn-table-cell.tsx +15 -15
- package/src/index.tsx +8 -8
- package/src/molecules/table-cell.tsx +111 -111
- package/src/molecules/table-component.tsx +123 -123
- package/src/molecules/table-header.tsx +38 -38
- package/src/molecules/table-methods.tsx +238 -238
- package/src/molecules/table-styled-components.tsx +249 -249
- package/src/molecules/table.tsx +166 -166
- package/src/molecules/useDimensionRef.tsx +37 -37
- package/src/molecules/useScrollRef.tsx +40 -40
- package/src/organisms/generic-table.tsx +34 -34
- package/src/organisms/questionnaire-table-methods.tsx +351 -351
- package/src/organisms/questionnaire-table.tsx +56 -56
|
@@ -1,351 +1,351 @@
|
|
|
1
|
-
import { CSSProperties } from 'react'
|
|
2
|
-
import { ActionMenuOption } from '@ltht-react/menu'
|
|
3
|
-
import {
|
|
4
|
-
Axis,
|
|
5
|
-
Maybe,
|
|
6
|
-
Questionnaire,
|
|
7
|
-
QuestionnaireItem,
|
|
8
|
-
QuestionnaireResponse,
|
|
9
|
-
QuestionnaireResponseItem,
|
|
10
|
-
QuestionnaireResponseItemAnswer,
|
|
11
|
-
QuestionnaireResponseStatus,
|
|
12
|
-
} from '@ltht-react/types'
|
|
13
|
-
import { EnsureMaybe, EnsureMaybeArray, partialDateTimeText } from '@ltht-react/utils'
|
|
14
|
-
import { getZIndex, TableDataWithPopUp } from '@ltht-react/styles'
|
|
15
|
-
import { DataEntity, Header, TableData } from '../molecules/table'
|
|
16
|
-
import { CellProps } from '../molecules/table-cell'
|
|
17
|
-
import QuestionnaireWithdrawnTableCell from '../atoms/questionnaire-withdrawn-table-cell'
|
|
18
|
-
|
|
19
|
-
const DEFAULT_VERTICAL_HEADER_CELL_STYLE: CSSProperties = {
|
|
20
|
-
maxWidth: '15rem',
|
|
21
|
-
textWrap: 'wrap',
|
|
22
|
-
textAlign: 'left',
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const withdrawnWrapper = (text: string): JSX.Element => <QuestionnaireWithdrawnTableCell text={text} />
|
|
26
|
-
|
|
27
|
-
const mapQuestionnaireDefinitionAndResponsesToTableData = (
|
|
28
|
-
definition: Questionnaire,
|
|
29
|
-
questionnaireResponses: QuestionnaireResponse[],
|
|
30
|
-
axis: Axis,
|
|
31
|
-
adminActions?: AdminActionsForQuestionnaire[]
|
|
32
|
-
): TableData | undefined => {
|
|
33
|
-
const definitionItems = EnsureMaybeArray<QuestionnaireItem>(
|
|
34
|
-
EnsureMaybe<Maybe<QuestionnaireItem>[]>(definition.item, [])
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
if (definitionItems.length === 0) {
|
|
38
|
-
return undefined
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (axis === 'y') {
|
|
42
|
-
return mapQuestionnaireObjectsToVerticalTableData(definitionItems, questionnaireResponses, adminActions)
|
|
43
|
-
}
|
|
44
|
-
return mapQuestionnaireObjectsToHorizontalTableData(definitionItems, questionnaireResponses, adminActions)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const mapQuestionnaireObjectsToHorizontalTableData = (
|
|
48
|
-
definitionItems: Array<QuestionnaireItem>,
|
|
49
|
-
records: QuestionnaireResponse[],
|
|
50
|
-
adminActions?: AdminActionsForQuestionnaire[]
|
|
51
|
-
): TableData => {
|
|
52
|
-
const tableData: TableData = {
|
|
53
|
-
headers: [
|
|
54
|
-
{
|
|
55
|
-
id: 'date',
|
|
56
|
-
type: 'accessor',
|
|
57
|
-
cellProps: { text: 'Record Date' },
|
|
58
|
-
},
|
|
59
|
-
...recursivelyMapQuestionnaireItemsIntoHeaders(definitionItems),
|
|
60
|
-
],
|
|
61
|
-
rows: mapQuestionnaireResponsesIntoDataEntities(records, adminActions),
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (adminActions) {
|
|
65
|
-
tableData.headers.splice(1, 0, {
|
|
66
|
-
id: 'adminactions',
|
|
67
|
-
type: 'accessor',
|
|
68
|
-
cellProps: { text: 'Actions' },
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
return tableData
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const recursivelyMapQuestionnaireItemsIntoHeaders = (questionnaireItems: QuestionnaireItem[]): Header[] =>
|
|
75
|
-
questionnaireItems.map((questionnaireItem) => {
|
|
76
|
-
const subItems = EnsureMaybeArray<QuestionnaireItem>(questionnaireItem.item ?? [])
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
id: questionnaireItem?.linkId ?? '',
|
|
80
|
-
type: subItems.length > 0 ? 'group' : 'accessor',
|
|
81
|
-
cellProps: { text: questionnaireItem?.text ?? '' },
|
|
82
|
-
subHeaders: recursivelyMapQuestionnaireItemsIntoHeaders(subItems),
|
|
83
|
-
}
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
const mapQuestionnaireResponsesIntoDataEntities = (
|
|
87
|
-
records: QuestionnaireResponse[],
|
|
88
|
-
adminActions?: AdminActionsForQuestionnaire[]
|
|
89
|
-
): DataEntity[] =>
|
|
90
|
-
records
|
|
91
|
-
.filter((record) => !!record.item)
|
|
92
|
-
.map((record) => {
|
|
93
|
-
let dataEntity: DataEntity = {}
|
|
94
|
-
|
|
95
|
-
dataEntity.date = {
|
|
96
|
-
customComponentOverride:
|
|
97
|
-
record.status === QuestionnaireResponseStatus.EnteredInError
|
|
98
|
-
? withdrawnWrapper(partialDateTimeText(record.authored))
|
|
99
|
-
: undefined,
|
|
100
|
-
text: partialDateTimeText(record.authored),
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (adminActions) {
|
|
104
|
-
const adminActionsForThisDataEntity = adminActions.find(
|
|
105
|
-
(actionForForm) => actionForForm.questionnaire === record.id
|
|
106
|
-
)
|
|
107
|
-
if (adminActionsForThisDataEntity) {
|
|
108
|
-
dataEntity.adminactions = {
|
|
109
|
-
id: record.id,
|
|
110
|
-
adminActions: adminActionsForThisDataEntity.adminActions,
|
|
111
|
-
parentStyle: { zIndex: getZIndex(TableDataWithPopUp) },
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
record.item
|
|
116
|
-
?.filter((item) => item?.linkId && item?.answer)
|
|
117
|
-
.forEach((item) => {
|
|
118
|
-
const linkId = EnsureMaybe<string>(item?.linkId)
|
|
119
|
-
const answer = EnsureMaybe<QuestionnaireResponseItemAnswer>(item?.answer?.find((answer) => !!answer))
|
|
120
|
-
|
|
121
|
-
dataEntity[linkId] = createCellPropsForAnswer(
|
|
122
|
-
answer,
|
|
123
|
-
false,
|
|
124
|
-
record.status === QuestionnaireResponseStatus.EnteredInError
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
if (answer.item) {
|
|
128
|
-
dataEntity = recursivelyMapResponseItemsOntoData(
|
|
129
|
-
EnsureMaybeArray<QuestionnaireResponseItem>(answer.item),
|
|
130
|
-
dataEntity,
|
|
131
|
-
record.status
|
|
132
|
-
)
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
return dataEntity
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
const recursivelyMapResponseItemsOntoData = (
|
|
140
|
-
items: QuestionnaireResponseItem[],
|
|
141
|
-
dataEntity: DataEntity,
|
|
142
|
-
status: QuestionnaireResponseStatus
|
|
143
|
-
): DataEntity => {
|
|
144
|
-
let updatedDataEntity = { ...dataEntity }
|
|
145
|
-
items.forEach((item) => {
|
|
146
|
-
const firstAnswer = item.answer ? item.answer[0] : undefined
|
|
147
|
-
|
|
148
|
-
if (item.linkId && firstAnswer) {
|
|
149
|
-
const props = createCellPropsForAnswer(firstAnswer, false, status === QuestionnaireResponseStatus.EnteredInError)
|
|
150
|
-
updatedDataEntity[item.linkId] = {
|
|
151
|
-
customComponentOverride: props.customComponentOverride,
|
|
152
|
-
text: props.text,
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (firstAnswer.item) {
|
|
156
|
-
updatedDataEntity = recursivelyMapResponseItemsOntoData(
|
|
157
|
-
EnsureMaybeArray<QuestionnaireResponseItem>(firstAnswer.item),
|
|
158
|
-
updatedDataEntity,
|
|
159
|
-
status
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
})
|
|
164
|
-
return updatedDataEntity
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const mapQuestionnaireObjectsToVerticalTableData = (
|
|
168
|
-
definitionItems: Array<QuestionnaireItem>,
|
|
169
|
-
records: QuestionnaireResponse[],
|
|
170
|
-
adminActions?: AdminActionsForQuestionnaire[]
|
|
171
|
-
): TableData => ({
|
|
172
|
-
headers: [
|
|
173
|
-
{
|
|
174
|
-
id: 'property',
|
|
175
|
-
type: 'accessor',
|
|
176
|
-
cellProps: { text: '' },
|
|
177
|
-
},
|
|
178
|
-
...records.map(
|
|
179
|
-
(record): Header => ({
|
|
180
|
-
id: record?.id ?? '',
|
|
181
|
-
type: 'accessor',
|
|
182
|
-
cellProps: {
|
|
183
|
-
customComponentOverride:
|
|
184
|
-
record.status === QuestionnaireResponseStatus.EnteredInError
|
|
185
|
-
? withdrawnWrapper(partialDateTimeText(record.authored) ?? '')
|
|
186
|
-
: undefined,
|
|
187
|
-
text: partialDateTimeText(record.authored) ?? '',
|
|
188
|
-
},
|
|
189
|
-
})
|
|
190
|
-
),
|
|
191
|
-
],
|
|
192
|
-
rows: buildVerticalCellRows(definitionItems, records, adminActions),
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
const buildVerticalCellRows = (
|
|
196
|
-
definitionItems: QuestionnaireItem[],
|
|
197
|
-
records: QuestionnaireResponse[],
|
|
198
|
-
adminActions?: AdminActionsForQuestionnaire[]
|
|
199
|
-
): DataEntity[] => {
|
|
200
|
-
const dataEntities = definitionItems.map((item) => {
|
|
201
|
-
let dataEntity: DataEntity = {}
|
|
202
|
-
|
|
203
|
-
dataEntity = buildVerticalCellRowsRecursive(EnsureMaybeArray<QuestionnaireItem>([item]), records, dataEntity)
|
|
204
|
-
|
|
205
|
-
return dataEntity
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
if (adminActions) {
|
|
209
|
-
const actionsDataEntity: DataEntity = {}
|
|
210
|
-
actionsDataEntity.property = { text: 'Actions', parentStyle: DEFAULT_VERTICAL_HEADER_CELL_STYLE }
|
|
211
|
-
|
|
212
|
-
records.forEach((record) => {
|
|
213
|
-
const adminActionsForThisDataEntity = adminActions.find(
|
|
214
|
-
(actionForForm) => actionForForm.questionnaire === record.id
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
if (adminActionsForThisDataEntity) {
|
|
218
|
-
actionsDataEntity[record.id] = {
|
|
219
|
-
id: record.id,
|
|
220
|
-
adminActions: adminActionsForThisDataEntity.adminActions,
|
|
221
|
-
parentStyle: { zIndex: getZIndex(TableDataWithPopUp) },
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
return [actionsDataEntity].concat(dataEntities)
|
|
227
|
-
}
|
|
228
|
-
return dataEntities
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const buildVerticalCellRowsRecursive = (
|
|
232
|
-
definitionItems: QuestionnaireItem[],
|
|
233
|
-
records: QuestionnaireResponse[],
|
|
234
|
-
dataEntity: DataEntity
|
|
235
|
-
): DataEntity => {
|
|
236
|
-
let updatedDataEntity = { ...dataEntity }
|
|
237
|
-
definitionItems.forEach((definitionItem) => {
|
|
238
|
-
const containsChildItems = !!definitionItem.item && definitionItem.item.length > 0
|
|
239
|
-
|
|
240
|
-
updatedDataEntity.property = {
|
|
241
|
-
text: definitionItem.text ?? '',
|
|
242
|
-
parentStyle: {
|
|
243
|
-
...DEFAULT_VERTICAL_HEADER_CELL_STYLE,
|
|
244
|
-
fontWeight: containsChildItems ? 'bold' : 'normal',
|
|
245
|
-
},
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (definitionItem.linkId) {
|
|
249
|
-
records.forEach((record) => {
|
|
250
|
-
updatedDataEntity = getRecordItemByLinkId(
|
|
251
|
-
EnsureMaybeArray<QuestionnaireResponseItem>(record.item ?? []),
|
|
252
|
-
EnsureMaybe<string>(definitionItem.linkId),
|
|
253
|
-
updatedDataEntity,
|
|
254
|
-
record.id,
|
|
255
|
-
record.status
|
|
256
|
-
)
|
|
257
|
-
})
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (definitionItem.item && definitionItem.item.length > 0) {
|
|
261
|
-
updatedDataEntity.subRows = buildVerticalCellRows(
|
|
262
|
-
EnsureMaybeArray<QuestionnaireItem>(definitionItem.item),
|
|
263
|
-
records
|
|
264
|
-
)
|
|
265
|
-
}
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
return updatedDataEntity
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const getRecordItemByLinkId = (
|
|
272
|
-
recordItems: QuestionnaireResponseItem[],
|
|
273
|
-
linkId: string,
|
|
274
|
-
dataEntity: DataEntity,
|
|
275
|
-
recordId: string,
|
|
276
|
-
status: QuestionnaireResponseStatus
|
|
277
|
-
) => {
|
|
278
|
-
let updatedDataEntity = { ...dataEntity }
|
|
279
|
-
recordItems.forEach((recordItem) => {
|
|
280
|
-
const recordItemAnswer =
|
|
281
|
-
recordItem.answer && recordItem.answer.length > 0 ? EnsureMaybe(recordItem.answer[0]) : undefined
|
|
282
|
-
|
|
283
|
-
if (recordItemAnswer) {
|
|
284
|
-
if (recordItem?.linkId && recordItem?.linkId === linkId) {
|
|
285
|
-
updatedDataEntity[recordId] = createCellPropsForAnswer(
|
|
286
|
-
recordItemAnswer,
|
|
287
|
-
true,
|
|
288
|
-
status === QuestionnaireResponseStatus.EnteredInError
|
|
289
|
-
)
|
|
290
|
-
}
|
|
291
|
-
if (recordItemAnswer.item && recordItemAnswer.item.length > 0) {
|
|
292
|
-
updatedDataEntity = getRecordItemByLinkId(
|
|
293
|
-
EnsureMaybeArray<QuestionnaireResponseItem>(recordItemAnswer.item),
|
|
294
|
-
linkId,
|
|
295
|
-
updatedDataEntity,
|
|
296
|
-
recordId,
|
|
297
|
-
status
|
|
298
|
-
)
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
})
|
|
302
|
-
|
|
303
|
-
return updatedDataEntity
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const createCellPropsForAnswer = (
|
|
307
|
-
answer: QuestionnaireResponseItemAnswer,
|
|
308
|
-
shouldRenderCheckbox: boolean,
|
|
309
|
-
isEnteredInError: boolean
|
|
310
|
-
): CellProps => {
|
|
311
|
-
if (answer.valueString) {
|
|
312
|
-
if (shouldRenderCheckbox && answer.valueString === 'CHECKBOX') {
|
|
313
|
-
return {
|
|
314
|
-
iconProps: { type: 'checkbox', size: 'medium' },
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return {
|
|
318
|
-
customComponentOverride: isEnteredInError ? withdrawnWrapper(answer.valueString) : undefined,
|
|
319
|
-
text: answer.valueString,
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
if (answer.valueBoolean != null) {
|
|
323
|
-
const parsedBoolean = answer.valueBoolean ? 'Yes' : 'No'
|
|
324
|
-
return {
|
|
325
|
-
customComponentOverride: isEnteredInError ? withdrawnWrapper(parsedBoolean) : undefined,
|
|
326
|
-
text: parsedBoolean,
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
if (answer.valueInteger != null) {
|
|
330
|
-
return {
|
|
331
|
-
customComponentOverride: isEnteredInError ? withdrawnWrapper(answer.valueInteger.toString()) : undefined,
|
|
332
|
-
text: answer.valueInteger.toString(),
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
if (answer.valueDecimal != null) {
|
|
336
|
-
return {
|
|
337
|
-
customComponentOverride: isEnteredInError ? withdrawnWrapper(answer.valueDecimal.toString()) : undefined,
|
|
338
|
-
text: answer.valueDecimal.toString(),
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
return {
|
|
342
|
-
text: '',
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
export interface AdminActionsForQuestionnaire {
|
|
347
|
-
questionnaire: string
|
|
348
|
-
adminActions: ActionMenuOption[]
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export default mapQuestionnaireDefinitionAndResponsesToTableData
|
|
1
|
+
import { CSSProperties } from 'react'
|
|
2
|
+
import { ActionMenuOption } from '@ltht-react/menu'
|
|
3
|
+
import {
|
|
4
|
+
Axis,
|
|
5
|
+
Maybe,
|
|
6
|
+
Questionnaire,
|
|
7
|
+
QuestionnaireItem,
|
|
8
|
+
QuestionnaireResponse,
|
|
9
|
+
QuestionnaireResponseItem,
|
|
10
|
+
QuestionnaireResponseItemAnswer,
|
|
11
|
+
QuestionnaireResponseStatus,
|
|
12
|
+
} from '@ltht-react/types'
|
|
13
|
+
import { EnsureMaybe, EnsureMaybeArray, partialDateTimeText } from '@ltht-react/utils'
|
|
14
|
+
import { getZIndex, TableDataWithPopUp } from '@ltht-react/styles'
|
|
15
|
+
import { DataEntity, Header, TableData } from '../molecules/table'
|
|
16
|
+
import { CellProps } from '../molecules/table-cell'
|
|
17
|
+
import QuestionnaireWithdrawnTableCell from '../atoms/questionnaire-withdrawn-table-cell'
|
|
18
|
+
|
|
19
|
+
const DEFAULT_VERTICAL_HEADER_CELL_STYLE: CSSProperties = {
|
|
20
|
+
maxWidth: '15rem',
|
|
21
|
+
textWrap: 'wrap',
|
|
22
|
+
textAlign: 'left',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const withdrawnWrapper = (text: string): JSX.Element => <QuestionnaireWithdrawnTableCell text={text} />
|
|
26
|
+
|
|
27
|
+
const mapQuestionnaireDefinitionAndResponsesToTableData = (
|
|
28
|
+
definition: Questionnaire,
|
|
29
|
+
questionnaireResponses: QuestionnaireResponse[],
|
|
30
|
+
axis: Axis,
|
|
31
|
+
adminActions?: AdminActionsForQuestionnaire[]
|
|
32
|
+
): TableData | undefined => {
|
|
33
|
+
const definitionItems = EnsureMaybeArray<QuestionnaireItem>(
|
|
34
|
+
EnsureMaybe<Maybe<QuestionnaireItem>[]>(definition.item, [])
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if (definitionItems.length === 0) {
|
|
38
|
+
return undefined
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (axis === 'y') {
|
|
42
|
+
return mapQuestionnaireObjectsToVerticalTableData(definitionItems, questionnaireResponses, adminActions)
|
|
43
|
+
}
|
|
44
|
+
return mapQuestionnaireObjectsToHorizontalTableData(definitionItems, questionnaireResponses, adminActions)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const mapQuestionnaireObjectsToHorizontalTableData = (
|
|
48
|
+
definitionItems: Array<QuestionnaireItem>,
|
|
49
|
+
records: QuestionnaireResponse[],
|
|
50
|
+
adminActions?: AdminActionsForQuestionnaire[]
|
|
51
|
+
): TableData => {
|
|
52
|
+
const tableData: TableData = {
|
|
53
|
+
headers: [
|
|
54
|
+
{
|
|
55
|
+
id: 'date',
|
|
56
|
+
type: 'accessor',
|
|
57
|
+
cellProps: { text: 'Record Date' },
|
|
58
|
+
},
|
|
59
|
+
...recursivelyMapQuestionnaireItemsIntoHeaders(definitionItems),
|
|
60
|
+
],
|
|
61
|
+
rows: mapQuestionnaireResponsesIntoDataEntities(records, adminActions),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (adminActions) {
|
|
65
|
+
tableData.headers.splice(1, 0, {
|
|
66
|
+
id: 'adminactions',
|
|
67
|
+
type: 'accessor',
|
|
68
|
+
cellProps: { text: 'Actions' },
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
return tableData
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const recursivelyMapQuestionnaireItemsIntoHeaders = (questionnaireItems: QuestionnaireItem[]): Header[] =>
|
|
75
|
+
questionnaireItems.map((questionnaireItem) => {
|
|
76
|
+
const subItems = EnsureMaybeArray<QuestionnaireItem>(questionnaireItem.item ?? [])
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
id: questionnaireItem?.linkId ?? '',
|
|
80
|
+
type: subItems.length > 0 ? 'group' : 'accessor',
|
|
81
|
+
cellProps: { text: questionnaireItem?.text ?? '' },
|
|
82
|
+
subHeaders: recursivelyMapQuestionnaireItemsIntoHeaders(subItems),
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const mapQuestionnaireResponsesIntoDataEntities = (
|
|
87
|
+
records: QuestionnaireResponse[],
|
|
88
|
+
adminActions?: AdminActionsForQuestionnaire[]
|
|
89
|
+
): DataEntity[] =>
|
|
90
|
+
records
|
|
91
|
+
.filter((record) => !!record.item)
|
|
92
|
+
.map((record) => {
|
|
93
|
+
let dataEntity: DataEntity = {}
|
|
94
|
+
|
|
95
|
+
dataEntity.date = {
|
|
96
|
+
customComponentOverride:
|
|
97
|
+
record.status === QuestionnaireResponseStatus.EnteredInError
|
|
98
|
+
? withdrawnWrapper(partialDateTimeText(record.authored))
|
|
99
|
+
: undefined,
|
|
100
|
+
text: partialDateTimeText(record.authored),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (adminActions) {
|
|
104
|
+
const adminActionsForThisDataEntity = adminActions.find(
|
|
105
|
+
(actionForForm) => actionForForm.questionnaire === record.id
|
|
106
|
+
)
|
|
107
|
+
if (adminActionsForThisDataEntity) {
|
|
108
|
+
dataEntity.adminactions = {
|
|
109
|
+
id: record.id,
|
|
110
|
+
adminActions: adminActionsForThisDataEntity.adminActions,
|
|
111
|
+
parentStyle: { zIndex: getZIndex(TableDataWithPopUp) },
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
record.item
|
|
116
|
+
?.filter((item) => item?.linkId && item?.answer)
|
|
117
|
+
.forEach((item) => {
|
|
118
|
+
const linkId = EnsureMaybe<string>(item?.linkId)
|
|
119
|
+
const answer = EnsureMaybe<QuestionnaireResponseItemAnswer>(item?.answer?.find((answer) => !!answer))
|
|
120
|
+
|
|
121
|
+
dataEntity[linkId] = createCellPropsForAnswer(
|
|
122
|
+
answer,
|
|
123
|
+
false,
|
|
124
|
+
record.status === QuestionnaireResponseStatus.EnteredInError
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
if (answer.item) {
|
|
128
|
+
dataEntity = recursivelyMapResponseItemsOntoData(
|
|
129
|
+
EnsureMaybeArray<QuestionnaireResponseItem>(answer.item),
|
|
130
|
+
dataEntity,
|
|
131
|
+
record.status
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
return dataEntity
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const recursivelyMapResponseItemsOntoData = (
|
|
140
|
+
items: QuestionnaireResponseItem[],
|
|
141
|
+
dataEntity: DataEntity,
|
|
142
|
+
status: QuestionnaireResponseStatus
|
|
143
|
+
): DataEntity => {
|
|
144
|
+
let updatedDataEntity = { ...dataEntity }
|
|
145
|
+
items.forEach((item) => {
|
|
146
|
+
const firstAnswer = item.answer ? item.answer[0] : undefined
|
|
147
|
+
|
|
148
|
+
if (item.linkId && firstAnswer) {
|
|
149
|
+
const props = createCellPropsForAnswer(firstAnswer, false, status === QuestionnaireResponseStatus.EnteredInError)
|
|
150
|
+
updatedDataEntity[item.linkId] = {
|
|
151
|
+
customComponentOverride: props.customComponentOverride,
|
|
152
|
+
text: props.text,
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (firstAnswer.item) {
|
|
156
|
+
updatedDataEntity = recursivelyMapResponseItemsOntoData(
|
|
157
|
+
EnsureMaybeArray<QuestionnaireResponseItem>(firstAnswer.item),
|
|
158
|
+
updatedDataEntity,
|
|
159
|
+
status
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
return updatedDataEntity
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const mapQuestionnaireObjectsToVerticalTableData = (
|
|
168
|
+
definitionItems: Array<QuestionnaireItem>,
|
|
169
|
+
records: QuestionnaireResponse[],
|
|
170
|
+
adminActions?: AdminActionsForQuestionnaire[]
|
|
171
|
+
): TableData => ({
|
|
172
|
+
headers: [
|
|
173
|
+
{
|
|
174
|
+
id: 'property',
|
|
175
|
+
type: 'accessor',
|
|
176
|
+
cellProps: { text: '' },
|
|
177
|
+
},
|
|
178
|
+
...records.map(
|
|
179
|
+
(record): Header => ({
|
|
180
|
+
id: record?.id ?? '',
|
|
181
|
+
type: 'accessor',
|
|
182
|
+
cellProps: {
|
|
183
|
+
customComponentOverride:
|
|
184
|
+
record.status === QuestionnaireResponseStatus.EnteredInError
|
|
185
|
+
? withdrawnWrapper(partialDateTimeText(record.authored) ?? '')
|
|
186
|
+
: undefined,
|
|
187
|
+
text: partialDateTimeText(record.authored) ?? '',
|
|
188
|
+
},
|
|
189
|
+
})
|
|
190
|
+
),
|
|
191
|
+
],
|
|
192
|
+
rows: buildVerticalCellRows(definitionItems, records, adminActions),
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
const buildVerticalCellRows = (
|
|
196
|
+
definitionItems: QuestionnaireItem[],
|
|
197
|
+
records: QuestionnaireResponse[],
|
|
198
|
+
adminActions?: AdminActionsForQuestionnaire[]
|
|
199
|
+
): DataEntity[] => {
|
|
200
|
+
const dataEntities = definitionItems.map((item) => {
|
|
201
|
+
let dataEntity: DataEntity = {}
|
|
202
|
+
|
|
203
|
+
dataEntity = buildVerticalCellRowsRecursive(EnsureMaybeArray<QuestionnaireItem>([item]), records, dataEntity)
|
|
204
|
+
|
|
205
|
+
return dataEntity
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
if (adminActions) {
|
|
209
|
+
const actionsDataEntity: DataEntity = {}
|
|
210
|
+
actionsDataEntity.property = { text: 'Actions', parentStyle: DEFAULT_VERTICAL_HEADER_CELL_STYLE }
|
|
211
|
+
|
|
212
|
+
records.forEach((record) => {
|
|
213
|
+
const adminActionsForThisDataEntity = adminActions.find(
|
|
214
|
+
(actionForForm) => actionForForm.questionnaire === record.id
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
if (adminActionsForThisDataEntity) {
|
|
218
|
+
actionsDataEntity[record.id] = {
|
|
219
|
+
id: record.id,
|
|
220
|
+
adminActions: adminActionsForThisDataEntity.adminActions,
|
|
221
|
+
parentStyle: { zIndex: getZIndex(TableDataWithPopUp) },
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
return [actionsDataEntity].concat(dataEntities)
|
|
227
|
+
}
|
|
228
|
+
return dataEntities
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const buildVerticalCellRowsRecursive = (
|
|
232
|
+
definitionItems: QuestionnaireItem[],
|
|
233
|
+
records: QuestionnaireResponse[],
|
|
234
|
+
dataEntity: DataEntity
|
|
235
|
+
): DataEntity => {
|
|
236
|
+
let updatedDataEntity = { ...dataEntity }
|
|
237
|
+
definitionItems.forEach((definitionItem) => {
|
|
238
|
+
const containsChildItems = !!definitionItem.item && definitionItem.item.length > 0
|
|
239
|
+
|
|
240
|
+
updatedDataEntity.property = {
|
|
241
|
+
text: definitionItem.text ?? '',
|
|
242
|
+
parentStyle: {
|
|
243
|
+
...DEFAULT_VERTICAL_HEADER_CELL_STYLE,
|
|
244
|
+
fontWeight: containsChildItems ? 'bold' : 'normal',
|
|
245
|
+
},
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (definitionItem.linkId) {
|
|
249
|
+
records.forEach((record) => {
|
|
250
|
+
updatedDataEntity = getRecordItemByLinkId(
|
|
251
|
+
EnsureMaybeArray<QuestionnaireResponseItem>(record.item ?? []),
|
|
252
|
+
EnsureMaybe<string>(definitionItem.linkId),
|
|
253
|
+
updatedDataEntity,
|
|
254
|
+
record.id,
|
|
255
|
+
record.status
|
|
256
|
+
)
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (definitionItem.item && definitionItem.item.length > 0) {
|
|
261
|
+
updatedDataEntity.subRows = buildVerticalCellRows(
|
|
262
|
+
EnsureMaybeArray<QuestionnaireItem>(definitionItem.item),
|
|
263
|
+
records
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
return updatedDataEntity
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const getRecordItemByLinkId = (
|
|
272
|
+
recordItems: QuestionnaireResponseItem[],
|
|
273
|
+
linkId: string,
|
|
274
|
+
dataEntity: DataEntity,
|
|
275
|
+
recordId: string,
|
|
276
|
+
status: QuestionnaireResponseStatus
|
|
277
|
+
) => {
|
|
278
|
+
let updatedDataEntity = { ...dataEntity }
|
|
279
|
+
recordItems.forEach((recordItem) => {
|
|
280
|
+
const recordItemAnswer =
|
|
281
|
+
recordItem.answer && recordItem.answer.length > 0 ? EnsureMaybe(recordItem.answer[0]) : undefined
|
|
282
|
+
|
|
283
|
+
if (recordItemAnswer) {
|
|
284
|
+
if (recordItem?.linkId && recordItem?.linkId === linkId) {
|
|
285
|
+
updatedDataEntity[recordId] = createCellPropsForAnswer(
|
|
286
|
+
recordItemAnswer,
|
|
287
|
+
true,
|
|
288
|
+
status === QuestionnaireResponseStatus.EnteredInError
|
|
289
|
+
)
|
|
290
|
+
}
|
|
291
|
+
if (recordItemAnswer.item && recordItemAnswer.item.length > 0) {
|
|
292
|
+
updatedDataEntity = getRecordItemByLinkId(
|
|
293
|
+
EnsureMaybeArray<QuestionnaireResponseItem>(recordItemAnswer.item),
|
|
294
|
+
linkId,
|
|
295
|
+
updatedDataEntity,
|
|
296
|
+
recordId,
|
|
297
|
+
status
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
return updatedDataEntity
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const createCellPropsForAnswer = (
|
|
307
|
+
answer: QuestionnaireResponseItemAnswer,
|
|
308
|
+
shouldRenderCheckbox: boolean,
|
|
309
|
+
isEnteredInError: boolean
|
|
310
|
+
): CellProps => {
|
|
311
|
+
if (answer.valueString) {
|
|
312
|
+
if (shouldRenderCheckbox && answer.valueString === 'CHECKBOX') {
|
|
313
|
+
return {
|
|
314
|
+
iconProps: { type: 'checkbox', size: 'medium' },
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return {
|
|
318
|
+
customComponentOverride: isEnteredInError ? withdrawnWrapper(answer.valueString) : undefined,
|
|
319
|
+
text: answer.valueString,
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (answer.valueBoolean != null) {
|
|
323
|
+
const parsedBoolean = answer.valueBoolean ? 'Yes' : 'No'
|
|
324
|
+
return {
|
|
325
|
+
customComponentOverride: isEnteredInError ? withdrawnWrapper(parsedBoolean) : undefined,
|
|
326
|
+
text: parsedBoolean,
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (answer.valueInteger != null) {
|
|
330
|
+
return {
|
|
331
|
+
customComponentOverride: isEnteredInError ? withdrawnWrapper(answer.valueInteger.toString()) : undefined,
|
|
332
|
+
text: answer.valueInteger.toString(),
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (answer.valueDecimal != null) {
|
|
336
|
+
return {
|
|
337
|
+
customComponentOverride: isEnteredInError ? withdrawnWrapper(answer.valueDecimal.toString()) : undefined,
|
|
338
|
+
text: answer.valueDecimal.toString(),
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
text: '',
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export interface AdminActionsForQuestionnaire {
|
|
347
|
+
questionnaire: string
|
|
348
|
+
adminActions: ActionMenuOption[]
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export default mapQuestionnaireDefinitionAndResponsesToTableData
|