@cdc/dashboard 4.25.6-2 → 4.25.7
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/dist/cdcdashboard.js +63503 -41005
- package/package.json +9 -9
- package/src/CdcDashboardComponent.tsx +11 -8
- package/src/components/Header/Header.tsx +2 -2
- package/src/components/VisualizationRow.tsx +324 -324
- package/src/helpers/getVizConfig.ts +1 -0
- package/src/helpers/getVizRowColumnLocator.ts +10 -10
- package/src/helpers/reloadURLHelpers.ts +124 -124
- package/src/store/dashboard.reducer.ts +288 -288
- package/src/types/ConfigRow.ts +19 -19
- package/src/types/Dashboard.ts +11 -11
- package/examples/private/DEV-10120.json +0 -1294
- package/examples/private/DEV-10527.json +0 -845
- package/examples/private/DEV-10586.json +0 -54319
- package/examples/private/DEV-10856.json +0 -54319
- package/examples/private/DEV-9199.json +0 -606
- package/examples/private/DEV-9644.json +0 -20092
- package/examples/private/DEV-9684.json +0 -2135
- package/examples/private/DEV-9932.json +0 -95
- package/examples/private/DEV-9989.json +0 -229
- package/examples/private/art-dashboard.json +0 -18174
- package/examples/private/art-scratch.json +0 -2406
- package/examples/private/bird-flu-2.json +0 -440
- package/examples/private/bird-flu.json +0 -413
- package/examples/private/crashing-sidebar.json +0 -975
- package/examples/private/d.json +0 -1561
- package/examples/private/dashboard-config-ehdi.json +0 -29915
- package/examples/private/dashboard-map-filter.json +0 -815
- package/examples/private/dashboard-margins.js +0 -15
- package/examples/private/dataset.json +0 -1452
- package/examples/private/dev-10856-2.json +0 -1348
- package/examples/private/ehdi-data.json +0 -29502
- package/examples/private/exposure-source-h5-data.csv +0 -26
- package/examples/private/fatal-data.csv +0 -3159
- package/examples/private/feelings.json +0 -1
- package/examples/private/gaza-issue.json +0 -1214
- package/examples/private/josh.json +0 -6175
- package/examples/private/map-issue.json +0 -628
- package/examples/private/markup.json +0 -115
- package/examples/private/mpox.json +0 -429
- package/examples/private/nhis.json +0 -1792
- package/examples/private/testing-pie.json +0 -436
- package/examples/private/workforce.json +0 -2041
|
@@ -1,324 +1,324 @@
|
|
|
1
|
-
import DataTableStandAlone from '@cdc/core/components/DataTable/DataTableStandAlone'
|
|
2
|
-
import React, { useContext, useEffect, useMemo, useState } from 'react'
|
|
3
|
-
import Toggle from './Toggle'
|
|
4
|
-
import _ from 'lodash'
|
|
5
|
-
import { ConfigRow } from '../types/ConfigRow'
|
|
6
|
-
import CdcDataBite from '@cdc/data-bite/src/CdcDataBite'
|
|
7
|
-
import CdcMap from '@cdc/map/src/CdcMapComponent'
|
|
8
|
-
import CdcWaffleChart from '@cdc/waffle-chart/src/CdcWaffleChart'
|
|
9
|
-
import CdcMarkupInclude from '@cdc/markup-include/src/CdcMarkupInclude'
|
|
10
|
-
import CdcFilteredText from '@cdc/filtered-text/src/CdcFilteredText'
|
|
11
|
-
import DashboardSharedFilters, { APIFilterDropdowns } from './DashboardFilters'
|
|
12
|
-
import { DashboardContext } from '../DashboardContext'
|
|
13
|
-
import { ViewPort } from '@cdc/core/types/ViewPort'
|
|
14
|
-
import { getVizConfig } from '../helpers/getVizConfig'
|
|
15
|
-
import { TableConfig } from '@cdc/core/components/DataTable/types/TableConfig'
|
|
16
|
-
import CollapsibleVisualizationRow from './CollapsibleVisualizationRow'
|
|
17
|
-
import { DashboardFilters } from '../types/DashboardFilters'
|
|
18
|
-
import { hasDashboardApplyBehavior } from '../helpers/hasDashboardApplyBehavior'
|
|
19
|
-
import CdcChart from '@cdc/chart/src/CdcChartComponent'
|
|
20
|
-
import ExpandCollapseButtons from './ExpandCollapseButtons'
|
|
21
|
-
import { ChartConfig } from '@cdc/chart/src/types/ChartConfig'
|
|
22
|
-
|
|
23
|
-
type VisualizationWrapperProps = {
|
|
24
|
-
allExpanded: boolean
|
|
25
|
-
children: React.ReactNode
|
|
26
|
-
currentViewport: ViewPort
|
|
27
|
-
groupName: string
|
|
28
|
-
className: string
|
|
29
|
-
collapsible?: boolean
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const VisualizationWrapper: React.FC<VisualizationWrapperProps> = ({
|
|
33
|
-
allExpanded,
|
|
34
|
-
currentViewport,
|
|
35
|
-
groupName,
|
|
36
|
-
collapsible,
|
|
37
|
-
className,
|
|
38
|
-
children
|
|
39
|
-
}) => {
|
|
40
|
-
return (
|
|
41
|
-
<div className={className}>
|
|
42
|
-
{collapsible ? (
|
|
43
|
-
<CollapsibleVisualizationRow allExpanded={allExpanded} groupName={groupName} currentViewport={currentViewport}>
|
|
44
|
-
{children}
|
|
45
|
-
</CollapsibleVisualizationRow>
|
|
46
|
-
) : (
|
|
47
|
-
<>
|
|
48
|
-
{groupName !== '' ? <h3>{groupName}</h3> : <></>}
|
|
49
|
-
{children}
|
|
50
|
-
</>
|
|
51
|
-
)}
|
|
52
|
-
</div>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
type VizRowProps = {
|
|
57
|
-
allExpanded: boolean
|
|
58
|
-
filteredDataOverride?: Object[]
|
|
59
|
-
groupName: string
|
|
60
|
-
row: ConfigRow
|
|
61
|
-
rowIndex: number
|
|
62
|
-
inNoDataState: boolean
|
|
63
|
-
setSharedFilter: Function
|
|
64
|
-
updateChildConfig: Function
|
|
65
|
-
apiFilterDropdowns: APIFilterDropdowns
|
|
66
|
-
currentViewport: ViewPort
|
|
67
|
-
isLastRow: boolean
|
|
68
|
-
setAllExpanded?: (expanded: boolean) => void
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const VisualizationRow: React.FC<VizRowProps> = ({
|
|
72
|
-
allExpanded,
|
|
73
|
-
filteredDataOverride,
|
|
74
|
-
groupName,
|
|
75
|
-
row,
|
|
76
|
-
rowIndex: index,
|
|
77
|
-
inNoDataState,
|
|
78
|
-
setSharedFilter,
|
|
79
|
-
updateChildConfig,
|
|
80
|
-
apiFilterDropdowns,
|
|
81
|
-
currentViewport,
|
|
82
|
-
isLastRow,
|
|
83
|
-
setAllExpanded
|
|
84
|
-
}) => {
|
|
85
|
-
const { config, filteredData: dashboardFilteredData, data: rawData } = useContext(DashboardContext)
|
|
86
|
-
const [toggledRow, setToggled] = React.useState<number>(0)
|
|
87
|
-
|
|
88
|
-
useEffect(() => {
|
|
89
|
-
if (row.toggle) setToggled(0)
|
|
90
|
-
}, [config.activeDashboard, index])
|
|
91
|
-
|
|
92
|
-
const show = useMemo(() => {
|
|
93
|
-
if (row.toggle) {
|
|
94
|
-
return row.columns.map((col, i) => i === toggledRow)
|
|
95
|
-
} else {
|
|
96
|
-
return row.columns.map((col, i) => true)
|
|
97
|
-
}
|
|
98
|
-
}, [config.activeDashboard, toggledRow])
|
|
99
|
-
|
|
100
|
-
const _data = dashboardFilteredData[index] || row.formattedData || []
|
|
101
|
-
const dataGroups =
|
|
102
|
-
row.multiVizColumn &&
|
|
103
|
-
_data.reduce((acc, dataRow) => {
|
|
104
|
-
const groupKey = dataRow[row.multiVizColumn]
|
|
105
|
-
if (!acc[groupKey]) acc[groupKey] = []
|
|
106
|
-
acc[groupKey].push(dataRow)
|
|
107
|
-
return acc
|
|
108
|
-
}, {})
|
|
109
|
-
|
|
110
|
-
const applyButtonNotClicked = (vizConfig: DashboardFilters): boolean => {
|
|
111
|
-
const dashboardFilters = Object.values(config.visualizations).filter(
|
|
112
|
-
v => v.type === 'dashboardFilters'
|
|
113
|
-
) as DashboardFilters[]
|
|
114
|
-
const applyFilters = dashboardFilters.filter(v => !v.autoLoad).flatMap(v => v.sharedFilterIndexes)
|
|
115
|
-
if (hasDashboardApplyBehavior(config.visualizations) && vizConfig.autoLoad) {
|
|
116
|
-
return applyFilters.some(index => {
|
|
117
|
-
const { queuedActive, active, subGrouping } = config.dashboard.sharedFilters[index]
|
|
118
|
-
if (!active && !queuedActive) return true
|
|
119
|
-
if (!queuedActive) return false
|
|
120
|
-
// for nested dropdowns
|
|
121
|
-
if (subGrouping) return queuedActive[0] !== active || queuedActive[1] !== subGrouping.active
|
|
122
|
-
// all other dropdowns
|
|
123
|
-
return queuedActive !== active
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
return false
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (dataGroups) {
|
|
130
|
-
return (
|
|
131
|
-
<React.Fragment key={`row__${index}`}>
|
|
132
|
-
{/* Expand/Collapse All */}
|
|
133
|
-
{!inNoDataState && row.expandCollapseAllButtons === true && (
|
|
134
|
-
<ExpandCollapseButtons setAllExpanded={setAllExpanded} />
|
|
135
|
-
)}
|
|
136
|
-
{Object.keys(dataGroups).map(groupName => {
|
|
137
|
-
const dataValue = dataGroups[groupName]
|
|
138
|
-
const _row = _.cloneDeep(row) // clone the row to avoid mutating the original row
|
|
139
|
-
_row.multiVizColumn = undefined // reset the multiVizColumn to avoid passing it to the child components
|
|
140
|
-
return (
|
|
141
|
-
<VisualizationRow
|
|
142
|
-
key={`row__${index}__${groupName}`}
|
|
143
|
-
allExpanded={allExpanded}
|
|
144
|
-
filteredDataOverride={dataValue}
|
|
145
|
-
groupName={groupName}
|
|
146
|
-
row={_row}
|
|
147
|
-
rowIndex={index}
|
|
148
|
-
setSharedFilter={setSharedFilter}
|
|
149
|
-
updateChildConfig={updateChildConfig}
|
|
150
|
-
apiFilterDropdowns={apiFilterDropdowns}
|
|
151
|
-
currentViewport={currentViewport}
|
|
152
|
-
inNoDataState={inNoDataState}
|
|
153
|
-
isLastRow={isLastRow}
|
|
154
|
-
/>
|
|
155
|
-
)
|
|
156
|
-
})}
|
|
157
|
-
</React.Fragment>
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
<div className={`row${row.equalHeight ? ' equal-height' : ''}${row.toggle ? ' toggle' : ''}`} key={`row__${index}`}>
|
|
163
|
-
{row.toggle && !inNoDataState && (
|
|
164
|
-
<Toggle row={row} visualizations={config.visualizations} active={toggledRow} setToggled={setToggled} />
|
|
165
|
-
)}
|
|
166
|
-
{row.columns.map((col, colIndex) => {
|
|
167
|
-
if (col.width) {
|
|
168
|
-
if (!col.widget) return <div key={`row__${index}__col__${colIndex}`} className={`col col-${col.width}`}></div>
|
|
169
|
-
|
|
170
|
-
const visualizationConfig = getVizConfig(
|
|
171
|
-
col.widget,
|
|
172
|
-
index,
|
|
173
|
-
config,
|
|
174
|
-
rawData,
|
|
175
|
-
dashboardFilteredData,
|
|
176
|
-
filteredDataOverride,
|
|
177
|
-
row.multiVizColumn
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
const { type, sharedFilterIndexes, filterBehavior, table, dataKey } = visualizationConfig
|
|
181
|
-
|
|
182
|
-
const setsSharedFilter =
|
|
183
|
-
config.dashboard.sharedFilters &&
|
|
184
|
-
config.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.setBy === col.widget).length > 0
|
|
185
|
-
const setSharedFilterValue = setsSharedFilter
|
|
186
|
-
? config.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.setBy === col.widget)[0].active
|
|
187
|
-
: undefined
|
|
188
|
-
const tableLink = (
|
|
189
|
-
<a href={`#data-table-${dataKey}`} className='margin-left-href'>
|
|
190
|
-
{dataKey} (Go to Table)
|
|
191
|
-
</a>
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
const hideVisualization =
|
|
195
|
-
inNoDataState &&
|
|
196
|
-
filterBehavior !== 'Apply Button' &&
|
|
197
|
-
(type !== 'dashboardFilters' || applyButtonNotClicked(visualizationConfig))
|
|
198
|
-
|
|
199
|
-
const shouldShow = row.toggle === undefined || (row.toggle && show[colIndex])
|
|
200
|
-
|
|
201
|
-
const hiddenDashboardFilters =
|
|
202
|
-
type === 'dashboardFilters' &&
|
|
203
|
-
sharedFilterIndexes &&
|
|
204
|
-
sharedFilterIndexes.filter(idx => config.dashboard.sharedFilters?.[idx]?.showDropdown === false).length ===
|
|
205
|
-
sharedFilterIndexes.length
|
|
206
|
-
const hasMarginBottom = !isLastRow && !hiddenDashboardFilters
|
|
207
|
-
|
|
208
|
-
const vizWrapperClass = `col-12 col-md-${col.width}${!shouldShow ? ' d-none' : ''}${
|
|
209
|
-
hideVisualization ? ' hide-parent-visualization' : hasMarginBottom ? ' mb-4' : ''
|
|
210
|
-
}`
|
|
211
|
-
const link =
|
|
212
|
-
config.table && config.table.show && config.datasets && table && table.showDataTableLink
|
|
213
|
-
? tableLink
|
|
214
|
-
: undefined
|
|
215
|
-
return hideVisualization ? null : (
|
|
216
|
-
<VisualizationWrapper
|
|
217
|
-
key={`vis__${index}__${colIndex}`}
|
|
218
|
-
className={vizWrapperClass}
|
|
219
|
-
allExpanded={allExpanded}
|
|
220
|
-
currentViewport={currentViewport}
|
|
221
|
-
groupName={groupName}
|
|
222
|
-
collapsible={row.expandCollapseAllButtons}
|
|
223
|
-
>
|
|
224
|
-
{type === 'chart' && (
|
|
225
|
-
<CdcChart
|
|
226
|
-
key={col.widget}
|
|
227
|
-
config={visualizationConfig as ChartConfig}
|
|
228
|
-
dashboardConfig={config}
|
|
229
|
-
datasets={config.datasets}
|
|
230
|
-
setConfig={newConfig => {
|
|
231
|
-
updateChildConfig(col.widget, newConfig)
|
|
232
|
-
}}
|
|
233
|
-
setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
|
|
234
|
-
isDashboard={true}
|
|
235
|
-
link={link}
|
|
236
|
-
/>
|
|
237
|
-
)}
|
|
238
|
-
{type === 'map' && (
|
|
239
|
-
<CdcMap
|
|
240
|
-
key={col.widget}
|
|
241
|
-
config={visualizationConfig}
|
|
242
|
-
setConfig={newConfig => {
|
|
243
|
-
updateChildConfig(col.widget, newConfig)
|
|
244
|
-
}}
|
|
245
|
-
showLoader={false}
|
|
246
|
-
setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
|
|
247
|
-
setSharedFilterValue={setSharedFilterValue}
|
|
248
|
-
isDashboard={true}
|
|
249
|
-
link={link}
|
|
250
|
-
dataset={config.datasets}
|
|
251
|
-
/>
|
|
252
|
-
)}
|
|
253
|
-
{type === 'data-bite' && (
|
|
254
|
-
<CdcDataBite
|
|
255
|
-
key={col.widget}
|
|
256
|
-
config={visualizationConfig}
|
|
257
|
-
setConfig={newConfig => {
|
|
258
|
-
updateChildConfig(col.widget, newConfig)
|
|
259
|
-
}}
|
|
260
|
-
isDashboard={true}
|
|
261
|
-
/>
|
|
262
|
-
)}
|
|
263
|
-
{type === 'waffle-chart' && (
|
|
264
|
-
<CdcWaffleChart
|
|
265
|
-
key={col.widget}
|
|
266
|
-
config={visualizationConfig}
|
|
267
|
-
setConfig={newConfig => {
|
|
268
|
-
updateChildConfig(col.widget, newConfig)
|
|
269
|
-
}}
|
|
270
|
-
isDashboard={true}
|
|
271
|
-
configUrl={link}
|
|
272
|
-
/>
|
|
273
|
-
)}
|
|
274
|
-
{type === 'markup-include' && (
|
|
275
|
-
<CdcMarkupInclude
|
|
276
|
-
key={col.widget}
|
|
277
|
-
config={visualizationConfig}
|
|
278
|
-
isDashboard={true}
|
|
279
|
-
setConfig={newConfig => {
|
|
280
|
-
updateChildConfig(col.widget, newConfig)
|
|
281
|
-
}}
|
|
282
|
-
/>
|
|
283
|
-
)}
|
|
284
|
-
{type === 'filtered-text' && (
|
|
285
|
-
<CdcFilteredText
|
|
286
|
-
key={col.widget}
|
|
287
|
-
config={visualizationConfig}
|
|
288
|
-
setConfig={newConfig => {
|
|
289
|
-
updateChildConfig(col.widget, newConfig)
|
|
290
|
-
}}
|
|
291
|
-
isDashboard={true}
|
|
292
|
-
/>
|
|
293
|
-
)}
|
|
294
|
-
{type === 'dashboardFilters' && (
|
|
295
|
-
<DashboardSharedFilters
|
|
296
|
-
setConfig={newConfig => {
|
|
297
|
-
updateChildConfig(col.widget, newConfig)
|
|
298
|
-
}}
|
|
299
|
-
key={col.widget}
|
|
300
|
-
visualizationConfig={visualizationConfig as DashboardFilters}
|
|
301
|
-
apiFilterDropdowns={apiFilterDropdowns}
|
|
302
|
-
currentViewport={currentViewport}
|
|
303
|
-
/>
|
|
304
|
-
)}
|
|
305
|
-
{type === 'table' && (
|
|
306
|
-
<DataTableStandAlone
|
|
307
|
-
key={col.widget}
|
|
308
|
-
updateConfig={newConfig => {
|
|
309
|
-
updateChildConfig(col.widget, newConfig)
|
|
310
|
-
}}
|
|
311
|
-
visualizationKey={col.widget}
|
|
312
|
-
config={visualizationConfig as TableConfig}
|
|
313
|
-
viewport={currentViewport}
|
|
314
|
-
/>
|
|
315
|
-
)}
|
|
316
|
-
</VisualizationWrapper>
|
|
317
|
-
)
|
|
318
|
-
}
|
|
319
|
-
})}
|
|
320
|
-
</div>
|
|
321
|
-
)
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
export default VisualizationRow
|
|
1
|
+
import DataTableStandAlone from '@cdc/core/components/DataTable/DataTableStandAlone'
|
|
2
|
+
import React, { useContext, useEffect, useMemo, useState } from 'react'
|
|
3
|
+
import Toggle from './Toggle'
|
|
4
|
+
import _ from 'lodash'
|
|
5
|
+
import { ConfigRow } from '../types/ConfigRow'
|
|
6
|
+
import CdcDataBite from '@cdc/data-bite/src/CdcDataBite'
|
|
7
|
+
import CdcMap from '@cdc/map/src/CdcMapComponent'
|
|
8
|
+
import CdcWaffleChart from '@cdc/waffle-chart/src/CdcWaffleChart'
|
|
9
|
+
import CdcMarkupInclude from '@cdc/markup-include/src/CdcMarkupInclude'
|
|
10
|
+
import CdcFilteredText from '@cdc/filtered-text/src/CdcFilteredText'
|
|
11
|
+
import DashboardSharedFilters, { APIFilterDropdowns } from './DashboardFilters'
|
|
12
|
+
import { DashboardContext } from '../DashboardContext'
|
|
13
|
+
import { ViewPort } from '@cdc/core/types/ViewPort'
|
|
14
|
+
import { getVizConfig } from '../helpers/getVizConfig'
|
|
15
|
+
import { TableConfig } from '@cdc/core/components/DataTable/types/TableConfig'
|
|
16
|
+
import CollapsibleVisualizationRow from './CollapsibleVisualizationRow'
|
|
17
|
+
import { DashboardFilters } from '../types/DashboardFilters'
|
|
18
|
+
import { hasDashboardApplyBehavior } from '../helpers/hasDashboardApplyBehavior'
|
|
19
|
+
import CdcChart from '@cdc/chart/src/CdcChartComponent'
|
|
20
|
+
import ExpandCollapseButtons from './ExpandCollapseButtons'
|
|
21
|
+
import { ChartConfig } from '@cdc/chart/src/types/ChartConfig'
|
|
22
|
+
|
|
23
|
+
type VisualizationWrapperProps = {
|
|
24
|
+
allExpanded: boolean
|
|
25
|
+
children: React.ReactNode
|
|
26
|
+
currentViewport: ViewPort
|
|
27
|
+
groupName: string
|
|
28
|
+
className: string
|
|
29
|
+
collapsible?: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const VisualizationWrapper: React.FC<VisualizationWrapperProps> = ({
|
|
33
|
+
allExpanded,
|
|
34
|
+
currentViewport,
|
|
35
|
+
groupName,
|
|
36
|
+
collapsible,
|
|
37
|
+
className,
|
|
38
|
+
children
|
|
39
|
+
}) => {
|
|
40
|
+
return (
|
|
41
|
+
<div className={className}>
|
|
42
|
+
{collapsible ? (
|
|
43
|
+
<CollapsibleVisualizationRow allExpanded={allExpanded} groupName={groupName} currentViewport={currentViewport}>
|
|
44
|
+
{children}
|
|
45
|
+
</CollapsibleVisualizationRow>
|
|
46
|
+
) : (
|
|
47
|
+
<>
|
|
48
|
+
{groupName !== '' ? <h3>{groupName}</h3> : <></>}
|
|
49
|
+
{children}
|
|
50
|
+
</>
|
|
51
|
+
)}
|
|
52
|
+
</div>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
type VizRowProps = {
|
|
57
|
+
allExpanded: boolean
|
|
58
|
+
filteredDataOverride?: Object[]
|
|
59
|
+
groupName: string
|
|
60
|
+
row: ConfigRow
|
|
61
|
+
rowIndex: number
|
|
62
|
+
inNoDataState: boolean
|
|
63
|
+
setSharedFilter: Function
|
|
64
|
+
updateChildConfig: Function
|
|
65
|
+
apiFilterDropdowns: APIFilterDropdowns
|
|
66
|
+
currentViewport: ViewPort
|
|
67
|
+
isLastRow: boolean
|
|
68
|
+
setAllExpanded?: (expanded: boolean) => void
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const VisualizationRow: React.FC<VizRowProps> = ({
|
|
72
|
+
allExpanded,
|
|
73
|
+
filteredDataOverride,
|
|
74
|
+
groupName,
|
|
75
|
+
row,
|
|
76
|
+
rowIndex: index,
|
|
77
|
+
inNoDataState,
|
|
78
|
+
setSharedFilter,
|
|
79
|
+
updateChildConfig,
|
|
80
|
+
apiFilterDropdowns,
|
|
81
|
+
currentViewport,
|
|
82
|
+
isLastRow,
|
|
83
|
+
setAllExpanded
|
|
84
|
+
}) => {
|
|
85
|
+
const { config, filteredData: dashboardFilteredData, data: rawData } = useContext(DashboardContext)
|
|
86
|
+
const [toggledRow, setToggled] = React.useState<number>(0)
|
|
87
|
+
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (row.toggle) setToggled(0)
|
|
90
|
+
}, [config.activeDashboard, index])
|
|
91
|
+
|
|
92
|
+
const show = useMemo(() => {
|
|
93
|
+
if (row.toggle) {
|
|
94
|
+
return row.columns.map((col, i) => i === toggledRow)
|
|
95
|
+
} else {
|
|
96
|
+
return row.columns.map((col, i) => true)
|
|
97
|
+
}
|
|
98
|
+
}, [config.activeDashboard, toggledRow])
|
|
99
|
+
|
|
100
|
+
const _data = dashboardFilteredData[index] || row.formattedData || []
|
|
101
|
+
const dataGroups =
|
|
102
|
+
row.multiVizColumn &&
|
|
103
|
+
_data.reduce((acc, dataRow) => {
|
|
104
|
+
const groupKey = dataRow[row.multiVizColumn]
|
|
105
|
+
if (!acc[groupKey]) acc[groupKey] = []
|
|
106
|
+
acc[groupKey].push(dataRow)
|
|
107
|
+
return acc
|
|
108
|
+
}, {})
|
|
109
|
+
|
|
110
|
+
const applyButtonNotClicked = (vizConfig: DashboardFilters): boolean => {
|
|
111
|
+
const dashboardFilters = Object.values(config.visualizations).filter(
|
|
112
|
+
v => v.type === 'dashboardFilters'
|
|
113
|
+
) as DashboardFilters[]
|
|
114
|
+
const applyFilters = dashboardFilters.filter(v => !v.autoLoad).flatMap(v => v.sharedFilterIndexes)
|
|
115
|
+
if (hasDashboardApplyBehavior(config.visualizations) && vizConfig.autoLoad) {
|
|
116
|
+
return applyFilters.some(index => {
|
|
117
|
+
const { queuedActive, active, subGrouping } = config.dashboard.sharedFilters[index]
|
|
118
|
+
if (!active && !queuedActive) return true
|
|
119
|
+
if (!queuedActive) return false
|
|
120
|
+
// for nested dropdowns
|
|
121
|
+
if (subGrouping) return queuedActive[0] !== active || queuedActive[1] !== subGrouping.active
|
|
122
|
+
// all other dropdowns
|
|
123
|
+
return queuedActive !== active
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
return false
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (dataGroups) {
|
|
130
|
+
return (
|
|
131
|
+
<React.Fragment key={`row__${index}`}>
|
|
132
|
+
{/* Expand/Collapse All */}
|
|
133
|
+
{!inNoDataState && row.expandCollapseAllButtons === true && (
|
|
134
|
+
<ExpandCollapseButtons setAllExpanded={setAllExpanded} />
|
|
135
|
+
)}
|
|
136
|
+
{Object.keys(dataGroups).map(groupName => {
|
|
137
|
+
const dataValue = dataGroups[groupName]
|
|
138
|
+
const _row = _.cloneDeep(row) // clone the row to avoid mutating the original row
|
|
139
|
+
_row.multiVizColumn = undefined // reset the multiVizColumn to avoid passing it to the child components
|
|
140
|
+
return (
|
|
141
|
+
<VisualizationRow
|
|
142
|
+
key={`row__${index}__${groupName}`}
|
|
143
|
+
allExpanded={allExpanded}
|
|
144
|
+
filteredDataOverride={dataValue}
|
|
145
|
+
groupName={groupName}
|
|
146
|
+
row={_row}
|
|
147
|
+
rowIndex={index}
|
|
148
|
+
setSharedFilter={setSharedFilter}
|
|
149
|
+
updateChildConfig={updateChildConfig}
|
|
150
|
+
apiFilterDropdowns={apiFilterDropdowns}
|
|
151
|
+
currentViewport={currentViewport}
|
|
152
|
+
inNoDataState={inNoDataState}
|
|
153
|
+
isLastRow={isLastRow}
|
|
154
|
+
/>
|
|
155
|
+
)
|
|
156
|
+
})}
|
|
157
|
+
</React.Fragment>
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<div className={`row${row.equalHeight ? ' equal-height' : ''}${row.toggle ? ' toggle' : ''}`} key={`row__${index}`}>
|
|
163
|
+
{row.toggle && !inNoDataState && (
|
|
164
|
+
<Toggle row={row} visualizations={config.visualizations} active={toggledRow} setToggled={setToggled} />
|
|
165
|
+
)}
|
|
166
|
+
{row.columns.map((col, colIndex) => {
|
|
167
|
+
if (col.width) {
|
|
168
|
+
if (!col.widget) return <div key={`row__${index}__col__${colIndex}`} className={`col col-${col.width}`}></div>
|
|
169
|
+
|
|
170
|
+
const visualizationConfig = getVizConfig(
|
|
171
|
+
col.widget,
|
|
172
|
+
index,
|
|
173
|
+
config,
|
|
174
|
+
rawData,
|
|
175
|
+
dashboardFilteredData,
|
|
176
|
+
filteredDataOverride,
|
|
177
|
+
row.multiVizColumn
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
const { type, sharedFilterIndexes, filterBehavior, table, dataKey } = visualizationConfig
|
|
181
|
+
|
|
182
|
+
const setsSharedFilter =
|
|
183
|
+
config.dashboard.sharedFilters &&
|
|
184
|
+
config.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.setBy === col.widget).length > 0
|
|
185
|
+
const setSharedFilterValue = setsSharedFilter
|
|
186
|
+
? config.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.setBy === col.widget)[0].active
|
|
187
|
+
: undefined
|
|
188
|
+
const tableLink = (
|
|
189
|
+
<a href={`#data-table-${dataKey}`} className='margin-left-href'>
|
|
190
|
+
{dataKey} (Go to Table)
|
|
191
|
+
</a>
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
const hideVisualization =
|
|
195
|
+
inNoDataState &&
|
|
196
|
+
filterBehavior !== 'Apply Button' &&
|
|
197
|
+
(type !== 'dashboardFilters' || applyButtonNotClicked(visualizationConfig))
|
|
198
|
+
|
|
199
|
+
const shouldShow = row.toggle === undefined || (row.toggle && show[colIndex])
|
|
200
|
+
|
|
201
|
+
const hiddenDashboardFilters =
|
|
202
|
+
type === 'dashboardFilters' &&
|
|
203
|
+
sharedFilterIndexes &&
|
|
204
|
+
sharedFilterIndexes.filter(idx => config.dashboard.sharedFilters?.[idx]?.showDropdown === false).length ===
|
|
205
|
+
sharedFilterIndexes.length
|
|
206
|
+
const hasMarginBottom = !isLastRow && !hiddenDashboardFilters
|
|
207
|
+
|
|
208
|
+
const vizWrapperClass = `col-12 col-md-${col.width}${!shouldShow ? ' d-none' : ''}${
|
|
209
|
+
hideVisualization ? ' hide-parent-visualization' : hasMarginBottom ? ' mb-4' : ''
|
|
210
|
+
}`
|
|
211
|
+
const link =
|
|
212
|
+
config.table && config.table.show && config.datasets && table && table.showDataTableLink
|
|
213
|
+
? tableLink
|
|
214
|
+
: undefined
|
|
215
|
+
return hideVisualization ? null : (
|
|
216
|
+
<VisualizationWrapper
|
|
217
|
+
key={`vis__${index}__${colIndex}`}
|
|
218
|
+
className={vizWrapperClass}
|
|
219
|
+
allExpanded={allExpanded}
|
|
220
|
+
currentViewport={currentViewport}
|
|
221
|
+
groupName={groupName}
|
|
222
|
+
collapsible={row.expandCollapseAllButtons}
|
|
223
|
+
>
|
|
224
|
+
{type === 'chart' && (
|
|
225
|
+
<CdcChart
|
|
226
|
+
key={col.widget}
|
|
227
|
+
config={visualizationConfig as ChartConfig}
|
|
228
|
+
dashboardConfig={config}
|
|
229
|
+
datasets={config.datasets}
|
|
230
|
+
setConfig={newConfig => {
|
|
231
|
+
updateChildConfig(col.widget, newConfig)
|
|
232
|
+
}}
|
|
233
|
+
setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
|
|
234
|
+
isDashboard={true}
|
|
235
|
+
link={link}
|
|
236
|
+
/>
|
|
237
|
+
)}
|
|
238
|
+
{type === 'map' && (
|
|
239
|
+
<CdcMap
|
|
240
|
+
key={col.widget}
|
|
241
|
+
config={visualizationConfig}
|
|
242
|
+
setConfig={newConfig => {
|
|
243
|
+
updateChildConfig(col.widget, newConfig)
|
|
244
|
+
}}
|
|
245
|
+
showLoader={false}
|
|
246
|
+
setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
|
|
247
|
+
setSharedFilterValue={setSharedFilterValue}
|
|
248
|
+
isDashboard={true}
|
|
249
|
+
link={link}
|
|
250
|
+
dataset={config.datasets}
|
|
251
|
+
/>
|
|
252
|
+
)}
|
|
253
|
+
{type === 'data-bite' && (
|
|
254
|
+
<CdcDataBite
|
|
255
|
+
key={col.widget}
|
|
256
|
+
config={visualizationConfig}
|
|
257
|
+
setConfig={newConfig => {
|
|
258
|
+
updateChildConfig(col.widget, newConfig)
|
|
259
|
+
}}
|
|
260
|
+
isDashboard={true}
|
|
261
|
+
/>
|
|
262
|
+
)}
|
|
263
|
+
{type === 'waffle-chart' && (
|
|
264
|
+
<CdcWaffleChart
|
|
265
|
+
key={col.widget}
|
|
266
|
+
config={visualizationConfig}
|
|
267
|
+
setConfig={newConfig => {
|
|
268
|
+
updateChildConfig(col.widget, newConfig)
|
|
269
|
+
}}
|
|
270
|
+
isDashboard={true}
|
|
271
|
+
configUrl={link}
|
|
272
|
+
/>
|
|
273
|
+
)}
|
|
274
|
+
{type === 'markup-include' && (
|
|
275
|
+
<CdcMarkupInclude
|
|
276
|
+
key={col.widget}
|
|
277
|
+
config={visualizationConfig}
|
|
278
|
+
isDashboard={true}
|
|
279
|
+
setConfig={newConfig => {
|
|
280
|
+
updateChildConfig(col.widget, newConfig)
|
|
281
|
+
}}
|
|
282
|
+
/>
|
|
283
|
+
)}
|
|
284
|
+
{type === 'filtered-text' && (
|
|
285
|
+
<CdcFilteredText
|
|
286
|
+
key={col.widget}
|
|
287
|
+
config={visualizationConfig}
|
|
288
|
+
setConfig={newConfig => {
|
|
289
|
+
updateChildConfig(col.widget, newConfig)
|
|
290
|
+
}}
|
|
291
|
+
isDashboard={true}
|
|
292
|
+
/>
|
|
293
|
+
)}
|
|
294
|
+
{type === 'dashboardFilters' && (
|
|
295
|
+
<DashboardSharedFilters
|
|
296
|
+
setConfig={newConfig => {
|
|
297
|
+
updateChildConfig(col.widget, newConfig)
|
|
298
|
+
}}
|
|
299
|
+
key={col.widget}
|
|
300
|
+
visualizationConfig={visualizationConfig as DashboardFilters}
|
|
301
|
+
apiFilterDropdowns={apiFilterDropdowns}
|
|
302
|
+
currentViewport={currentViewport}
|
|
303
|
+
/>
|
|
304
|
+
)}
|
|
305
|
+
{type === 'table' && (
|
|
306
|
+
<DataTableStandAlone
|
|
307
|
+
key={col.widget}
|
|
308
|
+
updateConfig={newConfig => {
|
|
309
|
+
updateChildConfig(col.widget, newConfig)
|
|
310
|
+
}}
|
|
311
|
+
visualizationKey={col.widget}
|
|
312
|
+
config={visualizationConfig as TableConfig}
|
|
313
|
+
viewport={currentViewport}
|
|
314
|
+
/>
|
|
315
|
+
)}
|
|
316
|
+
</VisualizationWrapper>
|
|
317
|
+
)
|
|
318
|
+
}
|
|
319
|
+
})}
|
|
320
|
+
</div>
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export default VisualizationRow
|