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