@cdc/chart 4.24.2 → 4.24.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 (60) hide show
  1. package/dist/cdcchart.js +47933 -36918
  2. package/examples/chart-regression-1.json +378 -0
  3. package/examples/chart-regression-2.json +2360 -0
  4. package/examples/feature/filters/url-filter.json +1076 -0
  5. package/examples/feature/line/line-chart.json +362 -37
  6. package/examples/feature/regions/index.json +50 -4
  7. package/examples/feature/sankey/sankey-example-data.json +1364 -0
  8. package/examples/feature/sankey/sankey_chart_data.csv +20 -0
  9. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +306 -19
  10. package/examples/region-issue.json +2065 -0
  11. package/examples/sparkline.json +868 -0
  12. package/examples/test.json +5409 -0
  13. package/index.html +130 -123
  14. package/package.json +4 -2
  15. package/src/CdcChart.tsx +178 -94
  16. package/src/_stories/ChartEditor.stories.tsx +14 -3
  17. package/src/_stories/_mock/url_filter.json +1076 -0
  18. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +2 -1
  19. package/src/components/AreaChart/components/AreaChart.jsx +2 -1
  20. package/src/components/BarChart/components/BarChart.Horizontal.tsx +46 -63
  21. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +36 -56
  22. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +32 -39
  23. package/src/components/BarChart/components/BarChart.Vertical.tsx +44 -59
  24. package/src/components/BoxPlot/BoxPlot.jsx +2 -1
  25. package/src/components/DeviationBar.jsx +3 -3
  26. package/src/components/EditorPanel/EditorPanel.tsx +1684 -1564
  27. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +1 -1
  28. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +107 -0
  29. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +48 -4
  30. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +41 -0
  31. package/src/components/EditorPanel/components/Panels/index.tsx +9 -7
  32. package/src/components/EditorPanel/components/panels.scss +11 -0
  33. package/src/components/EditorPanel/editor-panel.scss +0 -724
  34. package/src/components/EditorPanel/useEditorPermissions.js +40 -14
  35. package/src/components/Legend/Legend.Component.tsx +43 -63
  36. package/src/components/Legend/Legend.tsx +8 -4
  37. package/src/components/LineChart/LineChartProps.ts +1 -0
  38. package/src/components/LineChart/helpers.ts +2 -2
  39. package/src/components/LineChart/index.tsx +7 -7
  40. package/src/components/LinearChart.jsx +11 -31
  41. package/src/components/PairedBarChart.jsx +6 -10
  42. package/src/components/PieChart/PieChart.tsx +3 -3
  43. package/src/components/Regions/components/Regions.tsx +120 -78
  44. package/src/components/Sankey/index.tsx +434 -0
  45. package/src/components/Sankey/sankey.scss +153 -0
  46. package/src/components/Sankey/types/index.ts +16 -0
  47. package/src/components/ScatterPlot/ScatterPlot.jsx +1 -0
  48. package/src/components/Sparkline/{SparkLine.jsx → components/SparkLine.tsx} +14 -30
  49. package/src/components/Sparkline/index.scss +3 -0
  50. package/src/components/Sparkline/index.tsx +1 -1
  51. package/src/components/ZoomBrush.tsx +2 -1
  52. package/src/data/initial-state.js +46 -2
  53. package/src/helpers/computeMarginBottom.ts +2 -1
  54. package/src/helpers/tests/computeMarginBottom.test.ts +2 -1
  55. package/src/hooks/useBarChart.js +5 -2
  56. package/src/hooks/useScales.ts +47 -18
  57. package/src/hooks/useTooltip.tsx +9 -8
  58. package/src/scss/main.scss +33 -29
  59. package/src/types/ChartConfig.ts +32 -14
  60. package/src/types/ChartContext.ts +7 -0
@@ -1,7 +1,8 @@
1
1
  import { useState, useEffect, useCallback, memo, useContext } from 'react'
2
2
  import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'
3
-
3
+ import { isDateScale } from '@cdc/core/helpers/cove/date'
4
4
  import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
5
+ import Layout from '@cdc/core/components/Layout'
5
6
 
6
7
  // @cdc/core
7
8
  import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
@@ -182,7 +183,7 @@ const PreliminaryData = memo(({ config, updateConfig, data }) => {
182
183
  Remove
183
184
  </button>
184
185
  <Select value={type} initial='Select' fieldName='type' label='Type' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getTypeOptions()} />
185
- <Select value={seriesKey} initial='Select' fieldName='seriesKey' label='ASSOCIATE TO SERIES' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={config.runtime?.seriesKeys} />
186
+ <Select value={seriesKey} initial='Select' fieldName='seriesKey' label='ASSOCIATE TO SERIES' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={config.runtime.lineSeriesKeys ?? config.runtime?.seriesKeys} />
186
187
  <Select value={column} initial='Select' fieldName='column' label='COLUMN WITH CONFIGURATION VALUE' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getColumnOptions()} />
187
188
  <TextField value={value} fieldName='value' label='VALUE TO TRIGGER' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} />
188
189
  <Select value={style} initial='Select' fieldName='style' label='Style' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getStyleOptions()} />
@@ -193,14 +194,34 @@ const PreliminaryData = memo(({ config, updateConfig, data }) => {
193
194
  })}
194
195
 
195
196
  <button type='button' onClick={addColumn} className='btn full-width'>
196
- {config.visualizationType === 'Line' ? 'Add Special Line' : config.visualizationType === 'Bar' ? ' Add Special Bar' : 'Add Special Line/Bar'}
197
+ {config.visualizationType === 'Line' || config.visualizationType === 'Combo' ? 'Add Special Line' : config.visualizationType === 'Bar' ? ' Add Special Bar' : 'Add Special Line/Bar'}
197
198
  </button>
198
199
  </>
199
200
  )
200
201
  })
201
202
 
202
203
  const EditorPanel = () => {
203
- const { config, updateConfig, transformedData: data, loading, colorPalettes, twoColorPalette, unfilteredData, excludedData, isDashboard, setParentConfig, missingRequiredSections, isDebug, setFilteredData, lineOptions, rawData } = useContext<ChartContext>(ConfigContext)
204
+ const {
205
+ config,
206
+ updateConfig,
207
+ tableData,
208
+ transformedData: data,
209
+ loading,
210
+ colorScale,
211
+ colorPalettes,
212
+ twoColorPalette,
213
+ unfilteredData,
214
+ excludedData,
215
+ isDashboard,
216
+ setParentConfig,
217
+ missingRequiredSections,
218
+ isDebug,
219
+ setFilteredData,
220
+ lineOptions,
221
+ rawData,
222
+ highlight,
223
+ highlightReset
224
+ } = useContext<ChartContext>(ConfigContext)
204
225
 
205
226
  const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, unfilteredData)
206
227
 
@@ -220,8 +241,10 @@ const EditorPanel = () => {
220
241
  visHasAnchors,
221
242
  visHasBarBorders,
222
243
  visHasDataCutoff,
244
+ visHasSelectableLegendValues,
223
245
  visCanAnimate,
224
246
  visHasLegend,
247
+ visHasLegendAxisAlign,
225
248
  visHasBrushChart,
226
249
  visSupportsDateCategoryAxis,
227
250
  visSupportsValueAxisMin,
@@ -234,6 +257,7 @@ const EditorPanel = () => {
234
257
  visSupportsDateCategoryAxisPadding,
235
258
  visSupportsRegions,
236
259
  visSupportsFilters,
260
+ visSupportsPreliminaryData,
237
261
  visSupportsValueAxisGridLines,
238
262
  visSupportsValueAxisLine,
239
263
  visSupportsValueAxisTicks,
@@ -329,7 +353,7 @@ const EditorPanel = () => {
329
353
  if (updatedConfig.visualizationType === 'Combo') {
330
354
  updatedConfig.orientation = 'vertical'
331
355
  }
332
- if (updatedConfig.xAxis.sortDates && !updatedConfig.xAxis.padding) {
356
+ if (isDateScale(updatedConfig.xAxis) && !updatedConfig.xAxis.padding) {
333
357
  updatedConfig.xAxis.padding = 6
334
358
  }
335
359
  }
@@ -594,40 +618,10 @@ const EditorPanel = () => {
594
618
 
595
619
  const onBackClick = () => {
596
620
  setDisplayPanel(!displayPanel)
597
- }
598
-
599
- const Error = () => {
600
- return (
601
- <section className='waiting'>
602
- <section className='waiting-container'>
603
- <h3>Error With Configuration</h3>
604
- <p>{config.runtime.editorErrorMessage}</p>
605
- </section>
606
- </section>
607
- )
608
- }
609
-
610
- const Confirm = () => {
611
- const confirmDone = e => {
612
- e.preventDefault()
613
-
614
- let newConfig = { ...config }
615
- delete newConfig.newViz
616
-
617
- updateConfig(newConfig)
618
- }
619
-
620
- return (
621
- <section className='waiting'>
622
- <section className='waiting-container'>
623
- <h3>Finish Configuring</h3>
624
- <p>Set all required options to the left and confirm below to display a preview of the chart.</p>
625
- <button className='btn' style={{ margin: '1em auto' }} disabled={missingRequiredSections()} onClick={confirmDone}>
626
- I'm Done
627
- </button>
628
- </section>
629
- </section>
630
- )
621
+ updateConfig({
622
+ ...config,
623
+ showEditorPanel: !displayPanel
624
+ })
631
625
  }
632
626
 
633
627
  const convertStateToConfig = () => {
@@ -1003,6 +997,28 @@ const EditorPanel = () => {
1003
997
  columns: updatedColumns
1004
998
  })
1005
999
  }
1000
+
1001
+ const colorCodeByCategory = config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1
1002
+ const getLegendColumns = () => {
1003
+ const colorCodeData = data.map(d => d[config.legend.colorCode])
1004
+ return colorCodeByCategory ? colorCodeData : getColumns(false).filter(d => d !== config.xAxis.dataKey)
1005
+ }
1006
+
1007
+ const updateSeriesIsolateValues = updatedValues => {
1008
+ updateConfig({ ...config, legend: { ...config.legend, seriesHighlight: updatedValues } })
1009
+ }
1010
+
1011
+ const updateBehavior = (section, fieldName, newValue) => {
1012
+ const sectionValue = { ...config[section], [fieldName]: newValue }
1013
+ const updatedConfig = { ...config, [section]: sectionValue }
1014
+
1015
+ if (newValue === 'highlight' && config.legend.seriesHighlight?.length) {
1016
+ updatedConfig.legend.seriesHighlight.length = 0
1017
+ }
1018
+
1019
+ updateConfig(updatedConfig)
1020
+ }
1021
+
1006
1022
  const editorContextValues = {
1007
1023
  addNewExclusion,
1008
1024
  data,
@@ -1031,128 +1047,144 @@ const EditorPanel = () => {
1031
1047
  return (
1032
1048
  <EditorPanelContext.Provider value={editorContextValues}>
1033
1049
  <ErrorBoundary component='EditorPanel'>
1034
- {config.newViz && <Confirm />}
1035
- {undefined === config.newViz && config.runtime && config.runtime?.editorErrorMessage && <Error />}
1036
- <button className={displayPanel ? `editor-toggle` : `editor-toggle collapsed`} title={displayPanel ? `Collapse Editor` : `Expand Editor`} onClick={onBackClick}></button>
1037
- <section className={`${displayPanel ? 'editor-panel cove' : 'hidden editor-panel cove'}${isDashboard ? ' dashboard' : ''}`}>
1038
- <div aria-level={2} role='heading' className='heading-2'>
1039
- Configure Chart
1040
- </div>
1041
- <section className='form-container'>
1042
- <Accordion allowZeroExpanded={true}>
1043
- <Panels.General name='General' />
1044
- <Panels.ForestPlot name='Forest Plot Settings' />
1045
- {config.visualizationType !== 'Pie' && config.visualizationType !== 'Forest Plot' && (
1046
- <AccordionItem>
1047
- <AccordionItemHeading>
1048
- <AccordionItemButton>Data Series {(!config.series || config.series.length === 0 || (config.visualizationType === 'Paired Bar' && config.series.length < 2)) && <WarningImage width='25' className='warning-icon' />}</AccordionItemButton>
1049
- </AccordionItemHeading>
1050
- <AccordionItemPanel>
1051
- {(!config.series || config.series.length === 0) && config.visualizationType !== 'Paired Bar' && <p className='warning'>At least one series is required</p>}
1052
- {(!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>}
1050
+ <Layout.Sidebar displayPanel={displayPanel} isDashboard={isDashboard} title={'Configure Chart'} onBackClick={onBackClick}>
1051
+ <Accordion allowZeroExpanded={true}>
1052
+ <Panels.General name='General' />
1053
+ <Panels.ForestPlot name='Forest Plot Settings' />
1054
+ <Panels.Sankey name='Sankey' />
1055
+ {config.visualizationType !== 'Pie' && config.visualizationType !== 'Forest Plot' && config.visualizationType !== 'Sankey' && (
1056
+ <AccordionItem>
1057
+ <AccordionItemHeading>
1058
+ <AccordionItemButton>Data Series {(!config.series || config.series.length === 0 || (config.visualizationType === 'Paired Bar' && config.series.length < 2)) && <WarningImage width='25' className='warning-icon' />}</AccordionItemButton>
1059
+ </AccordionItemHeading>
1060
+ <AccordionItemPanel>
1061
+ {(!config.series || config.series.length === 0) && config.visualizationType !== 'Paired Bar' && <p className='warning'>At least one series is required</p>}
1062
+ {(!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>}
1063
+ <>
1064
+ <Select
1065
+ fieldName='visualizationType'
1066
+ label='Add Data Series'
1067
+ initial='Select'
1068
+ onChange={e => {
1069
+ if (e.target.value !== '' && e.target.value !== 'Select') {
1070
+ addNewSeries(e.target.value)
1071
+ }
1072
+ e.target.value = ''
1073
+ }}
1074
+ options={getColumns()}
1075
+ />
1076
+ {config.series && config.series.length !== 0 && (
1077
+ <Panels.Series.Wrapper getColumns={getColumns}>
1078
+ <fieldset>
1079
+ <legend className='edit-label float-left'>Displaying</legend>
1080
+ <Tooltip style={{ textTransform: 'none' }}>
1081
+ <Tooltip.Target>
1082
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1083
+ </Tooltip.Target>
1084
+ <Tooltip.Content>
1085
+ <p>A data series is a set of related data points plotted in a chart and typically represented in the chart legend.</p>
1086
+ </Tooltip.Content>
1087
+ </Tooltip>
1088
+ </fieldset>
1089
+
1090
+ <DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
1091
+ <Droppable droppableId='filter_order'>
1092
+ {/* prettier-ignore */}
1093
+ {provided => {
1094
+ return (
1095
+ <ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
1096
+ <Panels.Series.List series={config.series} getItemStyle={getItemStyle} sortableItemStyles={sortableItemStyles} chartsWithOptions={chartsWithOptions} />
1097
+ {provided.placeholder}
1098
+ </ul>
1099
+ )
1100
+ }}
1101
+ </Droppable>
1102
+ </DragDropContext>
1103
+ </Panels.Series.Wrapper>
1104
+ )}
1105
+ </>
1106
+ {config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
1053
1107
  <>
1054
- <Select
1055
- fieldName='visualizationType'
1056
- label='Add Data Series'
1057
- initial='Select'
1058
- onChange={e => {
1059
- if (e.target.value !== '' && e.target.value !== 'Select') {
1060
- addNewSeries(e.target.value)
1061
- }
1062
- e.target.value = ''
1063
- }}
1064
- options={getColumns()}
1065
- />
1066
- {config.series && config.series.length !== 0 && (
1067
- <Panels.Series.Wrapper getColumns={getColumns}>
1068
- <fieldset>
1069
- <legend className='edit-label float-left'>Displaying</legend>
1070
- <Tooltip style={{ textTransform: 'none' }}>
1071
- <Tooltip.Target>
1072
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1073
- </Tooltip.Target>
1074
- <Tooltip.Content>
1075
- <p>A data series is a set of related data points plotted in a chart and typically represented in the chart legend.</p>
1076
- </Tooltip.Content>
1077
- </Tooltip>
1078
- </fieldset>
1079
-
1080
- <DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
1081
- <Droppable droppableId='filter_order'>
1082
- {/* prettier-ignore */}
1083
- {provided => {
1084
- return (
1085
- <ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
1086
- <Panels.Series.List series={config.series} getItemStyle={getItemStyle} sortableItemStyles={sortableItemStyles} chartsWithOptions={chartsWithOptions} />
1087
- {provided.placeholder}
1088
- </ul>
1089
- )
1090
- }}
1091
- </Droppable>
1092
- </DragDropContext>
1093
- </Panels.Series.Wrapper>
1094
- )}
1108
+ <span className='divider-heading'>Confidence Keys</span>
1109
+ <Select value={config.confidenceKeys.upper || ''} section='confidenceKeys' fieldName='upper' label='Upper' updateField={updateField} initial='Select' options={getColumns()} />
1110
+ <Select value={config.confidenceKeys.lower || ''} section='confidenceKeys' fieldName='lower' label='Lower' updateField={updateField} initial='Select' options={getColumns()} />
1095
1111
  </>
1096
- {config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
1097
- <>
1098
- <span className='divider-heading'>Confidence Keys</span>
1099
- <Select value={config.confidenceKeys.upper || ''} section='confidenceKeys' fieldName='upper' label='Upper' updateField={updateField} initial='Select' options={getColumns()} />
1100
- <Select value={config.confidenceKeys.lower || ''} section='confidenceKeys' fieldName='lower' label='Lower' updateField={updateField} initial='Select' options={getColumns()} />
1101
- </>
1102
- )}
1103
- {visSupportsRankByValue() && config.series && config.series.length === 1 && <Select fieldName='visualizationType' label='Rank by Value' initial='Select' onChange={e => sortSeries(e.target.value)} options={['asc', 'desc']} />}
1104
- {/* {visHasDataSuppression() && <DataSuppression config={config} updateConfig={updateConfig} data={data} />} */}
1105
- {config.visualizationType === 'Line' && <PreliminaryData config={config} updateConfig={updateConfig} data={data} />}
1106
- </AccordionItemPanel>
1107
- </AccordionItem>
1108
- )}
1109
- <Panels.BoxPlot name='Measures' />
1110
- {/* Left Value Axis */}
1111
- {visSupportsLeftValueAxis() && (
1112
- <AccordionItem>
1113
- <AccordionItemHeading>
1114
- <AccordionItemButton>
1115
- {config.visualizationType === 'Pie' ? 'Data Format' : config.orientation === 'vertical' ? 'Left Value Axis' : 'Value Axis'}
1116
- {config.visualizationType === 'Pie' && !config.yAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
1117
- </AccordionItemButton>
1118
- </AccordionItemHeading>
1119
- <AccordionItemPanel>
1120
- {config.visualizationType === 'Pie' && (
1121
- <Select
1122
- value={config.yAxis.dataKey || ''}
1112
+ )}
1113
+ {visSupportsRankByValue() && config.series && config.series.length === 1 && <Select fieldName='visualizationType' label='Rank by Value' initial='Select' onChange={e => sortSeries(e.target.value)} options={['asc', 'desc']} />}
1114
+ {/* {visHasDataSuppression() && <DataSuppression config={config} updateConfig={updateConfig} data={data} />} */}
1115
+ {visSupportsPreliminaryData() && <PreliminaryData config={config} updateConfig={updateConfig} data={data} />}
1116
+ </AccordionItemPanel>
1117
+ </AccordionItem>
1118
+ )}
1119
+ <Panels.BoxPlot name='Measures' />
1120
+ {/* Left Value Axis */}
1121
+ {visSupportsLeftValueAxis() && (
1122
+ <AccordionItem>
1123
+ <AccordionItemHeading>
1124
+ <AccordionItemButton>
1125
+ {config.visualizationType === 'Pie' ? 'Data Format' : config.orientation === 'vertical' ? 'Left Value Axis' : 'Value Axis'}
1126
+ {config.visualizationType === 'Pie' && !config.yAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
1127
+ </AccordionItemButton>
1128
+ </AccordionItemHeading>
1129
+ <AccordionItemPanel>
1130
+ {config.visualizationType === 'Pie' && (
1131
+ <Select
1132
+ value={config.yAxis.dataKey || ''}
1133
+ section='yAxis'
1134
+ fieldName='dataKey'
1135
+ label='Data Column'
1136
+ initial='Select'
1137
+ required={true}
1138
+ updateField={updateField}
1139
+ options={getColumns(false)}
1140
+ tooltip={
1141
+ <Tooltip style={{ textTransform: 'none' }}>
1142
+ <Tooltip.Target>
1143
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1144
+ </Tooltip.Target>
1145
+ <Tooltip.Content>
1146
+ <p>Select the source data to be visually represented.</p>
1147
+ </Tooltip.Content>
1148
+ </Tooltip>
1149
+ }
1150
+ />
1151
+ )}
1152
+ {config.visualizationType !== 'Pie' && (
1153
+ <>
1154
+ <TextField value={config.yAxis.label} section='yAxis' fieldName='label' label='Label ' updateField={updateField} />
1155
+ {config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && !['Box Plot', 'Deviation Bar', 'Forest Plot'].includes(config.visualizationType) && (
1156
+ <CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />
1157
+ )}
1158
+ <TextField value={config.yAxis.numTicks} placeholder='Auto' type='number' section='yAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1159
+ <TextField
1160
+ value={config.yAxis.size}
1161
+ type='number'
1123
1162
  section='yAxis'
1124
- fieldName='dataKey'
1125
- label='Data Column'
1126
- initial='Select'
1127
- required={true}
1163
+ fieldName='size'
1164
+ label={config.orientation === 'horizontal' ? 'Size (Height)' : 'Size (Width)'}
1165
+ className='number-narrow'
1128
1166
  updateField={updateField}
1129
- options={getColumns(false)}
1130
1167
  tooltip={
1131
1168
  <Tooltip style={{ textTransform: 'none' }}>
1132
1169
  <Tooltip.Target>
1133
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1170
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1134
1171
  </Tooltip.Target>
1135
1172
  <Tooltip.Content>
1136
- <p>Select the source data to be visually represented.</p>
1173
+ <p>{`Increase the size if elements in the ${config.orientation} axis are being crowded or hidden behind other elements. Decrease if less space is required for the value axis.`}</p>
1137
1174
  </Tooltip.Content>
1138
1175
  </Tooltip>
1139
1176
  }
1140
1177
  />
1141
- )}
1142
- {config.visualizationType !== 'Pie' && (
1143
- <>
1144
- <TextField value={config.yAxis.label} section='yAxis' fieldName='label' label='Label ' updateField={updateField} />
1145
- {config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && !['Box Plot', 'Deviation Bar', 'Forest Plot'].includes(config.visualizationType) && (
1146
- <CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />
1147
- )}
1148
- <TextField value={config.yAxis.numTicks} placeholder='Auto' type='number' section='yAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1149
- {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} />}
1178
+ {config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
1179
+ {(config.orientation === 'vertical' || !config.isResponsiveTicks) && <TextField value={config.yAxis.tickRotation || 0} type='number' min={0} section='yAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
1180
+ {config.isResponsiveTicks && config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && (
1150
1181
  <TextField
1151
- value={config.yAxis.size}
1182
+ value={config.xAxis.maxTickRotation}
1152
1183
  type='number'
1153
- section='yAxis'
1154
- fieldName='size'
1155
- label={config.orientation === 'horizontal' ? 'Size (Height)' : 'Size (Width)'}
1184
+ min={0}
1185
+ section='xAxis'
1186
+ fieldName='maxTickRotation'
1187
+ label='Max Tick Rotation'
1156
1188
  className='number-narrow'
1157
1189
  updateField={updateField}
1158
1190
  tooltip={
@@ -1161,527 +1193,507 @@ const EditorPanel = () => {
1161
1193
  <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1162
1194
  </Tooltip.Target>
1163
1195
  <Tooltip.Content>
1164
- <p>{`Increase the size if elements in the ${config.orientation} axis are being crowded or hidden behind other elements. Decrease if less space is required for the value axis.`}</p>
1196
+ <p>Degrees ticks will be rotated if values overlap, especially in smaller viewports.</p>
1165
1197
  </Tooltip.Content>
1166
1198
  </Tooltip>
1167
1199
  }
1168
1200
  />
1169
- {config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
1170
- {(config.orientation === 'vertical' || !config.isResponsiveTicks) && <TextField value={config.yAxis.tickRotation} type='number' min={0} section='yAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
1171
- {config.isResponsiveTicks && config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && (
1172
- <TextField
1173
- value={config.xAxis.maxTickRotation}
1174
- type='number'
1175
- min={0}
1176
- section='xAxis'
1177
- fieldName='maxTickRotation'
1178
- label='Max Tick Rotation'
1179
- className='number-narrow'
1180
- updateField={updateField}
1181
- tooltip={
1182
- <Tooltip style={{ textTransform: 'none' }}>
1183
- <Tooltip.Target>
1184
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1185
- </Tooltip.Target>
1186
- <Tooltip.Content>
1187
- <p>Degrees ticks will be rotated if values overlap, especially in smaller viewports.</p>
1188
- </Tooltip.Content>
1189
- </Tooltip>
1190
- }
1191
- />
1192
- )}
1193
-
1194
- {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1195
- {/* <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1196
- {config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
1197
- {visSupportsValueAxisGridLines() && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Show Gridlines' updateField={updateField} />}
1198
- <CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
1199
- {config.yAxis.enablePadding && <TextField type='number' section='yAxis' fieldName='scalePadding' label='Padding Percentage' className='number-narrow' updateField={updateField} value={config.yAxis.scalePadding} />}
1200
- {config.visualizationSubType === 'regular' && config.visualizationType !== 'Forest Plot' && <CheckBox value={config.useLogScale} fieldName='useLogScale' label='use logarithmic scale' updateField={updateField} />}
1201
- </>
1202
- )}
1203
- <span className='divider-heading'>Number Formatting</span>
1204
- <CheckBox value={config.dataFormat.commas} section='dataFormat' fieldName='commas' label='Add commas' updateField={updateField} />
1205
- <CheckBox
1206
- value={config.dataFormat.abbreviated}
1201
+ )}
1202
+
1203
+ {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1204
+ {/* <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1205
+ {config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
1206
+ {visSupportsValueAxisGridLines() && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Show Gridlines' updateField={updateField} />}
1207
+ <CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
1208
+ {config.yAxis.enablePadding && <TextField type='number' section='yAxis' fieldName='scalePadding' label='Padding Percentage' className='number-narrow' updateField={updateField} value={config.yAxis.scalePadding} />}
1209
+ {config.visualizationSubType === 'regular' && config.visualizationType !== 'Forest Plot' && <CheckBox value={config.useLogScale} fieldName='useLogScale' label='use logarithmic scale' updateField={updateField} />}
1210
+ </>
1211
+ )}
1212
+ <span className='divider-heading'>Number Formatting</span>
1213
+ <CheckBox value={config.dataFormat.commas} section='dataFormat' fieldName='commas' label='Add commas' updateField={updateField} />
1214
+ <CheckBox
1215
+ value={config.dataFormat.abbreviated}
1216
+ section='dataFormat'
1217
+ fieldName='abbreviated'
1218
+ label='Abbreviate Axis Values'
1219
+ updateField={updateField}
1220
+ tooltip={
1221
+ <Tooltip style={{ textTransform: 'none' }}>
1222
+ <Tooltip.Target>
1223
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1224
+ </Tooltip.Target>
1225
+ <Tooltip.Content>
1226
+ <p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
1227
+ </Tooltip.Content>
1228
+ </Tooltip>
1229
+ }
1230
+ />
1231
+ <TextField value={config.dataFormat.roundTo ? config.dataFormat.roundTo : 0} type='number' section='dataFormat' fieldName='roundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1232
+ <div className='two-col-inputs'>
1233
+ <TextField
1234
+ value={config.dataFormat.prefix}
1207
1235
  section='dataFormat'
1208
- fieldName='abbreviated'
1209
- label='Abbreviate Axis Values'
1236
+ fieldName='prefix'
1237
+ label='Prefix'
1210
1238
  updateField={updateField}
1211
1239
  tooltip={
1212
1240
  <Tooltip style={{ textTransform: 'none' }}>
1213
1241
  <Tooltip.Target>
1214
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1242
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1215
1243
  </Tooltip.Target>
1216
1244
  <Tooltip.Content>
1217
- <p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
1245
+ {config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
1246
+ {config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
1218
1247
  </Tooltip.Content>
1219
1248
  </Tooltip>
1220
1249
  }
1221
1250
  />
1222
- <TextField value={config.dataFormat.roundTo ? config.dataFormat.roundTo : 0} type='number' section='dataFormat' fieldName='roundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1223
- <div className='two-col-inputs'>
1224
- <TextField
1225
- value={config.dataFormat.prefix}
1226
- section='dataFormat'
1227
- fieldName='prefix'
1228
- label='Prefix'
1229
- updateField={updateField}
1230
- tooltip={
1231
- <Tooltip style={{ textTransform: 'none' }}>
1232
- <Tooltip.Target>
1233
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1234
- </Tooltip.Target>
1235
- <Tooltip.Content>
1236
- {config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
1237
- {config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
1238
- </Tooltip.Content>
1239
- </Tooltip>
1240
- }
1241
- />
1242
- <TextField
1243
- value={config.dataFormat.suffix}
1244
- section='dataFormat'
1245
- fieldName='suffix'
1246
- label='Suffix'
1247
- updateField={updateField}
1248
- tooltip={
1249
- <Tooltip style={{ textTransform: 'none' }}>
1250
- <Tooltip.Target>
1251
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1252
- </Tooltip.Target>
1253
- <Tooltip.Content>
1254
- {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1255
- {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1256
- </Tooltip.Content>
1257
- </Tooltip>
1258
- }
1259
- />
1260
- </div>
1251
+ <TextField
1252
+ value={config.dataFormat.suffix}
1253
+ section='dataFormat'
1254
+ fieldName='suffix'
1255
+ label='Suffix'
1256
+ updateField={updateField}
1257
+ tooltip={
1258
+ <Tooltip style={{ textTransform: 'none' }}>
1259
+ <Tooltip.Target>
1260
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1261
+ </Tooltip.Target>
1262
+ <Tooltip.Content>
1263
+ {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1264
+ {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1265
+ </Tooltip.Content>
1266
+ </Tooltip>
1267
+ }
1268
+ />
1269
+ </div>
1261
1270
 
1262
- {config.orientation === 'horizontal' ? ( // horizontal - x is vertical y is horizontal
1271
+ {config.orientation === 'horizontal' ? ( // horizontal - x is vertical y is horizontal
1272
+ <>
1273
+ {visSupportsValueAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
1274
+ {visSupportsValueAxisLabels() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
1275
+ {visSupportsValueAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
1276
+ {visSupportsValueAxisMax() && <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />}
1277
+ <span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
1278
+ {visSupportsValueAxisMin() && <TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />}
1279
+ <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1280
+ {config.visualizationType === 'Deviation Bar' && (
1281
+ <>
1282
+ <TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
1283
+ <TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
1284
+ <CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Show Deviation point label' updateField={updateField} />
1285
+ </>
1286
+ )}
1287
+ </>
1288
+ ) : (
1289
+ config.visualizationType !== 'Pie' && (
1263
1290
  <>
1264
- {visSupportsValueAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
1265
- {visSupportsValueAxisLabels() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
1266
- {visSupportsValueAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
1267
- {visSupportsValueAxisMax() && <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />}
1291
+ <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
1292
+ <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
1293
+ <CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
1294
+
1295
+ <TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='left axis max value' placeholder='Auto' updateField={updateField} />
1268
1296
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
1269
- {visSupportsValueAxisMin() && <TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />}
1297
+ <TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='left axis min value' placeholder='Auto' updateField={updateField} />
1270
1298
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1271
- {config.visualizationType === 'Deviation Bar' && (
1272
- <>
1273
- <TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
1274
- <TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
1275
- <CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Show Deviation point label' updateField={updateField} />
1276
- </>
1277
- )}
1278
1299
  </>
1279
- ) : (
1280
- config.visualizationType !== 'Pie' && (
1281
- <>
1282
- <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
1283
- <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
1284
- <CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
1285
-
1286
- <TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='left axis max value' placeholder='Auto' updateField={updateField} />
1287
- <span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
1288
- <TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='left axis min value' placeholder='Auto' updateField={updateField} />
1289
- <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1290
- </>
1291
- )
1292
- )}
1293
-
1294
- {/* start: anchors */}
1295
- {visHasAnchors() && config.orientation !== 'horizontal' && (
1296
- <div className='edit-block'>
1297
- <span className='edit-label column-heading'>Anchors</span>
1298
- <Accordion allowZeroExpanded>
1299
- {config.yAxis?.anchors?.map((anchor, index) => (
1300
- <AccordionItem className='series-item series-item--chart' key={`yaxis-anchors-2-${index}`}>
1301
- <AccordionItemHeading className='series-item__title'>
1302
- <>
1303
- <AccordionItemButton className={'accordion__button accordion__button'}>
1304
- Anchor {index + 1}
1305
- <button
1306
- className='series-list__remove'
1307
- onClick={e => {
1308
- e.preventDefault()
1309
- const copiedAnchorGroups = [...config.yAxis.anchors]
1310
- copiedAnchorGroups.splice(index, 1)
1311
- updateConfig({
1312
- ...config,
1313
- yAxis: {
1314
- ...config.yAxis,
1315
- anchors: copiedAnchorGroups
1316
- }
1317
- })
1318
- }}
1319
- >
1320
- Remove
1321
- </button>
1322
- </AccordionItemButton>
1323
- </>
1324
- </AccordionItemHeading>
1325
- <AccordionItemPanel>
1326
- <label>
1327
- <span>Anchor Value</span>
1328
- <Tooltip style={{ textTransform: 'none' }}>
1329
- <Tooltip.Target>
1330
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1331
- </Tooltip.Target>
1332
- <Tooltip.Content>
1333
- <p>Enter the value as its shown in the data column</p>
1334
- </Tooltip.Content>
1335
- </Tooltip>
1336
- <input
1337
- type='text'
1338
- value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
1339
- onChange={e => {
1340
- e.preventDefault()
1341
- const copiedAnchors = [...config.yAxis.anchors]
1342
- copiedAnchors[index].value = e.target.value
1343
- updateConfig({
1344
- ...config,
1345
- yAxis: {
1346
- ...config.yAxis,
1347
- anchors: copiedAnchors
1348
- }
1349
- })
1350
- }}
1351
- />
1352
- </label>
1353
-
1354
- <label>
1355
- <span>Anchor Color</span>
1356
- <input
1357
- type='text'
1358
- value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
1359
- onChange={e => {
1300
+ )
1301
+ )}
1302
+
1303
+ {/* start: anchors */}
1304
+ {visHasAnchors() && config.orientation !== 'horizontal' && (
1305
+ <div className='edit-block'>
1306
+ <span className='edit-label column-heading'>Anchors</span>
1307
+ <Accordion allowZeroExpanded>
1308
+ {config.yAxis?.anchors?.map((anchor, index) => (
1309
+ <AccordionItem className='series-item series-item--chart' key={`yaxis-anchors-2-${index}`}>
1310
+ <AccordionItemHeading className='series-item__title'>
1311
+ <>
1312
+ <AccordionItemButton className={'accordion__button accordion__button'}>
1313
+ Anchor {index + 1}
1314
+ <button
1315
+ className='series-list__remove'
1316
+ onClick={e => {
1360
1317
  e.preventDefault()
1361
- const copiedAnchors = [...config.yAxis.anchors]
1362
- copiedAnchors[index].color = e.target.value
1318
+ const copiedAnchorGroups = [...config.yAxis.anchors]
1319
+ copiedAnchorGroups.splice(index, 1)
1363
1320
  updateConfig({
1364
1321
  ...config,
1365
1322
  yAxis: {
1366
1323
  ...config.yAxis,
1367
- anchors: copiedAnchors
1368
- }
1369
- })
1370
- }}
1371
- />
1372
- </label>
1373
-
1374
- <label>
1375
- Anchor Line Style
1376
- <select
1377
- value={config.yAxis.anchors[index].lineStyle || ''}
1378
- onChange={e => {
1379
- const copiedAnchors = [...config.yAxis.anchors]
1380
- copiedAnchors[index].lineStyle = e.target.value
1381
- updateConfig({
1382
- ...config,
1383
- yAxis: {
1384
- ...config.yAxis,
1385
- anchors: copiedAnchors
1324
+ anchors: copiedAnchorGroups
1386
1325
  }
1387
1326
  })
1388
1327
  }}
1389
1328
  >
1390
- <option>Select</option>
1391
- {lineOptions.map(line => (
1392
- <option key={line.key}>{line.value}</option>
1393
- ))}
1394
- </select>
1395
- </label>
1396
- </AccordionItemPanel>
1397
- </AccordionItem>
1398
- ))}
1399
- </Accordion>
1400
-
1401
- <button
1402
- className='btn full-width'
1403
- onClick={e => {
1404
- e.preventDefault()
1405
- const anchors = [...config.yAxis.anchors]
1406
- anchors.push({} as Anchor)
1407
- updateConfig({
1408
- ...config,
1409
- yAxis: {
1410
- ...config.yAxis,
1411
- anchors
1412
- }
1413
- })
1414
- }}
1415
- >
1416
- Add Anchor
1417
- </button>
1418
- </div>
1419
- )}
1329
+ Remove
1330
+ </button>
1331
+ </AccordionItemButton>
1332
+ </>
1333
+ </AccordionItemHeading>
1334
+ <AccordionItemPanel>
1335
+ <label>
1336
+ <span>Anchor Value</span>
1337
+ <Tooltip style={{ textTransform: 'none' }}>
1338
+ <Tooltip.Target>
1339
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1340
+ </Tooltip.Target>
1341
+ <Tooltip.Content>
1342
+ <p>Enter the value as its shown in the data column</p>
1343
+ </Tooltip.Content>
1344
+ </Tooltip>
1345
+ <input
1346
+ type='text'
1347
+ value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
1348
+ onChange={e => {
1349
+ e.preventDefault()
1350
+ const copiedAnchors = [...config.yAxis.anchors]
1351
+ copiedAnchors[index].value = e.target.value
1352
+ updateConfig({
1353
+ ...config,
1354
+ yAxis: {
1355
+ ...config.yAxis,
1356
+ anchors: copiedAnchors
1357
+ }
1358
+ })
1359
+ }}
1360
+ />
1361
+ </label>
1420
1362
 
1421
- {visHasAnchors() && config.orientation === 'horizontal' && (
1422
- <div className='edit-block'>
1423
- <span className='edit-label column-heading'>Anchors</span>
1424
- <Accordion allowZeroExpanded>
1425
- {config.xAxis?.anchors?.map((anchor, index) => (
1426
- <AccordionItem className='series-item series-item--chart' key={`xaxis-anchors-${index}`}>
1427
- <AccordionItemHeading className='series-item__title'>
1428
- <>
1429
- <AccordionItemButton className={'accordion__button accordion__button'}>
1430
- Anchor {index + 1}
1431
- <button
1432
- className='series-list__remove'
1433
- onClick={e => {
1434
- e.preventDefault()
1435
- const copiedAnchorGroups = [...config.xAxis.anchors]
1436
- copiedAnchorGroups.splice(index, 1)
1437
- updateConfig({
1438
- ...config,
1439
- xAxis: {
1440
- ...config.xAxis,
1441
- anchors: copiedAnchorGroups
1442
- }
1443
- })
1444
- }}
1445
- >
1446
- Remove
1447
- </button>
1448
- </AccordionItemButton>
1449
- </>
1450
- </AccordionItemHeading>
1451
- <AccordionItemPanel>
1452
- <label>
1453
- <span>Anchor Value</span>
1454
- <Tooltip style={{ textTransform: 'none' }}>
1455
- <Tooltip.Target>
1456
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1457
- </Tooltip.Target>
1458
- <Tooltip.Content>
1459
- <p>Enter the value as its shown in the data column</p>
1460
- </Tooltip.Content>
1461
- </Tooltip>
1462
- <input
1463
- type='text'
1464
- value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
1465
- onChange={e => {
1466
- e.preventDefault()
1467
- const copiedAnchors = [...config.xAxis.anchors]
1468
- copiedAnchors[index].value = e.target.value
1469
- updateConfig({
1470
- ...config,
1471
- xAxis: {
1472
- ...config.xAxis,
1473
- anchors: copiedAnchors
1474
- }
1475
- })
1476
- }}
1477
- />
1478
- </label>
1363
+ <label>
1364
+ <span>Anchor Color</span>
1365
+ <input
1366
+ type='text'
1367
+ value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
1368
+ onChange={e => {
1369
+ e.preventDefault()
1370
+ const copiedAnchors = [...config.yAxis.anchors]
1371
+ copiedAnchors[index].color = e.target.value
1372
+ updateConfig({
1373
+ ...config,
1374
+ yAxis: {
1375
+ ...config.yAxis,
1376
+ anchors: copiedAnchors
1377
+ }
1378
+ })
1379
+ }}
1380
+ />
1381
+ </label>
1479
1382
 
1480
- <label>
1481
- <span>Anchor Color</span>
1482
- <input
1483
- type='text'
1484
- value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
1485
- onChange={e => {
1383
+ <label>
1384
+ Anchor Line Style
1385
+ <select
1386
+ value={config.yAxis.anchors[index].lineStyle || ''}
1387
+ onChange={e => {
1388
+ const copiedAnchors = [...config.yAxis.anchors]
1389
+ copiedAnchors[index].lineStyle = e.target.value
1390
+ updateConfig({
1391
+ ...config,
1392
+ yAxis: {
1393
+ ...config.yAxis,
1394
+ anchors: copiedAnchors
1395
+ }
1396
+ })
1397
+ }}
1398
+ >
1399
+ <option>Select</option>
1400
+ {lineOptions.map(line => (
1401
+ <option key={line.key}>{line.value}</option>
1402
+ ))}
1403
+ </select>
1404
+ </label>
1405
+ </AccordionItemPanel>
1406
+ </AccordionItem>
1407
+ ))}
1408
+ </Accordion>
1409
+
1410
+ <button
1411
+ className='btn full-width'
1412
+ onClick={e => {
1413
+ e.preventDefault()
1414
+ const anchors = [...config.yAxis.anchors]
1415
+ anchors.push({} as Anchor)
1416
+ updateConfig({
1417
+ ...config,
1418
+ yAxis: {
1419
+ ...config.yAxis,
1420
+ anchors
1421
+ }
1422
+ })
1423
+ }}
1424
+ >
1425
+ Add Anchor
1426
+ </button>
1427
+ </div>
1428
+ )}
1429
+
1430
+ {visHasAnchors() && config.orientation === 'horizontal' && (
1431
+ <div className='edit-block'>
1432
+ <span className='edit-label column-heading'>Anchors</span>
1433
+ <Accordion allowZeroExpanded>
1434
+ {config.xAxis?.anchors?.map((anchor, index) => (
1435
+ <AccordionItem className='series-item series-item--chart' key={`xaxis-anchors-${index}`}>
1436
+ <AccordionItemHeading className='series-item__title'>
1437
+ <>
1438
+ <AccordionItemButton className={'accordion__button accordion__button'}>
1439
+ Anchor {index + 1}
1440
+ <button
1441
+ className='series-list__remove'
1442
+ onClick={e => {
1486
1443
  e.preventDefault()
1487
- const copiedAnchors = [...config.xAxis.anchors]
1488
- copiedAnchors[index].color = e.target.value
1489
- updateConfig({
1490
- ...config,
1491
- xAxis: {
1492
- ...config.xAxis,
1493
- anchors: copiedAnchors
1494
- }
1495
- })
1496
- }}
1497
- />
1498
- </label>
1499
-
1500
- <label>
1501
- Anchor Line Style
1502
- <select
1503
- value={config.xAxis.anchors[index].lineStyle || ''}
1504
- onChange={e => {
1505
- const copiedAnchors = [...config.xAxis.anchors]
1506
- copiedAnchors[index].lineStyle = e.target.value
1444
+ const copiedAnchorGroups = [...config.xAxis.anchors]
1445
+ copiedAnchorGroups.splice(index, 1)
1507
1446
  updateConfig({
1508
1447
  ...config,
1509
1448
  xAxis: {
1510
1449
  ...config.xAxis,
1511
- anchors: copiedAnchors
1450
+ anchors: copiedAnchorGroups
1512
1451
  }
1513
1452
  })
1514
1453
  }}
1515
1454
  >
1516
- <option>Select</option>
1517
- {lineOptions.map(line => (
1518
- <option key={line.key}>{line.value}</option>
1519
- ))}
1520
- </select>
1521
- </label>
1522
- </AccordionItemPanel>
1523
- </AccordionItem>
1524
- ))}
1525
- </Accordion>
1526
-
1527
- <button
1528
- className='btn full-width'
1529
- onClick={e => {
1530
- e.preventDefault()
1531
- const anchors = [...config.xAxis.anchors]
1532
- anchors.push({} as Anchor)
1533
- updateConfig({
1534
- ...config,
1535
- xAxis: {
1536
- ...config.xAxis,
1537
- anchors
1538
- }
1539
- })
1540
- }}
1541
- >
1542
- Add Anchor
1543
- </button>
1544
- </div>
1545
- )}
1546
- {/* end: anchors */}
1547
- </AccordionItemPanel>
1548
- </AccordionItem>
1549
- )}
1550
- {/* Right Value Axis Settings */}
1551
- {hasRightAxis && (
1552
- <AccordionItem>
1553
- <AccordionItemHeading>
1554
- <AccordionItemButton>Right Value Axis</AccordionItemButton>
1555
- </AccordionItemHeading>
1556
- <AccordionItemPanel>
1557
- <TextField value={config.yAxis.rightLabel} section='yAxis' fieldName='rightLabel' label='Label' updateField={updateField} />
1558
- <TextField value={config.yAxis.rightNumTicks} placeholder='Auto' type='number' section='yAxis' fieldName='rightNumTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1559
- <TextField value={config.yAxis.rightAxisSize} type='number' section='yAxis' fieldName='rightAxisSize' label='Size (Width)' className='number-narrow' updateField={updateField} />
1560
- <TextField value={config.yAxis.rightLabelOffsetSize} type='number' section='yAxis' fieldName='rightLabelOffsetSize' label='Label Offset' className='number-narrow' updateField={updateField} />
1561
-
1562
- <span className='divider-heading'>Number Formatting</span>
1563
- <CheckBox value={config.dataFormat.rightCommas} section='dataFormat' fieldName='rightCommas' label='Add commas' updateField={updateField} />
1564
- <TextField value={config.dataFormat.rightRoundTo} type='number' section='dataFormat' fieldName='rightRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1565
- <div className='two-col-inputs'>
1566
- <TextField
1567
- value={config.dataFormat.rightPrefix}
1568
- section='dataFormat'
1569
- fieldName='rightPrefix'
1570
- label='Prefix'
1571
- updateField={updateField}
1572
- tooltip={
1573
- <Tooltip style={{ textTransform: 'none' }}>
1574
- <Tooltip.Target>
1575
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1576
- </Tooltip.Target>
1577
- <Tooltip.Content>
1578
- {config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
1579
- {config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
1580
- </Tooltip.Content>
1581
- </Tooltip>
1582
- }
1583
- />
1584
- <TextField
1585
- value={config.dataFormat.rightSuffix}
1586
- section='dataFormat'
1587
- fieldName='rightSuffix'
1588
- label='Suffix'
1589
- updateField={updateField}
1590
- tooltip={
1591
- <Tooltip style={{ textTransform: 'none' }}>
1592
- <Tooltip.Target>
1593
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1594
- </Tooltip.Target>
1595
- <Tooltip.Content>
1596
- {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1597
- {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1598
- </Tooltip.Content>
1599
- </Tooltip>
1600
- }
1601
- />
1455
+ Remove
1456
+ </button>
1457
+ </AccordionItemButton>
1458
+ </>
1459
+ </AccordionItemHeading>
1460
+ <AccordionItemPanel>
1461
+ <label>
1462
+ <span>Anchor Value</span>
1463
+ <Tooltip style={{ textTransform: 'none' }}>
1464
+ <Tooltip.Target>
1465
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1466
+ </Tooltip.Target>
1467
+ <Tooltip.Content>
1468
+ <p>Enter the value as its shown in the data column</p>
1469
+ </Tooltip.Content>
1470
+ </Tooltip>
1471
+ <input
1472
+ type='text'
1473
+ value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
1474
+ onChange={e => {
1475
+ e.preventDefault()
1476
+ const copiedAnchors = [...config.xAxis.anchors]
1477
+ copiedAnchors[index].value = e.target.value
1478
+ updateConfig({
1479
+ ...config,
1480
+ xAxis: {
1481
+ ...config.xAxis,
1482
+ anchors: copiedAnchors
1483
+ }
1484
+ })
1485
+ }}
1486
+ />
1487
+ </label>
1488
+
1489
+ <label>
1490
+ <span>Anchor Color</span>
1491
+ <input
1492
+ type='text'
1493
+ value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
1494
+ onChange={e => {
1495
+ e.preventDefault()
1496
+ const copiedAnchors = [...config.xAxis.anchors]
1497
+ copiedAnchors[index].color = e.target.value
1498
+ updateConfig({
1499
+ ...config,
1500
+ xAxis: {
1501
+ ...config.xAxis,
1502
+ anchors: copiedAnchors
1503
+ }
1504
+ })
1505
+ }}
1506
+ />
1507
+ </label>
1508
+
1509
+ <label>
1510
+ Anchor Line Style
1511
+ <select
1512
+ value={config.xAxis.anchors[index].lineStyle || ''}
1513
+ onChange={e => {
1514
+ const copiedAnchors = [...config.xAxis.anchors]
1515
+ copiedAnchors[index].lineStyle = e.target.value
1516
+ updateConfig({
1517
+ ...config,
1518
+ xAxis: {
1519
+ ...config.xAxis,
1520
+ anchors: copiedAnchors
1521
+ }
1522
+ })
1523
+ }}
1524
+ >
1525
+ <option>Select</option>
1526
+ {lineOptions.map(line => (
1527
+ <option key={line.key}>{line.value}</option>
1528
+ ))}
1529
+ </select>
1530
+ </label>
1531
+ </AccordionItemPanel>
1532
+ </AccordionItem>
1533
+ ))}
1534
+ </Accordion>
1535
+
1536
+ <button
1537
+ className='btn full-width'
1538
+ onClick={e => {
1539
+ e.preventDefault()
1540
+ const anchors = [...config.xAxis.anchors]
1541
+ anchors.push({} as Anchor)
1542
+ updateConfig({
1543
+ ...config,
1544
+ xAxis: {
1545
+ ...config.xAxis,
1546
+ anchors
1547
+ }
1548
+ })
1549
+ }}
1550
+ >
1551
+ Add Anchor
1552
+ </button>
1602
1553
  </div>
1554
+ )}
1555
+ {/* end: anchors */}
1556
+ </AccordionItemPanel>
1557
+ </AccordionItem>
1558
+ )}
1559
+ {/* Right Value Axis Settings */}
1560
+ {hasRightAxis && (
1561
+ <AccordionItem>
1562
+ <AccordionItemHeading>
1563
+ <AccordionItemButton>Right Value Axis</AccordionItemButton>
1564
+ </AccordionItemHeading>
1565
+ <AccordionItemPanel>
1566
+ <TextField value={config.yAxis.rightLabel} section='yAxis' fieldName='rightLabel' label='Label' updateField={updateField} />
1567
+ <TextField value={config.yAxis.rightNumTicks} placeholder='Auto' type='number' section='yAxis' fieldName='rightNumTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1568
+ <TextField value={config.yAxis.rightAxisSize} type='number' section='yAxis' fieldName='rightAxisSize' label='Size (Width)' className='number-narrow' updateField={updateField} />
1569
+ <TextField value={config.yAxis.rightLabelOffsetSize} type='number' section='yAxis' fieldName='rightLabelOffsetSize' label='Label Offset' className='number-narrow' updateField={updateField} />
1570
+
1571
+ <span className='divider-heading'>Number Formatting</span>
1572
+ <CheckBox value={config.dataFormat.rightCommas} section='dataFormat' fieldName='rightCommas' label='Add commas' updateField={updateField} />
1573
+ <TextField value={config.dataFormat.rightRoundTo} type='number' section='dataFormat' fieldName='rightRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1574
+ <div className='two-col-inputs'>
1575
+ <TextField
1576
+ value={config.dataFormat.rightPrefix}
1577
+ section='dataFormat'
1578
+ fieldName='rightPrefix'
1579
+ label='Prefix'
1580
+ updateField={updateField}
1581
+ tooltip={
1582
+ <Tooltip style={{ textTransform: 'none' }}>
1583
+ <Tooltip.Target>
1584
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1585
+ </Tooltip.Target>
1586
+ <Tooltip.Content>
1587
+ {config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
1588
+ {config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
1589
+ </Tooltip.Content>
1590
+ </Tooltip>
1591
+ }
1592
+ />
1593
+ <TextField
1594
+ value={config.dataFormat.rightSuffix}
1595
+ section='dataFormat'
1596
+ fieldName='rightSuffix'
1597
+ label='Suffix'
1598
+ updateField={updateField}
1599
+ tooltip={
1600
+ <Tooltip style={{ textTransform: 'none' }}>
1601
+ <Tooltip.Target>
1602
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1603
+ </Tooltip.Target>
1604
+ <Tooltip.Content>
1605
+ {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1606
+ {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1607
+ </Tooltip.Content>
1608
+ </Tooltip>
1609
+ }
1610
+ />
1611
+ </div>
1612
+
1613
+ <CheckBox value={config.yAxis.rightHideAxis} section='yAxis' fieldName='rightHideAxis' label='Hide Axis' updateField={updateField} />
1614
+ <CheckBox value={config.yAxis.rightHideLabel} section='yAxis' fieldName='rightHideLabel' label='Hide Label' updateField={updateField} />
1615
+ <CheckBox value={config.yAxis.rightHideTicks} section='yAxis' fieldName='rightHideTicks' label='Hide Ticks' updateField={updateField} />
1616
+
1617
+ <TextField value={config.yAxis.max} section='yAxis' fieldName='rightMax' type='number' label='right axis max value' placeholder='Auto' updateField={updateField} />
1618
+ <span style={{ color: 'red', display: 'block' }}>{warningMsg.rightMaxMessage}</span>
1619
+ <TextField value={config.yAxis.min} section='yAxis' fieldName='rightMin' type='number' label='right axis min value' placeholder='Auto' updateField={updateField} />
1620
+ <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1621
+ </AccordionItemPanel>
1622
+ </AccordionItem>
1623
+ )}
1624
+ {visSupportsDateCategoryAxis() && (
1625
+ <AccordionItem>
1626
+ <AccordionItemHeading>
1627
+ <AccordionItemButton>
1628
+ {config.visualizationType === 'Pie' ? 'Segments' : 'Date/Category Axis'}
1629
+ {!config.xAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
1630
+ </AccordionItemButton>
1631
+ </AccordionItemHeading>
1632
+ <AccordionItemPanel>
1633
+ {config.visualizationType !== 'Pie' && (
1634
+ <>
1635
+ {config.visualizationType !== 'Forest Plot' && (
1636
+ <>
1637
+ <label>
1638
+ <span className='edit-label'>
1639
+ Data Scaling Type
1640
+ <Tooltip style={{ textTransform: 'none', display: 'inline-block' }}>
1641
+ <Tooltip.Target>
1642
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1643
+ </Tooltip.Target>
1644
+ <Tooltip.Content>Linear scales are employed for quantitative data, while time scales are used for time-series data.</Tooltip.Content>
1645
+ </Tooltip>
1646
+ </span>
1647
+ <select
1648
+ value={config.xAxis.type}
1649
+ onChange={e =>
1650
+ updateConfig({
1651
+ ...config,
1652
+ xAxis: {
1653
+ ...config.xAxis,
1654
+ type: e.target.value
1655
+ }
1656
+ })
1657
+ }
1658
+ >
1659
+ <option value='categorical'>Categorical (Linear Scale)</option>
1660
+ <option value='date'>Date (Linear Scale)</option>
1661
+ <option value='date-time'>Date (Date Time Scale)</option>
1662
+ {config.visualizationType === 'Scatter Plot' && <option value={'continuous'}>Continuous</option>}
1663
+ </select>
1664
+ </label>
1603
1665
 
1604
- <CheckBox value={config.yAxis.rightHideAxis} section='yAxis' fieldName='rightHideAxis' label='Hide Axis' updateField={updateField} />
1605
- <CheckBox value={config.yAxis.rightHideLabel} section='yAxis' fieldName='rightHideLabel' label='Hide Label' updateField={updateField} />
1606
- <CheckBox value={config.yAxis.rightHideTicks} section='yAxis' fieldName='rightHideTicks' label='Hide Ticks' updateField={updateField} />
1607
-
1608
- <TextField value={config.yAxis.max} section='yAxis' fieldName='rightMax' type='number' label='right axis max value' placeholder='Auto' updateField={updateField} />
1609
- <span style={{ color: 'red', display: 'block' }}>{warningMsg.rightMaxMessage}</span>
1610
- <TextField value={config.yAxis.min} section='yAxis' fieldName='rightMin' type='number' label='right axis min value' placeholder='Auto' updateField={updateField} />
1611
- <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1612
- </AccordionItemPanel>
1613
- </AccordionItem>
1614
- )}
1615
- {visSupportsDateCategoryAxis() && (
1616
- <AccordionItem>
1617
- <AccordionItemHeading>
1618
- <AccordionItemButton>
1619
- {config.visualizationType === 'Pie' ? 'Segments' : 'Date/Category Axis'}
1620
- {!config.xAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
1621
- </AccordionItemButton>
1622
- </AccordionItemHeading>
1623
- <AccordionItemPanel>
1624
- {config.visualizationType !== 'Pie' && (
1625
- <>
1626
- {config.visualizationType !== 'Forest Plot' && (
1627
- <>
1628
- <Select value={config.xAxis.type} section='xAxis' fieldName='type' label='Data Type' updateField={updateField} options={config.visualizationType !== 'Scatter Plot' ? ['categorical', 'date'] : ['categorical', 'continuous', 'date']} />
1629
- {(config.visualizationType === 'Bar' || config.visualizationType === 'Line' || config.visualizationType === 'Combo' || config.visualizationType === 'Area Chart') && config.xAxis.type === 'date' && config.orientation !== 'horizontal' && (
1630
- <CheckBox value={config.xAxis.sortDates} section='xAxis' fieldName='sortDates' label='Force Date Scale (Sort Dates)' updateField={updateField} />
1631
- )}{' '}
1632
- {visSupportsDateCategoryAxisPadding() && (
1633
- <TextField
1634
- value={config.xAxis.padding}
1635
- type='number'
1636
- min={0}
1637
- section='xAxis'
1638
- fieldName='padding'
1639
- label={'Padding (Percent)'}
1640
- className='number-narrow'
1641
- updateField={updateField}
1642
- tooltip={
1643
- <Tooltip style={{ textTransform: 'none' }}>
1644
- <Tooltip.Target>
1645
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1646
- </Tooltip.Target>
1647
- <Tooltip.Content>
1648
- <p>For use with date scale. Extends the earliest and latest dates represented on the scale by the percentage specified.</p>
1649
- </Tooltip.Content>
1650
- </Tooltip>
1651
- }
1652
- />
1653
- )}
1654
- </>
1655
- )}
1656
- <Select
1657
- value={config.xAxis.dataKey || setCategoryAxis() || ''}
1658
- section='xAxis'
1659
- fieldName='dataKey'
1660
- label='Data Key'
1661
- initial='Select'
1662
- required={true}
1663
- updateField={updateField}
1664
- options={getColumns(false)}
1665
- tooltip={
1666
- <Tooltip style={{ textTransform: 'none' }}>
1667
- <Tooltip.Target>
1668
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1669
- </Tooltip.Target>
1670
- <Tooltip.Content>
1671
- <p>Select the column or row containing the categories or dates for this axis. </p>
1672
- </Tooltip.Content>
1673
- </Tooltip>
1674
- }
1675
- />
1676
- </>
1677
- )}
1666
+ <CheckBox value={config.xAxis.manual} section='xAxis' fieldName='manual' label='Manual Ticks' updateField={updateField} />
1678
1667
 
1679
- {config.visualizationType === 'Pie' && (
1668
+ {visSupportsDateCategoryAxisPadding() && (
1669
+ <TextField
1670
+ value={config.xAxis.padding}
1671
+ type='number'
1672
+ min={0}
1673
+ section='xAxis'
1674
+ fieldName='padding'
1675
+ label={'Padding (Percent)'}
1676
+ className='number-narrow'
1677
+ updateField={updateField}
1678
+ tooltip={
1679
+ <Tooltip style={{ textTransform: 'none' }}>
1680
+ <Tooltip.Target>
1681
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1682
+ </Tooltip.Target>
1683
+ <Tooltip.Content>
1684
+ <p>For use with date scale. Extends the earliest and latest dates represented on the scale by the percentage specified.</p>
1685
+ </Tooltip.Content>
1686
+ </Tooltip>
1687
+ }
1688
+ />
1689
+ )}
1690
+ </>
1691
+ )}
1680
1692
  <Select
1681
- value={config.xAxis.dataKey || ''}
1693
+ value={config.xAxis.dataKey || setCategoryAxis() || ''}
1682
1694
  section='xAxis'
1683
1695
  fieldName='dataKey'
1684
- label='Segment Labels'
1696
+ label='Data Key'
1685
1697
  initial='Select'
1686
1698
  required={true}
1687
1699
  updateField={updateField}
@@ -1692,317 +1704,268 @@ const EditorPanel = () => {
1692
1704
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1693
1705
  </Tooltip.Target>
1694
1706
  <Tooltip.Content>
1695
- <p>Select the source row or column that contains the segment labels. Depending on the data structure, it may be listed as "Key."</p>
1707
+ <p>Select the column or row containing the categories or dates for this axis. </p>
1696
1708
  </Tooltip.Content>
1697
1709
  </Tooltip>
1698
1710
  }
1699
1711
  />
1700
- )}
1701
-
1702
- {config.visualizationType !== 'Pie' && (
1703
- <>
1704
- <TextField value={config.xAxis.label} section='xAxis' fieldName='label' label='Label' updateField={updateField} />
1705
-
1706
- {config.xAxis.type === 'continuous' && (
1707
- <>
1708
- <TextField
1709
- value={config.dataFormat.bottomPrefix}
1710
- section='dataFormat'
1711
- fieldName='bottomPrefix'
1712
- label='Prefix'
1713
- updateField={updateField}
1714
- tooltip={
1715
- <Tooltip style={{ textTransform: 'none' }}>
1716
- <Tooltip.Target>
1717
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1718
- </Tooltip.Target>
1719
- <Tooltip.Content>
1720
- <p>Enter a data suffix (such as "%"), if applicable.</p>
1721
- </Tooltip.Content>
1722
- </Tooltip>
1723
- }
1724
- />
1712
+ </>
1713
+ )}
1714
+
1715
+ {config.visualizationType === 'Pie' && (
1716
+ <Select
1717
+ value={config.xAxis.dataKey || ''}
1718
+ section='xAxis'
1719
+ fieldName='dataKey'
1720
+ label='Segment Labels'
1721
+ initial='Select'
1722
+ required={true}
1723
+ updateField={updateField}
1724
+ options={getColumns(false)}
1725
+ tooltip={
1726
+ <Tooltip style={{ textTransform: 'none' }}>
1727
+ <Tooltip.Target>
1728
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1729
+ </Tooltip.Target>
1730
+ <Tooltip.Content>
1731
+ <p>Select the source row or column that contains the segment labels. Depending on the data structure, it may be listed as "Key."</p>
1732
+ </Tooltip.Content>
1733
+ </Tooltip>
1734
+ }
1735
+ />
1736
+ )}
1725
1737
 
1726
- <TextField
1727
- value={config.dataFormat.bottomSuffix}
1728
- section='dataFormat'
1729
- fieldName='bottomSuffix'
1730
- label='Suffix'
1731
- updateField={updateField}
1732
- tooltip={
1733
- <Tooltip style={{ textTransform: 'none' }}>
1734
- <Tooltip.Target>
1735
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1736
- </Tooltip.Target>
1737
- <Tooltip.Content>
1738
- <p>Enter a data suffix (such as "%"), if applicable.</p>
1739
- </Tooltip.Content>
1740
- </Tooltip>
1741
- }
1742
- />
1738
+ {config.visualizationType !== 'Pie' && (
1739
+ <>
1740
+ <TextField value={config.xAxis.label} section='xAxis' fieldName='label' label='Label' updateField={updateField} />
1743
1741
 
1744
- <CheckBox
1745
- value={config.dataFormat.bottomAbbreviated}
1746
- section='dataFormat'
1747
- fieldName='bottomAbbreviated'
1748
- label='Abbreviate Axis Values'
1749
- updateField={updateField}
1750
- tooltip={
1751
- <Tooltip style={{ textTransform: 'none' }}>
1752
- <Tooltip.Target>
1753
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1754
- </Tooltip.Target>
1755
- <Tooltip.Content>
1756
- <p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
1757
- </Tooltip.Content>
1758
- </Tooltip>
1759
- }
1760
- />
1761
- </>
1762
- )}
1763
-
1764
- {config.xAxis.type === 'date' && (
1765
- <>
1766
- <p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
1767
- Format how charts should parse and display your dates using{' '}
1768
- <a href='https://github.com/d3/d3-time-format#locale_format' target='_blank' rel='noreferrer'>
1769
- these guidelines
1770
- </a>
1771
- .
1772
- </p>
1773
- <TextField
1774
- tooltip={
1775
- <Tooltip style={{ textTransform: 'none' }}>
1776
- <Tooltip.Target>
1777
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1778
- </Tooltip.Target>
1779
- <Tooltip.Content>
1780
- <p>This field specifies the pattern used to read and interpret dates in your dataset, ensuring the dates are correctly understood and processed. </p>
1781
- </Tooltip.Content>
1782
- </Tooltip>
1783
- }
1784
- value={config.xAxis.dateParseFormat}
1785
- section='xAxis'
1786
- fieldName='dateParseFormat'
1787
- placeholder='Ex. %Y-%m-%d'
1788
- label='Date Parse Format'
1789
- updateField={updateField}
1790
- />
1791
- <TextField
1792
- tooltip={
1793
- <Tooltip style={{ textTransform: 'none' }}>
1794
- <Tooltip.Target>
1795
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1796
- </Tooltip.Target>
1797
- <Tooltip.Content>
1798
- <p> Adjusts the date display format on the axis for clear, visual date representation.</p>
1799
- </Tooltip.Content>
1800
- </Tooltip>
1801
- }
1802
- value={config.xAxis.dateDisplayFormat}
1803
- section='xAxis'
1804
- fieldName='dateDisplayFormat'
1805
- placeholder='Ex. %Y-%m-%d'
1806
- label='AXIS DATE DISPLAY FORMAT'
1807
- updateField={updateField}
1808
- />
1809
- <TextField
1810
- tooltip={
1811
- <Tooltip style={{ textTransform: 'none' }}>
1812
- <Tooltip.Target>
1813
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1814
- </Tooltip.Target>
1815
- <Tooltip.Content>
1816
- <p>Specify a custom format for displaying dates in data table. If left empty, dates will adopt the Axis Date Display format. </p>
1817
- </Tooltip.Content>
1818
- </Tooltip>
1819
- }
1820
- value={config.table.dateDisplayFormat}
1821
- section='table'
1822
- fieldName='dateDisplayFormat'
1823
- placeholder='Ex. %Y-%m-%d'
1824
- label='DATA TABLE DATE DISPLAY FORMAT'
1825
- updateField={updateField}
1826
- />
1827
- <TextField
1828
- tooltip={
1829
- <Tooltip style={{ textTransform: 'none' }}>
1830
- <Tooltip.Target>
1831
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1832
- </Tooltip.Target>
1833
- <Tooltip.Content>
1834
- <p>Specify a custom format for displaying dates on hovers. If left empty, dates will adopt the Axis Date Display format. </p>
1835
- </Tooltip.Content>
1836
- </Tooltip>
1837
- }
1838
- value={config.tooltips.dateDisplayFormat}
1839
- section='tooltips'
1840
- fieldName='dateDisplayFormat'
1841
- placeholder='Ex. %Y-%m-%d'
1842
- label='HOVER DATE DISPLAY FORMAT'
1843
- updateField={updateField}
1844
- />
1845
- </>
1846
- )}
1847
-
1848
- <CheckBox
1849
- value={config.exclusions.active}
1850
- section='exclusions'
1851
- fieldName='active'
1852
- label={config.xAxis.type === 'date' ? 'Limit by start and/or end dates' : 'Exclude one or more values'}
1853
- tooltip={
1854
- <Tooltip style={{ textTransform: 'none' }}>
1855
- <Tooltip.Target>
1856
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1857
- </Tooltip.Target>
1858
- <Tooltip.Content>
1859
- <p>When this option is checked, you can select source-file values for exclusion from the date/category axis. </p>
1860
- </Tooltip.Content>
1861
- </Tooltip>
1862
- }
1863
- updateField={updateField}
1864
- />
1865
- {/* {visHasBrushChart && <CheckBox value={config.brush.active} section='brush' fieldName='active' label='Brush Slider ' updateField={updateField} />} */}
1742
+ {config.xAxis.type === 'continuous' && (
1743
+ <>
1744
+ <TextField
1745
+ value={config.dataFormat.bottomPrefix}
1746
+ section='dataFormat'
1747
+ fieldName='bottomPrefix'
1748
+ label='Prefix'
1749
+ updateField={updateField}
1750
+ tooltip={
1751
+ <Tooltip style={{ textTransform: 'none' }}>
1752
+ <Tooltip.Target>
1753
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1754
+ </Tooltip.Target>
1755
+ <Tooltip.Content>
1756
+ <p>Enter a data prefix (such as "$"), if applicable.</p>
1757
+ </Tooltip.Content>
1758
+ </Tooltip>
1759
+ }
1760
+ />
1866
1761
 
1867
- {config.exclusions.active && (
1868
- <>
1869
- {config.xAxis.type === 'categorical' && (
1870
- <>
1871
- {config.exclusions.keys.length > 0 && (
1872
- <>
1873
- <fieldset>
1874
- <legend className='edit-label'>Excluded Keys</legend>
1875
- </fieldset>
1876
- <ExclusionsList />
1877
- </>
1878
- )}
1762
+ <TextField
1763
+ value={config.dataFormat.bottomSuffix}
1764
+ section='dataFormat'
1765
+ fieldName='bottomSuffix'
1766
+ label='Suffix'
1767
+ updateField={updateField}
1768
+ tooltip={
1769
+ <Tooltip style={{ textTransform: 'none' }}>
1770
+ <Tooltip.Target>
1771
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1772
+ </Tooltip.Target>
1773
+ <Tooltip.Content>
1774
+ <p>Enter a data suffix (such as "%"), if applicable.</p>
1775
+ </Tooltip.Content>
1776
+ </Tooltip>
1777
+ }
1778
+ />
1879
1779
 
1880
- <Select
1881
- fieldName='visualizationType'
1882
- label='Add Exclusion'
1883
- initial='Select'
1884
- onChange={e => {
1885
- if (e.target.value !== '' && e.target.value !== 'Select') {
1886
- addNewExclusion(e.target.value)
1887
- }
1888
- e.target.value = ''
1889
- }}
1890
- options={getDataValues(config.xAxis.dataKey, true)}
1891
- />
1892
- </>
1893
- )}
1780
+ <CheckBox
1781
+ value={config.dataFormat.bottomAbbreviated}
1782
+ section='dataFormat'
1783
+ fieldName='bottomAbbreviated'
1784
+ label='Abbreviate Axis Values'
1785
+ updateField={updateField}
1786
+ tooltip={
1787
+ <Tooltip style={{ textTransform: 'none' }}>
1788
+ <Tooltip.Target>
1789
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1790
+ </Tooltip.Target>
1791
+ <Tooltip.Content>
1792
+ <p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
1793
+ </Tooltip.Content>
1794
+ </Tooltip>
1795
+ }
1796
+ />
1797
+ </>
1798
+ )}
1894
1799
 
1895
- {config.xAxis.type === 'date' && (
1896
- <>
1897
- <TextField type='date' section='exclusions' fieldName='dateStart' label='Start Date' updateField={updateField} value={config.exclusions.dateStart || ''} />
1898
- <TextField type='date' section='exclusions' fieldName='dateEnd' label='End Date' updateField={updateField} value={config.exclusions.dateEnd || ''} />
1899
- </>
1900
- )}
1901
- </>
1902
- )}
1903
-
1904
- {visSupportsDateCategoryNumTicks() && <TextField value={config.xAxis.numTicks} placeholder='Auto' type='number' min={1} section='xAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />}
1905
- {visSupportsDateCategoryHeight() && <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} />}
1906
-
1907
- {visSupportsDateCategoryAxisPadding() && <TextField value={config.xAxis.padding} type='number' min={0} section='xAxis' fieldName='padding' label={'Padding (Percent)'} className='number-narrow' updateField={updateField} />}
1908
-
1909
- {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1910
- {/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1911
- {(config.xAxis.type === 'continuous' || config.forestPlot.type === 'Logarithmic') && (
1912
- <>
1913
- <CheckBox value={config.dataFormat.bottomCommas} section='dataFormat' fieldName='bottomCommas' label='Add commas' updateField={updateField} />
1914
- <TextField value={config.dataFormat.bottomRoundTo} type='number' section='dataFormat' fieldName='bottomRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1915
- </>
1916
- )}
1917
- {visSupportsResponsiveTicks() && config.orientation === 'vertical' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
1918
- {(config.orientation === 'horizontal' || !config.isResponsiveTicks) && visSupportsDateCategoryTickRotation() && (
1919
- <TextField value={config.xAxis.tickRotation} type='number' min={0} section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />
1920
- )}
1921
- {config.orientation === 'vertical' && config.isResponsiveTicks && config.visualizationType !== 'Paired Bar' && (
1800
+ {isDateScale(config.xAxis) && (
1801
+ <>
1802
+ <p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
1803
+ Format how charts should parse and display your dates using{' '}
1804
+ <a href='https://github.com/d3/d3-time-format#locale_format' target='_blank' rel='noreferrer'>
1805
+ these guidelines
1806
+ </a>
1807
+ .
1808
+ </p>
1922
1809
  <TextField
1923
- value={config.xAxis.maxTickRotation}
1924
- type='number'
1925
- min={0}
1810
+ tooltip={
1811
+ <Tooltip style={{ textTransform: 'none' }}>
1812
+ <Tooltip.Target>
1813
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1814
+ </Tooltip.Target>
1815
+ <Tooltip.Content>
1816
+ <p>This field specifies the pattern used to read and interpret dates in your dataset, ensuring the dates are correctly understood and processed. </p>
1817
+ </Tooltip.Content>
1818
+ </Tooltip>
1819
+ }
1820
+ value={config.xAxis.dateParseFormat}
1926
1821
  section='xAxis'
1927
- fieldName='maxTickRotation'
1928
- label='Max Tick Rotation'
1929
- className='number-narrow'
1822
+ fieldName='dateParseFormat'
1823
+ placeholder='Ex. %Y-%m-%d'
1824
+ label='Date Parse Format'
1930
1825
  updateField={updateField}
1826
+ />
1827
+ <TextField
1931
1828
  tooltip={
1932
1829
  <Tooltip style={{ textTransform: 'none' }}>
1933
1830
  <Tooltip.Target>
1934
1831
  <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1935
1832
  </Tooltip.Target>
1936
1833
  <Tooltip.Content>
1937
- <p>Degrees ticks will be rotated if values overlap, especially in smaller viewports.</p>
1834
+ <p> Adjusts the date display format on the axis for clear, visual date representation.</p>
1938
1835
  </Tooltip.Content>
1939
1836
  </Tooltip>
1940
1837
  }
1838
+ value={config.xAxis.dateDisplayFormat}
1839
+ section='xAxis'
1840
+ fieldName='dateDisplayFormat'
1841
+ placeholder='Ex. %Y-%m-%d'
1842
+ label='AXIS DATE DISPLAY FORMAT'
1843
+ updateField={updateField}
1941
1844
  />
1942
- )}
1943
-
1944
- {config.orientation === 'horizontal' ? (
1945
- <>
1946
- {visSupportsDateCategoryAxisLine() && <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
1947
- {visSupportsDateCategoryAxisLabel() && <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
1948
- </>
1949
- ) : (
1950
- <>
1951
- {visSupportsDateCategoryAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
1952
- {visSupportsDateCategoryAxisLabel() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
1953
- {visSupportsDateCategoryAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
1954
- </>
1955
- )}
1956
-
1957
- {config.series?.length === 1 && config.visualizationType === 'Bar' && (
1958
- <>
1959
- {/* HIGHLIGHTED BARS */}
1960
- <label htmlFor='barHighlight'>Bar Highlighting</label>
1961
- {config.series.length === 1 &&
1962
- highlightedBarValues.map((highlightedBarValue, i) => (
1963
- <fieldset>
1964
- <div className='edit-block' key={`highlighted-bar-${i}`}>
1965
- <button className='remove-column' onClick={e => handleRemoveHighlightedBar(e, i)}>
1966
- Remove
1967
- </button>
1968
- <p>Highlighted Bar {i + 1}</p>
1969
- <label>
1970
- <span className='edit-label column-heading'>Value</span>
1971
- <select value={config.highlightedBarValues[i].value} onChange={e => handleUpdateHighlightedBar(e, i)}>
1972
- <option value=''>- Select Value -</option>
1973
- {highlightedSeriesValues && [...new Set(highlightedSeriesValues)].sort().map(option => <option key={`special-class-value-option-${i}-${option}`}>{option}</option>)}
1974
- </select>
1975
- </label>
1976
- <label>
1977
- <span className='edit-label column-heading'>Color</span>
1978
- <input type='text' value={config.highlightedBarValues[i].color ? config.highlightedBarValues[i].color : ''} onChange={e => handleUpdateHighlightedBarColor(e, i)} />
1979
- </label>
1980
- <label>
1981
- <span className='edit-label column-heading'>Border Width</span>
1982
- <input max='5' min='0' type='number' value={config.highlightedBarValues[i].borderWidth ? config.highlightedBarValues[i].borderWidth : ''} onChange={e => handleUpdateHighlightedBorderWidth(e, i)} />
1983
- </label>
1984
- <label>
1985
- <span className='edit-label column-heading'>Legend Label</span>
1986
- <input type='text' value={config.highlightedBarValues[i].legendLabel ? config.highlightedBarValues[i].legendLabel : ''} onChange={e => handleHighlightedBarLegendLabel(e, i)} />
1987
- </label>
1988
- </div>
1989
- </fieldset>
1990
- ))}
1991
- <button className='btn full-width' onClick={e => handleAddNewHighlightedBar(e)}>
1992
- Add Highlighted Bar
1993
- </button>
1994
- </>
1995
- )}
1996
- </>
1997
- )}
1845
+ <TextField
1846
+ tooltip={
1847
+ <Tooltip style={{ textTransform: 'none' }}>
1848
+ <Tooltip.Target>
1849
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1850
+ </Tooltip.Target>
1851
+ <Tooltip.Content>
1852
+ <p>Specify a custom format for displaying dates in data table. If left empty, dates will adopt the Axis Date Display format. </p>
1853
+ </Tooltip.Content>
1854
+ </Tooltip>
1855
+ }
1856
+ value={config.table.dateDisplayFormat}
1857
+ section='table'
1858
+ fieldName='dateDisplayFormat'
1859
+ placeholder='Ex. %Y-%m-%d'
1860
+ label='DATA TABLE DATE DISPLAY FORMAT'
1861
+ updateField={updateField}
1862
+ />
1863
+ <TextField
1864
+ tooltip={
1865
+ <Tooltip style={{ textTransform: 'none' }}>
1866
+ <Tooltip.Target>
1867
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1868
+ </Tooltip.Target>
1869
+ <Tooltip.Content>
1870
+ <p>Specify a custom format for displaying dates on hovers. If left empty, dates will adopt the Axis Date Display format. </p>
1871
+ </Tooltip.Content>
1872
+ </Tooltip>
1873
+ }
1874
+ value={config.tooltips.dateDisplayFormat}
1875
+ section='tooltips'
1876
+ fieldName='dateDisplayFormat'
1877
+ placeholder='Ex. %Y-%m-%d'
1878
+ label='HOVER DATE DISPLAY FORMAT'
1879
+ updateField={updateField}
1880
+ />
1881
+ </>
1882
+ )}
1998
1883
 
1999
- {config.visualizationType === 'Pie' && (
2000
- <>
2001
- <CheckBox
2002
- value={config.exclusions.active}
2003
- section='exclusions'
2004
- fieldName='active'
2005
- label={'Exclude one or more values'}
1884
+ <CheckBox
1885
+ value={config.exclusions.active}
1886
+ section='exclusions'
1887
+ fieldName='active'
1888
+ label={config.xAxis.type === 'date' ? 'Limit by start and/or end dates' : 'Exclude one or more values'}
1889
+ tooltip={
1890
+ <Tooltip style={{ textTransform: 'none' }}>
1891
+ <Tooltip.Target>
1892
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1893
+ </Tooltip.Target>
1894
+ <Tooltip.Content>
1895
+ <p>When this option is checked, you can select source-file values for exclusion from the date/category axis. </p>
1896
+ </Tooltip.Content>
1897
+ </Tooltip>
1898
+ }
1899
+ updateField={updateField}
1900
+ />
1901
+ {/* {visHasBrushChart && <CheckBox value={config.brush.active} section='brush' fieldName='active' label='Brush Slider ' updateField={updateField} />} */}
1902
+
1903
+ {config.exclusions.active && (
1904
+ <>
1905
+ {config.xAxis.type === 'categorical' && (
1906
+ <>
1907
+ {config.exclusions.keys.length > 0 && (
1908
+ <>
1909
+ <fieldset>
1910
+ <legend className='edit-label'>Excluded Keys</legend>
1911
+ </fieldset>
1912
+ <ExclusionsList />
1913
+ </>
1914
+ )}
1915
+
1916
+ <Select
1917
+ fieldName='visualizationType'
1918
+ label='Add Exclusion'
1919
+ initial='Select'
1920
+ onChange={e => {
1921
+ if (e.target.value !== '' && e.target.value !== 'Select') {
1922
+ addNewExclusion(e.target.value)
1923
+ }
1924
+ e.target.value = ''
1925
+ }}
1926
+ options={getDataValues(config.xAxis.dataKey, true)}
1927
+ />
1928
+ </>
1929
+ )}
1930
+
1931
+ {config.xAxis.type === 'date' && (
1932
+ <>
1933
+ <TextField type='date' section='exclusions' fieldName='dateStart' label='Start Date' updateField={updateField} value={config.exclusions.dateStart || ''} />
1934
+ <TextField type='date' section='exclusions' fieldName='dateEnd' label='End Date' updateField={updateField} value={config.exclusions.dateEnd || ''} />
1935
+ </>
1936
+ )}
1937
+ </>
1938
+ )}
1939
+
1940
+ {visSupportsDateCategoryNumTicks() && config.xAxis.type !== 'date-time' && config.xAxis.manual && (
1941
+ <TextField value={config.xAxis.manualStep} placeholder='Auto' type='number' min={1} section='xAxis' fieldName='manualStep' label='Step count' className='number-narrow' updateField={updateField} />
1942
+ )}
1943
+ {visSupportsDateCategoryNumTicks() && (config.xAxis.type === 'date-time' || !config.xAxis.manual) && (
1944
+ <TextField value={config.xAxis.numTicks} placeholder='Auto' type='number' min={1} section='xAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1945
+ )}
1946
+ {visSupportsDateCategoryHeight() && <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} />}
1947
+
1948
+ {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1949
+ {/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1950
+ {(config.xAxis.type === 'continuous' || config.forestPlot.type === 'Logarithmic') && (
1951
+ <>
1952
+ <CheckBox value={config.dataFormat.bottomCommas} section='dataFormat' fieldName='bottomCommas' label='Add commas' updateField={updateField} />
1953
+ <TextField value={config.dataFormat.bottomRoundTo} type='number' section='dataFormat' fieldName='bottomRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1954
+ </>
1955
+ )}
1956
+ {visSupportsResponsiveTicks() && config.orientation === 'vertical' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
1957
+ {(config.orientation === 'horizontal' || !config.isResponsiveTicks) && visSupportsDateCategoryTickRotation() && (
1958
+ <TextField value={config.xAxis.tickRotation} type='number' min={0} section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />
1959
+ )}
1960
+ {config.orientation === 'vertical' && config.isResponsiveTicks && config.visualizationType !== 'Paired Bar' && (
1961
+ <TextField
1962
+ value={config.xAxis.maxTickRotation}
1963
+ type='number'
1964
+ min={0}
1965
+ section='xAxis'
1966
+ fieldName='maxTickRotation'
1967
+ label='Max Tick Rotation'
1968
+ className='number-narrow'
2006
1969
  updateField={updateField}
2007
1970
  tooltip={
2008
1971
  <Tooltip style={{ textTransform: 'none' }}>
@@ -2010,543 +1973,619 @@ const EditorPanel = () => {
2010
1973
  <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2011
1974
  </Tooltip.Target>
2012
1975
  <Tooltip.Content>
2013
- <p>When this option is checked, you can select values for exclusion from the pie segments.</p>
1976
+ <p>Degrees ticks will be rotated if values overlap, especially in smaller viewports.</p>
2014
1977
  </Tooltip.Content>
2015
1978
  </Tooltip>
2016
1979
  }
2017
1980
  />
2018
- {config.exclusions.active && (
2019
- <>
2020
- {config.exclusions.keys.length > 0 && (
2021
- <>
2022
- <fieldset>
2023
- <legend className='edit-label'>Excluded Keys</legend>
2024
- </fieldset>
2025
- <ExclusionsList />
2026
- </>
2027
- )}
1981
+ )}
2028
1982
 
2029
- <Select
2030
- fieldName='visualizationType'
2031
- label='Add Exclusion'
2032
- initial='Select'
2033
- onChange={e => {
2034
- if (e.target.value !== '' && e.target.value !== 'Select') {
2035
- addNewExclusion(e.target.value)
2036
- }
2037
- e.target.value = ''
2038
- }}
2039
- options={getDataValues(config.xAxis.dataKey, true)}
2040
- />
2041
- </>
2042
- )}
2043
- </>
2044
- )}
1983
+ {config.orientation === 'horizontal' ? (
1984
+ <>
1985
+ {visSupportsDateCategoryAxisLine() && <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
1986
+ {visSupportsDateCategoryAxisLabel() && <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
1987
+ </>
1988
+ ) : (
1989
+ <>
1990
+ {visSupportsDateCategoryAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
1991
+ {visSupportsDateCategoryAxisLabel() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
1992
+ {visSupportsDateCategoryAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
1993
+ </>
1994
+ )}
2045
1995
 
2046
- {/* anchors */}
2047
- {visHasAnchors() && config.orientation !== 'horizontal' && (
2048
- <div className='edit-block'>
2049
- <span className='edit-label column-heading'>Anchors</span>
2050
- <Accordion allowZeroExpanded>
2051
- {config.xAxis?.anchors?.map((anchor, index) => (
2052
- <AccordionItem className='series-item series-item--chart' key={`xaxis-anchors-2-${index}`}>
2053
- <AccordionItemHeading className='series-item__title'>
2054
- <>
2055
- <AccordionItemButton className={'accordion__button accordion__button'}>
2056
- Anchor {index + 1}
2057
- <button
2058
- className='series-list__remove'
2059
- onClick={e => {
2060
- e.preventDefault()
2061
- const copiedAnchorGroups = [...config.xAxis.anchors]
2062
- copiedAnchorGroups.splice(index, 1)
2063
- updateConfig({
2064
- ...config,
2065
- xAxis: {
2066
- ...config.xAxis,
2067
- anchors: copiedAnchorGroups
2068
- }
2069
- })
2070
- }}
2071
- >
2072
- Remove
2073
- </button>
2074
- </AccordionItemButton>
2075
- </>
2076
- </AccordionItemHeading>
2077
- <AccordionItemPanel>
2078
- <label>
2079
- <span>Anchor Value</span>
2080
- <Tooltip style={{ textTransform: 'none' }}>
2081
- <Tooltip.Target>
2082
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2083
- </Tooltip.Target>
2084
- <Tooltip.Content>
2085
- <p>Enter the value as its shown in the data column</p>
2086
- </Tooltip.Content>
2087
- </Tooltip>
2088
- <input
2089
- type='text'
2090
- value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
2091
- onChange={e => {
2092
- e.preventDefault()
2093
- const copiedAnchors = [...config.xAxis.anchors]
2094
- copiedAnchors[index].value = e.target.value
2095
- updateConfig({
2096
- ...config,
2097
- xAxis: {
2098
- ...config.xAxis,
2099
- anchors: copiedAnchors
2100
- }
2101
- })
2102
- }}
2103
- />
2104
- </label>
1996
+ {config.series?.length === 1 && config.visualizationType === 'Bar' && (
1997
+ <>
1998
+ {/* HIGHLIGHTED BARS */}
1999
+ <label htmlFor='barHighlight'>Bar Highlighting</label>
2000
+ {config.series.length === 1 &&
2001
+ highlightedBarValues.map((highlightedBarValue, i) => (
2002
+ <fieldset>
2003
+ <div className='edit-block' key={`highlighted-bar-${i}`}>
2004
+ <button className='remove-column' onClick={e => handleRemoveHighlightedBar(e, i)}>
2005
+ Remove
2006
+ </button>
2007
+ <p>Highlighted Bar {i + 1}</p>
2008
+ <label>
2009
+ <span className='edit-label column-heading'>Value</span>
2010
+ <select value={config.highlightedBarValues[i].value} onChange={e => handleUpdateHighlightedBar(e, i)}>
2011
+ <option value=''>- Select Value -</option>
2012
+ {highlightedSeriesValues && [...new Set(highlightedSeriesValues)].sort().map(option => <option key={`special-class-value-option-${i}-${option}`}>{option}</option>)}
2013
+ </select>
2014
+ </label>
2015
+ <label>
2016
+ <span className='edit-label column-heading'>Color</span>
2017
+ <input type='text' value={config.highlightedBarValues[i].color ? config.highlightedBarValues[i].color : ''} onChange={e => handleUpdateHighlightedBarColor(e, i)} />
2018
+ </label>
2019
+ <label>
2020
+ <span className='edit-label column-heading'>Border Width</span>
2021
+ <input max='5' min='0' type='number' value={config.highlightedBarValues[i].borderWidth ? config.highlightedBarValues[i].borderWidth : ''} onChange={e => handleUpdateHighlightedBorderWidth(e, i)} />
2022
+ </label>
2023
+ <label>
2024
+ <span className='edit-label column-heading'>Legend Label</span>
2025
+ <input type='text' value={config.highlightedBarValues[i].legendLabel ? config.highlightedBarValues[i].legendLabel : ''} onChange={e => handleHighlightedBarLegendLabel(e, i)} />
2026
+ </label>
2027
+ </div>
2028
+ </fieldset>
2029
+ ))}
2030
+ <button className='btn full-width' onClick={e => handleAddNewHighlightedBar(e)}>
2031
+ Add Highlighted Bar
2032
+ </button>
2033
+ </>
2034
+ )}
2035
+ </>
2036
+ )}
2105
2037
 
2106
- <label>
2107
- <span>Anchor Color</span>
2108
- <input
2109
- type='text'
2110
- value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
2111
- onChange={e => {
2038
+ {config.visualizationType === 'Pie' && (
2039
+ <>
2040
+ <CheckBox
2041
+ value={config.exclusions.active}
2042
+ section='exclusions'
2043
+ fieldName='active'
2044
+ label={'Exclude one or more values'}
2045
+ updateField={updateField}
2046
+ tooltip={
2047
+ <Tooltip style={{ textTransform: 'none' }}>
2048
+ <Tooltip.Target>
2049
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2050
+ </Tooltip.Target>
2051
+ <Tooltip.Content>
2052
+ <p>When this option is checked, you can select values for exclusion from the pie segments.</p>
2053
+ </Tooltip.Content>
2054
+ </Tooltip>
2055
+ }
2056
+ />
2057
+ {config.exclusions.active && (
2058
+ <>
2059
+ {config.exclusions.keys.length > 0 && (
2060
+ <>
2061
+ <fieldset>
2062
+ <legend className='edit-label'>Excluded Keys</legend>
2063
+ </fieldset>
2064
+ <ExclusionsList />
2065
+ </>
2066
+ )}
2067
+
2068
+ <Select
2069
+ fieldName='visualizationType'
2070
+ label='Add Exclusion'
2071
+ initial='Select'
2072
+ onChange={e => {
2073
+ if (e.target.value !== '' && e.target.value !== 'Select') {
2074
+ addNewExclusion(e.target.value)
2075
+ }
2076
+ e.target.value = ''
2077
+ }}
2078
+ options={getDataValues(config.xAxis.dataKey, true)}
2079
+ />
2080
+ </>
2081
+ )}
2082
+ </>
2083
+ )}
2084
+
2085
+ {/* anchors */}
2086
+ {visHasAnchors() && config.orientation !== 'horizontal' && (
2087
+ <div className='edit-block'>
2088
+ <span className='edit-label column-heading'>Anchors</span>
2089
+ <Accordion allowZeroExpanded>
2090
+ {config.xAxis?.anchors?.map((anchor, index) => (
2091
+ <AccordionItem className='series-item series-item--chart' key={`xaxis-anchors-2-${index}`}>
2092
+ <AccordionItemHeading className='series-item__title'>
2093
+ <>
2094
+ <AccordionItemButton className={'accordion__button accordion__button'}>
2095
+ Anchor {index + 1}
2096
+ <button
2097
+ className='series-list__remove'
2098
+ onClick={e => {
2112
2099
  e.preventDefault()
2113
- const copiedAnchors = [...config.xAxis.anchors]
2114
- copiedAnchors[index].color = e.target.value
2100
+ const copiedAnchorGroups = [...config.xAxis.anchors]
2101
+ copiedAnchorGroups.splice(index, 1)
2115
2102
  updateConfig({
2116
2103
  ...config,
2117
2104
  xAxis: {
2118
2105
  ...config.xAxis,
2119
- anchors: copiedAnchors
2120
- }
2121
- })
2122
- }}
2123
- />
2124
- </label>
2125
-
2126
- <label>
2127
- Anchor Line Style
2128
- <select
2129
- value={config.xAxis.anchors[index].lineStyle || ''}
2130
- onChange={e => {
2131
- const copiedAnchors = [...config.xAxis.anchors]
2132
- copiedAnchors[index].lineStyle = e.target.value
2133
- updateConfig({
2134
- ...config,
2135
- xAxis: {
2136
- ...config.xAxis,
2137
- anchors: copiedAnchors
2106
+ anchors: copiedAnchorGroups
2138
2107
  }
2139
2108
  })
2140
2109
  }}
2141
2110
  >
2142
- <option>Select</option>
2143
- {lineOptions.map(line => (
2144
- <option key={line.key}>{line.value}</option>
2145
- ))}
2146
- </select>
2147
- </label>
2148
- </AccordionItemPanel>
2149
- </AccordionItem>
2150
- ))}
2151
- </Accordion>
2152
-
2153
- <button
2154
- className='btn full-width'
2155
- onClick={e => {
2156
- e.preventDefault()
2157
- const anchors = [...config.xAxis.anchors]
2158
- anchors.push({} as Anchor)
2159
- updateConfig({
2160
- ...config,
2161
- xAxis: {
2162
- ...config.xAxis,
2163
- anchors
2164
- }
2165
- })
2166
- }}
2167
- >
2168
- Add Anchor
2169
- </button>
2170
- </div>
2171
- )}
2111
+ Remove
2112
+ </button>
2113
+ </AccordionItemButton>
2114
+ </>
2115
+ </AccordionItemHeading>
2116
+ <AccordionItemPanel>
2117
+ <label>
2118
+ <span>Anchor Value</span>
2119
+ <Tooltip style={{ textTransform: 'none' }}>
2120
+ <Tooltip.Target>
2121
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2122
+ </Tooltip.Target>
2123
+ <Tooltip.Content>
2124
+ <p>Enter the value as its shown in the data column</p>
2125
+ </Tooltip.Content>
2126
+ </Tooltip>
2127
+ <input
2128
+ type='text'
2129
+ value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
2130
+ onChange={e => {
2131
+ e.preventDefault()
2132
+ const copiedAnchors = [...config.xAxis.anchors]
2133
+ copiedAnchors[index].value = e.target.value
2134
+ updateConfig({
2135
+ ...config,
2136
+ xAxis: {
2137
+ ...config.xAxis,
2138
+ anchors: copiedAnchors
2139
+ }
2140
+ })
2141
+ }}
2142
+ />
2143
+ </label>
2172
2144
 
2173
- {visHasAnchors() && config.orientation === 'horizontal' && (
2174
- <div className='edit-block'>
2175
- <span className='edit-label column-heading'>Anchors</span>
2176
- <Accordion allowZeroExpanded>
2177
- {config.yAxis?.anchors?.map((anchor, index) => (
2178
- <AccordionItem className='series-item series-item--chart' key={`accordion-yaxis-anchors-${index}`}>
2179
- <AccordionItemHeading className='series-item__title'>
2180
- <>
2181
- <AccordionItemButton className={'accordion__button accordion__button'}>
2182
- Anchor {index + 1}
2183
- <button
2184
- className='series-list__remove'
2185
- onClick={e => {
2186
- e.preventDefault()
2187
- const copiedAnchorGroups = [...config.yAxis.anchors]
2188
- copiedAnchorGroups.splice(index, 1)
2189
- updateConfig({
2190
- ...config,
2191
- yAxis: {
2192
- ...config.yAxis,
2193
- anchors: copiedAnchorGroups
2194
- }
2195
- })
2196
- }}
2197
- >
2198
- Remove
2199
- </button>
2200
- </AccordionItemButton>
2201
- </>
2202
- </AccordionItemHeading>
2203
- <AccordionItemPanel>
2204
- <label>
2205
- <span>Anchor Value</span>
2206
- <Tooltip style={{ textTransform: 'none' }}>
2207
- <Tooltip.Target>
2208
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2209
- </Tooltip.Target>
2210
- <Tooltip.Content>
2211
- <p>Enter the value as its shown in the data column</p>
2212
- </Tooltip.Content>
2213
- </Tooltip>
2214
- <input
2215
- type='text'
2216
- value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
2217
- onChange={e => {
2145
+ <label>
2146
+ <span>Anchor Color</span>
2147
+ <input
2148
+ type='text'
2149
+ value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
2150
+ onChange={e => {
2151
+ e.preventDefault()
2152
+ const copiedAnchors = [...config.xAxis.anchors]
2153
+ copiedAnchors[index].color = e.target.value
2154
+ updateConfig({
2155
+ ...config,
2156
+ xAxis: {
2157
+ ...config.xAxis,
2158
+ anchors: copiedAnchors
2159
+ }
2160
+ })
2161
+ }}
2162
+ />
2163
+ </label>
2164
+
2165
+ <label>
2166
+ Anchor Line Style
2167
+ <select
2168
+ value={config.xAxis.anchors[index].lineStyle || ''}
2169
+ onChange={e => {
2170
+ const copiedAnchors = [...config.xAxis.anchors]
2171
+ copiedAnchors[index].lineStyle = e.target.value
2172
+ updateConfig({
2173
+ ...config,
2174
+ xAxis: {
2175
+ ...config.xAxis,
2176
+ anchors: copiedAnchors
2177
+ }
2178
+ })
2179
+ }}
2180
+ >
2181
+ <option>Select</option>
2182
+ {lineOptions.map(line => (
2183
+ <option key={line.key}>{line.value}</option>
2184
+ ))}
2185
+ </select>
2186
+ </label>
2187
+ </AccordionItemPanel>
2188
+ </AccordionItem>
2189
+ ))}
2190
+ </Accordion>
2191
+
2192
+ <button
2193
+ className='btn full-width'
2194
+ onClick={e => {
2195
+ e.preventDefault()
2196
+ const anchors = [...config.xAxis.anchors]
2197
+ anchors.push({} as Anchor)
2198
+ updateConfig({
2199
+ ...config,
2200
+ xAxis: {
2201
+ ...config.xAxis,
2202
+ anchors
2203
+ }
2204
+ })
2205
+ }}
2206
+ >
2207
+ Add Anchor
2208
+ </button>
2209
+ </div>
2210
+ )}
2211
+
2212
+ {visHasAnchors() && config.orientation === 'horizontal' && (
2213
+ <div className='edit-block'>
2214
+ <span className='edit-label column-heading'>Anchors</span>
2215
+ <Accordion allowZeroExpanded>
2216
+ {config.yAxis?.anchors?.map((anchor, index) => (
2217
+ <AccordionItem className='series-item series-item--chart' key={`accordion-yaxis-anchors-${index}`}>
2218
+ <AccordionItemHeading className='series-item__title'>
2219
+ <>
2220
+ <AccordionItemButton className={'accordion__button accordion__button'}>
2221
+ Anchor {index + 1}
2222
+ <button
2223
+ className='series-list__remove'
2224
+ onClick={e => {
2218
2225
  e.preventDefault()
2219
- const copiedAnchors = [...config.yAxis.anchors]
2220
- copiedAnchors[index].value = e.target.value
2226
+ const copiedAnchorGroups = [...config.yAxis.anchors]
2227
+ copiedAnchorGroups.splice(index, 1)
2221
2228
  updateConfig({
2222
2229
  ...config,
2223
2230
  yAxis: {
2224
2231
  ...config.yAxis,
2225
- anchors: copiedAnchors
2232
+ anchors: copiedAnchorGroups
2226
2233
  }
2227
2234
  })
2228
2235
  }}
2229
- />
2230
- </label>
2236
+ >
2237
+ Remove
2238
+ </button>
2239
+ </AccordionItemButton>
2240
+ </>
2241
+ </AccordionItemHeading>
2242
+ <AccordionItemPanel>
2243
+ <label>
2244
+ <span>Anchor Value</span>
2245
+ <Tooltip style={{ textTransform: 'none' }}>
2246
+ <Tooltip.Target>
2247
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2248
+ </Tooltip.Target>
2249
+ <Tooltip.Content>
2250
+ <p>Enter the value as its shown in the data column</p>
2251
+ </Tooltip.Content>
2252
+ </Tooltip>
2253
+ <input
2254
+ type='text'
2255
+ value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
2256
+ onChange={e => {
2257
+ e.preventDefault()
2258
+ const copiedAnchors = [...config.yAxis.anchors]
2259
+ copiedAnchors[index].value = e.target.value
2260
+ updateConfig({
2261
+ ...config,
2262
+ yAxis: {
2263
+ ...config.yAxis,
2264
+ anchors: copiedAnchors
2265
+ }
2266
+ })
2267
+ }}
2268
+ />
2269
+ </label>
2231
2270
 
2232
- <label>
2233
- <span>Anchor Color</span>
2271
+ <label>
2272
+ <span>Anchor Color</span>
2273
+ <input
2274
+ type='text'
2275
+ value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
2276
+ onChange={e => {
2277
+ e.preventDefault()
2278
+ const copiedAnchors = [...config.yAxis.anchors]
2279
+ copiedAnchors[index].color = e.target.value
2280
+ updateConfig({
2281
+ ...config,
2282
+ yAxis: {
2283
+ ...config.yAxis,
2284
+ anchors: copiedAnchors
2285
+ }
2286
+ })
2287
+ }}
2288
+ />
2289
+ </label>
2290
+
2291
+ <label>
2292
+ Anchor Line Style
2293
+ <select
2294
+ value={config.yAxis.anchors[index].lineStyle || ''}
2295
+ onChange={e => {
2296
+ const copiedAnchors = [...config.yAxis.anchors]
2297
+ copiedAnchors[index].lineStyle = e.target.value
2298
+ updateConfig({
2299
+ ...config,
2300
+ yAxis: {
2301
+ ...config.yAxis,
2302
+ anchors: copiedAnchors
2303
+ }
2304
+ })
2305
+ }}
2306
+ >
2307
+ <option>Select</option>
2308
+ {lineOptions.map(line => (
2309
+ <option key={line.key}>{line.value}</option>
2310
+ ))}
2311
+ </select>
2312
+ </label>
2313
+ </AccordionItemPanel>
2314
+ </AccordionItem>
2315
+ ))}
2316
+ </Accordion>
2317
+
2318
+ <button
2319
+ className='btn full-width'
2320
+ onClick={e => {
2321
+ e.preventDefault()
2322
+ const anchors = [...config.yAxis.anchors]
2323
+ anchors.push({} as Anchor)
2324
+ updateConfig({
2325
+ ...config,
2326
+ yAxis: {
2327
+ ...config.yAxis,
2328
+ anchors
2329
+ }
2330
+ })
2331
+ }}
2332
+ >
2333
+ Add Anchor
2334
+ </button>
2335
+ </div>
2336
+ )}
2337
+ </AccordionItemPanel>
2338
+ </AccordionItem>
2339
+ )}
2340
+ <Panels.Regions name='Regions' />
2341
+ {/* Columns */}
2342
+ {config.visualizationType !== 'Box Plot' && (
2343
+ <AccordionItem>
2344
+ <AccordionItemHeading>
2345
+ <AccordionItemButton>Columns</AccordionItemButton>
2346
+ </AccordionItemHeading>
2347
+ <AccordionItemPanel>
2348
+ {'navigation' !== config.type && (
2349
+ <fieldset className='primary-fieldset edit-block'>
2350
+ <label>
2351
+ <span className='edit-label'>
2352
+ Additional Columns
2353
+ <Tooltip style={{ textTransform: 'none' }}>
2354
+ <Tooltip.Target>
2355
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2356
+ </Tooltip.Target>
2357
+ <Tooltip.Content>
2358
+ <p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
2359
+ </Tooltip.Content>
2360
+ </Tooltip>
2361
+ </span>
2362
+ </label>
2363
+ {additionalColumns.map(val => (
2364
+ <fieldset className='edit-block' key={val}>
2365
+ <button
2366
+ className='remove-column'
2367
+ onClick={event => {
2368
+ event.preventDefault()
2369
+ removeAdditionalColumn(val)
2370
+ }}
2371
+ >
2372
+ Remove
2373
+ </button>
2374
+ <label>
2375
+ <span className='edit-label column-heading'>Column</span>
2376
+ <select
2377
+ value={config.columns[val] ? config.columns[val].name : getColumns()[0]}
2378
+ onChange={event => {
2379
+ editColumn(val, 'name', event.target.value)
2380
+ }}
2381
+ >
2382
+ {getColumns().map(option => (
2383
+ <option>{option}</option>
2384
+ ))}
2385
+ </select>
2386
+ </label>
2387
+ <label>
2388
+ <span className='edit-label column-heading'>Associate to Series</span>
2389
+ <select
2390
+ value={config.columns[val] ? config.columns[val].series : ''}
2391
+ onChange={event => {
2392
+ editColumn(val, 'series', event.target.value)
2393
+ }}
2394
+ >
2395
+ <option value=''>Select series</option>
2396
+ {config.series.map(series => (
2397
+ <option>{series.dataKey}</option>
2398
+ ))}
2399
+ </select>
2400
+ </label>
2401
+ <TextField value={config.columns[val].label} section='columns' subsection={val} fieldName='label' label='Label' updateField={updateField} />
2402
+ <ul className='column-edit'>
2403
+ <li className='three-col'>
2404
+ <TextField value={config.columns[val].prefix} section='columns' subsection={val} fieldName='prefix' label='Prefix' updateField={updateField} />
2405
+ <TextField value={config.columns[val].suffix} section='columns' subsection={val} fieldName='suffix' label='Suffix' updateField={updateField} />
2406
+ <TextField type='number' value={config.columns[val].roundToPlace} section='columns' subsection={val} fieldName='roundToPlace' label='Round' updateField={updateField} />
2407
+ </li>
2408
+ <li>
2409
+ <label className='checkbox'>
2410
+ <input
2411
+ type='checkbox'
2412
+ checked={config.columns[val].commas}
2413
+ onChange={event => {
2414
+ editColumn(val, 'commas', event.target.checked)
2415
+ }}
2416
+ />
2417
+ <span className='edit-label'>Add Commas to Numbers</span>
2418
+ </label>
2419
+ </li>
2420
+ <li>
2421
+ {config.table.showVertical && (
2422
+ <label className='checkbox'>
2234
2423
  <input
2235
- type='text'
2236
- value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
2237
- onChange={e => {
2238
- e.preventDefault()
2239
- const copiedAnchors = [...config.yAxis.anchors]
2240
- copiedAnchors[index].color = e.target.value
2241
- updateConfig({
2242
- ...config,
2243
- yAxis: {
2244
- ...config.yAxis,
2245
- anchors: copiedAnchors
2246
- }
2247
- })
2424
+ type='checkbox'
2425
+ checked={config.columns[val].dataTable}
2426
+ onChange={event => {
2427
+ editColumn(val, 'dataTable', event.target.checked)
2248
2428
  }}
2249
2429
  />
2430
+ <span className='edit-label'>Show in Data Table</span>
2250
2431
  </label>
2251
-
2252
- <label>
2253
- Anchor Line Style
2254
- <select
2255
- value={config.yAxis.anchors[index].lineStyle || ''}
2256
- onChange={e => {
2257
- const copiedAnchors = [...config.yAxis.anchors]
2258
- copiedAnchors[index].lineStyle = e.target.value
2259
- updateConfig({
2260
- ...config,
2261
- yAxis: {
2262
- ...config.yAxis,
2263
- anchors: copiedAnchors
2264
- }
2265
- })
2266
- }}
2267
- >
2268
- <option>Select</option>
2269
- {lineOptions.map(line => (
2270
- <option key={line.key}>{line.value}</option>
2271
- ))}
2272
- </select>
2273
- </label>
2274
- </AccordionItemPanel>
2275
- </AccordionItem>
2276
- ))}
2277
- </Accordion>
2278
-
2279
- <button
2280
- className='btn full-width'
2281
- onClick={e => {
2282
- e.preventDefault()
2283
- const anchors = [...config.yAxis.anchors]
2284
- anchors.push({} as Anchor)
2285
- updateConfig({
2286
- ...config,
2287
- yAxis: {
2288
- ...config.yAxis,
2289
- anchors
2290
- }
2291
- })
2292
- }}
2293
- >
2294
- Add Anchor
2295
- </button>
2296
- </div>
2297
- )}
2298
- </AccordionItemPanel>
2299
- </AccordionItem>
2300
- )}
2301
- <Panels.Regions name='Regions' />
2302
- {/* Columns */}
2303
- {config.visualizationType !== 'Box Plot' && (
2304
- <AccordionItem>
2305
- <AccordionItemHeading>
2306
- <AccordionItemButton>Columns</AccordionItemButton>
2307
- </AccordionItemHeading>
2308
- <AccordionItemPanel>
2309
- {'navigation' !== config.type && (
2310
- <fieldset className='primary-fieldset edit-block'>
2311
- <label>
2312
- <span className='edit-label'>
2313
- Additional Columns
2314
- <Tooltip style={{ textTransform: 'none' }}>
2315
- <Tooltip.Target>
2316
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2317
- </Tooltip.Target>
2318
- <Tooltip.Content>
2319
- <p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
2320
- </Tooltip.Content>
2321
- </Tooltip>
2322
- </span>
2323
- </label>
2324
- {additionalColumns.map(val => (
2325
- <fieldset className='edit-block' key={val}>
2326
- <button
2327
- className='remove-column'
2328
- onClick={event => {
2329
- event.preventDefault()
2330
- removeAdditionalColumn(val)
2331
- }}
2332
- >
2333
- Remove
2334
- </button>
2335
- <label>
2336
- <span className='edit-label column-heading'>Column</span>
2337
- <select
2338
- value={config.columns[val] ? config.columns[val].name : getColumns()[0]}
2339
- onChange={event => {
2340
- editColumn(val, 'name', event.target.value)
2341
- }}
2342
- >
2343
- {getColumns().map(option => (
2344
- <option>{option}</option>
2345
- ))}
2346
- </select>
2347
- </label>
2348
- <label>
2349
- <span className='edit-label column-heading'>Associate to Series</span>
2350
- <select
2351
- value={config.columns[val] ? config.columns[val].series : ''}
2352
- onChange={event => {
2353
- editColumn(val, 'series', event.target.value)
2354
- }}
2355
- >
2356
- <option value=''>Select series</option>
2357
- {config.series.map(series => (
2358
- <option>{series.dataKey}</option>
2359
- ))}
2360
- </select>
2361
- </label>
2362
- <TextField value={config.columns[val].label} section='columns' subsection={val} fieldName='label' label='Label' updateField={updateField} />
2363
- <ul className='column-edit'>
2364
- <li className='three-col'>
2365
- <TextField value={config.columns[val].prefix} section='columns' subsection={val} fieldName='prefix' label='Prefix' updateField={updateField} />
2366
- <TextField value={config.columns[val].suffix} section='columns' subsection={val} fieldName='suffix' label='Suffix' updateField={updateField} />
2367
- <TextField type='number' value={config.columns[val].roundToPlace} section='columns' subsection={val} fieldName='roundToPlace' label='Round' updateField={updateField} />
2368
- </li>
2432
+ )}
2433
+ </li>
2434
+ {config.visualizationType === 'Pie' && (
2369
2435
  <li>
2370
2436
  <label className='checkbox'>
2371
2437
  <input
2372
2438
  type='checkbox'
2373
- checked={config.columns[val].commas}
2439
+ checked={config.columns[val].showInViz}
2374
2440
  onChange={event => {
2375
- editColumn(val, 'commas', event.target.checked)
2441
+ editColumn(val, 'showInViz', event.target.checked)
2376
2442
  }}
2377
2443
  />
2378
- <span className='edit-label'>Add Commas to Numbers</span>
2444
+ <span className='edit-label'>Show in Visualization</span>
2379
2445
  </label>
2380
2446
  </li>
2381
- <li>
2382
- {config.table.showVertical && (
2447
+ )}
2448
+
2449
+ {/* disable for now */}
2450
+
2451
+ <li>
2452
+ <label className='checkbox'>
2453
+ <input
2454
+ type='checkbox'
2455
+ checked={config.columns[val].tooltips || false}
2456
+ onChange={event => {
2457
+ updateSeriesTooltip(val, event.target.checked)
2458
+ }}
2459
+ />
2460
+ <span className='edit-label'>Show in tooltip</span>
2461
+ </label>
2462
+ </li>
2463
+
2464
+ {config.visualizationType === 'Forest Plot' && (
2465
+ <>
2466
+ <li>
2383
2467
  <label className='checkbox'>
2384
2468
  <input
2385
2469
  type='checkbox'
2386
- checked={config.columns[val].dataTable}
2470
+ checked={config.columns[val].forestPlot || false}
2387
2471
  onChange={event => {
2388
- editColumn(val, 'dataTable', event.target.checked)
2472
+ editColumn(val, 'forestPlot', event.target.checked)
2389
2473
  }}
2390
2474
  />
2391
- <span className='edit-label'>Show in Data Table</span>
2475
+ <span className='edit-label'>Show in Forest Plot</span>
2392
2476
  </label>
2393
- )}
2394
- </li>
2395
- {config.visualizationType === 'Pie' && (
2477
+ </li>
2396
2478
  <li>
2397
2479
  <label className='checkbox'>
2398
2480
  <input
2399
2481
  type='checkbox'
2400
- checked={config.columns[val].showInViz}
2482
+ checked={config.columns[val].forestPlotAlignRight || false}
2401
2483
  onChange={event => {
2402
- editColumn(val, 'showInViz', event.target.checked)
2484
+ editColumn(val, 'forestPlotAlignRight', event.target.checked)
2403
2485
  }}
2404
2486
  />
2405
- <span className='edit-label'>Show in Visualization</span>
2487
+ <span className='edit-label'>Align Right</span>
2406
2488
  </label>
2407
2489
  </li>
2408
- )}
2409
-
2410
- {/* disable for now */}
2411
-
2412
- <li>
2413
- <label className='checkbox'>
2414
- <input
2415
- type='checkbox'
2416
- checked={config.columns[val].tooltips || false}
2417
- onChange={event => {
2418
- updateSeriesTooltip(val, event.target.checked)
2419
- }}
2420
- />
2421
- <span className='edit-label'>Show in tooltip</span>
2422
- </label>
2423
- </li>
2424
2490
 
2425
- {config.visualizationType === 'Forest Plot' && (
2426
- <>
2427
- <li>
2428
- <label className='checkbox'>
2429
- <input
2430
- type='checkbox'
2431
- checked={config.columns[val].forestPlot || false}
2432
- onChange={event => {
2433
- editColumn(val, 'forestPlot', event.target.checked)
2434
- }}
2435
- />
2436
- <span className='edit-label'>Show in Forest Plot</span>
2437
- </label>
2438
- </li>
2491
+ {!config.columns[val].forestPlotAlignRight && (
2439
2492
  <li>
2440
- <label className='checkbox'>
2493
+ <label className='text'>
2494
+ <span className='edit-label'>Forest Plot Starting Point</span>
2441
2495
  <input
2442
- type='checkbox'
2443
- checked={config.columns[val].forestPlotAlignRight || false}
2496
+ type='number'
2497
+ value={config.columns[val].forestPlotStartingPoint || 0}
2444
2498
  onChange={event => {
2445
- editColumn(val, 'forestPlotAlignRight', event.target.checked)
2499
+ editColumn(val, 'forestPlotStartingPoint', event.target.value)
2446
2500
  }}
2447
2501
  />
2448
- <span className='edit-label'>Align Right</span>
2449
2502
  </label>
2450
2503
  </li>
2451
-
2452
- {!config.columns[val].forestPlotAlignRight && (
2453
- <li>
2454
- <label className='text'>
2455
- <span className='edit-label'>Forest Plot Starting Point</span>
2456
- <input
2457
- type='number'
2458
- value={config.columns[val].forestPlotStartingPoint || 0}
2459
- onChange={event => {
2460
- editColumn(val, 'forestPlotStartingPoint', event.target.value)
2461
- }}
2462
- />
2463
- </label>
2464
- </li>
2465
- )}
2466
- </>
2467
- )}
2468
- </ul>
2504
+ )}
2505
+ </>
2506
+ )}
2507
+ </ul>
2508
+ </fieldset>
2509
+ ))}
2510
+ <button
2511
+ className={'btn full-width'}
2512
+ onClick={event => {
2513
+ event.preventDefault()
2514
+ addAdditionalColumn(additionalColumns.length + 1)
2515
+ }}
2516
+ >
2517
+ Add Column
2518
+ </button>
2519
+ </fieldset>
2520
+ )}
2521
+ {'category' === config.legend.type && (
2522
+ <fieldset className='primary-fieldset edit-block'>
2523
+ <label>
2524
+ <span className='edit-label'>
2525
+ Additional Category
2526
+ <Tooltip style={{ textTransform: 'none' }}>
2527
+ <Tooltip.Target>
2528
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2529
+ </Tooltip.Target>
2530
+ <Tooltip.Content>
2531
+ <p>You can provide additional categories to ensure they appear in the legend</p>
2532
+ </Tooltip.Content>
2533
+ </Tooltip>
2534
+ </span>
2535
+ </label>
2536
+ {config.legend.additionalCategories &&
2537
+ config.legend.additionalCategories.map((val, i) => (
2538
+ <fieldset className='edit-block' key={val}>
2539
+ <button
2540
+ className='remove-column'
2541
+ onClick={event => {
2542
+ event.preventDefault()
2543
+ const updatedAdditionaCategories = [...config.legend.additionalCategories]
2544
+ updatedAdditionaCategories.splice(i, 1)
2545
+ updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
2546
+ }}
2547
+ >
2548
+ Remove
2549
+ </button>
2550
+ <TextField
2551
+ value={val}
2552
+ label='Category'
2553
+ section='legend'
2554
+ subsection={null}
2555
+ fieldName='additionalCategories'
2556
+ updateField={(section, subsection, fieldName, value) => {
2557
+ const updatedAdditionaCategories = [...config.legend.additionalCategories]
2558
+ updatedAdditionaCategories[i] = value
2559
+ updateField(section, subsection, fieldName, updatedAdditionaCategories)
2560
+ }}
2561
+ />
2469
2562
  </fieldset>
2470
2563
  ))}
2471
- <button
2472
- className={'btn full-width'}
2473
- onClick={event => {
2474
- event.preventDefault()
2475
- addAdditionalColumn(additionalColumns.length + 1)
2476
- }}
2477
- >
2478
- Add Column
2479
- </button>
2480
- </fieldset>
2481
- )}
2482
- {'category' === config.legend.type && (
2483
- <fieldset className='primary-fieldset edit-block'>
2484
- <label>
2485
- <span className='edit-label'>
2486
- Additional Category
2487
- <Tooltip style={{ textTransform: 'none' }}>
2488
- <Tooltip.Target>
2489
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2490
- </Tooltip.Target>
2491
- <Tooltip.Content>
2492
- <p>You can provide additional categories to ensure they appear in the legend</p>
2493
- </Tooltip.Content>
2494
- </Tooltip>
2495
- </span>
2496
- </label>
2497
- {config.legend.additionalCategories &&
2498
- config.legend.additionalCategories.map((val, i) => (
2499
- <fieldset className='edit-block' key={val}>
2500
- <button
2501
- className='remove-column'
2502
- onClick={event => {
2503
- event.preventDefault()
2504
- const updatedAdditionaCategories = [...config.legend.additionalCategories]
2505
- updatedAdditionaCategories.splice(i, 1)
2506
- updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
2507
- }}
2508
- >
2509
- Remove
2510
- </button>
2511
- <TextField
2512
- value={val}
2513
- label='Category'
2514
- section='legend'
2515
- subsection={null}
2516
- fieldName='additionalCategories'
2517
- updateField={(section, subsection, fieldName, value) => {
2518
- const updatedAdditionaCategories = [...config.legend.additionalCategories]
2519
- updatedAdditionaCategories[i] = value
2520
- updateField(section, subsection, fieldName, updatedAdditionaCategories)
2521
- }}
2522
- />
2523
- </fieldset>
2524
- ))}
2525
- <button
2526
- className={'btn full-width'}
2527
- onClick={event => {
2528
- event.preventDefault()
2529
- const updatedAdditionaCategories = [...(config.legend.additionalCategories || [])]
2530
- updatedAdditionaCategories.push('')
2531
- updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
2532
- }}
2533
- >
2534
- Add Category
2535
- </button>
2536
- </fieldset>
2537
- )}
2538
- </AccordionItemPanel>
2539
- </AccordionItem>
2540
- )}
2541
- {/* End Columns */}
2542
- {visHasLegend() && (
2543
- <AccordionItem>
2544
- <AccordionItemHeading>
2545
- <AccordionItemButton>Legend</AccordionItemButton>
2546
- </AccordionItemHeading>
2547
- <AccordionItemPanel>
2548
- <CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
2549
- {/* <fieldset className="checkbox-group">
2564
+ <button
2565
+ className={'btn full-width'}
2566
+ onClick={event => {
2567
+ event.preventDefault()
2568
+ const updatedAdditionaCategories = [...(config.legend.additionalCategories || [])]
2569
+ updatedAdditionaCategories.push('')
2570
+ updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
2571
+ }}
2572
+ >
2573
+ Add Category
2574
+ </button>
2575
+ </fieldset>
2576
+ )}
2577
+ </AccordionItemPanel>
2578
+ </AccordionItem>
2579
+ )}
2580
+ {/* End Columns */}
2581
+ {visHasLegend() && (
2582
+ <AccordionItem>
2583
+ <AccordionItemHeading>
2584
+ <AccordionItemButton>Legend</AccordionItemButton>
2585
+ </AccordionItemHeading>
2586
+ <AccordionItemPanel>
2587
+ <CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
2588
+ {/* <fieldset className="checkbox-group">
2550
2589
  <CheckBox value={config.legend.dynamicLegend} section="legend" fieldName="dynamicLegend" label="Dynamic Legend" updateField={updateField}/>
2551
2590
  {config.legend.dynamicLegend && (
2552
2591
  <>
@@ -2557,57 +2596,128 @@ const EditorPanel = () => {
2557
2596
  </>
2558
2597
  )}
2559
2598
  </fieldset> */}
2560
- <CheckBox
2561
- value={config.legend.hide ? true : false}
2562
- section='legend'
2563
- fieldName='hide'
2564
- label='Hide Legend'
2565
- updateField={updateField}
2566
- tooltip={
2567
- <Tooltip style={{ textTransform: 'none' }}>
2568
- <Tooltip.Target>
2569
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2570
- </Tooltip.Target>
2571
- <Tooltip.Content>
2572
- <p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
2573
- </Tooltip.Content>
2574
- </Tooltip>
2575
- }
2576
- />
2577
- {/* {config.visualizationType === 'Box Plot' &&
2599
+ <CheckBox
2600
+ value={config.legend.hide ? true : false}
2601
+ section='legend'
2602
+ fieldName='hide'
2603
+ label='Hide Legend'
2604
+ updateField={updateField}
2605
+ tooltip={
2606
+ <Tooltip style={{ textTransform: 'none' }}>
2607
+ <Tooltip.Target>
2608
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2609
+ </Tooltip.Target>
2610
+ <Tooltip.Content>
2611
+ <p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
2612
+ </Tooltip.Content>
2613
+ </Tooltip>
2614
+ }
2615
+ />
2616
+ {/* {config.visualizationType === 'Box Plot' &&
2578
2617
  <>
2579
2618
  <CheckBox value={config.boxplot.legend.displayHowToReadText} fieldName='displayHowToReadText' section='boxplot' subsection='legend' label='Display How To Read Text' updateField={updateField} />
2580
2619
  <TextField type='textarea' value={config.boxplot.legend.howToReadText} updateField={updateField} fieldName='howToReadText' section='boxplot' subsection='legend' label='How to read text' />
2581
2620
  </>
2582
2621
  } */}
2583
- {config.visualizationType === 'Line' && <CheckBox value={config.legend.lineMode} section='legend' fieldName='lineMode' label='Show Lined Style Legend' updateField={updateField} />}
2584
- {config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
2585
- <Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
2586
- )}
2587
- <Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={updateField} options={['highlight', 'isolate']} />
2588
- {config.legend.behavior === 'highlight' && config.tooltips.singleSeries && <CheckBox value={config.legend.highlightOnHover} section='legend' fieldName='highlightOnHover' label='HIGHLIGHT DATA SERIES ON HOVER' updateField={updateField} />}
2589
- <TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
2590
- <Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
2591
- {config.legend.position === 'bottom' && (
2592
- <>
2593
- <CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />
2594
- <CheckBox value={config.legend.verticalSorted} section='legend' fieldName='verticalSorted' label='Vertical sorted Legend' updateField={updateField} />
2595
- </>
2596
- )}
2597
- <TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
2598
- </AccordionItemPanel>
2599
- </AccordionItem>
2600
- )}
2601
- {visSupportsFilters() && (
2602
- <AccordionItem>
2603
- <AccordionItemHeading>
2604
- <AccordionItemButton>Filters</AccordionItemButton>
2605
- </AccordionItemHeading>
2606
- <AccordionItemPanel>
2607
- {config.filters && (
2608
- <>
2609
- {/* prettier-ignore */}
2610
- <Select
2622
+ {config.visualizationType === 'Line' && <CheckBox value={config.legend.lineMode} section='legend' fieldName='lineMode' label='Show Lined Style Legend' updateField={updateField} />}
2623
+ {config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
2624
+ <Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
2625
+ )}
2626
+ <Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={(...[section, , fieldName, value]) => updateBehavior(section, fieldName, value)} options={['highlight', 'isolate']} />
2627
+ {visHasLegendAxisAlign() && <CheckBox value={config.legend.axisAlign} fieldName='axisAlign' section='legend' label='Align to Axis on Isolate' updateField={updateField} />}
2628
+
2629
+ {config.legend.behavior === 'highlight' && config.tooltips.singleSeries && <CheckBox value={config.legend.highlightOnHover} section='legend' fieldName='highlightOnHover' label='HIGHLIGHT DATA SERIES ON HOVER' updateField={updateField} />}
2630
+
2631
+ {/* start: isolated values */}
2632
+ {visHasSelectableLegendValues && config.legend.behavior === 'isolate' && !colorCodeByCategory && (
2633
+ <fieldset className='primary-fieldset edit-block' key={'additional-highlight-values'}>
2634
+ <label>
2635
+ <span className='edit-label'>
2636
+ Isolate Data Series
2637
+ <Tooltip style={{ textTransform: 'none' }}>
2638
+ <Tooltip.Target>
2639
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2640
+ </Tooltip.Target>
2641
+ <Tooltip.Content>
2642
+ <p>You can choose data series that are shown on load. Others will be added when the user clicks on them in the legend.</p>
2643
+ </Tooltip.Content>
2644
+ </Tooltip>
2645
+ </span>
2646
+ </label>
2647
+ {config.legend.seriesHighlight &&
2648
+ config.legend.seriesHighlight.map((val, i) => (
2649
+ <fieldset className='edit-block' key={`${val}-${i}`}>
2650
+ <button
2651
+ className='remove-column'
2652
+ onClick={event => {
2653
+ event.preventDefault()
2654
+ const updatedSeriesHighlight = [...config.legend.seriesHighlight]
2655
+ updatedSeriesHighlight.splice(i, 1)
2656
+ updateField('legend', null, 'seriesHighlight', updatedSeriesHighlight)
2657
+ if (!updatedSeriesHighlight.length) {
2658
+ highlightReset()
2659
+ }
2660
+ }}
2661
+ >
2662
+ Remove
2663
+ </button>
2664
+ <Select
2665
+ value={config.legend.seriesHighlight[i]}
2666
+ fieldName='seriesHighlight'
2667
+ label='Isolate Value'
2668
+ onChange={e => {
2669
+ const updatedSeriesHighlight = [...config.legend.seriesHighlight]
2670
+ if (!updatedSeriesHighlight.includes(e.target.value)) {
2671
+ updatedSeriesHighlight[i] = e.target.value
2672
+ updateSeriesIsolateValues([...updatedSeriesHighlight])
2673
+ }
2674
+ }}
2675
+ options={getLegendColumns()}
2676
+ />
2677
+ </fieldset>
2678
+ ))}
2679
+ <button
2680
+ className={'btn full-width'}
2681
+ onClick={event => {
2682
+ event.preventDefault()
2683
+ const legendColumns = getLegendColumns()
2684
+ const updatedSeriesHighlight = [...config.legend.seriesHighlight]
2685
+ const seriesLength = updatedSeriesHighlight.length
2686
+ if (seriesLength < legendColumns.length) {
2687
+ const [newSeriesHighlight] = legendColumns.filter(d => !updatedSeriesHighlight.includes(d))
2688
+ updatedSeriesHighlight.push(newSeriesHighlight)
2689
+ updateSeriesIsolateValues([...updatedSeriesHighlight])
2690
+ }
2691
+ }}
2692
+ >
2693
+ Add Isolate Value
2694
+ </button>
2695
+ </fieldset>
2696
+ )}
2697
+ {/* end: isolated values */}
2698
+
2699
+ <TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
2700
+ <Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
2701
+ {config.legend.position === 'bottom' && (
2702
+ <>
2703
+ <CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />
2704
+ <CheckBox value={config.legend.verticalSorted} section='legend' fieldName='verticalSorted' label='Vertical sorted Legend' updateField={updateField} />
2705
+ </>
2706
+ )}
2707
+ <TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
2708
+ </AccordionItemPanel>
2709
+ </AccordionItem>
2710
+ )}
2711
+ {visSupportsFilters() && (
2712
+ <AccordionItem>
2713
+ <AccordionItemHeading>
2714
+ <AccordionItemButton>Filters</AccordionItemButton>
2715
+ </AccordionItemHeading>
2716
+ <AccordionItemPanel>
2717
+ {config.filters && (
2718
+ <>
2719
+ {/* prettier-ignore */}
2720
+ <Select
2611
2721
  value={config.filterBehavior}
2612
2722
  fieldName='filterBehavior'
2613
2723
  label='Filter Behavior'
@@ -2624,150 +2734,160 @@ const EditorPanel = () => {
2624
2734
  </Tooltip>
2625
2735
  }
2626
2736
  />
2627
- <br />
2628
- </>
2629
- )}
2630
- {config.filters && (
2631
- <ul className='filters-list'>
2632
- {/* Whether filters should apply onChange or Apply Button */}
2633
-
2634
- {config.filters.map((filter, index) => {
2635
- if (filter.type === 'url') return <></>
2636
-
2637
- return (
2638
- <fieldset className='edit-block' key={index}>
2639
- <button
2640
- type='button'
2641
- className='remove-column'
2642
- onClick={() => {
2643
- removeFilter(index)
2737
+ <br />
2738
+ </>
2739
+ )}
2740
+ {config.filters && (
2741
+ <ul className='filters-list'>
2742
+ {/* Whether filters should apply onChange or Apply Button */}
2743
+
2744
+ {config.filters.map((filter, index) => {
2745
+ if (filter.type === 'url') return <></>
2746
+
2747
+ return (
2748
+ <fieldset className='edit-block' key={index}>
2749
+ <button
2750
+ type='button'
2751
+ className='remove-column'
2752
+ onClick={() => {
2753
+ removeFilter(index)
2754
+ }}
2755
+ >
2756
+ Remove
2757
+ </button>
2758
+ <label>
2759
+ <span className='edit-label column-heading'>Filter</span>
2760
+ <select
2761
+ value={filter.columnName}
2762
+ onChange={e => {
2763
+ updateFilterProp('columnName', index, e.target.value)
2644
2764
  }}
2645
2765
  >
2646
- Remove
2647
- </button>
2648
- <label>
2649
- <span className='edit-label column-heading'>Filter</span>
2650
- <select
2651
- value={filter.columnName}
2652
- onChange={e => {
2653
- updateFilterProp('columnName', index, e.target.value)
2654
- }}
2655
- >
2656
- <option value=''>- Select Option -</option>
2657
- {getFilters().map((dataKey, index) => (
2658
- <option value={dataKey} key={index}>
2659
- {dataKey}
2660
- </option>
2661
- ))}
2662
- </select>
2663
- </label>
2766
+ <option value=''>- Select Option -</option>
2767
+ {getFilters().map((dataKey, index) => (
2768
+ <option value={dataKey} key={index}>
2769
+ {dataKey}
2770
+ </option>
2771
+ ))}
2772
+ </select>
2773
+ </label>
2664
2774
 
2665
- <label>
2666
- <span className='edit-showDropdown column-heading'>Show Filter Input</span>
2667
- <input
2668
- type='checkbox'
2669
- checked={filter.showDropdown === undefined ? true : filter.showDropdown}
2670
- onChange={e => {
2671
- updateFilterProp('showDropdown', index, e.target.checked)
2672
- }}
2673
- />
2674
- </label>
2775
+ <label>
2776
+ <span className='edit-showDropdown column-heading'>Show Filter Input</span>
2777
+ <input
2778
+ type='checkbox'
2779
+ checked={filter.showDropdown === undefined ? true : filter.showDropdown}
2780
+ onChange={e => {
2781
+ updateFilterProp('showDropdown', index, e.target.checked)
2782
+ }}
2783
+ />
2784
+ </label>
2675
2785
 
2676
- <label>
2677
- <span className='edit-label column-heading'>Filter Style</span>
2786
+ <label>
2787
+ <span className='edit-label column-heading'>Filter Style</span>
2678
2788
 
2679
- <select
2680
- value={filter.filterStyle}
2681
- onChange={e => {
2682
- updateFilterProp('filterStyle', index, e.target.value)
2683
- }}
2684
- >
2685
- {filterStyleOptions.map((item, index) => {
2686
- return (
2687
- <option key={`filter-style-${index}`} value={item}>
2688
- {item}
2689
- </option>
2690
- )
2691
- })}
2692
- </select>
2693
- </label>
2694
- <label>
2695
- <span className='edit-label column-heading'>Label</span>
2696
- <input
2697
- type='text'
2698
- value={filter.label}
2699
- onChange={e => {
2700
- updateFilterProp('label', index, e.target.value)
2701
- }}
2702
- />
2703
- </label>
2789
+ <select
2790
+ value={filter.filterStyle}
2791
+ onChange={e => {
2792
+ updateFilterProp('filterStyle', index, e.target.value)
2793
+ }}
2794
+ >
2795
+ {filterStyleOptions.map((item, index) => {
2796
+ return (
2797
+ <option key={`filter-style-${index}`} value={item}>
2798
+ {item}
2799
+ </option>
2800
+ )
2801
+ })}
2802
+ </select>
2803
+ </label>
2804
+ <label>
2805
+ <span className='edit-label column-heading'>Label</span>
2806
+ <input
2807
+ type='text'
2808
+ value={filter.label}
2809
+ onChange={e => {
2810
+ updateFilterProp('label', index, e.target.value)
2811
+ }}
2812
+ />
2813
+ </label>
2704
2814
 
2705
- <label>
2706
- <span className='edit-filterOrder column-heading'>Filter Order</span>
2707
- <select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
2708
- {filterOrderOptions.map((option, index) => {
2709
- return (
2710
- <option value={option.value} key={`filter-${index}`}>
2711
- {option.label}
2712
- </option>
2713
- )
2714
- })}
2715
- </select>
2815
+ <label>
2816
+ <span className='edit-label column-heading'>Default Value Set By Query String Parameter</span>
2817
+ <input
2818
+ type='text'
2819
+ value={filter.setByQueryParameter}
2820
+ onChange={e => {
2821
+ updateFilterProp('setByQueryParameter', index, e.target.value)
2822
+ }}
2823
+ />
2824
+ </label>
2716
2825
 
2717
- {filter.order === 'cust' && (
2718
- <DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
2719
- <Droppable droppableId='filter_order'>
2720
- {provided => (
2721
- <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
2722
- {config.filters[index]?.values.map((value, index) => {
2723
- return (
2724
- <Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
2725
- {(provided, snapshot) => (
2726
- <li>
2727
- <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
2728
- {value}
2729
- </div>
2730
- </li>
2731
- )}
2732
- </Draggable>
2733
- )
2734
- })}
2735
- {provided.placeholder}
2736
- </ul>
2737
- )}
2738
- </Droppable>
2739
- </DragDropContext>
2740
- )}
2741
- </label>
2742
- </fieldset>
2743
- )
2744
- })}
2745
- </ul>
2746
- )}
2747
- {!config.filters && <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
2748
- <button type='button' onClick={addNewFilter} className='btn full-width'>
2749
- Add Filter
2750
- </button>
2751
- </AccordionItemPanel>
2752
- </AccordionItem>
2753
- )}
2754
- <Panels.Visual name='Visual' />
2755
- {/* Spark Line has no data table */}
2756
- {config.visualizationType !== 'Spark Line' && (
2757
- <AccordionItem>
2758
- <AccordionItemHeading>
2759
- <AccordionItemButton>Data Table</AccordionItemButton>
2760
- </AccordionItemHeading>
2761
- <AccordionItemPanel>
2762
- <DataTableEditor config={config} columns={Object.keys(data[0] || {})} updateField={updateField} isDashboard={isDashboard} isLoadedFromUrl={isLoadedFromUrl} />{' '}
2763
- </AccordionItemPanel>
2764
- </AccordionItem>
2765
- )}
2766
- {/* {(config.visualizationType === 'Bar' || config.visualizationType === 'Line') && <Panels.DateHighlighting name='Date Highlighting' />} */}
2767
- </Accordion>
2768
- {config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig} state={config} convertStateToConfig={convertStateToConfig} />}
2769
- </section>
2770
- </section>
2826
+ <label>
2827
+ <span className='edit-filterOrder column-heading'>Filter Order</span>
2828
+ <select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
2829
+ {filterOrderOptions.map((option, index) => {
2830
+ return (
2831
+ <option value={option.value} key={`filter-${index}`}>
2832
+ {option.label}
2833
+ </option>
2834
+ )
2835
+ })}
2836
+ </select>
2837
+
2838
+ {filter.order === 'cust' && (
2839
+ <DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
2840
+ <Droppable droppableId='filter_order'>
2841
+ {provided => (
2842
+ <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
2843
+ {config.filters[index]?.values.map((value, index) => {
2844
+ return (
2845
+ <Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
2846
+ {(provided, snapshot) => (
2847
+ <li>
2848
+ <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
2849
+ {value}
2850
+ </div>
2851
+ </li>
2852
+ )}
2853
+ </Draggable>
2854
+ )
2855
+ })}
2856
+ {provided.placeholder}
2857
+ </ul>
2858
+ )}
2859
+ </Droppable>
2860
+ </DragDropContext>
2861
+ )}
2862
+ </label>
2863
+ </fieldset>
2864
+ )
2865
+ })}
2866
+ </ul>
2867
+ )}
2868
+ {!config.filters && <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
2869
+ <button type='button' onClick={addNewFilter} className='btn full-width'>
2870
+ Add Filter
2871
+ </button>
2872
+ </AccordionItemPanel>
2873
+ </AccordionItem>
2874
+ )}
2875
+ <Panels.Visual name='Visual' />
2876
+ {/* Spark Line has no data table */}
2877
+ {config.visualizationType !== 'Spark Line' && (
2878
+ <AccordionItem>
2879
+ <AccordionItemHeading>
2880
+ <AccordionItemButton>Data Table</AccordionItemButton>
2881
+ </AccordionItemHeading>
2882
+ <AccordionItemPanel>
2883
+ <DataTableEditor config={config} columns={Object.keys(data[0] || {})} updateField={updateField} isDashboard={isDashboard} isLoadedFromUrl={isLoadedFromUrl} />{' '}
2884
+ </AccordionItemPanel>
2885
+ </AccordionItem>
2886
+ )}
2887
+ {/* {(config.visualizationType === 'Bar' || config.visualizationType === 'Line') && <Panels.DateHighlighting name='Date Highlighting' />} */}
2888
+ </Accordion>
2889
+ {config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig} state={config} convertStateToConfig={convertStateToConfig} />}
2890
+ </Layout.Sidebar>
2771
2891
  </ErrorBoundary>
2772
2892
  </EditorPanelContext.Provider>
2773
2893
  )