@cdc/dashboard 4.24.12 → 4.25.1
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 +68752 -67417
- package/examples/private/DEV-10120.json +1294 -0
- package/examples/private/DEV-9989.json +229 -0
- package/examples/private/art-dashboard.json +2 -2
- package/examples/private/bird-flu-2.json +440 -0
- package/examples/private/bird-flu.json +413 -0
- package/examples/private/dashboard-config-ehdi.json +29915 -0
- package/examples/private/dashboard-margins.js +15 -0
- package/examples/private/dataset.json +1452 -0
- package/examples/private/ehdi-data.json +29502 -0
- package/examples/private/exposure-source-h5-data.csv +26 -0
- package/examples/private/workforce.json +2041 -0
- package/index.html +2 -6
- package/package.json +9 -9
- package/src/CdcDashboardComponent.tsx +12 -4
- package/src/_stories/Dashboard.stories.tsx +32 -0
- package/src/_stories/_mock/data-bite-dash-test.json +1 -0
- package/src/_stories/_mock/data-bite-dash-test_1.json +1 -0
- package/src/_stories/_mock/data-bite-dash-test_1_1.json +1 -0
- package/src/_stories/_mock/data-bite-dash-test_1_1_1.json +1 -0
- package/src/components/CollapsibleVisualizationRow.tsx +2 -2
- package/src/components/Column.tsx +12 -1
- package/src/components/DashboardFilters/DashboardFilters.tsx +4 -4
- package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +1 -3
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +1 -1
- package/src/components/DashboardFilters/dashboardfilter.styles.css +2 -0
- package/src/components/ExpandCollapseButtons.tsx +1 -1
- package/src/components/Header/Header.tsx +1 -2
- package/src/components/MultiConfigTabs/MultiConfigTabs.tsx +2 -2
- package/src/components/MultiConfigTabs/MultiTabs.tsx +1 -1
- package/src/components/VisualizationRow.tsx +2 -2
- package/src/components/Widget.tsx +9 -3
- package/src/helpers/apiFilterHelpers.ts +1 -1
- package/src/index.tsx +1 -0
- package/src/scss/main.scss +1 -12
- package/src/store/dashboard.actions.ts +2 -2
- package/src/store/dashboard.reducer.ts +17 -8
- package/src/types/DashboardConfig.ts +2 -0
package/index.html
CHANGED
|
@@ -17,11 +17,7 @@
|
|
|
17
17
|
}
|
|
18
18
|
</style>
|
|
19
19
|
<link rel="stylesheet prefetch" href="examples/custom/css/respiratory.css" />
|
|
20
|
-
<link
|
|
21
|
-
rel="stylesheet prefetch"
|
|
22
|
-
href="https://www.cdc.gov/TemplatePackage/contrib/libs/bootstrap/latest/css/bootstrap.min.css?_=39423"
|
|
23
|
-
/>
|
|
24
|
-
<link rel="stylesheet prefetch" href="https://www.cdc.gov/TemplatePackage/4.0/assets/css/app.min.css?_=39423" />
|
|
20
|
+
<link rel="stylesheet prefetch" href="https://www.cdc.gov/TemplatePackage/5.0/css/app.min.css?_=71669" />
|
|
25
21
|
</head>
|
|
26
22
|
|
|
27
23
|
<body>
|
|
@@ -34,7 +30,7 @@
|
|
|
34
30
|
<!-- <div class="react-container" data-config="/examples/dev-8332.json"></div> -->
|
|
35
31
|
<!-- <div class="react-container" data-config="/examples/dashboard-gallery.json"></div> -->
|
|
36
32
|
<!-- <div class="react-container" data-config="/examples/filtered-dash.json"></div> -->
|
|
37
|
-
<div class="react-container" data-config="/examples/
|
|
33
|
+
<div class="react-container" data-config="/examples/private/art-dashboard.json"></div>
|
|
38
34
|
<!-- <div class="react-container" data-config="/examples/sankey.json"></div> -->
|
|
39
35
|
<!-- <div class="react-container" data-config="/examples/DEV-6574.json"></div> -->
|
|
40
36
|
<!-- <div class="react-container" data-config="/examples/default-multi-dataset-2.json"></div> -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/dashboard",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.25.1",
|
|
4
4
|
"description": "React component for combining multiple visualizations into a single dashboard",
|
|
5
5
|
"moduleName": "CdcDashboard",
|
|
6
6
|
"main": "dist/cdcdashboard",
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@cdc/chart": "^4.
|
|
31
|
-
"@cdc/core": "^4.
|
|
32
|
-
"@cdc/data-bite": "^4.
|
|
33
|
-
"@cdc/filtered-text": "^4.
|
|
34
|
-
"@cdc/map": "^4.
|
|
35
|
-
"@cdc/markup-include": "^4.
|
|
36
|
-
"@cdc/waffle-chart": "^4.
|
|
30
|
+
"@cdc/chart": "^4.25.1",
|
|
31
|
+
"@cdc/core": "^4.25.1",
|
|
32
|
+
"@cdc/data-bite": "^4.25.1",
|
|
33
|
+
"@cdc/filtered-text": "^4.25.1",
|
|
34
|
+
"@cdc/map": "^4.25.1",
|
|
35
|
+
"@cdc/markup-include": "^4.25.1",
|
|
36
|
+
"@cdc/waffle-chart": "^4.25.1",
|
|
37
37
|
"html-react-parser": "^3.0.8",
|
|
38
38
|
"js-base64": "^2.5.2",
|
|
39
39
|
"papaparse": "^5.3.0",
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"react": "^18.2.0",
|
|
50
50
|
"react-dom": "^18.2.0"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "c32d727f516fe3525178e3a6480abbe70b2a20d6"
|
|
53
53
|
}
|
|
@@ -19,7 +19,7 @@ import Loading from '@cdc/core/components/Loading'
|
|
|
19
19
|
import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
20
20
|
import getViewport from '@cdc/core/helpers/getViewport'
|
|
21
21
|
|
|
22
|
-
import CdcChart from '@cdc/chart/src/
|
|
22
|
+
import CdcChart from '@cdc/chart/src/CdcChartComponent'
|
|
23
23
|
import CdcDataBite from '@cdc/data-bite/src/CdcDataBite'
|
|
24
24
|
import CdcMap from '@cdc/map/src/CdcMap'
|
|
25
25
|
import CdcWaffleChart from '@cdc/waffle-chart/src/CdcWaffleChart'
|
|
@@ -228,7 +228,15 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
|
|
|
228
228
|
)
|
|
229
229
|
dispatch({ type: 'SET_FILTERED_DATA', payload: filteredData })
|
|
230
230
|
const visualizations = reloadURLHelpers.getVisualizationsWithFormattedData(config.visualizations, newData)
|
|
231
|
-
dispatch({
|
|
231
|
+
dispatch({
|
|
232
|
+
type: 'SET_CONFIG',
|
|
233
|
+
payload: {
|
|
234
|
+
dashboard: dashboardConfig,
|
|
235
|
+
datasets: newDatasets,
|
|
236
|
+
visualizations,
|
|
237
|
+
activeDashboard: config.activeDashboard
|
|
238
|
+
}
|
|
239
|
+
})
|
|
232
240
|
setAPILoading(false)
|
|
233
241
|
}
|
|
234
242
|
}
|
|
@@ -268,7 +276,7 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
|
|
|
268
276
|
const loadAllFilters = shouldLoadAllFilters(config, isEditor && !isPreview)
|
|
269
277
|
const sharedFiltersWithValues = addValuesToDashboardFilters(config.dashboard.sharedFilters, state.data)
|
|
270
278
|
|
|
271
|
-
loadAPIFilters(sharedFiltersWithValues, apiFilterDropdowns, loadAllFilters)
|
|
279
|
+
loadAPIFilters(sharedFiltersWithValues, apiFilterDropdowns, loadAllFilters)?.then(newFilters => {
|
|
272
280
|
const allValuesSelected = newFilters.every(filter => {
|
|
273
281
|
return filter.type === 'datafilter' || filter.active
|
|
274
282
|
})
|
|
@@ -534,7 +542,7 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
|
|
|
534
542
|
classes={[`dashboard-title`, `${config.dashboard.theme ?? 'theme-blue'}`]}
|
|
535
543
|
/>
|
|
536
544
|
{/* Description */}
|
|
537
|
-
{description && <div className='subtext'>{parse(description)}</div>}
|
|
545
|
+
{description && <div className='subtext mb-3'>{parse(description)}</div>}
|
|
538
546
|
{/* Visualizations */}
|
|
539
547
|
{config.rows &&
|
|
540
548
|
config.rows
|
|
@@ -24,6 +24,10 @@ import { ConfigRow } from '../types/ConfigRow'
|
|
|
24
24
|
import BumpChartConfig from './_mock/bump-chart.json'
|
|
25
25
|
import MethodologyConfig from './_mock/methodology.json'
|
|
26
26
|
import methodologyAPI from './_mock/methodologyAPI'
|
|
27
|
+
import TopSpacing_1 from './_mock/data-bite-dash-test.json'
|
|
28
|
+
import TopSpacing_2 from './_mock/data-bite-dash-test_1.json'
|
|
29
|
+
import TopSpacing_3 from './_mock/data-bite-dash-test_1_1.json'
|
|
30
|
+
import TopSpacing_4 from './_mock/data-bite-dash-test_1_1_1.json'
|
|
27
31
|
|
|
28
32
|
const meta: Meta<typeof Dashboard> = {
|
|
29
33
|
title: 'Components/Pages/Dashboard',
|
|
@@ -403,4 +407,32 @@ export const RegressionMultiVisualization: Story = {
|
|
|
403
407
|
}
|
|
404
408
|
}
|
|
405
409
|
|
|
410
|
+
export const Top_Spacing_1: Story = {
|
|
411
|
+
args: {
|
|
412
|
+
config: TopSpacing_1,
|
|
413
|
+
isEditor: false
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export const Top_Spacing_2: Story = {
|
|
418
|
+
args: {
|
|
419
|
+
config: TopSpacing_2,
|
|
420
|
+
isEditor: false
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
export const Top_Spacing_3: Story = {
|
|
425
|
+
args: {
|
|
426
|
+
config: TopSpacing_3,
|
|
427
|
+
isEditor: false
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export const Top_Spacing_4: Story = {
|
|
432
|
+
args: {
|
|
433
|
+
config: TopSpacing_4,
|
|
434
|
+
isEditor: false
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
406
438
|
export default meta
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"dashboard":{"theme":"theme-blue","sharedFilters":[],"description":"Dash Description","title":"Dashboard Name"},"rows":[{"columns":[{"width":6,"widget":"data-bite1722537849962"},{"width":6,"widget":"data-bite1728059122204"}],"dataDescription":{"horizontal":false,"series":true,"singleRow":true},"dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}],"visualizations":{"data-bite1722537849962":{"type":"data-bite","dataBite":"","dataFunction":"Sum","dataColumn":"specimens tested","bitePosition":"Left","biteFontSize":24,"fontSize":"medium","biteBody":"specimens tested that would have detected influenza A(H5) or other novel influenza viruses","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":"+"},"biteStyle":"title","filters":[],"subtext":"","title":"Specimens tested","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"filterBehavior":"Filter Change","openModal":true,"uid":"data-bite1722537849962","visualizationType":"data-bite","dataDescription":{"horizontal":false,"series":true,"singleRow":true},"version":"4.24.10","dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"},"data-bite1728059122204":{"type":"data-bite","dataBite":"","dataFunction":"Sum","dataColumn":"Human cases","bitePosition":"Left","biteFontSize":24,"fontSize":"medium","biteBody":"case detected through national flu surveillance","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":""},"biteStyle":"title","filters":[],"subtext":"","title":"Human cases","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"filterBehavior":"Filter Change","openModal":true,"uid":"data-bite1728059122204","visualizationType":"data-bite","dataDescription":{"horizontal":false,"series":true,"singleRow":true},"version":"4.24.10","dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}},"table":{"label":"Data Table","show":false,"showDownloadUrl":false,"showVertical":true},"datasets":{"/bird-flu/modules/situation-summary/national-flu-surveillance.csv":{"dataFileSize":39,"dataFileName":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv","dataFileSourceType":"url","dataFileFormat":"OCTET-STREAM","preview":true,"dataUrl":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}},"type":"dashboard","version":"4.24.10","uuid":1722537847428}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"dashboard":{"theme":"theme-blue","sharedFilters":[],"description":"Dash Description","title":""},"rows":[{"columns":[{"width":6,"widget":"data-bite1722537849962"},{"width":6,"widget":"data-bite1728059122204"}],"dataDescription":{"horizontal":false,"series":true,"singleRow":true},"dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}],"visualizations":{"data-bite1722537849962":{"type":"data-bite","dataBite":"","dataFunction":"Sum","dataColumn":"specimens tested","bitePosition":"Left","biteFontSize":24,"fontSize":"medium","biteBody":"specimens tested that would have detected influenza A(H5) or other novel influenza viruses","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":"+"},"biteStyle":"title","filters":[],"subtext":"","title":"Specimens tested","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"filterBehavior":"Filter Change","openModal":true,"uid":"data-bite1722537849962","visualizationType":"data-bite","dataDescription":{"horizontal":false,"series":true,"singleRow":true},"version":"4.24.10","dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"},"data-bite1728059122204":{"type":"data-bite","dataBite":"","dataFunction":"Sum","dataColumn":"Human cases","bitePosition":"Left","biteFontSize":24,"fontSize":"medium","biteBody":"case detected through national flu surveillance","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":""},"biteStyle":"title","filters":[],"subtext":"","title":"Human cases","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"filterBehavior":"Filter Change","openModal":true,"uid":"data-bite1728059122204","visualizationType":"data-bite","dataDescription":{"horizontal":false,"series":true,"singleRow":true},"version":"4.24.10","dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}},"table":{"label":"Data Table","show":false,"showDownloadUrl":false,"showVertical":true},"datasets":{"/bird-flu/modules/situation-summary/national-flu-surveillance.csv":{"dataFileSize":39,"dataFileName":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv","dataFileSourceType":"url","dataFileFormat":"OCTET-STREAM","preview":true,"dataUrl":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}},"type":"dashboard","version":"4.24.10","uuid":1722537847428}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"dashboard":{"theme":"theme-blue","sharedFilters":[],"description":"","title":"Title no description"},"rows":[{"columns":[{"width":6,"widget":"data-bite1722537849962"},{"width":6,"widget":"data-bite1728059122204"}],"dataDescription":{"horizontal":false,"series":true,"singleRow":true},"dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}],"visualizations":{"data-bite1722537849962":{"type":"data-bite","dataBite":"","dataFunction":"Sum","dataColumn":"specimens tested","bitePosition":"Left","biteFontSize":24,"fontSize":"medium","biteBody":"specimens tested that would have detected influenza A(H5) or other novel influenza viruses","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":"+"},"biteStyle":"title","filters":[],"subtext":"","title":"Specimens tested","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"filterBehavior":"Filter Change","openModal":true,"uid":"data-bite1722537849962","visualizationType":"data-bite","dataDescription":{"horizontal":false,"series":true,"singleRow":true},"version":"4.24.10","dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"},"data-bite1728059122204":{"type":"data-bite","dataBite":"","dataFunction":"Sum","dataColumn":"Human cases","bitePosition":"Left","biteFontSize":24,"fontSize":"medium","biteBody":"case detected through national flu surveillance","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":""},"biteStyle":"title","filters":[],"subtext":"","title":"Human cases","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"filterBehavior":"Filter Change","openModal":true,"uid":"data-bite1728059122204","visualizationType":"data-bite","dataDescription":{"horizontal":false,"series":true,"singleRow":true},"version":"4.24.10","dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}},"table":{"label":"Data Table","show":false,"showDownloadUrl":false,"showVertical":true},"datasets":{"/bird-flu/modules/situation-summary/national-flu-surveillance.csv":{"dataFileSize":39,"dataFileName":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv","dataFileSourceType":"url","dataFileFormat":"OCTET-STREAM","preview":true,"dataUrl":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}},"type":"dashboard","version":"4.24.10","uuid":1722537847428}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"dashboard":{"theme":"theme-blue","sharedFilters":[],"description":"","title":""},"rows":[{"columns":[{"width":6,"widget":"data-bite1722537849962"},{"width":6,"widget":"data-bite1728059122204"}],"dataDescription":{"horizontal":false,"series":true,"singleRow":true},"dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}],"visualizations":{"data-bite1722537849962":{"type":"data-bite","dataBite":"","dataFunction":"Sum","dataColumn":"specimens tested","bitePosition":"Left","biteFontSize":24,"fontSize":"medium","biteBody":"specimens tested that would have detected influenza A(H5) or other novel influenza viruses","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":"+"},"biteStyle":"title","filters":[],"subtext":"","title":"Specimens tested","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"filterBehavior":"Filter Change","openModal":true,"uid":"data-bite1722537849962","visualizationType":"data-bite","dataDescription":{"horizontal":false,"series":true,"singleRow":true},"version":"4.24.10","dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"},"data-bite1728059122204":{"type":"data-bite","dataBite":"","dataFunction":"Sum","dataColumn":"Human cases","bitePosition":"Left","biteFontSize":24,"fontSize":"medium","biteBody":"case detected through national flu surveillance","imageData":{"display":"none","url":"","alt":"","options":[]},"dataFormat":{"roundToPlace":0,"commas":true,"prefix":"","suffix":""},"biteStyle":"title","filters":[],"subtext":"","title":"Human cases","theme":"theme-blue","shadow":false,"visual":{"border":false,"accent":false,"background":false,"hideBackgroundColor":false,"borderColorTheme":false},"general":{"isCompactStyle":false},"filterBehavior":"Filter Change","openModal":true,"uid":"data-bite1728059122204","visualizationType":"data-bite","dataDescription":{"horizontal":false,"series":true,"singleRow":true},"version":"4.24.10","dataKey":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}},"table":{"label":"Data Table","show":false,"showDownloadUrl":false,"showVertical":true},"datasets":{"/bird-flu/modules/situation-summary/national-flu-surveillance.csv":{"dataFileSize":39,"dataFileName":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv","dataFileSourceType":"url","dataFileFormat":"OCTET-STREAM","preview":true,"dataUrl":"/bird-flu/modules/situation-summary/national-flu-surveillance.csv"}},"type":"dashboard","version":"4.24.10","uuid":1722537847428}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState, useEffect } from 'react'
|
|
2
2
|
import Icon from '../../../core/components/ui/Icon'
|
|
3
|
+
import { appFontSize } from '@cdc/core/helpers/cove/fontSettings'
|
|
3
4
|
|
|
4
5
|
type CollapsableVizRow = {
|
|
5
6
|
allExpanded: boolean
|
|
@@ -16,8 +17,7 @@ const CollapsibleVisualizationRow: React.FC<CollapsableVizRow> = ({
|
|
|
16
17
|
children
|
|
17
18
|
}) => {
|
|
18
19
|
const [isExpanded, setIsExpanded] = useState(allExpanded)
|
|
19
|
-
const
|
|
20
|
-
const titleFontSize = ['xs', 'xxs'].includes(currentViewport) ? '13px' : `${fontSizes[fontSize]}px`
|
|
20
|
+
const titleFontSize = ['xs', 'xxs'].includes(currentViewport) ? '13px' : `${appFontSize}px`
|
|
21
21
|
|
|
22
22
|
useEffect(() => {
|
|
23
23
|
setIsExpanded(allExpanded)
|
|
@@ -37,10 +37,21 @@ const Column = ({ data, rowIdx, colIdx }) => {
|
|
|
37
37
|
classNames.push('column--populated')
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
const handleTitle = config => {
|
|
41
|
+
if (!config) return
|
|
42
|
+
if (config.type === 'map') return config.general.title
|
|
43
|
+
if (config.type === 'markup-include') return config.contentEditor?.title
|
|
44
|
+
return config.title
|
|
45
|
+
}
|
|
46
|
+
|
|
40
47
|
return (
|
|
41
48
|
<div className={classNames.join(' ')} ref={drop}>
|
|
42
49
|
{widget ? (
|
|
43
|
-
<Widget
|
|
50
|
+
<Widget
|
|
51
|
+
title={handleTitle(widget)}
|
|
52
|
+
widgetConfig={{ rowIdx, colIdx, ...widget }}
|
|
53
|
+
type={widget.visualizationType ?? widget.general?.geoType}
|
|
54
|
+
/>
|
|
44
55
|
) : (
|
|
45
56
|
<p className='builder-column__text'>
|
|
46
57
|
Drag and drop <br /> visualization
|
|
@@ -122,12 +122,12 @@ const DashboardFilters: React.FC<DashboardFilterProps> = ({
|
|
|
122
122
|
)
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
const formGroupClass = `form-group
|
|
125
|
+
const formGroupClass = `form-group me-4 mb-1${loading ? ' loading-filter' : ''}`
|
|
126
126
|
|
|
127
127
|
return (
|
|
128
128
|
<div className={formGroupClass} key={`${label}-filtersection-${filterIndex}`}>
|
|
129
129
|
{label && (
|
|
130
|
-
<label className='font-weight-bold
|
|
130
|
+
<label className='font-weight-bold mb-2' htmlFor={`filter-${filterIndex}`}>
|
|
131
131
|
{label}
|
|
132
132
|
</label>
|
|
133
133
|
)}
|
|
@@ -143,8 +143,8 @@ const DashboardFilters: React.FC<DashboardFilterProps> = ({
|
|
|
143
143
|
/>
|
|
144
144
|
) : filter.filterStyle === FILTER_STYLE.nestedDropdown ? (
|
|
145
145
|
<NestedDropdown
|
|
146
|
-
activeGroup={filter.active as string}
|
|
147
|
-
activeSubGroup={_key ? filter.subGrouping?.active : activeSubGroupValue}
|
|
146
|
+
activeGroup={(filter.queuedActive?.[0] || filter.active) as string}
|
|
147
|
+
activeSubGroup={_key ? filter.queuedActive?.[1] || filter.subGrouping?.active : activeSubGroupValue}
|
|
148
148
|
filterIndex={filterIndex}
|
|
149
149
|
options={_key ? getNestedDropdownOptions(apiFilterDropdowns[_key]) : nestedOptions}
|
|
150
150
|
listLabel={label}
|
|
@@ -40,7 +40,7 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
40
40
|
Number
|
|
41
41
|
)
|
|
42
42
|
return config.dashboard.sharedFilters
|
|
43
|
-
|
|
43
|
+
?.map<[number, string]>(({ key }, i) => [i, key])
|
|
44
44
|
.filter(([filterIndex]) => !sharedFilterIndexes.includes(filterIndex)) // filter out already added filters
|
|
45
45
|
.map(([filterIndex, filterName]) => (
|
|
46
46
|
<option key={filterIndex} value={filterIndex}>{`${filterIndex} - ${filterName}`}</option>
|
|
@@ -274,9 +274,7 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
274
274
|
</select>
|
|
275
275
|
</label>
|
|
276
276
|
) : (
|
|
277
|
-
|
|
278
277
|
<button onClick={() => setCanAddExisting(true)} className='btn btn-primary full-width mt-2'>
|
|
279
|
-
|
|
280
278
|
Add Existing Dashboard Filter
|
|
281
279
|
</button>
|
|
282
280
|
)}
|
|
@@ -226,7 +226,7 @@ const FilterEditor: React.FC<FilterEditorProps> = ({ filter, config, updateFilte
|
|
|
226
226
|
</label>
|
|
227
227
|
{filter.filterStyle === FILTER_STYLE.dropdown && (
|
|
228
228
|
<label>
|
|
229
|
-
<span className='
|
|
229
|
+
<span className='me-1'>Show Dropdown</span>
|
|
230
230
|
<input
|
|
231
231
|
type='checkbox'
|
|
232
232
|
checked={filter.showDropdown}
|
|
@@ -9,7 +9,7 @@ const ExpandCollapseButtons: React.FC<ExpandCollapseButtonsProps> = ({ setAllExp
|
|
|
9
9
|
<button className='btn expand-collapse-buttons' onClick={() => setAllExpanded(false)}>
|
|
10
10
|
- Collapse All
|
|
11
11
|
</button>
|
|
12
|
-
<button className='btn expand-collapse-buttons
|
|
12
|
+
<button className='btn expand-collapse-buttons me-2' onClick={() => setAllExpanded(true)}>
|
|
13
13
|
+ Expand All
|
|
14
14
|
</button>
|
|
15
15
|
</div>
|
|
@@ -6,7 +6,6 @@ import './index.scss'
|
|
|
6
6
|
import MultiConfigTabs from '../MultiConfigTabs'
|
|
7
7
|
import { Tab } from '../../types/Tab'
|
|
8
8
|
import _ from 'lodash'
|
|
9
|
-
import { getVizRowColumnLocator } from '../../helpers/getVizRowColumnLocator'
|
|
10
9
|
|
|
11
10
|
type HeaderProps = {
|
|
12
11
|
back?: any
|
|
@@ -29,7 +28,7 @@ const Header = (props: HeaderProps) => {
|
|
|
29
28
|
// the Widget component will do a data fetch if no data is available for the visualization
|
|
30
29
|
// this is intended to help visualization developers.
|
|
31
30
|
type SampleData = Record<string, { sample: boolean }> & Object[]
|
|
32
|
-
if (Object.values(data).some((d: SampleData) => d
|
|
31
|
+
if (Object.values(data).some((d: SampleData) => d?.sample)) {
|
|
33
32
|
const sampleDataRemoved = Object.keys(data).reduce((acc, key) => {
|
|
34
33
|
if ((data[key] as SampleData).sample) {
|
|
35
34
|
acc[key] = []
|
|
@@ -86,7 +86,7 @@ const Tab = ({ name, handleClick, tabs, index, active }) => {
|
|
|
86
86
|
) : (
|
|
87
87
|
<>
|
|
88
88
|
{name}
|
|
89
|
-
<button className='btn btn-danger border-0
|
|
89
|
+
<button className='btn btn-danger border-0 ms-1' onClick={handleRemove}>
|
|
90
90
|
X
|
|
91
91
|
</button>
|
|
92
92
|
</>
|
|
@@ -117,7 +117,7 @@ const MultiConfigTabs = () => {
|
|
|
117
117
|
|
|
118
118
|
if (!config.multiDashboards) return null
|
|
119
119
|
return (
|
|
120
|
-
<ul className='nav nav-tabs multi-config-tabs'>
|
|
120
|
+
<ul className='nav nav-tabs multi-config-tabs mb-4'>
|
|
121
121
|
{tabs.map((tab, index) => (
|
|
122
122
|
<Tab
|
|
123
123
|
key={tab + index}
|
|
@@ -21,7 +21,7 @@ const MultiTabs = () => {
|
|
|
21
21
|
|
|
22
22
|
if (!config.multiDashboards) return null
|
|
23
23
|
return (
|
|
24
|
-
<ul className='nav nav-tabs multi-config-tabs'>
|
|
24
|
+
<ul className='nav nav-tabs multi-config-tabs mb-4'>
|
|
25
25
|
{tabs.map((tab, index) => (
|
|
26
26
|
<li key={tab + index} className='nav-item'>
|
|
27
27
|
<a
|
|
@@ -3,7 +3,6 @@ import React, { useContext, useMemo } from 'react'
|
|
|
3
3
|
import Toggle from './Toggle'
|
|
4
4
|
import _ from 'lodash'
|
|
5
5
|
import { ConfigRow } from '../types/ConfigRow'
|
|
6
|
-
import CdcChart from '@cdc/chart/src/CdcChart'
|
|
7
6
|
import CdcDataBite from '@cdc/data-bite/src/CdcDataBite'
|
|
8
7
|
import CdcMap from '@cdc/map/src/CdcMap'
|
|
9
8
|
import CdcWaffleChart from '@cdc/waffle-chart/src/CdcWaffleChart'
|
|
@@ -18,6 +17,7 @@ import FootnotesStandAlone from '@cdc/core/components/Footnotes/FootnotesStandAl
|
|
|
18
17
|
import CollapsibleVisualizationRow from './CollapsibleVisualizationRow'
|
|
19
18
|
import { DashboardFilters } from '../types/DashboardFilters'
|
|
20
19
|
import { hasDashboardApplyBehavior } from '../helpers/hasDashboardApplyBehavior'
|
|
20
|
+
import CdcChart from '@cdc/chart/src/CdcChartComponent'
|
|
21
21
|
|
|
22
22
|
type VisualizationWrapperProps = {
|
|
23
23
|
allExpanded: boolean
|
|
@@ -160,7 +160,7 @@ const VisualizationRow: React.FC<VizRowProps> = ({
|
|
|
160
160
|
<div
|
|
161
161
|
key={`vis__${index}__${colIndex}`}
|
|
162
162
|
className={`col-12 col-md-${col.width}${!shouldShow ? ' d-none' : ''}${
|
|
163
|
-
hideVisualization ? ' hide-parent-visualization' : '
|
|
163
|
+
hideVisualization ? ' hide-parent-visualization' : ' mb-4'
|
|
164
164
|
}`}
|
|
165
165
|
>
|
|
166
166
|
{row.toggle && !hideVisualization && (
|
|
@@ -33,12 +33,13 @@ const labelHash = {
|
|
|
33
33
|
|
|
34
34
|
type WidgetConfig = AnyVisualization & { rowIdx: number; colIdx: number }
|
|
35
35
|
type WidgetProps = {
|
|
36
|
+
title: string
|
|
36
37
|
widgetConfig?: WidgetConfig
|
|
37
38
|
addVisualization?: Function
|
|
38
39
|
type: string
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
const Widget = ({ widgetConfig, addVisualization, type }: WidgetProps) => {
|
|
42
|
+
const Widget = ({ title, widgetConfig, addVisualization, type }: WidgetProps) => {
|
|
42
43
|
const { overlay } = useGlobalContext()
|
|
43
44
|
const { config, data } = useContext(DashboardContext)
|
|
44
45
|
const dispatch = useContext(DashboardDispatchContext)
|
|
@@ -74,9 +75,10 @@ const Widget = ({ widgetConfig, addVisualization, type }: WidgetProps) => {
|
|
|
74
75
|
|
|
75
76
|
const deleteWidget = () => {
|
|
76
77
|
if (!widgetConfig) return
|
|
78
|
+
|
|
77
79
|
dispatch({
|
|
78
80
|
type: 'DELETE_WIDGET',
|
|
79
|
-
payload: {
|
|
81
|
+
payload: { uid: widgetConfig.uid as string }
|
|
80
82
|
})
|
|
81
83
|
}
|
|
82
84
|
|
|
@@ -102,7 +104,10 @@ const Widget = ({ widgetConfig, addVisualization, type }: WidgetProps) => {
|
|
|
102
104
|
|
|
103
105
|
const editWidget = () => {
|
|
104
106
|
if (!widgetConfig) return
|
|
105
|
-
dispatch({
|
|
107
|
+
dispatch({
|
|
108
|
+
type: 'UPDATE_VISUALIZATION',
|
|
109
|
+
payload: { vizKey: widgetConfig.uid as string, configureData: { editing: true } }
|
|
110
|
+
})
|
|
106
111
|
loadSampleData()
|
|
107
112
|
}
|
|
108
113
|
|
|
@@ -156,6 +161,7 @@ const Widget = ({ widgetConfig, addVisualization, type }: WidgetProps) => {
|
|
|
156
161
|
)}
|
|
157
162
|
{iconHash[type]}
|
|
158
163
|
<span>{labelHash[type]}</span>
|
|
164
|
+
<span>{title}</span>
|
|
159
165
|
{widgetConfig?.newViz && type !== 'dashboardFilters' && (
|
|
160
166
|
<span onClick={editWidget} className='config-needed'>
|
|
161
167
|
Configuration needed
|
|
@@ -152,7 +152,7 @@ export const setAutoLoadDefaultValue = (
|
|
|
152
152
|
if (!sharedFilter.active) {
|
|
153
153
|
sharedFilter.active = defaultQueryParamValue || defaultValue
|
|
154
154
|
} else {
|
|
155
|
-
const currentOption = dropdownOptions.find(option => option.value
|
|
155
|
+
const currentOption = dropdownOptions.find(option => option.value == sharedFilter.active) // loose equality required: 2017 should equal '2017'
|
|
156
156
|
sharedFilter.active = currentOption ? currentOption.value : defaultValue
|
|
157
157
|
}
|
|
158
158
|
}
|
package/src/index.tsx
CHANGED
package/src/scss/main.scss
CHANGED
|
@@ -138,7 +138,6 @@
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
.btn {
|
|
141
|
-
|
|
142
141
|
// Expand and Collapse Buttons for Multiviz Dashboard
|
|
143
142
|
&.expand-collapse-buttons {
|
|
144
143
|
background-color: var(--lightestGray);
|
|
@@ -163,13 +162,6 @@
|
|
|
163
162
|
margin: 15px 0 0;
|
|
164
163
|
}
|
|
165
164
|
|
|
166
|
-
.data-table-container {
|
|
167
|
-
margin: 20px 0 0;
|
|
168
|
-
&.download-link-above {
|
|
169
|
-
margin: 0;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
165
|
.collapsable-multiviz-container {
|
|
174
166
|
position: relative;
|
|
175
167
|
border: var(--lightGray) 1px solid;
|
|
@@ -193,8 +185,7 @@
|
|
|
193
185
|
position: relative;
|
|
194
186
|
}
|
|
195
187
|
@include breakpoint(xs) {
|
|
196
|
-
|
|
197
|
-
font-size: $font-small + 0.2em;
|
|
188
|
+
font-size: 0.9em;
|
|
198
189
|
}
|
|
199
190
|
}
|
|
200
191
|
.data-table-heading {
|
|
@@ -283,8 +274,6 @@
|
|
|
283
274
|
}
|
|
284
275
|
|
|
285
276
|
.cdc-dashboard-inner-container {
|
|
286
|
-
margin: 1em;
|
|
287
|
-
|
|
288
277
|
&.is-editor {
|
|
289
278
|
margin-top: 7em;
|
|
290
279
|
}
|
|
@@ -9,12 +9,12 @@ import { SharedFilter } from '../types/SharedFilter'
|
|
|
9
9
|
type ADD_FOOTNOTE = Action<'ADD_FOOTNOTE', { id: string; rowIndex: number; config: Footnotes }>
|
|
10
10
|
type ADD_VISUALIZATION = Action<'ADD_VISUALIZATION', { rowIdx: number; colIdx: number; newViz: AnyVisualization }>
|
|
11
11
|
type APPLY_CONFIG = Action<'APPLY_CONFIG', [Config, Object?]>
|
|
12
|
-
type DELETE_WIDGET = Action<'DELETE_WIDGET', {
|
|
12
|
+
type DELETE_WIDGET = Action<'DELETE_WIDGET', { uid: string }>
|
|
13
13
|
type MOVE_VISUALIZATION = Action<
|
|
14
14
|
'MOVE_VISUALIZATION',
|
|
15
15
|
{ rowIdx: number; colIdx: number; widget: AnyVisualization & { rowIdx: number; colIdx: number } }
|
|
16
16
|
>
|
|
17
|
-
type SET_CONFIG = Action<'SET_CONFIG', Partial<Config
|
|
17
|
+
type SET_CONFIG = Action<'SET_CONFIG', Partial<Config> & { activeDashboard?: number }>
|
|
18
18
|
type UPDATE_CONFIG = Action<'UPDATE_CONFIG', [Config, Object?]>
|
|
19
19
|
type SET_DATA = Action<'SET_DATA', Record<string, any[]>>
|
|
20
20
|
type SET_LOADING = Action<'SET_LOADING', boolean>
|
|
@@ -4,20 +4,20 @@ import { MultiDashboardConfig } from '../types/MultiDashboard'
|
|
|
4
4
|
import DashboardActions from './dashboard.actions'
|
|
5
5
|
import { devToolsWrapper } from '@cdc/core/helpers/withDevTools'
|
|
6
6
|
import { Tab } from '../types/Tab'
|
|
7
|
-
import {
|
|
7
|
+
import { Dashboard } from '../types/Dashboard'
|
|
8
8
|
import { ConfigRow } from '../types/ConfigRow'
|
|
9
9
|
import { AnyVisualization } from '@cdc/core/types/Visualization'
|
|
10
10
|
import { initialState } from '../DashboardContext'
|
|
11
11
|
|
|
12
12
|
type BlankMultiConfig = {
|
|
13
|
-
dashboard: Partial<
|
|
13
|
+
dashboard: Partial<Dashboard>
|
|
14
14
|
rows: Partial<ConfigRow>[]
|
|
15
15
|
visualizations: Record<string, Object>
|
|
16
16
|
table: Object
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const createBlankDashboard: () => BlankMultiConfig = () => ({
|
|
20
|
-
dashboard: {},
|
|
20
|
+
dashboard: { sharedFilters: [] },
|
|
21
21
|
rows: [{ columns: [{ width: 12 }] }],
|
|
22
22
|
visualizations: {},
|
|
23
23
|
table: {
|
|
@@ -71,7 +71,12 @@ const reducer = (state: DashboardState, action: DashboardActions): DashboardStat
|
|
|
71
71
|
return { ...initialState, config, filteredData, data }
|
|
72
72
|
}
|
|
73
73
|
case 'SET_CONFIG': {
|
|
74
|
-
|
|
74
|
+
if (
|
|
75
|
+
action.payload.activeDashboard === undefined ||
|
|
76
|
+
state.config.activeDashboard === action.payload.activeDashboard
|
|
77
|
+
) {
|
|
78
|
+
return { ...state, config: { ...state.config, ...action.payload } }
|
|
79
|
+
} else return state // ignore SET_CONFIG calls that have the wrong activeDashboard due to async api fetching
|
|
75
80
|
}
|
|
76
81
|
case 'SET_DATA': {
|
|
77
82
|
return { ...state, data: action.payload }
|
|
@@ -203,11 +208,9 @@ const reducer = (state: DashboardState, action: DashboardActions): DashboardStat
|
|
|
203
208
|
return { ...state, config: { ...state.config, rows: newRows } }
|
|
204
209
|
}
|
|
205
210
|
case 'DELETE_WIDGET': {
|
|
206
|
-
const {
|
|
211
|
+
const { uid } = action.payload
|
|
207
212
|
const newRows = _.cloneDeep(state.config.rows)
|
|
208
|
-
newRows[rowIdx].columns[colIdx].widget = null
|
|
209
213
|
const newVisualizations = _.cloneDeep(state.config.visualizations)
|
|
210
|
-
delete newVisualizations[uid]
|
|
211
214
|
const newSharedFilters = _.cloneDeep(state.config.dashboard.sharedFilters)
|
|
212
215
|
if (newSharedFilters && newSharedFilters.length > 0) {
|
|
213
216
|
newSharedFilters.forEach(sharedFilter => {
|
|
@@ -216,13 +219,19 @@ const reducer = (state: DashboardState, action: DashboardActions): DashboardStat
|
|
|
216
219
|
}
|
|
217
220
|
})
|
|
218
221
|
}
|
|
222
|
+
|
|
223
|
+
const filteredRows = _.map(newRows, row => ({
|
|
224
|
+
...row,
|
|
225
|
+
columns: _.filter(row.columns, column => column.widget !== uid)
|
|
226
|
+
}))
|
|
227
|
+
|
|
219
228
|
return {
|
|
220
229
|
...state,
|
|
221
230
|
config: {
|
|
222
231
|
...state.config,
|
|
223
232
|
dashboard: { ...state.config.dashboard, sharedFilters: newSharedFilters },
|
|
224
233
|
visualizations: newVisualizations,
|
|
225
|
-
rows:
|
|
234
|
+
rows: filteredRows
|
|
226
235
|
}
|
|
227
236
|
}
|
|
228
237
|
}
|
|
@@ -5,6 +5,7 @@ import { ConfigRow } from './ConfigRow'
|
|
|
5
5
|
import { AnyVisualization } from '@cdc/core/types/Visualization'
|
|
6
6
|
import { Table } from '@cdc/core/types/Table'
|
|
7
7
|
import { Dashboard } from './Dashboard'
|
|
8
|
+
import { Version } from '@cdc/core/types/Version'
|
|
8
9
|
|
|
9
10
|
export type DashboardConfig = DataSet & {
|
|
10
11
|
dashboard: Dashboard
|
|
@@ -18,4 +19,5 @@ export type DashboardConfig = DataSet & {
|
|
|
18
19
|
runtime: Runtime
|
|
19
20
|
downloadImageButton: boolean
|
|
20
21
|
downloadPdfButton: boolean
|
|
22
|
+
version: Version
|
|
21
23
|
}
|