@cdc/chart 4.23.2 → 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.
Files changed (94) hide show
  1. package/dist/cdcchart.js +42292 -40337
  2. package/examples/feature/__data__/area-chart.json +56 -0
  3. package/examples/{planet-example-data.json → feature/__data__/planet-example-data-max-increase.json} +4 -4
  4. package/examples/feature/__data__/planet-example-data.json +68 -0
  5. package/examples/feature/area/area-chart.json +244 -0
  6. package/examples/{example-bar-chart.json → feature/bar/example-bar-chart.json} +4 -1
  7. package/examples/feature/bar/horizontal-chart-max-increase.json +44 -0
  8. package/examples/{horizontal-chart.json → feature/bar/horizontal-chart.json} +10 -4
  9. package/examples/{horizontal-stacked-bar-chart.json → feature/bar/horizontal-stacked-bar-chart.json} +7 -3
  10. package/examples/{planet-chart-horizontal-example-config.json → feature/bar/planet-chart-horizontal-example-config.json} +8 -3
  11. package/examples/feature/bar/planet-example-config.json +156 -0
  12. package/examples/{box-plot.json → feature/boxplot/boxplot.json} +7 -8
  13. package/examples/feature/boxplot/testing.csv +38 -0
  14. package/examples/feature/combo/combochart-categories_are_numbers .json +18 -0
  15. package/examples/{planet-combo-example-config.json → feature/combo/planet-combo-example-config.json} +1 -1
  16. package/examples/feature/deviation/planet-deviation-config.json +168 -0
  17. package/examples/feature/deviation/planet-deviation-data.json +38 -0
  18. package/examples/feature/filters/filter-testing.json +178 -0
  19. package/examples/feature/forecasting/case_date_example.csv +130 -0
  20. package/examples/feature/forecasting/effective_reproduction.json +202 -0
  21. package/examples/feature/forecasting/r_data.csv +130 -0
  22. package/examples/feature/line/line-chart-max-increase.json +32 -0
  23. package/examples/feature/line/line-chart.json +124 -0
  24. package/examples/{paired-bar-example.json → feature/paired-bar/paired-bar-example.json} +10 -4
  25. package/examples/{planet-pie-example-config.json → feature/pie/planet-pie-example-config.json} +2 -2
  26. package/examples/{scatterplot-continuous.csv → feature/scatterplot/scatterplot-continuous.csv} +3 -3
  27. package/examples/{scatterplot.json → feature/scatterplot/scatterplot.json} +3 -3
  28. package/examples/feature/sparkline/example-sparkline.json +76 -0
  29. package/examples/feature/tests-big-small/big-small-test-bar.json +328 -0
  30. package/examples/feature/tests-big-small/big-small-test-line.json +328 -0
  31. package/examples/feature/tests-big-small/big-small-test-negative.json +328 -0
  32. package/examples/{case-rate-example-config.json → feature/tests-case-rate/case-rate-example-config.json} +2 -2
  33. package/examples/{covid-confidence-example-config.json → feature/tests-covid/covid-confidence-example-config.json} +8 -3
  34. package/examples/{covid-example-config.json → feature/tests-covid/covid-example-config.json} +7 -3
  35. package/examples/{cutoff-example-config.json → feature/tests-cutoff/cutoff-example-config.json} +7 -3
  36. package/examples/{date-exclusions-config.json → feature/tests-date-exclusions/date-exclusions-config.json} +2 -2
  37. package/examples/{example-bar-chart-nonnumeric.json → feature/tests-non-numerics/example-bar-chart-nonnumeric.json} +1 -1
  38. package/examples/{line-chart-nonnumeric.json → feature/tests-non-numerics/line-chart-nonnumeric.json} +5 -5
  39. package/examples/{planet-pie-example-config-nonnumeric.json → feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json} +2 -2
  40. package/examples/{sparkline-chart-nonnumeric.json → feature/tests-non-numerics/sparkline-chart-nonnumeric.json} +2 -2
  41. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +31 -172
  42. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +145 -7
  43. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json +1 -0
  44. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +96 -14
  45. package/examples/gallery/line/line.json +1 -0
  46. package/examples/gallery/paired-bar/paired-bar-chart.json +1 -0
  47. package/index.html +76 -35
  48. package/package.json +6 -3
  49. package/src/CdcChart.jsx +245 -106
  50. package/src/components/AreaChart.jsx +233 -0
  51. package/src/components/BarChart.jsx +103 -62
  52. package/src/components/BoxPlot.jsx +39 -18
  53. package/src/components/DataTable.jsx +26 -21
  54. package/src/components/DeviationBar.jsx +191 -0
  55. package/src/components/EditorPanel.jsx +662 -298
  56. package/src/components/Legend.jsx +59 -46
  57. package/src/components/LineChart.jsx +12 -36
  58. package/src/components/LinearChart.jsx +163 -64
  59. package/src/components/PairedBarChart.jsx +6 -7
  60. package/src/components/PieChart.jsx +12 -17
  61. package/src/components/ScatterPlot.jsx +19 -16
  62. package/src/components/SparkLine.jsx +84 -118
  63. package/src/components/useIntersectionObserver.jsx +1 -1
  64. package/src/data/initial-state.js +27 -7
  65. package/src/hooks/useColorPalette.js +58 -48
  66. package/src/hooks/useReduceData.js +3 -4
  67. package/src/index.jsx +3 -2
  68. package/src/scss/editor-panel.scss +20 -0
  69. package/src/scss/main.scss +8 -6
  70. package/src/test/CdcChart.test.jsx +6 -0
  71. package/examples/box-plot.csv +0 -5
  72. package/examples/dynamic-legends.json +0 -125
  73. package/examples/line-chart.json +0 -34
  74. package/examples/planet-example-config.json +0 -37
  75. package/examples/temp-example-config.json +0 -64
  76. package/examples/temp-example-data.json +0 -130
  77. package/src/components/Filters.jsx +0 -125
  78. /package/examples/{age-adjusted-rates.json → feature/__data__/age-adjusted-rates.json} +0 -0
  79. /package/examples/{new-data.csv → feature/__data__/new-data.csv} +0 -0
  80. /package/examples/{Barchart_with_negative.json → feature/bar/Barchart_with_negative.json} +0 -0
  81. /package/examples/{stacked-vertical-bar-example-negative.json → feature/bar/stacked-vertical-bar-example-negative.json} +0 -0
  82. /package/examples/{stacked-vertical-bar-example.json → feature/bar/stacked-vertical-bar-example.json} +0 -0
  83. /package/examples/{box-plot-data.json → feature/boxplot/box-plot-data.json} +0 -0
  84. /package/examples/{newdata.json → feature/boxplot/boxplot-data.json} +0 -0
  85. /package/examples/{paired-bar-data.json → feature/paired-bar/paired-bar-data.json} +0 -0
  86. /package/examples/{paired-bar-formatted.json → feature/paired-bar/paired-bar-formatted.json} +0 -0
  87. /package/examples/{case-rate-example-data.json → feature/tests-case-rate/case-rate-example-data.json} +0 -0
  88. /package/examples/{covid-example-data-confidence.json → feature/tests-covid/covid-example-data-confidence.json} +0 -0
  89. /package/examples/{covid-example-data.json → feature/tests-covid/covid-example-data.json} +0 -0
  90. /package/examples/{cutoff-example-data.json → feature/tests-cutoff/cutoff-example-data.json} +0 -0
  91. /package/examples/{date-exclusions-data.json → feature/tests-date-exclusions/date-exclusions-data.json} +0 -0
  92. /package/examples/{example-combo-bar-nonnumeric.json → feature/tests-non-numerics/example-combo-bar-nonnumeric.json} +0 -0
  93. /package/examples/{planet-example-data-nonnumeric.json → feature/tests-non-numerics/planet-example-data-nonnumeric.json} +0 -0
  94. /package/examples/{stacked-vertical-bar-example-nonnumerics.json → feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json} +0 -0
@@ -17,9 +17,10 @@ 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 * as allCurves from '@visx/curve'
21
+ import { useFilters } from '@cdc/core/components/Filters'
20
22
 
21
23
  /* eslint-disable react-hooks/rules-of-hooks */
22
-
23
24
  const TextField = memo(({ label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', i = null, min = null, ...attributes }) => {
24
25
  const [value, setValue] = useState(stateValue)
25
26
 
@@ -71,12 +72,12 @@ 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}
78
79
  checked={value}
79
- onChange={() => {
80
+ onChange={e => {
80
81
  updateField(section, subsection, fieldName, !value)
81
82
  }}
82
83
  {...attributes}
@@ -206,17 +207,22 @@ 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, 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
- const { paletteName, isPaletteReversed, filteredPallets, filteredQualitative, dispatch } = useColorPalette(colorPalettes, config)
213
- useEffect(() => {
214
- if (paletteName) updateConfig({ ...config, palette: paletteName })
215
- }, [paletteName]) // eslint-disable-line
216
213
 
217
- useEffect(() => {
218
- dispatch({ type: 'GET_PALETTE', payload: colorPalettes, paletteName: config.palette })
219
- }, [dispatch, config.palette]) // eslint-disable-line
214
+ const { twoColorPalettes, sequential, nonSequential } = useColorPalette(config, updateConfig)
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
+ }
220
226
 
221
227
  // when the visualization type changes we
222
228
  // have to update the individual series type & axis details
@@ -240,22 +246,20 @@ const EditorPanel = () => {
240
246
  })
241
247
  }, [config.visualizationType]) // eslint-disable-line
242
248
 
243
- const { hasRightAxis } = useRightAxis({ config: config, yMax: config.yAxis.size, data: config.data, updateConfig })
244
-
245
- const filterOptions = [
246
- {
247
- label: 'Ascending Alphanumeric',
248
- value: 'asc'
249
- },
250
- {
251
- label: 'Descending Alphanumeric',
252
- value: 'desc'
253
- },
254
- {
255
- label: 'Custom',
256
- value: 'cust'
249
+ // Scatter Plots default date/category axis is 'continuous'
250
+ useEffect(() => {
251
+ if (config.visualizationType === 'Scatter Plot') {
252
+ updateConfig({
253
+ ...config,
254
+ xAxis: {
255
+ ...config.xAxis,
256
+ type: 'continuous'
257
+ }
258
+ })
257
259
  }
258
- ]
260
+ }, [])
261
+
262
+ const { hasRightAxis } = useRightAxis({ config: config, yMax: config.yAxis.size, data: config.data, updateConfig })
259
263
 
260
264
  const getItemStyle = (isDragging, draggableStyle) => ({
261
265
  ...draggableStyle
@@ -284,10 +288,13 @@ const EditorPanel = () => {
284
288
  if (updatedConfig.table.show === undefined) {
285
289
  updatedConfig.table.show = !isDashboard
286
290
  }
291
+ // DEV-3293 - Force combo to always be vertical
292
+ if (updatedConfig.visualizationType === 'Combo') {
293
+ updatedConfig.orientation = 'vertical'
294
+ }
287
295
  }
288
296
 
289
297
  const updateField = (section, subsection, fieldName, newValue) => {
290
-
291
298
  if (section === 'boxplot' && subsection === 'legend') {
292
299
  updateConfig({
293
300
  ...config,
@@ -315,7 +322,6 @@ const EditorPanel = () => {
315
322
  })
316
323
  return
317
324
  }
318
-
319
325
  if (null === section && null === subsection) {
320
326
  let updatedConfig = { ...config, [fieldName]: newValue }
321
327
  enforceRestrictions(updatedConfig)
@@ -327,8 +333,6 @@ const EditorPanel = () => {
327
333
 
328
334
  let sectionValue = isArray ? [...config[section], newValue] : { ...config[section], [fieldName]: newValue }
329
335
 
330
- console.log('section value', sectionValue)
331
-
332
336
  if (null !== subsection) {
333
337
  if (isArray) {
334
338
  sectionValue = [...config[section]]
@@ -353,6 +357,19 @@ const EditorPanel = () => {
353
357
  return null
354
358
  }
355
359
 
360
+ useEffect(() => {
361
+ if (!config.general?.boxplot) return
362
+ if (!config.general.boxplot.firstQuartilePercentage) {
363
+ updateConfig({
364
+ ...config,
365
+ boxplot: {
366
+ ...config.boxplot,
367
+ firstQuartilePercentage: 25
368
+ }
369
+ })
370
+ }
371
+ }, [config])
372
+
356
373
  const setLollipopShape = shape => {
357
374
  updateConfig({
358
375
  ...config,
@@ -386,7 +403,7 @@ const EditorPanel = () => {
386
403
 
387
404
  const addNewSeries = seriesKey => {
388
405
  let newSeries = config.series ? [...config.series] : []
389
- newSeries.push({ dataKey: seriesKey, type: 'Bar' })
406
+ newSeries.push({ dataKey: seriesKey, type: config.visualizationType })
390
407
  updateConfig({ ...config, series: newSeries }) // left axis series keys
391
408
  }
392
409
 
@@ -461,6 +478,16 @@ const EditorPanel = () => {
461
478
  }
462
479
  }
463
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
+
464
491
  const getColumns = (filter = true) => {
465
492
  let columns = {}
466
493
 
@@ -506,7 +533,7 @@ const EditorPanel = () => {
506
533
  }
507
534
 
508
535
  const showBarStyleOptions = () => {
509
- if (config.visualizationType === 'Bar' && config.visualizationSubType !== 'stacked' && (config.orientation === 'horizontal' || config.orientation === 'vertical')) {
536
+ if ((config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && config.visualizationSubType !== 'stacked' && (config.orientation === 'horizontal' || config.orientation === 'vertical')) {
510
537
  return ['flat', 'rounded', 'lollipop']
511
538
  } else {
512
539
  return ['flat', 'rounded']
@@ -590,6 +617,13 @@ const EditorPanel = () => {
590
617
  }
591
618
  }, [config.isLollipopChart, config.lollipopShape]) // eslint-disable-line
592
619
 
620
+ /// temporary force orientation untill we support Vartical deviaton bar
621
+ useEffect(() => {
622
+ if (config.visualizationType === 'Deviation Bar') {
623
+ updateConfig({ ...config, orientation: 'horizontal' })
624
+ }
625
+ }, [config.visualizationType])
626
+
593
627
  const ExclusionsList = useCallback(() => {
594
628
  const exclusions = [...config.exclusions.keys]
595
629
  return (
@@ -610,21 +644,65 @@ const EditorPanel = () => {
610
644
  )
611
645
  }, [config]) // eslint-disable-line
612
646
 
613
- const checkIsLine = type => {
614
- return type === ('Line' || 'dashed-sm')
647
+ const visHasLegend = () => {
648
+ const { visualizationType } = config
649
+
650
+ switch (visualizationType) {
651
+ case 'Box Plot':
652
+ return false
653
+ default:
654
+ return true
655
+ }
615
656
  }
616
657
 
617
- const handleFilterChange = (idx1, idx2, filterIndex, filter) => {
618
- let filterOrder = filter.values
619
- let [movedItem] = filterOrder.splice(idx1, 1)
620
- filterOrder.splice(idx2, 0, movedItem)
621
- let filters = [...config.filters]
622
- let filterItem = { ...config.filters[filterIndex] }
623
- filterItem.active = filter.values[0]
624
- filterItem.orderedValues = filterOrder
625
- filterItem.order = 'cust'
626
- filters[filterIndex] = filterItem
627
- updateConfig({ ...config, filters })
658
+ const visCanAnimate = () => {
659
+ const { visualizationType } = config
660
+ switch (visualizationType) {
661
+ case 'Area Chart':
662
+ return false
663
+ case 'Scatter Plot':
664
+ return false
665
+ case 'Box Plot':
666
+ return false
667
+ default:
668
+ return true
669
+ }
670
+ }
671
+
672
+ const visHasDataCutoff = () => {
673
+ const { visualizationType } = config
674
+ switch (visualizationType) {
675
+ case 'Box Plot':
676
+ return false
677
+ case 'Pie':
678
+ return false
679
+ default:
680
+ return true
681
+ }
682
+ }
683
+
684
+ const visHasLabelOnData = () => {
685
+ const { visualizationType } = config
686
+ switch (visualizationType) {
687
+ case 'Area Chart':
688
+ return false
689
+ case 'Box Plot':
690
+ return false
691
+ case 'Pie':
692
+ return false
693
+ case 'Scatter Plot':
694
+ return false
695
+ default:
696
+ return true
697
+ }
698
+ }
699
+
700
+ const visHasBarBorders = () => {
701
+ const { series, visualizationType } = config
702
+ if (visualizationType === 'Box Plot') return false
703
+ if (visualizationType === 'Scatter Plot') return false
704
+ if (visualizationType === 'Pie') return false
705
+ return series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar' || series.type === 'Deviation Bar')
628
706
  }
629
707
 
630
708
  const handleSeriesChange = (idx1, idx2) => {
@@ -679,7 +757,10 @@ const EditorPanel = () => {
679
757
  case (config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && enteredValue && minVal > 0 && parseFloat(enteredValue) > 0:
680
758
  message = 'Value must be less than or equal to 0'
681
759
  break
682
- case enteredValue && minVal < 0 && parseFloat(enteredValue) > minVal:
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:
683
764
  message = 'Value must be less than ' + minValue
684
765
  break
685
766
  default:
@@ -694,6 +775,54 @@ const EditorPanel = () => {
694
775
  validateMaxValue()
695
776
  }, [minValue, maxValue, config]) // eslint-disable-line
696
777
 
778
+ // prettier-ignore
779
+ const enabledChartTypes = [
780
+ // 'Area Chart',
781
+ 'Bar',
782
+ 'Box Plot',
783
+ 'Combo',
784
+ 'Deviation Bar',
785
+ 'Line',
786
+ 'Paired Bar',
787
+ 'Pie',
788
+ 'Scatter Plot',
789
+ 'Spark Line'
790
+ ]
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
+
697
826
  return (
698
827
  <ErrorBoundary component='EditorPanel'>
699
828
  {config.newViz && <Confirm />}
@@ -713,22 +842,44 @@ const EditorPanel = () => {
713
842
  <AccordionItemButton>General</AccordionItemButton>
714
843
  </AccordionItemHeading>
715
844
  <AccordionItemPanel>
716
- <Select value={config.visualizationType} fieldName='visualizationType' label='Chart Type' updateField={updateField} options={['Pie', 'Line', 'Bar', 'Combo', 'Paired Bar', 'Spark Line']} />
717
-
845
+ <Select value={config.visualizationType} fieldName='visualizationType' label='Chart Type' updateField={updateField} options={enabledChartTypes} />
718
846
  {(config.visualizationType === 'Bar' || config.visualizationType === 'Combo') && <Select value={config.visualizationSubType || 'Regular'} fieldName='visualizationSubType' label='Chart Subtype' updateField={updateField} options={['regular', 'stacked']} />}
719
847
  {config.visualizationType === 'Bar' && <Select value={config.orientation || 'vertical'} fieldName='orientation' label='Orientation' updateField={updateField} options={['vertical', 'horizontal']} />}
720
- {config.visualizationType === 'Bar' && <Select value={config.isLollipopChart ? 'lollipop' : config.barStyle || 'flat'} fieldName='barStyle' label='bar style' updateField={updateField} options={showBarStyleOptions()} />}
721
- {config.visualizationType === 'Bar' && config.barStyle === 'rounded' && <Select value={config.tipRounding || 'top'} fieldName='tipRounding' label='tip rounding' updateField={updateField} options={['top', 'full']} />}
722
- {config.visualizationType === 'Bar' && config.barStyle === 'rounded' && <Select value={config.roundingStyle || 'standard'} fieldName='roundingStyle' label='rounding style' updateField={updateField} options={['standard', 'shallow', 'finger']} />}
848
+ {config.visualizationType === 'Deviation Bar' && <Select label='Orientation' options={['horizontal']} />}
849
+ {(config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && <Select value={config.isLollipopChart ? 'lollipop' : config.barStyle || 'flat'} fieldName='barStyle' label='bar style' updateField={updateField} options={showBarStyleOptions()} />}
850
+ {(config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && config.barStyle === 'rounded' && <Select value={config.tipRounding || 'top'} fieldName='tipRounding' label='tip rounding' updateField={updateField} options={['top', 'full']} />}
851
+ {(config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && config.barStyle === 'rounded' && (
852
+ <Select value={config.roundingStyle || 'standard'} fieldName='roundingStyle' label='rounding style' updateField={updateField} options={['standard', 'shallow', 'finger']} />
853
+ )}
723
854
  {config.visualizationType === 'Bar' && config.orientation === 'horizontal' && <Select value={config.yAxis.labelPlacement || 'Below Bar'} section='yAxis' fieldName='labelPlacement' label='Label Placement' updateField={updateField} options={['Below Bar', 'On Date/Category Axis']} />}
724
- {config.orientation === 'horizontal' && (config.yAxis.labelPlacement === 'Below Bar' || config.yAxis.labelPlacement === 'On Date/Category Axis' || config.visualizationType === 'Paired Bar') ? (
855
+ {config.orientation === 'horizontal' && (config.yAxis.labelPlacement === 'Below Bar' || config.yAxis.labelPlacement === 'On Date/Category Axis' || config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar') ? (
725
856
  <CheckBox value={config.yAxis.displayNumbersOnBar} section='yAxis' fieldName='displayNumbersOnBar' label={config.isLollipopChart ? 'Display Numbers after Bar' : 'Display Numbers on Bar'} updateField={updateField} />
726
857
  ) : (
727
- config.visualizationType !== 'Pie' && <CheckBox value={config.labels} fieldName='labels' label='Display label on data' updateField={updateField} />
858
+ visHasLabelOnData() && <CheckBox value={config.labels} fieldName='labels' label='Display label on data' updateField={updateField} />
728
859
  )}
729
860
  {config.visualizationType === 'Pie' && <Select fieldName='pieType' label='Pie Chart Type' updateField={updateField} options={['Regular', 'Donut']} />}
730
861
 
731
- <TextField value={config.title} fieldName='title' label='Title' updateField={updateField} />
862
+ <TextField
863
+ value={config.title || 'Chart Title'}
864
+ fieldName='title'
865
+ id='title'
866
+ label='Title'
867
+ placeholder='Chart Title'
868
+ //defaultValue='Chart Title'
869
+ updateField={updateField}
870
+ //onChange={handleTitleChange}
871
+ tooltip={
872
+ <Tooltip style={{ textTransform: 'none' }}>
873
+ <Tooltip.Target>
874
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
875
+ </Tooltip.Target>
876
+ <Tooltip.Content>
877
+ <p>Title is required to set the name of the download file but can be hidden using the option below.</p>
878
+ </Tooltip.Content>
879
+ </Tooltip>
880
+ }
881
+ />
882
+ <CheckBox value={config.showTitle} fieldName='showTitle' label='Show Title' updateField={updateField} />
732
883
  <TextField
733
884
  value={config.superTitle}
734
885
  updateField={updateField}
@@ -813,6 +964,18 @@ const EditorPanel = () => {
813
964
  <AccordionItemPanel>
814
965
  {(!config.series || config.series.length === 0) && config.visualizationType !== 'Paired Bar' && <p className='warning'>At least one series is required</p>}
815
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
+ />
816
979
  {config.series && config.series.length !== 0 && (
817
980
  <>
818
981
  <fieldset>
@@ -830,9 +993,9 @@ const EditorPanel = () => {
830
993
  <DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
831
994
  <Droppable droppableId='filter_order'>
832
995
  {provided => (
833
- <ul {...provided.droppableProps} className='series-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
996
+ <ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
834
997
  {config.series.map((series, i) => {
835
- if (config.visualizationType === 'Combo') {
998
+ if (config.visualizationType === 'Combo' || 'Area Chart') {
836
999
  let changeType = (i, value) => {
837
1000
  let series = [...config.series]
838
1001
  series[i].type = value
@@ -842,50 +1005,143 @@ const EditorPanel = () => {
842
1005
  updateConfig({ ...config, series })
843
1006
  }
844
1007
 
1008
+ let changeLineType = (i, value) => {
1009
+ let series = [...config.series]
1010
+ series[i].lineType = value
1011
+ updateConfig({ ...config, series })
1012
+ }
1013
+
845
1014
  let typeDropdown = (
846
- <select
847
- value={series.type}
848
- onChange={event => {
849
- changeType(i, event.target.value)
850
- }}
851
- style={{ width: '100px', marginRight: '10px' }}
852
- >
853
- <option value='' default>
854
- Select
855
- </option>
856
- <option value='Bar'>Bar</option>
857
- <option value='Line'>Solid Line</option>
858
- <option value='dashed-sm'>Small Dashed</option>
859
- <option value='dashed-md'>Medium Dashed</option>
860
- <option value='dashed-lg'>Large Dashed</option>
861
- </select>
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
+ </>
1073
+ )
1074
+
1075
+ // line type dropdown
1076
+ const lineType = (
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
1089
+ </option>
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
+ </>
862
1100
  )
863
1101
 
864
1102
  return (
865
1103
  <Draggable key={series.dataKey} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
866
1104
  {(provided, snapshot) => (
867
- <li>
868
- <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
869
- <div className={`series-list__name${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}>
870
- <div className='series-list__name-text'>{series.dataKey}</div>
871
- </div>
872
- <span>
873
- <span className='series-list__dropdown'>{typeDropdown}</span>
874
- {config.series && config.series.length > 1 && (
875
- <button className='series-list__remove' onClick={() => removeSeries(series.dataKey)}>
876
- &#215;
877
- </button>
878
- )}
879
- </span>
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>
1133
+ )}
1134
+ </AccordionItem>
1135
+ </Accordion>
880
1136
  </div>
881
- </li>
1137
+ </>
882
1138
  )}
883
1139
  </Draggable>
884
1140
  )
885
1141
  }
886
1142
 
887
1143
  return (
888
- <Draggable key={series.dataKey} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
1144
+ <Draggable key={`series.dataKey--${i}`} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
889
1145
  {(provided, snapshot) => (
890
1146
  <li
891
1147
  key={series.dataKey}
@@ -918,18 +1174,6 @@ const EditorPanel = () => {
918
1174
  </>
919
1175
  )}
920
1176
 
921
- <Select
922
- fieldName='visualizationType'
923
- label='Add Data Series'
924
- initial='Select'
925
- onChange={e => {
926
- if (e.target.value !== '' && e.target.value !== 'Select') {
927
- addNewSeries(e.target.value)
928
- }
929
- e.target.value = ''
930
- }}
931
- options={getColumns()}
932
- />
933
1177
  {config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
934
1178
  <>
935
1179
  <span className='divider-heading'>Confidence Keys</span>
@@ -949,7 +1193,7 @@ const EditorPanel = () => {
949
1193
  <AccordionItemButton>Measures</AccordionItemButton>
950
1194
  </AccordionItemHeading>
951
1195
  <AccordionItemPanel>
952
- <h4>Labels for 5-Number Summary</h4>
1196
+ <h4 style={{ fontSize: '18px' }}>Labels for 5-Number Summary</h4>
953
1197
 
954
1198
  {/* prettier-ignore */}
955
1199
  {/* max */}
@@ -1060,12 +1304,14 @@ const EditorPanel = () => {
1060
1304
  </Tooltip>
1061
1305
  }
1062
1306
  />
1307
+ <br />
1308
+ <h4 style={{ fontSize: '18px' }}>Labels for Additional Measures</h4>
1063
1309
 
1064
1310
  {/* iqr */}
1065
1311
  <TextField type='text' value={config.boxplot.labels.iqr} fieldName='iqr' section='boxplot' subsection='labels' label='Interquartile Range' updateField={updateField} />
1066
1312
 
1067
1313
  {/* count */}
1068
- <TextField type='text' value={config.boxplot.labels.count} fieldName='count' section='boxplot' subsection='labels' label='Count' updateField={updateField} />
1314
+ <TextField type='text' value={config.boxplot.labels.total} fieldName='total' section='boxplot' subsection='labels' label='Total' updateField={updateField} />
1069
1315
 
1070
1316
  {/* mean */}
1071
1317
  <TextField type='text' value={config.boxplot.labels.mean} fieldName='mean' section='boxplot' subsection='labels' label='Mean' updateField={updateField} />
@@ -1074,10 +1320,10 @@ const EditorPanel = () => {
1074
1320
  {/* values */}
1075
1321
  <TextField type='text' value={config.boxplot.labels.values} fieldName='values' section='boxplot' subsection='labels' label='Values' updateField={updateField} />
1076
1322
  <br />
1077
- <h4>Percentages for Quartiles</h4>
1323
+ <h4 style={{ fontSize: '18px' }}>Percentages for Quartiles</h4>
1078
1324
  <TextField
1079
1325
  type='number'
1080
- value={config.boxplot.firstQuartilePercentage}
1326
+ value={config.boxplot.firstQuartilePercentage ? config.boxplot.firstQuartilePercentage : 25}
1081
1327
  fieldName='firstQuartilePercentage'
1082
1328
  section='boxplot'
1083
1329
  label='Lower Quartile'
@@ -1097,7 +1343,7 @@ const EditorPanel = () => {
1097
1343
 
1098
1344
  <TextField
1099
1345
  type='number'
1100
- value={config.boxplot.thirdQuartilePercentage}
1346
+ value={config.boxplot.thirdQuartilePercentage ? config.boxplot.thirdQuartilePercentage : 75}
1101
1347
  fieldName='thirdQuartilePercentage'
1102
1348
  label='Upper Quartile'
1103
1349
  section='boxplot'
@@ -1118,70 +1364,6 @@ const EditorPanel = () => {
1118
1364
  </AccordionItem>
1119
1365
  )}
1120
1366
 
1121
- {hasRightAxis && config.series && config.visualizationType === 'Combo' && (
1122
- <AccordionItem>
1123
- <AccordionItemHeading>
1124
- <AccordionItemButton>Assign Data Series Axis</AccordionItemButton>
1125
- </AccordionItemHeading>
1126
- <AccordionItemPanel>
1127
- <p>Only line series data can be assigned to the right axis. Check the data series section above.</p>
1128
- {config.series && config.series.filter(series => checkIsLine(series.type)) && (
1129
- <>
1130
- <fieldset>
1131
- <legend className='edit-label float-left'>Displaying</legend>
1132
- <Tooltip style={{ textTransform: 'none' }}>
1133
- <Tooltip.Target>
1134
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1135
- </Tooltip.Target>
1136
- <Tooltip.Content>
1137
- <p>Assign an axis for the series</p>
1138
- </Tooltip.Content>
1139
- </Tooltip>
1140
- </fieldset>
1141
- <ul className='series-list'>
1142
- {config.series &&
1143
- config.series.map((series, i) => {
1144
- if (series.type === 'Bar') return false // can't set individual bars atm.
1145
-
1146
- let changeAxis = (i, value) => {
1147
- let series = [...config.series]
1148
- series[i].axis = value
1149
- updateConfig({ ...config, series })
1150
- }
1151
-
1152
- let axisDropdown = (
1153
- <select
1154
- value={series.axis}
1155
- onChange={event => {
1156
- changeAxis(i, event.target.value)
1157
- }}
1158
- style={{ width: '100px', marginRight: '10px' }}
1159
- >
1160
- <option value='Left' default>
1161
- left
1162
- </option>
1163
- <option value='Right'>right</option>
1164
- </select>
1165
- )
1166
-
1167
- return (
1168
- <li key={series.dataKey}>
1169
- <div className={`series-list__name${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}>
1170
- <div className='series-list__name-text'>{series.dataKey}</div>
1171
- </div>
1172
- <span>
1173
- <span className='series-list__dropdown'>{axisDropdown}</span>
1174
- </span>
1175
- </li>
1176
- )
1177
- })}
1178
- </ul>
1179
- </>
1180
- )}
1181
- </AccordionItemPanel>
1182
- </AccordionItem>
1183
- )}
1184
-
1185
1367
  <AccordionItem>
1186
1368
  <AccordionItemHeading>
1187
1369
  <AccordionItemButton>
@@ -1215,7 +1397,7 @@ const EditorPanel = () => {
1215
1397
  {config.visualizationType !== 'Pie' && (
1216
1398
  <>
1217
1399
  <TextField value={config.yAxis.label} section='yAxis' fieldName='label' label='Label' updateField={updateField} />
1218
- {config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && <CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />}
1400
+ {config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && config.visualizationType !== 'Box Plot' && <CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />}
1219
1401
  <TextField value={config.yAxis.numTicks} placeholder='Auto' type='number' section='yAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1220
1402
  {config.visualizationType === 'Paired Bar' && <TextField value={config.yAxis.tickRotation || 0} type='number' min='0' section='yAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
1221
1403
  <TextField
@@ -1237,9 +1419,11 @@ const EditorPanel = () => {
1237
1419
  </Tooltip>
1238
1420
  }
1239
1421
  />
1240
- <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} />
1422
+ {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1423
+ {/* <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1241
1424
  {config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
1242
1425
  {config.orientation !== 'horizontal' && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Display Gridlines' updateField={updateField} />}
1426
+ <CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
1243
1427
  </>
1244
1428
  )}
1245
1429
  <span className='divider-heading'>Number Formatting</span>
@@ -1306,8 +1490,17 @@ const EditorPanel = () => {
1306
1490
  <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
1307
1491
  <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
1308
1492
  <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
1309
- <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='update max value' type='number' placeholder='Auto' updateField={updateField} />
1493
+ <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />
1310
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>
1497
+ {config.visualizationType === 'Deviation Bar' && (
1498
+ <>
1499
+ <TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
1500
+ <TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
1501
+ <CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Display Deviation point label' updateField={updateField} />
1502
+ </>
1503
+ )}
1311
1504
  </>
1312
1505
  ) : (
1313
1506
  config.visualizationType !== 'Pie' && (
@@ -1315,9 +1508,9 @@ const EditorPanel = () => {
1315
1508
  <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
1316
1509
  <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
1317
1510
  <CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
1318
- <TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='update max value' placeholder='Auto' updateField={updateField} />
1511
+ <TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='max value' placeholder='Auto' updateField={updateField} />
1319
1512
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
1320
- <TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='update min value' placeholder='Auto' updateField={updateField} />
1513
+ <TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />
1321
1514
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1322
1515
  </>
1323
1516
  )
@@ -1396,9 +1589,9 @@ const EditorPanel = () => {
1396
1589
  <AccordionItemPanel>
1397
1590
  {config.visualizationType !== 'Pie' && (
1398
1591
  <>
1399
- <Select value={config.xAxis.type} section='xAxis' fieldName='type' label='Data Type' updateField={updateField} options={config.visualizationType !== 'Scatter Plot' ? ['categorical', 'date'] : ['categorical', 'date', 'continuous']} />
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']} />
1400
1593
  <Select
1401
- value={config.xAxis.dataKey || ''}
1594
+ value={config.xAxis.dataKey || setCategoryAxis() || ''}
1402
1595
  section='xAxis'
1403
1596
  fieldName='dataKey'
1404
1597
  label='Data Key'
@@ -1447,6 +1640,66 @@ const EditorPanel = () => {
1447
1640
  <>
1448
1641
  <TextField value={config.xAxis.label} section='xAxis' fieldName='label' label='Label' updateField={updateField} />
1449
1642
 
1643
+ {config.xAxis.type === 'continuous' && (
1644
+ <>
1645
+ <TextField
1646
+ value={config.dataFormat.bottomPrefix}
1647
+ section='dataFormat'
1648
+ fieldName='bottomPrefix'
1649
+ label='Prefix'
1650
+ updateField={updateField}
1651
+ tooltip={
1652
+ <Tooltip style={{ textTransform: 'none' }}>
1653
+ <Tooltip.Target>
1654
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1655
+ </Tooltip.Target>
1656
+ <Tooltip.Content>
1657
+ {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1658
+ {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1659
+ </Tooltip.Content>
1660
+ </Tooltip>
1661
+ }
1662
+ />
1663
+
1664
+ <TextField
1665
+ value={config.dataFormat.bottomSuffix}
1666
+ section='dataFormat'
1667
+ fieldName='bottomSuffix'
1668
+ label='Suffix'
1669
+ updateField={updateField}
1670
+ tooltip={
1671
+ <Tooltip style={{ textTransform: 'none' }}>
1672
+ <Tooltip.Target>
1673
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1674
+ </Tooltip.Target>
1675
+ <Tooltip.Content>
1676
+ {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1677
+ {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1678
+ </Tooltip.Content>
1679
+ </Tooltip>
1680
+ }
1681
+ />
1682
+
1683
+ <CheckBox
1684
+ value={config.dataFormat.bottomAbbreviated}
1685
+ section='dataFormat'
1686
+ fieldName='bottomAbbreviated'
1687
+ label='Abbreviate Axis Values'
1688
+ updateField={updateField}
1689
+ tooltip={
1690
+ <Tooltip style={{ textTransform: 'none' }}>
1691
+ <Tooltip.Target>
1692
+ <Icon display='question' />
1693
+ </Tooltip.Target>
1694
+ <Tooltip.Content>
1695
+ <p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
1696
+ </Tooltip.Content>
1697
+ </Tooltip>
1698
+ }
1699
+ />
1700
+ </>
1701
+ )}
1702
+
1450
1703
  {config.xAxis.type === 'date' && (
1451
1704
  <>
1452
1705
  <p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
@@ -1518,7 +1771,16 @@ const EditorPanel = () => {
1518
1771
  <TextField value={config.xAxis.numTicks} placeholder='Auto' type='number' min='1' section='xAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1519
1772
 
1520
1773
  <TextField value={config.xAxis.size} type='number' min='0' section='xAxis' fieldName='size' label={config.orientation === 'horizontal' ? 'Size (Width)' : 'Size (Height)'} className='number-narrow' updateField={updateField} />
1521
- <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} />
1774
+
1775
+ {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1776
+ {/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1777
+
1778
+ {config.xAxis.type === 'continuous' && (
1779
+ <>
1780
+ <CheckBox value={config.dataFormat.bottomCommas} section='dataFormat' fieldName='bottomCommas' label='Add commas' updateField={updateField} />
1781
+ <TextField value={config.dataFormat.bottomRoundTo} type='number' section='dataFormat' fieldName='bottomRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1782
+ </>
1783
+ )}
1522
1784
 
1523
1785
  {config.yAxis.labelPlacement !== 'Below Bar' && <TextField value={config.xAxis.tickRotation} type='number' min='0' section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
1524
1786
  {config.orientation === 'horizontal' ? (
@@ -1596,13 +1858,14 @@ const EditorPanel = () => {
1596
1858
  </AccordionItem>
1597
1859
  )}
1598
1860
 
1599
- <AccordionItem>
1600
- <AccordionItemHeading>
1601
- <AccordionItemButton>Legend</AccordionItemButton>
1602
- </AccordionItemHeading>
1603
- <AccordionItemPanel>
1604
- <CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
1605
- {/* <fieldset className="checkbox-group">
1861
+ {visHasLegend() && (
1862
+ <AccordionItem>
1863
+ <AccordionItemHeading>
1864
+ <AccordionItemButton>Legend</AccordionItemButton>
1865
+ </AccordionItemHeading>
1866
+ <AccordionItemPanel>
1867
+ <CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
1868
+ {/* <fieldset className="checkbox-group">
1606
1869
  <CheckBox value={config.legend.dynamicLegend} section="legend" fieldName="dynamicLegend" label="Dynamic Legend" updateField={updateField}/>
1607
1870
  {config.legend.dynamicLegend && (
1608
1871
  <>
@@ -1613,43 +1876,77 @@ const EditorPanel = () => {
1613
1876
  </>
1614
1877
  )}
1615
1878
  </fieldset> */}
1616
- <CheckBox
1617
- value={config.legend.hide}
1618
- section='legend'
1619
- fieldName='hide'
1620
- label='Hide Legend'
1621
- updateField={updateField}
1622
- tooltip={
1623
- <Tooltip style={{ textTransform: 'none' }}>
1624
- <Tooltip.Target>
1625
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1626
- </Tooltip.Target>
1627
- <Tooltip.Content>
1628
- <p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
1629
- </Tooltip.Content>
1630
- </Tooltip>
1631
- }
1632
- />
1633
- <CheckBox value={config.legend.showLegendValuesTooltip} section='legend' fieldName='showLegendValuesTooltip' label='Show Legend Values in Tooltip' updateField={updateField} />
1879
+ <CheckBox
1880
+ value={config.legend.hide ? true : false}
1881
+ section='legend'
1882
+ fieldName='hide'
1883
+ label='Hide Legend'
1884
+ updateField={updateField}
1885
+ tooltip={
1886
+ <Tooltip style={{ textTransform: 'none' }}>
1887
+ <Tooltip.Target>
1888
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1889
+ </Tooltip.Target>
1890
+ <Tooltip.Content>
1891
+ <p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
1892
+ </Tooltip.Content>
1893
+ </Tooltip>
1894
+ }
1895
+ />
1634
1896
 
1635
- {config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
1636
- <Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
1637
- )}
1638
- <Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={updateField} options={['highlight', 'isolate']} />
1639
- <TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
1640
- <Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
1641
- {config.legend.position === 'bottom' && <CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />}
1642
- <TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
1643
- </AccordionItemPanel>
1644
- </AccordionItem>
1897
+ {/* {config.visualizationType === 'Box Plot' &&
1898
+ <>
1899
+ <CheckBox value={config.boxplot.legend.displayHowToReadText} fieldName='displayHowToReadText' section='boxplot' subsection='legend' label='Display How To Read Text' updateField={updateField} />
1900
+ <TextField type='textarea' value={config.boxplot.legend.howToReadText} updateField={updateField} fieldName='howToReadText' section='boxplot' subsection='legend' label='How to read text' />
1901
+ </>
1902
+ } */}
1903
+
1904
+ {config.visualizationType !== 'Box Plot' && <CheckBox value={config.legend.showLegendValuesTooltip ? true : false} section='legend' fieldName='showLegendValuesTooltip' label='Show Legend Values in Tooltip' updateField={updateField} />}
1905
+
1906
+ {config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
1907
+ <Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
1908
+ )}
1909
+ <Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={updateField} options={['highlight', 'isolate']} />
1910
+ <TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
1911
+ <Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
1912
+ {config.legend.position === 'bottom' && <CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />}
1913
+ <TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
1914
+ </AccordionItemPanel>
1915
+ </AccordionItem>
1916
+ )}
1645
1917
 
1646
1918
  <AccordionItem>
1647
1919
  <AccordionItemHeading>
1648
1920
  <AccordionItemButton>Filters</AccordionItemButton>
1649
1921
  </AccordionItemHeading>
1650
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
+ )}
1651
1946
  {config.filters && (
1652
1947
  <ul className='filters-list'>
1948
+ {/* Whether filters should apply onChange or Apply Button */}
1949
+
1653
1950
  {config.filters.map((filter, index) => (
1654
1951
  <fieldset className='edit-block' key={index}>
1655
1952
  <button
@@ -1670,13 +1967,29 @@ const EditorPanel = () => {
1670
1967
  }}
1671
1968
  >
1672
1969
  <option value=''>- Select Option -</option>
1673
- {getColumns().map((dataKey, index) => (
1970
+ {getFilters(true).map((dataKey, index) => (
1674
1971
  <option value={dataKey} key={index}>
1675
1972
  {dataKey}
1676
1973
  </option>
1677
1974
  ))}
1678
1975
  </select>
1679
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> */}
1680
1993
  <label>
1681
1994
  <span className='edit-label column-heading'>Label</span>
1682
1995
  <input
@@ -1691,7 +2004,7 @@ const EditorPanel = () => {
1691
2004
  <label>
1692
2005
  <span className='edit-filterOrder column-heading'>Filter Order</span>
1693
2006
  <select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
1694
- {filterOptions.map((option, index) => {
2007
+ {filterOrderOptions.map((option, index) => {
1695
2008
  return (
1696
2009
  <option value={option.value} key={`filter-${index}`}>
1697
2010
  {option.label}
@@ -1701,7 +2014,7 @@ const EditorPanel = () => {
1701
2014
  </select>
1702
2015
 
1703
2016
  {filter.order === 'cust' && (
1704
- <DragDropContext onDragEnd={({ source, destination }) => handleFilterChange(source.index, destination.index, index, config.filters[index])}>
2017
+ <DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
1705
2018
  <Droppable droppableId='filter_order'>
1706
2019
  {provided => (
1707
2020
  <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
@@ -1765,21 +2078,18 @@ const EditorPanel = () => {
1765
2078
  </>
1766
2079
  )}
1767
2080
 
1768
- {config.visualizationType === 'Box Plot' &&
1769
- <fieldset fieldset className='fieldset fieldset--boxplot'>
2081
+ {config.visualizationType === 'Box Plot' && (
2082
+ <fieldset className='fieldset fieldset--boxplot'>
1770
2083
  <legend className=''>Box Plot Settings</legend>
1771
- {config.visualizationType === 'Box Plot' && <Select value={config.boxplot.borders} fieldName='borders' section='boxplot' label='Box Plot Borders' updateField={updateField} options={['true', 'false']} />}
1772
- {config.visualizationType === 'Box Plot' && <CheckBox value={config.boxplot.plotOutlierValues} fieldName='plotOutlierValues' section='boxplot' label='Plot Outliers' updateField={updateField} />}
1773
- {config.visualizationType === 'Box Plot' && <CheckBox value={config.boxplot.plotNonOutlierValues} fieldName='plotNonOutlierValues' section='boxplot' label='Plot non-outlier values' updateField={updateField} />}
1774
- {config.visualizationType === 'Box Plot' && <CheckBox value={config.boxplot.legend.displayHowToReadText} fieldName='displayHowToReadText' section='boxplot' subsection='legend' label='Display How To Read Text' updateField={updateField} />}
1775
- <TextField type='textarea' value={config.boxplot.legend.howToReadText} updateField={updateField} fieldName='howToReadText' section='boxplot' subsection='legend' label='How to read text' />
2084
+ <Select value={config.boxplot.borders} fieldName='borders' section='boxplot' label='Box Plot Borders' updateField={updateField} options={['true', 'false']} />
2085
+ <CheckBox value={config.boxplot.plotOutlierValues} fieldName='plotOutlierValues' section='boxplot' label='Plot Outliers' updateField={updateField} />
2086
+ <CheckBox value={config.boxplot.plotNonOutlierValues} fieldName='plotNonOutlierValues' section='boxplot' label='Plot non-outlier values' updateField={updateField} />
1776
2087
  </fieldset>
1777
- }
2088
+ )}
1778
2089
 
1779
2090
  <Select value={config.fontSize} fieldName='fontSize' label='Font Size' updateField={updateField} options={['small', 'medium', 'large']} />
1780
- {config.visualizationType !== 'Box Plot' && config.series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar') && <Select value={config.barHasBorder} fieldName='barHasBorder' label='Bar Borders' updateField={updateField} options={['true', 'false']} />}
1781
-
1782
- <CheckBox value={config.animate} fieldName='animate' label='Animate Visualization' updateField={updateField} />
2091
+ {visHasBarBorders() && <Select value={config.barHasBorder} fieldName='barHasBorder' label='Bar Borders' updateField={updateField} options={['true', 'false']} />}
2092
+ {visCanAnimate() && <CheckBox value={config.animate} fieldName='animate' label='Animate Visualization' updateField={updateField} />}
1783
2093
 
1784
2094
  {/*<CheckBox value={config.animateReplay} fieldName="animateReplay" label="Replay Animation When Filters Are Changed" updateField={updateField} />*/}
1785
2095
 
@@ -1808,74 +2118,108 @@ const EditorPanel = () => {
1808
2118
  <span className='edit-label'>Chart Color Palette</span>
1809
2119
  </label>
1810
2120
  {/* eslint-enable */}
1811
- {/* <InputCheckbox fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} /> */}
1812
- <InputToggle fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} />
1813
- <span>Sequential</span>
1814
- <ul className='color-palette'>
1815
- {filteredPallets.map(palette => {
1816
- const colorOne = {
1817
- backgroundColor: colorPalettes[palette][2]
1818
- }
1819
-
1820
- const colorTwo = {
1821
- backgroundColor: colorPalettes[palette][3]
1822
- }
1823
-
1824
- const colorThree = {
1825
- backgroundColor: colorPalettes[palette][5]
1826
- }
1827
-
1828
- return (
1829
- <button
1830
- title={palette}
1831
- key={palette}
1832
- onClick={e => {
1833
- e.preventDefault()
1834
- updateConfig({ ...config, palette })
1835
- }}
1836
- className={config.palette === palette ? 'selected' : ''}
1837
- >
1838
- <span style={colorOne}></span>
1839
- <span style={colorTwo}></span>
1840
- <span style={colorThree}></span>
1841
- </button>
1842
- )
1843
- })}
1844
- </ul>
1845
- <span>Non-Sequential</span>
1846
- <ul className='color-palette'>
1847
- {filteredQualitative.map(palette => {
1848
- const colorOne = {
1849
- backgroundColor: colorPalettes[palette][2]
1850
- }
1851
-
1852
- const colorTwo = {
1853
- backgroundColor: colorPalettes[palette][4]
1854
- }
1855
-
1856
- const colorThree = {
1857
- backgroundColor: colorPalettes[palette][6]
1858
- }
1859
-
1860
- return (
1861
- <button
1862
- title={palette}
1863
- key={palette}
1864
- onClick={e => {
1865
- e.preventDefault()
1866
- updateConfig({ ...config, palette })
1867
- }}
1868
- className={config.palette === palette ? 'selected' : ''}
1869
- >
1870
- <span style={colorOne}></span>
1871
- <span style={colorTwo}></span>
1872
- <span style={colorThree}></span>
1873
- </button>
1874
- )
1875
- })}
1876
- </ul>
2121
+ {config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Deviation Bar' && (
2122
+ <>
2123
+ <InputToggle fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={config.isPaletteReversed} />
2124
+ <span>Sequential</span>
2125
+ <ul className='color-palette'>
2126
+ {sequential.map(palette => {
2127
+ const colorOne = {
2128
+ backgroundColor: colorPalettes[palette][2]
2129
+ }
2130
+
2131
+ const colorTwo = {
2132
+ backgroundColor: colorPalettes[palette][3]
2133
+ }
2134
+
2135
+ const colorThree = {
2136
+ backgroundColor: colorPalettes[palette][5]
2137
+ }
2138
+
2139
+ return (
2140
+ <button
2141
+ title={palette}
2142
+ key={palette}
2143
+ onClick={e => {
2144
+ e.preventDefault()
2145
+ updateConfig({ ...config, palette })
2146
+ }}
2147
+ className={config.palette === palette ? 'selected' : ''}
2148
+ >
2149
+ <span style={colorOne}></span>
2150
+ <span style={colorTwo}></span>
2151
+ <span style={colorThree}></span>
2152
+ </button>
2153
+ )
2154
+ })}
2155
+ </ul>
2156
+ <span>Non-Sequential</span>
2157
+ <ul className='color-palette'>
2158
+ {nonSequential.map(palette => {
2159
+ const colorOne = {
2160
+ backgroundColor: colorPalettes[palette][2]
2161
+ }
2162
+
2163
+ const colorTwo = {
2164
+ backgroundColor: colorPalettes[palette][4]
2165
+ }
2166
+
2167
+ const colorThree = {
2168
+ backgroundColor: colorPalettes[palette][6]
2169
+ }
2170
+
2171
+ return (
2172
+ <button
2173
+ title={palette}
2174
+ key={palette}
2175
+ onClick={e => {
2176
+ e.preventDefault()
2177
+ updateConfig({ ...config, palette })
2178
+ }}
2179
+ className={config.palette === palette ? 'selected' : ''}
2180
+ >
2181
+ <span style={colorOne}></span>
2182
+ <span style={colorTwo}></span>
2183
+ <span style={colorThree}></span>
2184
+ </button>
2185
+ )
2186
+ })}
2187
+ </ul>
2188
+ </>
2189
+ )}
2190
+ {(config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar') && (
2191
+ <>
2192
+ <InputToggle section='twoColor' fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={config.twoColor.isPaletteReversed} />
2193
+ <ul className='color-palette'>
2194
+ {twoColorPalettes.map(palette => {
2195
+ const colorOne = {
2196
+ backgroundColor: twoColorPalette[palette][0]
2197
+ }
2198
+
2199
+ const colorTwo = {
2200
+ backgroundColor: twoColorPalette[palette][1]
2201
+ }
2202
+
2203
+ return (
2204
+ <button
2205
+ title={palette}
2206
+ key={palette}
2207
+ onClick={e => {
2208
+ e.preventDefault()
2209
+ updateConfig({ ...config, twoColor: { ...config.twoColor, palette } })
2210
+ }}
2211
+ className={config.twoColor.palette === palette ? 'selected' : ''}
2212
+ >
2213
+ <span className='two-color' style={colorOne}></span>
2214
+ <span className='two-color' style={colorTwo}></span>
2215
+ </button>
2216
+ )
2217
+ })}
2218
+ </ul>
2219
+ </>
2220
+ )}
1877
2221
 
1878
- {config.visualizationType !== 'Pie' && (
2222
+ {visHasDataCutoff() && (
1879
2223
  <>
1880
2224
  <TextField
1881
2225
  value={config.dataCutoff}
@@ -1924,16 +2268,36 @@ const EditorPanel = () => {
1924
2268
  <AccordionItemButton>Data Table</AccordionItemButton>
1925
2269
  </AccordionItemHeading>
1926
2270
  <AccordionItemPanel>
2271
+ <TextField
2272
+ value={config.table.label}
2273
+ updateField={updateField}
2274
+ section='table'
2275
+ fieldName='label'
2276
+ id='tableLabel'
2277
+ label='Data Table Title'
2278
+ placeholder='Data Table'
2279
+ tooltip={
2280
+ <Tooltip style={{ textTransform: 'none' }}>
2281
+ <Tooltip.Target>
2282
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2283
+ </Tooltip.Target>
2284
+ <Tooltip.Content>
2285
+ <p>Label is required for Data Table for 508 Compliance</p>
2286
+ </Tooltip.Content>
2287
+ </Tooltip>
2288
+ }
2289
+ />
1927
2290
  <CheckBox
1928
2291
  value={config.table.show}
1929
2292
  section='table'
1930
2293
  fieldName='show'
1931
- label='Show Table'
2294
+ label='Show Data Table'
1932
2295
  updateField={updateField}
2296
+ className='column-heading'
1933
2297
  tooltip={
1934
2298
  <Tooltip style={{ textTransform: 'none' }}>
1935
2299
  <Tooltip.Target>
1936
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2300
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1937
2301
  </Tooltip.Target>
1938
2302
  <Tooltip.Content>
1939
2303
  <p>Hiding the data table may affect accessibility. An alternate form of accessing visualization data is a 508 requirement.</p>
@@ -1963,11 +2327,11 @@ const EditorPanel = () => {
1963
2327
  <CheckBox value={config.table.limitHeight} section='table' fieldName='limitHeight' label='Limit Table Height' updateField={updateField} />
1964
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} />}
1965
2329
  <CheckBox value={config.table.expanded} section='table' fieldName='expanded' label='Expanded by Default' updateField={updateField} />
1966
- <CheckBox value={config.table.download} section='table' fieldName='download' label='Display Download Button' updateField={updateField} />
1967
- <CheckBox value={config.table.showDownloadUrl} section='table' fieldName='showDownloadUrl' label='Display Link to Dataset' updateField={updateField} />
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} />
1968
2333
  {/* <CheckBox value={config.table.showDownloadImgButton} section='table' fieldName='showDownloadImgButton' label='Display Image Button' updateField={updateField} /> */}
1969
2334
  {/* <CheckBox value={config.table.showDownloadPdfButton} section='table' fieldName='showDownloadPdfButton' label='Display PDF Button' updateField={updateField} /> */}
1970
- <TextField value={config.table.label} section='table' fieldName='label' label='Label' updateField={updateField} />
1971
2335
  {config.visualizationType !== 'Pie' && <TextField value={config.table.indexLabel} section='table' fieldName='indexLabel' label='Index Column Header' updateField={updateField} />}
1972
2336
  </AccordionItemPanel>
1973
2337
  </AccordionItem>
@@ -1976,7 +2340,7 @@ const EditorPanel = () => {
1976
2340
  {config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig} state={config} convertStateToConfig={convertStateToConfig} />}
1977
2341
  </section>
1978
2342
  </section>
1979
- </ErrorBoundary >
2343
+ </ErrorBoundary>
1980
2344
  )
1981
2345
  }
1982
2346