@cdc/chart 4.23.3 → 4.23.5
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 +52543 -50830
- package/examples/feature/__data__/area-chart.json +56 -0
- package/examples/{planet-example-data.json → feature/__data__/planet-example-data.json} +3 -8
- package/examples/feature/__data__/planet-logaritmic-data.json +56 -0
- package/examples/feature/area/area-chart-category.json +240 -0
- package/examples/{area-chart.json → feature/area/area-chart-date.json} +70 -13
- package/examples/feature/bar/example-bar-chart.json +558 -0
- 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/feature/bar/planet-chart-logaritmic-config.json +170 -0
- 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/boxplot/valid-boxplot.csv +17 -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 +212 -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/forecasting/random_data.csv +366 -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/feature/test-highlight/test-highlight-2.json +789 -0
- package/examples/feature/test-highlight/test-highlight-vertical.json +561 -0
- package/examples/feature/test-highlight/test-highlight.json +100 -0
- 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/{stacked-vertical-bar-example-nonnumerics.json → feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json} +1 -2
- package/examples/gallery/bar-chart-horizontal/horizontal-highlight.json +345 -0
- 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 +405 -40
- package/src/components/AreaChart.jsx +122 -80
- package/src/components/BarChart.jsx +126 -49
- package/src/components/BoxPlot.jsx +28 -20
- package/src/components/DataTable.jsx +7 -6
- package/src/components/DeviationBar.jsx +34 -34
- package/src/components/EditorPanel.jsx +1332 -352
- package/src/components/Legend.jsx +40 -4
- package/src/components/LineChart.jsx +10 -23
- package/src/components/LinearChart.jsx +133 -286
- 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 +23 -4
- package/src/hooks/useHighlightedBars.js +154 -0
- package/src/hooks/useMinMax.js +92 -0
- package/src/hooks/useReduceData.js +31 -57
- package/src/hooks/useScales.js +202 -0
- 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/example-bar-chart.json +0 -36
- 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/{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
|
@@ -17,7 +17,8 @@ import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
|
17
17
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
18
18
|
import useReduceData from '../hooks/useReduceData'
|
|
19
19
|
import useRightAxis from '../hooks/useRightAxis'
|
|
20
|
-
import
|
|
20
|
+
import { useFilters } from '@cdc/core/components/Filters'
|
|
21
|
+
import { useHighlightedBars } from '../hooks/useHighlightedBars'
|
|
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, lineOptions } = 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
|
})
|
|
@@ -298,6 +295,8 @@ const EditorPanel = () => {
|
|
|
298
295
|
}
|
|
299
296
|
|
|
300
297
|
const updateField = (section, subsection, fieldName, newValue) => {
|
|
298
|
+
if (isDebug) console.log('#COVE: CHART: EditorPanel: section, subsection, fieldName, newValue', section, subsection, fieldName, newValue) // eslint-disable-line
|
|
299
|
+
|
|
301
300
|
if (section === 'boxplot' && subsection === 'legend') {
|
|
302
301
|
updateConfig({
|
|
303
302
|
...config,
|
|
@@ -325,6 +324,20 @@ const EditorPanel = () => {
|
|
|
325
324
|
})
|
|
326
325
|
return
|
|
327
326
|
}
|
|
327
|
+
|
|
328
|
+
if (section === 'columns' && subsection !== '' && fieldName !== '') {
|
|
329
|
+
updateConfig({
|
|
330
|
+
...config,
|
|
331
|
+
[section]: {
|
|
332
|
+
...config[section],
|
|
333
|
+
[subsection]: {
|
|
334
|
+
...config[section][subsection],
|
|
335
|
+
[fieldName]: newValue
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
})
|
|
339
|
+
return
|
|
340
|
+
}
|
|
328
341
|
if (null === section && null === subsection) {
|
|
329
342
|
let updatedConfig = { ...config, [fieldName]: newValue }
|
|
330
343
|
enforceRestrictions(updatedConfig)
|
|
@@ -481,13 +494,22 @@ const EditorPanel = () => {
|
|
|
481
494
|
}
|
|
482
495
|
}
|
|
483
496
|
|
|
484
|
-
const
|
|
497
|
+
const getFilters = () => {
|
|
485
498
|
let columns = {}
|
|
486
499
|
|
|
487
500
|
unfilteredData.forEach(row => {
|
|
488
501
|
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
489
502
|
})
|
|
490
503
|
|
|
504
|
+
return Object.keys(columns)
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const getColumns = (filter = true) => {
|
|
508
|
+
let columns = {}
|
|
509
|
+
unfilteredData.forEach(row => {
|
|
510
|
+
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
511
|
+
})
|
|
512
|
+
|
|
491
513
|
if (filter) {
|
|
492
514
|
Object.keys(columns).forEach(key => {
|
|
493
515
|
if (
|
|
@@ -591,6 +613,24 @@ const EditorPanel = () => {
|
|
|
591
613
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
592
614
|
}, [config])
|
|
593
615
|
|
|
616
|
+
// when the orientation changes, swap x and y axis anchors
|
|
617
|
+
useEffect(() => {
|
|
618
|
+
const prevXAnchors = config.xAxis.anchors.length > 0 ? config.xAxis.anchors : []
|
|
619
|
+
const prevYAnchors = config.yAxis.anchors.length > 0 ? config.yAxis.anchors : []
|
|
620
|
+
|
|
621
|
+
updateConfig({
|
|
622
|
+
...config,
|
|
623
|
+
xAxis: {
|
|
624
|
+
...config.xAxis,
|
|
625
|
+
anchors: prevYAnchors
|
|
626
|
+
},
|
|
627
|
+
yAxis: {
|
|
628
|
+
...config.yAxis,
|
|
629
|
+
anchors: prevXAnchors
|
|
630
|
+
}
|
|
631
|
+
})
|
|
632
|
+
}, [config.orientation])
|
|
633
|
+
|
|
594
634
|
// Set paired bars to be horizontal, even though that option doesn't display
|
|
595
635
|
useEffect(() => {
|
|
596
636
|
if (config.visualizationType === 'Paired Bar') {
|
|
@@ -637,23 +677,6 @@ const EditorPanel = () => {
|
|
|
637
677
|
)
|
|
638
678
|
}, [config]) // eslint-disable-line
|
|
639
679
|
|
|
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
680
|
const visHasLegend = () => {
|
|
658
681
|
const { visualizationType } = config
|
|
659
682
|
|
|
@@ -668,6 +691,8 @@ const EditorPanel = () => {
|
|
|
668
691
|
const visCanAnimate = () => {
|
|
669
692
|
const { visualizationType } = config
|
|
670
693
|
switch (visualizationType) {
|
|
694
|
+
case 'Area Chart':
|
|
695
|
+
return false
|
|
671
696
|
case 'Scatter Plot':
|
|
672
697
|
return false
|
|
673
698
|
case 'Box Plot':
|
|
@@ -692,6 +717,8 @@ const EditorPanel = () => {
|
|
|
692
717
|
const visHasLabelOnData = () => {
|
|
693
718
|
const { visualizationType } = config
|
|
694
719
|
switch (visualizationType) {
|
|
720
|
+
case 'Area Chart':
|
|
721
|
+
return false
|
|
695
722
|
case 'Box Plot':
|
|
696
723
|
return false
|
|
697
724
|
case 'Pie':
|
|
@@ -703,6 +730,24 @@ const EditorPanel = () => {
|
|
|
703
730
|
}
|
|
704
731
|
}
|
|
705
732
|
|
|
733
|
+
const visHasAnchors = () => {
|
|
734
|
+
const { visualizationType } = config
|
|
735
|
+
switch (visualizationType) {
|
|
736
|
+
case 'Area Chart':
|
|
737
|
+
return true
|
|
738
|
+
case 'Combo':
|
|
739
|
+
return true
|
|
740
|
+
case 'Line':
|
|
741
|
+
return true
|
|
742
|
+
case 'Bar':
|
|
743
|
+
return true
|
|
744
|
+
case 'Scatter Plot':
|
|
745
|
+
return true
|
|
746
|
+
default:
|
|
747
|
+
return false
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
706
751
|
const visHasBarBorders = () => {
|
|
707
752
|
const { series, visualizationType } = config
|
|
708
753
|
if (visualizationType === 'Box Plot') return false
|
|
@@ -743,9 +788,7 @@ const EditorPanel = () => {
|
|
|
743
788
|
default:
|
|
744
789
|
message = ''
|
|
745
790
|
}
|
|
746
|
-
setWarningMsg(
|
|
747
|
-
return { ...prevMsg, maxMsg: message }
|
|
748
|
-
})
|
|
791
|
+
setWarningMsg(prevMsg => ({ ...prevMsg, maxMsg: message }))
|
|
749
792
|
}
|
|
750
793
|
|
|
751
794
|
const validateMinValue = () => {
|
|
@@ -754,43 +797,226 @@ const EditorPanel = () => {
|
|
|
754
797
|
let message = ''
|
|
755
798
|
|
|
756
799
|
switch (true) {
|
|
800
|
+
case config.useLogScale && ['Line', 'Combo', 'Bar'].includes(config.visualizationType) && enteredValue < 0:
|
|
801
|
+
message = 'Negative numbers are not supported in logarithmic scale'
|
|
802
|
+
break
|
|
757
803
|
case (config.visualizationType === 'Line' || config.visualizationType === 'Spark Line') && enteredValue && parseFloat(enteredValue) > minVal:
|
|
758
|
-
message = 'Value
|
|
804
|
+
message = 'Value should not exceed ' + minValue
|
|
759
805
|
break
|
|
760
806
|
case config.visualizationType === 'Combo' && isAllLine && enteredValue && parseFloat(enteredValue) > minVal:
|
|
761
|
-
message = 'Value
|
|
807
|
+
message = 'Value should not exceed ' + minValue
|
|
808
|
+
break
|
|
809
|
+
case (config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && enteredValue && minVal > 0 && parseFloat(enteredValue) > 0:
|
|
810
|
+
message = config.useLogScale ? 'Value must be equal to 0' : 'Value must be less than or equal to 0'
|
|
762
811
|
break
|
|
763
|
-
case
|
|
764
|
-
message = 'Value must be less than
|
|
812
|
+
case config.visualizationType === 'Deviation Bar' && parseFloat(enteredValue) >= Math.min(minVal, config.xAxis.target):
|
|
813
|
+
message = 'Value must be less than ' + Math.min(minVal, config.xAxis.target)
|
|
765
814
|
break
|
|
766
|
-
case enteredValue && minVal < 0 && parseFloat(enteredValue) > minVal:
|
|
767
|
-
message = 'Value
|
|
815
|
+
case config.visualizationType !== 'Deviation Bar' && enteredValue && minVal < 0 && parseFloat(enteredValue) > minVal:
|
|
816
|
+
message = 'Value should not exceed ' + minValue
|
|
768
817
|
break
|
|
769
818
|
default:
|
|
770
819
|
message = ''
|
|
771
820
|
}
|
|
772
|
-
setWarningMsg(
|
|
773
|
-
return { ...prevMsg, minMsg: message }
|
|
774
|
-
})
|
|
821
|
+
setWarningMsg(prevMsg => ({ ...prevMsg, minMsg: message }))
|
|
775
822
|
}
|
|
776
823
|
useEffect(() => {
|
|
777
824
|
validateMinValue()
|
|
778
825
|
validateMaxValue()
|
|
779
826
|
}, [minValue, maxValue, config]) // eslint-disable-line
|
|
780
827
|
|
|
828
|
+
// prettier-ignore
|
|
781
829
|
const enabledChartTypes = [
|
|
782
|
-
'
|
|
783
|
-
'Line',
|
|
830
|
+
'Area Chart',
|
|
784
831
|
'Bar',
|
|
832
|
+
'Box Plot',
|
|
785
833
|
'Combo',
|
|
834
|
+
'Deviation Bar',
|
|
835
|
+
'Line',
|
|
786
836
|
'Paired Bar',
|
|
787
|
-
'
|
|
788
|
-
// 'Area Chart',
|
|
837
|
+
'Pie',
|
|
789
838
|
'Scatter Plot',
|
|
790
|
-
'
|
|
791
|
-
'Deviation Bar'
|
|
839
|
+
'Spark Line'
|
|
792
840
|
]
|
|
793
841
|
|
|
842
|
+
const isLoadedFromUrl = config?.dataKey?.includes('http://') || config?.dataKey?.includes('https://')
|
|
843
|
+
|
|
844
|
+
// if isDebug = true, then try to set the category and data col to reduce clicking
|
|
845
|
+
const setCategoryAxis = () => {
|
|
846
|
+
// only for debug mode
|
|
847
|
+
if (undefined !== isDebug && isDebug && !config?.xAxis?.dataKey) {
|
|
848
|
+
// then try to set the x axis to appropriate value so we dont have to manually do it
|
|
849
|
+
let datakeys = getColumns(false)
|
|
850
|
+
if (datakeys.includes('Date')) return 'Date'
|
|
851
|
+
if (datakeys.includes('Race')) return 'Race'
|
|
852
|
+
// add other known Category cols here to extend debug
|
|
853
|
+
}
|
|
854
|
+
return ''
|
|
855
|
+
}
|
|
856
|
+
const setDataColumn = () => {
|
|
857
|
+
// only for debug mode
|
|
858
|
+
if (undefined !== isDebug && isDebug && getColumns(false).length > 0) {
|
|
859
|
+
// then try to set the x axis to appropriate value so we dont have to manually do it
|
|
860
|
+
let datacols = getColumns(false).filter(x => x !== 'Date' && x !== 'Race')
|
|
861
|
+
if (datacols.length > 0) {
|
|
862
|
+
return datacols[0]
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
return ''
|
|
866
|
+
}
|
|
867
|
+
if (isDebug && !config.xAxis.dataKey) config.xAxis.dataKey = setCategoryAxis()
|
|
868
|
+
if (isDebug && config?.series?.length === 0) {
|
|
869
|
+
let setdatacol = setDataColumn()
|
|
870
|
+
if (setdatacol !== '') addNewSeries(setdatacol)
|
|
871
|
+
if (isDebug) console.log('### COVE DEBUG: Chart: Setting default datacol=', setdatacol) // eslint-disable-line
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
const chartsWithOptions = ['Area Chart', 'Combo', 'Line']
|
|
875
|
+
|
|
876
|
+
const columnsOptions = [
|
|
877
|
+
<option value='' key={'Select Option'}>
|
|
878
|
+
- Select Option -
|
|
879
|
+
</option>
|
|
880
|
+
]
|
|
881
|
+
|
|
882
|
+
if (config.data && config.series) {
|
|
883
|
+
Object.keys(config.data[0]).map(colName => {
|
|
884
|
+
// OMIT ANY COLUMNS THAT ARE IN DATA SERIES!
|
|
885
|
+
const found = config?.series.some(el => el.dataKey === colName)
|
|
886
|
+
if (colName !== config.xAxis.dataKey && !found) {
|
|
887
|
+
// if not the index then add it
|
|
888
|
+
return columnsOptions.push(
|
|
889
|
+
<option value={colName} key={colName}>
|
|
890
|
+
{colName}
|
|
891
|
+
</option>
|
|
892
|
+
)
|
|
893
|
+
}
|
|
894
|
+
})
|
|
895
|
+
|
|
896
|
+
let columnsByKey = {}
|
|
897
|
+
config.data.forEach(datum => {
|
|
898
|
+
Object.keys(datum).forEach(key => {
|
|
899
|
+
columnsByKey[key] = columnsByKey[key] || []
|
|
900
|
+
const value = typeof datum[key] === 'number' ? datum[key].toString() : datum[key]
|
|
901
|
+
|
|
902
|
+
if (columnsByKey[key].indexOf(value) === -1) {
|
|
903
|
+
columnsByKey[key].push(value)
|
|
904
|
+
}
|
|
905
|
+
})
|
|
906
|
+
})
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// for pie charts
|
|
910
|
+
if (!config.data && data) {
|
|
911
|
+
if (!data[0]) return
|
|
912
|
+
Object.keys(data[0]).map(colName => {
|
|
913
|
+
// OMIT ANY COLUMNS THAT ARE IN DATA SERIES!
|
|
914
|
+
const found = data.some(el => el.dataKey === colName)
|
|
915
|
+
if (colName !== config.xAxis.dataKey && !found) {
|
|
916
|
+
// if not the index then add it
|
|
917
|
+
return columnsOptions.push(
|
|
918
|
+
<option value={colName} key={colName}>
|
|
919
|
+
{colName}
|
|
920
|
+
</option>
|
|
921
|
+
)
|
|
922
|
+
}
|
|
923
|
+
})
|
|
924
|
+
|
|
925
|
+
let columnsByKey = {}
|
|
926
|
+
data.forEach(datum => {
|
|
927
|
+
Object.keys(datum).forEach(key => {
|
|
928
|
+
columnsByKey[key] = columnsByKey[key] || []
|
|
929
|
+
const value = typeof datum[key] === 'number' ? datum[key].toString() : datum[key]
|
|
930
|
+
|
|
931
|
+
if (columnsByKey[key].indexOf(value) === -1) {
|
|
932
|
+
columnsByKey[key].push(value)
|
|
933
|
+
}
|
|
934
|
+
})
|
|
935
|
+
})
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// prevents adding duplicates
|
|
939
|
+
const additionalColumns = Object.keys(config.columns).filter(value => {
|
|
940
|
+
const defaultCols = [config.xAxis.dataKey] // ['geo', 'navigate', 'primary', 'latitude', 'longitude']
|
|
941
|
+
|
|
942
|
+
if (true === defaultCols.includes(value)) {
|
|
943
|
+
return false
|
|
944
|
+
}
|
|
945
|
+
return true
|
|
946
|
+
})
|
|
947
|
+
|
|
948
|
+
// just adds a new column but not set to any data yet
|
|
949
|
+
const addAdditionalColumn = number => {
|
|
950
|
+
const columnKey = `additionalColumn${number}`
|
|
951
|
+
|
|
952
|
+
updateConfig({
|
|
953
|
+
...config,
|
|
954
|
+
columns: {
|
|
955
|
+
...config.columns,
|
|
956
|
+
[columnKey]: {
|
|
957
|
+
label: 'New Column',
|
|
958
|
+
dataTable: false,
|
|
959
|
+
tooltips: false,
|
|
960
|
+
prefix: '',
|
|
961
|
+
suffix: ''
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
})
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
const removeAdditionalColumn = columnName => {
|
|
968
|
+
const newColumns = config.columns
|
|
969
|
+
|
|
970
|
+
delete newColumns[columnName]
|
|
971
|
+
|
|
972
|
+
updateConfig({
|
|
973
|
+
...config,
|
|
974
|
+
columns: newColumns
|
|
975
|
+
})
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
const editColumn = async (addCol, columnName, setval) => {
|
|
979
|
+
// not using special classes like in map editorpanel so removed those cases
|
|
980
|
+
switch (columnName) {
|
|
981
|
+
case 'name':
|
|
982
|
+
updateConfig({
|
|
983
|
+
...config,
|
|
984
|
+
columns: {
|
|
985
|
+
...config.columns,
|
|
986
|
+
[addCol]: {
|
|
987
|
+
...config.columns[addCol],
|
|
988
|
+
[columnName]: setval
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
})
|
|
992
|
+
break
|
|
993
|
+
default:
|
|
994
|
+
updateConfig({
|
|
995
|
+
...config,
|
|
996
|
+
columns: {
|
|
997
|
+
...config.columns,
|
|
998
|
+
[addCol]: {
|
|
999
|
+
...config.columns[addCol],
|
|
1000
|
+
[columnName]: setval
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
})
|
|
1004
|
+
break
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// prettier-ignore
|
|
1009
|
+
const {
|
|
1010
|
+
highlightedBarValues,
|
|
1011
|
+
highlightedSeriesValues,
|
|
1012
|
+
handleUpdateHighlightedBar,
|
|
1013
|
+
handleAddNewHighlightedBar,
|
|
1014
|
+
handleRemoveHighlightedBar,
|
|
1015
|
+
handleUpdateHighlightedBarColor,
|
|
1016
|
+
handleHighlightedBarLegendLabel,
|
|
1017
|
+
handleUpdateHighlightedBorderWidth
|
|
1018
|
+
} = useHighlightedBars(config, updateConfig)
|
|
1019
|
+
|
|
794
1020
|
return (
|
|
795
1021
|
<ErrorBoundary component='EditorPanel'>
|
|
796
1022
|
{config.newViz && <Confirm />}
|
|
@@ -923,7 +1149,6 @@ const EditorPanel = () => {
|
|
|
923
1149
|
{config.orientation === 'vertical' && <TextField type='number' value={config.heights.vertical} section='heights' fieldName='vertical' label='Chart Height' updateField={updateField} />}
|
|
924
1150
|
</AccordionItemPanel>
|
|
925
1151
|
</AccordionItem>
|
|
926
|
-
|
|
927
1152
|
{config.visualizationType !== 'Pie' && (
|
|
928
1153
|
<AccordionItem>
|
|
929
1154
|
<AccordionItemHeading>
|
|
@@ -932,6 +1157,18 @@ const EditorPanel = () => {
|
|
|
932
1157
|
<AccordionItemPanel>
|
|
933
1158
|
{(!config.series || config.series.length === 0) && config.visualizationType !== 'Paired Bar' && <p className='warning'>At least one series is required</p>}
|
|
934
1159
|
{(!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>}
|
|
1160
|
+
<Select
|
|
1161
|
+
fieldName='visualizationType'
|
|
1162
|
+
label='Add Data Series'
|
|
1163
|
+
initial='Select'
|
|
1164
|
+
onChange={e => {
|
|
1165
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
1166
|
+
addNewSeries(e.target.value)
|
|
1167
|
+
}
|
|
1168
|
+
e.target.value = ''
|
|
1169
|
+
}}
|
|
1170
|
+
options={getColumns()}
|
|
1171
|
+
/>
|
|
935
1172
|
{config.series && config.series.length !== 0 && (
|
|
936
1173
|
<>
|
|
937
1174
|
<fieldset>
|
|
@@ -949,7 +1186,7 @@ const EditorPanel = () => {
|
|
|
949
1186
|
<DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
|
|
950
1187
|
<Droppable droppableId='filter_order'>
|
|
951
1188
|
{provided => (
|
|
952
|
-
<ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}
|
|
1189
|
+
<ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
|
|
953
1190
|
{config.series.map((series, i) => {
|
|
954
1191
|
if (config.visualizationType === 'Combo' || 'Area Chart') {
|
|
955
1192
|
let changeType = (i, value) => {
|
|
@@ -968,78 +1205,129 @@ const EditorPanel = () => {
|
|
|
968
1205
|
}
|
|
969
1206
|
|
|
970
1207
|
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
|
-
|
|
1208
|
+
<>
|
|
1209
|
+
<label htmlFor='type-dropdown'>Series Type</label>
|
|
1210
|
+
<select
|
|
1211
|
+
name='type-dropdown'
|
|
1212
|
+
value={series.type}
|
|
1213
|
+
onChange={event => {
|
|
1214
|
+
changeType(i, event.target.value)
|
|
1215
|
+
}}
|
|
1216
|
+
>
|
|
1217
|
+
<option value='' default key='default'>
|
|
1218
|
+
Select
|
|
1219
|
+
</option>
|
|
1220
|
+
{config.visualizationType === 'Combo' && <option value='Bar'>Bar</option>}
|
|
1221
|
+
<option value='Line' key='Line'>
|
|
1222
|
+
Solid Line
|
|
1223
|
+
</option>
|
|
1224
|
+
<option value='dashed-sm' key='dashed-sm'>
|
|
1225
|
+
Small Dashed
|
|
1226
|
+
</option>
|
|
1227
|
+
<option value='dashed-md' key='dashed-md'>
|
|
1228
|
+
Medium Dashed
|
|
1229
|
+
</option>
|
|
1230
|
+
<option value='dashed-lg' key='dashed-lg'>
|
|
1231
|
+
Large Dashed
|
|
1232
|
+
</option>
|
|
1233
|
+
<option value='Area Chart' key='Area Chart'>
|
|
1234
|
+
Area
|
|
1235
|
+
</option>
|
|
1236
|
+
</select>
|
|
1237
|
+
</>
|
|
1238
|
+
)
|
|
1239
|
+
|
|
1240
|
+
// used for assigning axis
|
|
1241
|
+
let changeAxis = (i, value) => {
|
|
1242
|
+
let series = [...config.series]
|
|
1243
|
+
series[i].axis = value
|
|
1244
|
+
updateConfig({ ...config, series })
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// assign an axis dropdown
|
|
1248
|
+
let axisDropdown = (
|
|
1249
|
+
<>
|
|
1250
|
+
<label htmlFor='assign-axis'>Assign an axis</label>
|
|
1251
|
+
<select
|
|
1252
|
+
name='assign-axis'
|
|
1253
|
+
value={series.axis}
|
|
1254
|
+
onChange={event => {
|
|
1255
|
+
changeAxis(i, event.target.value)
|
|
1256
|
+
}}
|
|
1257
|
+
>
|
|
1258
|
+
<option value='Left' default key='left'>
|
|
1259
|
+
left
|
|
1260
|
+
</option>
|
|
1261
|
+
<option value='Right' key='right'>
|
|
1262
|
+
right
|
|
1263
|
+
</option>
|
|
1264
|
+
</select>
|
|
1265
|
+
</>
|
|
995
1266
|
)
|
|
996
1267
|
|
|
1268
|
+
// line type dropdown
|
|
997
1269
|
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}
|
|
1270
|
+
<>
|
|
1271
|
+
<label htmlFor='line-type'>Line Type</label>
|
|
1272
|
+
<select
|
|
1273
|
+
name='line-type'
|
|
1274
|
+
value={series.lineStyle}
|
|
1275
|
+
onChange={event => {
|
|
1276
|
+
changeLineType(i, event.target.value)
|
|
1277
|
+
}}
|
|
1278
|
+
key='lineTypeSelection'
|
|
1279
|
+
>
|
|
1280
|
+
<option value='' default>
|
|
1281
|
+
Select
|
|
1013
1282
|
</option>
|
|
1014
|
-
|
|
1015
|
-
|
|
1283
|
+
|
|
1284
|
+
{Object.keys(approvedCurveTypes).map(curveName => {
|
|
1285
|
+
return (
|
|
1286
|
+
<option key={`curve-option-${approvedCurveTypes[curveName]}`} value={approvedCurveTypes[curveName]}>
|
|
1287
|
+
{curveName}
|
|
1288
|
+
</option>
|
|
1289
|
+
)
|
|
1290
|
+
})}
|
|
1291
|
+
</select>
|
|
1292
|
+
</>
|
|
1016
1293
|
)
|
|
1017
1294
|
|
|
1018
1295
|
return (
|
|
1019
1296
|
<Draggable key={series.dataKey} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
|
|
1020
1297
|
{(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
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1298
|
+
<>
|
|
1299
|
+
<div key={i} className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
1300
|
+
<div className={`series-list__name ${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}></div>
|
|
1301
|
+
<Accordion allowZeroExpanded>
|
|
1302
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
1303
|
+
<AccordionItemHeading className='series-item__title'>
|
|
1304
|
+
<AccordionItemButton className={chartsWithOptions.includes(config.visualizationType) ? 'accordion__button' : 'accordion__button hide-arrow'}>
|
|
1305
|
+
<Icon display='move' size={15} style={{ cursor: 'default' }} />
|
|
1306
|
+
{series.dataKey}
|
|
1307
|
+
{config.series && config.series.length > 1 && (
|
|
1308
|
+
<button className='series-list__remove' onClick={() => removeSeries(series.dataKey)}>
|
|
1309
|
+
Remove
|
|
1310
|
+
</button>
|
|
1311
|
+
)}
|
|
1312
|
+
</AccordionItemButton>
|
|
1313
|
+
</AccordionItemHeading>
|
|
1314
|
+
{chartsWithOptions.includes(config.visualizationType) && (
|
|
1315
|
+
<AccordionItemPanel>
|
|
1316
|
+
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
1317
|
+
{config.visualizationType === 'Combo' && (
|
|
1318
|
+
<>
|
|
1319
|
+
<span className='series-list__dropdown series-item__dropdown'>{typeDropdown}</span>
|
|
1320
|
+
{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>}
|
|
1321
|
+
</>
|
|
1322
|
+
)}
|
|
1323
|
+
{['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>}
|
|
1324
|
+
</div>
|
|
1325
|
+
</AccordionItemPanel>
|
|
1038
1326
|
)}
|
|
1039
|
-
|
|
1040
|
-
</
|
|
1327
|
+
</AccordionItem>
|
|
1328
|
+
</Accordion>
|
|
1041
1329
|
</div>
|
|
1042
|
-
|
|
1330
|
+
</>
|
|
1043
1331
|
)}
|
|
1044
1332
|
</Draggable>
|
|
1045
1333
|
)
|
|
@@ -1079,19 +1367,6 @@ const EditorPanel = () => {
|
|
|
1079
1367
|
</>
|
|
1080
1368
|
)}
|
|
1081
1369
|
|
|
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
1370
|
{config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
|
|
1096
1371
|
<>
|
|
1097
1372
|
<span className='divider-heading'>Confidence Keys</span>
|
|
@@ -1104,7 +1379,6 @@ const EditorPanel = () => {
|
|
|
1104
1379
|
</AccordionItemPanel>
|
|
1105
1380
|
</AccordionItem>
|
|
1106
1381
|
)}
|
|
1107
|
-
|
|
1108
1382
|
{config.visualizationType === 'Box Plot' && (
|
|
1109
1383
|
<AccordionItem>
|
|
1110
1384
|
<AccordionItemHeading>
|
|
@@ -1281,73 +1555,6 @@ const EditorPanel = () => {
|
|
|
1281
1555
|
</AccordionItemPanel>
|
|
1282
1556
|
</AccordionItem>
|
|
1283
1557
|
)}
|
|
1284
|
-
|
|
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
1558
|
<AccordionItem>
|
|
1352
1559
|
<AccordionItemHeading>
|
|
1353
1560
|
<AccordionItemButton>
|
|
@@ -1408,6 +1615,7 @@ const EditorPanel = () => {
|
|
|
1408
1615
|
{config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
|
|
1409
1616
|
{config.orientation !== 'horizontal' && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Display Gridlines' updateField={updateField} />}
|
|
1410
1617
|
<CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
|
|
1618
|
+
{config.visualizationSubType === 'regular' && <CheckBox value={config.useLogScale} fieldName='useLogScale' label='use logarithmic scale' updateField={updateField} />}
|
|
1411
1619
|
</>
|
|
1412
1620
|
)}
|
|
1413
1621
|
<span className='divider-heading'>Number Formatting</span>
|
|
@@ -1476,10 +1684,10 @@ const EditorPanel = () => {
|
|
|
1476
1684
|
<CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1477
1685
|
<TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />
|
|
1478
1686
|
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
1687
|
+
<TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />
|
|
1688
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
|
|
1479
1689
|
{config.visualizationType === 'Deviation Bar' && (
|
|
1480
1690
|
<>
|
|
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
1691
|
<TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
|
|
1484
1692
|
<TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
|
|
1485
1693
|
<CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Display Deviation point label' updateField={updateField} />
|
|
@@ -1492,6 +1700,7 @@ const EditorPanel = () => {
|
|
|
1492
1700
|
<CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
1493
1701
|
<CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
|
|
1494
1702
|
<CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1703
|
+
|
|
1495
1704
|
<TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='max value' placeholder='Auto' updateField={updateField} />
|
|
1496
1705
|
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
1497
1706
|
<TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />
|
|
@@ -1499,9 +1708,260 @@ const EditorPanel = () => {
|
|
|
1499
1708
|
</>
|
|
1500
1709
|
)
|
|
1501
1710
|
)}
|
|
1711
|
+
|
|
1712
|
+
{/* start: anchors */}
|
|
1713
|
+
{visHasAnchors() && config.orientation !== 'horizontal' ? (
|
|
1714
|
+
<div className='edit-block'>
|
|
1715
|
+
<h3>Anchors</h3>
|
|
1716
|
+
<Accordion allowZeroExpanded>
|
|
1717
|
+
{config.yAxis?.anchors?.map((anchor, index) => (
|
|
1718
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
1719
|
+
<AccordionItemHeading className='series-item__title'>
|
|
1720
|
+
<>
|
|
1721
|
+
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
1722
|
+
Anchor {index + 1}
|
|
1723
|
+
<button
|
|
1724
|
+
className='series-list__remove'
|
|
1725
|
+
onClick={e => {
|
|
1726
|
+
e.preventDefault()
|
|
1727
|
+
const copiedAnchorGroups = [...config.yAxis.anchors]
|
|
1728
|
+
copiedAnchorGroups.splice(index, 1)
|
|
1729
|
+
updateConfig({
|
|
1730
|
+
...config,
|
|
1731
|
+
yAxis: {
|
|
1732
|
+
...config.yAxis,
|
|
1733
|
+
anchors: copiedAnchorGroups
|
|
1734
|
+
}
|
|
1735
|
+
})
|
|
1736
|
+
}}
|
|
1737
|
+
>
|
|
1738
|
+
Remove
|
|
1739
|
+
</button>
|
|
1740
|
+
</AccordionItemButton>
|
|
1741
|
+
</>
|
|
1742
|
+
</AccordionItemHeading>
|
|
1743
|
+
<AccordionItemPanel>
|
|
1744
|
+
<label>
|
|
1745
|
+
<span>Anchor Value</span>
|
|
1746
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1747
|
+
<Tooltip.Target>
|
|
1748
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1749
|
+
</Tooltip.Target>
|
|
1750
|
+
<Tooltip.Content>
|
|
1751
|
+
<p>Enter the value as its shown in the data column</p>
|
|
1752
|
+
</Tooltip.Content>
|
|
1753
|
+
</Tooltip>
|
|
1754
|
+
<input
|
|
1755
|
+
type='text'
|
|
1756
|
+
value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
|
|
1757
|
+
onChange={e => {
|
|
1758
|
+
e.preventDefault()
|
|
1759
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
1760
|
+
copiedAnchors[index].value = e.target.value
|
|
1761
|
+
updateConfig({
|
|
1762
|
+
...config,
|
|
1763
|
+
yAxis: {
|
|
1764
|
+
...config.yAxis,
|
|
1765
|
+
anchors: copiedAnchors
|
|
1766
|
+
}
|
|
1767
|
+
})
|
|
1768
|
+
}}
|
|
1769
|
+
/>
|
|
1770
|
+
</label>
|
|
1771
|
+
|
|
1772
|
+
<label>
|
|
1773
|
+
<span>Anchor Color</span>
|
|
1774
|
+
<input
|
|
1775
|
+
type='text'
|
|
1776
|
+
value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
|
|
1777
|
+
onChange={e => {
|
|
1778
|
+
e.preventDefault()
|
|
1779
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
1780
|
+
copiedAnchors[index].color = e.target.value
|
|
1781
|
+
updateConfig({
|
|
1782
|
+
...config,
|
|
1783
|
+
yAxis: {
|
|
1784
|
+
...config.yAxis,
|
|
1785
|
+
anchors: copiedAnchors
|
|
1786
|
+
}
|
|
1787
|
+
})
|
|
1788
|
+
}}
|
|
1789
|
+
/>
|
|
1790
|
+
</label>
|
|
1791
|
+
|
|
1792
|
+
<label>
|
|
1793
|
+
Anchor Line Style
|
|
1794
|
+
<select
|
|
1795
|
+
value={config.yAxis.anchors[index].lineStyle || ''}
|
|
1796
|
+
onChange={e => {
|
|
1797
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
1798
|
+
copiedAnchors[index].lineStyle = e.target.value
|
|
1799
|
+
updateConfig({
|
|
1800
|
+
...config,
|
|
1801
|
+
yAxis: {
|
|
1802
|
+
...config.yAxis,
|
|
1803
|
+
anchors: copiedAnchors
|
|
1804
|
+
}
|
|
1805
|
+
})
|
|
1806
|
+
}}
|
|
1807
|
+
>
|
|
1808
|
+
<option>Select</option>
|
|
1809
|
+
{lineOptions.map(line => (
|
|
1810
|
+
<option key={line.key}>{line.value}</option>
|
|
1811
|
+
))}
|
|
1812
|
+
</select>
|
|
1813
|
+
</label>
|
|
1814
|
+
</AccordionItemPanel>
|
|
1815
|
+
</AccordionItem>
|
|
1816
|
+
))}
|
|
1817
|
+
</Accordion>
|
|
1818
|
+
|
|
1819
|
+
<button
|
|
1820
|
+
className='btn full-width'
|
|
1821
|
+
onClick={e => {
|
|
1822
|
+
e.preventDefault()
|
|
1823
|
+
const anchors = [...config.yAxis.anchors]
|
|
1824
|
+
anchors.push({})
|
|
1825
|
+
updateConfig({
|
|
1826
|
+
...config,
|
|
1827
|
+
yAxis: {
|
|
1828
|
+
...config.yAxis,
|
|
1829
|
+
anchors
|
|
1830
|
+
}
|
|
1831
|
+
})
|
|
1832
|
+
}}
|
|
1833
|
+
>
|
|
1834
|
+
Add Anchor
|
|
1835
|
+
</button>
|
|
1836
|
+
</div>
|
|
1837
|
+
) : (
|
|
1838
|
+
<div className='edit-block'>
|
|
1839
|
+
<h3>Anchors</h3>
|
|
1840
|
+
<Accordion allowZeroExpanded>
|
|
1841
|
+
{config.xAxis?.anchors?.map((anchor, index) => (
|
|
1842
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
1843
|
+
<AccordionItemHeading className='series-item__title'>
|
|
1844
|
+
<>
|
|
1845
|
+
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
1846
|
+
Anchor {index + 1}
|
|
1847
|
+
<button
|
|
1848
|
+
className='series-list__remove'
|
|
1849
|
+
onClick={e => {
|
|
1850
|
+
e.preventDefault()
|
|
1851
|
+
const copiedAnchorGroups = [...config.xAxis.anchors]
|
|
1852
|
+
copiedAnchorGroups.splice(index, 1)
|
|
1853
|
+
updateConfig({
|
|
1854
|
+
...config,
|
|
1855
|
+
xAxis: {
|
|
1856
|
+
...config.xAxis,
|
|
1857
|
+
anchors: copiedAnchorGroups
|
|
1858
|
+
}
|
|
1859
|
+
})
|
|
1860
|
+
}}
|
|
1861
|
+
>
|
|
1862
|
+
Remove
|
|
1863
|
+
</button>
|
|
1864
|
+
</AccordionItemButton>
|
|
1865
|
+
</>
|
|
1866
|
+
</AccordionItemHeading>
|
|
1867
|
+
<AccordionItemPanel>
|
|
1868
|
+
<label>
|
|
1869
|
+
<span>Anchor Value</span>
|
|
1870
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1871
|
+
<Tooltip.Target>
|
|
1872
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1873
|
+
</Tooltip.Target>
|
|
1874
|
+
<Tooltip.Content>
|
|
1875
|
+
<p>Enter the value as its shown in the data column</p>
|
|
1876
|
+
</Tooltip.Content>
|
|
1877
|
+
</Tooltip>
|
|
1878
|
+
<input
|
|
1879
|
+
type='text'
|
|
1880
|
+
value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
|
|
1881
|
+
onChange={e => {
|
|
1882
|
+
e.preventDefault()
|
|
1883
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
1884
|
+
copiedAnchors[index].value = e.target.value
|
|
1885
|
+
updateConfig({
|
|
1886
|
+
...config,
|
|
1887
|
+
xAxis: {
|
|
1888
|
+
...config.xAxis,
|
|
1889
|
+
anchors: copiedAnchors
|
|
1890
|
+
}
|
|
1891
|
+
})
|
|
1892
|
+
}}
|
|
1893
|
+
/>
|
|
1894
|
+
</label>
|
|
1895
|
+
|
|
1896
|
+
<label>
|
|
1897
|
+
<span>Anchor Color</span>
|
|
1898
|
+
<input
|
|
1899
|
+
type='text'
|
|
1900
|
+
value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
|
|
1901
|
+
onChange={e => {
|
|
1902
|
+
e.preventDefault()
|
|
1903
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
1904
|
+
copiedAnchors[index].color = e.target.value
|
|
1905
|
+
updateConfig({
|
|
1906
|
+
...config,
|
|
1907
|
+
xAxis: {
|
|
1908
|
+
...config.xAxis,
|
|
1909
|
+
anchors: copiedAnchors
|
|
1910
|
+
}
|
|
1911
|
+
})
|
|
1912
|
+
}}
|
|
1913
|
+
/>
|
|
1914
|
+
</label>
|
|
1915
|
+
|
|
1916
|
+
<label>
|
|
1917
|
+
Anchor Line Style
|
|
1918
|
+
<select
|
|
1919
|
+
value={config.xAxis.anchors[index].lineStyle || ''}
|
|
1920
|
+
onChange={e => {
|
|
1921
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
1922
|
+
copiedAnchors[index].lineStyle = e.target.value
|
|
1923
|
+
updateConfig({
|
|
1924
|
+
...config,
|
|
1925
|
+
xAxis: {
|
|
1926
|
+
...config.xAxis,
|
|
1927
|
+
anchors: copiedAnchors
|
|
1928
|
+
}
|
|
1929
|
+
})
|
|
1930
|
+
}}
|
|
1931
|
+
>
|
|
1932
|
+
<option>Select</option>
|
|
1933
|
+
{lineOptions.map(line => (
|
|
1934
|
+
<option key={line.key}>{line.value}</option>
|
|
1935
|
+
))}
|
|
1936
|
+
</select>
|
|
1937
|
+
</label>
|
|
1938
|
+
</AccordionItemPanel>
|
|
1939
|
+
</AccordionItem>
|
|
1940
|
+
))}
|
|
1941
|
+
</Accordion>
|
|
1942
|
+
|
|
1943
|
+
<button
|
|
1944
|
+
className='btn full-width'
|
|
1945
|
+
onClick={e => {
|
|
1946
|
+
e.preventDefault()
|
|
1947
|
+
const anchors = [...config.xAxis.anchors]
|
|
1948
|
+
anchors.push({})
|
|
1949
|
+
updateConfig({
|
|
1950
|
+
...config,
|
|
1951
|
+
xAxis: {
|
|
1952
|
+
...config.xAxis,
|
|
1953
|
+
anchors
|
|
1954
|
+
}
|
|
1955
|
+
})
|
|
1956
|
+
}}
|
|
1957
|
+
>
|
|
1958
|
+
Add Anchor
|
|
1959
|
+
</button>
|
|
1960
|
+
</div>
|
|
1961
|
+
)}
|
|
1962
|
+
{/* end: anchors */}
|
|
1502
1963
|
</AccordionItemPanel>
|
|
1503
1964
|
</AccordionItem>
|
|
1504
|
-
|
|
1505
1965
|
{/* Right Value Axis Settings */}
|
|
1506
1966
|
{hasRightAxis && (
|
|
1507
1967
|
<AccordionItem>
|
|
@@ -1562,7 +2022,6 @@ const EditorPanel = () => {
|
|
|
1562
2022
|
</AccordionItemPanel>
|
|
1563
2023
|
</AccordionItem>
|
|
1564
2024
|
)}
|
|
1565
|
-
|
|
1566
2025
|
<AccordionItem>
|
|
1567
2026
|
<AccordionItemHeading>
|
|
1568
2027
|
<AccordionItemButton>
|
|
@@ -1575,7 +2034,7 @@ const EditorPanel = () => {
|
|
|
1575
2034
|
<>
|
|
1576
2035
|
<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
2036
|
<Select
|
|
1578
|
-
value={config.xAxis.dataKey || ''}
|
|
2037
|
+
value={config.xAxis.dataKey || setCategoryAxis() || ''}
|
|
1579
2038
|
section='xAxis'
|
|
1580
2039
|
fieldName='dataKey'
|
|
1581
2040
|
label='Data Key'
|
|
@@ -1779,6 +2238,46 @@ const EditorPanel = () => {
|
|
|
1779
2238
|
<CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1780
2239
|
</>
|
|
1781
2240
|
)}
|
|
2241
|
+
|
|
2242
|
+
{config.series?.length === 1 && config.visualizationType === 'Bar' && (
|
|
2243
|
+
<>
|
|
2244
|
+
{/* HIGHLIGHTED BARS */}
|
|
2245
|
+
<label htmlFor='barHighlight'>Bar Highlighting</label>
|
|
2246
|
+
{config.series.length === 1 &&
|
|
2247
|
+
highlightedBarValues.map((highlightedBarValue, i) => (
|
|
2248
|
+
<fieldset>
|
|
2249
|
+
<div className='edit-block' key={`highlighted-bar-${i}`}>
|
|
2250
|
+
<button className='remove-column' onClick={e => handleRemoveHighlightedBar(e, i)}>
|
|
2251
|
+
Remove
|
|
2252
|
+
</button>
|
|
2253
|
+
<p>Highlighted Bar {i + 1}</p>
|
|
2254
|
+
<label>
|
|
2255
|
+
<span className='edit-label column-heading'>Value</span>
|
|
2256
|
+
<select value={config.highlightedBarValues[i].value} onChange={e => handleUpdateHighlightedBar(e, i)}>
|
|
2257
|
+
<option value=''>- Select Value -</option>
|
|
2258
|
+
{highlightedSeriesValues && [...new Set(highlightedSeriesValues)].sort().map(option => <option key={`special-class-value-option-${i}-${option}`}>{option}</option>)}
|
|
2259
|
+
</select>
|
|
2260
|
+
</label>
|
|
2261
|
+
<label>
|
|
2262
|
+
<span className='edit-label column-heading'>Color</span>
|
|
2263
|
+
<input type='text' value={config.highlightedBarValues[i].color ? config.highlightedBarValues[i].color : ''} onChange={e => handleUpdateHighlightedBarColor(e, i)} />
|
|
2264
|
+
</label>
|
|
2265
|
+
<label>
|
|
2266
|
+
<span className='edit-label column-heading'>Border Width</span>
|
|
2267
|
+
<input max='5' min='0' type='number' value={config.highlightedBarValues[i].borderWidth ? config.highlightedBarValues[i].borderWidth : ''} onChange={e => handleUpdateHighlightedBorderWidth(e, i)} />
|
|
2268
|
+
</label>
|
|
2269
|
+
<label>
|
|
2270
|
+
<span className='edit-label column-heading'>Legend Label</span>
|
|
2271
|
+
<input type='text' value={config.highlightedBarValues[i].legendLabel ? config.highlightedBarValues[i].legendLabel : ''} onChange={e => handleHighlightedBarLegendLabel(e, i)} />
|
|
2272
|
+
</label>
|
|
2273
|
+
</div>
|
|
2274
|
+
</fieldset>
|
|
2275
|
+
))}
|
|
2276
|
+
<button className='btn full-width' onClick={e => handleAddNewHighlightedBar(e)}>
|
|
2277
|
+
Add Highlighted Bar
|
|
2278
|
+
</button>
|
|
2279
|
+
</>
|
|
2280
|
+
)}
|
|
1782
2281
|
</>
|
|
1783
2282
|
)}
|
|
1784
2283
|
|
|
@@ -1828,9 +2327,259 @@ const EditorPanel = () => {
|
|
|
1828
2327
|
)}
|
|
1829
2328
|
</>
|
|
1830
2329
|
)}
|
|
2330
|
+
|
|
2331
|
+
{/* anchors */}
|
|
2332
|
+
{visHasAnchors() && config.orientation !== 'horizontal' ? (
|
|
2333
|
+
<div className='edit-block'>
|
|
2334
|
+
<h3>Anchors</h3>
|
|
2335
|
+
<Accordion allowZeroExpanded>
|
|
2336
|
+
{config.xAxis?.anchors?.map((anchor, index) => (
|
|
2337
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
2338
|
+
<AccordionItemHeading className='series-item__title'>
|
|
2339
|
+
<>
|
|
2340
|
+
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
2341
|
+
Anchor {index + 1}
|
|
2342
|
+
<button
|
|
2343
|
+
className='series-list__remove'
|
|
2344
|
+
onClick={e => {
|
|
2345
|
+
e.preventDefault()
|
|
2346
|
+
const copiedAnchorGroups = [...config.xAxis.anchors]
|
|
2347
|
+
copiedAnchorGroups.splice(index, 1)
|
|
2348
|
+
updateConfig({
|
|
2349
|
+
...config,
|
|
2350
|
+
xAxis: {
|
|
2351
|
+
...config.xAxis,
|
|
2352
|
+
anchors: copiedAnchorGroups
|
|
2353
|
+
}
|
|
2354
|
+
})
|
|
2355
|
+
}}
|
|
2356
|
+
>
|
|
2357
|
+
Remove
|
|
2358
|
+
</button>
|
|
2359
|
+
</AccordionItemButton>
|
|
2360
|
+
</>
|
|
2361
|
+
</AccordionItemHeading>
|
|
2362
|
+
<AccordionItemPanel>
|
|
2363
|
+
<label>
|
|
2364
|
+
<span>Anchor Value</span>
|
|
2365
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2366
|
+
<Tooltip.Target>
|
|
2367
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2368
|
+
</Tooltip.Target>
|
|
2369
|
+
<Tooltip.Content>
|
|
2370
|
+
<p>Enter the value as its shown in the data column</p>
|
|
2371
|
+
</Tooltip.Content>
|
|
2372
|
+
</Tooltip>
|
|
2373
|
+
<input
|
|
2374
|
+
type='text'
|
|
2375
|
+
value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
|
|
2376
|
+
onChange={e => {
|
|
2377
|
+
e.preventDefault()
|
|
2378
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
2379
|
+
copiedAnchors[index].value = e.target.value
|
|
2380
|
+
updateConfig({
|
|
2381
|
+
...config,
|
|
2382
|
+
xAxis: {
|
|
2383
|
+
...config.xAxis,
|
|
2384
|
+
anchors: copiedAnchors
|
|
2385
|
+
}
|
|
2386
|
+
})
|
|
2387
|
+
}}
|
|
2388
|
+
/>
|
|
2389
|
+
</label>
|
|
2390
|
+
|
|
2391
|
+
<label>
|
|
2392
|
+
<span>Anchor Color</span>
|
|
2393
|
+
<input
|
|
2394
|
+
type='text'
|
|
2395
|
+
value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
|
|
2396
|
+
onChange={e => {
|
|
2397
|
+
e.preventDefault()
|
|
2398
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
2399
|
+
copiedAnchors[index].color = e.target.value
|
|
2400
|
+
updateConfig({
|
|
2401
|
+
...config,
|
|
2402
|
+
xAxis: {
|
|
2403
|
+
...config.xAxis,
|
|
2404
|
+
anchors: copiedAnchors
|
|
2405
|
+
}
|
|
2406
|
+
})
|
|
2407
|
+
}}
|
|
2408
|
+
/>
|
|
2409
|
+
</label>
|
|
2410
|
+
|
|
2411
|
+
<label>
|
|
2412
|
+
Anchor Line Style
|
|
2413
|
+
<select
|
|
2414
|
+
value={config.xAxis.anchors[index].lineStyle || ''}
|
|
2415
|
+
onChange={e => {
|
|
2416
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
2417
|
+
copiedAnchors[index].lineStyle = e.target.value
|
|
2418
|
+
updateConfig({
|
|
2419
|
+
...config,
|
|
2420
|
+
xAxis: {
|
|
2421
|
+
...config.xAxis,
|
|
2422
|
+
anchors: copiedAnchors
|
|
2423
|
+
}
|
|
2424
|
+
})
|
|
2425
|
+
}}
|
|
2426
|
+
>
|
|
2427
|
+
<option>Select</option>
|
|
2428
|
+
{lineOptions.map(line => (
|
|
2429
|
+
<option key={line.key}>{line.value}</option>
|
|
2430
|
+
))}
|
|
2431
|
+
</select>
|
|
2432
|
+
</label>
|
|
2433
|
+
</AccordionItemPanel>
|
|
2434
|
+
</AccordionItem>
|
|
2435
|
+
))}
|
|
2436
|
+
</Accordion>
|
|
2437
|
+
|
|
2438
|
+
<button
|
|
2439
|
+
className='btn full-width'
|
|
2440
|
+
onClick={e => {
|
|
2441
|
+
e.preventDefault()
|
|
2442
|
+
const anchors = [...config.xAxis.anchors]
|
|
2443
|
+
anchors.push({})
|
|
2444
|
+
updateConfig({
|
|
2445
|
+
...config,
|
|
2446
|
+
xAxis: {
|
|
2447
|
+
...config.xAxis,
|
|
2448
|
+
anchors
|
|
2449
|
+
}
|
|
2450
|
+
})
|
|
2451
|
+
}}
|
|
2452
|
+
>
|
|
2453
|
+
Add Anchor
|
|
2454
|
+
</button>
|
|
2455
|
+
</div>
|
|
2456
|
+
) : (
|
|
2457
|
+
<div className='edit-block'>
|
|
2458
|
+
<h3>Anchors</h3>
|
|
2459
|
+
<Accordion allowZeroExpanded>
|
|
2460
|
+
{config.yAxis?.anchors?.map((anchor, index) => (
|
|
2461
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
2462
|
+
<AccordionItemHeading className='series-item__title'>
|
|
2463
|
+
<>
|
|
2464
|
+
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
2465
|
+
Anchor {index + 1}
|
|
2466
|
+
<button
|
|
2467
|
+
className='series-list__remove'
|
|
2468
|
+
onClick={e => {
|
|
2469
|
+
e.preventDefault()
|
|
2470
|
+
const copiedAnchorGroups = [...config.yAxis.anchors]
|
|
2471
|
+
copiedAnchorGroups.splice(index, 1)
|
|
2472
|
+
updateConfig({
|
|
2473
|
+
...config,
|
|
2474
|
+
yAxis: {
|
|
2475
|
+
...config.yAxis,
|
|
2476
|
+
anchors: copiedAnchorGroups
|
|
2477
|
+
}
|
|
2478
|
+
})
|
|
2479
|
+
}}
|
|
2480
|
+
>
|
|
2481
|
+
Remove
|
|
2482
|
+
</button>
|
|
2483
|
+
</AccordionItemButton>
|
|
2484
|
+
</>
|
|
2485
|
+
</AccordionItemHeading>
|
|
2486
|
+
<AccordionItemPanel>
|
|
2487
|
+
<label>
|
|
2488
|
+
<span>Anchor Value</span>
|
|
2489
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2490
|
+
<Tooltip.Target>
|
|
2491
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2492
|
+
</Tooltip.Target>
|
|
2493
|
+
<Tooltip.Content>
|
|
2494
|
+
<p>Enter the value as its shown in the data column</p>
|
|
2495
|
+
</Tooltip.Content>
|
|
2496
|
+
</Tooltip>
|
|
2497
|
+
<input
|
|
2498
|
+
type='text'
|
|
2499
|
+
value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
|
|
2500
|
+
onChange={e => {
|
|
2501
|
+
e.preventDefault()
|
|
2502
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
2503
|
+
copiedAnchors[index].value = e.target.value
|
|
2504
|
+
updateConfig({
|
|
2505
|
+
...config,
|
|
2506
|
+
yAxis: {
|
|
2507
|
+
...config.yAxis,
|
|
2508
|
+
anchors: copiedAnchors
|
|
2509
|
+
}
|
|
2510
|
+
})
|
|
2511
|
+
}}
|
|
2512
|
+
/>
|
|
2513
|
+
</label>
|
|
2514
|
+
|
|
2515
|
+
<label>
|
|
2516
|
+
<span>Anchor Color</span>
|
|
2517
|
+
<input
|
|
2518
|
+
type='text'
|
|
2519
|
+
value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
|
|
2520
|
+
onChange={e => {
|
|
2521
|
+
e.preventDefault()
|
|
2522
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
2523
|
+
copiedAnchors[index].color = e.target.value
|
|
2524
|
+
updateConfig({
|
|
2525
|
+
...config,
|
|
2526
|
+
yAxis: {
|
|
2527
|
+
...config.yAxis,
|
|
2528
|
+
anchors: copiedAnchors
|
|
2529
|
+
}
|
|
2530
|
+
})
|
|
2531
|
+
}}
|
|
2532
|
+
/>
|
|
2533
|
+
</label>
|
|
2534
|
+
|
|
2535
|
+
<label>
|
|
2536
|
+
Anchor Line Style
|
|
2537
|
+
<select
|
|
2538
|
+
value={config.yAxis.anchors[index].lineStyle || ''}
|
|
2539
|
+
onChange={e => {
|
|
2540
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
2541
|
+
copiedAnchors[index].lineStyle = e.target.value
|
|
2542
|
+
updateConfig({
|
|
2543
|
+
...config,
|
|
2544
|
+
yAxis: {
|
|
2545
|
+
...config.yAxis,
|
|
2546
|
+
anchors: copiedAnchors
|
|
2547
|
+
}
|
|
2548
|
+
})
|
|
2549
|
+
}}
|
|
2550
|
+
>
|
|
2551
|
+
<option>Select</option>
|
|
2552
|
+
{lineOptions.map(line => (
|
|
2553
|
+
<option key={line.key}>{line.value}</option>
|
|
2554
|
+
))}
|
|
2555
|
+
</select>
|
|
2556
|
+
</label>
|
|
2557
|
+
</AccordionItemPanel>
|
|
2558
|
+
</AccordionItem>
|
|
2559
|
+
))}
|
|
2560
|
+
</Accordion>
|
|
2561
|
+
|
|
2562
|
+
<button
|
|
2563
|
+
className='btn full-width'
|
|
2564
|
+
onClick={e => {
|
|
2565
|
+
e.preventDefault()
|
|
2566
|
+
const anchors = [...config.yAxis.anchors]
|
|
2567
|
+
anchors.push({})
|
|
2568
|
+
updateConfig({
|
|
2569
|
+
...config,
|
|
2570
|
+
yAxis: {
|
|
2571
|
+
...config.yAxis,
|
|
2572
|
+
anchors
|
|
2573
|
+
}
|
|
2574
|
+
})
|
|
2575
|
+
}}
|
|
2576
|
+
>
|
|
2577
|
+
Add Anchor
|
|
2578
|
+
</button>
|
|
2579
|
+
</div>
|
|
2580
|
+
)}
|
|
1831
2581
|
</AccordionItemPanel>
|
|
1832
2582
|
</AccordionItem>
|
|
1833
|
-
|
|
1834
2583
|
{config.visualizationType !== 'Pie' && config.visualizationType !== 'Paired Bar' && (
|
|
1835
2584
|
<AccordionItem>
|
|
1836
2585
|
<AccordionItemHeading>
|
|
@@ -1840,8 +2589,173 @@ const EditorPanel = () => {
|
|
|
1840
2589
|
<Regions config={config} updateConfig={updateConfig} />
|
|
1841
2590
|
</AccordionItemPanel>
|
|
1842
2591
|
</AccordionItem>
|
|
2592
|
+
)}{' '}
|
|
2593
|
+
{/* Columns */}
|
|
2594
|
+
{config.visualizationType !== 'Box Plot' && config.table.showVertical && (
|
|
2595
|
+
<AccordionItem>
|
|
2596
|
+
<AccordionItemHeading>
|
|
2597
|
+
<AccordionItemButton>Columns</AccordionItemButton>
|
|
2598
|
+
</AccordionItemHeading>
|
|
2599
|
+
<AccordionItemPanel>
|
|
2600
|
+
{'navigation' !== config.type && (
|
|
2601
|
+
<fieldset className='primary-fieldset edit-block'>
|
|
2602
|
+
<label>
|
|
2603
|
+
<span className='edit-label'>
|
|
2604
|
+
Additional Columns
|
|
2605
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2606
|
+
<Tooltip.Target>
|
|
2607
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2608
|
+
</Tooltip.Target>
|
|
2609
|
+
<Tooltip.Content>
|
|
2610
|
+
<p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
|
|
2611
|
+
</Tooltip.Content>
|
|
2612
|
+
</Tooltip>
|
|
2613
|
+
</span>
|
|
2614
|
+
</label>
|
|
2615
|
+
{additionalColumns.map(val => (
|
|
2616
|
+
<fieldset className='edit-block' key={val}>
|
|
2617
|
+
<button
|
|
2618
|
+
className='remove-column'
|
|
2619
|
+
onClick={event => {
|
|
2620
|
+
event.preventDefault()
|
|
2621
|
+
removeAdditionalColumn(val)
|
|
2622
|
+
}}
|
|
2623
|
+
>
|
|
2624
|
+
Remove
|
|
2625
|
+
</button>
|
|
2626
|
+
<label>
|
|
2627
|
+
<span className='edit-label column-heading'>Column</span>
|
|
2628
|
+
<select
|
|
2629
|
+
value={config.columns[val] ? config.columns[val].name : columnsOptions[0]}
|
|
2630
|
+
onChange={event => {
|
|
2631
|
+
editColumn(val, 'name', event.target.value)
|
|
2632
|
+
}}
|
|
2633
|
+
>
|
|
2634
|
+
{columnsOptions}
|
|
2635
|
+
</select>
|
|
2636
|
+
</label>
|
|
2637
|
+
<TextField value={config.columns[val].label} section='columns' subsection={val} fieldName='label' label='Label' updateField={updateField} />
|
|
2638
|
+
<ul className='column-edit'>
|
|
2639
|
+
<li className='three-col'>
|
|
2640
|
+
<TextField value={config.columns[val].prefix} section='columns' subsection={val} fieldName='prefix' label='Prefix' updateField={updateField} />
|
|
2641
|
+
<TextField value={config.columns[val].suffix} section='columns' subsection={val} fieldName='suffix' label='Suffix' updateField={updateField} />
|
|
2642
|
+
<TextField type='number' value={config.columns[val].roundToPlace} section='columns' subsection={val} fieldName='roundToPlace' label='Round' updateField={updateField} />
|
|
2643
|
+
</li>
|
|
2644
|
+
<li>
|
|
2645
|
+
<label className='checkbox'>
|
|
2646
|
+
<input
|
|
2647
|
+
type='checkbox'
|
|
2648
|
+
checked={config.columns[val].useCommas}
|
|
2649
|
+
onChange={event => {
|
|
2650
|
+
editColumn(val, 'useCommas', event.target.checked)
|
|
2651
|
+
}}
|
|
2652
|
+
/>
|
|
2653
|
+
<span className='edit-label'>Add Commas to Numbers</span>
|
|
2654
|
+
</label>
|
|
2655
|
+
</li>
|
|
2656
|
+
<li>
|
|
2657
|
+
<label className='checkbox'>
|
|
2658
|
+
<input
|
|
2659
|
+
type='checkbox'
|
|
2660
|
+
checked={config.columns[val].dataTable}
|
|
2661
|
+
onChange={event => {
|
|
2662
|
+
editColumn(val, 'dataTable', event.target.checked)
|
|
2663
|
+
}}
|
|
2664
|
+
/>
|
|
2665
|
+
<span className='edit-label'>Display in Data Table</span>
|
|
2666
|
+
</label>
|
|
2667
|
+
</li>
|
|
2668
|
+
{/* disable for now */}
|
|
2669
|
+
{/*
|
|
2670
|
+
<li>
|
|
2671
|
+
<label className='checkbox'>
|
|
2672
|
+
<input
|
|
2673
|
+
type='checkbox'
|
|
2674
|
+
checked={config.columns[val].tooltip}
|
|
2675
|
+
onChange={event => {
|
|
2676
|
+
editColumn(val, 'tooltip', event.target.checked)
|
|
2677
|
+
}}
|
|
2678
|
+
/>
|
|
2679
|
+
<span className='edit-label'>Display in Tooltips</span>
|
|
2680
|
+
</label>
|
|
2681
|
+
</li>
|
|
2682
|
+
*/}
|
|
2683
|
+
</ul>
|
|
2684
|
+
</fieldset>
|
|
2685
|
+
))}
|
|
2686
|
+
<button
|
|
2687
|
+
className={'btn full-width'}
|
|
2688
|
+
onClick={event => {
|
|
2689
|
+
event.preventDefault()
|
|
2690
|
+
addAdditionalColumn(additionalColumns.length + 1)
|
|
2691
|
+
}}
|
|
2692
|
+
>
|
|
2693
|
+
Add Column
|
|
2694
|
+
</button>
|
|
2695
|
+
</fieldset>
|
|
2696
|
+
)}
|
|
2697
|
+
{'category' === config.legend.type && (
|
|
2698
|
+
<fieldset className='primary-fieldset edit-block'>
|
|
2699
|
+
<label>
|
|
2700
|
+
<span className='edit-label'>
|
|
2701
|
+
Additional Category
|
|
2702
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2703
|
+
<Tooltip.Target>
|
|
2704
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2705
|
+
</Tooltip.Target>
|
|
2706
|
+
<Tooltip.Content>
|
|
2707
|
+
<p>You can provide additional categories to ensure they appear in the legend</p>
|
|
2708
|
+
</Tooltip.Content>
|
|
2709
|
+
</Tooltip>
|
|
2710
|
+
</span>
|
|
2711
|
+
</label>
|
|
2712
|
+
{config.legend.additionalCategories &&
|
|
2713
|
+
config.legend.additionalCategories.map((val, i) => (
|
|
2714
|
+
<fieldset className='edit-block' key={val}>
|
|
2715
|
+
<button
|
|
2716
|
+
className='remove-column'
|
|
2717
|
+
onClick={event => {
|
|
2718
|
+
event.preventDefault()
|
|
2719
|
+
const updatedAdditionaCategories = [...config.legend.additionalCategories]
|
|
2720
|
+
updatedAdditionaCategories.splice(i, 1)
|
|
2721
|
+
updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
|
|
2722
|
+
}}
|
|
2723
|
+
>
|
|
2724
|
+
Remove
|
|
2725
|
+
</button>
|
|
2726
|
+
<label>
|
|
2727
|
+
<span className='edit-label column-heading'>Category</span>
|
|
2728
|
+
<TextField
|
|
2729
|
+
value={val}
|
|
2730
|
+
section='legend'
|
|
2731
|
+
subsection={null}
|
|
2732
|
+
fieldName='additionalCategories'
|
|
2733
|
+
updateField={(section, subsection, fieldName, value) => {
|
|
2734
|
+
const updatedAdditionaCategories = [...config.legend.additionalCategories]
|
|
2735
|
+
updatedAdditionaCategories[i] = value
|
|
2736
|
+
updateField(section, subsection, fieldName, updatedAdditionaCategories)
|
|
2737
|
+
}}
|
|
2738
|
+
/>
|
|
2739
|
+
</label>
|
|
2740
|
+
</fieldset>
|
|
2741
|
+
))}
|
|
2742
|
+
<button
|
|
2743
|
+
className={'btn full-width'}
|
|
2744
|
+
onClick={event => {
|
|
2745
|
+
event.preventDefault()
|
|
2746
|
+
const updatedAdditionaCategories = [...(config.legend.additionalCategories || [])]
|
|
2747
|
+
updatedAdditionaCategories.push('')
|
|
2748
|
+
updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
|
|
2749
|
+
}}
|
|
2750
|
+
>
|
|
2751
|
+
Add Category
|
|
2752
|
+
</button>
|
|
2753
|
+
</fieldset>
|
|
2754
|
+
)}
|
|
2755
|
+
</AccordionItemPanel>
|
|
2756
|
+
</AccordionItem>
|
|
1843
2757
|
)}
|
|
1844
|
-
|
|
2758
|
+
{/* End Columns */}
|
|
1845
2759
|
{visHasLegend() && (
|
|
1846
2760
|
<AccordionItem>
|
|
1847
2761
|
<AccordionItemHeading>
|
|
@@ -1898,91 +2812,134 @@ const EditorPanel = () => {
|
|
|
1898
2812
|
</AccordionItemPanel>
|
|
1899
2813
|
</AccordionItem>
|
|
1900
2814
|
)}
|
|
1901
|
-
|
|
1902
2815
|
<AccordionItem>
|
|
1903
2816
|
<AccordionItemHeading>
|
|
1904
2817
|
<AccordionItemButton>Filters</AccordionItemButton>
|
|
1905
2818
|
</AccordionItemHeading>
|
|
1906
2819
|
<AccordionItemPanel>
|
|
2820
|
+
{config.filters && (
|
|
2821
|
+
<>
|
|
2822
|
+
{/* prettier-ignore */}
|
|
2823
|
+
<Select
|
|
2824
|
+
value={config.filterBehavior}
|
|
2825
|
+
fieldName='filterBehavior'
|
|
2826
|
+
label='Filter Behavior'
|
|
2827
|
+
updateField={updateField}
|
|
2828
|
+
options={['Apply Button', 'Filter Change']}
|
|
2829
|
+
tooltip={
|
|
2830
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2831
|
+
<Tooltip.Target>
|
|
2832
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2833
|
+
</Tooltip.Target>
|
|
2834
|
+
<Tooltip.Content>
|
|
2835
|
+
<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>
|
|
2836
|
+
</Tooltip.Content>
|
|
2837
|
+
</Tooltip>
|
|
2838
|
+
}
|
|
2839
|
+
/>
|
|
2840
|
+
<br />
|
|
2841
|
+
</>
|
|
2842
|
+
)}
|
|
1907
2843
|
{config.filters && (
|
|
1908
2844
|
<ul className='filters-list'>
|
|
1909
|
-
{
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
<span className='edit-label column-heading'>Filter</span>
|
|
1922
|
-
<select
|
|
1923
|
-
value={filter.columnName}
|
|
1924
|
-
onChange={e => {
|
|
1925
|
-
updateFilterProp('columnName', index, e.target.value)
|
|
2845
|
+
{/* Whether filters should apply onChange or Apply Button */}
|
|
2846
|
+
|
|
2847
|
+
{config.filters.map((filter, index) => {
|
|
2848
|
+
if (filter.type === 'url') return <></>
|
|
2849
|
+
|
|
2850
|
+
return (
|
|
2851
|
+
<fieldset className='edit-block' key={index}>
|
|
2852
|
+
<button
|
|
2853
|
+
type='button'
|
|
2854
|
+
className='remove-column'
|
|
2855
|
+
onClick={() => {
|
|
2856
|
+
removeFilter(index)
|
|
1926
2857
|
}}
|
|
1927
2858
|
>
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
updateFilterProp('label', index, e.target.value)
|
|
1943
|
-
}}
|
|
1944
|
-
/>
|
|
1945
|
-
</label>
|
|
1946
|
-
|
|
1947
|
-
<label>
|
|
1948
|
-
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
1949
|
-
<select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
|
|
1950
|
-
{filterOptions.map((option, index) => {
|
|
1951
|
-
return (
|
|
1952
|
-
<option value={option.value} key={`filter-${index}`}>
|
|
1953
|
-
{option.label}
|
|
2859
|
+
Remove
|
|
2860
|
+
</button>
|
|
2861
|
+
<label>
|
|
2862
|
+
<span className='edit-label column-heading'>Filter</span>
|
|
2863
|
+
<select
|
|
2864
|
+
value={filter.columnName}
|
|
2865
|
+
onChange={e => {
|
|
2866
|
+
updateFilterProp('columnName', index, e.target.value)
|
|
2867
|
+
}}
|
|
2868
|
+
>
|
|
2869
|
+
<option value=''>- Select Option -</option>
|
|
2870
|
+
{getFilters(true).map((dataKey, index) => (
|
|
2871
|
+
<option value={dataKey} key={index}>
|
|
2872
|
+
{dataKey}
|
|
1954
2873
|
</option>
|
|
1955
|
-
)
|
|
1956
|
-
|
|
1957
|
-
</
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
<
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
)
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
2874
|
+
))}
|
|
2875
|
+
</select>
|
|
2876
|
+
</label>
|
|
2877
|
+
|
|
2878
|
+
<label>
|
|
2879
|
+
<span className='edit-label column-heading'>Filter Style</span>
|
|
2880
|
+
|
|
2881
|
+
<select
|
|
2882
|
+
value={filter.filterStyle}
|
|
2883
|
+
onChange={e => {
|
|
2884
|
+
updateFilterProp('filterStyle', index, e.target.value)
|
|
2885
|
+
}}
|
|
2886
|
+
>
|
|
2887
|
+
{filterStyleOptions.map(item => {
|
|
2888
|
+
return <option value={item}>{item}</option>
|
|
2889
|
+
})}
|
|
2890
|
+
</select>
|
|
2891
|
+
</label>
|
|
2892
|
+
<label>
|
|
2893
|
+
<span className='edit-label column-heading'>Label</span>
|
|
2894
|
+
<input
|
|
2895
|
+
type='text'
|
|
2896
|
+
value={filter.label}
|
|
2897
|
+
onChange={e => {
|
|
2898
|
+
updateFilterProp('label', index, e.target.value)
|
|
2899
|
+
}}
|
|
2900
|
+
/>
|
|
2901
|
+
</label>
|
|
2902
|
+
|
|
2903
|
+
<label>
|
|
2904
|
+
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
2905
|
+
<select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
|
|
2906
|
+
{filterOrderOptions.map((option, index) => {
|
|
2907
|
+
return (
|
|
2908
|
+
<option value={option.value} key={`filter-${index}`}>
|
|
2909
|
+
{option.label}
|
|
2910
|
+
</option>
|
|
2911
|
+
)
|
|
2912
|
+
})}
|
|
2913
|
+
</select>
|
|
2914
|
+
|
|
2915
|
+
{filter.order === 'cust' && (
|
|
2916
|
+
<DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
|
|
2917
|
+
<Droppable droppableId='filter_order'>
|
|
2918
|
+
{provided => (
|
|
2919
|
+
<ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
2920
|
+
{config.filters[index]?.values.map((value, index) => {
|
|
2921
|
+
return (
|
|
2922
|
+
<Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
|
|
2923
|
+
{(provided, snapshot) => (
|
|
2924
|
+
<li>
|
|
2925
|
+
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
2926
|
+
{value}
|
|
2927
|
+
</div>
|
|
2928
|
+
</li>
|
|
2929
|
+
)}
|
|
2930
|
+
</Draggable>
|
|
2931
|
+
)
|
|
2932
|
+
})}
|
|
2933
|
+
{provided.placeholder}
|
|
2934
|
+
</ul>
|
|
2935
|
+
)}
|
|
2936
|
+
</Droppable>
|
|
2937
|
+
</DragDropContext>
|
|
2938
|
+
)}
|
|
2939
|
+
</label>
|
|
2940
|
+
</fieldset>
|
|
2941
|
+
)
|
|
2942
|
+
})}
|
|
1986
2943
|
</ul>
|
|
1987
2944
|
)}
|
|
1988
2945
|
{!config.filters && <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
|
|
@@ -1991,7 +2948,6 @@ const EditorPanel = () => {
|
|
|
1991
2948
|
</button>
|
|
1992
2949
|
</AccordionItemPanel>
|
|
1993
2950
|
</AccordionItem>
|
|
1994
|
-
|
|
1995
2951
|
<AccordionItem>
|
|
1996
2952
|
<AccordionItemHeading>
|
|
1997
2953
|
<AccordionItemButton>Visual</AccordionItemButton>
|
|
@@ -2205,77 +3161,101 @@ const EditorPanel = () => {
|
|
|
2205
3161
|
)}
|
|
2206
3162
|
</AccordionItemPanel>
|
|
2207
3163
|
</AccordionItem>
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
<
|
|
2211
|
-
<
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
<
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
<Tooltip
|
|
2225
|
-
<
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
<
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
<
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
3164
|
+
{/* Spark Line has no data table */}
|
|
3165
|
+
{config.visualizationType !== 'Spark Line' && (
|
|
3166
|
+
<AccordionItem>
|
|
3167
|
+
<AccordionItemHeading>
|
|
3168
|
+
<AccordionItemButton>Data Table</AccordionItemButton>
|
|
3169
|
+
</AccordionItemHeading>
|
|
3170
|
+
<AccordionItemPanel>
|
|
3171
|
+
<TextField
|
|
3172
|
+
value={config.table.label}
|
|
3173
|
+
updateField={updateField}
|
|
3174
|
+
section='table'
|
|
3175
|
+
fieldName='label'
|
|
3176
|
+
id='tableLabel'
|
|
3177
|
+
label='Data Table Title'
|
|
3178
|
+
placeholder='Data Table'
|
|
3179
|
+
tooltip={
|
|
3180
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3181
|
+
<Tooltip.Target>
|
|
3182
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
3183
|
+
</Tooltip.Target>
|
|
3184
|
+
<Tooltip.Content>
|
|
3185
|
+
<p>Label is required for Data Table for 508 Compliance</p>
|
|
3186
|
+
</Tooltip.Content>
|
|
3187
|
+
</Tooltip>
|
|
3188
|
+
}
|
|
3189
|
+
/>
|
|
3190
|
+
<CheckBox
|
|
3191
|
+
value={config.table.show}
|
|
3192
|
+
section='table'
|
|
3193
|
+
fieldName='show'
|
|
3194
|
+
label='Show Data Table'
|
|
3195
|
+
updateField={updateField}
|
|
3196
|
+
className='column-heading'
|
|
3197
|
+
tooltip={
|
|
3198
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3199
|
+
<Tooltip.Target>
|
|
3200
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
3201
|
+
</Tooltip.Target>
|
|
3202
|
+
<Tooltip.Content>
|
|
3203
|
+
<p>Hiding the data table may affect accessibility. An alternate form of accessing visualization data is a 508 requirement.</p>
|
|
3204
|
+
</Tooltip.Content>
|
|
3205
|
+
</Tooltip>
|
|
3206
|
+
}
|
|
3207
|
+
/>
|
|
3208
|
+
{config.visualizationType !== 'Box Plot' && (
|
|
3209
|
+
<CheckBox
|
|
3210
|
+
value={config.table.showVertical}
|
|
3211
|
+
section='table'
|
|
3212
|
+
fieldName='showVertical'
|
|
3213
|
+
label='Show Vertical Data'
|
|
3214
|
+
updateField={updateField}
|
|
3215
|
+
className='column-heading'
|
|
3216
|
+
tooltip={
|
|
3217
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3218
|
+
<Tooltip.Target>
|
|
3219
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
3220
|
+
</Tooltip.Target>
|
|
3221
|
+
<Tooltip.Content>
|
|
3222
|
+
<p>This will draw the data table with vertical data instead of horizontal.</p>
|
|
3223
|
+
</Tooltip.Content>
|
|
3224
|
+
</Tooltip>
|
|
3225
|
+
}
|
|
3226
|
+
/>
|
|
3227
|
+
)}
|
|
3228
|
+
<TextField value={config.table.indexLabel} section='table' fieldName='indexLabel' label='Index Column Header' updateField={updateField} />
|
|
3229
|
+
<TextField
|
|
3230
|
+
value={config.table.caption}
|
|
3231
|
+
updateField={updateField}
|
|
3232
|
+
section='table'
|
|
3233
|
+
type='textarea'
|
|
3234
|
+
fieldName='caption'
|
|
3235
|
+
label='Data Table Caption'
|
|
3236
|
+
placeholder=' Data table'
|
|
3237
|
+
tooltip={
|
|
3238
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3239
|
+
<Tooltip.Target>
|
|
3240
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
3241
|
+
</Tooltip.Target>
|
|
3242
|
+
<Tooltip.Content>
|
|
3243
|
+
<p>Enter a description of the data table to be read by screen readers.</p>
|
|
3244
|
+
</Tooltip.Content>
|
|
3245
|
+
</Tooltip>
|
|
3246
|
+
}
|
|
3247
|
+
/>
|
|
3248
|
+
<CheckBox value={config.table.limitHeight} section='table' fieldName='limitHeight' label='Limit Table Height' updateField={updateField} />
|
|
3249
|
+
{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} />}
|
|
3250
|
+
<CheckBox value={config.table.expanded} section='table' fieldName='expanded' label='Expanded by Default' updateField={updateField} />
|
|
3251
|
+
{isDashboard && <CheckBox value={config.table.showDataTableLink} section='table' fieldName='showDataTableLink' label='Show Data Table Name & Link' updateField={updateField} />}
|
|
3252
|
+
{isLoadedFromUrl && <CheckBox value={config.table.showDownloadUrl} section='table' fieldName='showDownloadUrl' label='Show URL to Automatically Updated Data' updateField={updateField} />}
|
|
3253
|
+
<CheckBox value={config.table.download} section='table' fieldName='download' label='Show Download CSV Link' updateField={updateField} />
|
|
3254
|
+
{/* <CheckBox value={config.table.showDownloadImgButton} section='table' fieldName='showDownloadImgButton' label='Display Image Button' updateField={updateField} /> */}
|
|
3255
|
+
{/* <CheckBox value={config.table.showDownloadPdfButton} section='table' fieldName='showDownloadPdfButton' label='Display PDF Button' updateField={updateField} /> */}
|
|
3256
|
+
</AccordionItemPanel>
|
|
3257
|
+
</AccordionItem>
|
|
3258
|
+
)}
|
|
2279
3259
|
</Accordion>
|
|
2280
3260
|
</form>
|
|
2281
3261
|
{config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig} state={config} convertStateToConfig={convertStateToConfig} />}
|