@cdc/chart 4.22.10 → 4.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/495.js +3 -0
- package/dist/703.js +1 -0
- package/dist/cdcchart.js +723 -6
- package/examples/age-adjusted-rates.json +1486 -1218
- package/examples/box-plot-data.json +71 -0
- package/examples/box-plot.csv +5 -0
- package/examples/{private/yaxis-test.json → box-plot.json} +46 -54
- package/examples/case-rate-example-config.json +1 -1
- package/examples/covid-confidence-example-config.json +33 -33
- package/examples/covid-example-config.json +34 -34
- package/examples/covid-example-data-confidence.json +30 -30
- package/examples/covid-example-data.json +20 -20
- package/examples/cutoff-example-config.json +36 -36
- package/examples/cutoff-example-data.json +36 -36
- package/examples/date-exclusions-config.json +1 -1
- package/examples/dynamic-legends.json +124 -124
- package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json +191 -197
- package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +230 -240
- package/examples/gallery/bar-chart-horizontal/horizontal-stacked.json +239 -247
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +138 -136
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +79 -79
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +80 -80
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +67 -67
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +179 -110
- package/examples/gallery/lollipop/lollipop-style-horizontal.json +215 -219
- package/examples/gallery/paired-bar/paired-bar-chart.json +195 -195
- package/examples/horizontal-chart.json +35 -35
- package/examples/horizontal-stacked-bar-chart.json +34 -34
- package/examples/line-chart.json +75 -75
- package/examples/new-data.csv +17 -0
- package/examples/newdata.json +90 -0
- package/examples/paired-bar-data.json +16 -14
- package/examples/paired-bar-example.json +48 -48
- package/examples/paired-bar-formatted.json +36 -36
- package/examples/planet-chart-horizontal-example-config.json +33 -33
- package/examples/planet-combo-example-config.json +34 -31
- package/examples/planet-example-config.json +35 -33
- package/examples/planet-example-data.json +56 -56
- package/examples/planet-pie-example-config.json +28 -28
- package/examples/stacked-vertical-bar-example.json +1 -1
- package/examples/temp-example-config.json +61 -54
- package/examples/temp-example-data.json +1 -1
- package/package.json +3 -2
- package/src/CdcChart.tsx +449 -434
- package/src/components/BarChart.tsx +383 -497
- package/src/components/BoxPlot.js +92 -0
- package/src/components/DataTable.tsx +182 -197
- package/src/components/EditorPanel.js +1068 -722
- package/src/components/Filters.js +131 -0
- package/src/components/Legend.js +286 -329
- package/src/components/LineChart.tsx +143 -81
- package/src/components/LinearChart.tsx +432 -451
- package/src/components/PairedBarChart.tsx +197 -213
- package/src/components/PieChart.tsx +105 -151
- package/src/components/SparkLine.js +179 -201
- package/src/components/useIntersectionObserver.tsx +19 -20
- package/src/context.tsx +3 -3
- package/src/data/initial-state.js +44 -17
- package/src/hooks/useActiveElement.js +13 -13
- package/src/hooks/useChartClasses.js +34 -28
- package/src/hooks/useColorPalette.ts +56 -63
- package/src/hooks/useLegendClasses.js +18 -10
- package/src/hooks/useReduceData.ts +64 -77
- package/src/hooks/useRightAxis.js +25 -0
- package/src/hooks/useTopAxis.js +6 -0
- package/src/index.html +19 -19
- package/src/index.tsx +13 -16
- package/src/scss/DataTable.scss +6 -5
- package/src/scss/editor-panel.scss +71 -69
- package/src/scss/main.scss +188 -114
- package/src/scss/variables.scss +1 -1
- package/examples/private/line-test-data.json +0 -22
- package/examples/private/line-test-two.json +0 -216
- package/examples/private/line-test.json +0 -102
- package/examples/private/newtest.csv +0 -101
- package/examples/private/shawn.json +0 -1296
- package/examples/private/test.json +0 -10124
- package/examples/private/yaxis-testing.csv +0 -27
- package/examples/private/yaxis.json +0 -28
|
@@ -1,46 +1,42 @@
|
|
|
1
1
|
import React, { useState, useEffect, useCallback, memo, useContext } from 'react'
|
|
2
2
|
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
Accordion,
|
|
6
|
-
AccordionItem,
|
|
7
|
-
AccordionItemHeading,
|
|
8
|
-
AccordionItemPanel,
|
|
9
|
-
AccordionItemButton,
|
|
10
|
-
} from 'react-accessible-accordion'
|
|
4
|
+
import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
|
|
11
5
|
|
|
12
|
-
import {
|
|
13
|
-
import { useDebounce, useDebouncedCallback } from 'use-debounce'
|
|
6
|
+
import { useDebounce } from 'use-debounce'
|
|
14
7
|
|
|
15
8
|
import Context from '../context'
|
|
16
9
|
import WarningImage from '../images/warning.svg'
|
|
17
|
-
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
10
|
+
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
18
11
|
|
|
19
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
20
|
-
import
|
|
21
|
-
import QuestionIcon from '@cdc/core/assets/icon-question-circle.svg'; //TODO: Update with Icon component
|
|
22
|
-
import {useColorPalette} from '../hooks/useColorPalette';
|
|
12
|
+
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
13
|
+
import { useColorPalette } from '../hooks/useColorPalette'
|
|
23
14
|
|
|
24
|
-
import
|
|
25
|
-
import InputToggle from '@cdc/core/components/inputs/InputToggle';
|
|
15
|
+
import InputToggle from '@cdc/core/components/inputs/InputToggle'
|
|
26
16
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
27
17
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
28
|
-
import useReduceData from '../hooks/useReduceData'
|
|
18
|
+
import useReduceData from '../hooks/useReduceData'
|
|
19
|
+
import useRightAxis from '../hooks/useRightAxis'
|
|
29
20
|
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
// TODO: Remove unused imports
|
|
22
|
+
// TDOO: Move inline styles to a scss file
|
|
32
23
|
|
|
33
|
-
|
|
24
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
25
|
+
|
|
26
|
+
const TextField = memo(({ label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', i = null, min = null, ...attributes }) => {
|
|
27
|
+
const [value, setValue] = useState(stateValue)
|
|
28
|
+
|
|
29
|
+
const [debouncedValue] = useDebounce(value, 500)
|
|
34
30
|
|
|
35
31
|
useEffect(() => {
|
|
36
32
|
if ('string' === typeof debouncedValue && stateValue !== debouncedValue) {
|
|
37
33
|
updateField(section, subsection, fieldName, debouncedValue, i)
|
|
38
34
|
}
|
|
39
|
-
}, [
|
|
35
|
+
}, [debouncedValue]) // eslint-disable-line
|
|
40
36
|
|
|
41
37
|
let name = subsection ? `${section}-${subsection}-${fieldName}` : `${section}-${subsection}-${fieldName}`
|
|
42
38
|
|
|
43
|
-
const onChange =
|
|
39
|
+
const onChange = e => {
|
|
44
40
|
if ('number' !== type || min === null) {
|
|
45
41
|
setValue(e.target.value)
|
|
46
42
|
} else {
|
|
@@ -52,52 +48,79 @@ const TextField = memo(({label, tooltip, section = null, subsection = null, fiel
|
|
|
52
48
|
}
|
|
53
49
|
}
|
|
54
50
|
|
|
55
|
-
let formElement = <input type=
|
|
51
|
+
let formElement = <input type='text' name={name} onChange={onChange} {...attributes} value={value} />
|
|
56
52
|
|
|
57
53
|
if ('textarea' === type) {
|
|
58
|
-
formElement =
|
|
59
|
-
<textarea name={name} onChange={onChange} {...attributes} value={value}></textarea>
|
|
60
|
-
)
|
|
54
|
+
formElement = <textarea name={name} onChange={onChange} {...attributes} value={value}></textarea>
|
|
61
55
|
}
|
|
62
56
|
|
|
63
57
|
if ('number' === type) {
|
|
64
|
-
formElement = <input type=
|
|
58
|
+
formElement = <input type='number' name={name} onChange={onChange} {...attributes} value={value} />
|
|
65
59
|
}
|
|
66
60
|
|
|
67
61
|
if ('date' === type) {
|
|
68
|
-
formElement = <input type=
|
|
62
|
+
formElement = <input type='date' name={name} onChange={onChange} {...attributes} value={value} />
|
|
69
63
|
}
|
|
70
64
|
|
|
71
65
|
return (
|
|
72
66
|
<label>
|
|
73
|
-
<span className=
|
|
67
|
+
<span className='edit-label column-heading'>
|
|
68
|
+
{label}
|
|
69
|
+
{tooltip}
|
|
70
|
+
</span>
|
|
74
71
|
{formElement}
|
|
75
72
|
</label>
|
|
76
73
|
)
|
|
77
74
|
})
|
|
78
75
|
|
|
79
76
|
const CheckBox = memo(({ label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes }) => (
|
|
80
|
-
<label className=
|
|
81
|
-
<input
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
<label className='checkbox'>
|
|
78
|
+
<input
|
|
79
|
+
type='checkbox'
|
|
80
|
+
name={fieldName}
|
|
81
|
+
checked={value}
|
|
82
|
+
onChange={() => {
|
|
83
|
+
updateField(section, subsection, fieldName, !value)
|
|
84
|
+
}}
|
|
85
|
+
{...attributes}
|
|
86
|
+
/>
|
|
87
|
+
<span className='edit-label'>
|
|
88
|
+
{label}
|
|
89
|
+
{tooltip}
|
|
90
|
+
</span>
|
|
85
91
|
</label>
|
|
86
92
|
))
|
|
87
93
|
|
|
88
94
|
const Select = memo(({ label, value, options, fieldName, section = null, subsection = null, required = false, tooltip, updateField, initial: initialValue, ...attributes }) => {
|
|
89
|
-
let optionsJsx = options.map((optionName, index) =>
|
|
95
|
+
let optionsJsx = options.map((optionName, index) => (
|
|
96
|
+
<option value={optionName} key={index}>
|
|
97
|
+
{optionName}
|
|
98
|
+
</option>
|
|
99
|
+
))
|
|
90
100
|
|
|
91
101
|
if (initialValue) {
|
|
92
|
-
optionsJsx.unshift(
|
|
102
|
+
optionsJsx.unshift(
|
|
103
|
+
<option value='' key='initial'>
|
|
104
|
+
{initialValue}
|
|
105
|
+
</option>
|
|
106
|
+
)
|
|
93
107
|
}
|
|
94
108
|
|
|
95
109
|
return (
|
|
96
110
|
<label>
|
|
97
|
-
<span className=
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
111
|
+
<span className='edit-label'>
|
|
112
|
+
{label}
|
|
113
|
+
{tooltip}
|
|
114
|
+
</span>
|
|
115
|
+
<select
|
|
116
|
+
className={required && !value ? 'warning' : ''}
|
|
117
|
+
name={fieldName}
|
|
118
|
+
value={value}
|
|
119
|
+
onChange={event => {
|
|
120
|
+
updateField(section, subsection, fieldName, event.target.value)
|
|
121
|
+
}}
|
|
122
|
+
{...attributes}
|
|
123
|
+
>
|
|
101
124
|
{optionsJsx}
|
|
102
125
|
</select>
|
|
103
126
|
</label>
|
|
@@ -109,7 +132,7 @@ const Regions = memo(({ config, updateConfig }) => {
|
|
|
109
132
|
let regions = []
|
|
110
133
|
|
|
111
134
|
if (config.regions) {
|
|
112
|
-
regions = [
|
|
135
|
+
regions = [...config.regions]
|
|
113
136
|
}
|
|
114
137
|
|
|
115
138
|
regions[i][fieldName] = value
|
|
@@ -118,11 +141,11 @@ const Regions = memo(({ config, updateConfig }) => {
|
|
|
118
141
|
|
|
119
142
|
let updateField = (section, subsection, fieldName, value, i) => regionUpdate(fieldName, value, i)
|
|
120
143
|
|
|
121
|
-
let removeColumn =
|
|
144
|
+
let removeColumn = i => {
|
|
122
145
|
let regions = []
|
|
123
146
|
|
|
124
147
|
if (config.regions) {
|
|
125
|
-
regions = [
|
|
148
|
+
regions = [...config.regions]
|
|
126
149
|
}
|
|
127
150
|
|
|
128
151
|
regions.splice(i, 1)
|
|
@@ -131,11 +154,10 @@ const Regions = memo(({ config, updateConfig }) => {
|
|
|
131
154
|
}
|
|
132
155
|
|
|
133
156
|
let addColumn = () => {
|
|
134
|
-
|
|
135
157
|
let regions = []
|
|
136
158
|
|
|
137
159
|
if (config.regions) {
|
|
138
|
-
regions = [
|
|
160
|
+
regions = [...config.regions]
|
|
139
161
|
}
|
|
140
162
|
|
|
141
163
|
regions.push({})
|
|
@@ -145,63 +167,83 @@ const Regions = memo(({ config, updateConfig }) => {
|
|
|
145
167
|
|
|
146
168
|
return (
|
|
147
169
|
<>
|
|
148
|
-
{config.regions &&
|
|
149
|
-
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
<TextField value={
|
|
162
|
-
<
|
|
170
|
+
{config.regions &&
|
|
171
|
+
config.regions.map(({ label, color, from, to, background }, i) => (
|
|
172
|
+
<div className='edit-block' key={`region-${i}`}>
|
|
173
|
+
<button
|
|
174
|
+
type='button'
|
|
175
|
+
className='remove-column'
|
|
176
|
+
onClick={event => {
|
|
177
|
+
event.preventDefault()
|
|
178
|
+
removeColumn(i)
|
|
179
|
+
}}
|
|
180
|
+
>
|
|
181
|
+
Remove
|
|
182
|
+
</button>
|
|
183
|
+
<TextField value={label} label='Region Label' fieldName='label' i={i} updateField={updateField} />
|
|
184
|
+
<div className='two-col-inputs'>
|
|
185
|
+
<TextField value={color} label='Text Color' fieldName='color' updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)} />
|
|
186
|
+
<TextField value={background} label='Background' fieldName='background' updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)} />
|
|
187
|
+
</div>
|
|
188
|
+
<div className='two-col-inputs'>
|
|
189
|
+
<TextField value={from} label='From Value' fieldName='from' updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)} />
|
|
190
|
+
<TextField value={to} label='To Value' fieldName='to' updateField={(section, subsection, fieldName, value) => regionUpdate(fieldName, value, i)} />
|
|
191
|
+
</div>
|
|
163
192
|
</div>
|
|
164
|
-
|
|
165
|
-
))}
|
|
193
|
+
))}
|
|
166
194
|
{!config.regions && <p style={{ textAlign: 'center' }}>There are currently no regions.</p>}
|
|
167
|
-
<button
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
195
|
+
<button
|
|
196
|
+
type='button'
|
|
197
|
+
className='btn full-width'
|
|
198
|
+
onClick={e => {
|
|
199
|
+
e.preventDefault()
|
|
200
|
+
addColumn()
|
|
201
|
+
}}
|
|
202
|
+
>
|
|
203
|
+
Add Region
|
|
171
204
|
</button>
|
|
172
205
|
</>
|
|
173
206
|
)
|
|
174
207
|
})
|
|
175
208
|
|
|
176
|
-
const headerColors = [
|
|
209
|
+
const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
|
|
177
210
|
|
|
178
211
|
const EditorPanel = () => {
|
|
179
|
-
const {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
212
|
+
const { config, updateConfig, transformedData: data, loading, colorPalettes, unfilteredData, excludedData, isDashboard, setParentConfig, missingRequiredSections } = useContext(Context)
|
|
213
|
+
|
|
214
|
+
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, unfilteredData)
|
|
215
|
+
const { paletteName, isPaletteReversed, filteredPallets, filteredQualitative, dispatch } = useColorPalette(colorPalettes, config)
|
|
216
|
+
useEffect(() => {
|
|
217
|
+
if (paletteName) updateConfig({ ...config, palette: paletteName })
|
|
218
|
+
}, [paletteName]) // eslint-disable-line
|
|
219
|
+
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
dispatch({ type: 'GET_PALETTE', payload: colorPalettes, paletteName: config.palette })
|
|
222
|
+
}, [dispatch, config.palette]) // eslint-disable-line
|
|
223
|
+
|
|
224
|
+
// when the visualization type changes we
|
|
225
|
+
// have to update the individual series type & axis details
|
|
226
|
+
// dataKey is unchanged here.
|
|
227
|
+
// ie. { dataKey: 'series_name', type: 'Bar', axis: 'Left'}
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
let newSeries = []
|
|
230
|
+
if (config.series) {
|
|
231
|
+
newSeries = config.series.map(series => {
|
|
232
|
+
return {
|
|
233
|
+
...series,
|
|
234
|
+
type: config.visualizationType === 'Combo' ? 'Bar' : config.visualizationType ? config.visualizationType : 'Bar',
|
|
235
|
+
axis: 'Left'
|
|
236
|
+
}
|
|
237
|
+
})
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
updateConfig({
|
|
241
|
+
...config,
|
|
242
|
+
series: newSeries
|
|
243
|
+
})
|
|
244
|
+
}, [config.visualizationType]) // eslint-disable-line
|
|
245
|
+
|
|
246
|
+
const { hasRightAxis } = useRightAxis({ config: config, yMax: config.yAxis.size, data: config.data, updateConfig })
|
|
205
247
|
|
|
206
248
|
const filterOptions = [
|
|
207
249
|
{
|
|
@@ -219,7 +261,7 @@ const EditorPanel = () => {
|
|
|
219
261
|
]
|
|
220
262
|
|
|
221
263
|
const getItemStyle = (isDragging, draggableStyle) => ({
|
|
222
|
-
...draggableStyle
|
|
264
|
+
...draggableStyle
|
|
223
265
|
})
|
|
224
266
|
|
|
225
267
|
const sortableItemStyles = {
|
|
@@ -235,10 +277,10 @@ const EditorPanel = () => {
|
|
|
235
277
|
marginRight: '.3em',
|
|
236
278
|
marginBottom: '.3em',
|
|
237
279
|
cursor: 'move',
|
|
238
|
-
zIndex: '999'
|
|
280
|
+
zIndex: '999'
|
|
239
281
|
}
|
|
240
282
|
|
|
241
|
-
const enforceRestrictions =
|
|
283
|
+
const enforceRestrictions = updatedConfig => {
|
|
242
284
|
if (updatedConfig.orientation === 'horizontal') {
|
|
243
285
|
updatedConfig.labels = false
|
|
244
286
|
}
|
|
@@ -260,11 +302,11 @@ const EditorPanel = () => {
|
|
|
260
302
|
|
|
261
303
|
const isArray = Array.isArray(config[section])
|
|
262
304
|
|
|
263
|
-
let sectionValue = isArray ? [
|
|
305
|
+
let sectionValue = isArray ? [...config[section], newValue] : { ...config[section], [fieldName]: newValue }
|
|
264
306
|
|
|
265
307
|
if (null !== subsection) {
|
|
266
308
|
if (isArray) {
|
|
267
|
-
sectionValue = [
|
|
309
|
+
sectionValue = [...config[section]]
|
|
268
310
|
sectionValue[subsection] = { ...sectionValue[subsection], [fieldName]: newValue }
|
|
269
311
|
} else if (typeof newValue === 'string') {
|
|
270
312
|
sectionValue[subsection] = newValue
|
|
@@ -280,22 +322,21 @@ const EditorPanel = () => {
|
|
|
280
322
|
updateConfig(updatedConfig)
|
|
281
323
|
}
|
|
282
324
|
|
|
283
|
-
const [
|
|
284
|
-
const [ lollipopColorStyle, setLollipopColorStyle ] = useState('two-tone')
|
|
325
|
+
const [displayPanel, setDisplayPanel] = useState(true)
|
|
285
326
|
|
|
286
327
|
if (loading) {
|
|
287
328
|
return null
|
|
288
329
|
}
|
|
289
330
|
|
|
290
|
-
const setLollipopShape =
|
|
331
|
+
const setLollipopShape = shape => {
|
|
291
332
|
updateConfig({
|
|
292
333
|
...config,
|
|
293
334
|
lollipopShape: shape
|
|
294
335
|
})
|
|
295
336
|
}
|
|
296
337
|
|
|
297
|
-
const removeFilter =
|
|
298
|
-
let filters = [
|
|
338
|
+
const removeFilter = index => {
|
|
339
|
+
let filters = [...config.filters]
|
|
299
340
|
|
|
300
341
|
filters.splice(index, 1)
|
|
301
342
|
|
|
@@ -303,7 +344,7 @@ const EditorPanel = () => {
|
|
|
303
344
|
}
|
|
304
345
|
|
|
305
346
|
const updateFilterProp = (name, index, value) => {
|
|
306
|
-
let filters = [
|
|
347
|
+
let filters = [...config.filters]
|
|
307
348
|
|
|
308
349
|
filters[index][name] = value
|
|
309
350
|
|
|
@@ -311,29 +352,28 @@ const EditorPanel = () => {
|
|
|
311
352
|
}
|
|
312
353
|
|
|
313
354
|
const addNewFilter = () => {
|
|
314
|
-
let filters = config.filters ? [
|
|
355
|
+
let filters = config.filters ? [...config.filters] : []
|
|
315
356
|
|
|
316
|
-
filters.push({ values: [] })
|
|
357
|
+
filters.push({ values: [] })
|
|
317
358
|
|
|
318
|
-
updateConfig({ ...config, filters })
|
|
359
|
+
updateConfig({ ...config, filters })
|
|
319
360
|
}
|
|
320
361
|
|
|
321
|
-
const addNewSeries =
|
|
322
|
-
let newSeries = config.series ? [
|
|
323
|
-
newSeries.push({ dataKey: seriesKey, type: 'Bar' })
|
|
324
|
-
updateConfig({ ...config, series: newSeries })
|
|
362
|
+
const addNewSeries = seriesKey => {
|
|
363
|
+
let newSeries = config.series ? [...config.series] : []
|
|
364
|
+
newSeries.push({ dataKey: seriesKey, type: 'Bar' })
|
|
365
|
+
updateConfig({ ...config, series: newSeries }) // left axis series keys
|
|
325
366
|
}
|
|
326
367
|
|
|
327
|
-
const sortSeries =
|
|
368
|
+
const sortSeries = e => {
|
|
328
369
|
const series = config.series[0].dataKey
|
|
329
|
-
const sorted = data.sort((a, b) => a[series] - b[series])
|
|
330
|
-
const newData = e ===
|
|
331
|
-
updateConfig({ ...config }, newData)
|
|
370
|
+
const sorted = data.sort((a, b) => a[series] - b[series])
|
|
371
|
+
const newData = e === 'asc' ? sorted : sorted.reverse()
|
|
372
|
+
updateConfig({ ...config }, newData)
|
|
332
373
|
}
|
|
333
374
|
|
|
334
|
-
const removeSeries =
|
|
335
|
-
|
|
336
|
-
let series = [ ...config.series ]
|
|
375
|
+
const removeSeries = seriesKey => {
|
|
376
|
+
let series = [...config.series]
|
|
337
377
|
let seriesIndex = -1
|
|
338
378
|
|
|
339
379
|
for (let i = 0; i < series.length; i++) {
|
|
@@ -363,17 +403,17 @@ const EditorPanel = () => {
|
|
|
363
403
|
}
|
|
364
404
|
}
|
|
365
405
|
|
|
366
|
-
const addNewExclusion =
|
|
367
|
-
let newExclusion = [
|
|
406
|
+
const addNewExclusion = exclusionKey => {
|
|
407
|
+
let newExclusion = [...config.exclusions.keys]
|
|
368
408
|
newExclusion.push(exclusionKey)
|
|
369
409
|
|
|
370
410
|
let payload = { ...config.exclusions, keys: newExclusion }
|
|
371
411
|
updateConfig({ ...config, exclusions: payload })
|
|
372
412
|
}
|
|
373
413
|
|
|
374
|
-
const removeExclusion =
|
|
414
|
+
const removeExclusion = excludeValue => {
|
|
375
415
|
let exclusionsIndex = -1
|
|
376
|
-
let exclusions = [
|
|
416
|
+
let exclusions = [...config.exclusions.keys]
|
|
377
417
|
|
|
378
418
|
for (let i = 0; i < exclusions.length; i++) {
|
|
379
419
|
if (exclusions[i] === excludeValue) {
|
|
@@ -399,14 +439,11 @@ const EditorPanel = () => {
|
|
|
399
439
|
const getColumns = (filter = true) => {
|
|
400
440
|
let columns = {}
|
|
401
441
|
|
|
402
|
-
unfilteredData.
|
|
403
|
-
Object.keys(row).forEach(columnName => columns[columnName] = true)
|
|
442
|
+
unfilteredData.forEach(row => {
|
|
443
|
+
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
404
444
|
})
|
|
405
445
|
|
|
406
446
|
if (filter) {
|
|
407
|
-
let confidenceUpper = config.confidenceKeys?.upper && config.confidenceKeys?.upper !== ''
|
|
408
|
-
let confidenceLower = config.confidenceKeys?.lower && config.confidenceKeys?.lower !== ''
|
|
409
|
-
|
|
410
447
|
Object.keys(columns).forEach(key => {
|
|
411
448
|
if (
|
|
412
449
|
(config.series && config.series.filter(series => series.dataKey === key).length > 0) ||
|
|
@@ -424,32 +461,30 @@ const EditorPanel = () => {
|
|
|
424
461
|
return Object.keys(columns)
|
|
425
462
|
}
|
|
426
463
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
for (
|
|
432
|
-
|
|
433
|
-
set.add(key)
|
|
434
|
-
}
|
|
435
|
-
|
|
464
|
+
const getDataValueOptions = data => {
|
|
465
|
+
if (!data) return []
|
|
466
|
+
const set = new Set()
|
|
467
|
+
for (let i = 0; i < data.length; i++) {
|
|
468
|
+
for (const [key] of Object.entries(data[i])) {
|
|
469
|
+
set.add(key)
|
|
436
470
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
471
|
+
}
|
|
472
|
+
return Array.from(set)
|
|
473
|
+
}
|
|
474
|
+
|
|
440
475
|
const getDataValues = (dataKey, unique = false) => {
|
|
441
476
|
let values = []
|
|
442
|
-
excludedData.
|
|
477
|
+
excludedData.forEach(e => {
|
|
443
478
|
values.push(e[dataKey])
|
|
444
479
|
})
|
|
445
|
-
return unique ? [
|
|
480
|
+
return unique ? [...new Set(values)] : values
|
|
446
481
|
}
|
|
447
482
|
|
|
448
|
-
const showBarStyleOptions = ()=>{
|
|
449
|
-
if (config.visualizationType === 'Bar' && config.visualizationSubType !== 'stacked' && (config.orientation==='horizontal' || config.orientation==='vertical')
|
|
450
|
-
return ['flat','rounded','lollipop']
|
|
483
|
+
const showBarStyleOptions = () => {
|
|
484
|
+
if (config.visualizationType === 'Bar' && config.visualizationSubType !== 'stacked' && (config.orientation === 'horizontal' || config.orientation === 'vertical')) {
|
|
485
|
+
return ['flat', 'rounded', 'lollipop']
|
|
451
486
|
} else {
|
|
452
|
-
return ['flat','rounded']
|
|
487
|
+
return ['flat', 'rounded']
|
|
453
488
|
}
|
|
454
489
|
}
|
|
455
490
|
|
|
@@ -459,18 +494,17 @@ const EditorPanel = () => {
|
|
|
459
494
|
|
|
460
495
|
const Error = () => {
|
|
461
496
|
return (
|
|
462
|
-
<section className=
|
|
463
|
-
<section className=
|
|
497
|
+
<section className='waiting'>
|
|
498
|
+
<section className='waiting-container'>
|
|
464
499
|
<h3>Error With Configuration</h3>
|
|
465
500
|
<p>{config.runtime.editorErrorMessage}</p>
|
|
466
501
|
</section>
|
|
467
502
|
</section>
|
|
468
503
|
)
|
|
469
|
-
|
|
470
504
|
}
|
|
471
505
|
|
|
472
506
|
const Confirm = () => {
|
|
473
|
-
const confirmDone =
|
|
507
|
+
const confirmDone = e => {
|
|
474
508
|
e.preventDefault()
|
|
475
509
|
|
|
476
510
|
let newConfig = { ...config }
|
|
@@ -480,11 +514,13 @@ const EditorPanel = () => {
|
|
|
480
514
|
}
|
|
481
515
|
|
|
482
516
|
return (
|
|
483
|
-
<section className=
|
|
484
|
-
<section className=
|
|
517
|
+
<section className='waiting'>
|
|
518
|
+
<section className='waiting-container'>
|
|
485
519
|
<h3>Finish Configuring</h3>
|
|
486
520
|
<p>Set all required options to the left and confirm below to display a preview of the chart.</p>
|
|
487
|
-
<button className=
|
|
521
|
+
<button className='btn' style={{ margin: '1em auto' }} disabled={missingRequiredSections()} onClick={confirmDone}>
|
|
522
|
+
I'm Done
|
|
523
|
+
</button>
|
|
488
524
|
</section>
|
|
489
525
|
</section>
|
|
490
526
|
)
|
|
@@ -508,17 +544,17 @@ const EditorPanel = () => {
|
|
|
508
544
|
}
|
|
509
545
|
|
|
510
546
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
511
|
-
}, [
|
|
512
|
-
|
|
547
|
+
}, [config])
|
|
548
|
+
|
|
513
549
|
// Set paired bars to be horizontal, even though that option doesn't display
|
|
514
550
|
useEffect(() => {
|
|
515
|
-
if(config.visualizationType === 'Paired Bar') {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
551
|
+
if (config.visualizationType === 'Paired Bar') {
|
|
552
|
+
updateConfig({
|
|
553
|
+
...config,
|
|
554
|
+
orientation: 'horizontal'
|
|
519
555
|
})
|
|
520
556
|
}
|
|
521
|
-
}, [])
|
|
557
|
+
}, []) // eslint-disable-line
|
|
522
558
|
|
|
523
559
|
useEffect(() => {
|
|
524
560
|
if (config.orientation === 'horizontal') {
|
|
@@ -527,50 +563,50 @@ const EditorPanel = () => {
|
|
|
527
563
|
lollipopShape: config.lollipopShape
|
|
528
564
|
})
|
|
529
565
|
}
|
|
530
|
-
}, [
|
|
566
|
+
}, [config.isLollipopChart, config.lollipopShape]) // eslint-disable-line
|
|
531
567
|
|
|
532
568
|
const ExclusionsList = useCallback(() => {
|
|
533
|
-
const exclusions = [
|
|
569
|
+
const exclusions = [...config.exclusions.keys]
|
|
534
570
|
return (
|
|
535
|
-
<ul className=
|
|
571
|
+
<ul className='series-list'>
|
|
536
572
|
{exclusions.map((exclusion, index) => {
|
|
537
573
|
return (
|
|
538
574
|
<li key={exclusion}>
|
|
539
|
-
<div className=
|
|
540
|
-
<div className=
|
|
541
|
-
{exclusion}
|
|
542
|
-
</div>
|
|
575
|
+
<div className='series-list__name' data-title={exclusion}>
|
|
576
|
+
<div className='series-list__name--text'>{exclusion}</div>
|
|
543
577
|
</div>
|
|
544
|
-
<button className=
|
|
578
|
+
<button className='series-list__remove' onClick={() => removeExclusion(exclusion)}>
|
|
579
|
+
×
|
|
580
|
+
</button>
|
|
545
581
|
</li>
|
|
546
582
|
)
|
|
547
583
|
})}
|
|
548
584
|
</ul>
|
|
549
585
|
)
|
|
550
|
-
}, [
|
|
586
|
+
}, [config]) // eslint-disable-line
|
|
551
587
|
|
|
552
|
-
const
|
|
553
|
-
return (
|
|
554
|
-
<section className="waiting">
|
|
555
|
-
<section className="waiting-container">
|
|
556
|
-
<h3>Error With Configuration</h3>
|
|
557
|
-
<p>{message}</p>
|
|
558
|
-
</section>
|
|
559
|
-
</section>
|
|
560
|
-
)
|
|
588
|
+
const checkIsLine = type => {
|
|
589
|
+
return type === ('Line' || 'dashed-sm')
|
|
561
590
|
}
|
|
562
591
|
|
|
563
592
|
const handleFilterChange = (idx1, idx2, filterIndex, filter) => {
|
|
564
593
|
let filterOrder = filter.values
|
|
565
|
-
let [
|
|
594
|
+
let [movedItem] = filterOrder.splice(idx1, 1)
|
|
566
595
|
filterOrder.splice(idx2, 0, movedItem)
|
|
567
|
-
let filters = [
|
|
596
|
+
let filters = [...config.filters]
|
|
568
597
|
let filterItem = { ...config.filters[filterIndex] }
|
|
569
598
|
filterItem.active = filter.values[0]
|
|
570
|
-
filterItem.
|
|
599
|
+
filterItem.orderedValues = filterOrder
|
|
571
600
|
filterItem.order = 'cust'
|
|
572
601
|
filters[filterIndex] = filterItem
|
|
573
|
-
|
|
602
|
+
updateConfig({ ...config, filters })
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const handleSeriesChange = (idx1, idx2) => {
|
|
606
|
+
let seriesOrder = config.series
|
|
607
|
+
let [movedItem] = seriesOrder.splice(idx1, 1)
|
|
608
|
+
seriesOrder.splice(idx2, 0, movedItem)
|
|
609
|
+
updateConfig({ ...config, series: seriesOrder })
|
|
574
610
|
}
|
|
575
611
|
|
|
576
612
|
if (config.isLollipopChart && config?.series?.length > 1) {
|
|
@@ -581,500 +617,787 @@ const EditorPanel = () => {
|
|
|
581
617
|
config.runtime.editorErrorMessage = 'Add a data series'
|
|
582
618
|
}
|
|
583
619
|
|
|
584
|
-
const section = config.orientation==='horizontal'
|
|
585
|
-
const [warningMsg,setWarningMsg] = useState({maxMsg:'',minMsg:''})
|
|
620
|
+
const section = config.orientation === 'horizontal' ? 'xAxis' : 'yAxis'
|
|
621
|
+
const [warningMsg, setWarningMsg] = useState({ maxMsg: '', minMsg: '' })
|
|
586
622
|
|
|
587
623
|
const validateMaxValue = () => {
|
|
588
|
-
const enteredValue = config[section].max
|
|
589
|
-
let message = ''
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
624
|
+
const enteredValue = config[section].max
|
|
625
|
+
let message = ''
|
|
626
|
+
|
|
627
|
+
switch (true) {
|
|
628
|
+
case enteredValue && parseFloat(enteredValue) < parseFloat(maxValue) && existPositiveValue:
|
|
629
|
+
message = 'Max value must be more than ' + maxValue
|
|
630
|
+
break
|
|
631
|
+
case enteredValue && parseFloat(enteredValue) < 0 && !existPositiveValue:
|
|
632
|
+
message = 'Value must be more than or equal to 0'
|
|
633
|
+
break
|
|
634
|
+
default:
|
|
635
|
+
message = ''
|
|
636
|
+
}
|
|
637
|
+
setWarningMsg(function (prevMsg) {
|
|
638
|
+
return { ...prevMsg, maxMsg: message }
|
|
639
|
+
})
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
const validateMinValue = () => {
|
|
643
|
+
const enteredValue = config[section].min
|
|
644
|
+
let minVal = Number(minValue)
|
|
645
|
+
let message = ''
|
|
646
|
+
|
|
647
|
+
switch (true) {
|
|
648
|
+
case (config.visualizationType === 'Line' || config.visualizationType === 'Spark Line') && enteredValue && parseFloat(enteredValue) > minVal:
|
|
649
|
+
message = 'Value must be less than ' + minValue
|
|
650
|
+
break
|
|
651
|
+
case config.visualizationType === 'Combo' && isAllLine && enteredValue && parseFloat(enteredValue) > minVal:
|
|
652
|
+
message = 'Value must be less than ' + minValue
|
|
653
|
+
break
|
|
654
|
+
case (config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && enteredValue && minVal > 0 && parseFloat(enteredValue) > 0:
|
|
655
|
+
message = 'Value must be less than or equal to 0'
|
|
656
|
+
break
|
|
657
|
+
case enteredValue && minVal < 0 && parseFloat(enteredValue) > minVal:
|
|
658
|
+
message = 'Value must be less than ' + minValue
|
|
659
|
+
break
|
|
660
|
+
default:
|
|
661
|
+
message = ''
|
|
662
|
+
}
|
|
663
|
+
setWarningMsg(function (prevMsg) {
|
|
664
|
+
return { ...prevMsg, minMsg: message }
|
|
665
|
+
})
|
|
666
|
+
}
|
|
667
|
+
useEffect(() => {
|
|
668
|
+
validateMinValue()
|
|
669
|
+
validateMaxValue()
|
|
670
|
+
}, [minValue, maxValue, config]) // eslint-disable-line
|
|
628
671
|
|
|
629
672
|
return (
|
|
630
|
-
<ErrorBoundary component=
|
|
631
|
-
{config.newViz && <Confirm/>}
|
|
632
|
-
{undefined === config.newViz && config.runtime && config.runtime.editorErrorMessage && <Error/>}
|
|
673
|
+
<ErrorBoundary component='EditorPanel'>
|
|
674
|
+
{config.newViz && <Confirm />}
|
|
675
|
+
{undefined === config.newViz && config.runtime && config.runtime.editorErrorMessage && <Error />}
|
|
633
676
|
<button className={displayPanel ? `editor-toggle` : `editor-toggle collapsed`} title={displayPanel ? `Collapse Editor` : `Expand Editor`} onClick={onBackClick}></button>
|
|
634
677
|
<section className={`${displayPanel ? 'editor-panel cove' : 'hidden editor-panel cove'}${isDashboard ? ' dashboard' : ''}`}>
|
|
635
|
-
<div aria-level=
|
|
636
|
-
|
|
678
|
+
<div aria-level='2' role='heading' className='heading-2'>
|
|
679
|
+
Configure Chart
|
|
680
|
+
</div>
|
|
681
|
+
<section className='form-container'>
|
|
637
682
|
<form>
|
|
638
683
|
<Accordion allowZeroExpanded={true}>
|
|
639
|
-
<AccordionItem>
|
|
684
|
+
<AccordionItem>
|
|
685
|
+
{' '}
|
|
686
|
+
{/* General */}
|
|
640
687
|
<AccordionItemHeading>
|
|
641
|
-
<AccordionItemButton>
|
|
642
|
-
General
|
|
643
|
-
</AccordionItemButton>
|
|
688
|
+
<AccordionItemButton>General</AccordionItemButton>
|
|
644
689
|
</AccordionItemHeading>
|
|
645
690
|
<AccordionItemPanel>
|
|
646
|
-
<Select value={config.visualizationType} fieldName=
|
|
647
|
-
{(config.visualizationType === 'Bar'|| config.visualizationType === 'Combo') && <Select value={config.visualizationSubType || 'Regular'} fieldName=
|
|
648
|
-
{config.visualizationType === 'Bar' && <Select value={config.orientation || 'vertical'} fieldName=
|
|
649
|
-
{config.visualizationType === 'Bar' &&
|
|
650
|
-
{
|
|
651
|
-
{
|
|
652
|
-
{
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
<CheckBox value={config.
|
|
657
|
-
): config.visualizationType !== 'Pie' && (
|
|
658
|
-
<CheckBox value={config.labels} fieldName="labels" label="Display label on data" updateField={updateField}/>
|
|
691
|
+
<Select value={config.visualizationType} fieldName='visualizationType' label='Chart Type' updateField={updateField} options={['Pie', 'Line', 'Bar', 'Combo', 'Paired Bar', 'Spark Line']} />
|
|
692
|
+
{(config.visualizationType === 'Bar' || config.visualizationType === 'Combo') && <Select value={config.visualizationSubType || 'Regular'} fieldName='visualizationSubType' label='Chart Subtype' updateField={updateField} options={['regular', 'stacked']} />}
|
|
693
|
+
{config.visualizationType === 'Bar' && <Select value={config.orientation || 'vertical'} fieldName='orientation' label='Orientation' updateField={updateField} options={['vertical', 'horizontal']} />}
|
|
694
|
+
{config.visualizationType === 'Bar' && <Select value={config.isLollipopChart ? 'lollipop' : config.barStyle || 'flat'} fieldName='barStyle' label='bar style' updateField={updateField} options={showBarStyleOptions()} />}
|
|
695
|
+
{config.visualizationType === 'Bar' && config.barStyle === 'rounded' && <Select value={config.tipRounding || 'top'} fieldName='tipRounding' label='tip rounding' updateField={updateField} options={['top', 'full']} />}
|
|
696
|
+
{config.visualizationType === 'Bar' && config.barStyle === 'rounded' && <Select value={config.roundingStyle || 'standard'} fieldName='roundingStyle' label='rounding style' updateField={updateField} options={['standard', 'shallow', 'finger']} />}
|
|
697
|
+
{config.visualizationType === 'Bar' && config.orientation === 'horizontal' && <Select value={config.yAxis.labelPlacement || 'Below Bar'} section='yAxis' fieldName='labelPlacement' label='Label Placement' updateField={updateField} options={['Below Bar', 'On Date/Category Axis']} />}
|
|
698
|
+
{config.orientation === 'horizontal' && (config.yAxis.labelPlacement === 'Below Bar' || config.yAxis.labelPlacement === 'On Date/Category Axis' || config.visualizationType === 'Paired Bar') ? (
|
|
699
|
+
<CheckBox value={config.yAxis.displayNumbersOnBar} section='yAxis' fieldName='displayNumbersOnBar' label={config.isLollipopChart ? 'Display Numbers after Bar' : 'Display Numbers on Bar'} updateField={updateField} />
|
|
700
|
+
) : (
|
|
701
|
+
config.visualizationType !== 'Pie' && <CheckBox value={config.labels} fieldName='labels' label='Display label on data' updateField={updateField} />
|
|
659
702
|
)}
|
|
660
|
-
{config.visualizationType === 'Pie' && <Select fieldName=
|
|
661
|
-
|
|
662
|
-
|
|
703
|
+
{config.visualizationType === 'Pie' && <Select fieldName='pieType' label='Pie Chart Type' updateField={updateField} options={['Regular', 'Donut']} />}
|
|
704
|
+
|
|
705
|
+
<TextField value={config.title} fieldName='title' label='Title' updateField={updateField} />
|
|
663
706
|
<TextField
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
<Tooltip style={{textTransform: 'none'}}>
|
|
671
|
-
<Tooltip.Target
|
|
707
|
+
value={config.superTitle}
|
|
708
|
+
updateField={updateField}
|
|
709
|
+
fieldName='superTitle'
|
|
710
|
+
label='Super Title'
|
|
711
|
+
placeholder='Super Title'
|
|
712
|
+
tooltip={
|
|
713
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
714
|
+
<Tooltip.Target>
|
|
715
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
716
|
+
</Tooltip.Target>
|
|
672
717
|
<Tooltip.Content>
|
|
673
|
-
|
|
718
|
+
<p>Super Title</p>
|
|
674
719
|
</Tooltip.Content>
|
|
675
720
|
</Tooltip>
|
|
676
|
-
|
|
721
|
+
}
|
|
677
722
|
/>
|
|
678
|
-
|
|
723
|
+
|
|
679
724
|
<TextField
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
<Tooltip style={{textTransform: 'none'}}>
|
|
687
|
-
<Tooltip.Target
|
|
725
|
+
type='textarea'
|
|
726
|
+
value={config.introText}
|
|
727
|
+
updateField={updateField}
|
|
728
|
+
fieldName='introText'
|
|
729
|
+
label='Intro Text'
|
|
730
|
+
tooltip={
|
|
731
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
732
|
+
<Tooltip.Target>
|
|
733
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
734
|
+
</Tooltip.Target>
|
|
688
735
|
<Tooltip.Content>
|
|
689
|
-
|
|
736
|
+
<p>Intro Text</p>
|
|
690
737
|
</Tooltip.Content>
|
|
691
738
|
</Tooltip>
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
<TextField
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
739
|
+
}
|
|
740
|
+
/>
|
|
741
|
+
|
|
742
|
+
<TextField
|
|
743
|
+
type='textarea'
|
|
744
|
+
value={config.description}
|
|
745
|
+
fieldName='description'
|
|
746
|
+
label='Subtext'
|
|
747
|
+
updateField={updateField}
|
|
748
|
+
tooltip={
|
|
749
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
750
|
+
<Tooltip.Target>
|
|
751
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
752
|
+
</Tooltip.Target>
|
|
753
|
+
<Tooltip.Content>
|
|
754
|
+
<p>Enter supporting text to display below the data visualization, if applicable. The following HTML tags are supported: strong, em, sup, and sub.</p>
|
|
755
|
+
</Tooltip.Content>
|
|
756
|
+
</Tooltip>
|
|
757
|
+
}
|
|
758
|
+
/>
|
|
759
|
+
|
|
704
760
|
<TextField
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
<Tooltip style={{textTransform: 'none'}}>
|
|
712
|
-
<Tooltip.Target
|
|
761
|
+
type='textarea'
|
|
762
|
+
value={config.footnotes}
|
|
763
|
+
updateField={updateField}
|
|
764
|
+
fieldName='footnotes'
|
|
765
|
+
label='Footnotes'
|
|
766
|
+
tooltip={
|
|
767
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
768
|
+
<Tooltip.Target>
|
|
769
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
770
|
+
</Tooltip.Target>
|
|
713
771
|
<Tooltip.Content>
|
|
714
|
-
|
|
772
|
+
<p>Footnotes</p>
|
|
715
773
|
</Tooltip.Content>
|
|
716
774
|
</Tooltip>
|
|
717
|
-
|
|
718
|
-
|
|
775
|
+
}
|
|
776
|
+
/>
|
|
719
777
|
|
|
720
|
-
{config.
|
|
721
|
-
<TextField type="number" value={config.height} fieldName="height" label="Chart Height" updateField={updateField}/>
|
|
722
|
-
}
|
|
778
|
+
{config.orientation === 'vertical' && <TextField type='number' value={config.heights.vertical} section='heights' fieldName='vertical' label='Chart Height' updateField={updateField} />}
|
|
723
779
|
</AccordionItemPanel>
|
|
724
780
|
</AccordionItem>
|
|
725
781
|
|
|
726
|
-
|
|
727
|
-
{config.visualizationType !== 'Pie' &&
|
|
782
|
+
{config.visualizationType !== 'Pie' && (
|
|
728
783
|
<AccordionItem>
|
|
729
784
|
<AccordionItemHeading>
|
|
730
|
-
<AccordionItemButton>
|
|
731
|
-
Data Series {((!config.series || config.series.length === 0) || (config.visualizationType === 'Paired Bar' && config.series.length < 2)) && <WarningImage width="25" className="warning-icon"/>}
|
|
732
|
-
</AccordionItemButton>
|
|
785
|
+
<AccordionItemButton>Data Series {(!config.series || config.series.length === 0 || (config.visualizationType === 'Paired Bar' && config.series.length < 2)) && <WarningImage width='25' className='warning-icon' />}</AccordionItemButton>
|
|
733
786
|
</AccordionItemHeading>
|
|
734
787
|
<AccordionItemPanel>
|
|
735
|
-
{(
|
|
736
|
-
{(
|
|
788
|
+
{(!config.series || config.series.length === 0) && config.visualizationType !== 'Paired Bar' && <p className='warning'>At least one series is required</p>}
|
|
789
|
+
{(!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>}
|
|
737
790
|
{config.series && config.series.length !== 0 && (
|
|
738
791
|
<>
|
|
739
792
|
<fieldset>
|
|
740
|
-
<legend className=
|
|
741
|
-
Displaying
|
|
742
|
-
</legend>
|
|
793
|
+
<legend className='edit-label float-left'>Displaying</legend>
|
|
743
794
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
744
|
-
<Tooltip.Target
|
|
795
|
+
<Tooltip.Target>
|
|
796
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
797
|
+
</Tooltip.Target>
|
|
745
798
|
<Tooltip.Content>
|
|
746
799
|
<p>A data series is a set of related data points plotted in a chart and typically represented in the chart legend.</p>
|
|
747
800
|
</Tooltip.Content>
|
|
748
801
|
</Tooltip>
|
|
749
802
|
</fieldset>
|
|
750
|
-
<ul className="series-list">
|
|
751
|
-
{config.series.map((series, i) => {
|
|
752
803
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
804
|
+
<DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
|
|
805
|
+
<Droppable droppableId='filter_order'>
|
|
806
|
+
{provided => (
|
|
807
|
+
<ul {...provided.droppableProps} className='series-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
808
|
+
{config.series.map((series, i) => {
|
|
809
|
+
if (config.visualizationType === 'Combo') {
|
|
810
|
+
let changeType = (i, value) => {
|
|
811
|
+
let series = [...config.series]
|
|
812
|
+
series[i].type = value
|
|
813
|
+
|
|
814
|
+
series[i].axis = 'Left'
|
|
815
|
+
|
|
816
|
+
updateConfig({ ...config, series })
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
let typeDropdown = (
|
|
820
|
+
<select
|
|
821
|
+
value={series.type}
|
|
822
|
+
onChange={event => {
|
|
823
|
+
changeType(i, event.target.value)
|
|
824
|
+
}}
|
|
825
|
+
style={{ width: '100px', marginRight: '10px' }}
|
|
826
|
+
>
|
|
827
|
+
<option value='' default>
|
|
828
|
+
Select
|
|
829
|
+
</option>
|
|
830
|
+
<option value='Bar'>Bar</option>
|
|
831
|
+
<option value='Line'>Solid Line</option>
|
|
832
|
+
<option value='dashed-sm'>Small Dashed</option>
|
|
833
|
+
<option value='dashed-md'>Medium Dashed</option>
|
|
834
|
+
<option value='dashed-lg'>Large Dashed</option>
|
|
835
|
+
</select>
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
return (
|
|
839
|
+
<Draggable key={series.dataKey} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
|
|
840
|
+
{(provided, snapshot) => (
|
|
841
|
+
<li>
|
|
842
|
+
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
843
|
+
<div className={`series-list__name${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}>
|
|
844
|
+
<div className='series-list__name-text'>{series.dataKey}</div>
|
|
845
|
+
</div>
|
|
846
|
+
<span>
|
|
847
|
+
<span className='series-list__dropdown'>{typeDropdown}</span>
|
|
848
|
+
{config.series && config.series.length > 1 && (
|
|
849
|
+
<button className='series-list__remove' onClick={() => removeSeries(series.dataKey)}>
|
|
850
|
+
×
|
|
851
|
+
</button>
|
|
852
|
+
)}
|
|
853
|
+
</span>
|
|
854
|
+
</div>
|
|
855
|
+
</li>
|
|
856
|
+
)}
|
|
857
|
+
</Draggable>
|
|
858
|
+
)
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
return (
|
|
862
|
+
<Draggable key={series.dataKey} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
|
|
863
|
+
{(provided, snapshot) => (
|
|
864
|
+
<li
|
|
865
|
+
key={series.dataKey}
|
|
866
|
+
className={snapshot.isDragging ? 'currently-dragging' : ''}
|
|
867
|
+
style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)}
|
|
868
|
+
ref={provided.innerRef}
|
|
869
|
+
{...provided.draggableProps}
|
|
870
|
+
{...provided.dragHandleProps}
|
|
871
|
+
>
|
|
872
|
+
{/*<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>*/}
|
|
873
|
+
<div className='series-list__name' data-title={series.dataKey}>
|
|
874
|
+
<div className='series-list__name--text'>{series.dataKey}</div>
|
|
875
|
+
</div>
|
|
876
|
+
{config.series && config.series.length > 1 && (
|
|
877
|
+
<button className='series-list__remove' onClick={() => removeSeries(series.dataKey)}>
|
|
878
|
+
×
|
|
879
|
+
</button>
|
|
880
|
+
)}
|
|
881
|
+
{/*</div>*/}
|
|
882
|
+
</li>
|
|
883
|
+
)}
|
|
884
|
+
</Draggable>
|
|
885
|
+
)
|
|
886
|
+
})}
|
|
887
|
+
{provided.placeholder}
|
|
888
|
+
</ul>
|
|
889
|
+
)}
|
|
890
|
+
</Droppable>
|
|
891
|
+
</DragDropContext>
|
|
892
|
+
</>
|
|
893
|
+
)}
|
|
894
|
+
|
|
895
|
+
<Select
|
|
896
|
+
fieldName='visualizationType'
|
|
897
|
+
label='Add Data Series'
|
|
898
|
+
initial='Select'
|
|
899
|
+
onChange={e => {
|
|
900
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
901
|
+
addNewSeries(e.target.value)
|
|
902
|
+
}
|
|
903
|
+
e.target.value = ''
|
|
904
|
+
}}
|
|
905
|
+
options={getColumns()}
|
|
906
|
+
/>
|
|
907
|
+
{config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
|
|
908
|
+
<>
|
|
909
|
+
<span className='divider-heading'>Confidence Keys</span>
|
|
910
|
+
<Select value={config.confidenceKeys.upper || ''} section='confidenceKeys' fieldName='upper' label='Upper' updateField={updateField} initial='Select' options={getColumns()} />
|
|
911
|
+
<Select value={config.confidenceKeys.lower || ''} section='confidenceKeys' fieldName='lower' label='Lower' updateField={updateField} initial='Select' options={getColumns()} />
|
|
912
|
+
</>
|
|
913
|
+
)}
|
|
914
|
+
|
|
915
|
+
{config.series && config.series.length === 1 && <Select fieldName='visualizationType' label='Rank by Value' initial='Select' onChange={e => sortSeries(e.target.value)} options={['asc', 'desc']} />}
|
|
916
|
+
</AccordionItemPanel>
|
|
917
|
+
</AccordionItem>
|
|
918
|
+
)}
|
|
919
|
+
|
|
920
|
+
{hasRightAxis && config.series && config.visualizationType === 'Combo' && (
|
|
921
|
+
<AccordionItem>
|
|
922
|
+
<AccordionItemHeading>
|
|
923
|
+
<AccordionItemButton>Assign Data Series Axis</AccordionItemButton>
|
|
924
|
+
</AccordionItemHeading>
|
|
925
|
+
<AccordionItemPanel>
|
|
926
|
+
<p>Only line series data can be assigned to the right axis. Check the data series section above.</p>
|
|
927
|
+
{config.series && config.series.filter(series => checkIsLine(series.type)) && (
|
|
928
|
+
<>
|
|
929
|
+
<fieldset>
|
|
930
|
+
<legend className='edit-label float-left'>Displaying</legend>
|
|
931
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
932
|
+
<Tooltip.Target>
|
|
933
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
934
|
+
</Tooltip.Target>
|
|
935
|
+
<Tooltip.Content>
|
|
936
|
+
<p>Assign an axis for the series</p>
|
|
937
|
+
</Tooltip.Content>
|
|
938
|
+
</Tooltip>
|
|
939
|
+
</fieldset>
|
|
940
|
+
<ul className='series-list'>
|
|
941
|
+
{config.series &&
|
|
942
|
+
config.series.map((series, i) => {
|
|
943
|
+
if (series.type === 'Bar') return false // can't set individual bars atm.
|
|
944
|
+
|
|
945
|
+
let changeAxis = (i, value) => {
|
|
946
|
+
let series = [...config.series]
|
|
947
|
+
series[i].axis = value
|
|
757
948
|
updateConfig({ ...config, series })
|
|
758
949
|
}
|
|
759
950
|
|
|
760
|
-
let
|
|
761
|
-
<select
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
<option value=
|
|
769
|
-
|
|
951
|
+
let axisDropdown = (
|
|
952
|
+
<select
|
|
953
|
+
value={series.axis}
|
|
954
|
+
onChange={event => {
|
|
955
|
+
changeAxis(i, event.target.value)
|
|
956
|
+
}}
|
|
957
|
+
style={{ width: '100px', marginRight: '10px' }}
|
|
958
|
+
>
|
|
959
|
+
<option value='Left' default>
|
|
960
|
+
left
|
|
961
|
+
</option>
|
|
962
|
+
<option value='Right'>right</option>
|
|
770
963
|
</select>
|
|
771
964
|
)
|
|
772
965
|
|
|
773
966
|
return (
|
|
774
967
|
<li key={series.dataKey}>
|
|
775
968
|
<div className={`series-list__name${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}>
|
|
776
|
-
<div className=
|
|
969
|
+
<div className='series-list__name-text'>{series.dataKey}</div>
|
|
777
970
|
</div>
|
|
778
971
|
<span>
|
|
779
|
-
<span className=
|
|
780
|
-
{config.series && config.series.length > 1 &&
|
|
781
|
-
<button className="series-list__remove" onClick={() => removeSeries(series.dataKey)}>×</button>
|
|
782
|
-
}
|
|
972
|
+
<span className='series-list__dropdown'>{axisDropdown}</span>
|
|
783
973
|
</span>
|
|
784
974
|
</li>
|
|
785
975
|
)
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
return (
|
|
789
|
-
<li key={series.dataKey}>
|
|
790
|
-
<div className="series-list__name" data-title={series.dataKey}>
|
|
791
|
-
<div className="series-list__name--text">
|
|
792
|
-
{series.dataKey}
|
|
793
|
-
</div>
|
|
794
|
-
</div>
|
|
795
|
-
{config.series && config.series.length > 1 &&
|
|
796
|
-
<button className="series-list__remove" onClick={() => removeSeries(series.dataKey)}>×</button>
|
|
797
|
-
}
|
|
798
|
-
</li>
|
|
799
|
-
)
|
|
800
|
-
})}
|
|
976
|
+
})}
|
|
801
977
|
</ul>
|
|
802
|
-
</>)}
|
|
803
|
-
|
|
804
|
-
<Select fieldName="visualizationType" label="Add Data Series" initial="Select" onChange={(e) => {
|
|
805
|
-
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
806
|
-
addNewSeries(e.target.value)
|
|
807
|
-
}
|
|
808
|
-
e.target.value = ''
|
|
809
|
-
}} options={getColumns()}/>
|
|
810
|
-
{config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
|
|
811
|
-
<>
|
|
812
|
-
<span className="divider-heading">Confidence Keys</span>
|
|
813
|
-
<Select value={config.confidenceKeys.upper || ''} section="confidenceKeys" fieldName="upper" label="Upper" updateField={updateField} initial="Select" options={getColumns()}/>
|
|
814
|
-
<Select value={config.confidenceKeys.lower || ''} section="confidenceKeys" fieldName="lower" label="Lower" updateField={updateField} initial="Select" options={getColumns()}/>
|
|
815
978
|
</>
|
|
816
979
|
)}
|
|
817
|
-
|
|
818
|
-
{config.series && config.series.length === 1 && <Select
|
|
819
|
-
fieldName="visualizationType"
|
|
820
|
-
label="Rank by Value"
|
|
821
|
-
initial="Select"
|
|
822
|
-
onChange={(e) => sortSeries(e.target.value)}
|
|
823
|
-
options={['asc', 'desc']} />}
|
|
824
|
-
|
|
825
980
|
</AccordionItemPanel>
|
|
826
981
|
</AccordionItem>
|
|
827
|
-
}
|
|
982
|
+
)}
|
|
828
983
|
|
|
829
984
|
<AccordionItem>
|
|
830
985
|
<AccordionItemHeading>
|
|
831
986
|
<AccordionItemButton>
|
|
832
|
-
{config.visualizationType !== 'Pie'
|
|
833
|
-
|
|
834
|
-
: 'Data Format'
|
|
835
|
-
}
|
|
836
|
-
{config.visualizationType === 'Pie' && !config.yAxis.dataKey && <WarningImage width="25" className="warning-icon"/>}
|
|
987
|
+
{config.visualizationType !== 'Pie' ? (config.orientation !== 'horizontal' ? 'Left Value Axis' : 'Value Axis') : 'Data Format'}
|
|
988
|
+
{config.visualizationType === 'Pie' && !config.yAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
|
|
837
989
|
</AccordionItemButton>
|
|
838
990
|
</AccordionItemHeading>
|
|
839
991
|
<AccordionItemPanel>
|
|
840
|
-
{config.visualizationType === 'Pie' &&
|
|
841
|
-
<Select
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
992
|
+
{config.visualizationType === 'Pie' && (
|
|
993
|
+
<Select
|
|
994
|
+
value={config.yAxis.dataKey || ''}
|
|
995
|
+
section='yAxis'
|
|
996
|
+
fieldName='dataKey'
|
|
997
|
+
label='Data Column'
|
|
998
|
+
initial='Select'
|
|
999
|
+
required={true}
|
|
1000
|
+
updateField={updateField}
|
|
1001
|
+
options={getColumns(false)}
|
|
1002
|
+
tooltip={
|
|
1003
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1004
|
+
<Tooltip.Target>
|
|
1005
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1006
|
+
</Tooltip.Target>
|
|
1007
|
+
<Tooltip.Content>
|
|
1008
|
+
<p>Select the source data to be visually represented.</p>
|
|
1009
|
+
</Tooltip.Content>
|
|
1010
|
+
</Tooltip>
|
|
1011
|
+
}
|
|
1012
|
+
/>
|
|
1013
|
+
)}
|
|
850
1014
|
{config.visualizationType !== 'Pie' && (
|
|
851
1015
|
<>
|
|
852
|
-
<TextField value={config.yAxis.label} section=
|
|
853
|
-
<
|
|
854
|
-
<TextField value={config.yAxis.
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
1016
|
+
<TextField value={config.yAxis.label} section='yAxis' fieldName='label' label='Label' updateField={updateField} />
|
|
1017
|
+
{config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && <CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />}
|
|
1018
|
+
<TextField value={config.yAxis.numTicks} placeholder='Auto' type='number' section='yAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
|
|
1019
|
+
<TextField
|
|
1020
|
+
value={config.yAxis.size}
|
|
1021
|
+
type='number'
|
|
1022
|
+
section='yAxis'
|
|
1023
|
+
fieldName='size'
|
|
1024
|
+
label={config.orientation === 'horizontal' ? 'Size (Height)' : 'Size (Width)'}
|
|
1025
|
+
className='number-narrow'
|
|
1026
|
+
updateField={updateField}
|
|
1027
|
+
tooltip={
|
|
1028
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1029
|
+
<Tooltip.Target>
|
|
1030
|
+
<Icon display='question' />
|
|
1031
|
+
</Tooltip.Target>
|
|
1032
|
+
<Tooltip.Content>
|
|
1033
|
+
<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>
|
|
1034
|
+
</Tooltip.Content>
|
|
1035
|
+
</Tooltip>
|
|
1036
|
+
}
|
|
1037
|
+
/>
|
|
1038
|
+
{config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
|
|
1039
|
+
{config.orientation !== 'horizontal' && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Display Gridlines' updateField={updateField} />}
|
|
863
1040
|
</>
|
|
864
1041
|
)}
|
|
865
|
-
<span className=
|
|
866
|
-
<CheckBox value={config.dataFormat.commas} section=
|
|
867
|
-
<
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
{config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
|
|
875
|
-
</Tooltip.Content>
|
|
876
|
-
</Tooltip>
|
|
877
|
-
}/>
|
|
878
|
-
<TextField value={config.dataFormat.suffix} section="dataFormat" fieldName="suffix" label="Suffix" updateField={updateField} tooltip={
|
|
1042
|
+
<span className='divider-heading'>Number Formatting</span>
|
|
1043
|
+
<CheckBox value={config.dataFormat.commas} section='dataFormat' fieldName='commas' label='Add commas' updateField={updateField} />
|
|
1044
|
+
<CheckBox
|
|
1045
|
+
value={config.dataFormat.abbreviated}
|
|
1046
|
+
section='dataFormat'
|
|
1047
|
+
fieldName='abbreviated'
|
|
1048
|
+
label='Abbreviate Axis Values'
|
|
1049
|
+
updateField={updateField}
|
|
1050
|
+
tooltip={
|
|
879
1051
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
880
|
-
<Tooltip.Target
|
|
1052
|
+
<Tooltip.Target>
|
|
1053
|
+
<Icon display='question' />
|
|
1054
|
+
</Tooltip.Target>
|
|
881
1055
|
<Tooltip.Content>
|
|
882
|
-
|
|
883
|
-
{config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
|
|
1056
|
+
<p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
|
|
884
1057
|
</Tooltip.Content>
|
|
885
1058
|
</Tooltip>
|
|
886
|
-
}
|
|
1059
|
+
}
|
|
1060
|
+
/>
|
|
1061
|
+
<TextField value={config.dataFormat.roundTo} type='number' section='dataFormat' fieldName='roundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
|
|
1062
|
+
<div className='two-col-inputs'>
|
|
1063
|
+
<TextField
|
|
1064
|
+
value={config.dataFormat.prefix}
|
|
1065
|
+
section='dataFormat'
|
|
1066
|
+
fieldName='prefix'
|
|
1067
|
+
label='Prefix'
|
|
1068
|
+
updateField={updateField}
|
|
1069
|
+
tooltip={
|
|
1070
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1071
|
+
<Tooltip.Target>
|
|
1072
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1073
|
+
</Tooltip.Target>
|
|
1074
|
+
<Tooltip.Content>
|
|
1075
|
+
{config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
|
|
1076
|
+
{config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
|
|
1077
|
+
</Tooltip.Content>
|
|
1078
|
+
</Tooltip>
|
|
1079
|
+
}
|
|
1080
|
+
/>
|
|
1081
|
+
<TextField
|
|
1082
|
+
value={config.dataFormat.suffix}
|
|
1083
|
+
section='dataFormat'
|
|
1084
|
+
fieldName='suffix'
|
|
1085
|
+
label='Suffix'
|
|
1086
|
+
updateField={updateField}
|
|
1087
|
+
tooltip={
|
|
1088
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1089
|
+
<Tooltip.Target>
|
|
1090
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1091
|
+
</Tooltip.Target>
|
|
1092
|
+
<Tooltip.Content>
|
|
1093
|
+
{config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
|
|
1094
|
+
{config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
|
|
1095
|
+
</Tooltip.Content>
|
|
1096
|
+
</Tooltip>
|
|
1097
|
+
}
|
|
1098
|
+
/>
|
|
887
1099
|
</div>
|
|
888
|
-
|
|
889
|
-
{
|
|
890
|
-
<>
|
|
891
|
-
<CheckBox value={config.xAxis.hideAxis} section="xAxis" fieldName="hideAxis" label="Hide Axis" updateField={updateField} />
|
|
892
|
-
<CheckBox value={config.xAxis.hideLabel} section="xAxis" fieldName="hideLabel" label="Hide Label" updateField={updateField} />
|
|
893
|
-
<CheckBox value={config.xAxis.hideTicks} section="xAxis" fieldName="hideTicks" label="Hide Ticks" updateField={updateField} />
|
|
894
|
-
<TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='update max value' type='number' placeholder='Auto' updateField={updateField} />
|
|
895
|
-
<span style={{color:'red',display:'block'}} >{warningMsg.maxMsg}</span>
|
|
896
|
-
</>
|
|
897
|
-
: (config.visualizationType !=='Pie') &&
|
|
1100
|
+
|
|
1101
|
+
{config.orientation === 'horizontal' ? ( // horizontal - x is vertical y is horizontal
|
|
898
1102
|
<>
|
|
899
|
-
<CheckBox value={config.
|
|
900
|
-
<CheckBox value={config.
|
|
901
|
-
<CheckBox value={config.
|
|
902
|
-
<TextField value={config.
|
|
903
|
-
<span style={{color:'red',display:'block'}}
|
|
904
|
-
<TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='update min value' placeholder='Auto' updateField={updateField} />
|
|
905
|
-
<span style={{color:'red',display:'block'}} >{warningMsg.minMsg}</span>
|
|
1103
|
+
<CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
1104
|
+
<CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
|
|
1105
|
+
<CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1106
|
+
<TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='update max value' type='number' placeholder='Auto' updateField={updateField} />
|
|
1107
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
906
1108
|
</>
|
|
907
|
-
|
|
1109
|
+
) : (
|
|
1110
|
+
config.visualizationType !== 'Pie' && (
|
|
1111
|
+
<>
|
|
1112
|
+
<CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
1113
|
+
<CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
|
|
1114
|
+
<CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1115
|
+
<TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='update max value' placeholder='Auto' updateField={updateField} />
|
|
1116
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
1117
|
+
<TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='update min value' placeholder='Auto' updateField={updateField} />
|
|
1118
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
|
|
1119
|
+
</>
|
|
1120
|
+
)
|
|
1121
|
+
)}
|
|
908
1122
|
</AccordionItemPanel>
|
|
909
1123
|
</AccordionItem>
|
|
910
1124
|
|
|
1125
|
+
{/* Right Value Axis Settings */}
|
|
1126
|
+
{hasRightAxis && (
|
|
1127
|
+
<AccordionItem>
|
|
1128
|
+
<AccordionItemHeading>
|
|
1129
|
+
<AccordionItemButton>Right Value Axis</AccordionItemButton>
|
|
1130
|
+
</AccordionItemHeading>
|
|
1131
|
+
<AccordionItemPanel>
|
|
1132
|
+
<TextField value={config.yAxis.rightLabel} section='yAxis' fieldName='rightLabel' label='Label' updateField={updateField} />
|
|
1133
|
+
<TextField value={config.yAxis.rightNumTicks} placeholder='Auto' type='number' section='yAxis' fieldName='rightNumTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
|
|
1134
|
+
<TextField value={config.yAxis.rightAxisSize} type='number' section='yAxis' fieldName='rightAxisSize' label='Size (Width)' className='number-narrow' updateField={updateField} />
|
|
1135
|
+
<TextField value={config.yAxis.rightLabelOffsetSize} type='number' section='yAxis' fieldName='rightLabelOffsetSize' label='Label Offset' className='number-narrow' updateField={updateField} />
|
|
1136
|
+
|
|
1137
|
+
<span className='divider-heading'>Number Formatting</span>
|
|
1138
|
+
<CheckBox value={config.dataFormat.rightCommas} section='dataFormat' fieldName='rightCommas' label='Add commas' updateField={updateField} />
|
|
1139
|
+
<TextField value={config.dataFormat.rightRoundTo} type='number' section='dataFormat' fieldName='rightRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
|
|
1140
|
+
<div className='two-col-inputs'>
|
|
1141
|
+
<TextField
|
|
1142
|
+
value={config.dataFormat.rightPrefix}
|
|
1143
|
+
section='dataFormat'
|
|
1144
|
+
fieldName='rightPrefix'
|
|
1145
|
+
label='Prefix'
|
|
1146
|
+
updateField={updateField}
|
|
1147
|
+
tooltip={
|
|
1148
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1149
|
+
<Tooltip.Target>
|
|
1150
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1151
|
+
</Tooltip.Target>
|
|
1152
|
+
<Tooltip.Content>
|
|
1153
|
+
{config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
|
|
1154
|
+
{config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
|
|
1155
|
+
</Tooltip.Content>
|
|
1156
|
+
</Tooltip>
|
|
1157
|
+
}
|
|
1158
|
+
/>
|
|
1159
|
+
<TextField
|
|
1160
|
+
value={config.dataFormat.rightSuffix}
|
|
1161
|
+
section='dataFormat'
|
|
1162
|
+
fieldName='rightSuffix'
|
|
1163
|
+
label='Suffix'
|
|
1164
|
+
updateField={updateField}
|
|
1165
|
+
tooltip={
|
|
1166
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1167
|
+
<Tooltip.Target>
|
|
1168
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1169
|
+
</Tooltip.Target>
|
|
1170
|
+
<Tooltip.Content>
|
|
1171
|
+
{config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
|
|
1172
|
+
{config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
|
|
1173
|
+
</Tooltip.Content>
|
|
1174
|
+
</Tooltip>
|
|
1175
|
+
}
|
|
1176
|
+
/>
|
|
1177
|
+
</div>
|
|
1178
|
+
|
|
1179
|
+
<CheckBox value={config.yAxis.rightHideAxis} section='yAxis' fieldName='rightHideAxis' label='Hide Axis' updateField={updateField} />
|
|
1180
|
+
<CheckBox value={config.yAxis.rightHideLabel} section='yAxis' fieldName='rightHideLabel' label='Hide Label' updateField={updateField} />
|
|
1181
|
+
<CheckBox value={config.yAxis.rightHideTicks} section='yAxis' fieldName='rightHideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1182
|
+
</AccordionItemPanel>
|
|
1183
|
+
</AccordionItem>
|
|
1184
|
+
)}
|
|
1185
|
+
|
|
911
1186
|
<AccordionItem>
|
|
912
1187
|
<AccordionItemHeading>
|
|
913
1188
|
<AccordionItemButton>
|
|
914
|
-
{config.visualizationType !== 'Pie'
|
|
915
|
-
|
|
916
|
-
: 'Segments'
|
|
917
|
-
}
|
|
918
|
-
{!config.xAxis.dataKey && <WarningImage width="25" className="warning-icon"/>}
|
|
1189
|
+
{config.visualizationType !== 'Pie' ? (config.visualizationType === 'Bar' ? 'Date/Category Axis' : 'Date/Category Axis') : 'Segments'}
|
|
1190
|
+
{!config.xAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
|
|
919
1191
|
</AccordionItemButton>
|
|
920
1192
|
</AccordionItemHeading>
|
|
921
1193
|
<AccordionItemPanel>
|
|
922
|
-
{config.visualizationType !== 'Pie' &&
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
<
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1194
|
+
{config.visualizationType !== 'Pie' && (
|
|
1195
|
+
<>
|
|
1196
|
+
<Select value={config.xAxis.type} section='xAxis' fieldName='type' label='Data Type' updateField={updateField} options={['categorical', 'date']} />
|
|
1197
|
+
<Select
|
|
1198
|
+
value={config.xAxis.dataKey || ''}
|
|
1199
|
+
section='xAxis'
|
|
1200
|
+
fieldName='dataKey'
|
|
1201
|
+
label='Data Key'
|
|
1202
|
+
initial='Select'
|
|
1203
|
+
required={true}
|
|
1204
|
+
updateField={updateField}
|
|
1205
|
+
options={getColumns(false)}
|
|
1206
|
+
tooltip={
|
|
1207
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1208
|
+
<Tooltip.Target>
|
|
1209
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1210
|
+
</Tooltip.Target>
|
|
1211
|
+
<Tooltip.Content>
|
|
1212
|
+
<p>Select the column or row containing the categories or dates for this axis. </p>
|
|
1213
|
+
</Tooltip.Content>
|
|
1214
|
+
</Tooltip>
|
|
1215
|
+
}
|
|
1216
|
+
/>
|
|
1217
|
+
</>
|
|
1218
|
+
)}
|
|
933
1219
|
|
|
934
|
-
{config.visualizationType === 'Pie' &&
|
|
935
|
-
<Select
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1220
|
+
{config.visualizationType === 'Pie' && (
|
|
1221
|
+
<Select
|
|
1222
|
+
value={config.xAxis.dataKey || ''}
|
|
1223
|
+
section='xAxis'
|
|
1224
|
+
fieldName='dataKey'
|
|
1225
|
+
label='Segment Labels'
|
|
1226
|
+
initial='Select'
|
|
1227
|
+
required={true}
|
|
1228
|
+
updateField={updateField}
|
|
1229
|
+
options={getColumns(false)}
|
|
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
|
+
<p>Select the source row or column that contains the segment labels. Depending on the data structure, it may be listed as "Key."</p>
|
|
1237
|
+
</Tooltip.Content>
|
|
1238
|
+
</Tooltip>
|
|
1239
|
+
}
|
|
1240
|
+
/>
|
|
1241
|
+
)}
|
|
944
1242
|
|
|
945
1243
|
{config.visualizationType !== 'Pie' && (
|
|
946
1244
|
<>
|
|
947
|
-
<TextField value={config.xAxis.label} section=
|
|
1245
|
+
<TextField value={config.xAxis.label} section='xAxis' fieldName='label' label='Label' updateField={updateField} />
|
|
948
1246
|
|
|
949
1247
|
{config.xAxis.type === 'date' && (
|
|
950
1248
|
<>
|
|
951
|
-
<p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
|
|
952
|
-
|
|
953
|
-
|
|
1249
|
+
<p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
|
|
1250
|
+
Format how charts should parse and display your dates using{' '}
|
|
1251
|
+
<a href='https://github.com/d3/d3-time-format#locale_format' target='_blank' rel='noreferrer'>
|
|
1252
|
+
these guidelines
|
|
1253
|
+
</a>
|
|
1254
|
+
.
|
|
1255
|
+
</p>
|
|
1256
|
+
<TextField value={config.xAxis.dateParseFormat} section='xAxis' fieldName='dateParseFormat' placeholder='Ex. %Y-%m-%d' label='Date Parse Format' updateField={updateField} />
|
|
1257
|
+
<TextField value={config.xAxis.dateDisplayFormat} section='xAxis' fieldName='dateDisplayFormat' placeholder='Ex. %Y-%m-%d' label='Date Display Format' updateField={updateField} />
|
|
954
1258
|
</>
|
|
955
1259
|
)}
|
|
956
1260
|
|
|
957
|
-
<CheckBox
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1261
|
+
<CheckBox
|
|
1262
|
+
value={config.exclusions.active}
|
|
1263
|
+
section='exclusions'
|
|
1264
|
+
fieldName='active'
|
|
1265
|
+
label={config.xAxis.type === 'date' ? 'Limit by start and/or end dates' : 'Exclude one or more values'}
|
|
1266
|
+
tooltip={
|
|
1267
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1268
|
+
<Tooltip.Target>
|
|
1269
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1270
|
+
</Tooltip.Target>
|
|
1271
|
+
<Tooltip.Content>
|
|
1272
|
+
<p>When this option is checked, you can select source-file values for exclusion from the date/category axis. </p>
|
|
1273
|
+
</Tooltip.Content>
|
|
1274
|
+
</Tooltip>
|
|
1275
|
+
}
|
|
1276
|
+
updateField={updateField}
|
|
1277
|
+
/>
|
|
965
1278
|
|
|
966
|
-
{config.exclusions.active &&
|
|
1279
|
+
{config.exclusions.active && (
|
|
967
1280
|
<>
|
|
968
|
-
{config.xAxis.type === 'categorical' &&
|
|
1281
|
+
{config.xAxis.type === 'categorical' && (
|
|
969
1282
|
<>
|
|
970
|
-
{config.exclusions.keys.length > 0 &&
|
|
1283
|
+
{config.exclusions.keys.length > 0 && (
|
|
971
1284
|
<>
|
|
972
1285
|
<fieldset>
|
|
973
|
-
<legend className=
|
|
1286
|
+
<legend className='edit-label'>Excluded Keys</legend>
|
|
974
1287
|
</fieldset>
|
|
975
|
-
<ExclusionsList/>
|
|
1288
|
+
<ExclusionsList />
|
|
976
1289
|
</>
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
<Select
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
e
|
|
984
|
-
|
|
1290
|
+
)}
|
|
1291
|
+
|
|
1292
|
+
<Select
|
|
1293
|
+
fieldName='visualizationType'
|
|
1294
|
+
label='Add Exclusion'
|
|
1295
|
+
initial='Select'
|
|
1296
|
+
onChange={e => {
|
|
1297
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
1298
|
+
addNewExclusion(e.target.value)
|
|
1299
|
+
}
|
|
1300
|
+
e.target.value = ''
|
|
1301
|
+
}}
|
|
1302
|
+
options={getDataValues(config.xAxis.dataKey, true)}
|
|
1303
|
+
/>
|
|
985
1304
|
</>
|
|
986
|
-
}
|
|
1305
|
+
)}
|
|
987
1306
|
|
|
988
|
-
{config.xAxis.type === 'date' &&
|
|
1307
|
+
{config.xAxis.type === 'date' && (
|
|
989
1308
|
<>
|
|
990
|
-
<TextField type=
|
|
991
|
-
<TextField type=
|
|
1309
|
+
<TextField type='date' section='exclusions' fieldName='dateStart' label='Start Date' updateField={updateField} value={config.exclusions.dateStart || ''} />
|
|
1310
|
+
<TextField type='date' section='exclusions' fieldName='dateEnd' label='End Date' updateField={updateField} value={config.exclusions.dateEnd || ''} />
|
|
992
1311
|
</>
|
|
993
|
-
}
|
|
994
|
-
</>
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
{config.xAxis.type === 'date' &&
|
|
998
|
-
<>
|
|
999
|
-
<TextField value={config.xAxis.numTicks} placeholder="Auto" type="number" min="1" section="xAxis" fieldName="numTicks" label="Number of ticks" className="number-narrow" updateField={updateField}/>
|
|
1312
|
+
)}
|
|
1000
1313
|
</>
|
|
1001
|
-
}
|
|
1314
|
+
)}
|
|
1315
|
+
<TextField value={config.xAxis.numTicks} placeholder='Auto' type='number' min='1' section='xAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
|
|
1002
1316
|
|
|
1003
|
-
<TextField value={config.xAxis.size} type=
|
|
1317
|
+
<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} />
|
|
1004
1318
|
|
|
1005
|
-
{config.yAxis.labelPlacement !== 'Below Bar' &&
|
|
1006
|
-
|
|
1007
|
-
}
|
|
1008
|
-
{(config.orientation === 'horizontal') ?
|
|
1319
|
+
{config.yAxis.labelPlacement !== 'Below Bar' && <TextField value={config.xAxis.tickRotation} type='number' min='0' section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
|
|
1320
|
+
{config.orientation === 'horizontal' ? (
|
|
1009
1321
|
<>
|
|
1010
|
-
<CheckBox value={config.yAxis.hideAxis} section=
|
|
1011
|
-
<CheckBox value={config.yAxis.hideLabel} section=
|
|
1322
|
+
<CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
1323
|
+
<CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
|
|
1012
1324
|
</>
|
|
1013
|
-
|
|
1325
|
+
) : (
|
|
1014
1326
|
<>
|
|
1015
|
-
<CheckBox value={config.xAxis.hideAxis} section=
|
|
1016
|
-
<CheckBox value={config.xAxis.hideLabel} section=
|
|
1017
|
-
<CheckBox value={config.xAxis.hideTicks} section=
|
|
1327
|
+
<CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
1328
|
+
<CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
|
|
1329
|
+
<CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1018
1330
|
</>
|
|
1019
|
-
}
|
|
1331
|
+
)}
|
|
1020
1332
|
</>
|
|
1021
1333
|
)}
|
|
1022
1334
|
|
|
1023
|
-
{config.visualizationType === 'Pie' &&
|
|
1335
|
+
{config.visualizationType === 'Pie' && (
|
|
1024
1336
|
<>
|
|
1025
|
-
<CheckBox
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1337
|
+
<CheckBox
|
|
1338
|
+
value={config.exclusions.active}
|
|
1339
|
+
section='exclusions'
|
|
1340
|
+
fieldName='active'
|
|
1341
|
+
label={'Exclude one or more values'}
|
|
1342
|
+
updateField={updateField}
|
|
1343
|
+
tooltip={
|
|
1344
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1345
|
+
<Tooltip.Target>
|
|
1346
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1347
|
+
</Tooltip.Target>
|
|
1348
|
+
<Tooltip.Content>
|
|
1349
|
+
<p>When this option is checked, you can select values for exclusion from the pie segments.</p>
|
|
1350
|
+
</Tooltip.Content>
|
|
1351
|
+
</Tooltip>
|
|
1352
|
+
}
|
|
1353
|
+
/>
|
|
1354
|
+
{config.exclusions.active && (
|
|
1034
1355
|
<>
|
|
1035
|
-
{config.exclusions.keys.length > 0 &&
|
|
1356
|
+
{config.exclusions.keys.length > 0 && (
|
|
1036
1357
|
<>
|
|
1037
1358
|
<fieldset>
|
|
1038
|
-
<legend className=
|
|
1359
|
+
<legend className='edit-label'>Excluded Keys</legend>
|
|
1039
1360
|
</fieldset>
|
|
1040
|
-
<ExclusionsList/>
|
|
1361
|
+
<ExclusionsList />
|
|
1041
1362
|
</>
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
<Select
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
e
|
|
1049
|
-
|
|
1363
|
+
)}
|
|
1364
|
+
|
|
1365
|
+
<Select
|
|
1366
|
+
fieldName='visualizationType'
|
|
1367
|
+
label='Add Exclusion'
|
|
1368
|
+
initial='Select'
|
|
1369
|
+
onChange={e => {
|
|
1370
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
1371
|
+
addNewExclusion(e.target.value)
|
|
1372
|
+
}
|
|
1373
|
+
e.target.value = ''
|
|
1374
|
+
}}
|
|
1375
|
+
options={getDataValues(config.xAxis.dataKey, true)}
|
|
1376
|
+
/>
|
|
1050
1377
|
</>
|
|
1051
|
-
}
|
|
1378
|
+
)}
|
|
1052
1379
|
</>
|
|
1053
|
-
}
|
|
1380
|
+
)}
|
|
1054
1381
|
</AccordionItemPanel>
|
|
1055
1382
|
</AccordionItem>
|
|
1056
1383
|
|
|
1057
|
-
{
|
|
1384
|
+
{config.visualizationType !== 'Pie' && config.visualizationType !== 'Paired Bar' && (
|
|
1058
1385
|
<AccordionItem>
|
|
1059
1386
|
<AccordionItemHeading>
|
|
1060
|
-
<AccordionItemButton>
|
|
1061
|
-
Regions
|
|
1062
|
-
</AccordionItemButton>
|
|
1387
|
+
<AccordionItemButton>Regions</AccordionItemButton>
|
|
1063
1388
|
</AccordionItemHeading>
|
|
1064
1389
|
<AccordionItemPanel>
|
|
1065
|
-
<Regions config={config} updateConfig={updateConfig}/>
|
|
1390
|
+
<Regions config={config} updateConfig={updateConfig} />
|
|
1066
1391
|
</AccordionItemPanel>
|
|
1067
1392
|
</AccordionItem>
|
|
1068
|
-
}
|
|
1393
|
+
)}
|
|
1069
1394
|
|
|
1070
1395
|
<AccordionItem>
|
|
1071
1396
|
<AccordionItemHeading>
|
|
1072
|
-
<AccordionItemButton>
|
|
1073
|
-
Legend
|
|
1074
|
-
</AccordionItemButton>
|
|
1397
|
+
<AccordionItemButton>Legend</AccordionItemButton>
|
|
1075
1398
|
</AccordionItemHeading>
|
|
1076
1399
|
<AccordionItemPanel>
|
|
1077
|
-
|
|
1400
|
+
<CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
|
|
1078
1401
|
{/* <fieldset className="checkbox-group">
|
|
1079
1402
|
<CheckBox value={config.legend.dynamicLegend} section="legend" fieldName="dynamicLegend" label="Dynamic Legend" updateField={updateField}/>
|
|
1080
1403
|
{config.legend.dynamicLegend && (
|
|
@@ -1086,88 +1409,104 @@ useEffect(()=>{
|
|
|
1086
1409
|
</>
|
|
1087
1410
|
)}
|
|
1088
1411
|
</fieldset> */}
|
|
1089
|
-
<CheckBox
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1412
|
+
<CheckBox
|
|
1413
|
+
value={config.legend.hide}
|
|
1414
|
+
section='legend'
|
|
1415
|
+
fieldName='hide'
|
|
1416
|
+
label='Hide Legend'
|
|
1417
|
+
updateField={updateField}
|
|
1418
|
+
tooltip={
|
|
1419
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1420
|
+
<Tooltip.Target>
|
|
1421
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1422
|
+
</Tooltip.Target>
|
|
1423
|
+
<Tooltip.Content>
|
|
1424
|
+
<p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
|
|
1425
|
+
</Tooltip.Content>
|
|
1426
|
+
</Tooltip>
|
|
1427
|
+
}
|
|
1428
|
+
/>
|
|
1429
|
+
<CheckBox value={config.legend.showLegendValuesTooltip} section='legend' fieldName='showLegendValuesTooltip' label='Show Legend Values in Tooltip' updateField={updateField} />
|
|
1430
|
+
|
|
1431
|
+
{config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
|
|
1432
|
+
<Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
|
|
1100
1433
|
)}
|
|
1101
|
-
<Select value={config.legend.behavior} section=
|
|
1102
|
-
<TextField value={config.legend.label} section=
|
|
1103
|
-
<Select value={config.legend.position} section=
|
|
1104
|
-
|
|
1434
|
+
<Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={updateField} options={['highlight', 'isolate']} />
|
|
1435
|
+
<TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
|
|
1436
|
+
<Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
|
|
1437
|
+
{config.legend.position === 'bottom' && <CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />}
|
|
1438
|
+
<TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
|
|
1105
1439
|
</AccordionItemPanel>
|
|
1106
1440
|
</AccordionItem>
|
|
1107
1441
|
|
|
1108
1442
|
<AccordionItem>
|
|
1109
1443
|
<AccordionItemHeading>
|
|
1110
|
-
<AccordionItemButton>
|
|
1111
|
-
Filters
|
|
1112
|
-
</AccordionItemButton>
|
|
1444
|
+
<AccordionItemButton>Filters</AccordionItemButton>
|
|
1113
1445
|
</AccordionItemHeading>
|
|
1114
1446
|
<AccordionItemPanel>
|
|
1115
|
-
{config.filters &&
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1447
|
+
{config.filters && (
|
|
1448
|
+
<ul className='filters-list'>
|
|
1449
|
+
{config.filters.map((filter, index) => (
|
|
1450
|
+
<fieldset className='edit-block' key={index}>
|
|
1451
|
+
<button
|
|
1452
|
+
type='button'
|
|
1453
|
+
className='remove-column'
|
|
1454
|
+
onClick={() => {
|
|
1455
|
+
removeFilter(index)
|
|
1456
|
+
}}
|
|
1457
|
+
>
|
|
1458
|
+
Remove
|
|
1121
1459
|
</button>
|
|
1122
1460
|
<label>
|
|
1123
|
-
<span className=
|
|
1124
|
-
<select
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1461
|
+
<span className='edit-label column-heading'>Filter</span>
|
|
1462
|
+
<select
|
|
1463
|
+
value={filter.columnName}
|
|
1464
|
+
onChange={e => {
|
|
1465
|
+
updateFilterProp('columnName', index, e.target.value)
|
|
1466
|
+
}}
|
|
1467
|
+
>
|
|
1468
|
+
<option value=''>- Select Option -</option>
|
|
1128
1469
|
{getColumns().map((dataKey, index) => (
|
|
1129
|
-
<option value={dataKey} key={index}>
|
|
1470
|
+
<option value={dataKey} key={index}>
|
|
1471
|
+
{dataKey}
|
|
1472
|
+
</option>
|
|
1130
1473
|
))}
|
|
1131
1474
|
</select>
|
|
1132
1475
|
</label>
|
|
1133
1476
|
<label>
|
|
1134
|
-
<span className=
|
|
1135
|
-
<input
|
|
1136
|
-
|
|
1137
|
-
|
|
1477
|
+
<span className='edit-label column-heading'>Label</span>
|
|
1478
|
+
<input
|
|
1479
|
+
type='text'
|
|
1480
|
+
value={filter.label}
|
|
1481
|
+
onChange={e => {
|
|
1482
|
+
updateFilterProp('label', index, e.target.value)
|
|
1483
|
+
}}
|
|
1484
|
+
/>
|
|
1138
1485
|
</label>
|
|
1139
1486
|
|
|
1140
1487
|
<label>
|
|
1141
|
-
<span className=
|
|
1142
|
-
<select value={filter.order ? filter.order : 'asc'} onChange={
|
|
1488
|
+
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
1489
|
+
<select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
|
|
1143
1490
|
{filterOptions.map((option, index) => {
|
|
1144
|
-
return
|
|
1491
|
+
return (
|
|
1492
|
+
<option value={option.value} key={`filter-${index}`}>
|
|
1493
|
+
{option.label}
|
|
1494
|
+
</option>
|
|
1495
|
+
)
|
|
1145
1496
|
})}
|
|
1146
1497
|
</select>
|
|
1147
1498
|
|
|
1148
|
-
{filter.order === 'cust' &&
|
|
1149
|
-
<DragDropContext
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
<Droppable droppableId="filter_order">
|
|
1154
|
-
{(provided) => (
|
|
1155
|
-
<ul
|
|
1156
|
-
{...provided.droppableProps}
|
|
1157
|
-
className="sort-list"
|
|
1158
|
-
ref={provided.innerRef}
|
|
1159
|
-
style={{ marginTop: '1em' }}
|
|
1160
|
-
>
|
|
1499
|
+
{filter.order === 'cust' && (
|
|
1500
|
+
<DragDropContext onDragEnd={({ source, destination }) => handleFilterChange(source.index, destination.index, index, config.filters[index])}>
|
|
1501
|
+
<Droppable droppableId='filter_order'>
|
|
1502
|
+
{provided => (
|
|
1503
|
+
<ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
1161
1504
|
{config.filters[index]?.values.map((value, index) => {
|
|
1162
1505
|
return (
|
|
1163
1506
|
<Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
|
|
1164
1507
|
{(provided, snapshot) => (
|
|
1165
1508
|
<li>
|
|
1166
|
-
<div className={snapshot.isDragging ? 'currently-dragging' : ''}
|
|
1167
|
-
style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)}
|
|
1168
|
-
ref={provided.innerRef}
|
|
1169
|
-
{...provided.draggableProps}
|
|
1170
|
-
{...provided.dragHandleProps}>
|
|
1509
|
+
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
1171
1510
|
{value}
|
|
1172
1511
|
</div>
|
|
1173
1512
|
</li>
|
|
@@ -1180,98 +1519,86 @@ useEffect(()=>{
|
|
|
1180
1519
|
)}
|
|
1181
1520
|
</Droppable>
|
|
1182
1521
|
</DragDropContext>
|
|
1183
|
-
}
|
|
1522
|
+
)}
|
|
1184
1523
|
</label>
|
|
1185
|
-
|
|
1186
1524
|
</fieldset>
|
|
1187
|
-
)
|
|
1188
|
-
|
|
1189
|
-
|
|
1525
|
+
))}
|
|
1526
|
+
</ul>
|
|
1527
|
+
)}
|
|
1190
1528
|
{!config.filters && <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
|
|
1191
|
-
<button type=
|
|
1529
|
+
<button type='button' onClick={addNewFilter} className='btn full-width'>
|
|
1530
|
+
Add Filter
|
|
1531
|
+
</button>
|
|
1192
1532
|
</AccordionItemPanel>
|
|
1193
1533
|
</AccordionItem>
|
|
1194
1534
|
|
|
1195
1535
|
<AccordionItem>
|
|
1196
1536
|
<AccordionItemHeading>
|
|
1197
|
-
<AccordionItemButton>
|
|
1198
|
-
Visual
|
|
1199
|
-
</AccordionItemButton>
|
|
1537
|
+
<AccordionItemButton>Visual</AccordionItemButton>
|
|
1200
1538
|
</AccordionItemHeading>
|
|
1201
1539
|
<AccordionItemPanel>
|
|
1202
|
-
|
|
1203
|
-
{config.isLollipopChart &&
|
|
1540
|
+
{config.isLollipopChart && (
|
|
1204
1541
|
<>
|
|
1205
|
-
<fieldset className=
|
|
1206
|
-
<legend className=
|
|
1207
|
-
<div
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
value="circle"
|
|
1215
|
-
checked={config.lollipopShape === 'circle'}
|
|
1216
|
-
/>
|
|
1542
|
+
<fieldset className='header'>
|
|
1543
|
+
<legend className='edit-label'>Lollipop Shape</legend>
|
|
1544
|
+
<div
|
|
1545
|
+
onChange={e => {
|
|
1546
|
+
setLollipopShape(e.target.value)
|
|
1547
|
+
}}
|
|
1548
|
+
>
|
|
1549
|
+
<label className='radio-label'>
|
|
1550
|
+
<input type='radio' name='lollipopShape' value='circle' checked={config.lollipopShape === 'circle'} />
|
|
1217
1551
|
Circle
|
|
1218
1552
|
</label>
|
|
1219
|
-
<label className=
|
|
1220
|
-
<input
|
|
1221
|
-
type="radio"
|
|
1222
|
-
name="lollipopShape"
|
|
1223
|
-
value="square"
|
|
1224
|
-
checked={config.lollipopShape === 'square'}
|
|
1225
|
-
/>
|
|
1553
|
+
<label className='radio-label'>
|
|
1554
|
+
<input type='radio' name='lollipopShape' value='square' checked={config.lollipopShape === 'square'} />
|
|
1226
1555
|
Square
|
|
1227
1556
|
</label>
|
|
1228
1557
|
</div>
|
|
1229
|
-
|
|
1230
1558
|
</fieldset>
|
|
1231
|
-
<Select value={config.lollipopColorStyle ? config.lollipopColorStyle : 'two-tone'} fieldName=
|
|
1232
|
-
<Select value={config.lollipopSize ? config.lollipopSize : 'small'} fieldName=
|
|
1559
|
+
<Select value={config.lollipopColorStyle ? config.lollipopColorStyle : 'two-tone'} fieldName='lollipopColorStyle' label='Lollipop Color Style' updateField={updateField} options={['regular', 'two-tone']} />
|
|
1560
|
+
<Select value={config.lollipopSize ? config.lollipopSize : 'small'} fieldName='lollipopSize' label='Lollipop Size' updateField={updateField} options={['small', 'medium', 'large']} />
|
|
1233
1561
|
</>
|
|
1234
|
-
}
|
|
1562
|
+
)}
|
|
1235
1563
|
|
|
1236
|
-
<Select value={config.fontSize} fieldName=
|
|
1564
|
+
<Select value={config.fontSize} fieldName='fontSize' label='Font Size' updateField={updateField} options={['small', 'medium', 'large']} />
|
|
1237
1565
|
|
|
1238
|
-
{config.series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar') &&
|
|
1239
|
-
<Select value={config.barHasBorder} fieldName="barHasBorder" label="Bar Borders" updateField={updateField} options={[ 'true', 'false' ]}/>
|
|
1240
|
-
}
|
|
1566
|
+
{config.series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar') && <Select value={config.barHasBorder} fieldName='barHasBorder' label='Bar Borders' updateField={updateField} options={['true', 'false']} />}
|
|
1241
1567
|
|
|
1242
|
-
|
|
1568
|
+
<CheckBox value={config.animate} fieldName='animate' label='Animate Visualization' updateField={updateField} />
|
|
1243
1569
|
|
|
1244
1570
|
{/*<CheckBox value={config.animateReplay} fieldName="animateReplay" label="Replay Animation When Filters Are Changed" updateField={updateField} />*/}
|
|
1245
1571
|
|
|
1246
|
-
{((config.series?.some(series => series.type === 'Line') && config.visualizationType === 'Combo') || config.visualizationType === 'Line' || config.visualizationType ===
|
|
1247
|
-
<Select value={config.lineDatapointStyle} fieldName=
|
|
1248
|
-
}
|
|
1572
|
+
{((config.series?.some(series => series.type === 'Line') && config.visualizationType === 'Combo') || config.visualizationType === 'Line' || config.visualizationType === 'Spark Line') && (
|
|
1573
|
+
<Select value={config.lineDatapointStyle} fieldName='lineDatapointStyle' label='Line Datapoint Style' updateField={updateField} options={['hidden', 'hover', 'always show']} />
|
|
1574
|
+
)}
|
|
1249
1575
|
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
<
|
|
1253
|
-
|
|
1254
|
-
|
|
1576
|
+
{/* eslint-disable */}
|
|
1577
|
+
<label className='header'>
|
|
1578
|
+
<span className='edit-label'>Header Theme</span>
|
|
1579
|
+
<ul className='color-palette'>
|
|
1580
|
+
{headerColors.map(palette => (
|
|
1581
|
+
<button
|
|
1255
1582
|
title={palette}
|
|
1256
|
-
key={palette}
|
|
1257
|
-
onClick={
|
|
1258
|
-
e.preventDefault()
|
|
1583
|
+
key={palette}
|
|
1584
|
+
onClick={e => {
|
|
1585
|
+
e.preventDefault()
|
|
1259
1586
|
updateConfig({ ...config, theme: palette })
|
|
1260
|
-
}}
|
|
1261
|
-
className={config.theme === palette ? 'selected ' + palette : palette}
|
|
1262
|
-
|
|
1587
|
+
}}
|
|
1588
|
+
className={config.theme === palette ? 'selected ' + palette : palette}
|
|
1589
|
+
></button>
|
|
1263
1590
|
))}
|
|
1264
1591
|
</ul>
|
|
1265
1592
|
</label>
|
|
1266
1593
|
<label>
|
|
1267
|
-
<span className=
|
|
1594
|
+
<span className='edit-label'>Chart Color Palette</span>
|
|
1268
1595
|
</label>
|
|
1596
|
+
{/* eslint-enable */}
|
|
1269
1597
|
{/* <InputCheckbox fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} /> */}
|
|
1270
|
-
<InputToggle fieldName=
|
|
1598
|
+
<InputToggle fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} />
|
|
1271
1599
|
<span>Sequential</span>
|
|
1272
|
-
<ul className=
|
|
1273
|
-
{filteredPallets.map(
|
|
1274
|
-
|
|
1600
|
+
<ul className='color-palette'>
|
|
1601
|
+
{filteredPallets.map(palette => {
|
|
1275
1602
|
const colorOne = {
|
|
1276
1603
|
backgroundColor: colorPalettes[palette][2]
|
|
1277
1604
|
}
|
|
@@ -1285,11 +1612,11 @@ useEffect(()=>{
|
|
|
1285
1612
|
}
|
|
1286
1613
|
|
|
1287
1614
|
return (
|
|
1288
|
-
<button
|
|
1289
|
-
title={palette}
|
|
1290
|
-
key={palette}
|
|
1291
|
-
onClick={
|
|
1292
|
-
e.preventDefault()
|
|
1615
|
+
<button
|
|
1616
|
+
title={palette}
|
|
1617
|
+
key={palette}
|
|
1618
|
+
onClick={e => {
|
|
1619
|
+
e.preventDefault()
|
|
1293
1620
|
updateConfig({ ...config, palette })
|
|
1294
1621
|
}}
|
|
1295
1622
|
className={config.palette === palette ? 'selected' : ''}
|
|
@@ -1302,9 +1629,8 @@ useEffect(()=>{
|
|
|
1302
1629
|
})}
|
|
1303
1630
|
</ul>
|
|
1304
1631
|
<span>Non-Sequential</span>
|
|
1305
|
-
<ul className=
|
|
1306
|
-
{filteredQualitative.map(
|
|
1307
|
-
|
|
1632
|
+
<ul className='color-palette'>
|
|
1633
|
+
{filteredQualitative.map(palette => {
|
|
1308
1634
|
const colorOne = {
|
|
1309
1635
|
backgroundColor: colorPalettes[palette][2]
|
|
1310
1636
|
}
|
|
@@ -1317,13 +1643,12 @@ useEffect(()=>{
|
|
|
1317
1643
|
backgroundColor: colorPalettes[palette][6]
|
|
1318
1644
|
}
|
|
1319
1645
|
|
|
1320
|
-
|
|
1321
1646
|
return (
|
|
1322
|
-
<button
|
|
1323
|
-
title={palette}
|
|
1324
|
-
key={palette}
|
|
1325
|
-
onClick={
|
|
1326
|
-
e.preventDefault()
|
|
1647
|
+
<button
|
|
1648
|
+
title={palette}
|
|
1649
|
+
key={palette}
|
|
1650
|
+
onClick={e => {
|
|
1651
|
+
e.preventDefault()
|
|
1327
1652
|
updateConfig({ ...config, palette })
|
|
1328
1653
|
}}
|
|
1329
1654
|
className={config.palette === palette ? 'selected' : ''}
|
|
@@ -1338,82 +1663,103 @@ useEffect(()=>{
|
|
|
1338
1663
|
|
|
1339
1664
|
{config.visualizationType !== 'Pie' && (
|
|
1340
1665
|
<>
|
|
1341
|
-
<TextField
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1666
|
+
<TextField
|
|
1667
|
+
value={config.dataCutoff}
|
|
1668
|
+
type='number'
|
|
1669
|
+
fieldName='dataCutoff'
|
|
1670
|
+
className='number-narrow'
|
|
1671
|
+
label='Data Cutoff'
|
|
1672
|
+
updateField={updateField}
|
|
1673
|
+
tooltip={
|
|
1674
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1675
|
+
<Tooltip.Target>
|
|
1676
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1677
|
+
</Tooltip.Target>
|
|
1678
|
+
<Tooltip.Content>
|
|
1679
|
+
<p>Any value below the cut-off value is included in a special "less than" category. This option supports special conditions like suppressed data.</p>
|
|
1680
|
+
</Tooltip.Content>
|
|
1681
|
+
</Tooltip>
|
|
1682
|
+
}
|
|
1683
|
+
/>
|
|
1349
1684
|
</>
|
|
1350
1685
|
)}
|
|
1351
|
-
{
|
|
1352
|
-
|
|
1353
|
-
}
|
|
1354
|
-
{(
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
<CheckBox value={config.visual?.
|
|
1361
|
-
<CheckBox value={config.visual?.
|
|
1362
|
-
<CheckBox value={config.visual?.
|
|
1363
|
-
<CheckBox value={config.visual?.background} section="visual" fieldName="background" label="Use Theme Background Color" updateField={updateField} />
|
|
1364
|
-
<CheckBox value={config.visual?.hideBackgroundColor} section="visual" fieldName="hideBackgroundColor" label="Hide Background Color" updateField={updateField} />
|
|
1686
|
+
{config.orientation === 'horizontal' && !config.isLollipopChart && config.yAxis.labelPlacement !== 'On Bar' && <TextField type='number' value={config.barHeight || '25'} fieldName='barHeight' label=' Bar Thickness' updateField={updateField} min='15' />}
|
|
1687
|
+
{((config.visualizationType === 'Bar' && config.orientation !== 'horizontal') || config.visualizationType === 'Combo') && <TextField value={config.barThickness} type='number' fieldName='barThickness' label='Bar Thickness' updateField={updateField} />}
|
|
1688
|
+
{config.orientation === 'horizontal' && <TextField type='number' value={config.barSpace || '20'} fieldName='barSpace' label='Bar Space' updateField={updateField} min='0' />}
|
|
1689
|
+
{(config.visualizationType === 'Bar' || config.visualizationType === 'Line' || config.visualizationType === 'Combo') && <CheckBox value={config.topAxis.hasLine} section='topAxis' fieldName='hasLine' label='Add Top Axis Line' updateField={updateField} />}
|
|
1690
|
+
|
|
1691
|
+
{config.visualizationType === 'Spark Line' && (
|
|
1692
|
+
<div className='cove-accordion__panel-section checkbox-group'>
|
|
1693
|
+
<CheckBox value={config.visual?.border} section='visual' fieldName='border' label='Display Border' updateField={updateField} />
|
|
1694
|
+
<CheckBox value={config.visual?.borderColorTheme} section='visual' fieldName='borderColorTheme' label='Use Border Color Theme' updateField={updateField} />
|
|
1695
|
+
<CheckBox value={config.visual?.accent} section='visual' fieldName='accent' label='Use Accent Style' updateField={updateField} />
|
|
1696
|
+
<CheckBox value={config.visual?.background} section='visual' fieldName='background' label='Use Theme Background Color' updateField={updateField} />
|
|
1697
|
+
<CheckBox value={config.visual?.hideBackgroundColor} section='visual' fieldName='hideBackgroundColor' label='Hide Background Color' updateField={updateField} />
|
|
1365
1698
|
</div>
|
|
1366
|
-
}
|
|
1699
|
+
)}
|
|
1700
|
+
|
|
1701
|
+
{(config.visualizationType === 'Line' || config.visualizationType === 'Combo') && <CheckBox value={config.showLineSeriesLabels} fieldName='showLineSeriesLabels' label='Append Series Name to End of Line Charts' updateField={updateField} />}
|
|
1702
|
+
{(config.visualizationType === 'Line' || config.visualizationType === 'Combo') && config.showLineSeriesLabels && (
|
|
1703
|
+
<CheckBox value={config.colorMatchLineSeriesLabels} fieldName='colorMatchLineSeriesLabels' label='Match Series Color to Name at End of Line Charts' updateField={updateField} />
|
|
1704
|
+
)}
|
|
1367
1705
|
</AccordionItemPanel>
|
|
1368
1706
|
</AccordionItem>
|
|
1369
1707
|
|
|
1370
1708
|
<AccordionItem>
|
|
1371
1709
|
<AccordionItemHeading>
|
|
1372
|
-
<AccordionItemButton>
|
|
1373
|
-
Data Table
|
|
1374
|
-
</AccordionItemButton>
|
|
1710
|
+
<AccordionItemButton>Data Table</AccordionItemButton>
|
|
1375
1711
|
</AccordionItemHeading>
|
|
1376
1712
|
<AccordionItemPanel>
|
|
1377
|
-
<CheckBox
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1713
|
+
<CheckBox
|
|
1714
|
+
value={config.table.show}
|
|
1715
|
+
section='table'
|
|
1716
|
+
fieldName='show'
|
|
1717
|
+
label='Show Table'
|
|
1718
|
+
updateField={updateField}
|
|
1719
|
+
tooltip={
|
|
1720
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1721
|
+
<Tooltip.Target>
|
|
1722
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1723
|
+
</Tooltip.Target>
|
|
1724
|
+
<Tooltip.Content>
|
|
1725
|
+
<p>Hiding the data table may affect accessibility. An alternate form of accessing visualization data is a 508 requirement.</p>
|
|
1726
|
+
</Tooltip.Content>
|
|
1727
|
+
</Tooltip>
|
|
1728
|
+
}
|
|
1729
|
+
/>
|
|
1730
|
+
<TextField
|
|
1731
|
+
value={config.table.caption}
|
|
1732
|
+
updateField={updateField}
|
|
1733
|
+
section='table'
|
|
1734
|
+
type='textarea'
|
|
1735
|
+
fieldName='caption'
|
|
1736
|
+
label='Data Table Caption'
|
|
1737
|
+
placeholder=' Data table'
|
|
1738
|
+
tooltip={
|
|
1739
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1740
|
+
<Tooltip.Target>
|
|
1741
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1742
|
+
</Tooltip.Target>
|
|
1743
|
+
<Tooltip.Content>
|
|
1744
|
+
<p>Enter a description of the data table to be read by screen readers.</p>
|
|
1745
|
+
</Tooltip.Content>
|
|
1746
|
+
</Tooltip>
|
|
1747
|
+
}
|
|
1748
|
+
/>
|
|
1749
|
+
<CheckBox value={config.table.limitHeight} section='table' fieldName='limitHeight' label='Limit Table Height' updateField={updateField} />
|
|
1750
|
+
{config.table.limitHeight && <TextField value={config.table.height} section='table' fieldName='height' label='Data Table Height' type='number' min='0' max='500' placeholder='Height(px)' updateField={updateField} />}
|
|
1751
|
+
<CheckBox value={config.table.expanded} section='table' fieldName='expanded' label='Expanded by Default' updateField={updateField} />
|
|
1752
|
+
<CheckBox value={config.table.download} section='table' fieldName='download' label='Display Download Button' updateField={updateField} />
|
|
1753
|
+
<CheckBox value={config.table.showDownloadUrl} section='table' fieldName='showDownloadUrl' label='Display Link to Dataset' updateField={updateField} />
|
|
1754
|
+
{/* <CheckBox value={config.table.showDownloadImgButton} section='table' fieldName='showDownloadImgButton' label='Display Image Button' updateField={updateField} /> */}
|
|
1755
|
+
{/* <CheckBox value={config.table.showDownloadPdfButton} section='table' fieldName='showDownloadPdfButton' label='Display PDF Button' updateField={updateField} /> */}
|
|
1756
|
+
<TextField value={config.table.label} section='table' fieldName='label' label='Label' updateField={updateField} />
|
|
1757
|
+
{config.visualizationType !== 'Pie' && <TextField value={config.table.indexLabel} section='table' fieldName='indexLabel' label='Index Column Header' updateField={updateField} />}
|
|
1410
1758
|
</AccordionItemPanel>
|
|
1411
1759
|
</AccordionItem>
|
|
1412
1760
|
</Accordion>
|
|
1413
1761
|
</form>
|
|
1414
|
-
{config.type !== 'Spark Line' &&
|
|
1415
|
-
<AdvancedEditor loadConfig={updateConfig} state={config} convertStateToConfig={convertStateToConfig} />
|
|
1416
|
-
}
|
|
1762
|
+
{config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig} state={config} convertStateToConfig={convertStateToConfig} />}
|
|
1417
1763
|
</section>
|
|
1418
1764
|
</section>
|
|
1419
1765
|
</ErrorBoundary>
|