@cdc/chart 4.23.3 → 4.23.4
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/cdcchart.js +24397 -24193
- package/examples/feature/__data__/area-chart.json +56 -0
- package/examples/{planet-example-data.json → feature/__data__/planet-example-data.json} +16 -4
- package/examples/{area-chart.json → feature/area/area-chart.json} +70 -13
- package/examples/{horizontal-chart-max-increase.json → feature/bar/horizontal-chart-max-increase.json} +10 -4
- package/examples/{horizontal-chart.json → feature/bar/horizontal-chart.json} +10 -4
- package/examples/{horizontal-stacked-bar-chart.json → feature/bar/horizontal-stacked-bar-chart.json} +7 -3
- package/examples/{planet-chart-horizontal-example-config.json → feature/bar/planet-chart-horizontal-example-config.json} +8 -3
- package/examples/{planet-example-config.json → feature/bar/planet-example-config.json} +2 -2
- package/examples/{box-plot.json → feature/boxplot/boxplot.json} +7 -7
- package/examples/feature/boxplot/testing.csv +38 -0
- package/examples/feature/combo/combochart-categories_are_numbers .json +18 -0
- package/examples/{planet-combo-example-config.json → feature/combo/planet-combo-example-config.json} +1 -1
- package/examples/{planet-deviation-config.json → feature/deviation/planet-deviation-config.json} +2 -2
- package/examples/{planet-deviation-data.json → feature/deviation/planet-deviation-data.json} +9 -9
- package/examples/feature/filters/filter-testing.json +178 -0
- package/examples/feature/forecasting/case_date_example.csv +130 -0
- package/examples/feature/forecasting/effective_reproduction.json +202 -0
- package/examples/feature/forecasting/r_data.csv +130 -0
- package/examples/feature/line/line-chart.json +124 -0
- package/examples/{paired-bar-example.json → feature/paired-bar/paired-bar-example.json} +10 -4
- package/examples/{planet-pie-example-config.json → feature/pie/planet-pie-example-config.json} +2 -2
- package/examples/{scatterplot.json → feature/scatterplot/scatterplot.json} +1 -1
- package/examples/{case-rate-example-config.json → feature/tests-case-rate/case-rate-example-config.json} +2 -2
- package/examples/{covid-confidence-example-config.json → feature/tests-covid/covid-confidence-example-config.json} +8 -3
- package/examples/{covid-example-config.json → feature/tests-covid/covid-example-config.json} +7 -3
- package/examples/{cutoff-example-config.json → feature/tests-cutoff/cutoff-example-config.json} +7 -3
- package/examples/{date-exclusions-config.json → feature/tests-date-exclusions/date-exclusions-config.json} +2 -2
- package/examples/{example-bar-chart-nonnumeric.json → feature/tests-non-numerics/example-bar-chart-nonnumeric.json} +1 -1
- package/examples/{planet-pie-example-config-nonnumeric.json → feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json} +2 -2
- package/examples/{sparkline-chart-nonnumeric.json → feature/tests-non-numerics/sparkline-chart-nonnumeric.json} +1 -1
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +145 -7
- package/examples/gallery/paired-bar/paired-bar-chart.json +1 -0
- package/index.html +73 -49
- package/package.json +2 -2
- package/src/CdcChart.jsx +111 -26
- package/src/components/AreaChart.jsx +105 -70
- package/src/components/BarChart.jsx +45 -28
- package/src/components/BoxPlot.jsx +28 -20
- package/src/components/DataTable.jsx +7 -6
- package/src/components/DeviationBar.jsx +2 -2
- package/src/components/EditorPanel.jsx +252 -193
- package/src/components/Legend.jsx +1 -1
- package/src/components/LineChart.jsx +10 -16
- package/src/components/LinearChart.jsx +30 -34
- package/src/components/PairedBarChart.jsx +6 -6
- package/src/components/PieChart.jsx +2 -4
- package/src/components/SparkLine.jsx +6 -42
- package/src/data/initial-state.js +7 -3
- package/src/index.jsx +2 -1
- package/src/scss/editor-panel.scss +15 -0
- package/src/scss/main.scss +8 -6
- package/examples/box-plot.csv +0 -5
- package/examples/dynamic-legends.json +0 -125
- package/examples/line-chart.json +0 -34
- package/examples/temp-example-config.json +0 -64
- package/examples/temp-example-data.json +0 -130
- package/src/components/Filters.jsx +0 -126
- /package/examples/{age-adjusted-rates.json → feature/__data__/age-adjusted-rates.json} +0 -0
- /package/examples/{new-data.csv → feature/__data__/new-data.csv} +0 -0
- /package/examples/{planet-example-data-max-increase.json → feature/__data__/planet-example-data-max-increase.json} +0 -0
- /package/examples/{Barchart_with_negative.json → feature/bar/Barchart_with_negative.json} +0 -0
- /package/examples/{example-bar-chart.json → feature/bar/example-bar-chart.json} +0 -0
- /package/examples/{stacked-vertical-bar-example-negative.json → feature/bar/stacked-vertical-bar-example-negative.json} +0 -0
- /package/examples/{stacked-vertical-bar-example.json → feature/bar/stacked-vertical-bar-example.json} +0 -0
- /package/examples/{box-plot-data.json → feature/boxplot/box-plot-data.json} +0 -0
- /package/examples/{newdata.json → feature/boxplot/boxplot-data.json} +0 -0
- /package/examples/{line-chart-max-increase.json → feature/line/line-chart-max-increase.json} +0 -0
- /package/examples/{paired-bar-data.json → feature/paired-bar/paired-bar-data.json} +0 -0
- /package/examples/{paired-bar-formatted.json → feature/paired-bar/paired-bar-formatted.json} +0 -0
- /package/examples/{scatterplot-continuous.csv → feature/scatterplot/scatterplot-continuous.csv} +0 -0
- /package/examples/{example-sparkline.json → feature/sparkline/example-sparkline.json} +0 -0
- /package/examples/{big-small-test-bar.json → feature/tests-big-small/big-small-test-bar.json} +0 -0
- /package/examples/{big-small-test-line.json → feature/tests-big-small/big-small-test-line.json} +0 -0
- /package/examples/{big-small-test-negative.json → feature/tests-big-small/big-small-test-negative.json} +0 -0
- /package/examples/{case-rate-example-data.json → feature/tests-case-rate/case-rate-example-data.json} +0 -0
- /package/examples/{covid-example-data-confidence.json → feature/tests-covid/covid-example-data-confidence.json} +0 -0
- /package/examples/{covid-example-data.json → feature/tests-covid/covid-example-data.json} +0 -0
- /package/examples/{cutoff-example-data.json → feature/tests-cutoff/cutoff-example-data.json} +0 -0
- /package/examples/{date-exclusions-data.json → feature/tests-date-exclusions/date-exclusions-data.json} +0 -0
- /package/examples/{example-combo-bar-nonnumeric.json → feature/tests-non-numerics/example-combo-bar-nonnumeric.json} +0 -0
- /package/examples/{line-chart-nonnumeric.json → feature/tests-non-numerics/line-chart-nonnumeric.json} +0 -0
- /package/examples/{planet-example-data-nonnumeric.json → feature/tests-non-numerics/planet-example-data-nonnumeric.json} +0 -0
- /package/examples/{stacked-vertical-bar-example-nonnumerics.json → feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json} +0 -0
|
@@ -18,6 +18,7 @@ import Icon from '@cdc/core/components/ui/Icon'
|
|
|
18
18
|
import useReduceData from '../hooks/useReduceData'
|
|
19
19
|
import useRightAxis from '../hooks/useRightAxis'
|
|
20
20
|
import * as allCurves from '@visx/curve'
|
|
21
|
+
import { useFilters } from '@cdc/core/components/Filters'
|
|
21
22
|
|
|
22
23
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
23
24
|
const TextField = memo(({ label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', i = null, min = null, ...attributes }) => {
|
|
@@ -71,7 +72,7 @@ const TextField = memo(({ label, tooltip, section = null, subsection = null, fie
|
|
|
71
72
|
})
|
|
72
73
|
|
|
73
74
|
const CheckBox = memo(({ label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes }) => (
|
|
74
|
-
<label className='checkbox'>
|
|
75
|
+
<label className='checkbox column-heading'>
|
|
75
76
|
<input
|
|
76
77
|
type='checkbox'
|
|
77
78
|
name={fieldName}
|
|
@@ -206,12 +207,23 @@ const Regions = memo(({ config, updateConfig }) => {
|
|
|
206
207
|
const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
|
|
207
208
|
|
|
208
209
|
const EditorPanel = () => {
|
|
209
|
-
const { config, updateConfig, transformedData: data, loading, colorPalettes, twoColorPalette, unfilteredData, excludedData, isDashboard, setParentConfig, missingRequiredSections } = useContext(ConfigContext)
|
|
210
|
+
const { config, updateConfig, transformedData: data, loading, colorPalettes, twoColorPalette, unfilteredData, excludedData, isDashboard, setParentConfig, missingRequiredSections, isDebug, setFilteredData } = useContext(ConfigContext)
|
|
210
211
|
|
|
211
212
|
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, unfilteredData)
|
|
212
213
|
|
|
213
214
|
const { twoColorPalettes, sequential, nonSequential } = useColorPalette(config, updateConfig)
|
|
214
215
|
|
|
216
|
+
// argument acts as props
|
|
217
|
+
const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({ config, setConfig: updateConfig, filteredData: data, setFilteredData })
|
|
218
|
+
|
|
219
|
+
const approvedCurveTypes = {
|
|
220
|
+
Linear: 'curveLinear',
|
|
221
|
+
Cardinal: 'curveCardinal',
|
|
222
|
+
Natural: 'curveNatural',
|
|
223
|
+
'Monotone X': 'curveMonotoneX',
|
|
224
|
+
Step: 'curveStep'
|
|
225
|
+
}
|
|
226
|
+
|
|
215
227
|
// when the visualization type changes we
|
|
216
228
|
// have to update the individual series type & axis details
|
|
217
229
|
// dataKey is unchanged here.
|
|
@@ -249,21 +261,6 @@ const EditorPanel = () => {
|
|
|
249
261
|
|
|
250
262
|
const { hasRightAxis } = useRightAxis({ config: config, yMax: config.yAxis.size, data: config.data, updateConfig })
|
|
251
263
|
|
|
252
|
-
const filterOptions = [
|
|
253
|
-
{
|
|
254
|
-
label: 'Ascending Alphanumeric',
|
|
255
|
-
value: 'asc'
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
label: 'Descending Alphanumeric',
|
|
259
|
-
value: 'desc'
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
label: 'Custom',
|
|
263
|
-
value: 'cust'
|
|
264
|
-
}
|
|
265
|
-
]
|
|
266
|
-
|
|
267
264
|
const getItemStyle = (isDragging, draggableStyle) => ({
|
|
268
265
|
...draggableStyle
|
|
269
266
|
})
|
|
@@ -481,6 +478,16 @@ const EditorPanel = () => {
|
|
|
481
478
|
}
|
|
482
479
|
}
|
|
483
480
|
|
|
481
|
+
const getFilters = () => {
|
|
482
|
+
let columns = {}
|
|
483
|
+
|
|
484
|
+
unfilteredData.forEach(row => {
|
|
485
|
+
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
return Object.keys(columns)
|
|
489
|
+
}
|
|
490
|
+
|
|
484
491
|
const getColumns = (filter = true) => {
|
|
485
492
|
let columns = {}
|
|
486
493
|
|
|
@@ -637,23 +644,6 @@ const EditorPanel = () => {
|
|
|
637
644
|
)
|
|
638
645
|
}, [config]) // eslint-disable-line
|
|
639
646
|
|
|
640
|
-
const checkIsLine = type => {
|
|
641
|
-
return type === ('Line' || 'dashed-sm')
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
const handleFilterChange = (idx1, idx2, filterIndex, filter) => {
|
|
645
|
-
let filterOrder = filter.values
|
|
646
|
-
let [movedItem] = filterOrder.splice(idx1, 1)
|
|
647
|
-
filterOrder.splice(idx2, 0, movedItem)
|
|
648
|
-
let filters = [...config.filters]
|
|
649
|
-
let filterItem = { ...config.filters[filterIndex] }
|
|
650
|
-
filterItem.active = filter.values[0]
|
|
651
|
-
filterItem.orderedValues = filterOrder
|
|
652
|
-
filterItem.order = 'cust'
|
|
653
|
-
filters[filterIndex] = filterItem
|
|
654
|
-
updateConfig({ ...config, filters })
|
|
655
|
-
}
|
|
656
|
-
|
|
657
647
|
const visHasLegend = () => {
|
|
658
648
|
const { visualizationType } = config
|
|
659
649
|
|
|
@@ -668,6 +658,8 @@ const EditorPanel = () => {
|
|
|
668
658
|
const visCanAnimate = () => {
|
|
669
659
|
const { visualizationType } = config
|
|
670
660
|
switch (visualizationType) {
|
|
661
|
+
case 'Area Chart':
|
|
662
|
+
return false
|
|
671
663
|
case 'Scatter Plot':
|
|
672
664
|
return false
|
|
673
665
|
case 'Box Plot':
|
|
@@ -692,6 +684,8 @@ const EditorPanel = () => {
|
|
|
692
684
|
const visHasLabelOnData = () => {
|
|
693
685
|
const { visualizationType } = config
|
|
694
686
|
switch (visualizationType) {
|
|
687
|
+
case 'Area Chart':
|
|
688
|
+
return false
|
|
695
689
|
case 'Box Plot':
|
|
696
690
|
return false
|
|
697
691
|
case 'Pie':
|
|
@@ -760,10 +754,13 @@ const EditorPanel = () => {
|
|
|
760
754
|
case config.visualizationType === 'Combo' && isAllLine && enteredValue && parseFloat(enteredValue) > minVal:
|
|
761
755
|
message = 'Value must be less than ' + minValue
|
|
762
756
|
break
|
|
763
|
-
case (config.visualizationType === 'Bar' ||
|
|
757
|
+
case (config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && enteredValue && minVal > 0 && parseFloat(enteredValue) > 0:
|
|
764
758
|
message = 'Value must be less than or equal to 0'
|
|
765
759
|
break
|
|
766
|
-
case
|
|
760
|
+
case config.visualizationType === 'Deviation Bar' && parseFloat(enteredValue) >= Math.min(minVal, config.xAxis.target):
|
|
761
|
+
message = 'Value must be less than ' + Math.min(minVal, config.xAxis.target)
|
|
762
|
+
break
|
|
763
|
+
case config.visualizationType !== 'Deviation Bar' && enteredValue && minVal < 0 && parseFloat(enteredValue) > minVal:
|
|
767
764
|
message = 'Value must be less than ' + minValue
|
|
768
765
|
break
|
|
769
766
|
default:
|
|
@@ -778,19 +775,54 @@ const EditorPanel = () => {
|
|
|
778
775
|
validateMaxValue()
|
|
779
776
|
}, [minValue, maxValue, config]) // eslint-disable-line
|
|
780
777
|
|
|
778
|
+
// prettier-ignore
|
|
781
779
|
const enabledChartTypes = [
|
|
782
|
-
'
|
|
783
|
-
'Line',
|
|
780
|
+
// 'Area Chart',
|
|
784
781
|
'Bar',
|
|
782
|
+
'Box Plot',
|
|
785
783
|
'Combo',
|
|
784
|
+
'Deviation Bar',
|
|
785
|
+
'Line',
|
|
786
786
|
'Paired Bar',
|
|
787
|
-
'
|
|
788
|
-
// 'Area Chart',
|
|
787
|
+
'Pie',
|
|
789
788
|
'Scatter Plot',
|
|
790
|
-
'
|
|
791
|
-
'Deviation Bar'
|
|
789
|
+
'Spark Line'
|
|
792
790
|
]
|
|
793
791
|
|
|
792
|
+
const isLoadedFromUrl = config?.dataKey?.includes('http://') || config?.dataKey?.includes('https://')
|
|
793
|
+
|
|
794
|
+
// if isDebug = true, then try to set the category and data col to reduce clicking
|
|
795
|
+
const setCategoryAxis = () => {
|
|
796
|
+
// only for debug mode
|
|
797
|
+
if (undefined !== isDebug && isDebug && !config?.xAxis?.dataKey) {
|
|
798
|
+
// then try to set the x axis to appropriate value so we dont have to manually do it
|
|
799
|
+
let datakeys = getColumns(false)
|
|
800
|
+
if (datakeys.includes('Date')) return 'Date'
|
|
801
|
+
if (datakeys.includes('Race')) return 'Race'
|
|
802
|
+
// add other known Category cols here to extend debug
|
|
803
|
+
}
|
|
804
|
+
return ''
|
|
805
|
+
}
|
|
806
|
+
const setDataColumn = () => {
|
|
807
|
+
// only for debug mode
|
|
808
|
+
if (undefined !== isDebug && isDebug && getColumns(false).length > 0) {
|
|
809
|
+
// then try to set the x axis to appropriate value so we dont have to manually do it
|
|
810
|
+
let datacols = getColumns(false).filter(x => x !== 'Date' && x !== 'Race')
|
|
811
|
+
if (datacols.length > 0) {
|
|
812
|
+
return datacols[0]
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
return ''
|
|
816
|
+
}
|
|
817
|
+
if (isDebug && !config.xAxis.dataKey) config.xAxis.dataKey = setCategoryAxis()
|
|
818
|
+
if (isDebug && config?.series?.length === 0) {
|
|
819
|
+
let setdatacol = setDataColumn()
|
|
820
|
+
if (setdatacol !== '') addNewSeries(setdatacol)
|
|
821
|
+
if (isDebug) console.log('### COVE DEBUG: Chart: Setting default datacol=', setdatacol) // eslint-disable-line
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
const chartsWithOptions = ['Area Chart', 'Combo', 'Line']
|
|
825
|
+
|
|
794
826
|
return (
|
|
795
827
|
<ErrorBoundary component='EditorPanel'>
|
|
796
828
|
{config.newViz && <Confirm />}
|
|
@@ -932,6 +964,18 @@ const EditorPanel = () => {
|
|
|
932
964
|
<AccordionItemPanel>
|
|
933
965
|
{(!config.series || config.series.length === 0) && config.visualizationType !== 'Paired Bar' && <p className='warning'>At least one series is required</p>}
|
|
934
966
|
{(!config.series || config.series.length === 0 || config.series.length < 2) && config.visualizationType === 'Paired Bar' && <p className='warning'>Select two data series for paired bar chart (e.g., Male and Female).</p>}
|
|
967
|
+
<Select
|
|
968
|
+
fieldName='visualizationType'
|
|
969
|
+
label='Add Data Series'
|
|
970
|
+
initial='Select'
|
|
971
|
+
onChange={e => {
|
|
972
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
973
|
+
addNewSeries(e.target.value)
|
|
974
|
+
}
|
|
975
|
+
e.target.value = ''
|
|
976
|
+
}}
|
|
977
|
+
options={getColumns()}
|
|
978
|
+
/>
|
|
935
979
|
{config.series && config.series.length !== 0 && (
|
|
936
980
|
<>
|
|
937
981
|
<fieldset>
|
|
@@ -949,7 +993,7 @@ const EditorPanel = () => {
|
|
|
949
993
|
<DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
|
|
950
994
|
<Droppable droppableId='filter_order'>
|
|
951
995
|
{provided => (
|
|
952
|
-
<ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}
|
|
996
|
+
<ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
|
|
953
997
|
{config.series.map((series, i) => {
|
|
954
998
|
if (config.visualizationType === 'Combo' || 'Area Chart') {
|
|
955
999
|
let changeType = (i, value) => {
|
|
@@ -968,78 +1012,129 @@ const EditorPanel = () => {
|
|
|
968
1012
|
}
|
|
969
1013
|
|
|
970
1014
|
let typeDropdown = (
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1015
|
+
<>
|
|
1016
|
+
<label htmlFor='type-dropdown'>Series Type</label>
|
|
1017
|
+
<select
|
|
1018
|
+
name='type-dropdown'
|
|
1019
|
+
value={series.type}
|
|
1020
|
+
onChange={event => {
|
|
1021
|
+
changeType(i, event.target.value)
|
|
1022
|
+
}}
|
|
1023
|
+
>
|
|
1024
|
+
<option value='' default key='default'>
|
|
1025
|
+
Select
|
|
1026
|
+
</option>
|
|
1027
|
+
{config.visualizationType === 'Combo' && <option value='Bar'>Bar</option>}
|
|
1028
|
+
<option value='Line' key='Line'>
|
|
1029
|
+
Solid Line
|
|
1030
|
+
</option>
|
|
1031
|
+
<option value='dashed-sm' key='dashed-sm'>
|
|
1032
|
+
Small Dashed
|
|
1033
|
+
</option>
|
|
1034
|
+
<option value='dashed-md' key='dashed-md'>
|
|
1035
|
+
Medium Dashed
|
|
1036
|
+
</option>
|
|
1037
|
+
<option value='dashed-lg' key='dashed-lg'>
|
|
1038
|
+
Large Dashed
|
|
1039
|
+
</option>
|
|
1040
|
+
<option value='Area Chart' key='Area Chart'>
|
|
1041
|
+
Area
|
|
1042
|
+
</option>
|
|
1043
|
+
</select>
|
|
1044
|
+
</>
|
|
1045
|
+
)
|
|
1046
|
+
|
|
1047
|
+
// used for assigning axis
|
|
1048
|
+
let changeAxis = (i, value) => {
|
|
1049
|
+
let series = [...config.series]
|
|
1050
|
+
series[i].axis = value
|
|
1051
|
+
updateConfig({ ...config, series })
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// assign an axis dropdown
|
|
1055
|
+
let axisDropdown = (
|
|
1056
|
+
<>
|
|
1057
|
+
<label htmlFor='assign-axis'>Assign an axis</label>
|
|
1058
|
+
<select
|
|
1059
|
+
name='assign-axis'
|
|
1060
|
+
value={series.axis}
|
|
1061
|
+
onChange={event => {
|
|
1062
|
+
changeAxis(i, event.target.value)
|
|
1063
|
+
}}
|
|
1064
|
+
>
|
|
1065
|
+
<option value='Left' default key='left'>
|
|
1066
|
+
left
|
|
1067
|
+
</option>
|
|
1068
|
+
<option value='Right' key='right'>
|
|
1069
|
+
right
|
|
1070
|
+
</option>
|
|
1071
|
+
</select>
|
|
1072
|
+
</>
|
|
995
1073
|
)
|
|
996
1074
|
|
|
1075
|
+
// line type dropdown
|
|
997
1076
|
const lineType = (
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
{Object.keys(allCurves).map(curveName => (
|
|
1011
|
-
<option key={`curve-option-${curveName}`} value={curveName}>
|
|
1012
|
-
{curveName}
|
|
1077
|
+
<>
|
|
1078
|
+
<label htmlFor='line-type'>Line Type</label>
|
|
1079
|
+
<select
|
|
1080
|
+
name='line-type'
|
|
1081
|
+
value={series.lineStyle}
|
|
1082
|
+
onChange={event => {
|
|
1083
|
+
changeLineType(i, event.target.value)
|
|
1084
|
+
}}
|
|
1085
|
+
key='lineTypeSelection'
|
|
1086
|
+
>
|
|
1087
|
+
<option value='' default>
|
|
1088
|
+
Select
|
|
1013
1089
|
</option>
|
|
1014
|
-
|
|
1015
|
-
|
|
1090
|
+
|
|
1091
|
+
{Object.keys(approvedCurveTypes).map(curveName => {
|
|
1092
|
+
return (
|
|
1093
|
+
<option key={`curve-option-${approvedCurveTypes[curveName]}`} value={approvedCurveTypes[curveName]}>
|
|
1094
|
+
{curveName}
|
|
1095
|
+
</option>
|
|
1096
|
+
)
|
|
1097
|
+
})}
|
|
1098
|
+
</select>
|
|
1099
|
+
</>
|
|
1016
1100
|
)
|
|
1017
1101
|
|
|
1018
1102
|
return (
|
|
1019
1103
|
<Draggable key={series.dataKey} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
|
|
1020
1104
|
{(provided, snapshot) => (
|
|
1021
|
-
|
|
1022
|
-
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
1023
|
-
<div className={`series-list__name${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}>
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1105
|
+
<>
|
|
1106
|
+
<div key={i} className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
1107
|
+
<div className={`series-list__name ${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}></div>
|
|
1108
|
+
<Accordion allowZeroExpanded>
|
|
1109
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
1110
|
+
<AccordionItemHeading className='series-item__title'>
|
|
1111
|
+
<AccordionItemButton className={chartsWithOptions.includes(config.visualizationType) ? 'accordion__button' : 'accordion__button hide-arrow'}>
|
|
1112
|
+
<Icon display='move' size={15} style={{ cursor: 'default' }} />
|
|
1113
|
+
{series.dataKey}
|
|
1114
|
+
{config.series && config.series.length > 1 && (
|
|
1115
|
+
<button className='series-list__remove' onClick={() => removeSeries(series.dataKey)}>
|
|
1116
|
+
Remove
|
|
1117
|
+
</button>
|
|
1118
|
+
)}
|
|
1119
|
+
</AccordionItemButton>
|
|
1120
|
+
</AccordionItemHeading>
|
|
1121
|
+
{chartsWithOptions.includes(config.visualizationType) && (
|
|
1122
|
+
<AccordionItemPanel>
|
|
1123
|
+
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
1124
|
+
{config.visualizationType === 'Combo' && (
|
|
1125
|
+
<>
|
|
1126
|
+
<span className='series-list__dropdown series-item__dropdown'>{typeDropdown}</span>
|
|
1127
|
+
{hasRightAxis && config.series && (series.type === 'Line' || series.type === 'dashed-sm' || series.type === 'dashed-md' || series.type === 'dashed-lg') && <span className='series-item__dropdown series-list__dropdown'>{axisDropdown}</span>}
|
|
1128
|
+
</>
|
|
1129
|
+
)}
|
|
1130
|
+
{['Line', 'dashed-sm', 'dashed-md', 'dashed-lg', 'Area Chart'].some(item => item.includes(series.type)) && <span className='series-item__dropdown series-list__dropdown series-list__dropdown--lineType'>{lineType}</span>}
|
|
1131
|
+
</div>
|
|
1132
|
+
</AccordionItemPanel>
|
|
1033
1133
|
)}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
×
|
|
1037
|
-
</button>
|
|
1038
|
-
)}
|
|
1039
|
-
</>
|
|
1040
|
-
</span>
|
|
1134
|
+
</AccordionItem>
|
|
1135
|
+
</Accordion>
|
|
1041
1136
|
</div>
|
|
1042
|
-
|
|
1137
|
+
</>
|
|
1043
1138
|
)}
|
|
1044
1139
|
</Draggable>
|
|
1045
1140
|
)
|
|
@@ -1079,19 +1174,6 @@ const EditorPanel = () => {
|
|
|
1079
1174
|
</>
|
|
1080
1175
|
)}
|
|
1081
1176
|
|
|
1082
|
-
<Select
|
|
1083
|
-
fieldName='visualizationType'
|
|
1084
|
-
label='Add Data Series'
|
|
1085
|
-
initial='Select'
|
|
1086
|
-
onChange={e => {
|
|
1087
|
-
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
1088
|
-
addNewSeries(e.target.value)
|
|
1089
|
-
}
|
|
1090
|
-
e.target.value = ''
|
|
1091
|
-
}}
|
|
1092
|
-
options={getColumns()}
|
|
1093
|
-
/>
|
|
1094
|
-
|
|
1095
1177
|
{config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
|
|
1096
1178
|
<>
|
|
1097
1179
|
<span className='divider-heading'>Confidence Keys</span>
|
|
@@ -1282,72 +1364,6 @@ const EditorPanel = () => {
|
|
|
1282
1364
|
</AccordionItem>
|
|
1283
1365
|
)}
|
|
1284
1366
|
|
|
1285
|
-
{hasRightAxis && config.series && config.visualizationType === 'Combo' && (
|
|
1286
|
-
<AccordionItem>
|
|
1287
|
-
<AccordionItemHeading>
|
|
1288
|
-
<AccordionItemButton>Assign Data Series Axis</AccordionItemButton>
|
|
1289
|
-
</AccordionItemHeading>
|
|
1290
|
-
<AccordionItemPanel>
|
|
1291
|
-
<p>Only line series data can be assigned to the right axis. Check the data series section above.</p>
|
|
1292
|
-
{config.series && config.series.filter(series => checkIsLine(series.type)) && (
|
|
1293
|
-
<>
|
|
1294
|
-
<fieldset>
|
|
1295
|
-
<legend className='edit-label float-left'>Displaying</legend>
|
|
1296
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1297
|
-
<Tooltip.Target>
|
|
1298
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1299
|
-
</Tooltip.Target>
|
|
1300
|
-
<Tooltip.Content>
|
|
1301
|
-
<p>Assign an axis for the series</p>
|
|
1302
|
-
</Tooltip.Content>
|
|
1303
|
-
</Tooltip>
|
|
1304
|
-
</fieldset>
|
|
1305
|
-
<ul className='series-list'>
|
|
1306
|
-
{config.series &&
|
|
1307
|
-
config.series.map((series, i) => {
|
|
1308
|
-
if (series.type === 'Bar') return false // can't set individual bars atm.
|
|
1309
|
-
|
|
1310
|
-
let changeAxis = (i, value) => {
|
|
1311
|
-
let series = [...config.series]
|
|
1312
|
-
series[i].axis = value
|
|
1313
|
-
updateConfig({ ...config, series })
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
let axisDropdown = (
|
|
1317
|
-
<select
|
|
1318
|
-
value={series.axis}
|
|
1319
|
-
onChange={event => {
|
|
1320
|
-
changeAxis(i, event.target.value)
|
|
1321
|
-
}}
|
|
1322
|
-
style={{ width: '100px', marginRight: '10px' }}
|
|
1323
|
-
>
|
|
1324
|
-
<option value='Left' default key='left'>
|
|
1325
|
-
left
|
|
1326
|
-
</option>
|
|
1327
|
-
<option value='Right' key='right'>
|
|
1328
|
-
right
|
|
1329
|
-
</option>
|
|
1330
|
-
</select>
|
|
1331
|
-
)
|
|
1332
|
-
|
|
1333
|
-
return (
|
|
1334
|
-
<li key={series.dataKey}>
|
|
1335
|
-
<div className={`series-list__name${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}>
|
|
1336
|
-
<div className='series-list__name-text'>{series.dataKey}</div>
|
|
1337
|
-
</div>
|
|
1338
|
-
<span>
|
|
1339
|
-
<span className='series-list__dropdown'>{axisDropdown}</span>
|
|
1340
|
-
</span>
|
|
1341
|
-
</li>
|
|
1342
|
-
)
|
|
1343
|
-
})}
|
|
1344
|
-
</ul>
|
|
1345
|
-
</>
|
|
1346
|
-
)}
|
|
1347
|
-
</AccordionItemPanel>
|
|
1348
|
-
</AccordionItem>
|
|
1349
|
-
)}
|
|
1350
|
-
|
|
1351
1367
|
<AccordionItem>
|
|
1352
1368
|
<AccordionItemHeading>
|
|
1353
1369
|
<AccordionItemButton>
|
|
@@ -1476,10 +1492,10 @@ const EditorPanel = () => {
|
|
|
1476
1492
|
<CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1477
1493
|
<TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />
|
|
1478
1494
|
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
1495
|
+
<TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />
|
|
1496
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
|
|
1479
1497
|
{config.visualizationType === 'Deviation Bar' && (
|
|
1480
1498
|
<>
|
|
1481
|
-
<TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />
|
|
1482
|
-
<span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
|
|
1483
1499
|
<TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
|
|
1484
1500
|
<TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
|
|
1485
1501
|
<CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Display Deviation point label' updateField={updateField} />
|
|
@@ -1575,7 +1591,7 @@ const EditorPanel = () => {
|
|
|
1575
1591
|
<>
|
|
1576
1592
|
<Select value={config.xAxis.type} section='xAxis' fieldName='type' label='Data Type' updateField={updateField} options={config.visualizationType !== 'Scatter Plot' ? ['categorical', 'date'] : ['categorical', 'continuous', 'date']} />
|
|
1577
1593
|
<Select
|
|
1578
|
-
value={config.xAxis.dataKey || ''}
|
|
1594
|
+
value={config.xAxis.dataKey || setCategoryAxis() || ''}
|
|
1579
1595
|
section='xAxis'
|
|
1580
1596
|
fieldName='dataKey'
|
|
1581
1597
|
label='Data Key'
|
|
@@ -1904,8 +1920,33 @@ const EditorPanel = () => {
|
|
|
1904
1920
|
<AccordionItemButton>Filters</AccordionItemButton>
|
|
1905
1921
|
</AccordionItemHeading>
|
|
1906
1922
|
<AccordionItemPanel>
|
|
1923
|
+
{config.filters && (
|
|
1924
|
+
<>
|
|
1925
|
+
{/* prettier-ignore */}
|
|
1926
|
+
<Select
|
|
1927
|
+
value={config.filterBehavior}
|
|
1928
|
+
fieldName='filterBehavior'
|
|
1929
|
+
label='Filter Behavior'
|
|
1930
|
+
updateField={updateField}
|
|
1931
|
+
options={['Apply Button', 'Filter Change']}
|
|
1932
|
+
tooltip={
|
|
1933
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1934
|
+
<Tooltip.Target>
|
|
1935
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1936
|
+
</Tooltip.Target>
|
|
1937
|
+
<Tooltip.Content>
|
|
1938
|
+
<p>The Apply Button option changes the visualization when the user clicks "apply". The Filter Change option immediately changes the visualization when the selection is changed.</p>
|
|
1939
|
+
</Tooltip.Content>
|
|
1940
|
+
</Tooltip>
|
|
1941
|
+
}
|
|
1942
|
+
/>
|
|
1943
|
+
<br />
|
|
1944
|
+
</>
|
|
1945
|
+
)}
|
|
1907
1946
|
{config.filters && (
|
|
1908
1947
|
<ul className='filters-list'>
|
|
1948
|
+
{/* Whether filters should apply onChange or Apply Button */}
|
|
1949
|
+
|
|
1909
1950
|
{config.filters.map((filter, index) => (
|
|
1910
1951
|
<fieldset className='edit-block' key={index}>
|
|
1911
1952
|
<button
|
|
@@ -1926,13 +1967,29 @@ const EditorPanel = () => {
|
|
|
1926
1967
|
}}
|
|
1927
1968
|
>
|
|
1928
1969
|
<option value=''>- Select Option -</option>
|
|
1929
|
-
{
|
|
1970
|
+
{getFilters(true).map((dataKey, index) => (
|
|
1930
1971
|
<option value={dataKey} key={index}>
|
|
1931
1972
|
{dataKey}
|
|
1932
1973
|
</option>
|
|
1933
1974
|
))}
|
|
1934
1975
|
</select>
|
|
1935
1976
|
</label>
|
|
1977
|
+
|
|
1978
|
+
{/* COMING SOON: 4.23.5 FILTER STYLES */}
|
|
1979
|
+
{/* <label>
|
|
1980
|
+
<span className='edit-label column-heading'>Filter Style</span>
|
|
1981
|
+
|
|
1982
|
+
<select
|
|
1983
|
+
value={filter.filterStyle}
|
|
1984
|
+
onChange={e => {
|
|
1985
|
+
updateFilterProp('filterStyle', index, e.target.value)
|
|
1986
|
+
}}
|
|
1987
|
+
>
|
|
1988
|
+
{filterStyleOptions.map(item => {
|
|
1989
|
+
return <option value={item}>{item}</option>
|
|
1990
|
+
})}
|
|
1991
|
+
</select>
|
|
1992
|
+
</label> */}
|
|
1936
1993
|
<label>
|
|
1937
1994
|
<span className='edit-label column-heading'>Label</span>
|
|
1938
1995
|
<input
|
|
@@ -1947,7 +2004,7 @@ const EditorPanel = () => {
|
|
|
1947
2004
|
<label>
|
|
1948
2005
|
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
1949
2006
|
<select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
|
|
1950
|
-
{
|
|
2007
|
+
{filterOrderOptions.map((option, index) => {
|
|
1951
2008
|
return (
|
|
1952
2009
|
<option value={option.value} key={`filter-${index}`}>
|
|
1953
2010
|
{option.label}
|
|
@@ -1957,7 +2014,7 @@ const EditorPanel = () => {
|
|
|
1957
2014
|
</select>
|
|
1958
2015
|
|
|
1959
2016
|
{filter.order === 'cust' && (
|
|
1960
|
-
<DragDropContext onDragEnd={({ source, destination }) =>
|
|
2017
|
+
<DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
|
|
1961
2018
|
<Droppable droppableId='filter_order'>
|
|
1962
2019
|
{provided => (
|
|
1963
2020
|
<ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
@@ -2234,12 +2291,13 @@ const EditorPanel = () => {
|
|
|
2234
2291
|
value={config.table.show}
|
|
2235
2292
|
section='table'
|
|
2236
2293
|
fieldName='show'
|
|
2237
|
-
label='Show Table'
|
|
2294
|
+
label='Show Data Table'
|
|
2238
2295
|
updateField={updateField}
|
|
2296
|
+
className='column-heading'
|
|
2239
2297
|
tooltip={
|
|
2240
2298
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
2241
2299
|
<Tooltip.Target>
|
|
2242
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2300
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2243
2301
|
</Tooltip.Target>
|
|
2244
2302
|
<Tooltip.Content>
|
|
2245
2303
|
<p>Hiding the data table may affect accessibility. An alternate form of accessing visualization data is a 508 requirement.</p>
|
|
@@ -2269,8 +2327,9 @@ const EditorPanel = () => {
|
|
|
2269
2327
|
<CheckBox value={config.table.limitHeight} section='table' fieldName='limitHeight' label='Limit Table Height' updateField={updateField} />
|
|
2270
2328
|
{config.table.limitHeight && <TextField value={config.table.height} section='table' fieldName='height' label='Data Table Height' type='number' min='0' max='500' placeholder='Height(px)' updateField={updateField} />}
|
|
2271
2329
|
<CheckBox value={config.table.expanded} section='table' fieldName='expanded' label='Expanded by Default' updateField={updateField} />
|
|
2272
|
-
<CheckBox value={config.table.
|
|
2273
|
-
<CheckBox value={config.table.showDownloadUrl} section='table' fieldName='showDownloadUrl' label='
|
|
2330
|
+
{isDashboard && <CheckBox value={config.table.showDataTableLink} section='table' fieldName='showDataTableLink' label='Show Data Table Name & Link' updateField={updateField} />}
|
|
2331
|
+
{isLoadedFromUrl && <CheckBox value={config.table.showDownloadUrl} section='table' fieldName='showDownloadUrl' label='Show URL to Automatically Updated Data' updateField={updateField} />}
|
|
2332
|
+
<CheckBox value={config.table.download} section='table' fieldName='download' label='Show Download CSV Link' updateField={updateField} />
|
|
2274
2333
|
{/* <CheckBox value={config.table.showDownloadImgButton} section='table' fieldName='showDownloadImgButton' label='Display Image Button' updateField={updateField} /> */}
|
|
2275
2334
|
{/* <CheckBox value={config.table.showDownloadPdfButton} section='table' fieldName='showDownloadPdfButton' label='Display PDF Button' updateField={updateField} /> */}
|
|
2276
2335
|
{config.visualizationType !== 'Pie' && <TextField value={config.table.indexLabel} section='table' fieldName='indexLabel' label='Index Column Header' updateField={updateField} />}
|