@cdc/chart 4.23.3 → 4.23.4

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