@cdc/chart 4.24.9 → 4.24.11
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/LICENSE +201 -0
- package/dist/cdcchart.js +45911 -41739
- package/examples/feature/boxplot/boxplot-data.json +88 -22
- package/examples/feature/boxplot/boxplot.json +540 -16
- package/examples/feature/boxplot/testing.csv +7 -7
- package/examples/feature/sankey/sankey-example-data.json +0 -1
- package/examples/private/test.json +20092 -0
- package/index.html +4 -4
- package/package.json +2 -2
- package/src/CdcChart.tsx +209 -188
- package/src/_stories/Chart.CustomColors.stories.tsx +19 -0
- package/src/_stories/Chart.DynamicSeries.stories.tsx +27 -0
- package/src/_stories/Chart.Legend.Gradient.stories.tsx +74 -0
- package/src/_stories/Chart.stories.tsx +30 -3
- package/src/_stories/ChartAxisLabels.stories.tsx +20 -0
- package/src/_stories/ChartAxisTitles.stories.tsx +53 -0
- package/src/_stories/ChartEditor.stories.tsx +27 -0
- package/src/_stories/ChartLine.Suppression.stories.tsx +25 -0
- package/src/_stories/ChartPrefixSuffix.stories.tsx +159 -0
- package/src/_stories/_mock/boxplot_multiseries.json +647 -0
- package/src/_stories/_mock/dynamic_series_bar_config.json +723 -0
- package/src/_stories/_mock/dynamic_series_config.json +979 -0
- package/src/_stories/_mock/horizontal_bar.json +257 -0
- package/src/_stories/_mock/large_x_axis_labels.json +261 -0
- package/src/_stories/_mock/paired-bar.json +262 -0
- package/src/_stories/_mock/pie_with_data.json +255 -0
- package/{examples/feature/scatterplot/scatterplot.json → src/_stories/_mock/scatterplot_mock.json} +62 -92
- package/src/_stories/_mock/simplified_line.json +1510 -0
- package/src/_stories/_mock/suppression_mock.json +1549 -0
- package/src/components/Annotations/components/AnnotationDraggable.tsx +0 -3
- package/src/components/Annotations/components/AnnotationDropdown.tsx +1 -1
- package/src/components/Axis/Categorical.Axis.tsx +22 -4
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +95 -16
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +41 -17
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +43 -9
- package/src/components/BarChart/components/BarChart.Vertical.tsx +123 -47
- package/src/components/BarChart/helpers/index.ts +23 -5
- package/src/components/BoxPlot/BoxPlot.tsx +189 -0
- package/src/components/BrushChart.tsx +3 -2
- package/src/components/DeviationBar.jsx +58 -8
- package/src/components/EditorPanel/EditorPanel.tsx +127 -102
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +11 -28
- package/src/components/EditorPanel/components/Panels/Panel.BoxPlot.tsx +51 -6
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +21 -4
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +40 -9
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +121 -56
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +296 -35
- package/src/components/EditorPanel/components/panels.scss +4 -6
- package/src/components/EditorPanel/editor-panel.scss +0 -8
- package/src/components/EditorPanel/helpers/tests/updateFieldRankByValue.test.ts +38 -0
- package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +42 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +16 -1
- package/src/components/ForestPlot/ForestPlot.tsx +2 -3
- package/src/components/ForestPlot/ForestPlotProps.ts +2 -0
- package/src/components/Legend/Legend.Component.tsx +23 -24
- package/src/components/Legend/Legend.Suppression.tsx +25 -20
- package/src/components/Legend/Legend.tsx +16 -18
- package/src/components/Legend/helpers/index.ts +16 -19
- package/src/components/LegendWrapper.tsx +3 -1
- package/src/components/LineChart/components/LineChart.Circle.tsx +10 -0
- package/src/components/LineChart/helpers.ts +48 -43
- package/src/components/LineChart/index.tsx +88 -82
- package/src/components/LinearChart.tsx +747 -562
- package/src/components/PairedBarChart.jsx +50 -10
- package/src/components/PieChart/PieChart.tsx +1 -6
- package/src/components/Regions/components/Regions.tsx +33 -19
- package/src/components/Sankey/index.tsx +50 -32
- package/src/components/Sankey/sankey.scss +6 -5
- package/src/components/Sankey/useSankeyAlert.tsx +60 -0
- package/src/components/ScatterPlot/ScatterPlot.jsx +20 -4
- package/src/components/ZoomBrush.tsx +25 -6
- package/src/coreStyles_chart.scss +3 -0
- package/src/data/initial-state.js +8 -10
- package/src/helpers/configHelpers.ts +28 -0
- package/src/helpers/handleRankByValue.ts +15 -0
- package/src/helpers/sizeHelpers.ts +25 -0
- package/src/helpers/tests/handleRankByValue.test.ts +37 -0
- package/src/helpers/tests/sizeHelpers.test.ts +80 -0
- package/src/hooks/useColorPalette.js +10 -2
- package/src/hooks/useLegendClasses.ts +13 -22
- package/src/hooks/useMinMax.ts +27 -13
- package/src/hooks/useReduceData.ts +43 -10
- package/src/hooks/useScales.ts +87 -38
- package/src/hooks/useTooltip.tsx +62 -53
- package/src/index.jsx +1 -0
- package/src/scss/DataTable.scss +5 -4
- package/src/scss/main.scss +57 -70
- package/src/types/ChartConfig.ts +43 -34
- package/src/types/ChartContext.ts +22 -15
- package/src/types/ForestPlot.ts +8 -0
- package/src/_stories/Chart.Legend.Gradient.tsx +0 -19
- package/src/_stories/ChartBrush.stories.tsx +0 -19
- package/src/components/BoxPlot/BoxPlot.jsx +0 -111
- package/src/components/LinearChart.jsx +0 -817
package/src/CdcChart.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback, useRef, useId } from 'react'
|
|
1
|
+
import React, { useState, useEffect, useCallback, useRef, useId, useMemo } from 'react'
|
|
2
2
|
|
|
3
3
|
// IE11
|
|
4
4
|
import ResizeObserver from 'resize-observer-polyfill'
|
|
@@ -9,6 +9,7 @@ import Button from '@cdc/core/components/elements/Button'
|
|
|
9
9
|
|
|
10
10
|
//types
|
|
11
11
|
import { DimensionsType } from '@cdc/core/types/Dimensions'
|
|
12
|
+
import { type DashboardConfig } from '@cdc/dashboard/src/types/DashboardConfig'
|
|
12
13
|
|
|
13
14
|
// External Libraries
|
|
14
15
|
import { scaleOrdinal } from '@visx/scale'
|
|
@@ -34,10 +35,10 @@ import EditorPanel from './components/EditorPanel'
|
|
|
34
35
|
import { abbreviateNumber } from './helpers/abbreviateNumber'
|
|
35
36
|
import { handleChartTabbing } from './helpers/handleChartTabbing'
|
|
36
37
|
import { getQuartiles } from './helpers/getQuartiles'
|
|
37
|
-
import { sortAsc, sortDesc } from './helpers/sort'
|
|
38
38
|
import { handleChartAriaLabels } from './helpers/handleChartAriaLabels'
|
|
39
39
|
import { lineOptions } from './helpers/lineOptions'
|
|
40
40
|
import { handleLineType } from './helpers/handleLineType'
|
|
41
|
+
import { handleRankByValue } from './helpers/handleRankByValue'
|
|
41
42
|
import { generateColorsArray } from './helpers/generateColorsArray'
|
|
42
43
|
import Loading from '@cdc/core/components/Loading'
|
|
43
44
|
import Filters from '@cdc/core/components/Filters'
|
|
@@ -45,7 +46,6 @@ import MediaControls from '@cdc/core/components/MediaControls'
|
|
|
45
46
|
import Annotation from './components/Annotations'
|
|
46
47
|
|
|
47
48
|
// Helpers
|
|
48
|
-
import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
|
|
49
49
|
import { publish, subscribe, unsubscribe } from '@cdc/core/helpers/events'
|
|
50
50
|
import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses'
|
|
51
51
|
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
@@ -54,23 +54,42 @@ import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
|
54
54
|
import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
|
|
55
55
|
import isNumber from '@cdc/core/helpers/isNumber'
|
|
56
56
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
57
|
-
import { getQueryStringFilterValue } from '@cdc/core/helpers/queryStringUtils'
|
|
58
57
|
import { isConvertLineToBarGraph } from './helpers/isConvertLineToBarGraph'
|
|
58
|
+
import { isLegendWrapViewport } from '@cdc/core/helpers/viewports'
|
|
59
59
|
|
|
60
60
|
import './scss/main.scss'
|
|
61
61
|
// load both then config below determines which to use
|
|
62
62
|
import DataTable from '@cdc/core/components/DataTable'
|
|
63
|
+
import type { TableConfig } from '@cdc/core/components/DataTable/types/TableConfig'
|
|
63
64
|
import { getFileExtension } from '@cdc/core/helpers/getFileExtension'
|
|
64
65
|
import Title from '@cdc/core/components/ui/Title'
|
|
65
|
-
import { ChartConfig } from './types/ChartConfig'
|
|
66
|
+
import { AllChartsConfig, ChartConfig } from './types/ChartConfig'
|
|
66
67
|
import { Label } from './types/Label'
|
|
67
68
|
import { type ViewportSize } from './types/ChartConfig'
|
|
68
69
|
import { isSolrCsv, isSolrJson } from '@cdc/core/helpers/isSolr'
|
|
69
70
|
import SkipTo from '@cdc/core/components/elements/SkipTo'
|
|
70
71
|
import { filterVizData } from '@cdc/core/helpers/filterVizData'
|
|
71
72
|
import LegendWrapper from './components/LegendWrapper'
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
import _ from 'lodash'
|
|
74
|
+
import { addValuesToFilters } from '@cdc/core/helpers/addValuesToFilters'
|
|
75
|
+
import { Runtime } from '@cdc/core/types/Runtime'
|
|
76
|
+
import { Pivot } from '@cdc/core/types/Table'
|
|
77
|
+
|
|
78
|
+
interface CdcChartProps {
|
|
79
|
+
configUrl?: string
|
|
80
|
+
config?: ChartConfig
|
|
81
|
+
isEditor?: boolean
|
|
82
|
+
isDebug?: boolean
|
|
83
|
+
isDashboard?: boolean
|
|
84
|
+
setConfig?: (config: ChartConfig) => void
|
|
85
|
+
setEditing?: (editing: boolean) => void
|
|
86
|
+
hostname?: string
|
|
87
|
+
link?: string
|
|
88
|
+
setSharedFilter?: (filter: any) => void
|
|
89
|
+
setSharedFilterValue?: (value: any) => void
|
|
90
|
+
dashboardConfig?: DashboardConfig
|
|
91
|
+
}
|
|
92
|
+
const CdcChart = ({
|
|
74
93
|
configUrl,
|
|
75
94
|
config: configObj,
|
|
76
95
|
isEditor = false,
|
|
@@ -83,12 +102,13 @@ export default function CdcChart({
|
|
|
83
102
|
setSharedFilter,
|
|
84
103
|
setSharedFilterValue,
|
|
85
104
|
dashboardConfig
|
|
86
|
-
}) {
|
|
105
|
+
}: CdcChartProps) => {
|
|
87
106
|
const transform = new DataTransform()
|
|
88
107
|
const [loading, setLoading] = useState(true)
|
|
108
|
+
const svgRef = useRef(null)
|
|
89
109
|
const [colorScale, setColorScale] = useState(null)
|
|
90
110
|
const [config, setConfig] = useState<ChartConfig>({} as ChartConfig)
|
|
91
|
-
const [stateData, setStateData] = useState(
|
|
111
|
+
const [stateData, setStateData] = useState(_.cloneDeep(configObj?.data) || [])
|
|
92
112
|
const [excludedData, setExcludedData] = useState<Record<string, number>[] | undefined>(undefined)
|
|
93
113
|
const [filteredData, setFilteredData] = useState<Record<string, any>[] | undefined>(undefined)
|
|
94
114
|
const [seriesHighlight, setSeriesHighlight] = useState<string[]>(
|
|
@@ -108,19 +128,10 @@ export default function CdcChart({
|
|
|
108
128
|
isBrushing: false
|
|
109
129
|
})
|
|
110
130
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const useMobileVertical = config.heights?.mobileVertical && ['xs', 'xxs'].includes(currentViewport)
|
|
114
|
-
const responsiveVertical = useMobileVertical ? 'mobileVertical' : 'vertical'
|
|
115
|
-
const renderedOrientation = useVertical ? responsiveVertical : 'horizontal'
|
|
116
|
-
let height = config.aspectRatio ? width * config.aspectRatio : config?.heights?.[renderedOrientation]
|
|
117
|
-
if (config.visualizationType === 'Pie') height = config?.heights?.[renderedOrientation]
|
|
118
|
-
height = height + Number(config?.xAxis?.size) + 45
|
|
119
|
-
|
|
120
|
-
type Config = typeof config
|
|
121
|
-
let legendMemo = useRef(new Map()) // map collection
|
|
122
|
-
let innerContainerRef = useRef()
|
|
131
|
+
const { description, visualizationType } = config
|
|
132
|
+
|
|
123
133
|
const legendRef = useRef(null)
|
|
134
|
+
const parentRef = useRef(null)
|
|
124
135
|
|
|
125
136
|
const handleDragStateChange = isDragging => {
|
|
126
137
|
setIsDraggingAnnotation(isDragging)
|
|
@@ -129,7 +140,7 @@ export default function CdcChart({
|
|
|
129
140
|
if (isDebug) console.log('Chart config, isEditor', config, isEditor)
|
|
130
141
|
|
|
131
142
|
// Destructure items from config for more readable JSX
|
|
132
|
-
let { legend, title
|
|
143
|
+
let { legend, title } = config
|
|
133
144
|
|
|
134
145
|
// set defaults on titles if blank AND only in editor
|
|
135
146
|
if (isEditor) {
|
|
@@ -138,7 +149,7 @@ export default function CdcChart({
|
|
|
138
149
|
|
|
139
150
|
if (config.table && (!config.table?.label || config.table?.label === '')) config.table.label = 'Data Table'
|
|
140
151
|
|
|
141
|
-
const {
|
|
152
|
+
const { lineDatapointClass, contentClasses, sparkLineStyles } = useDataVizClasses(config)
|
|
142
153
|
const legendId = useId()
|
|
143
154
|
|
|
144
155
|
const checkLineToBarGraph = () => {
|
|
@@ -201,6 +212,8 @@ export default function CdcChart({
|
|
|
201
212
|
|
|
202
213
|
Object.assign(data, { urlFiltered: true })
|
|
203
214
|
|
|
215
|
+
data = handleRankByValue(data, config)
|
|
216
|
+
|
|
204
217
|
updateConfig({ ...config, runtimeDataUrl: dataUrlFinal, data, formattedData: data })
|
|
205
218
|
|
|
206
219
|
if (data) {
|
|
@@ -212,7 +225,7 @@ export default function CdcChart({
|
|
|
212
225
|
}
|
|
213
226
|
|
|
214
227
|
const loadConfig = async () => {
|
|
215
|
-
|
|
228
|
+
const response = _.cloneDeep(configObj) || (await (await fetch(configUrl)).json())
|
|
216
229
|
|
|
217
230
|
// If data is included through a URL, fetch that and store
|
|
218
231
|
let data: any[] = response.data || []
|
|
@@ -263,6 +276,8 @@ export default function CdcChart({
|
|
|
263
276
|
data = transform.developerStandardize(data, response.dataDescription)
|
|
264
277
|
}
|
|
265
278
|
|
|
279
|
+
data = handleRankByValue(data, response)
|
|
280
|
+
|
|
266
281
|
if (data) {
|
|
267
282
|
setStateData(data)
|
|
268
283
|
setExcludedData(data)
|
|
@@ -276,18 +291,7 @@ export default function CdcChart({
|
|
|
276
291
|
}
|
|
277
292
|
}
|
|
278
293
|
let newConfig = { ...defaults, ...response }
|
|
279
|
-
if (newConfig.filters) {
|
|
280
|
-
newConfig.filters.forEach((filter, index) => {
|
|
281
|
-
const queryStringFilterValue = getQueryStringFilterValue(filter)
|
|
282
|
-
if (queryStringFilterValue) {
|
|
283
|
-
newConfig.filters[index].active = queryStringFilterValue
|
|
284
|
-
}
|
|
285
|
-
})
|
|
286
|
-
}
|
|
287
294
|
|
|
288
|
-
if (newConfig.visualizationType === 'Box Plot') {
|
|
289
|
-
newConfig.legend.hide = true
|
|
290
|
-
}
|
|
291
295
|
if (undefined === newConfig.table.show) newConfig.table.show = !isDashboard
|
|
292
296
|
|
|
293
297
|
newConfig.series.forEach(series => {
|
|
@@ -306,9 +310,12 @@ export default function CdcChart({
|
|
|
306
310
|
updateConfig(processedConfig, data)
|
|
307
311
|
}
|
|
308
312
|
|
|
309
|
-
const updateConfig = (
|
|
313
|
+
const updateConfig = (_config: AllChartsConfig, dataOverride?: any[]) => {
|
|
314
|
+
const newConfig = _.cloneDeep(_config)
|
|
310
315
|
let data = dataOverride || stateData
|
|
311
316
|
|
|
317
|
+
data = handleRankByValue(data, newConfig)
|
|
318
|
+
|
|
312
319
|
// Deeper copy
|
|
313
320
|
Object.keys(defaults).forEach(key => {
|
|
314
321
|
if (newConfig[key] && 'object' === typeof newConfig[key] && !Array.isArray(newConfig[key])) {
|
|
@@ -356,28 +363,8 @@ export default function CdcChart({
|
|
|
356
363
|
// After data is grabbed, loop through and generate filter column values if there are any
|
|
357
364
|
let currentData: any[] = []
|
|
358
365
|
if (newConfig.filters) {
|
|
359
|
-
newConfig.filters
|
|
360
|
-
|
|
361
|
-
filter.filterStyle === 'nested-dropdown'
|
|
362
|
-
? filter.values
|
|
363
|
-
: filter.orderedValues ||
|
|
364
|
-
generateValuesForFilter(filter.columnName, newExcludedData).sort(
|
|
365
|
-
filter.order === 'desc' ? sortDesc : sortAsc
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
newConfig.filters[index].values = filterValues
|
|
369
|
-
// Initial filter should be active
|
|
370
|
-
|
|
371
|
-
const includes = (arr: any[], val: any): boolean => (arr || []).map(val => String(val)).includes(String(val))
|
|
372
|
-
newConfig.filters[index].active =
|
|
373
|
-
!newConfig.filters[index].active || !includes(filterValues, newConfig.filters[index].active)
|
|
374
|
-
? filterValues[0]
|
|
375
|
-
: newConfig.filters[index].active
|
|
376
|
-
newConfig.filters[index].filterStyle = newConfig.filters[index].filterStyle
|
|
377
|
-
? newConfig.filters[index].filterStyle
|
|
378
|
-
: 'dropdown'
|
|
379
|
-
})
|
|
380
|
-
currentData = filterVizData(newConfig.filters, newExcludedData)
|
|
366
|
+
const filtersWithValues = addValuesToFilters(newConfig.filters, newExcludedData)
|
|
367
|
+
currentData = filterVizData(filtersWithValues, newExcludedData)
|
|
381
368
|
setFilteredData(currentData)
|
|
382
369
|
}
|
|
383
370
|
|
|
@@ -386,19 +373,18 @@ export default function CdcChart({
|
|
|
386
373
|
}
|
|
387
374
|
|
|
388
375
|
//Enforce default values that need to be calculated at runtime
|
|
389
|
-
newConfig.runtime = {}
|
|
390
|
-
newConfig.runtime.series = newConfig.dynamicSeries ? [] : newConfig.series
|
|
376
|
+
newConfig.runtime = {} as Runtime
|
|
377
|
+
newConfig.runtime.series = newConfig.dynamicSeries ? [] : _.cloneDeep(newConfig.series)
|
|
391
378
|
newConfig.runtime.seriesLabels = {}
|
|
392
379
|
newConfig.runtime.seriesLabelsAll = []
|
|
393
380
|
newConfig.runtime.originalXAxis = newConfig.xAxis
|
|
394
381
|
|
|
395
382
|
if (newConfig.dynamicSeries) {
|
|
396
383
|
let finalData = dataOverride || newConfig.formattedData || newConfig.data
|
|
397
|
-
if (finalData
|
|
384
|
+
if (finalData?.length) {
|
|
398
385
|
Object.keys(finalData[0]).forEach(seriesKey => {
|
|
399
386
|
if (
|
|
400
387
|
seriesKey !== newConfig.xAxis.dataKey &&
|
|
401
|
-
finalData[0][seriesKey] &&
|
|
402
388
|
(!newConfig.filters || newConfig.filters.filter(filter => filter.columnName === seriesKey).length === 0) &&
|
|
403
389
|
(!newConfig.columns || Object.keys(newConfig.columns).indexOf(seriesKey) === -1)
|
|
404
390
|
) {
|
|
@@ -417,30 +403,42 @@ export default function CdcChart({
|
|
|
417
403
|
newConfig.runtime.seriesKeys = (dataOverride || data).map(d => d[newConfig.xAxis.dataKey])
|
|
418
404
|
newConfig.runtime.seriesLabelsAll = newConfig.runtime.seriesKeys
|
|
419
405
|
} else {
|
|
420
|
-
newConfig.
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
406
|
+
const finalData = dataOverride || newConfig.formattedData || newConfig.data
|
|
407
|
+
newConfig.runtime.seriesKeys = (newConfig.runtime.series || []).flatMap(series => {
|
|
408
|
+
if (series.dynamicCategory) {
|
|
409
|
+
_.remove(newConfig.runtime.seriesLabelsAll, label => label === series.dataKey)
|
|
410
|
+
_.remove(newConfig.runtime.series, s => s.dataKey === series.dataKey)
|
|
411
|
+
// grab the dynamic series keys from the data
|
|
412
|
+
const seriesKeys: string[] = _.uniq(finalData.map(d => d[series.dynamicCategory]))
|
|
413
|
+
// for each of those keys perform side effects
|
|
414
|
+
seriesKeys.forEach(dataKey => {
|
|
415
|
+
newConfig.runtime.seriesLabels[dataKey] = dataKey
|
|
416
|
+
newConfig.runtime.seriesLabelsAll.push(dataKey)
|
|
417
|
+
newConfig.runtime.series.push({
|
|
418
|
+
dataKey,
|
|
419
|
+
type: series.type,
|
|
420
|
+
lineType: series.lineType,
|
|
421
|
+
originalDataKey: series.dataKey,
|
|
422
|
+
dynamicCategory: series.dynamicCategory,
|
|
423
|
+
tooltip: true
|
|
424
|
+
})
|
|
425
425
|
})
|
|
426
|
-
|
|
426
|
+
// return the series keys
|
|
427
|
+
return seriesKeys
|
|
428
|
+
} else {
|
|
429
|
+
newConfig.runtime.seriesLabels[series.dataKey] = series.name || series.label || series.dataKey
|
|
430
|
+
newConfig.runtime.seriesLabelsAll.push(series.name || series.dataKey)
|
|
431
|
+
// return the series keys
|
|
432
|
+
return [series.dataKey]
|
|
433
|
+
}
|
|
434
|
+
})
|
|
427
435
|
}
|
|
428
436
|
|
|
429
437
|
if (newConfig.visualizationType === 'Box Plot' && newConfig.series) {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
let allValues = newExcludedData
|
|
434
|
-
? newExcludedData.map(d => Number(d[newConfig?.series[0]?.dataKey]))
|
|
435
|
-
: data.map(d => Number(d[newConfig?.series[0]?.dataKey]))
|
|
436
|
-
|
|
437
|
-
const uniqueArray = function (arrArg) {
|
|
438
|
-
return arrArg.filter(function (elem, pos, arr) {
|
|
439
|
-
return arr.indexOf(elem) === pos
|
|
440
|
-
})
|
|
441
|
-
}
|
|
438
|
+
const combinedData = filteredData || data
|
|
439
|
+
let allKeys = combinedData.map(d => d[newConfig.xAxis.dataKey])
|
|
440
|
+
const groups = _.uniq(allKeys)
|
|
442
441
|
|
|
443
|
-
const groups = uniqueArray(allKeys)
|
|
444
442
|
let tableData: any[] = []
|
|
445
443
|
const plots: any[] = []
|
|
446
444
|
|
|
@@ -452,9 +450,8 @@ export default function CdcChart({
|
|
|
452
450
|
if (!g) throw new Error('No groups resolved in box plots')
|
|
453
451
|
|
|
454
452
|
// filter data by group
|
|
455
|
-
let filteredData =
|
|
456
|
-
|
|
457
|
-
: data.filter(item => item[newConfig.xAxis.dataKey] === g)
|
|
453
|
+
let filteredData = combinedData.filter(item => item[newConfig.xAxis.dataKey] === g)
|
|
454
|
+
|
|
458
455
|
let filteredDataValues: number[] = filteredData.map(item => Number(item[newConfig?.series[0]?.dataKey]))
|
|
459
456
|
|
|
460
457
|
// Sort the data for upcoming functions.
|
|
@@ -463,16 +460,18 @@ export default function CdcChart({
|
|
|
463
460
|
// ! - Notice d3.quantile doesn't work here, and we had to take a custom route.
|
|
464
461
|
const quartiles = getQuartiles(sortedData)
|
|
465
462
|
|
|
466
|
-
|
|
467
|
-
|
|
463
|
+
const getValuesBySeriesKey = () => {
|
|
464
|
+
const allSeriesKeys = newConfig.series.map(item => item?.dataKey)
|
|
465
|
+
const result = {}
|
|
466
|
+
allSeriesKeys.forEach(key => {
|
|
467
|
+
result[key] = filteredData.map(item => item[key])
|
|
468
|
+
})
|
|
468
469
|
|
|
469
|
-
|
|
470
|
-
newConfig.boxplot.firstQuartilePercentage = 0
|
|
470
|
+
return result
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
if (
|
|
474
|
-
|
|
475
|
-
}
|
|
473
|
+
if (!filteredData) throw new Error('boxplots dont have data yet')
|
|
474
|
+
if (!plots) throw new Error('boxplots dont have plots yet')
|
|
476
475
|
|
|
477
476
|
const q1 = quartiles.q1
|
|
478
477
|
const q3 = quartiles.q3
|
|
@@ -481,9 +480,7 @@ export default function CdcChart({
|
|
|
481
480
|
const upperBounds = q3 + (q3 - q1) * 1.5
|
|
482
481
|
|
|
483
482
|
const outliers = sortedData.filter(v => v < lowerBounds || v > upperBounds)
|
|
484
|
-
let nonOutliers = filteredDataValues
|
|
485
483
|
|
|
486
|
-
nonOutliers = nonOutliers.filter(item => !outliers.includes(item))
|
|
487
484
|
const minValue: number = d3.min<number>(filteredDataValues) || 0
|
|
488
485
|
const _colMin = d3.max<number>([minValue, q1 - 1.5 * iqr])
|
|
489
486
|
plots.push({
|
|
@@ -493,7 +490,7 @@ export default function CdcChart({
|
|
|
493
490
|
columnMedian: Number(d3.median(filteredDataValues)).toFixed(newConfig.dataFormat.roundTo),
|
|
494
491
|
columnFirstQuartile: q1.toFixed(newConfig.dataFormat.roundTo),
|
|
495
492
|
columnMin: _colMin,
|
|
496
|
-
|
|
493
|
+
columnCount: filteredData.length,
|
|
497
494
|
columnSd: Number(d3.deviation(filteredDataValues)).toFixed(newConfig.dataFormat.roundTo),
|
|
498
495
|
columnMean: Number(d3.mean(filteredDataValues)).toFixed(newConfig.dataFormat.roundTo),
|
|
499
496
|
columnIqr: Number(iqr).toFixed(newConfig.dataFormat.roundTo),
|
|
@@ -501,7 +498,7 @@ export default function CdcChart({
|
|
|
501
498
|
columnUpperBounds: d3.min([d3.max(sortedData), q1 + 1.5 * iqr]),
|
|
502
499
|
columnOutliers: outliers,
|
|
503
500
|
values: filteredDataValues,
|
|
504
|
-
|
|
501
|
+
keyValues: getValuesBySeriesKey()
|
|
505
502
|
})
|
|
506
503
|
} catch (e) {
|
|
507
504
|
console.error('COVE: ', e.message) // eslint-disable-line
|
|
@@ -519,8 +516,6 @@ export default function CdcChart({
|
|
|
519
516
|
return null // resolve eslint
|
|
520
517
|
})
|
|
521
518
|
|
|
522
|
-
// any other data we can add to boxplots
|
|
523
|
-
newConfig.boxplot['allValues'] = allValues
|
|
524
519
|
newConfig.boxplot['categories'] = groups
|
|
525
520
|
newConfig.boxplot.plots = plots
|
|
526
521
|
newConfig.boxplot.tableData = tableData
|
|
@@ -580,6 +575,7 @@ export default function CdcChart({
|
|
|
580
575
|
) {
|
|
581
576
|
newConfig.runtime.xAxis = newConfig.yAxis['yAxis'] ? newConfig.yAxis['yAxis'] : newConfig.yAxis
|
|
582
577
|
newConfig.runtime.yAxis = newConfig.xAxis['xAxis'] ? newConfig.xAxis['xAxis'] : newConfig.xAxis
|
|
578
|
+
newConfig.runtime.yAxis.labelOffset *= -1
|
|
583
579
|
|
|
584
580
|
newConfig.runtime.horizontal = false
|
|
585
581
|
newConfig.orientation = 'horizontal'
|
|
@@ -618,21 +614,6 @@ export default function CdcChart({
|
|
|
618
614
|
setConfig(newConfig)
|
|
619
615
|
}
|
|
620
616
|
|
|
621
|
-
// Gets filter values from dataset
|
|
622
|
-
const generateValuesForFilter = (columnName, data = this.state.data) => {
|
|
623
|
-
const values: any[] = []
|
|
624
|
-
|
|
625
|
-
data.forEach(row => {
|
|
626
|
-
const value = row[columnName]
|
|
627
|
-
//@ts-ignore
|
|
628
|
-
if (value && false === values.includes(value)) {
|
|
629
|
-
values.push(value)
|
|
630
|
-
}
|
|
631
|
-
})
|
|
632
|
-
|
|
633
|
-
return values
|
|
634
|
-
}
|
|
635
|
-
|
|
636
617
|
// Sorts data series for horizontal bar charts
|
|
637
618
|
const sortData = (a, b) => {
|
|
638
619
|
let sortKey =
|
|
@@ -655,7 +636,6 @@ export default function CdcChart({
|
|
|
655
636
|
const resizeObserver = new ResizeObserver(entries => {
|
|
656
637
|
for (let entry of entries) {
|
|
657
638
|
let { width, height } = entry.contentRect
|
|
658
|
-
let svgMarginWidth = 32
|
|
659
639
|
let editorWidth = 350
|
|
660
640
|
|
|
661
641
|
width = isEditor ? width - editorWidth : width
|
|
@@ -668,7 +648,7 @@ export default function CdcChart({
|
|
|
668
648
|
width = width - 2.5
|
|
669
649
|
}
|
|
670
650
|
|
|
671
|
-
width = width
|
|
651
|
+
width = width
|
|
672
652
|
|
|
673
653
|
setDimensions([width, height])
|
|
674
654
|
}
|
|
@@ -682,14 +662,14 @@ export default function CdcChart({
|
|
|
682
662
|
setContainer(node)
|
|
683
663
|
}, []) // eslint-disable-line
|
|
684
664
|
|
|
685
|
-
|
|
665
|
+
const isEmpty = obj => {
|
|
686
666
|
return Object.keys(obj).length === 0
|
|
687
667
|
}
|
|
688
668
|
|
|
689
669
|
// Load data when component first mounts
|
|
690
670
|
useEffect(() => {
|
|
691
671
|
loadConfig()
|
|
692
|
-
}, []) // eslint-disable-line
|
|
672
|
+
}, [configObj?.data?.length ? configObj.data : null]) // eslint-disable-line
|
|
693
673
|
|
|
694
674
|
useEffect(() => {
|
|
695
675
|
reloadURLData()
|
|
@@ -753,14 +733,6 @@ export default function CdcChart({
|
|
|
753
733
|
}
|
|
754
734
|
}, [externalFilters]) // eslint-disable-line
|
|
755
735
|
|
|
756
|
-
// Load data when configObj data changes
|
|
757
|
-
if (configObj) {
|
|
758
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
759
|
-
useEffect(() => {
|
|
760
|
-
loadConfig()
|
|
761
|
-
}, [configObj.data]) // eslint-disable-line
|
|
762
|
-
}
|
|
763
|
-
|
|
764
736
|
// This will set the bump chart's default scaling type to date-time
|
|
765
737
|
useEffect(() => {
|
|
766
738
|
if (['Bump Chart'].includes(config.visualizationType)) {
|
|
@@ -875,8 +847,23 @@ export default function CdcChart({
|
|
|
875
847
|
}
|
|
876
848
|
}
|
|
877
849
|
|
|
878
|
-
const formatDate = date => {
|
|
879
|
-
|
|
850
|
+
const formatDate = (date, i, ticks) => {
|
|
851
|
+
let formattedDate = timeFormat(config.runtime[section].dateDisplayFormat)(date)
|
|
852
|
+
// Handle the case where all months work with '%b.' except for May
|
|
853
|
+
if (config.runtime[section].dateDisplayFormat?.includes('%b.') && formattedDate.includes('May.')) {
|
|
854
|
+
formattedDate = formattedDate.replace(/May\./g, 'May')
|
|
855
|
+
}
|
|
856
|
+
// Show years only once
|
|
857
|
+
if (config.xAxis.showYearsOnce && config.runtime[section].dateDisplayFormat?.includes('%Y') && ticks) {
|
|
858
|
+
const prevDate = ticks[i - 1] ? ticks[i - 1].value : null
|
|
859
|
+
const prevFormattedDate = timeFormat(config.runtime[section].dateDisplayFormat)(prevDate)
|
|
860
|
+
const year = formattedDate.match(/\d{4}/)
|
|
861
|
+
const prevYear = prevFormattedDate.match(/\d{4}/)
|
|
862
|
+
if (year && prevYear && year[0] === prevYear[0]) {
|
|
863
|
+
formattedDate = formattedDate.replace(year, '')
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
return formattedDate
|
|
880
867
|
}
|
|
881
868
|
|
|
882
869
|
const formatTooltipsDate = date => {
|
|
@@ -886,7 +873,16 @@ export default function CdcChart({
|
|
|
886
873
|
// Format numeric data based on settings in config OR from passed in settings for Additional Columns
|
|
887
874
|
// - use only for old horizontal data - newer formatNumber is in helper/formatNumber
|
|
888
875
|
// TODO: we should combine various formatNumber functions across this project.
|
|
889
|
-
|
|
876
|
+
// TODO suggestion: pass all options as object key/values to allow for more flexibility
|
|
877
|
+
const formatNumber = (
|
|
878
|
+
num,
|
|
879
|
+
axis,
|
|
880
|
+
shouldAbbreviate = false,
|
|
881
|
+
addColPrefix,
|
|
882
|
+
addColSuffix,
|
|
883
|
+
addColRoundTo,
|
|
884
|
+
{ index, length } = { index: null, length: null }
|
|
885
|
+
) => {
|
|
890
886
|
// if num is NaN return num
|
|
891
887
|
if (isNaN(num) || !num) return num
|
|
892
888
|
// Check if the input number is negative
|
|
@@ -913,7 +909,8 @@ export default function CdcChart({
|
|
|
913
909
|
rightSuffix,
|
|
914
910
|
bottomPrefix,
|
|
915
911
|
bottomSuffix,
|
|
916
|
-
bottomAbbreviated
|
|
912
|
+
bottomAbbreviated,
|
|
913
|
+
onlyShowTopPrefixSuffix
|
|
917
914
|
}
|
|
918
915
|
} = config
|
|
919
916
|
|
|
@@ -1006,7 +1003,9 @@ export default function CdcChart({
|
|
|
1006
1003
|
if (addColPrefix && axis === 'left') {
|
|
1007
1004
|
result = addColPrefix + result
|
|
1008
1005
|
} else {
|
|
1009
|
-
if
|
|
1006
|
+
// if onlyShowTopPrefixSuffix only show top prefix
|
|
1007
|
+
const suppressAllButLast = onlyShowTopPrefixSuffix && length - 1 !== index
|
|
1008
|
+
if (prefix && axis === 'left' && !suppressAllButLast) {
|
|
1010
1009
|
result += prefix
|
|
1011
1010
|
}
|
|
1012
1011
|
}
|
|
@@ -1025,7 +1024,7 @@ export default function CdcChart({
|
|
|
1025
1024
|
if (addColSuffix && axis === 'left') {
|
|
1026
1025
|
result += addColSuffix
|
|
1027
1026
|
} else {
|
|
1028
|
-
if (suffix && axis === 'left') {
|
|
1027
|
+
if (suffix && axis === 'left' && !onlyShowTopPrefixSuffix) {
|
|
1029
1028
|
result += suffix
|
|
1030
1029
|
}
|
|
1031
1030
|
}
|
|
@@ -1161,7 +1160,7 @@ export default function CdcChart({
|
|
|
1161
1160
|
<h3>Finish Configuring</h3>
|
|
1162
1161
|
<p>Set all required options to the left and confirm below to display a preview of the chart.</p>
|
|
1163
1162
|
<Button
|
|
1164
|
-
className='btn'
|
|
1163
|
+
className='btn btn-primary'
|
|
1165
1164
|
style={{ margin: '1em auto' }}
|
|
1166
1165
|
disabled={missingRequiredSections()}
|
|
1167
1166
|
onClick={e => confirmDone(e)}
|
|
@@ -1218,12 +1217,31 @@ export default function CdcChart({
|
|
|
1218
1217
|
// cleaning is deleting data we need in forecasting charts.
|
|
1219
1218
|
if (!Array.isArray(data)) return []
|
|
1220
1219
|
if (config.visualizationType === 'Forecasting') return data
|
|
1220
|
+
if (config.series?.some(series => !!series.dynamicCategory)) return data
|
|
1221
1221
|
return config?.xAxis?.dataKey ? transform.cleanData(data, config.xAxis.dataKey) : data
|
|
1222
1222
|
}
|
|
1223
1223
|
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1224
|
+
const getTableRuntimeData = () => {
|
|
1225
|
+
if (visualizationType === 'Sankey') return config?.data?.[0]?.tableData
|
|
1226
|
+
const data = filteredData || excludedData
|
|
1227
|
+
const dynamicSeries = config.series.find(series => !!series.dynamicCategory)
|
|
1228
|
+
if (!dynamicSeries) return data
|
|
1229
|
+
const usedColumns = Object.values(config.columns)
|
|
1230
|
+
.filter(col => col.dataTable)
|
|
1231
|
+
.map(col => col.name)
|
|
1232
|
+
.concat([dynamicSeries.dynamicCategory, dynamicSeries.dataKey])
|
|
1233
|
+
if (config.xAxis?.dataKey) usedColumns.push(config.xAxis.dataKey)
|
|
1234
|
+
return data.map(d => _.pick(d, usedColumns))
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
const pivotDynamicSeries = (config: ChartConfig): TableConfig => {
|
|
1238
|
+
const tableConfig: TableConfig = _.cloneDeep(config)
|
|
1239
|
+
const dynamicSeries = tableConfig.series.find(series => !!series.dynamicCategory)
|
|
1240
|
+
if (dynamicSeries) {
|
|
1241
|
+
const pivot: Pivot = { columnName: dynamicSeries.dynamicCategory, valueColumns: [dynamicSeries.dataKey] }
|
|
1242
|
+
tableConfig.table.pivot = pivot
|
|
1243
|
+
}
|
|
1244
|
+
return tableConfig
|
|
1227
1245
|
}
|
|
1228
1246
|
|
|
1229
1247
|
// Prevent render if loading
|
|
@@ -1235,10 +1253,10 @@ export default function CdcChart({
|
|
|
1235
1253
|
}
|
|
1236
1254
|
|
|
1237
1255
|
const getChartWrapperClasses = () => {
|
|
1238
|
-
const isLegendOnBottom = legend?.position === 'bottom' ||
|
|
1256
|
+
const isLegendOnBottom = legend?.position === 'bottom' || isLegendWrapViewport(currentViewport)
|
|
1239
1257
|
const classes = ['chart-container', 'p-relative']
|
|
1240
1258
|
if (legend?.position) {
|
|
1241
|
-
if (
|
|
1259
|
+
if (isLegendWrapViewport(currentViewport) && legend?.position !== 'top') {
|
|
1242
1260
|
classes.push('legend-bottom')
|
|
1243
1261
|
} else {
|
|
1244
1262
|
classes.push(`legend-${legend.position}`)
|
|
@@ -1255,7 +1273,7 @@ export default function CdcChart({
|
|
|
1255
1273
|
|
|
1256
1274
|
const getChartSubTextClasses = () => {
|
|
1257
1275
|
const classes = ['subtext ']
|
|
1258
|
-
const isLegendOnBottom = legend?.position === 'bottom' ||
|
|
1276
|
+
const isLegendOnBottom = legend?.position === 'bottom' || isLegendWrapViewport(currentViewport)
|
|
1259
1277
|
|
|
1260
1278
|
if (config.isResponsiveTicks) classes.push('subtext--responsive-ticks ')
|
|
1261
1279
|
if (config.brush?.active && !isLegendOnBottom) classes.push('subtext--brush-active ')
|
|
@@ -1291,42 +1309,38 @@ export default function CdcChart({
|
|
|
1291
1309
|
classes={['chart-title', `${config.theme}`, 'cove-component__header']}
|
|
1292
1310
|
style={undefined}
|
|
1293
1311
|
/>
|
|
1294
|
-
{/* Intro Text/Message */}
|
|
1295
|
-
{config?.introText && config.visualizationType !== 'Spark Line' && (
|
|
1296
|
-
<section
|
|
1297
|
-
className={`introText legend_${config.legend.hide ? 'hidden' : 'visible'}_${config.legend.position} `}
|
|
1298
|
-
>
|
|
1299
|
-
{parse(config.introText)}
|
|
1300
|
-
</section>
|
|
1301
|
-
)}
|
|
1302
|
-
|
|
1303
|
-
{/* Filters */}
|
|
1304
|
-
{config.filters && !externalFilters && config.visualizationType !== 'Spark Line' && (
|
|
1305
|
-
<Filters
|
|
1306
|
-
config={config}
|
|
1307
|
-
setConfig={setConfig}
|
|
1308
|
-
setFilteredData={setFilteredData}
|
|
1309
|
-
filteredData={filteredData}
|
|
1310
|
-
excludedData={excludedData}
|
|
1311
|
-
filterData={filterVizData}
|
|
1312
|
-
dimensions={dimensions}
|
|
1313
|
-
/>
|
|
1314
|
-
)}
|
|
1315
|
-
<SkipTo skipId={handleChartTabbing(config, legendId)} skipMessage='Skip Over Chart Container' />
|
|
1316
|
-
{config.annotations?.length > 0 && (
|
|
1317
|
-
<SkipTo
|
|
1318
|
-
skipId={handleChartTabbing(config, legendId)}
|
|
1319
|
-
skipMessage={`Skip over annotations`}
|
|
1320
|
-
key={`skip-annotations`}
|
|
1321
|
-
/>
|
|
1322
|
-
)}
|
|
1323
1312
|
|
|
1324
1313
|
{/* Visualization Wrapper */}
|
|
1325
1314
|
<div className={getChartWrapperClasses().join(' ')}>
|
|
1315
|
+
{/* Intro Text/Message */}
|
|
1316
|
+
{config?.introText && config.visualizationType !== 'Spark Line' && (
|
|
1317
|
+
<section className={`introText `}>{parse(config.introText)}</section>
|
|
1318
|
+
)}
|
|
1319
|
+
|
|
1320
|
+
{/* Filters */}
|
|
1321
|
+
{config.filters && !externalFilters && config.visualizationType !== 'Spark Line' && (
|
|
1322
|
+
<Filters
|
|
1323
|
+
config={config}
|
|
1324
|
+
setConfig={setConfig}
|
|
1325
|
+
setFilteredData={setFilteredData}
|
|
1326
|
+
filteredData={filteredData}
|
|
1327
|
+
excludedData={excludedData}
|
|
1328
|
+
filterData={filterVizData}
|
|
1329
|
+
dimensions={dimensions}
|
|
1330
|
+
/>
|
|
1331
|
+
)}
|
|
1332
|
+
<SkipTo skipId={handleChartTabbing(config, legendId)} skipMessage='Skip Over Chart Container' />
|
|
1333
|
+
{config.annotations?.length > 0 && (
|
|
1334
|
+
<SkipTo
|
|
1335
|
+
skipId={handleChartTabbing(config, legendId)}
|
|
1336
|
+
skipMessage={`Skip over annotations`}
|
|
1337
|
+
key={`skip-annotations`}
|
|
1338
|
+
/>
|
|
1339
|
+
)}
|
|
1326
1340
|
<LegendWrapper>
|
|
1327
1341
|
<div
|
|
1328
1342
|
className={
|
|
1329
|
-
legend.hide ||
|
|
1343
|
+
legend.hide || isLegendWrapViewport(currentViewport)
|
|
1330
1344
|
? 'w-100'
|
|
1331
1345
|
: legend.position === 'bottom' || legend.position === 'top' || visualizationType === 'Sankey'
|
|
1332
1346
|
? 'w-100'
|
|
@@ -1335,30 +1349,36 @@ export default function CdcChart({
|
|
|
1335
1349
|
>
|
|
1336
1350
|
{/* All charts with LinearChart */}
|
|
1337
1351
|
{!['Spark Line', 'Line', 'Sankey', 'Pie', 'Sankey'].includes(config.visualizationType) && (
|
|
1338
|
-
<div style={{
|
|
1352
|
+
<div ref={parentRef} style={{ width: `100%` }}>
|
|
1339
1353
|
<ParentSize>
|
|
1340
|
-
{parent =>
|
|
1354
|
+
{parent => (
|
|
1355
|
+
<LinearChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />
|
|
1356
|
+
)}
|
|
1341
1357
|
</ParentSize>
|
|
1342
1358
|
</div>
|
|
1343
1359
|
)}
|
|
1344
1360
|
|
|
1345
1361
|
{config.visualizationType === 'Pie' && (
|
|
1346
|
-
<ParentSize className='justify-content-center d-flex' style={{
|
|
1347
|
-
{parent => <PieChart parentWidth={parent.width} parentHeight={parent.height} />}
|
|
1362
|
+
<ParentSize className='justify-content-center d-flex' style={{ width: `100%` }}>
|
|
1363
|
+
{parent => <PieChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />}
|
|
1348
1364
|
</ParentSize>
|
|
1349
1365
|
)}
|
|
1350
1366
|
{/* Line Chart */}
|
|
1351
1367
|
{config.visualizationType === 'Line' &&
|
|
1352
1368
|
(checkLineToBarGraph() ? (
|
|
1353
|
-
<div style={{
|
|
1369
|
+
<div ref={parentRef} style={{ width: `100%` }}>
|
|
1354
1370
|
<ParentSize>
|
|
1355
|
-
{parent =>
|
|
1371
|
+
{parent => (
|
|
1372
|
+
<LinearChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />
|
|
1373
|
+
)}
|
|
1356
1374
|
</ParentSize>
|
|
1357
1375
|
</div>
|
|
1358
1376
|
) : (
|
|
1359
|
-
<div style={{
|
|
1377
|
+
<div ref={parentRef} style={{ width: `100%` }}>
|
|
1360
1378
|
<ParentSize>
|
|
1361
|
-
{parent =>
|
|
1379
|
+
{parent => (
|
|
1380
|
+
<LinearChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />
|
|
1381
|
+
)}
|
|
1362
1382
|
</ParentSize>
|
|
1363
1383
|
</div>
|
|
1364
1384
|
))}
|
|
@@ -1412,7 +1432,6 @@ export default function CdcChart({
|
|
|
1412
1432
|
{description && config.visualizationType !== 'Spark Line' && (
|
|
1413
1433
|
<div className={getChartSubTextClasses().join('')}>{parse(description)}</div>
|
|
1414
1434
|
)}
|
|
1415
|
-
{false && <Annotation.List />}
|
|
1416
1435
|
|
|
1417
1436
|
{/* buttons */}
|
|
1418
1437
|
<MediaControls.Section classes={['download-buttons']}>
|
|
@@ -1442,7 +1461,7 @@ export default function CdcChart({
|
|
|
1442
1461
|
config.visualizationType !== 'Sankey') ||
|
|
1443
1462
|
(config.visualizationType === 'Sankey' && config.table.show)) && (
|
|
1444
1463
|
<DataTable
|
|
1445
|
-
config={config}
|
|
1464
|
+
config={pivotDynamicSeries(config)}
|
|
1446
1465
|
rawData={
|
|
1447
1466
|
config.visualizationType === 'Sankey'
|
|
1448
1467
|
? config?.data?.[0]?.tableData
|
|
@@ -1450,15 +1469,11 @@ export default function CdcChart({
|
|
|
1450
1469
|
? filterVizData(config.filters, config.data)
|
|
1451
1470
|
: config.data
|
|
1452
1471
|
}
|
|
1453
|
-
runtimeData={
|
|
1454
|
-
config.visualizationType === 'Sankey'
|
|
1455
|
-
? config?.data?.[0]?.tableData
|
|
1456
|
-
: filteredData || excludedData
|
|
1457
|
-
}
|
|
1472
|
+
runtimeData={getTableRuntimeData()}
|
|
1458
1473
|
expandDataTable={config.table.expanded}
|
|
1459
1474
|
columns={config.columns}
|
|
1460
1475
|
displayDataAsText={displayDataAsText}
|
|
1461
|
-
displayGeoName={
|
|
1476
|
+
displayGeoName={name => name}
|
|
1462
1477
|
applyLegendToRow={applyLegendToRow}
|
|
1463
1478
|
tableTitle={config.table.label}
|
|
1464
1479
|
indexTitle={config.table.indexLabel}
|
|
@@ -1501,32 +1516,35 @@ export default function CdcChart({
|
|
|
1501
1516
|
debugSvg: isDebug,
|
|
1502
1517
|
dimensions,
|
|
1503
1518
|
dynamicLegendItems,
|
|
1504
|
-
excludedData
|
|
1519
|
+
excludedData,
|
|
1505
1520
|
formatDate,
|
|
1506
1521
|
formatNumber,
|
|
1507
1522
|
formatTooltipsDate,
|
|
1508
|
-
getTextWidth,
|
|
1509
1523
|
getXAxisData,
|
|
1510
1524
|
getYAxisData,
|
|
1511
1525
|
handleChartAriaLabels,
|
|
1512
1526
|
handleLineType,
|
|
1527
|
+
handleChartTabbing,
|
|
1513
1528
|
highlight,
|
|
1514
1529
|
highlightReset,
|
|
1515
1530
|
imageId,
|
|
1516
1531
|
isDashboard,
|
|
1517
|
-
isLegendBottom: legend?.position === 'bottom' ||
|
|
1532
|
+
isLegendBottom: legend?.position === 'bottom' || isLegendWrapViewport(currentViewport),
|
|
1518
1533
|
isDebug,
|
|
1519
1534
|
isDraggingAnnotation,
|
|
1520
1535
|
handleDragStateChange,
|
|
1521
1536
|
isEditor,
|
|
1522
1537
|
isNumber,
|
|
1523
1538
|
legend,
|
|
1539
|
+
legendId,
|
|
1540
|
+
legendRef,
|
|
1524
1541
|
lineOptions,
|
|
1525
1542
|
loading,
|
|
1526
1543
|
missingRequiredSections,
|
|
1527
1544
|
outerContainerRef,
|
|
1545
|
+
parentRef,
|
|
1528
1546
|
parseDate,
|
|
1529
|
-
rawData: stateData ?? {},
|
|
1547
|
+
rawData: _.cloneDeep(stateData) ?? {},
|
|
1530
1548
|
seriesHighlight,
|
|
1531
1549
|
setBrushConfig,
|
|
1532
1550
|
setConfig,
|
|
@@ -1537,10 +1555,11 @@ export default function CdcChart({
|
|
|
1537
1555
|
setSeriesHighlight,
|
|
1538
1556
|
setSharedFilter,
|
|
1539
1557
|
setSharedFilterValue,
|
|
1558
|
+
svgRef,
|
|
1540
1559
|
tableData: filteredData || excludedData, // do not clean table data
|
|
1541
1560
|
transformedData: clean(filteredData || excludedData), // do this right before passing to components
|
|
1542
1561
|
twoColorPalette,
|
|
1543
|
-
unfilteredData: stateData,
|
|
1562
|
+
unfilteredData: _.cloneDeep(stateData),
|
|
1544
1563
|
updateConfig
|
|
1545
1564
|
}
|
|
1546
1565
|
|
|
@@ -1559,3 +1578,5 @@ export default function CdcChart({
|
|
|
1559
1578
|
</ConfigContext.Provider>
|
|
1560
1579
|
)
|
|
1561
1580
|
}
|
|
1581
|
+
|
|
1582
|
+
export default CdcChart
|