@cdc/chart 4.24.3 → 4.24.5
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/dist/cdcchart.js +34377 -33726
- package/examples/feature/line/line-chart.json +361 -37
- package/examples/region-issue.json +2065 -0
- package/examples/test.json +5409 -0
- package/index.html +13 -11
- package/package.json +2 -2
- package/src/CdcChart.tsx +159 -89
- package/src/_stories/Chart.stories.tsx +8 -0
- package/src/_stories/_mock/bar-chart-suppressed.json +474 -0
- package/src/components/AreaChart/components/AreaChart.jsx +2 -2
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +61 -63
- package/src/components/BarChart/components/BarChart.Vertical.tsx +79 -94
- package/src/components/DeviationBar.jsx +4 -2
- package/src/components/EditorPanel/EditorPanel.tsx +1580 -1924
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +19 -2
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +0 -1
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -5
- package/src/components/EditorPanel/editor-panel.scss +0 -724
- package/src/components/EditorPanel/useEditorPermissions.js +4 -1
- package/src/components/Legend/Legend.Component.tsx +82 -58
- package/src/components/Legend/Legend.tsx +5 -1
- package/src/components/LineChart/LineChartProps.ts +13 -6
- package/src/components/LineChart/components/LineChart.Circle.tsx +22 -11
- package/src/components/LineChart/helpers.ts +134 -10
- package/src/components/LineChart/index.tsx +69 -42
- package/src/components/LinearChart.jsx +156 -139
- package/src/components/ZoomBrush.tsx +40 -21
- package/src/data/initial-state.js +4 -4
- package/src/hooks/useBarChart.js +47 -22
- package/src/hooks/useMinMax.ts +21 -2
- package/src/hooks/useScales.ts +33 -1
- package/src/hooks/useTooltip.tsx +11 -11
- package/src/scss/main.scss +80 -5
- package/src/types/ChartConfig.ts +3 -13
- package/src/types/ChartContext.ts +4 -0
- package/src/_stories/ChartLine.preliminary.tsx +0 -19
- package/src/_stories/ChartSuppress.stories.tsx +0 -19
- package/src/_stories/_mock/suppress_mock.json +0 -911
- package/src/helpers/computeMarginBottom.ts +0 -56
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { useState, useEffect, useCallback, memo, useContext } from 'react'
|
|
2
|
-
import { DragDropContext, Droppable
|
|
2
|
+
import { DragDropContext, Droppable } from '@hello-pangea/dnd'
|
|
3
3
|
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
4
4
|
import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
|
|
5
|
+
import Layout from '@cdc/core/components/Layout'
|
|
5
6
|
|
|
6
7
|
// @cdc/core
|
|
7
8
|
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
8
9
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
9
10
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
10
|
-
import
|
|
11
|
+
import ColumnsEditor from '@cdc/core/components/EditorPanel/ColumnsEditor'
|
|
12
|
+
import DataTableEditor from '@cdc/core/components/EditorPanel/DataTableEditor'
|
|
13
|
+
import VizFilterEditor from '@cdc/core/components/EditorPanel/VizFilterEditor'
|
|
11
14
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
12
15
|
import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
13
16
|
|
|
14
17
|
// chart components
|
|
15
18
|
import Panels from './components/Panels'
|
|
16
|
-
import Series from './components/Panel.Series.jsx'
|
|
17
19
|
|
|
18
20
|
// cdc additional
|
|
19
|
-
import { useColorPalette } from '../../hooks/useColorPalette'
|
|
20
21
|
import { useEditorPermissions } from './useEditorPermissions'
|
|
21
|
-
import { useFilters } from '@cdc/core/components/Filters'
|
|
22
22
|
import { useHighlightedBars } from '../../hooks/useHighlightedBars'
|
|
23
23
|
import ConfigContext from '../../ConfigContext'
|
|
24
24
|
import useReduceData from '../../hooks/useReduceData'
|
|
@@ -26,113 +26,57 @@ import useRightAxis from '../../hooks/useRightAxis'
|
|
|
26
26
|
import WarningImage from '../../images/warning.svg'
|
|
27
27
|
import useMinMax from '../../hooks/useMinMax'
|
|
28
28
|
|
|
29
|
-
import { type ChartConfig } from '../../types/ChartConfig'
|
|
30
29
|
import { type ChartContext } from '../../types/ChartContext'
|
|
30
|
+
import { type ChartConfig } from '../../types/ChartConfig'
|
|
31
31
|
|
|
32
32
|
import './editor-panel.scss'
|
|
33
33
|
import { Anchor } from '@cdc/core/types/Axis'
|
|
34
|
-
import DataTableEditor from '@cdc/core/components/EditorPanel/DataTableEditor'
|
|
35
34
|
import EditorPanelContext from './EditorPanelContext'
|
|
35
|
+
import _ from 'lodash'
|
|
36
|
+
import { adjustedSymbols as symbolCodes } from '@cdc/core/helpers/footnoteSymbols'
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
keys.add(key)
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
return [...keys]
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const getIconOptions = () => {
|
|
49
|
-
return ['star']
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
let removeColumn = i => {
|
|
53
|
-
let suppressedData = []
|
|
54
|
-
|
|
55
|
-
if (config.suppressedData) {
|
|
56
|
-
suppressedData = [...config.suppressedData]
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
suppressedData.splice(i, 1)
|
|
38
|
+
interface PreliminaryProps {
|
|
39
|
+
config: ChartConfig
|
|
40
|
+
updateConfig: Function
|
|
41
|
+
data: Record<string, any>[]
|
|
42
|
+
}
|
|
60
43
|
|
|
61
|
-
|
|
62
|
-
|
|
44
|
+
const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, data }) => {
|
|
45
|
+
const isCombo = config.visualizationType === 'Combo'
|
|
46
|
+
const lineSeriesExists = config.runtime.lineSeriesKeys?.length > 0
|
|
47
|
+
const barSeriesExists = config.runtime.barSeriesKeys?.length > 0
|
|
48
|
+
const hasComboLineSeries = isCombo && lineSeriesExists
|
|
49
|
+
const hasComboBarSeries = isCombo && barSeriesExists
|
|
63
50
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
suppressedData.push({ label: '', column: '', value: '', icon: '' })
|
|
67
|
-
updateConfig({ ...config, suppressedData })
|
|
51
|
+
const getColumnOptions = () => {
|
|
52
|
+
return _.uniq(_.flatMap(data, _.keys))
|
|
68
53
|
}
|
|
69
54
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (config.suppressedData) {
|
|
74
|
-
suppressedData = [...config.suppressedData]
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
suppressedData[i][fieldName] = value
|
|
78
|
-
updateConfig({ ...config, suppressedData })
|
|
55
|
+
const getTypeOptions = () => {
|
|
56
|
+
return config.visualizationType === 'Line' || hasComboLineSeries ? ['effect', 'suppression'] : ['suppression']
|
|
79
57
|
}
|
|
80
58
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
<div key={`suppressed-${i}`} className='edit-block'>
|
|
87
|
-
<button
|
|
88
|
-
type='button'
|
|
89
|
-
className='remove-column'
|
|
90
|
-
onClick={event => {
|
|
91
|
-
event.preventDefault()
|
|
92
|
-
removeColumn(i)
|
|
93
|
-
}}
|
|
94
|
-
>
|
|
95
|
-
Remove
|
|
96
|
-
</button>
|
|
97
|
-
<Select value={column} initial='Select' fieldName='column' label='Column' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getColumnOptions()} />
|
|
98
|
-
<TextField value={value} fieldName='value' label='Value' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} />
|
|
99
|
-
<Select value={icon} initial='Select' fieldName='icon' label='Icon' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getIconOptions()} />
|
|
100
|
-
<TextField value={label} fieldName='label' label='Label' placeholder='suppressed' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} />
|
|
101
|
-
</div>
|
|
102
|
-
)
|
|
103
|
-
})}
|
|
104
|
-
|
|
105
|
-
<button type='button' onClick={addColumn} className='btn full-width'>
|
|
106
|
-
Add Suppression Class
|
|
107
|
-
</button>
|
|
108
|
-
</>
|
|
109
|
-
)
|
|
110
|
-
})
|
|
111
|
-
const PreliminaryData = memo(({ config, updateConfig, data }) => {
|
|
112
|
-
const getColumnOptions = () => {
|
|
113
|
-
const keys = new Set()
|
|
114
|
-
data.forEach(d => {
|
|
115
|
-
Object.keys(d).forEach(key => {
|
|
116
|
-
keys.add(key)
|
|
117
|
-
})
|
|
118
|
-
})
|
|
119
|
-
return [...keys]
|
|
59
|
+
const lineCodes = {
|
|
60
|
+
'Dashed Small': '\u002D \u002D \u002D',
|
|
61
|
+
'Dashed Medium': '\u2013 \u2013',
|
|
62
|
+
'Dashed Large': '\u2014 \u2013',
|
|
63
|
+
'Open Circles': '\u25EF'
|
|
120
64
|
}
|
|
121
65
|
|
|
122
|
-
const
|
|
123
|
-
if (config.visualizationType === 'Line' ||
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
66
|
+
const getStyleOptions = type => {
|
|
67
|
+
if (config.visualizationType === 'Line' || isCombo) {
|
|
68
|
+
const options = Object.keys(lineCodes)
|
|
69
|
+
if (type === 'suppression') {
|
|
70
|
+
return options.slice(0, -1)
|
|
71
|
+
} else {
|
|
72
|
+
return options
|
|
73
|
+
}
|
|
127
74
|
}
|
|
128
75
|
}
|
|
129
76
|
|
|
130
|
-
const
|
|
131
|
-
if (config.visualizationType === '
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
if (config.visualizationType === 'Bar') {
|
|
135
|
-
return ['star']
|
|
77
|
+
const getSymbolOptions = () => {
|
|
78
|
+
if (config.visualizationType === 'Bar' || hasComboBarSeries) {
|
|
79
|
+
return Object.keys(symbolCodes)
|
|
136
80
|
}
|
|
137
81
|
}
|
|
138
82
|
|
|
@@ -149,8 +93,23 @@ const PreliminaryData = memo(({ config, updateConfig, data }) => {
|
|
|
149
93
|
}
|
|
150
94
|
|
|
151
95
|
let addColumn = () => {
|
|
96
|
+
const defaultType = config.visualizationType === 'Line' ? 'effect' : 'suppression'
|
|
152
97
|
let preliminaryData = config.preliminaryData ? [...config.preliminaryData] : []
|
|
153
|
-
|
|
98
|
+
const defaultValues = {
|
|
99
|
+
type: defaultType,
|
|
100
|
+
seriesKey: '',
|
|
101
|
+
label: 'Suppressed',
|
|
102
|
+
column: '',
|
|
103
|
+
value: '',
|
|
104
|
+
style: '',
|
|
105
|
+
displayTooltip: true,
|
|
106
|
+
displayLegend: true,
|
|
107
|
+
displayTable: true,
|
|
108
|
+
symbol: '',
|
|
109
|
+
iconCode: '',
|
|
110
|
+
lineCode: ''
|
|
111
|
+
}
|
|
112
|
+
preliminaryData.push(defaultValues)
|
|
154
113
|
updateConfig({ ...config, preliminaryData })
|
|
155
114
|
}
|
|
156
115
|
|
|
@@ -162,15 +121,22 @@ const PreliminaryData = memo(({ config, updateConfig, data }) => {
|
|
|
162
121
|
}
|
|
163
122
|
|
|
164
123
|
preliminaryData[i][fieldName] = value
|
|
124
|
+
if (fieldName === 'symbol') {
|
|
125
|
+
preliminaryData[i]['iconCode'] = symbolCodes[value]
|
|
126
|
+
}
|
|
127
|
+
if (fieldName === 'style') {
|
|
128
|
+
preliminaryData[i]['lineCode'] = lineCodes[value]
|
|
129
|
+
}
|
|
165
130
|
updateConfig({ ...config, preliminaryData })
|
|
166
131
|
}
|
|
167
132
|
|
|
168
133
|
return (
|
|
169
134
|
<>
|
|
170
135
|
{config.preliminaryData &&
|
|
171
|
-
config.preliminaryData
|
|
136
|
+
config.preliminaryData?.map(({ column, displayLegend, displayTable, displayTooltip, label, seriesKey, style, symbol, type, value }, i) => {
|
|
172
137
|
return (
|
|
173
138
|
<div key={`preliminaryData-${i}`} className='edit-block'>
|
|
139
|
+
<p> {type === 'suppression' ? 'Suppressed' : 'Effect'} Data</p>
|
|
174
140
|
<button
|
|
175
141
|
type='button'
|
|
176
142
|
className='remove-column'
|
|
@@ -181,23 +147,156 @@ const PreliminaryData = memo(({ config, updateConfig, data }) => {
|
|
|
181
147
|
>
|
|
182
148
|
Remove
|
|
183
149
|
</button>
|
|
184
|
-
<Select value={type} initial='Select' fieldName='type' label='Type' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getTypeOptions()} />
|
|
185
|
-
<Select value={seriesKey} initial='Select' fieldName='seriesKey' label='ASSOCIATE TO SERIES' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={config.runtime.lineSeriesKeys ?? config.runtime?.seriesKeys} />
|
|
186
|
-
<Select value={column} initial='Select' fieldName='column' label='COLUMN WITH CONFIGURATION VALUE' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getColumnOptions()} />
|
|
187
|
-
<TextField value={value} fieldName='value' label='VALUE TO TRIGGER' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} />
|
|
188
|
-
<Select value={style} initial='Select' fieldName='style' label='Style' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getStyleOptions()} />
|
|
189
150
|
|
|
190
|
-
<
|
|
151
|
+
<Select value={type} initial={config.visualizationType == 'Bar' ? '' : 'Select'} fieldName='type' label='Type' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getTypeOptions()} />
|
|
152
|
+
{type === 'suppression' ? (
|
|
153
|
+
<>
|
|
154
|
+
<Select
|
|
155
|
+
tooltip={
|
|
156
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
157
|
+
<Tooltip.Target>
|
|
158
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
159
|
+
</Tooltip.Target>
|
|
160
|
+
<Tooltip.Content>
|
|
161
|
+
<p>If no “Data Series" is selected, the symbol will be applied to "all" suppressed values indicated in the dataset.</p>
|
|
162
|
+
</Tooltip.Content>
|
|
163
|
+
</Tooltip>
|
|
164
|
+
}
|
|
165
|
+
value={column}
|
|
166
|
+
initial='Select'
|
|
167
|
+
fieldName='column'
|
|
168
|
+
label='Add Data Series'
|
|
169
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
170
|
+
options={config.runtime?.seriesKeys}
|
|
171
|
+
/>
|
|
172
|
+
<TextField value={value} fieldName='value' label='Suppressed Data Value' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
|
|
173
|
+
{(hasComboLineSeries || config.visualizationType === 'Line') && (
|
|
174
|
+
<Select
|
|
175
|
+
tooltip={
|
|
176
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
177
|
+
<Tooltip.Target>
|
|
178
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
179
|
+
</Tooltip.Target>
|
|
180
|
+
<Tooltip.Content>
|
|
181
|
+
<p>The recommended approach for presenting data is to include a footnote indicating any data suppression.</p>
|
|
182
|
+
</Tooltip.Content>
|
|
183
|
+
</Tooltip>
|
|
184
|
+
}
|
|
185
|
+
value={style}
|
|
186
|
+
initial='Select'
|
|
187
|
+
fieldName='style'
|
|
188
|
+
label={'suppression line style'}
|
|
189
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
190
|
+
options={getStyleOptions(type)}
|
|
191
|
+
/>
|
|
192
|
+
)}
|
|
193
|
+
|
|
194
|
+
{(hasComboBarSeries || config.visualizationType === 'Bar') && (
|
|
195
|
+
<Select
|
|
196
|
+
tooltip={
|
|
197
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
198
|
+
<Tooltip.Target>
|
|
199
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
200
|
+
</Tooltip.Target>
|
|
201
|
+
<Tooltip.Content>
|
|
202
|
+
<p>The suggested method for presenting suppressed data is to use "double asterisks". If "double asterisks" are already used elsewhere (e.g., footnotes), please select an alternative symbol from the menu to denote data suppression.</p>
|
|
203
|
+
</Tooltip.Content>
|
|
204
|
+
</Tooltip>
|
|
205
|
+
}
|
|
206
|
+
value={symbol}
|
|
207
|
+
initial='Select'
|
|
208
|
+
fieldName='symbol'
|
|
209
|
+
label={config.visualizationType === 'Combo' ? 'suppression bar symbol' : 'suppression symbol'}
|
|
210
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
211
|
+
options={getSymbolOptions()}
|
|
212
|
+
/>
|
|
213
|
+
)}
|
|
214
|
+
|
|
215
|
+
<TextField
|
|
216
|
+
tooltip={
|
|
217
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
218
|
+
<Tooltip.Target>
|
|
219
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
220
|
+
</Tooltip.Target>
|
|
221
|
+
<Tooltip.Content>
|
|
222
|
+
<p>This label will display in the tooltip and legend.</p>
|
|
223
|
+
</Tooltip.Content>
|
|
224
|
+
</Tooltip>
|
|
225
|
+
}
|
|
226
|
+
value={label ? label : 'Suppressed'}
|
|
227
|
+
fieldName='label'
|
|
228
|
+
label='Suppressed Data Label'
|
|
229
|
+
placeholder=''
|
|
230
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
231
|
+
/>
|
|
232
|
+
<CheckBox
|
|
233
|
+
tooltip={
|
|
234
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
235
|
+
<Tooltip.Target>
|
|
236
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
237
|
+
</Tooltip.Target>
|
|
238
|
+
<Tooltip.Content>
|
|
239
|
+
<p>Enabling this tooltip will provide a clearer indication of 'suppressed' or 'zero data' values, whichever is applicable. Deselecting 'Display In Tooltip' indicates that you do not want to display 'suppressed' or 'zero data' values in tooltips when hovering over them.</p>
|
|
240
|
+
</Tooltip.Content>
|
|
241
|
+
</Tooltip>
|
|
242
|
+
}
|
|
243
|
+
value={displayTooltip}
|
|
244
|
+
fieldName='displayTooltip'
|
|
245
|
+
label='Display in tooltips'
|
|
246
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
247
|
+
/>
|
|
248
|
+
<CheckBox
|
|
249
|
+
tooltip={
|
|
250
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
251
|
+
<Tooltip.Target>
|
|
252
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
253
|
+
</Tooltip.Target>
|
|
254
|
+
<Tooltip.Content>
|
|
255
|
+
<p>Deselecting "Display in Legend" indicates that you do not want to display suppressed data in the legend.</p>
|
|
256
|
+
</Tooltip.Content>
|
|
257
|
+
</Tooltip>
|
|
258
|
+
}
|
|
259
|
+
value={displayLegend}
|
|
260
|
+
fieldName='displayLegend'
|
|
261
|
+
label='Display in legend'
|
|
262
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
263
|
+
/>
|
|
264
|
+
<CheckBox
|
|
265
|
+
tooltip={
|
|
266
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
267
|
+
<Tooltip.Target>
|
|
268
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
269
|
+
</Tooltip.Target>
|
|
270
|
+
<Tooltip.Content>
|
|
271
|
+
<p>Deselecting "Display In Data Table" indicates that you do not want to display suppressed data in the data table.</p>
|
|
272
|
+
</Tooltip.Content>
|
|
273
|
+
</Tooltip>
|
|
274
|
+
}
|
|
275
|
+
value={displayTable}
|
|
276
|
+
fieldName='displayTable'
|
|
277
|
+
label='Display in table'
|
|
278
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
279
|
+
/>
|
|
280
|
+
</>
|
|
281
|
+
) : (
|
|
282
|
+
<>
|
|
283
|
+
<Select value={seriesKey} initial='Select' fieldName='seriesKey' label='ASSOCIATE TO SERIES' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={config.runtime.lineSeriesKeys ?? config.runtime?.seriesKeys} />
|
|
284
|
+
<Select value={column} initial='Select' fieldName='column' label='COLUMN WITH CONFIGURATION VALUE' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getColumnOptions()} />
|
|
285
|
+
<TextField value={value} fieldName='value' label='VALUE TO TRIGGER' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
|
|
286
|
+
<Select value={style} initial='Select' fieldName='style' label='Style' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getStyleOptions(type)} />
|
|
287
|
+
<TextField value={label} fieldName='label' label='Label' placeholder='' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
|
|
288
|
+
</>
|
|
289
|
+
)}
|
|
191
290
|
</div>
|
|
192
291
|
)
|
|
193
292
|
})}
|
|
194
293
|
|
|
195
294
|
<button type='button' onClick={addColumn} className='btn full-width'>
|
|
196
|
-
{config.visualizationType === 'Line'
|
|
295
|
+
{config.visualizationType === 'Line' ? 'Add Special Line' : config.visualizationType === 'Bar' ? ' Add Special Bar' : 'Add Special Bar/Line'}
|
|
197
296
|
</button>
|
|
198
297
|
</>
|
|
199
298
|
)
|
|
200
|
-
}
|
|
299
|
+
}
|
|
201
300
|
|
|
202
301
|
const EditorPanel = () => {
|
|
203
302
|
const {
|
|
@@ -223,9 +322,6 @@ const EditorPanel = () => {
|
|
|
223
322
|
} = useContext<ChartContext>(ConfigContext)
|
|
224
323
|
|
|
225
324
|
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, unfilteredData)
|
|
226
|
-
|
|
227
|
-
const { twoColorPalettes, sequential, nonSequential } = useColorPalette(config, updateConfig)
|
|
228
|
-
|
|
229
325
|
const properties = { data, config }
|
|
230
326
|
const { leftMax, rightMax } = useMinMax(properties)
|
|
231
327
|
|
|
@@ -275,9 +371,6 @@ const EditorPanel = () => {
|
|
|
275
371
|
visHasDataSuppression
|
|
276
372
|
} = useEditorPermissions()
|
|
277
373
|
|
|
278
|
-
// argument acts as props
|
|
279
|
-
const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({ config, setConfig: updateConfig, filteredData: data, setFilteredData })
|
|
280
|
-
|
|
281
374
|
// when the visualization type changes we
|
|
282
375
|
// have to update the individual series type & axis details
|
|
283
376
|
// dataKey is unchanged here.
|
|
@@ -388,13 +481,18 @@ const EditorPanel = () => {
|
|
|
388
481
|
return
|
|
389
482
|
}
|
|
390
483
|
|
|
391
|
-
|
|
484
|
+
const truthy = val => {
|
|
485
|
+
if (val === 0) return true // indexes can be used as keys
|
|
486
|
+
return !!val
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (section === 'columns' && truthy(subsection) && truthy(fieldName)) {
|
|
392
490
|
updateConfig({
|
|
393
491
|
...config,
|
|
394
|
-
|
|
395
|
-
...config
|
|
492
|
+
columns: {
|
|
493
|
+
...config.columns,
|
|
396
494
|
[subsection]: {
|
|
397
|
-
...config[
|
|
495
|
+
...config.columns[subsection],
|
|
398
496
|
[fieldName]: newValue
|
|
399
497
|
}
|
|
400
498
|
}
|
|
@@ -402,6 +500,8 @@ const EditorPanel = () => {
|
|
|
402
500
|
return
|
|
403
501
|
}
|
|
404
502
|
if (null === section && null === subsection) {
|
|
503
|
+
// special case that allows for updating the config object directly
|
|
504
|
+
if (!truthy(fieldName)) console.error('fieldName is required')
|
|
405
505
|
let updatedConfig = { ...config, [fieldName]: newValue }
|
|
406
506
|
enforceRestrictions(updatedConfig)
|
|
407
507
|
updateConfig(updatedConfig)
|
|
@@ -412,13 +512,13 @@ const EditorPanel = () => {
|
|
|
412
512
|
|
|
413
513
|
let sectionValue = isArray ? [...config[section], newValue] : { ...config[section], [fieldName]: newValue }
|
|
414
514
|
|
|
415
|
-
if (
|
|
515
|
+
if (truthy(subsection)) {
|
|
416
516
|
if (isArray) {
|
|
417
517
|
sectionValue = [...config[section]]
|
|
418
518
|
sectionValue[subsection] = { ...sectionValue[subsection], [fieldName]: newValue }
|
|
419
519
|
} else if (typeof newValue === 'string') {
|
|
420
520
|
sectionValue[subsection] = newValue
|
|
421
|
-
} else {
|
|
521
|
+
} else if (truthy(fieldName)) {
|
|
422
522
|
sectionValue = { ...config[section], [subsection]: { ...config[section][subsection], [fieldName]: newValue } }
|
|
423
523
|
}
|
|
424
524
|
}
|
|
@@ -456,30 +556,6 @@ const EditorPanel = () => {
|
|
|
456
556
|
})
|
|
457
557
|
}
|
|
458
558
|
|
|
459
|
-
const removeFilter = index => {
|
|
460
|
-
let filters = [...config.filters]
|
|
461
|
-
|
|
462
|
-
filters.splice(index, 1)
|
|
463
|
-
|
|
464
|
-
updateConfig({ ...config, filters })
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
const updateFilterProp = (name, index, value) => {
|
|
468
|
-
let filters = [...config.filters]
|
|
469
|
-
|
|
470
|
-
filters[index][name] = value
|
|
471
|
-
|
|
472
|
-
updateConfig({ ...config, filters })
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
const addNewFilter = () => {
|
|
476
|
-
let filters = config.filters ? [...config.filters] : []
|
|
477
|
-
|
|
478
|
-
filters.push({ values: [] })
|
|
479
|
-
|
|
480
|
-
updateConfig({ ...config, filters })
|
|
481
|
-
}
|
|
482
|
-
|
|
483
559
|
const addNewSeries = seriesKey => {
|
|
484
560
|
let newSeries = config.series ? [...config.series] : []
|
|
485
561
|
let forecastingStages = Array.from(new Set(data.map(item => item[seriesKey])))
|
|
@@ -504,37 +580,6 @@ const EditorPanel = () => {
|
|
|
504
580
|
updateConfig({ ...config }, newData)
|
|
505
581
|
}
|
|
506
582
|
|
|
507
|
-
const removeSeries = seriesKey => {
|
|
508
|
-
let series = [...config.series]
|
|
509
|
-
let seriesIndex = -1
|
|
510
|
-
|
|
511
|
-
for (let i = 0; i < series.length; i++) {
|
|
512
|
-
if (series[i].dataKey === seriesKey) {
|
|
513
|
-
seriesIndex = i
|
|
514
|
-
break
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
if (seriesIndex !== -1) {
|
|
519
|
-
series.splice(seriesIndex, 1)
|
|
520
|
-
|
|
521
|
-
let newConfig = { ...config, series }
|
|
522
|
-
|
|
523
|
-
if (series.length === 0) {
|
|
524
|
-
delete newConfig.series
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
updateConfig(newConfig)
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
if (config.visualizationType === 'Paired Bar') {
|
|
531
|
-
updateConfig({
|
|
532
|
-
...config,
|
|
533
|
-
series: []
|
|
534
|
-
})
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
583
|
const addNewExclusion = exclusionKey => {
|
|
539
584
|
let newExclusion = [...config.exclusions.keys]
|
|
540
585
|
newExclusion.push(exclusionKey)
|
|
@@ -568,16 +613,6 @@ const EditorPanel = () => {
|
|
|
568
613
|
}
|
|
569
614
|
}
|
|
570
615
|
|
|
571
|
-
const getFilters = () => {
|
|
572
|
-
let columns = {}
|
|
573
|
-
|
|
574
|
-
unfilteredData.forEach(row => {
|
|
575
|
-
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
576
|
-
})
|
|
577
|
-
|
|
578
|
-
return Object.keys(columns)
|
|
579
|
-
}
|
|
580
|
-
|
|
581
616
|
const getColumns = (filter = true) => {
|
|
582
617
|
let columns = {}
|
|
583
618
|
unfilteredData.forEach(row => {
|
|
@@ -617,40 +652,10 @@ const EditorPanel = () => {
|
|
|
617
652
|
|
|
618
653
|
const onBackClick = () => {
|
|
619
654
|
setDisplayPanel(!displayPanel)
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
<section className='waiting'>
|
|
625
|
-
<section className='waiting-container'>
|
|
626
|
-
<h3>Error With Configuration</h3>
|
|
627
|
-
<p>{config.runtime.editorErrorMessage}</p>
|
|
628
|
-
</section>
|
|
629
|
-
</section>
|
|
630
|
-
)
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
const Confirm = () => {
|
|
634
|
-
const confirmDone = e => {
|
|
635
|
-
e.preventDefault()
|
|
636
|
-
|
|
637
|
-
let newConfig = { ...config }
|
|
638
|
-
delete newConfig.newViz
|
|
639
|
-
|
|
640
|
-
updateConfig(newConfig)
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
return (
|
|
644
|
-
<section className='waiting'>
|
|
645
|
-
<section className='waiting-container'>
|
|
646
|
-
<h3>Finish Configuring</h3>
|
|
647
|
-
<p>Set all required options to the left and confirm below to display a preview of the chart.</p>
|
|
648
|
-
<button className='btn' style={{ margin: '1em auto' }} disabled={missingRequiredSections()} onClick={confirmDone}>
|
|
649
|
-
I'm Done
|
|
650
|
-
</button>
|
|
651
|
-
</section>
|
|
652
|
-
</section>
|
|
653
|
-
)
|
|
655
|
+
updateConfig({
|
|
656
|
+
...config,
|
|
657
|
+
showEditorPanel: !displayPanel
|
|
658
|
+
})
|
|
654
659
|
}
|
|
655
660
|
|
|
656
661
|
const convertStateToConfig = () => {
|
|
@@ -931,40 +936,8 @@ const EditorPanel = () => {
|
|
|
931
936
|
})
|
|
932
937
|
}
|
|
933
938
|
|
|
934
|
-
// prevents adding duplicates
|
|
935
|
-
const additionalColumns = Object.keys(config.columns).filter(value => {
|
|
936
|
-
const defaultCols = [config.xAxis.dataKey] // ['geo', 'navigate', 'primary', 'latitude', 'longitude']
|
|
937
|
-
|
|
938
|
-
if (true === defaultCols.includes(value)) {
|
|
939
|
-
return false
|
|
940
|
-
}
|
|
941
|
-
return true
|
|
942
|
-
})
|
|
943
|
-
|
|
944
|
-
// just adds a new column but not set to any data yet
|
|
945
|
-
const addAdditionalColumn = number => {
|
|
946
|
-
const columnKey = `additionalColumn${number}`
|
|
947
|
-
|
|
948
|
-
updateConfig({
|
|
949
|
-
...config,
|
|
950
|
-
columns: {
|
|
951
|
-
...config.columns,
|
|
952
|
-
[columnKey]: {
|
|
953
|
-
label: 'New Column',
|
|
954
|
-
dataTable: false,
|
|
955
|
-
tooltips: false,
|
|
956
|
-
prefix: '',
|
|
957
|
-
suffix: '',
|
|
958
|
-
forestPlot: false,
|
|
959
|
-
startingPoint: '0',
|
|
960
|
-
forestPlotAlignRight: false
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
})
|
|
964
|
-
}
|
|
965
|
-
|
|
966
939
|
const removeAdditionalColumn = columnName => {
|
|
967
|
-
const newColumns = config.columns
|
|
940
|
+
const newColumns = _.cloneDeep(config.columns)
|
|
968
941
|
|
|
969
942
|
delete newColumns[columnName]
|
|
970
943
|
|
|
@@ -1076,128 +1049,144 @@ const EditorPanel = () => {
|
|
|
1076
1049
|
return (
|
|
1077
1050
|
<EditorPanelContext.Provider value={editorContextValues}>
|
|
1078
1051
|
<ErrorBoundary component='EditorPanel'>
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1052
|
+
<Layout.Sidebar displayPanel={displayPanel} isDashboard={isDashboard} title={'Configure Chart'} onBackClick={onBackClick}>
|
|
1053
|
+
<Accordion allowZeroExpanded={true}>
|
|
1054
|
+
<Panels.General name='General' />
|
|
1055
|
+
<Panels.ForestPlot name='Forest Plot Settings' />
|
|
1056
|
+
<Panels.Sankey name='Sankey' />
|
|
1057
|
+
{config.visualizationType !== 'Pie' && config.visualizationType !== 'Forest Plot' && config.visualizationType !== 'Sankey' && (
|
|
1058
|
+
<AccordionItem>
|
|
1059
|
+
<AccordionItemHeading>
|
|
1060
|
+
<AccordionItemButton>Data Series {(!config.series || config.series.length === 0 || (config.visualizationType === 'Paired Bar' && config.series.length < 2)) && <WarningImage width='25' className='warning-icon' />}</AccordionItemButton>
|
|
1061
|
+
</AccordionItemHeading>
|
|
1062
|
+
<AccordionItemPanel>
|
|
1063
|
+
{(!config.series || config.series.length === 0) && config.visualizationType !== 'Paired Bar' && <p className='warning'>At least one series is required</p>}
|
|
1064
|
+
{(!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>}
|
|
1065
|
+
<>
|
|
1066
|
+
<Select
|
|
1067
|
+
fieldName='visualizationType'
|
|
1068
|
+
label='Add Data Series'
|
|
1069
|
+
initial='Select'
|
|
1070
|
+
onChange={e => {
|
|
1071
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
1072
|
+
addNewSeries(e.target.value)
|
|
1073
|
+
}
|
|
1074
|
+
e.target.value = ''
|
|
1075
|
+
}}
|
|
1076
|
+
options={getColumns()}
|
|
1077
|
+
/>
|
|
1078
|
+
{config.series && config.series.length !== 0 && (
|
|
1079
|
+
<Panels.Series.Wrapper getColumns={getColumns}>
|
|
1080
|
+
<fieldset>
|
|
1081
|
+
<legend className='edit-label float-left'>Displaying</legend>
|
|
1082
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1083
|
+
<Tooltip.Target>
|
|
1084
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1085
|
+
</Tooltip.Target>
|
|
1086
|
+
<Tooltip.Content>
|
|
1087
|
+
<p>A data series is a set of related data points plotted in a chart and typically represented in the chart legend.</p>
|
|
1088
|
+
</Tooltip.Content>
|
|
1089
|
+
</Tooltip>
|
|
1090
|
+
</fieldset>
|
|
1091
|
+
|
|
1092
|
+
<DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
|
|
1093
|
+
<Droppable droppableId='filter_order'>
|
|
1094
|
+
{/* prettier-ignore */}
|
|
1095
|
+
{provided => {
|
|
1096
|
+
return (
|
|
1097
|
+
<ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
|
|
1098
|
+
<Panels.Series.List series={config.series} getItemStyle={getItemStyle} sortableItemStyles={sortableItemStyles} chartsWithOptions={chartsWithOptions} />
|
|
1099
|
+
{provided.placeholder}
|
|
1100
|
+
</ul>
|
|
1101
|
+
)
|
|
1102
|
+
}}
|
|
1103
|
+
</Droppable>
|
|
1104
|
+
</DragDropContext>
|
|
1105
|
+
</Panels.Series.Wrapper>
|
|
1106
|
+
)}
|
|
1107
|
+
</>
|
|
1108
|
+
{config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
|
|
1099
1109
|
<>
|
|
1100
|
-
<
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
initial='Select'
|
|
1104
|
-
onChange={e => {
|
|
1105
|
-
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
1106
|
-
addNewSeries(e.target.value)
|
|
1107
|
-
}
|
|
1108
|
-
e.target.value = ''
|
|
1109
|
-
}}
|
|
1110
|
-
options={getColumns()}
|
|
1111
|
-
/>
|
|
1112
|
-
{config.series && config.series.length !== 0 && (
|
|
1113
|
-
<Panels.Series.Wrapper getColumns={getColumns}>
|
|
1114
|
-
<fieldset>
|
|
1115
|
-
<legend className='edit-label float-left'>Displaying</legend>
|
|
1116
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1117
|
-
<Tooltip.Target>
|
|
1118
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1119
|
-
</Tooltip.Target>
|
|
1120
|
-
<Tooltip.Content>
|
|
1121
|
-
<p>A data series is a set of related data points plotted in a chart and typically represented in the chart legend.</p>
|
|
1122
|
-
</Tooltip.Content>
|
|
1123
|
-
</Tooltip>
|
|
1124
|
-
</fieldset>
|
|
1125
|
-
|
|
1126
|
-
<DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
|
|
1127
|
-
<Droppable droppableId='filter_order'>
|
|
1128
|
-
{/* prettier-ignore */}
|
|
1129
|
-
{provided => {
|
|
1130
|
-
return (
|
|
1131
|
-
<ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
|
|
1132
|
-
<Panels.Series.List series={config.series} getItemStyle={getItemStyle} sortableItemStyles={sortableItemStyles} chartsWithOptions={chartsWithOptions} />
|
|
1133
|
-
{provided.placeholder}
|
|
1134
|
-
</ul>
|
|
1135
|
-
)
|
|
1136
|
-
}}
|
|
1137
|
-
</Droppable>
|
|
1138
|
-
</DragDropContext>
|
|
1139
|
-
</Panels.Series.Wrapper>
|
|
1140
|
-
)}
|
|
1110
|
+
<span className='divider-heading'>Confidence Keys</span>
|
|
1111
|
+
<Select value={config.confidenceKeys.upper || ''} section='confidenceKeys' fieldName='upper' label='Upper' updateField={updateField} initial='Select' options={getColumns()} />
|
|
1112
|
+
<Select value={config.confidenceKeys.lower || ''} section='confidenceKeys' fieldName='lower' label='Lower' updateField={updateField} initial='Select' options={getColumns()} />
|
|
1141
1113
|
</>
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
{config.
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1114
|
+
)}
|
|
1115
|
+
{visSupportsRankByValue() && config.series && config.series.length === 1 && <Select fieldName='visualizationType' label='Rank by Value' initial='Select' onChange={e => sortSeries(e.target.value)} options={['asc', 'desc']} />}
|
|
1116
|
+
{/* {visHasDataSuppression() && <DataSuppression config={config} updateConfig={updateConfig} data={data} />} */}
|
|
1117
|
+
{visSupportsPreliminaryData() && <PreliminaryData config={config} updateConfig={updateConfig} data={data} />}
|
|
1118
|
+
</AccordionItemPanel>
|
|
1119
|
+
</AccordionItem>
|
|
1120
|
+
)}
|
|
1121
|
+
<Panels.BoxPlot name='Measures' />
|
|
1122
|
+
{/* Left Value Axis */}
|
|
1123
|
+
{visSupportsLeftValueAxis() && (
|
|
1124
|
+
<AccordionItem>
|
|
1125
|
+
<AccordionItemHeading>
|
|
1126
|
+
<AccordionItemButton>
|
|
1127
|
+
{config.visualizationType === 'Pie' ? 'Data Format' : config.orientation === 'vertical' ? 'Left Value Axis' : 'Value Axis'}
|
|
1128
|
+
{config.visualizationType === 'Pie' && !config.yAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
|
|
1129
|
+
</AccordionItemButton>
|
|
1130
|
+
</AccordionItemHeading>
|
|
1131
|
+
<AccordionItemPanel>
|
|
1132
|
+
{config.visualizationType === 'Pie' && (
|
|
1133
|
+
<Select
|
|
1134
|
+
value={config.yAxis.dataKey || ''}
|
|
1135
|
+
section='yAxis'
|
|
1136
|
+
fieldName='dataKey'
|
|
1137
|
+
label='Data Column'
|
|
1138
|
+
initial='Select'
|
|
1139
|
+
required={true}
|
|
1140
|
+
updateField={updateField}
|
|
1141
|
+
options={getColumns(false)}
|
|
1142
|
+
tooltip={
|
|
1143
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1144
|
+
<Tooltip.Target>
|
|
1145
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1146
|
+
</Tooltip.Target>
|
|
1147
|
+
<Tooltip.Content>
|
|
1148
|
+
<p>Select the source data to be visually represented.</p>
|
|
1149
|
+
</Tooltip.Content>
|
|
1150
|
+
</Tooltip>
|
|
1151
|
+
}
|
|
1152
|
+
/>
|
|
1153
|
+
)}
|
|
1154
|
+
{config.visualizationType !== 'Pie' && (
|
|
1155
|
+
<>
|
|
1156
|
+
<TextField value={config.yAxis.label} section='yAxis' fieldName='label' label='Label ' updateField={updateField} />
|
|
1157
|
+
{config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && !['Box Plot', 'Deviation Bar', 'Forest Plot'].includes(config.visualizationType) && (
|
|
1158
|
+
<CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />
|
|
1159
|
+
)}
|
|
1160
|
+
<TextField value={config.yAxis.numTicks} placeholder='Auto' type='number' section='yAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
|
|
1161
|
+
<TextField
|
|
1162
|
+
value={config.yAxis.size}
|
|
1163
|
+
type='number'
|
|
1169
1164
|
section='yAxis'
|
|
1170
|
-
fieldName='
|
|
1171
|
-
label='
|
|
1172
|
-
|
|
1173
|
-
required={true}
|
|
1165
|
+
fieldName='size'
|
|
1166
|
+
label={config.orientation === 'horizontal' ? 'Size (Height)' : 'Size (Width)'}
|
|
1167
|
+
className='number-narrow'
|
|
1174
1168
|
updateField={updateField}
|
|
1175
|
-
options={getColumns(false)}
|
|
1176
1169
|
tooltip={
|
|
1177
1170
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
1178
1171
|
<Tooltip.Target>
|
|
1179
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1172
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1180
1173
|
</Tooltip.Target>
|
|
1181
1174
|
<Tooltip.Content>
|
|
1182
|
-
<p>
|
|
1175
|
+
<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>
|
|
1183
1176
|
</Tooltip.Content>
|
|
1184
1177
|
</Tooltip>
|
|
1185
1178
|
}
|
|
1186
1179
|
/>
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
<TextField value={config.yAxis.label} section='yAxis' fieldName='label' label='Label ' updateField={updateField} />
|
|
1191
|
-
{config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && !['Box Plot', 'Deviation Bar', 'Forest Plot'].includes(config.visualizationType) && (
|
|
1192
|
-
<CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />
|
|
1193
|
-
)}
|
|
1194
|
-
<TextField value={config.yAxis.numTicks} placeholder='Auto' type='number' section='yAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
|
|
1180
|
+
{config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
|
|
1181
|
+
{(config.orientation === 'vertical' || !config.isResponsiveTicks) && <TextField value={config.yAxis.tickRotation || 0} type='number' min={0} section='yAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
|
|
1182
|
+
{config.isResponsiveTicks && config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && (
|
|
1195
1183
|
<TextField
|
|
1196
|
-
value={config.
|
|
1184
|
+
value={config.xAxis.maxTickRotation}
|
|
1197
1185
|
type='number'
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1186
|
+
min={0}
|
|
1187
|
+
section='xAxis'
|
|
1188
|
+
fieldName='maxTickRotation'
|
|
1189
|
+
label='Max Tick Rotation'
|
|
1201
1190
|
className='number-narrow'
|
|
1202
1191
|
updateField={updateField}
|
|
1203
1192
|
tooltip={
|
|
@@ -1206,552 +1195,523 @@ const EditorPanel = () => {
|
|
|
1206
1195
|
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1207
1196
|
</Tooltip.Target>
|
|
1208
1197
|
<Tooltip.Content>
|
|
1209
|
-
<p>
|
|
1198
|
+
<p>Degrees ticks will be rotated if values overlap, especially in smaller viewports.</p>
|
|
1210
1199
|
</Tooltip.Content>
|
|
1211
1200
|
</Tooltip>
|
|
1212
1201
|
}
|
|
1213
1202
|
/>
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1203
|
+
)}
|
|
1204
|
+
|
|
1205
|
+
{/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
|
|
1206
|
+
{/* <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
|
|
1207
|
+
{config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
|
|
1208
|
+
{visSupportsValueAxisGridLines() && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Show Gridlines' updateField={updateField} />}
|
|
1209
|
+
<CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
|
|
1210
|
+
{config.yAxis.enablePadding && <TextField type='number' section='yAxis' fieldName='scalePadding' label='Padding Percentage' className='number-narrow' updateField={updateField} value={config.yAxis.scalePadding} />}
|
|
1211
|
+
{config.visualizationSubType === 'regular' && config.visualizationType !== 'Forest Plot' && <CheckBox value={config.useLogScale} fieldName='useLogScale' label='use logarithmic scale' updateField={updateField} />}
|
|
1212
|
+
</>
|
|
1213
|
+
)}
|
|
1214
|
+
<span className='divider-heading'>Number Formatting</span>
|
|
1215
|
+
<CheckBox
|
|
1216
|
+
value={config.dataFormat.commas}
|
|
1217
|
+
section='dataFormat'
|
|
1218
|
+
fieldName='commas'
|
|
1219
|
+
label='Add commas'
|
|
1220
|
+
updateField={updateField}
|
|
1221
|
+
tooltip={
|
|
1222
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1223
|
+
<Tooltip.Target>
|
|
1224
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1225
|
+
</Tooltip.Target>
|
|
1226
|
+
<Tooltip.Content>
|
|
1227
|
+
<p>{`Selecting this option will add commas to the left value axis, tooltip hover, and data table.`}</p>
|
|
1228
|
+
</Tooltip.Content>
|
|
1229
|
+
</Tooltip>
|
|
1230
|
+
}
|
|
1231
|
+
/>
|
|
1232
|
+
<CheckBox
|
|
1233
|
+
value={config.dataFormat.abbreviated}
|
|
1234
|
+
section='dataFormat'
|
|
1235
|
+
fieldName='abbreviated'
|
|
1236
|
+
label='Abbreviate Axis Values'
|
|
1237
|
+
updateField={updateField}
|
|
1238
|
+
tooltip={
|
|
1239
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1240
|
+
<Tooltip.Target>
|
|
1241
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1242
|
+
</Tooltip.Target>
|
|
1243
|
+
<Tooltip.Content>
|
|
1244
|
+
<p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
|
|
1245
|
+
</Tooltip.Content>
|
|
1246
|
+
</Tooltip>
|
|
1247
|
+
}
|
|
1248
|
+
/>
|
|
1249
|
+
<TextField value={config.dataFormat.roundTo ? config.dataFormat.roundTo : 0} type='number' section='dataFormat' fieldName='roundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
|
|
1250
|
+
<div className='two-col-inputs'>
|
|
1251
|
+
<TextField
|
|
1252
|
+
value={config.dataFormat.prefix}
|
|
1252
1253
|
section='dataFormat'
|
|
1253
|
-
fieldName='
|
|
1254
|
-
label='
|
|
1254
|
+
fieldName='prefix'
|
|
1255
|
+
label='Prefix'
|
|
1255
1256
|
updateField={updateField}
|
|
1256
1257
|
tooltip={
|
|
1257
1258
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
1258
1259
|
<Tooltip.Target>
|
|
1259
|
-
<Icon display='question' style={{ marginLeft: '0.5rem'
|
|
1260
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1260
1261
|
</Tooltip.Target>
|
|
1261
1262
|
<Tooltip.Content>
|
|
1262
|
-
<p>
|
|
1263
|
+
{config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
|
|
1264
|
+
{config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
|
|
1263
1265
|
</Tooltip.Content>
|
|
1264
1266
|
</Tooltip>
|
|
1265
1267
|
}
|
|
1266
1268
|
/>
|
|
1267
|
-
<TextField
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
<
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
/>
|
|
1287
|
-
<TextField
|
|
1288
|
-
value={config.dataFormat.suffix}
|
|
1289
|
-
section='dataFormat'
|
|
1290
|
-
fieldName='suffix'
|
|
1291
|
-
label='Suffix'
|
|
1292
|
-
updateField={updateField}
|
|
1293
|
-
tooltip={
|
|
1294
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1295
|
-
<Tooltip.Target>
|
|
1296
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1297
|
-
</Tooltip.Target>
|
|
1298
|
-
<Tooltip.Content>
|
|
1299
|
-
{config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
|
|
1300
|
-
{config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
|
|
1301
|
-
</Tooltip.Content>
|
|
1302
|
-
</Tooltip>
|
|
1303
|
-
}
|
|
1304
|
-
/>
|
|
1305
|
-
</div>
|
|
1269
|
+
<TextField
|
|
1270
|
+
value={config.dataFormat.suffix}
|
|
1271
|
+
section='dataFormat'
|
|
1272
|
+
fieldName='suffix'
|
|
1273
|
+
label='Suffix'
|
|
1274
|
+
updateField={updateField}
|
|
1275
|
+
tooltip={
|
|
1276
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1277
|
+
<Tooltip.Target>
|
|
1278
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1279
|
+
</Tooltip.Target>
|
|
1280
|
+
<Tooltip.Content>
|
|
1281
|
+
{config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
|
|
1282
|
+
{config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
|
|
1283
|
+
</Tooltip.Content>
|
|
1284
|
+
</Tooltip>
|
|
1285
|
+
}
|
|
1286
|
+
/>
|
|
1287
|
+
</div>
|
|
1306
1288
|
|
|
1307
|
-
|
|
1289
|
+
{config.orientation === 'horizontal' ? ( // horizontal - x is vertical y is horizontal
|
|
1290
|
+
<>
|
|
1291
|
+
{visSupportsValueAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
|
|
1292
|
+
{visSupportsValueAxisLabels() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
|
|
1293
|
+
{visSupportsValueAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
|
|
1294
|
+
{visSupportsValueAxisMax() && <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />}
|
|
1295
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
1296
|
+
{visSupportsValueAxisMin() && <TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />}
|
|
1297
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
|
|
1298
|
+
{config.visualizationType === 'Deviation Bar' && (
|
|
1299
|
+
<>
|
|
1300
|
+
<TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
|
|
1301
|
+
<TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
|
|
1302
|
+
<CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Show Deviation point label' updateField={updateField} />
|
|
1303
|
+
</>
|
|
1304
|
+
)}
|
|
1305
|
+
</>
|
|
1306
|
+
) : (
|
|
1307
|
+
config.visualizationType !== 'Pie' && (
|
|
1308
1308
|
<>
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1309
|
+
<CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
1310
|
+
<CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
|
|
1311
|
+
<CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1312
|
+
|
|
1313
|
+
<TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='left axis max value' placeholder='Auto' updateField={updateField} />
|
|
1313
1314
|
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
1314
|
-
|
|
1315
|
+
<TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='left axis min value' placeholder='Auto' updateField={updateField} />
|
|
1315
1316
|
<span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
|
|
1316
|
-
{config.visualizationType === 'Deviation Bar' && (
|
|
1317
|
-
<>
|
|
1318
|
-
<TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
|
|
1319
|
-
<TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
|
|
1320
|
-
<CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Show Deviation point label' updateField={updateField} />
|
|
1321
|
-
</>
|
|
1322
|
-
)}
|
|
1323
1317
|
</>
|
|
1324
|
-
)
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
<
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
<div className='edit-block'>
|
|
1342
|
-
<span className='edit-label column-heading'>Anchors</span>
|
|
1343
|
-
<Accordion allowZeroExpanded>
|
|
1344
|
-
{config.yAxis?.anchors?.map((anchor, index) => (
|
|
1345
|
-
<AccordionItem className='series-item series-item--chart' key={`yaxis-anchors-2-${index}`}>
|
|
1346
|
-
<AccordionItemHeading className='series-item__title'>
|
|
1347
|
-
<>
|
|
1348
|
-
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
1349
|
-
Anchor {index + 1}
|
|
1350
|
-
<button
|
|
1351
|
-
className='series-list__remove'
|
|
1352
|
-
onClick={e => {
|
|
1353
|
-
e.preventDefault()
|
|
1354
|
-
const copiedAnchorGroups = [...config.yAxis.anchors]
|
|
1355
|
-
copiedAnchorGroups.splice(index, 1)
|
|
1356
|
-
updateConfig({
|
|
1357
|
-
...config,
|
|
1358
|
-
yAxis: {
|
|
1359
|
-
...config.yAxis,
|
|
1360
|
-
anchors: copiedAnchorGroups
|
|
1361
|
-
}
|
|
1362
|
-
})
|
|
1363
|
-
}}
|
|
1364
|
-
>
|
|
1365
|
-
Remove
|
|
1366
|
-
</button>
|
|
1367
|
-
</AccordionItemButton>
|
|
1368
|
-
</>
|
|
1369
|
-
</AccordionItemHeading>
|
|
1370
|
-
<AccordionItemPanel>
|
|
1371
|
-
<label>
|
|
1372
|
-
<span>Anchor Value</span>
|
|
1373
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1374
|
-
<Tooltip.Target>
|
|
1375
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1376
|
-
</Tooltip.Target>
|
|
1377
|
-
<Tooltip.Content>
|
|
1378
|
-
<p>Enter the value as its shown in the data column</p>
|
|
1379
|
-
</Tooltip.Content>
|
|
1380
|
-
</Tooltip>
|
|
1381
|
-
<input
|
|
1382
|
-
type='text'
|
|
1383
|
-
value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
|
|
1384
|
-
onChange={e => {
|
|
1385
|
-
e.preventDefault()
|
|
1386
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
1387
|
-
copiedAnchors[index].value = e.target.value
|
|
1388
|
-
updateConfig({
|
|
1389
|
-
...config,
|
|
1390
|
-
yAxis: {
|
|
1391
|
-
...config.yAxis,
|
|
1392
|
-
anchors: copiedAnchors
|
|
1393
|
-
}
|
|
1394
|
-
})
|
|
1395
|
-
}}
|
|
1396
|
-
/>
|
|
1397
|
-
</label>
|
|
1398
|
-
|
|
1399
|
-
<label>
|
|
1400
|
-
<span>Anchor Color</span>
|
|
1401
|
-
<input
|
|
1402
|
-
type='text'
|
|
1403
|
-
value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
|
|
1404
|
-
onChange={e => {
|
|
1318
|
+
)
|
|
1319
|
+
)}
|
|
1320
|
+
|
|
1321
|
+
{/* start: anchors */}
|
|
1322
|
+
{visHasAnchors() && config.orientation !== 'horizontal' && (
|
|
1323
|
+
<div className='edit-block'>
|
|
1324
|
+
<span className='edit-label column-heading'>Anchors</span>
|
|
1325
|
+
<Accordion allowZeroExpanded>
|
|
1326
|
+
{config.yAxis?.anchors?.map((anchor, index) => (
|
|
1327
|
+
<AccordionItem className='series-item series-item--chart' key={`yaxis-anchors-2-${index}`}>
|
|
1328
|
+
<AccordionItemHeading className='series-item__title'>
|
|
1329
|
+
<>
|
|
1330
|
+
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
1331
|
+
Anchor {index + 1}
|
|
1332
|
+
<button
|
|
1333
|
+
className='series-list__remove'
|
|
1334
|
+
onClick={e => {
|
|
1405
1335
|
e.preventDefault()
|
|
1406
|
-
const
|
|
1407
|
-
|
|
1336
|
+
const copiedAnchorGroups = [...config.yAxis.anchors]
|
|
1337
|
+
copiedAnchorGroups.splice(index, 1)
|
|
1408
1338
|
updateConfig({
|
|
1409
1339
|
...config,
|
|
1410
1340
|
yAxis: {
|
|
1411
1341
|
...config.yAxis,
|
|
1412
|
-
anchors:
|
|
1413
|
-
}
|
|
1414
|
-
})
|
|
1415
|
-
}}
|
|
1416
|
-
/>
|
|
1417
|
-
</label>
|
|
1418
|
-
|
|
1419
|
-
<label>
|
|
1420
|
-
Anchor Line Style
|
|
1421
|
-
<select
|
|
1422
|
-
value={config.yAxis.anchors[index].lineStyle || ''}
|
|
1423
|
-
onChange={e => {
|
|
1424
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
1425
|
-
copiedAnchors[index].lineStyle = e.target.value
|
|
1426
|
-
updateConfig({
|
|
1427
|
-
...config,
|
|
1428
|
-
yAxis: {
|
|
1429
|
-
...config.yAxis,
|
|
1430
|
-
anchors: copiedAnchors
|
|
1342
|
+
anchors: copiedAnchorGroups
|
|
1431
1343
|
}
|
|
1432
1344
|
})
|
|
1433
1345
|
}}
|
|
1434
1346
|
>
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1347
|
+
Remove
|
|
1348
|
+
</button>
|
|
1349
|
+
</AccordionItemButton>
|
|
1350
|
+
</>
|
|
1351
|
+
</AccordionItemHeading>
|
|
1352
|
+
<AccordionItemPanel>
|
|
1353
|
+
<label>
|
|
1354
|
+
<span>Anchor Value</span>
|
|
1355
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1356
|
+
<Tooltip.Target>
|
|
1357
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1358
|
+
</Tooltip.Target>
|
|
1359
|
+
<Tooltip.Content>
|
|
1360
|
+
<p>Enter the value as its shown in the data column</p>
|
|
1361
|
+
</Tooltip.Content>
|
|
1362
|
+
</Tooltip>
|
|
1363
|
+
<input
|
|
1364
|
+
type='text'
|
|
1365
|
+
value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
|
|
1366
|
+
onChange={e => {
|
|
1367
|
+
e.preventDefault()
|
|
1368
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
1369
|
+
copiedAnchors[index].value = e.target.value
|
|
1370
|
+
updateConfig({
|
|
1371
|
+
...config,
|
|
1372
|
+
yAxis: {
|
|
1373
|
+
...config.yAxis,
|
|
1374
|
+
anchors: copiedAnchors
|
|
1375
|
+
}
|
|
1376
|
+
})
|
|
1377
|
+
}}
|
|
1378
|
+
/>
|
|
1379
|
+
</label>
|
|
1465
1380
|
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1381
|
+
<label>
|
|
1382
|
+
<span>Anchor Color</span>
|
|
1383
|
+
<input
|
|
1384
|
+
type='text'
|
|
1385
|
+
value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
|
|
1386
|
+
onChange={e => {
|
|
1387
|
+
e.preventDefault()
|
|
1388
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
1389
|
+
copiedAnchors[index].color = e.target.value
|
|
1390
|
+
updateConfig({
|
|
1391
|
+
...config,
|
|
1392
|
+
yAxis: {
|
|
1393
|
+
...config.yAxis,
|
|
1394
|
+
anchors: copiedAnchors
|
|
1395
|
+
}
|
|
1396
|
+
})
|
|
1397
|
+
}}
|
|
1398
|
+
/>
|
|
1399
|
+
</label>
|
|
1400
|
+
|
|
1401
|
+
<label>
|
|
1402
|
+
Anchor Line Style
|
|
1403
|
+
<select
|
|
1404
|
+
value={config.yAxis.anchors[index].lineStyle || ''}
|
|
1405
|
+
onChange={e => {
|
|
1406
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
1407
|
+
copiedAnchors[index].lineStyle = e.target.value
|
|
1408
|
+
updateConfig({
|
|
1409
|
+
...config,
|
|
1410
|
+
yAxis: {
|
|
1411
|
+
...config.yAxis,
|
|
1412
|
+
anchors: copiedAnchors
|
|
1413
|
+
}
|
|
1414
|
+
})
|
|
1415
|
+
}}
|
|
1416
|
+
>
|
|
1417
|
+
<option>Select</option>
|
|
1418
|
+
{lineOptions.map(line => (
|
|
1419
|
+
<option key={line.key}>{line.value}</option>
|
|
1420
|
+
))}
|
|
1421
|
+
</select>
|
|
1422
|
+
</label>
|
|
1423
|
+
</AccordionItemPanel>
|
|
1424
|
+
</AccordionItem>
|
|
1425
|
+
))}
|
|
1426
|
+
</Accordion>
|
|
1427
|
+
|
|
1428
|
+
<button
|
|
1429
|
+
className='btn full-width'
|
|
1430
|
+
onClick={e => {
|
|
1431
|
+
e.preventDefault()
|
|
1432
|
+
const anchors = [...config.yAxis.anchors]
|
|
1433
|
+
anchors.push({} as Anchor)
|
|
1434
|
+
updateConfig({
|
|
1435
|
+
...config,
|
|
1436
|
+
yAxis: {
|
|
1437
|
+
...config.yAxis,
|
|
1438
|
+
anchors
|
|
1439
|
+
}
|
|
1440
|
+
})
|
|
1441
|
+
}}
|
|
1442
|
+
>
|
|
1443
|
+
Add Anchor
|
|
1444
|
+
</button>
|
|
1445
|
+
</div>
|
|
1446
|
+
)}
|
|
1447
|
+
|
|
1448
|
+
{visHasAnchors() && config.orientation === 'horizontal' && (
|
|
1449
|
+
<div className='edit-block'>
|
|
1450
|
+
<span className='edit-label column-heading'>Anchors</span>
|
|
1451
|
+
<Accordion allowZeroExpanded>
|
|
1452
|
+
{config.xAxis?.anchors?.map((anchor, index) => (
|
|
1453
|
+
<AccordionItem className='series-item series-item--chart' key={`xaxis-anchors-${index}`}>
|
|
1454
|
+
<AccordionItemHeading className='series-item__title'>
|
|
1455
|
+
<>
|
|
1456
|
+
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
1457
|
+
Anchor {index + 1}
|
|
1458
|
+
<button
|
|
1459
|
+
className='series-list__remove'
|
|
1460
|
+
onClick={e => {
|
|
1531
1461
|
e.preventDefault()
|
|
1532
|
-
const
|
|
1533
|
-
|
|
1462
|
+
const copiedAnchorGroups = [...config.xAxis.anchors]
|
|
1463
|
+
copiedAnchorGroups.splice(index, 1)
|
|
1534
1464
|
updateConfig({
|
|
1535
1465
|
...config,
|
|
1536
1466
|
xAxis: {
|
|
1537
1467
|
...config.xAxis,
|
|
1538
|
-
anchors:
|
|
1539
|
-
}
|
|
1540
|
-
})
|
|
1541
|
-
}}
|
|
1542
|
-
/>
|
|
1543
|
-
</label>
|
|
1544
|
-
|
|
1545
|
-
<label>
|
|
1546
|
-
Anchor Line Style
|
|
1547
|
-
<select
|
|
1548
|
-
value={config.xAxis.anchors[index].lineStyle || ''}
|
|
1549
|
-
onChange={e => {
|
|
1550
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
1551
|
-
copiedAnchors[index].lineStyle = e.target.value
|
|
1552
|
-
updateConfig({
|
|
1553
|
-
...config,
|
|
1554
|
-
xAxis: {
|
|
1555
|
-
...config.xAxis,
|
|
1556
|
-
anchors: copiedAnchors
|
|
1468
|
+
anchors: copiedAnchorGroups
|
|
1557
1469
|
}
|
|
1558
1470
|
})
|
|
1559
1471
|
}}
|
|
1560
1472
|
>
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1473
|
+
Remove
|
|
1474
|
+
</button>
|
|
1475
|
+
</AccordionItemButton>
|
|
1476
|
+
</>
|
|
1477
|
+
</AccordionItemHeading>
|
|
1478
|
+
<AccordionItemPanel>
|
|
1479
|
+
<label>
|
|
1480
|
+
<span>Anchor Value</span>
|
|
1481
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1482
|
+
<Tooltip.Target>
|
|
1483
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1484
|
+
</Tooltip.Target>
|
|
1485
|
+
<Tooltip.Content>
|
|
1486
|
+
<p>Enter the value as its shown in the data column</p>
|
|
1487
|
+
</Tooltip.Content>
|
|
1488
|
+
</Tooltip>
|
|
1489
|
+
<input
|
|
1490
|
+
type='text'
|
|
1491
|
+
value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
|
|
1492
|
+
onChange={e => {
|
|
1493
|
+
e.preventDefault()
|
|
1494
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
1495
|
+
copiedAnchors[index].value = e.target.value
|
|
1496
|
+
updateConfig({
|
|
1497
|
+
...config,
|
|
1498
|
+
xAxis: {
|
|
1499
|
+
...config.xAxis,
|
|
1500
|
+
anchors: copiedAnchors
|
|
1501
|
+
}
|
|
1502
|
+
})
|
|
1503
|
+
}}
|
|
1504
|
+
/>
|
|
1505
|
+
</label>
|
|
1506
|
+
|
|
1507
|
+
<label>
|
|
1508
|
+
<span>Anchor Color</span>
|
|
1509
|
+
<input
|
|
1510
|
+
type='text'
|
|
1511
|
+
value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
|
|
1512
|
+
onChange={e => {
|
|
1513
|
+
e.preventDefault()
|
|
1514
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
1515
|
+
copiedAnchors[index].color = e.target.value
|
|
1516
|
+
updateConfig({
|
|
1517
|
+
...config,
|
|
1518
|
+
xAxis: {
|
|
1519
|
+
...config.xAxis,
|
|
1520
|
+
anchors: copiedAnchors
|
|
1521
|
+
}
|
|
1522
|
+
})
|
|
1523
|
+
}}
|
|
1524
|
+
/>
|
|
1525
|
+
</label>
|
|
1526
|
+
|
|
1527
|
+
<label>
|
|
1528
|
+
Anchor Line Style
|
|
1529
|
+
<select
|
|
1530
|
+
value={config.xAxis.anchors[index].lineStyle || ''}
|
|
1531
|
+
onChange={e => {
|
|
1532
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
1533
|
+
copiedAnchors[index].lineStyle = e.target.value
|
|
1534
|
+
updateConfig({
|
|
1535
|
+
...config,
|
|
1536
|
+
xAxis: {
|
|
1537
|
+
...config.xAxis,
|
|
1538
|
+
anchors: copiedAnchors
|
|
1539
|
+
}
|
|
1540
|
+
})
|
|
1541
|
+
}}
|
|
1542
|
+
>
|
|
1543
|
+
<option>Select</option>
|
|
1544
|
+
{lineOptions.map(line => (
|
|
1545
|
+
<option key={line.key}>{line.value}</option>
|
|
1546
|
+
))}
|
|
1547
|
+
</select>
|
|
1548
|
+
</label>
|
|
1549
|
+
</AccordionItemPanel>
|
|
1550
|
+
</AccordionItem>
|
|
1551
|
+
))}
|
|
1552
|
+
</Accordion>
|
|
1553
|
+
|
|
1554
|
+
<button
|
|
1555
|
+
className='btn full-width'
|
|
1556
|
+
onClick={e => {
|
|
1557
|
+
e.preventDefault()
|
|
1558
|
+
const anchors = [...config.xAxis.anchors]
|
|
1559
|
+
anchors.push({} as Anchor)
|
|
1560
|
+
updateConfig({
|
|
1561
|
+
...config,
|
|
1562
|
+
xAxis: {
|
|
1563
|
+
...config.xAxis,
|
|
1564
|
+
anchors
|
|
1565
|
+
}
|
|
1566
|
+
})
|
|
1567
|
+
}}
|
|
1568
|
+
>
|
|
1569
|
+
Add Anchor
|
|
1570
|
+
</button>
|
|
1647
1571
|
</div>
|
|
1572
|
+
)}
|
|
1573
|
+
{/* end: anchors */}
|
|
1574
|
+
</AccordionItemPanel>
|
|
1575
|
+
</AccordionItem>
|
|
1576
|
+
)}
|
|
1577
|
+
{/* Right Value Axis Settings */}
|
|
1578
|
+
{hasRightAxis && (
|
|
1579
|
+
<AccordionItem>
|
|
1580
|
+
<AccordionItemHeading>
|
|
1581
|
+
<AccordionItemButton>Right Value Axis</AccordionItemButton>
|
|
1582
|
+
</AccordionItemHeading>
|
|
1583
|
+
<AccordionItemPanel>
|
|
1584
|
+
<TextField value={config.yAxis.rightLabel} section='yAxis' fieldName='rightLabel' label='Label' updateField={updateField} />
|
|
1585
|
+
<TextField value={config.yAxis.rightNumTicks} placeholder='Auto' type='number' section='yAxis' fieldName='rightNumTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
|
|
1586
|
+
<TextField value={config.yAxis.rightAxisSize} type='number' section='yAxis' fieldName='rightAxisSize' label='Size (Width)' className='number-narrow' updateField={updateField} />
|
|
1587
|
+
<TextField value={config.yAxis.rightLabelOffsetSize} type='number' section='yAxis' fieldName='rightLabelOffsetSize' label='Label Offset' className='number-narrow' updateField={updateField} />
|
|
1588
|
+
|
|
1589
|
+
<span className='divider-heading'>Number Formatting</span>
|
|
1590
|
+
<CheckBox value={config.dataFormat.rightCommas} section='dataFormat' fieldName='rightCommas' label='Add commas' updateField={updateField} />
|
|
1591
|
+
<TextField value={config.dataFormat.rightRoundTo} type='number' section='dataFormat' fieldName='rightRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
|
|
1592
|
+
<div className='two-col-inputs'>
|
|
1593
|
+
<TextField
|
|
1594
|
+
value={config.dataFormat.rightPrefix}
|
|
1595
|
+
section='dataFormat'
|
|
1596
|
+
fieldName='rightPrefix'
|
|
1597
|
+
label='Prefix'
|
|
1598
|
+
updateField={updateField}
|
|
1599
|
+
tooltip={
|
|
1600
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1601
|
+
<Tooltip.Target>
|
|
1602
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1603
|
+
</Tooltip.Target>
|
|
1604
|
+
<Tooltip.Content>
|
|
1605
|
+
{config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
|
|
1606
|
+
{config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
|
|
1607
|
+
</Tooltip.Content>
|
|
1608
|
+
</Tooltip>
|
|
1609
|
+
}
|
|
1610
|
+
/>
|
|
1611
|
+
<TextField
|
|
1612
|
+
value={config.dataFormat.rightSuffix}
|
|
1613
|
+
section='dataFormat'
|
|
1614
|
+
fieldName='rightSuffix'
|
|
1615
|
+
label='Suffix'
|
|
1616
|
+
updateField={updateField}
|
|
1617
|
+
tooltip={
|
|
1618
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1619
|
+
<Tooltip.Target>
|
|
1620
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1621
|
+
</Tooltip.Target>
|
|
1622
|
+
<Tooltip.Content>
|
|
1623
|
+
{config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
|
|
1624
|
+
{config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
|
|
1625
|
+
</Tooltip.Content>
|
|
1626
|
+
</Tooltip>
|
|
1627
|
+
}
|
|
1628
|
+
/>
|
|
1629
|
+
</div>
|
|
1630
|
+
|
|
1631
|
+
<CheckBox value={config.yAxis.rightHideAxis} section='yAxis' fieldName='rightHideAxis' label='Hide Axis' updateField={updateField} />
|
|
1632
|
+
<CheckBox value={config.yAxis.rightHideLabel} section='yAxis' fieldName='rightHideLabel' label='Hide Label' updateField={updateField} />
|
|
1633
|
+
<CheckBox value={config.yAxis.rightHideTicks} section='yAxis' fieldName='rightHideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1634
|
+
|
|
1635
|
+
<TextField value={config.yAxis.max} section='yAxis' fieldName='rightMax' type='number' label='right axis max value' placeholder='Auto' updateField={updateField} />
|
|
1636
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.rightMaxMessage}</span>
|
|
1637
|
+
<TextField value={config.yAxis.min} section='yAxis' fieldName='rightMin' type='number' label='right axis min value' placeholder='Auto' updateField={updateField} />
|
|
1638
|
+
<span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
|
|
1639
|
+
</AccordionItemPanel>
|
|
1640
|
+
</AccordionItem>
|
|
1641
|
+
)}
|
|
1642
|
+
{visSupportsDateCategoryAxis() && (
|
|
1643
|
+
<AccordionItem>
|
|
1644
|
+
<AccordionItemHeading>
|
|
1645
|
+
<AccordionItemButton>
|
|
1646
|
+
{config.visualizationType === 'Pie' ? 'Segments' : 'Date/Category Axis'}
|
|
1647
|
+
{!config.xAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
|
|
1648
|
+
</AccordionItemButton>
|
|
1649
|
+
</AccordionItemHeading>
|
|
1650
|
+
<AccordionItemPanel>
|
|
1651
|
+
{config.visualizationType !== 'Pie' && (
|
|
1652
|
+
<>
|
|
1653
|
+
{config.visualizationType !== 'Forest Plot' && (
|
|
1654
|
+
<>
|
|
1655
|
+
<label>
|
|
1656
|
+
<span className='edit-label'>
|
|
1657
|
+
Data Scaling Type
|
|
1658
|
+
<Tooltip style={{ textTransform: 'none', display: 'inline-block' }}>
|
|
1659
|
+
<Tooltip.Target>
|
|
1660
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1661
|
+
</Tooltip.Target>
|
|
1662
|
+
<Tooltip.Content>Linear scales are employed for quantitative data, while time scales are used for time-series data.</Tooltip.Content>
|
|
1663
|
+
</Tooltip>
|
|
1664
|
+
</span>
|
|
1665
|
+
<select
|
|
1666
|
+
value={config.xAxis.type}
|
|
1667
|
+
onChange={e =>
|
|
1668
|
+
updateConfig({
|
|
1669
|
+
...config,
|
|
1670
|
+
xAxis: {
|
|
1671
|
+
...config.xAxis,
|
|
1672
|
+
type: e.target.value
|
|
1673
|
+
}
|
|
1674
|
+
})
|
|
1675
|
+
}
|
|
1676
|
+
>
|
|
1677
|
+
<option value='categorical'>Categorical (Linear Scale)</option>
|
|
1678
|
+
<option value='date'>Date (Linear Scale)</option>
|
|
1679
|
+
<option value='date-time'>Date (Date Time Scale)</option>
|
|
1680
|
+
{config.visualizationType === 'Scatter Plot' && <option value={'continuous'}>Continuous</option>}
|
|
1681
|
+
</select>
|
|
1682
|
+
</label>
|
|
1648
1683
|
|
|
1649
|
-
|
|
1650
|
-
<CheckBox value={config.yAxis.rightHideLabel} section='yAxis' fieldName='rightHideLabel' label='Hide Label' updateField={updateField} />
|
|
1651
|
-
<CheckBox value={config.yAxis.rightHideTicks} section='yAxis' fieldName='rightHideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1684
|
+
<CheckBox value={config.xAxis.manual} section='xAxis' fieldName='manual' label='Manual Ticks' updateField={updateField} />
|
|
1652
1685
|
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
{!config.xAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
|
|
1666
|
-
</AccordionItemButton>
|
|
1667
|
-
</AccordionItemHeading>
|
|
1668
|
-
<AccordionItemPanel>
|
|
1669
|
-
{config.visualizationType !== 'Pie' && (
|
|
1670
|
-
<>
|
|
1671
|
-
{config.visualizationType !== 'Forest Plot' && (
|
|
1672
|
-
<>
|
|
1673
|
-
<label>
|
|
1674
|
-
<span className='edit-label'>
|
|
1675
|
-
Data Scaling Type
|
|
1676
|
-
<Tooltip style={{ textTransform: 'none', display: 'inline-block' }}>
|
|
1686
|
+
{visSupportsDateCategoryAxisPadding() && (
|
|
1687
|
+
<TextField
|
|
1688
|
+
value={config.xAxis.padding}
|
|
1689
|
+
type='number'
|
|
1690
|
+
min={0}
|
|
1691
|
+
section='xAxis'
|
|
1692
|
+
fieldName='padding'
|
|
1693
|
+
label={'Padding (Percent)'}
|
|
1694
|
+
className='number-narrow'
|
|
1695
|
+
updateField={updateField}
|
|
1696
|
+
tooltip={
|
|
1697
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1677
1698
|
<Tooltip.Target>
|
|
1678
1699
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1679
1700
|
</Tooltip.Target>
|
|
1680
|
-
<Tooltip.Content>
|
|
1701
|
+
<Tooltip.Content>
|
|
1702
|
+
<p>For use with date scale. Extends the earliest and latest dates represented on the scale by the percentage specified.</p>
|
|
1703
|
+
</Tooltip.Content>
|
|
1681
1704
|
</Tooltip>
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
...config,
|
|
1688
|
-
xAxis: {
|
|
1689
|
-
...config.xAxis,
|
|
1690
|
-
type: e.target.value
|
|
1691
|
-
}
|
|
1692
|
-
})
|
|
1693
|
-
}
|
|
1694
|
-
>
|
|
1695
|
-
<option value='categorical'>Categorical (Linear Scale)</option>
|
|
1696
|
-
<option value='date'>Date (Linear Scale)</option>
|
|
1697
|
-
<option value='date-time'>Date (Date Time Scale)</option>
|
|
1698
|
-
{config.visualizationType === 'Scatter Plot' && <option value={'continuous'}>Continuous</option>}
|
|
1699
|
-
</select>
|
|
1700
|
-
</label>
|
|
1701
|
-
|
|
1702
|
-
{visSupportsDateCategoryAxisPadding() && (
|
|
1703
|
-
<TextField
|
|
1704
|
-
value={config.xAxis.padding}
|
|
1705
|
-
type='number'
|
|
1706
|
-
min={0}
|
|
1707
|
-
section='xAxis'
|
|
1708
|
-
fieldName='padding'
|
|
1709
|
-
label={'Padding (Percent)'}
|
|
1710
|
-
className='number-narrow'
|
|
1711
|
-
updateField={updateField}
|
|
1712
|
-
tooltip={
|
|
1713
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1714
|
-
<Tooltip.Target>
|
|
1715
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1716
|
-
</Tooltip.Target>
|
|
1717
|
-
<Tooltip.Content>
|
|
1718
|
-
<p>For use with date scale. Extends the earliest and latest dates represented on the scale by the percentage specified.</p>
|
|
1719
|
-
</Tooltip.Content>
|
|
1720
|
-
</Tooltip>
|
|
1721
|
-
}
|
|
1722
|
-
/>
|
|
1723
|
-
)}
|
|
1724
|
-
</>
|
|
1725
|
-
)}
|
|
1726
|
-
<Select
|
|
1727
|
-
value={config.xAxis.dataKey || setCategoryAxis() || ''}
|
|
1728
|
-
section='xAxis'
|
|
1729
|
-
fieldName='dataKey'
|
|
1730
|
-
label='Data Key'
|
|
1731
|
-
initial='Select'
|
|
1732
|
-
required={true}
|
|
1733
|
-
updateField={updateField}
|
|
1734
|
-
options={getColumns(false)}
|
|
1735
|
-
tooltip={
|
|
1736
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1737
|
-
<Tooltip.Target>
|
|
1738
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1739
|
-
</Tooltip.Target>
|
|
1740
|
-
<Tooltip.Content>
|
|
1741
|
-
<p>Select the column or row containing the categories or dates for this axis. </p>
|
|
1742
|
-
</Tooltip.Content>
|
|
1743
|
-
</Tooltip>
|
|
1744
|
-
}
|
|
1745
|
-
/>
|
|
1746
|
-
</>
|
|
1747
|
-
)}
|
|
1748
|
-
|
|
1749
|
-
{config.visualizationType === 'Pie' && (
|
|
1705
|
+
}
|
|
1706
|
+
/>
|
|
1707
|
+
)}
|
|
1708
|
+
</>
|
|
1709
|
+
)}
|
|
1750
1710
|
<Select
|
|
1751
|
-
value={config.xAxis.dataKey || ''}
|
|
1711
|
+
value={config.xAxis.dataKey || setCategoryAxis() || ''}
|
|
1752
1712
|
section='xAxis'
|
|
1753
1713
|
fieldName='dataKey'
|
|
1754
|
-
label='
|
|
1714
|
+
label='Data Key'
|
|
1755
1715
|
initial='Select'
|
|
1756
1716
|
required={true}
|
|
1757
1717
|
updateField={updateField}
|
|
@@ -1762,1164 +1722,860 @@ const EditorPanel = () => {
|
|
|
1762
1722
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1763
1723
|
</Tooltip.Target>
|
|
1764
1724
|
<Tooltip.Content>
|
|
1765
|
-
<p>Select the
|
|
1725
|
+
<p>Select the column or row containing the categories or dates for this axis. </p>
|
|
1766
1726
|
</Tooltip.Content>
|
|
1767
1727
|
</Tooltip>
|
|
1768
1728
|
}
|
|
1769
1729
|
/>
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1730
|
+
</>
|
|
1731
|
+
)}
|
|
1732
|
+
|
|
1733
|
+
{config.visualizationType === 'Pie' && (
|
|
1734
|
+
<Select
|
|
1735
|
+
value={config.xAxis.dataKey || ''}
|
|
1736
|
+
section='xAxis'
|
|
1737
|
+
fieldName='dataKey'
|
|
1738
|
+
label='Segment Labels'
|
|
1739
|
+
initial='Select'
|
|
1740
|
+
required={true}
|
|
1741
|
+
updateField={updateField}
|
|
1742
|
+
options={getColumns(false)}
|
|
1743
|
+
tooltip={
|
|
1744
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1745
|
+
<Tooltip.Target>
|
|
1746
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1747
|
+
</Tooltip.Target>
|
|
1748
|
+
<Tooltip.Content>
|
|
1749
|
+
<p>Select the source row or column that contains the segment labels. Depending on the data structure, it may be listed as "Key."</p>
|
|
1750
|
+
</Tooltip.Content>
|
|
1751
|
+
</Tooltip>
|
|
1752
|
+
}
|
|
1753
|
+
/>
|
|
1754
|
+
)}
|
|
1775
1755
|
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
value={config.dataFormat.bottomPrefix}
|
|
1780
|
-
section='dataFormat'
|
|
1781
|
-
fieldName='bottomPrefix'
|
|
1782
|
-
label='Prefix'
|
|
1783
|
-
updateField={updateField}
|
|
1784
|
-
tooltip={
|
|
1785
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1786
|
-
<Tooltip.Target>
|
|
1787
|
-
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1788
|
-
</Tooltip.Target>
|
|
1789
|
-
<Tooltip.Content>
|
|
1790
|
-
<p>Enter a data suffix (such as "%"), if applicable.</p>
|
|
1791
|
-
</Tooltip.Content>
|
|
1792
|
-
</Tooltip>
|
|
1793
|
-
}
|
|
1794
|
-
/>
|
|
1756
|
+
{config.visualizationType !== 'Pie' && (
|
|
1757
|
+
<>
|
|
1758
|
+
<TextField value={config.xAxis.label} section='xAxis' fieldName='label' label='Label' updateField={updateField} />
|
|
1795
1759
|
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
<
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1760
|
+
{config.xAxis.type === 'continuous' && (
|
|
1761
|
+
<>
|
|
1762
|
+
<TextField
|
|
1763
|
+
value={config.dataFormat.bottomPrefix}
|
|
1764
|
+
section='dataFormat'
|
|
1765
|
+
fieldName='bottomPrefix'
|
|
1766
|
+
label='Prefix'
|
|
1767
|
+
updateField={updateField}
|
|
1768
|
+
tooltip={
|
|
1769
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1770
|
+
<Tooltip.Target>
|
|
1771
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1772
|
+
</Tooltip.Target>
|
|
1773
|
+
<Tooltip.Content>
|
|
1774
|
+
<p>Enter a data prefix (such as "$"), if applicable.</p>
|
|
1775
|
+
</Tooltip.Content>
|
|
1776
|
+
</Tooltip>
|
|
1777
|
+
}
|
|
1778
|
+
/>
|
|
1813
1779
|
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
</>
|
|
1832
|
-
)}
|
|
1833
|
-
|
|
1834
|
-
{isDateScale(config.xAxis) && (
|
|
1835
|
-
<>
|
|
1836
|
-
<p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
|
|
1837
|
-
Format how charts should parse and display your dates using{' '}
|
|
1838
|
-
<a href='https://github.com/d3/d3-time-format#locale_format' target='_blank' rel='noreferrer'>
|
|
1839
|
-
these guidelines
|
|
1840
|
-
</a>
|
|
1841
|
-
.
|
|
1842
|
-
</p>
|
|
1843
|
-
<TextField
|
|
1844
|
-
tooltip={
|
|
1845
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1846
|
-
<Tooltip.Target>
|
|
1847
|
-
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1848
|
-
</Tooltip.Target>
|
|
1849
|
-
<Tooltip.Content>
|
|
1850
|
-
<p>This field specifies the pattern used to read and interpret dates in your dataset, ensuring the dates are correctly understood and processed. </p>
|
|
1851
|
-
</Tooltip.Content>
|
|
1852
|
-
</Tooltip>
|
|
1853
|
-
}
|
|
1854
|
-
value={config.xAxis.dateParseFormat}
|
|
1855
|
-
section='xAxis'
|
|
1856
|
-
fieldName='dateParseFormat'
|
|
1857
|
-
placeholder='Ex. %Y-%m-%d'
|
|
1858
|
-
label='Date Parse Format'
|
|
1859
|
-
updateField={updateField}
|
|
1860
|
-
/>
|
|
1861
|
-
<TextField
|
|
1862
|
-
tooltip={
|
|
1863
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1864
|
-
<Tooltip.Target>
|
|
1865
|
-
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1866
|
-
</Tooltip.Target>
|
|
1867
|
-
<Tooltip.Content>
|
|
1868
|
-
<p> Adjusts the date display format on the axis for clear, visual date representation.</p>
|
|
1869
|
-
</Tooltip.Content>
|
|
1870
|
-
</Tooltip>
|
|
1871
|
-
}
|
|
1872
|
-
value={config.xAxis.dateDisplayFormat}
|
|
1873
|
-
section='xAxis'
|
|
1874
|
-
fieldName='dateDisplayFormat'
|
|
1875
|
-
placeholder='Ex. %Y-%m-%d'
|
|
1876
|
-
label='AXIS DATE DISPLAY FORMAT'
|
|
1877
|
-
updateField={updateField}
|
|
1878
|
-
/>
|
|
1879
|
-
<TextField
|
|
1880
|
-
tooltip={
|
|
1881
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1882
|
-
<Tooltip.Target>
|
|
1883
|
-
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1884
|
-
</Tooltip.Target>
|
|
1885
|
-
<Tooltip.Content>
|
|
1886
|
-
<p>Specify a custom format for displaying dates in data table. If left empty, dates will adopt the Axis Date Display format. </p>
|
|
1887
|
-
</Tooltip.Content>
|
|
1888
|
-
</Tooltip>
|
|
1889
|
-
}
|
|
1890
|
-
value={config.table.dateDisplayFormat}
|
|
1891
|
-
section='table'
|
|
1892
|
-
fieldName='dateDisplayFormat'
|
|
1893
|
-
placeholder='Ex. %Y-%m-%d'
|
|
1894
|
-
label='DATA TABLE DATE DISPLAY FORMAT'
|
|
1895
|
-
updateField={updateField}
|
|
1896
|
-
/>
|
|
1897
|
-
<TextField
|
|
1898
|
-
tooltip={
|
|
1899
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1900
|
-
<Tooltip.Target>
|
|
1901
|
-
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1902
|
-
</Tooltip.Target>
|
|
1903
|
-
<Tooltip.Content>
|
|
1904
|
-
<p>Specify a custom format for displaying dates on hovers. If left empty, dates will adopt the Axis Date Display format. </p>
|
|
1905
|
-
</Tooltip.Content>
|
|
1906
|
-
</Tooltip>
|
|
1907
|
-
}
|
|
1908
|
-
value={config.tooltips.dateDisplayFormat}
|
|
1909
|
-
section='tooltips'
|
|
1910
|
-
fieldName='dateDisplayFormat'
|
|
1911
|
-
placeholder='Ex. %Y-%m-%d'
|
|
1912
|
-
label='HOVER DATE DISPLAY FORMAT'
|
|
1913
|
-
updateField={updateField}
|
|
1914
|
-
/>
|
|
1915
|
-
</>
|
|
1916
|
-
)}
|
|
1917
|
-
|
|
1918
|
-
<CheckBox
|
|
1919
|
-
value={config.exclusions.active}
|
|
1920
|
-
section='exclusions'
|
|
1921
|
-
fieldName='active'
|
|
1922
|
-
label={config.xAxis.type === 'date' ? 'Limit by start and/or end dates' : 'Exclude one or more values'}
|
|
1923
|
-
tooltip={
|
|
1924
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1925
|
-
<Tooltip.Target>
|
|
1926
|
-
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1927
|
-
</Tooltip.Target>
|
|
1928
|
-
<Tooltip.Content>
|
|
1929
|
-
<p>When this option is checked, you can select source-file values for exclusion from the date/category axis. </p>
|
|
1930
|
-
</Tooltip.Content>
|
|
1931
|
-
</Tooltip>
|
|
1932
|
-
}
|
|
1933
|
-
updateField={updateField}
|
|
1934
|
-
/>
|
|
1935
|
-
{/* {visHasBrushChart && <CheckBox value={config.brush.active} section='brush' fieldName='active' label='Brush Slider ' updateField={updateField} />} */}
|
|
1780
|
+
<TextField
|
|
1781
|
+
value={config.dataFormat.bottomSuffix}
|
|
1782
|
+
section='dataFormat'
|
|
1783
|
+
fieldName='bottomSuffix'
|
|
1784
|
+
label='Suffix'
|
|
1785
|
+
updateField={updateField}
|
|
1786
|
+
tooltip={
|
|
1787
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1788
|
+
<Tooltip.Target>
|
|
1789
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1790
|
+
</Tooltip.Target>
|
|
1791
|
+
<Tooltip.Content>
|
|
1792
|
+
<p>Enter a data suffix (such as "%"), if applicable.</p>
|
|
1793
|
+
</Tooltip.Content>
|
|
1794
|
+
</Tooltip>
|
|
1795
|
+
}
|
|
1796
|
+
/>
|
|
1936
1797
|
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
addNewExclusion(e.target.value)
|
|
1957
|
-
}
|
|
1958
|
-
e.target.value = ''
|
|
1959
|
-
}}
|
|
1960
|
-
options={getDataValues(config.xAxis.dataKey, true)}
|
|
1961
|
-
/>
|
|
1962
|
-
</>
|
|
1963
|
-
)}
|
|
1798
|
+
<CheckBox
|
|
1799
|
+
value={config.dataFormat.bottomAbbreviated}
|
|
1800
|
+
section='dataFormat'
|
|
1801
|
+
fieldName='bottomAbbreviated'
|
|
1802
|
+
label='Abbreviate Axis Values'
|
|
1803
|
+
updateField={updateField}
|
|
1804
|
+
tooltip={
|
|
1805
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1806
|
+
<Tooltip.Target>
|
|
1807
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1808
|
+
</Tooltip.Target>
|
|
1809
|
+
<Tooltip.Content>
|
|
1810
|
+
<p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
|
|
1811
|
+
</Tooltip.Content>
|
|
1812
|
+
</Tooltip>
|
|
1813
|
+
}
|
|
1814
|
+
/>
|
|
1815
|
+
</>
|
|
1816
|
+
)}
|
|
1964
1817
|
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
{visSupportsDateCategoryNumTicks() && <TextField value={config.xAxis.numTicks} placeholder='Auto' type='number' min={1} section='xAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />}
|
|
1975
|
-
{visSupportsDateCategoryHeight() && <TextField value={config.xAxis.size} type='number' min={0} section='xAxis' fieldName='size' label={config.orientation === 'horizontal' ? 'Size (Width)' : 'Size (Height)'} className='number-narrow' updateField={updateField} />}
|
|
1976
|
-
|
|
1977
|
-
{visSupportsDateCategoryAxisPadding() && <TextField value={config.xAxis.padding} type='number' min={0} section='xAxis' fieldName='padding' label={'Padding (Percent)'} className='number-narrow' updateField={updateField} />}
|
|
1978
|
-
|
|
1979
|
-
{/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
|
|
1980
|
-
{/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
|
|
1981
|
-
{(config.xAxis.type === 'continuous' || config.forestPlot.type === 'Logarithmic') && (
|
|
1982
|
-
<>
|
|
1983
|
-
<CheckBox value={config.dataFormat.bottomCommas} section='dataFormat' fieldName='bottomCommas' label='Add commas' updateField={updateField} />
|
|
1984
|
-
<TextField value={config.dataFormat.bottomRoundTo} type='number' section='dataFormat' fieldName='bottomRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
|
|
1985
|
-
</>
|
|
1986
|
-
)}
|
|
1987
|
-
{visSupportsResponsiveTicks() && config.orientation === 'vertical' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
|
|
1988
|
-
{(config.orientation === 'horizontal' || !config.isResponsiveTicks) && visSupportsDateCategoryTickRotation() && (
|
|
1989
|
-
<TextField value={config.xAxis.tickRotation} type='number' min={0} section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />
|
|
1990
|
-
)}
|
|
1991
|
-
{config.orientation === 'vertical' && config.isResponsiveTicks && config.visualizationType !== 'Paired Bar' && (
|
|
1818
|
+
{isDateScale(config.xAxis) && (
|
|
1819
|
+
<>
|
|
1820
|
+
<p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
|
|
1821
|
+
Format how charts should parse and display your dates using{' '}
|
|
1822
|
+
<a href='https://github.com/d3/d3-time-format#locale_format' target='_blank' rel='noreferrer'>
|
|
1823
|
+
these guidelines
|
|
1824
|
+
</a>
|
|
1825
|
+
.
|
|
1826
|
+
</p>
|
|
1992
1827
|
<TextField
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1828
|
+
tooltip={
|
|
1829
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1830
|
+
<Tooltip.Target>
|
|
1831
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1832
|
+
</Tooltip.Target>
|
|
1833
|
+
<Tooltip.Content>
|
|
1834
|
+
<p>This field specifies the pattern used to read and interpret dates in your dataset, ensuring the dates are correctly understood and processed. </p>
|
|
1835
|
+
</Tooltip.Content>
|
|
1836
|
+
</Tooltip>
|
|
1837
|
+
}
|
|
1838
|
+
value={config.xAxis.dateParseFormat}
|
|
1996
1839
|
section='xAxis'
|
|
1997
|
-
fieldName='
|
|
1998
|
-
|
|
1999
|
-
|
|
1840
|
+
fieldName='dateParseFormat'
|
|
1841
|
+
placeholder='Ex. %Y-%m-%d'
|
|
1842
|
+
label='Date Parse Format'
|
|
2000
1843
|
updateField={updateField}
|
|
1844
|
+
/>
|
|
1845
|
+
<TextField
|
|
2001
1846
|
tooltip={
|
|
2002
1847
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
2003
1848
|
<Tooltip.Target>
|
|
2004
1849
|
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2005
1850
|
</Tooltip.Target>
|
|
2006
1851
|
<Tooltip.Content>
|
|
2007
|
-
<p>
|
|
1852
|
+
<p> Adjusts the date display format on the axis for clear, visual date representation.</p>
|
|
2008
1853
|
</Tooltip.Content>
|
|
2009
1854
|
</Tooltip>
|
|
2010
1855
|
}
|
|
1856
|
+
value={config.xAxis.dateDisplayFormat}
|
|
1857
|
+
section='xAxis'
|
|
1858
|
+
fieldName='dateDisplayFormat'
|
|
1859
|
+
placeholder='Ex. %Y-%m-%d'
|
|
1860
|
+
label='AXIS DATE DISPLAY FORMAT'
|
|
1861
|
+
updateField={updateField}
|
|
2011
1862
|
/>
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
{
|
|
2032
|
-
|
|
2033
|
-
<
|
|
2034
|
-
<
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
<label>
|
|
2051
|
-
<span className='edit-label column-heading'>Border Width</span>
|
|
2052
|
-
<input max='5' min='0' type='number' value={config.highlightedBarValues[i].borderWidth ? config.highlightedBarValues[i].borderWidth : ''} onChange={e => handleUpdateHighlightedBorderWidth(e, i)} />
|
|
2053
|
-
</label>
|
|
2054
|
-
<label>
|
|
2055
|
-
<span className='edit-label column-heading'>Legend Label</span>
|
|
2056
|
-
<input type='text' value={config.highlightedBarValues[i].legendLabel ? config.highlightedBarValues[i].legendLabel : ''} onChange={e => handleHighlightedBarLegendLabel(e, i)} />
|
|
2057
|
-
</label>
|
|
2058
|
-
</div>
|
|
2059
|
-
</fieldset>
|
|
2060
|
-
))}
|
|
2061
|
-
<button className='btn full-width' onClick={e => handleAddNewHighlightedBar(e)}>
|
|
2062
|
-
Add Highlighted Bar
|
|
2063
|
-
</button>
|
|
2064
|
-
</>
|
|
2065
|
-
)}
|
|
2066
|
-
</>
|
|
2067
|
-
)}
|
|
2068
|
-
|
|
2069
|
-
{config.visualizationType === 'Pie' && (
|
|
2070
|
-
<>
|
|
2071
|
-
<CheckBox
|
|
2072
|
-
value={config.exclusions.active}
|
|
2073
|
-
section='exclusions'
|
|
2074
|
-
fieldName='active'
|
|
2075
|
-
label={'Exclude one or more values'}
|
|
2076
|
-
updateField={updateField}
|
|
2077
|
-
tooltip={
|
|
2078
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2079
|
-
<Tooltip.Target>
|
|
2080
|
-
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2081
|
-
</Tooltip.Target>
|
|
2082
|
-
<Tooltip.Content>
|
|
2083
|
-
<p>When this option is checked, you can select values for exclusion from the pie segments.</p>
|
|
2084
|
-
</Tooltip.Content>
|
|
2085
|
-
</Tooltip>
|
|
2086
|
-
}
|
|
2087
|
-
/>
|
|
2088
|
-
{config.exclusions.active && (
|
|
2089
|
-
<>
|
|
2090
|
-
{config.exclusions.keys.length > 0 && (
|
|
2091
|
-
<>
|
|
2092
|
-
<fieldset>
|
|
2093
|
-
<legend className='edit-label'>Excluded Keys</legend>
|
|
2094
|
-
</fieldset>
|
|
2095
|
-
<ExclusionsList />
|
|
2096
|
-
</>
|
|
2097
|
-
)}
|
|
2098
|
-
|
|
2099
|
-
<Select
|
|
2100
|
-
fieldName='visualizationType'
|
|
2101
|
-
label='Add Exclusion'
|
|
2102
|
-
initial='Select'
|
|
2103
|
-
onChange={e => {
|
|
2104
|
-
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
2105
|
-
addNewExclusion(e.target.value)
|
|
2106
|
-
}
|
|
2107
|
-
e.target.value = ''
|
|
2108
|
-
}}
|
|
2109
|
-
options={getDataValues(config.xAxis.dataKey, true)}
|
|
2110
|
-
/>
|
|
2111
|
-
</>
|
|
2112
|
-
)}
|
|
2113
|
-
</>
|
|
2114
|
-
)}
|
|
2115
|
-
|
|
2116
|
-
{/* anchors */}
|
|
2117
|
-
{visHasAnchors() && config.orientation !== 'horizontal' && (
|
|
2118
|
-
<div className='edit-block'>
|
|
2119
|
-
<span className='edit-label column-heading'>Anchors</span>
|
|
2120
|
-
<Accordion allowZeroExpanded>
|
|
2121
|
-
{config.xAxis?.anchors?.map((anchor, index) => (
|
|
2122
|
-
<AccordionItem className='series-item series-item--chart' key={`xaxis-anchors-2-${index}`}>
|
|
2123
|
-
<AccordionItemHeading className='series-item__title'>
|
|
2124
|
-
<>
|
|
2125
|
-
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
2126
|
-
Anchor {index + 1}
|
|
2127
|
-
<button
|
|
2128
|
-
className='series-list__remove'
|
|
2129
|
-
onClick={e => {
|
|
2130
|
-
e.preventDefault()
|
|
2131
|
-
const copiedAnchorGroups = [...config.xAxis.anchors]
|
|
2132
|
-
copiedAnchorGroups.splice(index, 1)
|
|
2133
|
-
updateConfig({
|
|
2134
|
-
...config,
|
|
2135
|
-
xAxis: {
|
|
2136
|
-
...config.xAxis,
|
|
2137
|
-
anchors: copiedAnchorGroups
|
|
2138
|
-
}
|
|
2139
|
-
})
|
|
2140
|
-
}}
|
|
2141
|
-
>
|
|
2142
|
-
Remove
|
|
2143
|
-
</button>
|
|
2144
|
-
</AccordionItemButton>
|
|
2145
|
-
</>
|
|
2146
|
-
</AccordionItemHeading>
|
|
2147
|
-
<AccordionItemPanel>
|
|
2148
|
-
<label>
|
|
2149
|
-
<span>Anchor Value</span>
|
|
2150
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2151
|
-
<Tooltip.Target>
|
|
2152
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2153
|
-
</Tooltip.Target>
|
|
2154
|
-
<Tooltip.Content>
|
|
2155
|
-
<p>Enter the value as its shown in the data column</p>
|
|
2156
|
-
</Tooltip.Content>
|
|
2157
|
-
</Tooltip>
|
|
2158
|
-
<input
|
|
2159
|
-
type='text'
|
|
2160
|
-
value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
|
|
2161
|
-
onChange={e => {
|
|
2162
|
-
e.preventDefault()
|
|
2163
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
2164
|
-
copiedAnchors[index].value = e.target.value
|
|
2165
|
-
updateConfig({
|
|
2166
|
-
...config,
|
|
2167
|
-
xAxis: {
|
|
2168
|
-
...config.xAxis,
|
|
2169
|
-
anchors: copiedAnchors
|
|
2170
|
-
}
|
|
2171
|
-
})
|
|
2172
|
-
}}
|
|
2173
|
-
/>
|
|
2174
|
-
</label>
|
|
2175
|
-
|
|
2176
|
-
<label>
|
|
2177
|
-
<span>Anchor Color</span>
|
|
2178
|
-
<input
|
|
2179
|
-
type='text'
|
|
2180
|
-
value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
|
|
2181
|
-
onChange={e => {
|
|
2182
|
-
e.preventDefault()
|
|
2183
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
2184
|
-
copiedAnchors[index].color = e.target.value
|
|
2185
|
-
updateConfig({
|
|
2186
|
-
...config,
|
|
2187
|
-
xAxis: {
|
|
2188
|
-
...config.xAxis,
|
|
2189
|
-
anchors: copiedAnchors
|
|
2190
|
-
}
|
|
2191
|
-
})
|
|
2192
|
-
}}
|
|
2193
|
-
/>
|
|
2194
|
-
</label>
|
|
2195
|
-
|
|
2196
|
-
<label>
|
|
2197
|
-
Anchor Line Style
|
|
2198
|
-
<select
|
|
2199
|
-
value={config.xAxis.anchors[index].lineStyle || ''}
|
|
2200
|
-
onChange={e => {
|
|
2201
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
2202
|
-
copiedAnchors[index].lineStyle = e.target.value
|
|
2203
|
-
updateConfig({
|
|
2204
|
-
...config,
|
|
2205
|
-
xAxis: {
|
|
2206
|
-
...config.xAxis,
|
|
2207
|
-
anchors: copiedAnchors
|
|
2208
|
-
}
|
|
2209
|
-
})
|
|
2210
|
-
}}
|
|
2211
|
-
>
|
|
2212
|
-
<option>Select</option>
|
|
2213
|
-
{lineOptions.map(line => (
|
|
2214
|
-
<option key={line.key}>{line.value}</option>
|
|
2215
|
-
))}
|
|
2216
|
-
</select>
|
|
2217
|
-
</label>
|
|
2218
|
-
</AccordionItemPanel>
|
|
2219
|
-
</AccordionItem>
|
|
2220
|
-
))}
|
|
2221
|
-
</Accordion>
|
|
2222
|
-
|
|
2223
|
-
<button
|
|
2224
|
-
className='btn full-width'
|
|
2225
|
-
onClick={e => {
|
|
2226
|
-
e.preventDefault()
|
|
2227
|
-
const anchors = [...config.xAxis.anchors]
|
|
2228
|
-
anchors.push({} as Anchor)
|
|
2229
|
-
updateConfig({
|
|
2230
|
-
...config,
|
|
2231
|
-
xAxis: {
|
|
2232
|
-
...config.xAxis,
|
|
2233
|
-
anchors
|
|
2234
|
-
}
|
|
2235
|
-
})
|
|
2236
|
-
}}
|
|
2237
|
-
>
|
|
2238
|
-
Add Anchor
|
|
2239
|
-
</button>
|
|
2240
|
-
</div>
|
|
2241
|
-
)}
|
|
2242
|
-
|
|
2243
|
-
{visHasAnchors() && config.orientation === 'horizontal' && (
|
|
2244
|
-
<div className='edit-block'>
|
|
2245
|
-
<span className='edit-label column-heading'>Anchors</span>
|
|
2246
|
-
<Accordion allowZeroExpanded>
|
|
2247
|
-
{config.yAxis?.anchors?.map((anchor, index) => (
|
|
2248
|
-
<AccordionItem className='series-item series-item--chart' key={`accordion-yaxis-anchors-${index}`}>
|
|
2249
|
-
<AccordionItemHeading className='series-item__title'>
|
|
2250
|
-
<>
|
|
2251
|
-
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
2252
|
-
Anchor {index + 1}
|
|
2253
|
-
<button
|
|
2254
|
-
className='series-list__remove'
|
|
2255
|
-
onClick={e => {
|
|
2256
|
-
e.preventDefault()
|
|
2257
|
-
const copiedAnchorGroups = [...config.yAxis.anchors]
|
|
2258
|
-
copiedAnchorGroups.splice(index, 1)
|
|
2259
|
-
updateConfig({
|
|
2260
|
-
...config,
|
|
2261
|
-
yAxis: {
|
|
2262
|
-
...config.yAxis,
|
|
2263
|
-
anchors: copiedAnchorGroups
|
|
2264
|
-
}
|
|
2265
|
-
})
|
|
2266
|
-
}}
|
|
2267
|
-
>
|
|
2268
|
-
Remove
|
|
2269
|
-
</button>
|
|
2270
|
-
</AccordionItemButton>
|
|
2271
|
-
</>
|
|
2272
|
-
</AccordionItemHeading>
|
|
2273
|
-
<AccordionItemPanel>
|
|
2274
|
-
<label>
|
|
2275
|
-
<span>Anchor Value</span>
|
|
2276
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2277
|
-
<Tooltip.Target>
|
|
2278
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2279
|
-
</Tooltip.Target>
|
|
2280
|
-
<Tooltip.Content>
|
|
2281
|
-
<p>Enter the value as its shown in the data column</p>
|
|
2282
|
-
</Tooltip.Content>
|
|
2283
|
-
</Tooltip>
|
|
2284
|
-
<input
|
|
2285
|
-
type='text'
|
|
2286
|
-
value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
|
|
2287
|
-
onChange={e => {
|
|
2288
|
-
e.preventDefault()
|
|
2289
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
2290
|
-
copiedAnchors[index].value = e.target.value
|
|
2291
|
-
updateConfig({
|
|
2292
|
-
...config,
|
|
2293
|
-
yAxis: {
|
|
2294
|
-
...config.yAxis,
|
|
2295
|
-
anchors: copiedAnchors
|
|
2296
|
-
}
|
|
2297
|
-
})
|
|
2298
|
-
}}
|
|
2299
|
-
/>
|
|
2300
|
-
</label>
|
|
2301
|
-
|
|
2302
|
-
<label>
|
|
2303
|
-
<span>Anchor Color</span>
|
|
2304
|
-
<input
|
|
2305
|
-
type='text'
|
|
2306
|
-
value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
|
|
2307
|
-
onChange={e => {
|
|
2308
|
-
e.preventDefault()
|
|
2309
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
2310
|
-
copiedAnchors[index].color = e.target.value
|
|
2311
|
-
updateConfig({
|
|
2312
|
-
...config,
|
|
2313
|
-
yAxis: {
|
|
2314
|
-
...config.yAxis,
|
|
2315
|
-
anchors: copiedAnchors
|
|
2316
|
-
}
|
|
2317
|
-
})
|
|
2318
|
-
}}
|
|
2319
|
-
/>
|
|
2320
|
-
</label>
|
|
2321
|
-
|
|
2322
|
-
<label>
|
|
2323
|
-
Anchor Line Style
|
|
2324
|
-
<select
|
|
2325
|
-
value={config.yAxis.anchors[index].lineStyle || ''}
|
|
2326
|
-
onChange={e => {
|
|
2327
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
2328
|
-
copiedAnchors[index].lineStyle = e.target.value
|
|
2329
|
-
updateConfig({
|
|
2330
|
-
...config,
|
|
2331
|
-
yAxis: {
|
|
2332
|
-
...config.yAxis,
|
|
2333
|
-
anchors: copiedAnchors
|
|
2334
|
-
}
|
|
2335
|
-
})
|
|
2336
|
-
}}
|
|
2337
|
-
>
|
|
2338
|
-
<option>Select</option>
|
|
2339
|
-
{lineOptions.map(line => (
|
|
2340
|
-
<option key={line.key}>{line.value}</option>
|
|
2341
|
-
))}
|
|
2342
|
-
</select>
|
|
2343
|
-
</label>
|
|
2344
|
-
</AccordionItemPanel>
|
|
2345
|
-
</AccordionItem>
|
|
2346
|
-
))}
|
|
2347
|
-
</Accordion>
|
|
2348
|
-
|
|
2349
|
-
<button
|
|
2350
|
-
className='btn full-width'
|
|
2351
|
-
onClick={e => {
|
|
2352
|
-
e.preventDefault()
|
|
2353
|
-
const anchors = [...config.yAxis.anchors]
|
|
2354
|
-
anchors.push({} as Anchor)
|
|
2355
|
-
updateConfig({
|
|
2356
|
-
...config,
|
|
2357
|
-
yAxis: {
|
|
2358
|
-
...config.yAxis,
|
|
2359
|
-
anchors
|
|
2360
|
-
}
|
|
2361
|
-
})
|
|
2362
|
-
}}
|
|
2363
|
-
>
|
|
2364
|
-
Add Anchor
|
|
2365
|
-
</button>
|
|
2366
|
-
</div>
|
|
2367
|
-
)}
|
|
2368
|
-
</AccordionItemPanel>
|
|
2369
|
-
</AccordionItem>
|
|
2370
|
-
)}
|
|
2371
|
-
<Panels.Regions name='Regions' />
|
|
2372
|
-
{/* Columns */}
|
|
2373
|
-
{config.visualizationType !== 'Box Plot' && (
|
|
2374
|
-
<AccordionItem>
|
|
2375
|
-
<AccordionItemHeading>
|
|
2376
|
-
<AccordionItemButton>Columns</AccordionItemButton>
|
|
2377
|
-
</AccordionItemHeading>
|
|
2378
|
-
<AccordionItemPanel>
|
|
2379
|
-
{'navigation' !== config.type && (
|
|
2380
|
-
<fieldset className='primary-fieldset edit-block'>
|
|
2381
|
-
<label>
|
|
2382
|
-
<span className='edit-label'>
|
|
2383
|
-
Additional Columns
|
|
2384
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2385
|
-
<Tooltip.Target>
|
|
2386
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2387
|
-
</Tooltip.Target>
|
|
2388
|
-
<Tooltip.Content>
|
|
2389
|
-
<p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
|
|
2390
|
-
</Tooltip.Content>
|
|
2391
|
-
</Tooltip>
|
|
2392
|
-
</span>
|
|
2393
|
-
</label>
|
|
2394
|
-
{additionalColumns.map(val => (
|
|
2395
|
-
<fieldset className='edit-block' key={val}>
|
|
2396
|
-
<button
|
|
2397
|
-
className='remove-column'
|
|
2398
|
-
onClick={event => {
|
|
2399
|
-
event.preventDefault()
|
|
2400
|
-
removeAdditionalColumn(val)
|
|
2401
|
-
}}
|
|
2402
|
-
>
|
|
2403
|
-
Remove
|
|
2404
|
-
</button>
|
|
2405
|
-
<label>
|
|
2406
|
-
<span className='edit-label column-heading'>Column</span>
|
|
2407
|
-
<select
|
|
2408
|
-
value={config.columns[val] ? config.columns[val].name : getColumns()[0]}
|
|
2409
|
-
onChange={event => {
|
|
2410
|
-
editColumn(val, 'name', event.target.value)
|
|
2411
|
-
}}
|
|
2412
|
-
>
|
|
2413
|
-
{getColumns().map(option => (
|
|
2414
|
-
<option>{option}</option>
|
|
2415
|
-
))}
|
|
2416
|
-
</select>
|
|
2417
|
-
</label>
|
|
2418
|
-
<label>
|
|
2419
|
-
<span className='edit-label column-heading'>Associate to Series</span>
|
|
2420
|
-
<select
|
|
2421
|
-
value={config.columns[val] ? config.columns[val].series : ''}
|
|
2422
|
-
onChange={event => {
|
|
2423
|
-
editColumn(val, 'series', event.target.value)
|
|
2424
|
-
}}
|
|
2425
|
-
>
|
|
2426
|
-
<option value=''>Select series</option>
|
|
2427
|
-
{config.series.map(series => (
|
|
2428
|
-
<option>{series.dataKey}</option>
|
|
2429
|
-
))}
|
|
2430
|
-
</select>
|
|
2431
|
-
</label>
|
|
2432
|
-
<TextField value={config.columns[val].label} section='columns' subsection={val} fieldName='label' label='Label' updateField={updateField} />
|
|
2433
|
-
<ul className='column-edit'>
|
|
2434
|
-
<li className='three-col'>
|
|
2435
|
-
<TextField value={config.columns[val].prefix} section='columns' subsection={val} fieldName='prefix' label='Prefix' updateField={updateField} />
|
|
2436
|
-
<TextField value={config.columns[val].suffix} section='columns' subsection={val} fieldName='suffix' label='Suffix' updateField={updateField} />
|
|
2437
|
-
<TextField type='number' value={config.columns[val].roundToPlace} section='columns' subsection={val} fieldName='roundToPlace' label='Round' updateField={updateField} />
|
|
2438
|
-
</li>
|
|
2439
|
-
<li>
|
|
2440
|
-
<label className='checkbox'>
|
|
2441
|
-
<input
|
|
2442
|
-
type='checkbox'
|
|
2443
|
-
checked={config.columns[val].commas}
|
|
2444
|
-
onChange={event => {
|
|
2445
|
-
editColumn(val, 'commas', event.target.checked)
|
|
2446
|
-
}}
|
|
2447
|
-
/>
|
|
2448
|
-
<span className='edit-label'>Add Commas to Numbers</span>
|
|
2449
|
-
</label>
|
|
2450
|
-
</li>
|
|
2451
|
-
<li>
|
|
2452
|
-
{config.table.showVertical && (
|
|
2453
|
-
<label className='checkbox'>
|
|
2454
|
-
<input
|
|
2455
|
-
type='checkbox'
|
|
2456
|
-
checked={config.columns[val].dataTable}
|
|
2457
|
-
onChange={event => {
|
|
2458
|
-
editColumn(val, 'dataTable', event.target.checked)
|
|
2459
|
-
}}
|
|
2460
|
-
/>
|
|
2461
|
-
<span className='edit-label'>Show in Data Table</span>
|
|
2462
|
-
</label>
|
|
2463
|
-
)}
|
|
2464
|
-
</li>
|
|
2465
|
-
{config.visualizationType === 'Pie' && (
|
|
2466
|
-
<li>
|
|
2467
|
-
<label className='checkbox'>
|
|
2468
|
-
<input
|
|
2469
|
-
type='checkbox'
|
|
2470
|
-
checked={config.columns[val].showInViz}
|
|
2471
|
-
onChange={event => {
|
|
2472
|
-
editColumn(val, 'showInViz', event.target.checked)
|
|
2473
|
-
}}
|
|
2474
|
-
/>
|
|
2475
|
-
<span className='edit-label'>Show in Visualization</span>
|
|
2476
|
-
</label>
|
|
2477
|
-
</li>
|
|
2478
|
-
)}
|
|
2479
|
-
|
|
2480
|
-
{/* disable for now */}
|
|
1863
|
+
<TextField
|
|
1864
|
+
tooltip={
|
|
1865
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1866
|
+
<Tooltip.Target>
|
|
1867
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1868
|
+
</Tooltip.Target>
|
|
1869
|
+
<Tooltip.Content>
|
|
1870
|
+
<p>Specify a custom format for displaying dates in data table. If left empty, dates will adopt the Axis Date Display format. </p>
|
|
1871
|
+
</Tooltip.Content>
|
|
1872
|
+
</Tooltip>
|
|
1873
|
+
}
|
|
1874
|
+
value={config.table.dateDisplayFormat}
|
|
1875
|
+
section='table'
|
|
1876
|
+
fieldName='dateDisplayFormat'
|
|
1877
|
+
placeholder='Ex. %Y-%m-%d'
|
|
1878
|
+
label='DATA TABLE DATE DISPLAY FORMAT'
|
|
1879
|
+
updateField={updateField}
|
|
1880
|
+
/>
|
|
1881
|
+
<TextField
|
|
1882
|
+
tooltip={
|
|
1883
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1884
|
+
<Tooltip.Target>
|
|
1885
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1886
|
+
</Tooltip.Target>
|
|
1887
|
+
<Tooltip.Content>
|
|
1888
|
+
<p>Specify a custom format for displaying dates on hovers. If left empty, dates will adopt the Axis Date Display format. </p>
|
|
1889
|
+
</Tooltip.Content>
|
|
1890
|
+
</Tooltip>
|
|
1891
|
+
}
|
|
1892
|
+
value={config.tooltips.dateDisplayFormat}
|
|
1893
|
+
section='tooltips'
|
|
1894
|
+
fieldName='dateDisplayFormat'
|
|
1895
|
+
placeholder='Ex. %Y-%m-%d'
|
|
1896
|
+
label='HOVER DATE DISPLAY FORMAT'
|
|
1897
|
+
updateField={updateField}
|
|
1898
|
+
/>
|
|
1899
|
+
</>
|
|
1900
|
+
)}
|
|
2481
1901
|
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
</
|
|
1902
|
+
<CheckBox
|
|
1903
|
+
value={config.exclusions.active}
|
|
1904
|
+
section='exclusions'
|
|
1905
|
+
fieldName='active'
|
|
1906
|
+
label={config.xAxis.type === 'date' ? 'Limit by start and/or end dates' : 'Exclude one or more values'}
|
|
1907
|
+
tooltip={
|
|
1908
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1909
|
+
<Tooltip.Target>
|
|
1910
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1911
|
+
</Tooltip.Target>
|
|
1912
|
+
<Tooltip.Content>
|
|
1913
|
+
<p>When this option is checked, you can select source-file values for exclusion from the date/category axis. </p>
|
|
1914
|
+
</Tooltip.Content>
|
|
1915
|
+
</Tooltip>
|
|
1916
|
+
}
|
|
1917
|
+
updateField={updateField}
|
|
1918
|
+
/>
|
|
1919
|
+
{/* {visHasBrushChart && <CheckBox value={config.brush.active} section='brush' fieldName='active' label='Brush Slider ' updateField={updateField} />} */}
|
|
2494
1920
|
|
|
2495
|
-
|
|
1921
|
+
{config.exclusions.active && (
|
|
1922
|
+
<>
|
|
1923
|
+
{config.xAxis.type === 'categorical' && (
|
|
1924
|
+
<>
|
|
1925
|
+
{config.exclusions.keys.length > 0 && (
|
|
2496
1926
|
<>
|
|
2497
|
-
<
|
|
2498
|
-
<
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
checked={config.columns[val].forestPlot || false}
|
|
2502
|
-
onChange={event => {
|
|
2503
|
-
editColumn(val, 'forestPlot', event.target.checked)
|
|
2504
|
-
}}
|
|
2505
|
-
/>
|
|
2506
|
-
<span className='edit-label'>Show in Forest Plot</span>
|
|
2507
|
-
</label>
|
|
2508
|
-
</li>
|
|
2509
|
-
<li>
|
|
2510
|
-
<label className='checkbox'>
|
|
2511
|
-
<input
|
|
2512
|
-
type='checkbox'
|
|
2513
|
-
checked={config.columns[val].forestPlotAlignRight || false}
|
|
2514
|
-
onChange={event => {
|
|
2515
|
-
editColumn(val, 'forestPlotAlignRight', event.target.checked)
|
|
2516
|
-
}}
|
|
2517
|
-
/>
|
|
2518
|
-
<span className='edit-label'>Align Right</span>
|
|
2519
|
-
</label>
|
|
2520
|
-
</li>
|
|
2521
|
-
|
|
2522
|
-
{!config.columns[val].forestPlotAlignRight && (
|
|
2523
|
-
<li>
|
|
2524
|
-
<label className='text'>
|
|
2525
|
-
<span className='edit-label'>Forest Plot Starting Point</span>
|
|
2526
|
-
<input
|
|
2527
|
-
type='number'
|
|
2528
|
-
value={config.columns[val].forestPlotStartingPoint || 0}
|
|
2529
|
-
onChange={event => {
|
|
2530
|
-
editColumn(val, 'forestPlotStartingPoint', event.target.value)
|
|
2531
|
-
}}
|
|
2532
|
-
/>
|
|
2533
|
-
</label>
|
|
2534
|
-
</li>
|
|
2535
|
-
)}
|
|
1927
|
+
<fieldset>
|
|
1928
|
+
<legend className='edit-label'>Excluded Keys</legend>
|
|
1929
|
+
</fieldset>
|
|
1930
|
+
<ExclusionsList />
|
|
2536
1931
|
</>
|
|
2537
1932
|
)}
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
Add Column
|
|
2549
|
-
</button>
|
|
2550
|
-
</fieldset>
|
|
2551
|
-
)}
|
|
2552
|
-
{'category' === config.legend.type && (
|
|
2553
|
-
<fieldset className='primary-fieldset edit-block'>
|
|
2554
|
-
<label>
|
|
2555
|
-
<span className='edit-label'>
|
|
2556
|
-
Additional Category
|
|
2557
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2558
|
-
<Tooltip.Target>
|
|
2559
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2560
|
-
</Tooltip.Target>
|
|
2561
|
-
<Tooltip.Content>
|
|
2562
|
-
<p>You can provide additional categories to ensure they appear in the legend</p>
|
|
2563
|
-
</Tooltip.Content>
|
|
2564
|
-
</Tooltip>
|
|
2565
|
-
</span>
|
|
2566
|
-
</label>
|
|
2567
|
-
{config.legend.additionalCategories &&
|
|
2568
|
-
config.legend.additionalCategories.map((val, i) => (
|
|
2569
|
-
<fieldset className='edit-block' key={val}>
|
|
2570
|
-
<button
|
|
2571
|
-
className='remove-column'
|
|
2572
|
-
onClick={event => {
|
|
2573
|
-
event.preventDefault()
|
|
2574
|
-
const updatedAdditionaCategories = [...config.legend.additionalCategories]
|
|
2575
|
-
updatedAdditionaCategories.splice(i, 1)
|
|
2576
|
-
updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
|
|
2577
|
-
}}
|
|
2578
|
-
>
|
|
2579
|
-
Remove
|
|
2580
|
-
</button>
|
|
2581
|
-
<TextField
|
|
2582
|
-
value={val}
|
|
2583
|
-
label='Category'
|
|
2584
|
-
section='legend'
|
|
2585
|
-
subsection={null}
|
|
2586
|
-
fieldName='additionalCategories'
|
|
2587
|
-
updateField={(section, subsection, fieldName, value) => {
|
|
2588
|
-
const updatedAdditionaCategories = [...config.legend.additionalCategories]
|
|
2589
|
-
updatedAdditionaCategories[i] = value
|
|
2590
|
-
updateField(section, subsection, fieldName, updatedAdditionaCategories)
|
|
1933
|
+
|
|
1934
|
+
<Select
|
|
1935
|
+
fieldName='visualizationType'
|
|
1936
|
+
label='Add Exclusion'
|
|
1937
|
+
initial='Select'
|
|
1938
|
+
onChange={e => {
|
|
1939
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
1940
|
+
addNewExclusion(e.target.value)
|
|
1941
|
+
}
|
|
1942
|
+
e.target.value = ''
|
|
2591
1943
|
}}
|
|
1944
|
+
options={getDataValues(config.xAxis.dataKey, true)}
|
|
2592
1945
|
/>
|
|
2593
|
-
|
|
2594
|
-
)
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
Add Category
|
|
2605
|
-
</button>
|
|
2606
|
-
</fieldset>
|
|
2607
|
-
)}
|
|
2608
|
-
</AccordionItemPanel>
|
|
2609
|
-
</AccordionItem>
|
|
2610
|
-
)}
|
|
2611
|
-
{/* End Columns */}
|
|
2612
|
-
{visHasLegend() && (
|
|
2613
|
-
<AccordionItem>
|
|
2614
|
-
<AccordionItemHeading>
|
|
2615
|
-
<AccordionItemButton>Legend</AccordionItemButton>
|
|
2616
|
-
</AccordionItemHeading>
|
|
2617
|
-
<AccordionItemPanel>
|
|
2618
|
-
<CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
|
|
2619
|
-
{/* <fieldset className="checkbox-group">
|
|
2620
|
-
<CheckBox value={config.legend.dynamicLegend} section="legend" fieldName="dynamicLegend" label="Dynamic Legend" updateField={updateField}/>
|
|
2621
|
-
{config.legend.dynamicLegend && (
|
|
2622
|
-
<>
|
|
2623
|
-
<TextField value={config.legend.dynamicLegendDefaultText} section="legend" fieldName="dynamicLegendDefaultText" label="Dynamic Legend Default Text" updateField={updateField} />
|
|
2624
|
-
<TextField value={config.legend.dynamicLegendItemLimit} type="number" min="0" section="legend" fieldName="dynamicLegendItemLimit" label={'Dynamic Legend Limit'} className="number-narrow" updateField={updateField}/>
|
|
2625
|
-
<TextField value={config.legend.dynamicLegendItemLimitMessage} section="legend" fieldName="dynamicLegendItemLimitMessage" label="Dynamic Legend Item Limit Message" updateField={updateField} />
|
|
2626
|
-
<TextField value={config.legend.dynamicLegendChartMessage} section="legend" fieldName="dynamicLegendChartMessage" label="Dynamic Legend Chart Message" updateField={updateField} />
|
|
2627
|
-
</>
|
|
2628
|
-
)}
|
|
2629
|
-
</fieldset> */}
|
|
2630
|
-
<CheckBox
|
|
2631
|
-
value={config.legend.hide ? true : false}
|
|
2632
|
-
section='legend'
|
|
2633
|
-
fieldName='hide'
|
|
2634
|
-
label='Hide Legend'
|
|
2635
|
-
updateField={updateField}
|
|
2636
|
-
tooltip={
|
|
2637
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2638
|
-
<Tooltip.Target>
|
|
2639
|
-
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2640
|
-
</Tooltip.Target>
|
|
2641
|
-
<Tooltip.Content>
|
|
2642
|
-
<p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
|
|
2643
|
-
</Tooltip.Content>
|
|
2644
|
-
</Tooltip>
|
|
2645
|
-
}
|
|
2646
|
-
/>
|
|
2647
|
-
{/* {config.visualizationType === 'Box Plot' &&
|
|
2648
|
-
<>
|
|
2649
|
-
<CheckBox value={config.boxplot.legend.displayHowToReadText} fieldName='displayHowToReadText' section='boxplot' subsection='legend' label='Display How To Read Text' updateField={updateField} />
|
|
2650
|
-
<TextField type='textarea' value={config.boxplot.legend.howToReadText} updateField={updateField} fieldName='howToReadText' section='boxplot' subsection='legend' label='How to read text' />
|
|
2651
|
-
</>
|
|
2652
|
-
} */}
|
|
2653
|
-
{config.visualizationType === 'Line' && <CheckBox value={config.legend.lineMode} section='legend' fieldName='lineMode' label='Show Lined Style Legend' updateField={updateField} />}
|
|
2654
|
-
{config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
|
|
2655
|
-
<Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
|
|
2656
|
-
)}
|
|
2657
|
-
<Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={(...[section, , fieldName, value]) => updateBehavior(section, fieldName, value)} options={['highlight', 'isolate']} />
|
|
2658
|
-
{visHasLegendAxisAlign() && <CheckBox value={config.legend.axisAlign} fieldName='axisAlign' section='legend' label='Align to Axis on Isolate' updateField={updateField} />}
|
|
1946
|
+
</>
|
|
1947
|
+
)}
|
|
1948
|
+
|
|
1949
|
+
{config.xAxis.type === 'date' && (
|
|
1950
|
+
<>
|
|
1951
|
+
<TextField type='date' section='exclusions' fieldName='dateStart' label='Start Date' updateField={updateField} value={config.exclusions.dateStart || ''} />
|
|
1952
|
+
<TextField type='date' section='exclusions' fieldName='dateEnd' label='End Date' updateField={updateField} value={config.exclusions.dateEnd || ''} />
|
|
1953
|
+
</>
|
|
1954
|
+
)}
|
|
1955
|
+
</>
|
|
1956
|
+
)}
|
|
2659
1957
|
|
|
2660
|
-
|
|
1958
|
+
{visSupportsDateCategoryNumTicks() && config.xAxis.type !== 'date-time' && config.xAxis.manual && (
|
|
1959
|
+
<TextField value={config.xAxis.manualStep} placeholder='Auto' type='number' min={1} section='xAxis' fieldName='manualStep' label='Step count' className='number-narrow' updateField={updateField} />
|
|
1960
|
+
)}
|
|
1961
|
+
{visSupportsDateCategoryNumTicks() && (config.xAxis.type === 'date-time' || !config.xAxis.manual) && (
|
|
1962
|
+
<TextField value={config.xAxis.numTicks} placeholder='Auto' type='number' min={1} section='xAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
|
|
1963
|
+
)}
|
|
1964
|
+
{visSupportsDateCategoryHeight() && <TextField value={config.xAxis.padding} type='number' min={0} section='xAxis' fieldName='padding' label={config.orientation === 'horizontal' ? 'Size (Width)' : 'Size (Height)'} className='number-narrow' updateField={updateField} />}
|
|
2661
1965
|
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
<
|
|
2667
|
-
|
|
1966
|
+
{/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
|
|
1967
|
+
{/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
|
|
1968
|
+
{(config.xAxis.type === 'continuous' || config.forestPlot.type === 'Logarithmic') && (
|
|
1969
|
+
<>
|
|
1970
|
+
<CheckBox value={config.dataFormat.bottomCommas} section='dataFormat' fieldName='bottomCommas' label='Add commas' updateField={updateField} />
|
|
1971
|
+
<TextField value={config.dataFormat.bottomRoundTo} type='number' section='dataFormat' fieldName='bottomRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
|
|
1972
|
+
</>
|
|
1973
|
+
)}
|
|
1974
|
+
{visSupportsResponsiveTicks() && config.orientation === 'vertical' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
|
|
1975
|
+
{(config.orientation === 'horizontal' || !config.isResponsiveTicks) && visSupportsDateCategoryTickRotation() && (
|
|
1976
|
+
<TextField value={config.xAxis.tickRotation} type='number' min={0} section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />
|
|
1977
|
+
)}
|
|
1978
|
+
{config.orientation === 'vertical' && config.isResponsiveTicks && config.visualizationType !== 'Paired Bar' && (
|
|
1979
|
+
<TextField
|
|
1980
|
+
value={config.xAxis.maxTickRotation}
|
|
1981
|
+
type='number'
|
|
1982
|
+
min={0}
|
|
1983
|
+
section='xAxis'
|
|
1984
|
+
fieldName='maxTickRotation'
|
|
1985
|
+
label='Max Tick Rotation'
|
|
1986
|
+
className='number-narrow'
|
|
1987
|
+
updateField={updateField}
|
|
1988
|
+
tooltip={
|
|
2668
1989
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
2669
1990
|
<Tooltip.Target>
|
|
2670
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1991
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2671
1992
|
</Tooltip.Target>
|
|
2672
1993
|
<Tooltip.Content>
|
|
2673
|
-
<p>
|
|
1994
|
+
<p>Degrees ticks will be rotated if values overlap, especially in smaller viewports.</p>
|
|
2674
1995
|
</Tooltip.Content>
|
|
2675
1996
|
</Tooltip>
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
config.legend.seriesHighlight.map((val, i) => (
|
|
2680
|
-
<fieldset className='edit-block' key={`${val}-${i}`}>
|
|
2681
|
-
<button
|
|
2682
|
-
className='remove-column'
|
|
2683
|
-
onClick={event => {
|
|
2684
|
-
event.preventDefault()
|
|
2685
|
-
const updatedSeriesHighlight = [...config.legend.seriesHighlight]
|
|
2686
|
-
updatedSeriesHighlight.splice(i, 1)
|
|
2687
|
-
updateField('legend', null, 'seriesHighlight', updatedSeriesHighlight)
|
|
2688
|
-
if (!updatedSeriesHighlight.length) {
|
|
2689
|
-
highlightReset()
|
|
2690
|
-
}
|
|
2691
|
-
}}
|
|
2692
|
-
>
|
|
2693
|
-
Remove
|
|
2694
|
-
</button>
|
|
2695
|
-
<Select
|
|
2696
|
-
value={config.legend.seriesHighlight[i]}
|
|
2697
|
-
fieldName='seriesHighlight'
|
|
2698
|
-
label='Isolate Value'
|
|
2699
|
-
onChange={e => {
|
|
2700
|
-
const updatedSeriesHighlight = [...config.legend.seriesHighlight]
|
|
2701
|
-
if (!updatedSeriesHighlight.includes(e.target.value)) {
|
|
2702
|
-
updatedSeriesHighlight[i] = e.target.value
|
|
2703
|
-
updateSeriesIsolateValues([...updatedSeriesHighlight])
|
|
2704
|
-
}
|
|
2705
|
-
}}
|
|
2706
|
-
options={getLegendColumns()}
|
|
2707
|
-
/>
|
|
2708
|
-
</fieldset>
|
|
2709
|
-
))}
|
|
2710
|
-
<button
|
|
2711
|
-
className={'btn full-width'}
|
|
2712
|
-
onClick={event => {
|
|
2713
|
-
event.preventDefault()
|
|
2714
|
-
const legendColumns = getLegendColumns()
|
|
2715
|
-
const updatedSeriesHighlight = [...config.legend.seriesHighlight]
|
|
2716
|
-
const seriesLength = updatedSeriesHighlight.length
|
|
2717
|
-
if (seriesLength < legendColumns.length) {
|
|
2718
|
-
const [newSeriesHighlight] = legendColumns.filter(d => !updatedSeriesHighlight.includes(d))
|
|
2719
|
-
updatedSeriesHighlight.push(newSeriesHighlight)
|
|
2720
|
-
updateSeriesIsolateValues([...updatedSeriesHighlight])
|
|
2721
|
-
}
|
|
2722
|
-
}}
|
|
2723
|
-
>
|
|
2724
|
-
Add Isolate Value
|
|
2725
|
-
</button>
|
|
2726
|
-
</fieldset>
|
|
2727
|
-
)}
|
|
2728
|
-
{/* end: isolated values */}
|
|
1997
|
+
}
|
|
1998
|
+
/>
|
|
1999
|
+
)}
|
|
2729
2000
|
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2001
|
+
{config.orientation === 'horizontal' ? (
|
|
2002
|
+
<>
|
|
2003
|
+
{visSupportsDateCategoryAxisLine() && <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
|
|
2004
|
+
{visSupportsDateCategoryAxisLabel() && <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
|
|
2005
|
+
</>
|
|
2006
|
+
) : (
|
|
2007
|
+
<>
|
|
2008
|
+
{visSupportsDateCategoryAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
|
|
2009
|
+
{visSupportsDateCategoryAxisLabel() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
|
|
2010
|
+
{visSupportsDateCategoryAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
|
|
2011
|
+
</>
|
|
2012
|
+
)}
|
|
2013
|
+
<CheckBox
|
|
2014
|
+
tooltip={
|
|
2015
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2016
|
+
<Tooltip.Target>
|
|
2017
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2018
|
+
</Tooltip.Target>
|
|
2019
|
+
<Tooltip.Content>
|
|
2020
|
+
<p>Selecting this option will display a "thin line" slightly above the Date/Category Axis to indicate "suppressed data" where "suppressed data" values are indicated in the Data Series.</p>
|
|
2021
|
+
</Tooltip.Content>
|
|
2022
|
+
</Tooltip>
|
|
2023
|
+
}
|
|
2024
|
+
value={config.xAxis.showSuppressedLine}
|
|
2025
|
+
section='xAxis'
|
|
2026
|
+
fieldName='showSuppressedLine'
|
|
2027
|
+
label='Display suppressed data line'
|
|
2755
2028
|
updateField={updateField}
|
|
2756
|
-
|
|
2029
|
+
/>
|
|
2030
|
+
<CheckBox
|
|
2757
2031
|
tooltip={
|
|
2758
2032
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
2759
2033
|
<Tooltip.Target>
|
|
2760
2034
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2761
2035
|
</Tooltip.Target>
|
|
2762
2036
|
<Tooltip.Content>
|
|
2763
|
-
<p>
|
|
2037
|
+
<p>Selecting this option will display "suppressed data symbol" on the Date/Category Axis where suppressed data values are indicated in the Data Series, unless a different symbol was chosen from the data series (e.g., suppression symbol) menu.</p>
|
|
2764
2038
|
</Tooltip.Content>
|
|
2765
2039
|
</Tooltip>
|
|
2766
2040
|
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
<
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2041
|
+
value={config.xAxis.showSuppressedSymbol}
|
|
2042
|
+
section='xAxis'
|
|
2043
|
+
fieldName='showSuppressedSymbol'
|
|
2044
|
+
label='Display suppressed data symbol'
|
|
2045
|
+
updateField={updateField}
|
|
2046
|
+
/>
|
|
2047
|
+
|
|
2048
|
+
{config.series?.length === 1 && config.visualizationType === 'Bar' && (
|
|
2049
|
+
<>
|
|
2050
|
+
{/* HIGHLIGHTED BARS */}
|
|
2051
|
+
<label htmlFor='barHighlight'>Bar Highlighting</label>
|
|
2052
|
+
{config.series.length === 1 &&
|
|
2053
|
+
highlightedBarValues.map((highlightedBarValue, i) => (
|
|
2054
|
+
<fieldset>
|
|
2055
|
+
<div className='edit-block' key={`highlighted-bar-${i}`}>
|
|
2056
|
+
<button className='remove-column' onClick={e => handleRemoveHighlightedBar(e, i)}>
|
|
2057
|
+
Remove
|
|
2058
|
+
</button>
|
|
2059
|
+
<p>Highlighted Bar {i + 1}</p>
|
|
2060
|
+
<label>
|
|
2061
|
+
<span className='edit-label column-heading'>Value</span>
|
|
2062
|
+
<select value={config.highlightedBarValues[i].value} onChange={e => handleUpdateHighlightedBar(e, i)}>
|
|
2063
|
+
<option value=''>- Select Value -</option>
|
|
2064
|
+
{highlightedSeriesValues && [...new Set(highlightedSeriesValues)].sort().map(option => <option key={`special-class-value-option-${i}-${option}`}>{option}</option>)}
|
|
2065
|
+
</select>
|
|
2066
|
+
</label>
|
|
2067
|
+
<label>
|
|
2068
|
+
<span className='edit-label column-heading'>Color</span>
|
|
2069
|
+
<input type='text' value={config.highlightedBarValues[i].color ? config.highlightedBarValues[i].color : ''} onChange={e => handleUpdateHighlightedBarColor(e, i)} />
|
|
2070
|
+
</label>
|
|
2071
|
+
<label>
|
|
2072
|
+
<span className='edit-label column-heading'>Border Width</span>
|
|
2073
|
+
<input max='5' min='0' type='number' value={config.highlightedBarValues[i].borderWidth ? config.highlightedBarValues[i].borderWidth : ''} onChange={e => handleUpdateHighlightedBorderWidth(e, i)} />
|
|
2074
|
+
</label>
|
|
2075
|
+
<label>
|
|
2076
|
+
<span className='edit-label column-heading'>Legend Label</span>
|
|
2077
|
+
<input type='text' value={config.highlightedBarValues[i].legendLabel ? config.highlightedBarValues[i].legendLabel : ''} onChange={e => handleHighlightedBarLegendLabel(e, i)} />
|
|
2078
|
+
</label>
|
|
2079
|
+
</div>
|
|
2080
|
+
</fieldset>
|
|
2081
|
+
))}
|
|
2082
|
+
<button className='btn full-width' onClick={e => handleAddNewHighlightedBar(e)}>
|
|
2083
|
+
Add Highlighted Bar
|
|
2084
|
+
</button>
|
|
2085
|
+
</>
|
|
2086
|
+
)}
|
|
2087
|
+
</>
|
|
2088
|
+
)}
|
|
2089
|
+
|
|
2090
|
+
{config.visualizationType === 'Pie' && (
|
|
2091
|
+
<>
|
|
2092
|
+
<CheckBox
|
|
2093
|
+
value={config.exclusions.active}
|
|
2094
|
+
section='exclusions'
|
|
2095
|
+
fieldName='active'
|
|
2096
|
+
label={'Exclude one or more values'}
|
|
2097
|
+
updateField={updateField}
|
|
2098
|
+
tooltip={
|
|
2099
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2100
|
+
<Tooltip.Target>
|
|
2101
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2102
|
+
</Tooltip.Target>
|
|
2103
|
+
<Tooltip.Content>
|
|
2104
|
+
<p>When this option is checked, you can select values for exclusion from the pie segments.</p>
|
|
2105
|
+
</Tooltip.Content>
|
|
2106
|
+
</Tooltip>
|
|
2107
|
+
}
|
|
2108
|
+
/>
|
|
2109
|
+
{config.exclusions.active && (
|
|
2110
|
+
<>
|
|
2111
|
+
{config.exclusions.keys.length > 0 && (
|
|
2112
|
+
<>
|
|
2113
|
+
<fieldset>
|
|
2114
|
+
<legend className='edit-label'>Excluded Keys</legend>
|
|
2115
|
+
</fieldset>
|
|
2116
|
+
<ExclusionsList />
|
|
2117
|
+
</>
|
|
2118
|
+
)}
|
|
2119
|
+
|
|
2120
|
+
<Select
|
|
2121
|
+
fieldName='visualizationType'
|
|
2122
|
+
label='Add Exclusion'
|
|
2123
|
+
initial='Select'
|
|
2124
|
+
onChange={e => {
|
|
2125
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
2126
|
+
addNewExclusion(e.target.value)
|
|
2127
|
+
}
|
|
2128
|
+
e.target.value = ''
|
|
2129
|
+
}}
|
|
2130
|
+
options={getDataValues(config.xAxis.dataKey, true)}
|
|
2131
|
+
/>
|
|
2132
|
+
</>
|
|
2133
|
+
)}
|
|
2134
|
+
</>
|
|
2135
|
+
)}
|
|
2136
|
+
|
|
2137
|
+
{/* anchors */}
|
|
2138
|
+
{visHasAnchors() && config.orientation !== 'horizontal' && (
|
|
2139
|
+
<div className='edit-block'>
|
|
2140
|
+
<span className='edit-label column-heading'>Anchors</span>
|
|
2141
|
+
<Accordion allowZeroExpanded>
|
|
2142
|
+
{config.xAxis?.anchors?.map((anchor, index) => (
|
|
2143
|
+
<AccordionItem className='series-item series-item--chart' key={`xaxis-anchors-2-${index}`}>
|
|
2144
|
+
<AccordionItemHeading className='series-item__title'>
|
|
2145
|
+
<>
|
|
2146
|
+
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
2147
|
+
Anchor {index + 1}
|
|
2148
|
+
<button
|
|
2149
|
+
className='series-list__remove'
|
|
2150
|
+
onClick={e => {
|
|
2151
|
+
e.preventDefault()
|
|
2152
|
+
const copiedAnchorGroups = [...config.xAxis.anchors]
|
|
2153
|
+
copiedAnchorGroups.splice(index, 1)
|
|
2154
|
+
updateConfig({
|
|
2155
|
+
...config,
|
|
2156
|
+
xAxis: {
|
|
2157
|
+
...config.xAxis,
|
|
2158
|
+
anchors: copiedAnchorGroups
|
|
2159
|
+
}
|
|
2160
|
+
})
|
|
2161
|
+
}}
|
|
2162
|
+
>
|
|
2163
|
+
Remove
|
|
2164
|
+
</button>
|
|
2165
|
+
</AccordionItemButton>
|
|
2166
|
+
</>
|
|
2167
|
+
</AccordionItemHeading>
|
|
2168
|
+
<AccordionItemPanel>
|
|
2789
2169
|
<label>
|
|
2790
|
-
<span
|
|
2791
|
-
<
|
|
2792
|
-
|
|
2170
|
+
<span>Anchor Value</span>
|
|
2171
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2172
|
+
<Tooltip.Target>
|
|
2173
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2174
|
+
</Tooltip.Target>
|
|
2175
|
+
<Tooltip.Content>
|
|
2176
|
+
<p>Enter the value as its shown in the data column</p>
|
|
2177
|
+
</Tooltip.Content>
|
|
2178
|
+
</Tooltip>
|
|
2179
|
+
<input
|
|
2180
|
+
type='text'
|
|
2181
|
+
value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
|
|
2793
2182
|
onChange={e => {
|
|
2794
|
-
|
|
2183
|
+
e.preventDefault()
|
|
2184
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
2185
|
+
copiedAnchors[index].value = e.target.value
|
|
2186
|
+
updateConfig({
|
|
2187
|
+
...config,
|
|
2188
|
+
xAxis: {
|
|
2189
|
+
...config.xAxis,
|
|
2190
|
+
anchors: copiedAnchors
|
|
2191
|
+
}
|
|
2192
|
+
})
|
|
2795
2193
|
}}
|
|
2796
|
-
|
|
2797
|
-
<option value=''>- Select Option -</option>
|
|
2798
|
-
{getFilters().map((dataKey, index) => (
|
|
2799
|
-
<option value={dataKey} key={index}>
|
|
2800
|
-
{dataKey}
|
|
2801
|
-
</option>
|
|
2802
|
-
))}
|
|
2803
|
-
</select>
|
|
2194
|
+
/>
|
|
2804
2195
|
</label>
|
|
2805
2196
|
|
|
2806
2197
|
<label>
|
|
2807
|
-
<span
|
|
2198
|
+
<span>Anchor Color</span>
|
|
2808
2199
|
<input
|
|
2809
|
-
type='
|
|
2810
|
-
|
|
2200
|
+
type='text'
|
|
2201
|
+
value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
|
|
2811
2202
|
onChange={e => {
|
|
2812
|
-
|
|
2203
|
+
e.preventDefault()
|
|
2204
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
2205
|
+
copiedAnchors[index].color = e.target.value
|
|
2206
|
+
updateConfig({
|
|
2207
|
+
...config,
|
|
2208
|
+
xAxis: {
|
|
2209
|
+
...config.xAxis,
|
|
2210
|
+
anchors: copiedAnchors
|
|
2211
|
+
}
|
|
2212
|
+
})
|
|
2813
2213
|
}}
|
|
2814
2214
|
/>
|
|
2815
2215
|
</label>
|
|
2816
2216
|
|
|
2817
2217
|
<label>
|
|
2818
|
-
|
|
2819
|
-
|
|
2218
|
+
Anchor Line Style
|
|
2820
2219
|
<select
|
|
2821
|
-
value={
|
|
2220
|
+
value={config.xAxis.anchors[index].lineStyle || ''}
|
|
2822
2221
|
onChange={e => {
|
|
2823
|
-
|
|
2222
|
+
const copiedAnchors = [...config.xAxis.anchors]
|
|
2223
|
+
copiedAnchors[index].lineStyle = e.target.value
|
|
2224
|
+
updateConfig({
|
|
2225
|
+
...config,
|
|
2226
|
+
xAxis: {
|
|
2227
|
+
...config.xAxis,
|
|
2228
|
+
anchors: copiedAnchors
|
|
2229
|
+
}
|
|
2230
|
+
})
|
|
2824
2231
|
}}
|
|
2825
2232
|
>
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
</option>
|
|
2831
|
-
)
|
|
2832
|
-
})}
|
|
2233
|
+
<option>Select</option>
|
|
2234
|
+
{lineOptions.map(line => (
|
|
2235
|
+
<option key={line.key}>{line.value}</option>
|
|
2236
|
+
))}
|
|
2833
2237
|
</select>
|
|
2834
2238
|
</label>
|
|
2239
|
+
</AccordionItemPanel>
|
|
2240
|
+
</AccordionItem>
|
|
2241
|
+
))}
|
|
2242
|
+
</Accordion>
|
|
2243
|
+
|
|
2244
|
+
<button
|
|
2245
|
+
className='btn full-width'
|
|
2246
|
+
onClick={e => {
|
|
2247
|
+
e.preventDefault()
|
|
2248
|
+
const anchors = [...config.xAxis.anchors]
|
|
2249
|
+
anchors.push({} as Anchor)
|
|
2250
|
+
updateConfig({
|
|
2251
|
+
...config,
|
|
2252
|
+
xAxis: {
|
|
2253
|
+
...config.xAxis,
|
|
2254
|
+
anchors
|
|
2255
|
+
}
|
|
2256
|
+
})
|
|
2257
|
+
}}
|
|
2258
|
+
>
|
|
2259
|
+
Add Anchor
|
|
2260
|
+
</button>
|
|
2261
|
+
</div>
|
|
2262
|
+
)}
|
|
2263
|
+
|
|
2264
|
+
{visHasAnchors() && config.orientation === 'horizontal' && (
|
|
2265
|
+
<div className='edit-block'>
|
|
2266
|
+
<span className='edit-label column-heading'>Anchors</span>
|
|
2267
|
+
<Accordion allowZeroExpanded>
|
|
2268
|
+
{config.yAxis?.anchors?.map((anchor, index) => (
|
|
2269
|
+
<AccordionItem className='series-item series-item--chart' key={`accordion-yaxis-anchors-${index}`}>
|
|
2270
|
+
<AccordionItemHeading className='series-item__title'>
|
|
2271
|
+
<>
|
|
2272
|
+
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
2273
|
+
Anchor {index + 1}
|
|
2274
|
+
<button
|
|
2275
|
+
className='series-list__remove'
|
|
2276
|
+
onClick={e => {
|
|
2277
|
+
e.preventDefault()
|
|
2278
|
+
const copiedAnchorGroups = [...config.yAxis.anchors]
|
|
2279
|
+
copiedAnchorGroups.splice(index, 1)
|
|
2280
|
+
updateConfig({
|
|
2281
|
+
...config,
|
|
2282
|
+
yAxis: {
|
|
2283
|
+
...config.yAxis,
|
|
2284
|
+
anchors: copiedAnchorGroups
|
|
2285
|
+
}
|
|
2286
|
+
})
|
|
2287
|
+
}}
|
|
2288
|
+
>
|
|
2289
|
+
Remove
|
|
2290
|
+
</button>
|
|
2291
|
+
</AccordionItemButton>
|
|
2292
|
+
</>
|
|
2293
|
+
</AccordionItemHeading>
|
|
2294
|
+
<AccordionItemPanel>
|
|
2835
2295
|
<label>
|
|
2836
|
-
<span
|
|
2296
|
+
<span>Anchor Value</span>
|
|
2297
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2298
|
+
<Tooltip.Target>
|
|
2299
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2300
|
+
</Tooltip.Target>
|
|
2301
|
+
<Tooltip.Content>
|
|
2302
|
+
<p>Enter the value as its shown in the data column</p>
|
|
2303
|
+
</Tooltip.Content>
|
|
2304
|
+
</Tooltip>
|
|
2837
2305
|
<input
|
|
2838
2306
|
type='text'
|
|
2839
|
-
value={
|
|
2307
|
+
value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
|
|
2840
2308
|
onChange={e => {
|
|
2841
|
-
|
|
2309
|
+
e.preventDefault()
|
|
2310
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
2311
|
+
copiedAnchors[index].value = e.target.value
|
|
2312
|
+
updateConfig({
|
|
2313
|
+
...config,
|
|
2314
|
+
yAxis: {
|
|
2315
|
+
...config.yAxis,
|
|
2316
|
+
anchors: copiedAnchors
|
|
2317
|
+
}
|
|
2318
|
+
})
|
|
2842
2319
|
}}
|
|
2843
2320
|
/>
|
|
2844
2321
|
</label>
|
|
2845
2322
|
|
|
2846
2323
|
<label>
|
|
2847
|
-
<span
|
|
2324
|
+
<span>Anchor Color</span>
|
|
2848
2325
|
<input
|
|
2849
2326
|
type='text'
|
|
2850
|
-
value={
|
|
2327
|
+
value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
|
|
2851
2328
|
onChange={e => {
|
|
2852
|
-
|
|
2329
|
+
e.preventDefault()
|
|
2330
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
2331
|
+
copiedAnchors[index].color = e.target.value
|
|
2332
|
+
updateConfig({
|
|
2333
|
+
...config,
|
|
2334
|
+
yAxis: {
|
|
2335
|
+
...config.yAxis,
|
|
2336
|
+
anchors: copiedAnchors
|
|
2337
|
+
}
|
|
2338
|
+
})
|
|
2853
2339
|
}}
|
|
2854
2340
|
/>
|
|
2855
2341
|
</label>
|
|
2856
2342
|
|
|
2857
2343
|
<label>
|
|
2858
|
-
|
|
2859
|
-
<select
|
|
2860
|
-
{
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2344
|
+
Anchor Line Style
|
|
2345
|
+
<select
|
|
2346
|
+
value={config.yAxis.anchors[index].lineStyle || ''}
|
|
2347
|
+
onChange={e => {
|
|
2348
|
+
const copiedAnchors = [...config.yAxis.anchors]
|
|
2349
|
+
copiedAnchors[index].lineStyle = e.target.value
|
|
2350
|
+
updateConfig({
|
|
2351
|
+
...config,
|
|
2352
|
+
yAxis: {
|
|
2353
|
+
...config.yAxis,
|
|
2354
|
+
anchors: copiedAnchors
|
|
2355
|
+
}
|
|
2356
|
+
})
|
|
2357
|
+
}}
|
|
2358
|
+
>
|
|
2359
|
+
<option>Select</option>
|
|
2360
|
+
{lineOptions.map(line => (
|
|
2361
|
+
<option key={line.key}>{line.value}</option>
|
|
2362
|
+
))}
|
|
2867
2363
|
</select>
|
|
2868
|
-
|
|
2869
|
-
{filter.order === 'cust' && (
|
|
2870
|
-
<DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
|
|
2871
|
-
<Droppable droppableId='filter_order'>
|
|
2872
|
-
{provided => (
|
|
2873
|
-
<ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
2874
|
-
{config.filters[index]?.values.map((value, index) => {
|
|
2875
|
-
return (
|
|
2876
|
-
<Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
|
|
2877
|
-
{(provided, snapshot) => (
|
|
2878
|
-
<li>
|
|
2879
|
-
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
2880
|
-
{value}
|
|
2881
|
-
</div>
|
|
2882
|
-
</li>
|
|
2883
|
-
)}
|
|
2884
|
-
</Draggable>
|
|
2885
|
-
)
|
|
2886
|
-
})}
|
|
2887
|
-
{provided.placeholder}
|
|
2888
|
-
</ul>
|
|
2889
|
-
)}
|
|
2890
|
-
</Droppable>
|
|
2891
|
-
</DragDropContext>
|
|
2892
|
-
)}
|
|
2893
2364
|
</label>
|
|
2894
|
-
</
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
</
|
|
2365
|
+
</AccordionItemPanel>
|
|
2366
|
+
</AccordionItem>
|
|
2367
|
+
))}
|
|
2368
|
+
</Accordion>
|
|
2369
|
+
|
|
2370
|
+
<button
|
|
2371
|
+
className='btn full-width'
|
|
2372
|
+
onClick={e => {
|
|
2373
|
+
e.preventDefault()
|
|
2374
|
+
const anchors = [...config.yAxis.anchors]
|
|
2375
|
+
anchors.push({} as Anchor)
|
|
2376
|
+
updateConfig({
|
|
2377
|
+
...config,
|
|
2378
|
+
yAxis: {
|
|
2379
|
+
...config.yAxis,
|
|
2380
|
+
anchors
|
|
2381
|
+
}
|
|
2382
|
+
})
|
|
2383
|
+
}}
|
|
2384
|
+
>
|
|
2385
|
+
Add Anchor
|
|
2386
|
+
</button>
|
|
2387
|
+
</div>
|
|
2388
|
+
)}
|
|
2389
|
+
</AccordionItemPanel>
|
|
2390
|
+
</AccordionItem>
|
|
2391
|
+
)}
|
|
2392
|
+
<Panels.Regions name='Regions' />
|
|
2393
|
+
|
|
2394
|
+
{/* Columns */}
|
|
2395
|
+
{config.visualizationType !== 'Box Plot' && (
|
|
2396
|
+
<AccordionItem>
|
|
2397
|
+
<AccordionItemHeading>
|
|
2398
|
+
<AccordionItemButton>Columns</AccordionItemButton>
|
|
2399
|
+
</AccordionItemHeading>
|
|
2400
|
+
<AccordionItemPanel>
|
|
2401
|
+
<ColumnsEditor config={config} updateField={updateField} deleteColumn={removeAdditionalColumn} />{' '}
|
|
2402
|
+
</AccordionItemPanel>
|
|
2403
|
+
</AccordionItem>
|
|
2404
|
+
)}
|
|
2405
|
+
{/* End Columns */}
|
|
2406
|
+
{visHasLegend() && (
|
|
2407
|
+
<AccordionItem>
|
|
2408
|
+
<AccordionItemHeading>
|
|
2409
|
+
<AccordionItemButton>Legend</AccordionItemButton>
|
|
2410
|
+
</AccordionItemHeading>
|
|
2411
|
+
<AccordionItemPanel>
|
|
2412
|
+
<CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
|
|
2413
|
+
{/* <fieldset className="checkbox-group">
|
|
2414
|
+
<CheckBox value={config.legend.dynamicLegend} section="legend" fieldName="dynamicLegend" label="Dynamic Legend" updateField={updateField}/>
|
|
2415
|
+
{config.legend.dynamicLegend && (
|
|
2416
|
+
<>
|
|
2417
|
+
<TextField value={config.legend.dynamicLegendDefaultText} section="legend" fieldName="dynamicLegendDefaultText" label="Dynamic Legend Default Text" updateField={updateField} />
|
|
2418
|
+
<TextField value={config.legend.dynamicLegendItemLimit} type="number" min="0" section="legend" fieldName="dynamicLegendItemLimit" label={'Dynamic Legend Limit'} className="number-narrow" updateField={updateField}/>
|
|
2419
|
+
<TextField value={config.legend.dynamicLegendItemLimitMessage} section="legend" fieldName="dynamicLegendItemLimitMessage" label="Dynamic Legend Item Limit Message" updateField={updateField} />
|
|
2420
|
+
<TextField value={config.legend.dynamicLegendChartMessage} section="legend" fieldName="dynamicLegendChartMessage" label="Dynamic Legend Chart Message" updateField={updateField} />
|
|
2421
|
+
</>
|
|
2898
2422
|
)}
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2423
|
+
</fieldset> */}
|
|
2424
|
+
<CheckBox
|
|
2425
|
+
value={config.legend.hide ? true : false}
|
|
2426
|
+
section='legend'
|
|
2427
|
+
fieldName='hide'
|
|
2428
|
+
label='Hide Legend'
|
|
2429
|
+
updateField={updateField}
|
|
2430
|
+
tooltip={
|
|
2431
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2432
|
+
<Tooltip.Target>
|
|
2433
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2434
|
+
</Tooltip.Target>
|
|
2435
|
+
<Tooltip.Content>
|
|
2436
|
+
<p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
|
|
2437
|
+
</Tooltip.Content>
|
|
2438
|
+
</Tooltip>
|
|
2439
|
+
}
|
|
2440
|
+
/>
|
|
2441
|
+
<CheckBox
|
|
2442
|
+
value={config.legend.hideSuppressedLabels}
|
|
2443
|
+
section='legend'
|
|
2444
|
+
fieldName='hideSuppressedLabels'
|
|
2445
|
+
label='Hide Suppressed Labels'
|
|
2446
|
+
updateField={updateField}
|
|
2447
|
+
tooltip={
|
|
2448
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2449
|
+
<Tooltip.Target>
|
|
2450
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2451
|
+
</Tooltip.Target>
|
|
2452
|
+
<Tooltip.Content>
|
|
2453
|
+
<p>Hiding suppressed labels will not override the 'Special Class' assigned to line chart indicating "suppressed" data in the Data Series Panel.</p>
|
|
2454
|
+
</Tooltip.Content>
|
|
2455
|
+
</Tooltip>
|
|
2456
|
+
}
|
|
2457
|
+
/>
|
|
2458
|
+
{/* {config.visualizationType === 'Box Plot' &&
|
|
2459
|
+
<>
|
|
2460
|
+
<CheckBox value={config.boxplot.legend.displayHowToReadText} fieldName='displayHowToReadText' section='boxplot' subsection='legend' label='Display How To Read Text' updateField={updateField} />
|
|
2461
|
+
<TextField type='textarea' value={config.boxplot.legend.howToReadText} updateField={updateField} fieldName='howToReadText' section='boxplot' subsection='legend' label='How to read text' />
|
|
2462
|
+
</>
|
|
2463
|
+
} */}
|
|
2464
|
+
{config.visualizationType === 'Line' && <CheckBox value={config.legend.lineMode} section='legend' fieldName='lineMode' label='Show Lined Style Legend' updateField={updateField} />}
|
|
2465
|
+
{config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
|
|
2466
|
+
<Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
|
|
2467
|
+
)}
|
|
2468
|
+
<Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={(...[section, , fieldName, value]) => updateBehavior(section, fieldName, value)} options={['highlight', 'isolate']} />
|
|
2469
|
+
{visHasLegendAxisAlign() && <CheckBox value={config.legend.axisAlign} fieldName='axisAlign' section='legend' label='Align to Axis on Isolate' updateField={updateField} />}
|
|
2470
|
+
|
|
2471
|
+
{config.legend.behavior === 'highlight' && config.tooltips.singleSeries && <CheckBox value={config.legend.highlightOnHover} section='legend' fieldName='highlightOnHover' label='HIGHLIGHT DATA SERIES ON HOVER' updateField={updateField} />}
|
|
2472
|
+
|
|
2473
|
+
{/* start: isolated values */}
|
|
2474
|
+
{visHasSelectableLegendValues && config.legend.behavior === 'isolate' && !colorCodeByCategory && (
|
|
2475
|
+
<fieldset className='primary-fieldset edit-block' key={'additional-highlight-values'}>
|
|
2476
|
+
<label>
|
|
2477
|
+
<span className='edit-label'>
|
|
2478
|
+
Isolate Data Series
|
|
2479
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2480
|
+
<Tooltip.Target>
|
|
2481
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2482
|
+
</Tooltip.Target>
|
|
2483
|
+
<Tooltip.Content>
|
|
2484
|
+
<p>You can choose data series that are shown on load. Others will be added when the user clicks on them in the legend.</p>
|
|
2485
|
+
</Tooltip.Content>
|
|
2486
|
+
</Tooltip>
|
|
2487
|
+
</span>
|
|
2488
|
+
</label>
|
|
2489
|
+
{config.legend.seriesHighlight &&
|
|
2490
|
+
config.legend.seriesHighlight.map((val, i) => (
|
|
2491
|
+
<fieldset className='edit-block' key={`${val}-${i}`}>
|
|
2492
|
+
<button
|
|
2493
|
+
className='remove-column'
|
|
2494
|
+
onClick={event => {
|
|
2495
|
+
event.preventDefault()
|
|
2496
|
+
const updatedSeriesHighlight = [...config.legend.seriesHighlight]
|
|
2497
|
+
updatedSeriesHighlight.splice(i, 1)
|
|
2498
|
+
updateField('legend', null, 'seriesHighlight', updatedSeriesHighlight)
|
|
2499
|
+
if (!updatedSeriesHighlight.length) {
|
|
2500
|
+
highlightReset()
|
|
2501
|
+
}
|
|
2502
|
+
}}
|
|
2503
|
+
>
|
|
2504
|
+
Remove
|
|
2505
|
+
</button>
|
|
2506
|
+
<Select
|
|
2507
|
+
value={config.legend.seriesHighlight[i]}
|
|
2508
|
+
fieldName='seriesHighlight'
|
|
2509
|
+
label='Isolate Value'
|
|
2510
|
+
onChange={e => {
|
|
2511
|
+
const updatedSeriesHighlight = [...config.legend.seriesHighlight]
|
|
2512
|
+
if (!updatedSeriesHighlight.includes(e.target.value)) {
|
|
2513
|
+
updatedSeriesHighlight[i] = e.target.value
|
|
2514
|
+
updateSeriesIsolateValues([...updatedSeriesHighlight])
|
|
2515
|
+
}
|
|
2516
|
+
}}
|
|
2517
|
+
options={getLegendColumns()}
|
|
2518
|
+
/>
|
|
2519
|
+
</fieldset>
|
|
2520
|
+
))}
|
|
2521
|
+
<button
|
|
2522
|
+
className={'btn full-width'}
|
|
2523
|
+
onClick={event => {
|
|
2524
|
+
event.preventDefault()
|
|
2525
|
+
const legendColumns = getLegendColumns()
|
|
2526
|
+
const updatedSeriesHighlight = [...config.legend.seriesHighlight]
|
|
2527
|
+
const seriesLength = updatedSeriesHighlight.length
|
|
2528
|
+
if (seriesLength < legendColumns.length) {
|
|
2529
|
+
const [newSeriesHighlight] = legendColumns.filter(d => !updatedSeriesHighlight.includes(d))
|
|
2530
|
+
updatedSeriesHighlight.push(newSeriesHighlight)
|
|
2531
|
+
updateSeriesIsolateValues([...updatedSeriesHighlight])
|
|
2532
|
+
}
|
|
2533
|
+
}}
|
|
2534
|
+
>
|
|
2535
|
+
Add Isolate Value
|
|
2536
|
+
</button>
|
|
2537
|
+
</fieldset>
|
|
2538
|
+
)}
|
|
2539
|
+
{/* end: isolated values */}
|
|
2540
|
+
|
|
2541
|
+
<TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
|
|
2542
|
+
<Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
|
|
2543
|
+
{config.legend.position === 'bottom' && (
|
|
2544
|
+
<>
|
|
2545
|
+
<CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />
|
|
2546
|
+
<CheckBox value={config.legend.verticalSorted} section='legend' fieldName='verticalSorted' label='Vertical sorted Legend' updateField={updateField} />
|
|
2547
|
+
</>
|
|
2548
|
+
)}
|
|
2549
|
+
<TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
|
|
2550
|
+
</AccordionItemPanel>
|
|
2551
|
+
</AccordionItem>
|
|
2552
|
+
)}
|
|
2553
|
+
{visSupportsFilters() && (
|
|
2554
|
+
<AccordionItem>
|
|
2555
|
+
<AccordionItemHeading>
|
|
2556
|
+
<AccordionItemButton>Filters</AccordionItemButton>
|
|
2557
|
+
</AccordionItemHeading>
|
|
2558
|
+
<AccordionItemPanel>
|
|
2559
|
+
<VizFilterEditor config={config} updateField={updateField} rawData={rawData} />
|
|
2560
|
+
</AccordionItemPanel>
|
|
2561
|
+
</AccordionItem>
|
|
2562
|
+
)}
|
|
2563
|
+
<Panels.Visual name='Visual' />
|
|
2564
|
+
{/* Spark Line has no data table */}
|
|
2565
|
+
{config.visualizationType !== 'Spark Line' && (
|
|
2566
|
+
<AccordionItem>
|
|
2567
|
+
<AccordionItemHeading>
|
|
2568
|
+
<AccordionItemButton>Data Table</AccordionItemButton>
|
|
2569
|
+
</AccordionItemHeading>
|
|
2570
|
+
<AccordionItemPanel>
|
|
2571
|
+
<DataTableEditor config={config} columns={Object.keys(data[0] || {})} updateField={updateField} isDashboard={isDashboard} isLoadedFromUrl={isLoadedFromUrl} />{' '}
|
|
2572
|
+
</AccordionItemPanel>
|
|
2573
|
+
</AccordionItem>
|
|
2574
|
+
)}
|
|
2575
|
+
{/* {(config.visualizationType === 'Bar' || config.visualizationType === 'Line') && <Panels.DateHighlighting name='Date Highlighting' />} */}
|
|
2576
|
+
</Accordion>
|
|
2577
|
+
{config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig} state={config} convertStateToConfig={convertStateToConfig} />}
|
|
2578
|
+
</Layout.Sidebar>
|
|
2923
2579
|
</ErrorBoundary>
|
|
2924
2580
|
</EditorPanelContext.Provider>
|
|
2925
2581
|
)
|