@cdc/chart 4.24.4 → 4.24.7
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 +39611 -36038
- package/examples/feature/annotations/index.json +542 -0
- package/examples/xaxis.json +493 -0
- package/index.html +9 -8
- package/package.json +5 -4
- package/src/CdcChart.tsx +115 -71
- package/src/_stories/Chart.stories.tsx +26 -171
- package/src/_stories/ChartAnnotation.stories.tsx +32 -0
- package/src/_stories/_mock/annotation_category_mock.json +473 -0
- package/src/_stories/_mock/annotation_date-linear_mock.json +530 -0
- package/src/_stories/_mock/annotation_date-time_mock.json +530 -0
- package/src/_stories/_mock/bar-chart-suppressed.json +474 -0
- package/src/_stories/_mock/line_chart_two_points_new_chart.json +128 -0
- package/src/_stories/_mock/line_chart_two_points_regression_test.json +127 -0
- package/src/_stories/_mock/lollipop.json +171 -0
- package/src/components/Annotations/components/AnnotationDraggable.styles.css +31 -0
- package/src/components/Annotations/components/AnnotationDraggable.tsx +154 -0
- package/src/components/Annotations/components/AnnotationDropdown.styles.css +14 -0
- package/src/components/Annotations/components/AnnotationDropdown.tsx +72 -0
- package/src/components/Annotations/components/AnnotationList.styles.css +45 -0
- package/src/components/Annotations/components/AnnotationList.tsx +42 -0
- package/src/components/Annotations/components/findNearestDatum.ts +138 -0
- package/src/components/Annotations/components/helpers/index.tsx +46 -0
- package/src/components/Annotations/index.tsx +13 -0
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -1
- package/src/components/AreaChart/components/AreaChart.jsx +2 -2
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +78 -71
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +1 -2
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +11 -11
- package/src/components/BarChart/components/BarChart.Vertical.tsx +100 -87
- package/src/components/BarChart/helpers/index.ts +102 -0
- package/src/components/DeviationBar.jsx +4 -2
- package/src/components/EditorPanel/EditorPanel.tsx +435 -613
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +306 -0
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +135 -7
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +2 -3
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -5
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +3 -2
- package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
- package/src/components/EditorPanel/components/panels.scss +4 -0
- package/src/components/EditorPanel/editor-panel.scss +19 -0
- package/src/components/EditorPanel/useEditorPermissions.js +23 -3
- package/src/components/Legend/Legend.Component.tsx +66 -15
- package/src/components/Legend/helpers/createFormatLabels.tsx +1 -1
- package/src/components/Legend/helpers/index.ts +5 -0
- package/src/components/LineChart/LineChartProps.ts +16 -6
- package/src/components/LineChart/components/LineChart.Circle.tsx +22 -11
- package/src/components/LineChart/helpers.ts +148 -10
- package/src/components/LineChart/index.tsx +71 -44
- package/src/components/LinearChart.jsx +184 -125
- package/src/components/PairedBarChart.jsx +9 -9
- package/src/components/PieChart/PieChart.tsx +4 -4
- package/src/components/Sankey/index.tsx +73 -20
- package/src/components/ScatterPlot/ScatterPlot.jsx +22 -8
- package/src/components/ZoomBrush.tsx +120 -55
- package/src/data/initial-state.js +14 -6
- package/src/helpers/handleChartTabbing.ts +8 -0
- package/src/helpers/isConvertLineToBarGraph.ts +4 -0
- package/src/hooks/{useBarChart.js → useBarChart.ts} +9 -22
- package/src/hooks/useColorScale.ts +1 -1
- package/src/hooks/useMinMax.ts +29 -5
- package/src/hooks/useScales.ts +48 -26
- package/src/hooks/useTooltip.tsx +62 -15
- package/src/scss/main.scss +69 -12
- package/src/types/ChartConfig.ts +53 -16
- package/src/types/ChartContext.ts +13 -0
- package/tests-examples/helpers/testZeroValue.test.ts +30 -0
- package/LICENSE +0 -201
- 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
- package/src/helpers/filterData.ts +0 -18
- package/src/helpers/tests/computeMarginBottom.test.ts +0 -21
- /package/src/hooks/{useLegendClasses.js → useLegendClasses.ts} +0 -0
- /package/src/hooks/{useReduceData.js → useReduceData.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
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
5
|
import Layout from '@cdc/core/components/Layout'
|
|
@@ -8,18 +8,18 @@ import Layout from '@cdc/core/components/Layout'
|
|
|
8
8
|
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
9
9
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
10
10
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
11
|
-
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'
|
|
12
14
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
13
15
|
import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
16
|
+
import { viewports } from '@cdc/core/helpers/getViewport'
|
|
14
17
|
|
|
15
18
|
// chart components
|
|
16
19
|
import Panels from './components/Panels'
|
|
17
|
-
import Series from './components/Panel.Series.jsx'
|
|
18
20
|
|
|
19
21
|
// cdc additional
|
|
20
|
-
import { useColorPalette } from '../../hooks/useColorPalette'
|
|
21
22
|
import { useEditorPermissions } from './useEditorPermissions'
|
|
22
|
-
import { useFilters } from '@cdc/core/components/Filters'
|
|
23
23
|
import { useHighlightedBars } from '../../hooks/useHighlightedBars'
|
|
24
24
|
import ConfigContext from '../../ConfigContext'
|
|
25
25
|
import useReduceData from '../../hooks/useReduceData'
|
|
@@ -27,113 +27,56 @@ import useRightAxis from '../../hooks/useRightAxis'
|
|
|
27
27
|
import WarningImage from '../../images/warning.svg'
|
|
28
28
|
import useMinMax from '../../hooks/useMinMax'
|
|
29
29
|
|
|
30
|
-
import { type ChartConfig } from '../../types/ChartConfig'
|
|
31
30
|
import { type ChartContext } from '../../types/ChartContext'
|
|
31
|
+
import { type ChartConfig } from '../../types/ChartConfig'
|
|
32
32
|
|
|
33
33
|
import './editor-panel.scss'
|
|
34
34
|
import { Anchor } from '@cdc/core/types/Axis'
|
|
35
|
-
import DataTableEditor from '@cdc/core/components/EditorPanel/DataTableEditor'
|
|
36
35
|
import EditorPanelContext from './EditorPanelContext'
|
|
36
|
+
import _ from 'lodash'
|
|
37
|
+
import { adjustedSymbols as symbolCodes } from '@cdc/core/helpers/footnoteSymbols'
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
keys.add(key)
|
|
44
|
-
})
|
|
45
|
-
})
|
|
46
|
-
return [...keys]
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const getIconOptions = () => {
|
|
50
|
-
return ['star']
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let removeColumn = i => {
|
|
54
|
-
let suppressedData = []
|
|
55
|
-
|
|
56
|
-
if (config.suppressedData) {
|
|
57
|
-
suppressedData = [...config.suppressedData]
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
suppressedData.splice(i, 1)
|
|
39
|
+
interface PreliminaryProps {
|
|
40
|
+
config: ChartConfig
|
|
41
|
+
updateConfig: Function
|
|
42
|
+
data: Record<string, any>[]
|
|
43
|
+
}
|
|
61
44
|
|
|
62
|
-
|
|
63
|
-
|
|
45
|
+
const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, data }) => {
|
|
46
|
+
const isCombo = config.visualizationType === 'Combo'
|
|
47
|
+
const lineSeriesExists = config.runtime.lineSeriesKeys?.length > 0
|
|
48
|
+
const barSeriesExists = config.runtime.barSeriesKeys?.length > 0
|
|
49
|
+
const hasComboLineSeries = isCombo && lineSeriesExists
|
|
50
|
+
const hasComboBarSeries = isCombo && barSeriesExists
|
|
64
51
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
suppressedData.push({ label: '', column: '', value: '', icon: '' })
|
|
68
|
-
updateConfig({ ...config, suppressedData })
|
|
52
|
+
const getColumnOptions = () => {
|
|
53
|
+
return _.uniq(_.flatMap(data, _.keys))
|
|
69
54
|
}
|
|
70
55
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (config.suppressedData) {
|
|
75
|
-
suppressedData = [...config.suppressedData]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
suppressedData[i][fieldName] = value
|
|
79
|
-
updateConfig({ ...config, suppressedData })
|
|
56
|
+
const getTypeOptions = () => {
|
|
57
|
+
return config.visualizationType === 'Line' || hasComboLineSeries ? ['effect', 'suppression'] : ['suppression']
|
|
80
58
|
}
|
|
81
59
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
<button
|
|
89
|
-
type='button'
|
|
90
|
-
className='remove-column'
|
|
91
|
-
onClick={event => {
|
|
92
|
-
event.preventDefault()
|
|
93
|
-
removeColumn(i)
|
|
94
|
-
}}
|
|
95
|
-
>
|
|
96
|
-
Remove
|
|
97
|
-
</button>
|
|
98
|
-
<Select value={column} initial='Select' fieldName='column' label='Column' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getColumnOptions()} />
|
|
99
|
-
<TextField value={value} fieldName='value' label='Value' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} />
|
|
100
|
-
<Select value={icon} initial='Select' fieldName='icon' label='Icon' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getIconOptions()} />
|
|
101
|
-
<TextField value={label} fieldName='label' label='Label' placeholder='suppressed' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} />
|
|
102
|
-
</div>
|
|
103
|
-
)
|
|
104
|
-
})}
|
|
105
|
-
|
|
106
|
-
<button type='button' onClick={addColumn} className='btn full-width'>
|
|
107
|
-
Add Suppression Class
|
|
108
|
-
</button>
|
|
109
|
-
</>
|
|
110
|
-
)
|
|
111
|
-
})
|
|
112
|
-
const PreliminaryData = memo(({ config, updateConfig, data }) => {
|
|
113
|
-
const getColumnOptions = () => {
|
|
114
|
-
const keys = new Set()
|
|
115
|
-
data.forEach(d => {
|
|
116
|
-
Object.keys(d).forEach(key => {
|
|
117
|
-
keys.add(key)
|
|
118
|
-
})
|
|
119
|
-
})
|
|
120
|
-
return [...keys]
|
|
60
|
+
const lineCodes = {
|
|
61
|
+
'Dashed Small': '\u002D \u002D \u002D',
|
|
62
|
+
'Dashed Medium': '\u2013 \u2013',
|
|
63
|
+
'Dashed Large': '\u2014 \u2013',
|
|
64
|
+
'Open Circles': '\u25EF',
|
|
65
|
+
'Filled Circles': ''
|
|
121
66
|
}
|
|
122
67
|
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
68
|
+
const getStyleOptions = type => {
|
|
69
|
+
const options = Object.keys(lineCodes)
|
|
70
|
+
if (type === 'suppression') {
|
|
71
|
+
return options.slice(0, -1)
|
|
126
72
|
} else {
|
|
127
|
-
return
|
|
73
|
+
return options
|
|
128
74
|
}
|
|
129
75
|
}
|
|
130
76
|
|
|
131
|
-
const
|
|
132
|
-
if (config.visualizationType === '
|
|
133
|
-
return
|
|
134
|
-
}
|
|
135
|
-
if (config.visualizationType === 'Bar') {
|
|
136
|
-
return ['star']
|
|
77
|
+
const getSymbolOptions = () => {
|
|
78
|
+
if (config.visualizationType === 'Bar' || hasComboBarSeries) {
|
|
79
|
+
return Object.keys(symbolCodes)
|
|
137
80
|
}
|
|
138
81
|
}
|
|
139
82
|
|
|
@@ -150,8 +93,26 @@ const PreliminaryData = memo(({ config, updateConfig, data }) => {
|
|
|
150
93
|
}
|
|
151
94
|
|
|
152
95
|
let addColumn = () => {
|
|
96
|
+
const defaultType = config.visualizationType === 'Line' ? 'effect' : 'suppression'
|
|
153
97
|
let preliminaryData = config.preliminaryData ? [...config.preliminaryData] : []
|
|
154
|
-
|
|
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
|
+
hideBarSymbol: false,
|
|
112
|
+
hideLineStyle: false,
|
|
113
|
+
circleSize: 6
|
|
114
|
+
}
|
|
115
|
+
preliminaryData.push(defaultValues)
|
|
155
116
|
updateConfig({ ...config, preliminaryData })
|
|
156
117
|
}
|
|
157
118
|
|
|
@@ -163,15 +124,22 @@ const PreliminaryData = memo(({ config, updateConfig, data }) => {
|
|
|
163
124
|
}
|
|
164
125
|
|
|
165
126
|
preliminaryData[i][fieldName] = value
|
|
127
|
+
if (fieldName === 'symbol') {
|
|
128
|
+
preliminaryData[i]['iconCode'] = symbolCodes[value]
|
|
129
|
+
}
|
|
130
|
+
if (fieldName === 'style') {
|
|
131
|
+
preliminaryData[i]['lineCode'] = lineCodes[value]
|
|
132
|
+
}
|
|
166
133
|
updateConfig({ ...config, preliminaryData })
|
|
167
134
|
}
|
|
168
135
|
|
|
169
136
|
return (
|
|
170
137
|
<>
|
|
171
138
|
{config.preliminaryData &&
|
|
172
|
-
config.preliminaryData
|
|
139
|
+
config.preliminaryData?.map(({ circleSize, column, displayLegend, displayTable, displayTooltip, label, seriesKey, style, symbol, type, value, hideBarSymbol, hideLineStyle }, i) => {
|
|
173
140
|
return (
|
|
174
141
|
<div key={`preliminaryData-${i}`} className='edit-block'>
|
|
142
|
+
<p> {type === 'suppression' ? 'Suppressed' : 'Effect'} Data</p>
|
|
175
143
|
<button
|
|
176
144
|
type='button'
|
|
177
145
|
className='remove-column'
|
|
@@ -182,23 +150,178 @@ const PreliminaryData = memo(({ config, updateConfig, data }) => {
|
|
|
182
150
|
>
|
|
183
151
|
Remove
|
|
184
152
|
</button>
|
|
185
|
-
<Select value={type} initial='Select' fieldName='type' label='Type' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getTypeOptions()} />
|
|
186
|
-
<Select value={seriesKey} initial='Select' fieldName='seriesKey' label='ASSOCIATE TO SERIES' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={config.runtime.lineSeriesKeys ?? config.runtime?.seriesKeys} />
|
|
187
|
-
<Select value={column} initial='Select' fieldName='column' label='COLUMN WITH CONFIGURATION VALUE' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getColumnOptions()} />
|
|
188
|
-
<TextField value={value} fieldName='value' label='VALUE TO TRIGGER' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} />
|
|
189
|
-
<Select value={style} initial='Select' fieldName='style' label='Style' updateField={(section, subsection, fieldName, value) => update(fieldName, value, i)} options={getStyleOptions()} />
|
|
190
153
|
|
|
191
|
-
<
|
|
154
|
+
<Select value={type} initial={config.visualizationType == 'Bar' ? '' : 'Select'} fieldName='type' label='Type' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getTypeOptions()} />
|
|
155
|
+
{type === 'suppression' ? (
|
|
156
|
+
<>
|
|
157
|
+
<Select
|
|
158
|
+
tooltip={
|
|
159
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
160
|
+
<Tooltip.Target>
|
|
161
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
162
|
+
</Tooltip.Target>
|
|
163
|
+
<Tooltip.Content>
|
|
164
|
+
<p> If no “Data Series" is selected, the symbol will be applied to "all" suppressed values indicated in the dataset. If you select a particular data series, there's no need to fill in “suppression line style” and “suppression symbol” below.</p>
|
|
165
|
+
</Tooltip.Content>
|
|
166
|
+
</Tooltip>
|
|
167
|
+
}
|
|
168
|
+
value={column}
|
|
169
|
+
initial='Select'
|
|
170
|
+
fieldName='column'
|
|
171
|
+
label='Add Data Series'
|
|
172
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
173
|
+
options={config.runtime?.seriesKeys}
|
|
174
|
+
/>
|
|
175
|
+
<TextField value={value} fieldName='value' label='Suppressed Data Value' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
|
|
176
|
+
{(hasComboLineSeries || config.visualizationType === 'Line') && (
|
|
177
|
+
<>
|
|
178
|
+
<Select
|
|
179
|
+
tooltip={
|
|
180
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
181
|
+
<Tooltip.Target>
|
|
182
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
183
|
+
</Tooltip.Target>
|
|
184
|
+
<Tooltip.Content>
|
|
185
|
+
<p>The recommended approach for presenting data is to include a footnote indicating any data suppression.</p>
|
|
186
|
+
</Tooltip.Content>
|
|
187
|
+
</Tooltip>
|
|
188
|
+
}
|
|
189
|
+
value={style}
|
|
190
|
+
initial='Select'
|
|
191
|
+
fieldName='style'
|
|
192
|
+
label={'suppression line style'}
|
|
193
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
194
|
+
options={getStyleOptions(type)}
|
|
195
|
+
/>
|
|
196
|
+
<CheckBox value={hideLineStyle} fieldName='hideLineStyle' label='Hide Suppressed line Style' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
|
|
197
|
+
</>
|
|
198
|
+
)}
|
|
199
|
+
|
|
200
|
+
{(hasComboBarSeries || config.visualizationType === 'Bar') && (
|
|
201
|
+
<>
|
|
202
|
+
<Select
|
|
203
|
+
tooltip={
|
|
204
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
205
|
+
<Tooltip.Target>
|
|
206
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
207
|
+
</Tooltip.Target>
|
|
208
|
+
<Tooltip.Content>
|
|
209
|
+
<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>
|
|
210
|
+
</Tooltip.Content>
|
|
211
|
+
</Tooltip>
|
|
212
|
+
}
|
|
213
|
+
value={symbol}
|
|
214
|
+
initial='Select'
|
|
215
|
+
fieldName='symbol'
|
|
216
|
+
label={config.visualizationType === 'Combo' ? 'suppression bar symbol' : 'suppression symbol'}
|
|
217
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
218
|
+
options={getSymbolOptions()}
|
|
219
|
+
/>
|
|
220
|
+
<CheckBox value={hideBarSymbol} fieldName='hideBarSymbol' label='Hide Suppressed Bar Symbol ' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
|
|
221
|
+
</>
|
|
222
|
+
)}
|
|
223
|
+
|
|
224
|
+
<TextField
|
|
225
|
+
tooltip={
|
|
226
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
227
|
+
<Tooltip.Target>
|
|
228
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
229
|
+
</Tooltip.Target>
|
|
230
|
+
<Tooltip.Content>
|
|
231
|
+
<p>This label will display in the tooltip and legend.</p>
|
|
232
|
+
</Tooltip.Content>
|
|
233
|
+
</Tooltip>
|
|
234
|
+
}
|
|
235
|
+
value={label ? label : 'Suppressed'}
|
|
236
|
+
fieldName='label'
|
|
237
|
+
label='Suppressed Data Label'
|
|
238
|
+
placeholder=''
|
|
239
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
240
|
+
/>
|
|
241
|
+
<CheckBox
|
|
242
|
+
tooltip={
|
|
243
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
244
|
+
<Tooltip.Target>
|
|
245
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
246
|
+
</Tooltip.Target>
|
|
247
|
+
<Tooltip.Content>
|
|
248
|
+
<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>
|
|
249
|
+
</Tooltip.Content>
|
|
250
|
+
</Tooltip>
|
|
251
|
+
}
|
|
252
|
+
value={displayTooltip}
|
|
253
|
+
fieldName='displayTooltip'
|
|
254
|
+
label='Display in tooltips'
|
|
255
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
256
|
+
/>
|
|
257
|
+
<CheckBox
|
|
258
|
+
tooltip={
|
|
259
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
260
|
+
<Tooltip.Target>
|
|
261
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
262
|
+
</Tooltip.Target>
|
|
263
|
+
<Tooltip.Content>
|
|
264
|
+
<p>Deselecting "Display in Legend" indicates that you do not want to display suppressed data in the legend.</p>
|
|
265
|
+
</Tooltip.Content>
|
|
266
|
+
</Tooltip>
|
|
267
|
+
}
|
|
268
|
+
value={displayLegend}
|
|
269
|
+
fieldName='displayLegend'
|
|
270
|
+
label='Display in legend'
|
|
271
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
272
|
+
/>
|
|
273
|
+
<CheckBox
|
|
274
|
+
tooltip={
|
|
275
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
276
|
+
<Tooltip.Target>
|
|
277
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
278
|
+
</Tooltip.Target>
|
|
279
|
+
<Tooltip.Content>
|
|
280
|
+
<p>Deselecting "Display In Data Table" indicates that you do not want to display suppressed data in the data table.</p>
|
|
281
|
+
</Tooltip.Content>
|
|
282
|
+
</Tooltip>
|
|
283
|
+
}
|
|
284
|
+
value={displayTable}
|
|
285
|
+
fieldName='displayTable'
|
|
286
|
+
label='Display in table'
|
|
287
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
288
|
+
/>
|
|
289
|
+
</>
|
|
290
|
+
) : (
|
|
291
|
+
<>
|
|
292
|
+
<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} />
|
|
293
|
+
<Select value={column} initial='Select' fieldName='column' label='COLUMN WITH CONFIGURATION VALUE' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getColumnOptions()} />
|
|
294
|
+
<TextField
|
|
295
|
+
tooltip={
|
|
296
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
297
|
+
<Tooltip.Target>
|
|
298
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
299
|
+
</Tooltip.Target>
|
|
300
|
+
<Tooltip.Content>
|
|
301
|
+
<p>If 'Filled Circles' is selected as the style, this field is optional, and the style 'Filled Circles' will apply to all points within the associated series data.</p>
|
|
302
|
+
</Tooltip.Content>
|
|
303
|
+
</Tooltip>
|
|
304
|
+
}
|
|
305
|
+
value={value}
|
|
306
|
+
fieldName='value'
|
|
307
|
+
label='VALUE TO TRIGGER'
|
|
308
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
309
|
+
/>
|
|
310
|
+
<Select value={style} initial='Select' fieldName='style' label='Style' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getStyleOptions(type)} />
|
|
311
|
+
{style.includes('Circles') && <TextField className='number-narrow' type='number' value={circleSize} fieldName='circleSize' label='circle size' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />}
|
|
312
|
+
{style !== 'Filled Circles' && <TextField value={label} fieldName='label' label='Label' placeholder='' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />}
|
|
313
|
+
</>
|
|
314
|
+
)}
|
|
192
315
|
</div>
|
|
193
316
|
)
|
|
194
317
|
})}
|
|
195
318
|
|
|
196
319
|
<button type='button' onClick={addColumn} className='btn full-width'>
|
|
197
|
-
{config.visualizationType === 'Line'
|
|
320
|
+
{config.visualizationType === 'Line' ? 'Add Special Line' : config.visualizationType === 'Bar' ? ' Add Special Bar' : 'Add Special Bar/Line'}
|
|
198
321
|
</button>
|
|
199
322
|
</>
|
|
200
323
|
)
|
|
201
|
-
}
|
|
324
|
+
}
|
|
202
325
|
|
|
203
326
|
const EditorPanel = () => {
|
|
204
327
|
const {
|
|
@@ -220,13 +343,11 @@ const EditorPanel = () => {
|
|
|
220
343
|
lineOptions,
|
|
221
344
|
rawData,
|
|
222
345
|
highlight,
|
|
223
|
-
highlightReset
|
|
346
|
+
highlightReset,
|
|
347
|
+
dimensions
|
|
224
348
|
} = useContext<ChartContext>(ConfigContext)
|
|
225
349
|
|
|
226
350
|
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, unfilteredData)
|
|
227
|
-
|
|
228
|
-
const { twoColorPalettes, sequential, nonSequential } = useColorPalette(config, updateConfig)
|
|
229
|
-
|
|
230
351
|
const properties = { data, config }
|
|
231
352
|
const { leftMax, rightMax } = useMinMax(properties)
|
|
232
353
|
|
|
@@ -276,9 +397,6 @@ const EditorPanel = () => {
|
|
|
276
397
|
visHasDataSuppression
|
|
277
398
|
} = useEditorPermissions()
|
|
278
399
|
|
|
279
|
-
// argument acts as props
|
|
280
|
-
const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({ config, setConfig: updateConfig, filteredData: data, setFilteredData })
|
|
281
|
-
|
|
282
400
|
// when the visualization type changes we
|
|
283
401
|
// have to update the individual series type & axis details
|
|
284
402
|
// dataKey is unchanged here.
|
|
@@ -356,6 +474,12 @@ const EditorPanel = () => {
|
|
|
356
474
|
if (isDateScale(updatedConfig.xAxis) && !updatedConfig.xAxis.padding) {
|
|
357
475
|
updatedConfig.xAxis.padding = 6
|
|
358
476
|
}
|
|
477
|
+
// DEV-8008 - Remove Bar styling when Line is converted to Bar
|
|
478
|
+
if (updatedConfig.visualizationType === 'Line') {
|
|
479
|
+
updatedConfig.visualizationSubType = 'regular'
|
|
480
|
+
updatedConfig.barStyle = 'flat'
|
|
481
|
+
updatedConfig.isLollipopChart = false
|
|
482
|
+
}
|
|
359
483
|
}
|
|
360
484
|
|
|
361
485
|
const updateField = (section, subsection, fieldName, newValue) => {
|
|
@@ -389,13 +513,18 @@ const EditorPanel = () => {
|
|
|
389
513
|
return
|
|
390
514
|
}
|
|
391
515
|
|
|
392
|
-
|
|
516
|
+
const truthy = val => {
|
|
517
|
+
if (val === 0) return true // indexes can be used as keys
|
|
518
|
+
return !!val
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (section === 'columns' && truthy(subsection) && truthy(fieldName)) {
|
|
393
522
|
updateConfig({
|
|
394
523
|
...config,
|
|
395
|
-
|
|
396
|
-
...config
|
|
524
|
+
columns: {
|
|
525
|
+
...config.columns,
|
|
397
526
|
[subsection]: {
|
|
398
|
-
...config[
|
|
527
|
+
...config.columns[subsection],
|
|
399
528
|
[fieldName]: newValue
|
|
400
529
|
}
|
|
401
530
|
}
|
|
@@ -403,6 +532,8 @@ const EditorPanel = () => {
|
|
|
403
532
|
return
|
|
404
533
|
}
|
|
405
534
|
if (null === section && null === subsection) {
|
|
535
|
+
// special case that allows for updating the config object directly
|
|
536
|
+
if (!truthy(fieldName)) console.error('fieldName is required')
|
|
406
537
|
let updatedConfig = { ...config, [fieldName]: newValue }
|
|
407
538
|
enforceRestrictions(updatedConfig)
|
|
408
539
|
updateConfig(updatedConfig)
|
|
@@ -413,13 +544,13 @@ const EditorPanel = () => {
|
|
|
413
544
|
|
|
414
545
|
let sectionValue = isArray ? [...config[section], newValue] : { ...config[section], [fieldName]: newValue }
|
|
415
546
|
|
|
416
|
-
if (
|
|
547
|
+
if (truthy(subsection)) {
|
|
417
548
|
if (isArray) {
|
|
418
549
|
sectionValue = [...config[section]]
|
|
419
550
|
sectionValue[subsection] = { ...sectionValue[subsection], [fieldName]: newValue }
|
|
420
551
|
} else if (typeof newValue === 'string') {
|
|
421
552
|
sectionValue[subsection] = newValue
|
|
422
|
-
} else {
|
|
553
|
+
} else if (truthy(fieldName)) {
|
|
423
554
|
sectionValue = { ...config[section], [subsection]: { ...config[section][subsection], [fieldName]: newValue } }
|
|
424
555
|
}
|
|
425
556
|
}
|
|
@@ -432,6 +563,7 @@ const EditorPanel = () => {
|
|
|
432
563
|
}
|
|
433
564
|
|
|
434
565
|
const [displayPanel, setDisplayPanel] = useState(true)
|
|
566
|
+
const [displayViewportOverrides, setDisplayViewportOverrides] = useState(false)
|
|
435
567
|
|
|
436
568
|
if (loading) {
|
|
437
569
|
return null
|
|
@@ -457,30 +589,6 @@ const EditorPanel = () => {
|
|
|
457
589
|
})
|
|
458
590
|
}
|
|
459
591
|
|
|
460
|
-
const removeFilter = index => {
|
|
461
|
-
let filters = [...config.filters]
|
|
462
|
-
|
|
463
|
-
filters.splice(index, 1)
|
|
464
|
-
|
|
465
|
-
updateConfig({ ...config, filters })
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
const updateFilterProp = (name, index, value) => {
|
|
469
|
-
let filters = [...config.filters]
|
|
470
|
-
|
|
471
|
-
filters[index][name] = value
|
|
472
|
-
|
|
473
|
-
updateConfig({ ...config, filters })
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const addNewFilter = () => {
|
|
477
|
-
let filters = config.filters ? [...config.filters] : []
|
|
478
|
-
|
|
479
|
-
filters.push({ values: [] })
|
|
480
|
-
|
|
481
|
-
updateConfig({ ...config, filters })
|
|
482
|
-
}
|
|
483
|
-
|
|
484
592
|
const addNewSeries = seriesKey => {
|
|
485
593
|
let newSeries = config.series ? [...config.series] : []
|
|
486
594
|
let forecastingStages = Array.from(new Set(data.map(item => item[seriesKey])))
|
|
@@ -505,37 +613,6 @@ const EditorPanel = () => {
|
|
|
505
613
|
updateConfig({ ...config }, newData)
|
|
506
614
|
}
|
|
507
615
|
|
|
508
|
-
const removeSeries = seriesKey => {
|
|
509
|
-
let series = [...config.series]
|
|
510
|
-
let seriesIndex = -1
|
|
511
|
-
|
|
512
|
-
for (let i = 0; i < series.length; i++) {
|
|
513
|
-
if (series[i].dataKey === seriesKey) {
|
|
514
|
-
seriesIndex = i
|
|
515
|
-
break
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
if (seriesIndex !== -1) {
|
|
520
|
-
series.splice(seriesIndex, 1)
|
|
521
|
-
|
|
522
|
-
let newConfig = { ...config, series }
|
|
523
|
-
|
|
524
|
-
if (series.length === 0) {
|
|
525
|
-
delete newConfig.series
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
updateConfig(newConfig)
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
if (config.visualizationType === 'Paired Bar') {
|
|
532
|
-
updateConfig({
|
|
533
|
-
...config,
|
|
534
|
-
series: []
|
|
535
|
-
})
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
616
|
const addNewExclusion = exclusionKey => {
|
|
540
617
|
let newExclusion = [...config.exclusions.keys]
|
|
541
618
|
newExclusion.push(exclusionKey)
|
|
@@ -569,16 +646,6 @@ const EditorPanel = () => {
|
|
|
569
646
|
}
|
|
570
647
|
}
|
|
571
648
|
|
|
572
|
-
const getFilters = () => {
|
|
573
|
-
let columns = {}
|
|
574
|
-
|
|
575
|
-
unfilteredData.forEach(row => {
|
|
576
|
-
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
577
|
-
})
|
|
578
|
-
|
|
579
|
-
return Object.keys(columns)
|
|
580
|
-
}
|
|
581
|
-
|
|
582
649
|
const getColumns = (filter = true) => {
|
|
583
650
|
let columns = {}
|
|
584
651
|
unfilteredData.forEach(row => {
|
|
@@ -902,40 +969,8 @@ const EditorPanel = () => {
|
|
|
902
969
|
})
|
|
903
970
|
}
|
|
904
971
|
|
|
905
|
-
// prevents adding duplicates
|
|
906
|
-
const additionalColumns = Object.keys(config.columns).filter(value => {
|
|
907
|
-
const defaultCols = [config.xAxis.dataKey] // ['geo', 'navigate', 'primary', 'latitude', 'longitude']
|
|
908
|
-
|
|
909
|
-
if (true === defaultCols.includes(value)) {
|
|
910
|
-
return false
|
|
911
|
-
}
|
|
912
|
-
return true
|
|
913
|
-
})
|
|
914
|
-
|
|
915
|
-
// just adds a new column but not set to any data yet
|
|
916
|
-
const addAdditionalColumn = number => {
|
|
917
|
-
const columnKey = `additionalColumn${number}`
|
|
918
|
-
|
|
919
|
-
updateConfig({
|
|
920
|
-
...config,
|
|
921
|
-
columns: {
|
|
922
|
-
...config.columns,
|
|
923
|
-
[columnKey]: {
|
|
924
|
-
label: 'New Column',
|
|
925
|
-
dataTable: false,
|
|
926
|
-
tooltips: false,
|
|
927
|
-
prefix: '',
|
|
928
|
-
suffix: '',
|
|
929
|
-
forestPlot: false,
|
|
930
|
-
startingPoint: '0',
|
|
931
|
-
forestPlotAlignRight: false
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
})
|
|
935
|
-
}
|
|
936
|
-
|
|
937
972
|
const removeAdditionalColumn = columnName => {
|
|
938
|
-
const newColumns = config.columns
|
|
973
|
+
const newColumns = _.cloneDeep(config.columns)
|
|
939
974
|
|
|
940
975
|
delete newColumns[columnName]
|
|
941
976
|
|
|
@@ -1019,6 +1054,14 @@ const EditorPanel = () => {
|
|
|
1019
1054
|
updateConfig(updatedConfig)
|
|
1020
1055
|
}
|
|
1021
1056
|
|
|
1057
|
+
const updateViewportOverrides = (property, viewport, numTicks) => {
|
|
1058
|
+
const propertyObject = { ...config.xAxis[property] }
|
|
1059
|
+
propertyObject[viewport] = numTicks
|
|
1060
|
+
const updatedConfig = { ...config, xAxis: { ...config.xAxis, [property]: propertyObject } }
|
|
1061
|
+
|
|
1062
|
+
updateConfig(updatedConfig)
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1022
1065
|
const editorContextValues = {
|
|
1023
1066
|
addNewExclusion,
|
|
1024
1067
|
data,
|
|
@@ -1155,7 +1198,26 @@ const EditorPanel = () => {
|
|
|
1155
1198
|
{config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && !['Box Plot', 'Deviation Bar', 'Forest Plot'].includes(config.visualizationType) && (
|
|
1156
1199
|
<CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />
|
|
1157
1200
|
)}
|
|
1158
|
-
<TextField
|
|
1201
|
+
<TextField
|
|
1202
|
+
value={config.yAxis.numTicks}
|
|
1203
|
+
placeholder='Auto'
|
|
1204
|
+
type='number'
|
|
1205
|
+
section='yAxis'
|
|
1206
|
+
fieldName='numTicks'
|
|
1207
|
+
label='Number of ticks'
|
|
1208
|
+
className='number-narrow'
|
|
1209
|
+
tooltip={
|
|
1210
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1211
|
+
<Tooltip.Target>
|
|
1212
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1213
|
+
</Tooltip.Target>
|
|
1214
|
+
<Tooltip.Content>
|
|
1215
|
+
<p>Apporoximate number of ticks. Other factors such as space available and data may change the exact number of ticks used.</p>
|
|
1216
|
+
</Tooltip.Content>
|
|
1217
|
+
</Tooltip>
|
|
1218
|
+
}
|
|
1219
|
+
updateField={updateField}
|
|
1220
|
+
/>
|
|
1159
1221
|
<TextField
|
|
1160
1222
|
value={config.yAxis.size}
|
|
1161
1223
|
type='number'
|
|
@@ -1175,6 +1237,7 @@ const EditorPanel = () => {
|
|
|
1175
1237
|
</Tooltip>
|
|
1176
1238
|
}
|
|
1177
1239
|
/>
|
|
1240
|
+
<TextField value={config.yAxis.labelOffset} section='yAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />
|
|
1178
1241
|
{config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
|
|
1179
1242
|
{(config.orientation === 'vertical' || !config.isResponsiveTicks) && <TextField value={config.yAxis.tickRotation || 0} type='number' min={0} section='yAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
|
|
1180
1243
|
{config.isResponsiveTicks && config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && (
|
|
@@ -1202,7 +1265,6 @@ const EditorPanel = () => {
|
|
|
1202
1265
|
|
|
1203
1266
|
{/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
|
|
1204
1267
|
{/* <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
|
|
1205
|
-
{config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
|
|
1206
1268
|
{visSupportsValueAxisGridLines() && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Show Gridlines' updateField={updateField} />}
|
|
1207
1269
|
<CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
|
|
1208
1270
|
{config.yAxis.enablePadding && <TextField type='number' section='yAxis' fieldName='scalePadding' label='Padding Percentage' className='number-narrow' updateField={updateField} value={config.yAxis.scalePadding} />}
|
|
@@ -1210,7 +1272,23 @@ const EditorPanel = () => {
|
|
|
1210
1272
|
</>
|
|
1211
1273
|
)}
|
|
1212
1274
|
<span className='divider-heading'>Number Formatting</span>
|
|
1213
|
-
<CheckBox
|
|
1275
|
+
<CheckBox
|
|
1276
|
+
value={config.dataFormat.commas}
|
|
1277
|
+
section='dataFormat'
|
|
1278
|
+
fieldName='commas'
|
|
1279
|
+
label='Add commas'
|
|
1280
|
+
updateField={updateField}
|
|
1281
|
+
tooltip={
|
|
1282
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1283
|
+
<Tooltip.Target>
|
|
1284
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1285
|
+
</Tooltip.Target>
|
|
1286
|
+
<Tooltip.Content>
|
|
1287
|
+
<p>{`Selecting this option will add commas to the left value axis, tooltip hover, and data table.`}</p>
|
|
1288
|
+
</Tooltip.Content>
|
|
1289
|
+
</Tooltip>
|
|
1290
|
+
}
|
|
1291
|
+
/>
|
|
1214
1292
|
<CheckBox
|
|
1215
1293
|
value={config.dataFormat.abbreviated}
|
|
1216
1294
|
section='dataFormat'
|
|
@@ -1271,7 +1349,7 @@ const EditorPanel = () => {
|
|
|
1271
1349
|
{config.orientation === 'horizontal' ? ( // horizontal - x is vertical y is horizontal
|
|
1272
1350
|
<>
|
|
1273
1351
|
{visSupportsValueAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
|
|
1274
|
-
{visSupportsValueAxisLabels() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide
|
|
1352
|
+
{visSupportsValueAxisLabels() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Tick Labels' updateField={updateField} />}
|
|
1275
1353
|
{visSupportsValueAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
|
|
1276
1354
|
{visSupportsValueAxisMax() && <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />}
|
|
1277
1355
|
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
@@ -1289,7 +1367,7 @@ const EditorPanel = () => {
|
|
|
1289
1367
|
config.visualizationType !== 'Pie' && (
|
|
1290
1368
|
<>
|
|
1291
1369
|
<CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
1292
|
-
<CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide
|
|
1370
|
+
<CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Tick Labels' updateField={updateField} />
|
|
1293
1371
|
<CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1294
1372
|
|
|
1295
1373
|
<TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='left axis max value' placeholder='Auto' updateField={updateField} />
|
|
@@ -1611,7 +1689,7 @@ const EditorPanel = () => {
|
|
|
1611
1689
|
</div>
|
|
1612
1690
|
|
|
1613
1691
|
<CheckBox value={config.yAxis.rightHideAxis} section='yAxis' fieldName='rightHideAxis' label='Hide Axis' updateField={updateField} />
|
|
1614
|
-
<CheckBox value={config.yAxis.rightHideLabel} section='yAxis' fieldName='rightHideLabel' label='Hide
|
|
1692
|
+
<CheckBox value={config.yAxis.rightHideLabel} section='yAxis' fieldName='rightHideLabel' label='Hide Tick Labels' updateField={updateField} />
|
|
1615
1693
|
<CheckBox value={config.yAxis.rightHideTicks} section='yAxis' fieldName='rightHideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1616
1694
|
|
|
1617
1695
|
<TextField value={config.yAxis.max} section='yAxis' fieldName='rightMax' type='number' label='right axis max value' placeholder='Auto' updateField={updateField} />
|
|
@@ -1898,7 +1976,25 @@ const EditorPanel = () => {
|
|
|
1898
1976
|
}
|
|
1899
1977
|
updateField={updateField}
|
|
1900
1978
|
/>
|
|
1901
|
-
{
|
|
1979
|
+
{false && visHasBrushChart && (
|
|
1980
|
+
<CheckBox
|
|
1981
|
+
value={config.brush?.active}
|
|
1982
|
+
section='brush'
|
|
1983
|
+
fieldName='active'
|
|
1984
|
+
label='Brush Slider '
|
|
1985
|
+
updateField={updateField}
|
|
1986
|
+
tooltip={
|
|
1987
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1988
|
+
<Tooltip.Target>
|
|
1989
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
1990
|
+
</Tooltip.Target>
|
|
1991
|
+
<Tooltip.Content>
|
|
1992
|
+
<p>Use the brush slider to narrow down your data view to specific values along the axis. This tool is useful for examining detailed data segments within the larger dataset. </p>
|
|
1993
|
+
</Tooltip.Content>
|
|
1994
|
+
</Tooltip>
|
|
1995
|
+
}
|
|
1996
|
+
/>
|
|
1997
|
+
)}
|
|
1902
1998
|
|
|
1903
1999
|
{config.exclusions.active && (
|
|
1904
2000
|
<>
|
|
@@ -1938,12 +2034,101 @@ const EditorPanel = () => {
|
|
|
1938
2034
|
)}
|
|
1939
2035
|
|
|
1940
2036
|
{visSupportsDateCategoryNumTicks() && config.xAxis.type !== 'date-time' && config.xAxis.manual && (
|
|
1941
|
-
|
|
2037
|
+
<>
|
|
2038
|
+
<TextField
|
|
2039
|
+
value={config.xAxis.manualStep}
|
|
2040
|
+
placeholder='Auto'
|
|
2041
|
+
type='number'
|
|
2042
|
+
min={1}
|
|
2043
|
+
section='xAxis'
|
|
2044
|
+
fieldName='manualStep'
|
|
2045
|
+
label='Step count'
|
|
2046
|
+
className='number-narrow'
|
|
2047
|
+
updateField={updateField}
|
|
2048
|
+
tooltip={
|
|
2049
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2050
|
+
<Tooltip.Target>
|
|
2051
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2052
|
+
</Tooltip.Target>
|
|
2053
|
+
<Tooltip.Content>
|
|
2054
|
+
<p>Number of data points which are assigned a tick, starting from the right most data point. Value of 1 will show a tick at every data point, value of 2 will show a tick for every other, etc.</p>
|
|
2055
|
+
</Tooltip.Content>
|
|
2056
|
+
</Tooltip>
|
|
2057
|
+
}
|
|
2058
|
+
/>
|
|
2059
|
+
<div className='viewport-overrides'>
|
|
2060
|
+
<label>
|
|
2061
|
+
<button onClick={() => setDisplayViewportOverrides(!displayViewportOverrides)} className='edit-label'>
|
|
2062
|
+
Step Count: viewport overrides <span style={{ transform: `rotate(${displayViewportOverrides ? '90deg' : '0deg'})` }}>></span>
|
|
2063
|
+
</button>
|
|
2064
|
+
</label>
|
|
2065
|
+
{displayViewportOverrides && (
|
|
2066
|
+
<div className='edit-block'>
|
|
2067
|
+
{Object.keys(viewports).map(viewport => (
|
|
2068
|
+
<TextField
|
|
2069
|
+
key={`viewport-step-count-input-${viewport}`}
|
|
2070
|
+
value={config.xAxis.viewportStepCount ? config.xAxis.viewportStepCount[viewport] : undefined}
|
|
2071
|
+
placeholder='Auto'
|
|
2072
|
+
type='number'
|
|
2073
|
+
label={viewport}
|
|
2074
|
+
className='number-narrow'
|
|
2075
|
+
updateField={(section, fieldName, label, val) => updateViewportOverrides('viewportStepCount', viewport, val)}
|
|
2076
|
+
/>
|
|
2077
|
+
))}
|
|
2078
|
+
</div>
|
|
2079
|
+
)}
|
|
2080
|
+
</div>
|
|
2081
|
+
</>
|
|
1942
2082
|
)}
|
|
1943
2083
|
{visSupportsDateCategoryNumTicks() && (config.xAxis.type === 'date-time' || !config.xAxis.manual) && (
|
|
1944
|
-
|
|
2084
|
+
<>
|
|
2085
|
+
<TextField
|
|
2086
|
+
value={config.xAxis.numTicks}
|
|
2087
|
+
placeholder='Auto'
|
|
2088
|
+
type='number'
|
|
2089
|
+
min={1}
|
|
2090
|
+
section='xAxis'
|
|
2091
|
+
fieldName='numTicks'
|
|
2092
|
+
label='Number of ticks'
|
|
2093
|
+
className='number-narrow'
|
|
2094
|
+
updateField={updateField}
|
|
2095
|
+
tooltip={
|
|
2096
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2097
|
+
<Tooltip.Target>
|
|
2098
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2099
|
+
</Tooltip.Target>
|
|
2100
|
+
<Tooltip.Content>
|
|
2101
|
+
<p>Apporoximate number of ticks. Other factors such as space available and data may change the exact number of ticks used. To enforce an exact number of ticks, check "Manual Ticks" above.</p>
|
|
2102
|
+
</Tooltip.Content>
|
|
2103
|
+
</Tooltip>
|
|
2104
|
+
}
|
|
2105
|
+
/>
|
|
2106
|
+
<div className='viewport-overrides'>
|
|
2107
|
+
<label>
|
|
2108
|
+
<button onClick={() => setDisplayViewportOverrides(!displayViewportOverrides)} className='edit-label'>
|
|
2109
|
+
Number of ticks: viewport overrides <span style={{ transform: `rotate(${displayViewportOverrides ? '90deg' : '0deg'})` }}>></span>
|
|
2110
|
+
</button>
|
|
2111
|
+
</label>
|
|
2112
|
+
{displayViewportOverrides && (
|
|
2113
|
+
<div className='edit-block'>
|
|
2114
|
+
{Object.keys(viewports).map(viewport => (
|
|
2115
|
+
<TextField
|
|
2116
|
+
key={`viewport-num-ticks-input-${viewport}`}
|
|
2117
|
+
value={config.xAxis.viewportNumTicks ? config.xAxis.viewportNumTicks[viewport] : undefined}
|
|
2118
|
+
placeholder='Auto'
|
|
2119
|
+
type='number'
|
|
2120
|
+
label={viewport}
|
|
2121
|
+
className='number-narrow'
|
|
2122
|
+
updateField={(section, fieldName, label, val) => updateViewportOverrides('viewportNumTicks', viewport, val)}
|
|
2123
|
+
/>
|
|
2124
|
+
))}
|
|
2125
|
+
</div>
|
|
2126
|
+
)}
|
|
2127
|
+
</div>
|
|
2128
|
+
</>
|
|
1945
2129
|
)}
|
|
1946
2130
|
{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} />}
|
|
2131
|
+
<TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />
|
|
1947
2132
|
|
|
1948
2133
|
{/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
|
|
1949
2134
|
{/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
|
|
@@ -1983,12 +2168,12 @@ const EditorPanel = () => {
|
|
|
1983
2168
|
{config.orientation === 'horizontal' ? (
|
|
1984
2169
|
<>
|
|
1985
2170
|
{visSupportsDateCategoryAxisLine() && <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
|
|
1986
|
-
{visSupportsDateCategoryAxisLabel() && <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide
|
|
2171
|
+
{visSupportsDateCategoryAxisLabel() && <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Tick Labels' updateField={updateField} />}
|
|
1987
2172
|
</>
|
|
1988
2173
|
) : (
|
|
1989
2174
|
<>
|
|
1990
2175
|
{visSupportsDateCategoryAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
|
|
1991
|
-
{visSupportsDateCategoryAxisLabel() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide
|
|
2176
|
+
{visSupportsDateCategoryAxisLabel() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Tick Labels' updateField={updateField} />}
|
|
1992
2177
|
{visSupportsDateCategoryAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
|
|
1993
2178
|
</>
|
|
1994
2179
|
)}
|
|
@@ -2338,242 +2523,15 @@ const EditorPanel = () => {
|
|
|
2338
2523
|
</AccordionItem>
|
|
2339
2524
|
)}
|
|
2340
2525
|
<Panels.Regions name='Regions' />
|
|
2526
|
+
|
|
2341
2527
|
{/* Columns */}
|
|
2342
|
-
{config.visualizationType !== 'Box Plot' && (
|
|
2528
|
+
{config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Sankey' && (
|
|
2343
2529
|
<AccordionItem>
|
|
2344
2530
|
<AccordionItemHeading>
|
|
2345
2531
|
<AccordionItemButton>Columns</AccordionItemButton>
|
|
2346
2532
|
</AccordionItemHeading>
|
|
2347
2533
|
<AccordionItemPanel>
|
|
2348
|
-
{
|
|
2349
|
-
<fieldset className='primary-fieldset edit-block'>
|
|
2350
|
-
<label>
|
|
2351
|
-
<span className='edit-label'>
|
|
2352
|
-
Additional Columns
|
|
2353
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2354
|
-
<Tooltip.Target>
|
|
2355
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2356
|
-
</Tooltip.Target>
|
|
2357
|
-
<Tooltip.Content>
|
|
2358
|
-
<p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
|
|
2359
|
-
</Tooltip.Content>
|
|
2360
|
-
</Tooltip>
|
|
2361
|
-
</span>
|
|
2362
|
-
</label>
|
|
2363
|
-
{additionalColumns.map(val => (
|
|
2364
|
-
<fieldset className='edit-block' key={val}>
|
|
2365
|
-
<button
|
|
2366
|
-
className='remove-column'
|
|
2367
|
-
onClick={event => {
|
|
2368
|
-
event.preventDefault()
|
|
2369
|
-
removeAdditionalColumn(val)
|
|
2370
|
-
}}
|
|
2371
|
-
>
|
|
2372
|
-
Remove
|
|
2373
|
-
</button>
|
|
2374
|
-
<label>
|
|
2375
|
-
<span className='edit-label column-heading'>Column</span>
|
|
2376
|
-
<select
|
|
2377
|
-
value={config.columns[val] ? config.columns[val].name : getColumns()[0]}
|
|
2378
|
-
onChange={event => {
|
|
2379
|
-
editColumn(val, 'name', event.target.value)
|
|
2380
|
-
}}
|
|
2381
|
-
>
|
|
2382
|
-
{getColumns().map(option => (
|
|
2383
|
-
<option>{option}</option>
|
|
2384
|
-
))}
|
|
2385
|
-
</select>
|
|
2386
|
-
</label>
|
|
2387
|
-
<label>
|
|
2388
|
-
<span className='edit-label column-heading'>Associate to Series</span>
|
|
2389
|
-
<select
|
|
2390
|
-
value={config.columns[val] ? config.columns[val].series : ''}
|
|
2391
|
-
onChange={event => {
|
|
2392
|
-
editColumn(val, 'series', event.target.value)
|
|
2393
|
-
}}
|
|
2394
|
-
>
|
|
2395
|
-
<option value=''>Select series</option>
|
|
2396
|
-
{config.series.map(series => (
|
|
2397
|
-
<option>{series.dataKey}</option>
|
|
2398
|
-
))}
|
|
2399
|
-
</select>
|
|
2400
|
-
</label>
|
|
2401
|
-
<TextField value={config.columns[val].label} section='columns' subsection={val} fieldName='label' label='Label' updateField={updateField} />
|
|
2402
|
-
<ul className='column-edit'>
|
|
2403
|
-
<li className='three-col'>
|
|
2404
|
-
<TextField value={config.columns[val].prefix} section='columns' subsection={val} fieldName='prefix' label='Prefix' updateField={updateField} />
|
|
2405
|
-
<TextField value={config.columns[val].suffix} section='columns' subsection={val} fieldName='suffix' label='Suffix' updateField={updateField} />
|
|
2406
|
-
<TextField type='number' value={config.columns[val].roundToPlace} section='columns' subsection={val} fieldName='roundToPlace' label='Round' updateField={updateField} />
|
|
2407
|
-
</li>
|
|
2408
|
-
<li>
|
|
2409
|
-
<label className='checkbox'>
|
|
2410
|
-
<input
|
|
2411
|
-
type='checkbox'
|
|
2412
|
-
checked={config.columns[val].commas}
|
|
2413
|
-
onChange={event => {
|
|
2414
|
-
editColumn(val, 'commas', event.target.checked)
|
|
2415
|
-
}}
|
|
2416
|
-
/>
|
|
2417
|
-
<span className='edit-label'>Add Commas to Numbers</span>
|
|
2418
|
-
</label>
|
|
2419
|
-
</li>
|
|
2420
|
-
<li>
|
|
2421
|
-
{config.table.showVertical && (
|
|
2422
|
-
<label className='checkbox'>
|
|
2423
|
-
<input
|
|
2424
|
-
type='checkbox'
|
|
2425
|
-
checked={config.columns[val].dataTable}
|
|
2426
|
-
onChange={event => {
|
|
2427
|
-
editColumn(val, 'dataTable', event.target.checked)
|
|
2428
|
-
}}
|
|
2429
|
-
/>
|
|
2430
|
-
<span className='edit-label'>Show in Data Table</span>
|
|
2431
|
-
</label>
|
|
2432
|
-
)}
|
|
2433
|
-
</li>
|
|
2434
|
-
{config.visualizationType === 'Pie' && (
|
|
2435
|
-
<li>
|
|
2436
|
-
<label className='checkbox'>
|
|
2437
|
-
<input
|
|
2438
|
-
type='checkbox'
|
|
2439
|
-
checked={config.columns[val].showInViz}
|
|
2440
|
-
onChange={event => {
|
|
2441
|
-
editColumn(val, 'showInViz', event.target.checked)
|
|
2442
|
-
}}
|
|
2443
|
-
/>
|
|
2444
|
-
<span className='edit-label'>Show in Visualization</span>
|
|
2445
|
-
</label>
|
|
2446
|
-
</li>
|
|
2447
|
-
)}
|
|
2448
|
-
|
|
2449
|
-
{/* disable for now */}
|
|
2450
|
-
|
|
2451
|
-
<li>
|
|
2452
|
-
<label className='checkbox'>
|
|
2453
|
-
<input
|
|
2454
|
-
type='checkbox'
|
|
2455
|
-
checked={config.columns[val].tooltips || false}
|
|
2456
|
-
onChange={event => {
|
|
2457
|
-
updateSeriesTooltip(val, event.target.checked)
|
|
2458
|
-
}}
|
|
2459
|
-
/>
|
|
2460
|
-
<span className='edit-label'>Show in tooltip</span>
|
|
2461
|
-
</label>
|
|
2462
|
-
</li>
|
|
2463
|
-
|
|
2464
|
-
{config.visualizationType === 'Forest Plot' && (
|
|
2465
|
-
<>
|
|
2466
|
-
<li>
|
|
2467
|
-
<label className='checkbox'>
|
|
2468
|
-
<input
|
|
2469
|
-
type='checkbox'
|
|
2470
|
-
checked={config.columns[val].forestPlot || false}
|
|
2471
|
-
onChange={event => {
|
|
2472
|
-
editColumn(val, 'forestPlot', event.target.checked)
|
|
2473
|
-
}}
|
|
2474
|
-
/>
|
|
2475
|
-
<span className='edit-label'>Show in Forest Plot</span>
|
|
2476
|
-
</label>
|
|
2477
|
-
</li>
|
|
2478
|
-
<li>
|
|
2479
|
-
<label className='checkbox'>
|
|
2480
|
-
<input
|
|
2481
|
-
type='checkbox'
|
|
2482
|
-
checked={config.columns[val].forestPlotAlignRight || false}
|
|
2483
|
-
onChange={event => {
|
|
2484
|
-
editColumn(val, 'forestPlotAlignRight', event.target.checked)
|
|
2485
|
-
}}
|
|
2486
|
-
/>
|
|
2487
|
-
<span className='edit-label'>Align Right</span>
|
|
2488
|
-
</label>
|
|
2489
|
-
</li>
|
|
2490
|
-
|
|
2491
|
-
{!config.columns[val].forestPlotAlignRight && (
|
|
2492
|
-
<li>
|
|
2493
|
-
<label className='text'>
|
|
2494
|
-
<span className='edit-label'>Forest Plot Starting Point</span>
|
|
2495
|
-
<input
|
|
2496
|
-
type='number'
|
|
2497
|
-
value={config.columns[val].forestPlotStartingPoint || 0}
|
|
2498
|
-
onChange={event => {
|
|
2499
|
-
editColumn(val, 'forestPlotStartingPoint', event.target.value)
|
|
2500
|
-
}}
|
|
2501
|
-
/>
|
|
2502
|
-
</label>
|
|
2503
|
-
</li>
|
|
2504
|
-
)}
|
|
2505
|
-
</>
|
|
2506
|
-
)}
|
|
2507
|
-
</ul>
|
|
2508
|
-
</fieldset>
|
|
2509
|
-
))}
|
|
2510
|
-
<button
|
|
2511
|
-
className={'btn full-width'}
|
|
2512
|
-
onClick={event => {
|
|
2513
|
-
event.preventDefault()
|
|
2514
|
-
addAdditionalColumn(additionalColumns.length + 1)
|
|
2515
|
-
}}
|
|
2516
|
-
>
|
|
2517
|
-
Add Column
|
|
2518
|
-
</button>
|
|
2519
|
-
</fieldset>
|
|
2520
|
-
)}
|
|
2521
|
-
{'category' === config.legend.type && (
|
|
2522
|
-
<fieldset className='primary-fieldset edit-block'>
|
|
2523
|
-
<label>
|
|
2524
|
-
<span className='edit-label'>
|
|
2525
|
-
Additional Category
|
|
2526
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2527
|
-
<Tooltip.Target>
|
|
2528
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2529
|
-
</Tooltip.Target>
|
|
2530
|
-
<Tooltip.Content>
|
|
2531
|
-
<p>You can provide additional categories to ensure they appear in the legend</p>
|
|
2532
|
-
</Tooltip.Content>
|
|
2533
|
-
</Tooltip>
|
|
2534
|
-
</span>
|
|
2535
|
-
</label>
|
|
2536
|
-
{config.legend.additionalCategories &&
|
|
2537
|
-
config.legend.additionalCategories.map((val, i) => (
|
|
2538
|
-
<fieldset className='edit-block' key={val}>
|
|
2539
|
-
<button
|
|
2540
|
-
className='remove-column'
|
|
2541
|
-
onClick={event => {
|
|
2542
|
-
event.preventDefault()
|
|
2543
|
-
const updatedAdditionaCategories = [...config.legend.additionalCategories]
|
|
2544
|
-
updatedAdditionaCategories.splice(i, 1)
|
|
2545
|
-
updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
|
|
2546
|
-
}}
|
|
2547
|
-
>
|
|
2548
|
-
Remove
|
|
2549
|
-
</button>
|
|
2550
|
-
<TextField
|
|
2551
|
-
value={val}
|
|
2552
|
-
label='Category'
|
|
2553
|
-
section='legend'
|
|
2554
|
-
subsection={null}
|
|
2555
|
-
fieldName='additionalCategories'
|
|
2556
|
-
updateField={(section, subsection, fieldName, value) => {
|
|
2557
|
-
const updatedAdditionaCategories = [...config.legend.additionalCategories]
|
|
2558
|
-
updatedAdditionaCategories[i] = value
|
|
2559
|
-
updateField(section, subsection, fieldName, updatedAdditionaCategories)
|
|
2560
|
-
}}
|
|
2561
|
-
/>
|
|
2562
|
-
</fieldset>
|
|
2563
|
-
))}
|
|
2564
|
-
<button
|
|
2565
|
-
className={'btn full-width'}
|
|
2566
|
-
onClick={event => {
|
|
2567
|
-
event.preventDefault()
|
|
2568
|
-
const updatedAdditionaCategories = [...(config.legend.additionalCategories || [])]
|
|
2569
|
-
updatedAdditionaCategories.push('')
|
|
2570
|
-
updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
|
|
2571
|
-
}}
|
|
2572
|
-
>
|
|
2573
|
-
Add Category
|
|
2574
|
-
</button>
|
|
2575
|
-
</fieldset>
|
|
2576
|
-
)}
|
|
2534
|
+
<ColumnsEditor config={config} updateField={updateField} deleteColumn={removeAdditionalColumn} />{' '}
|
|
2577
2535
|
</AccordionItemPanel>
|
|
2578
2536
|
</AccordionItem>
|
|
2579
2537
|
)}
|
|
@@ -2613,6 +2571,23 @@ const EditorPanel = () => {
|
|
|
2613
2571
|
</Tooltip>
|
|
2614
2572
|
}
|
|
2615
2573
|
/>
|
|
2574
|
+
<CheckBox
|
|
2575
|
+
value={config.legend.hideSuppressedLabels}
|
|
2576
|
+
section='legend'
|
|
2577
|
+
fieldName='hideSuppressedLabels'
|
|
2578
|
+
label='Hide Suppressed Labels'
|
|
2579
|
+
updateField={updateField}
|
|
2580
|
+
tooltip={
|
|
2581
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2582
|
+
<Tooltip.Target>
|
|
2583
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2584
|
+
</Tooltip.Target>
|
|
2585
|
+
<Tooltip.Content>
|
|
2586
|
+
<p>Hiding suppressed labels will not override the 'Special Class' assigned to line chart indicating "suppressed" data in the Data Series Panel.</p>
|
|
2587
|
+
</Tooltip.Content>
|
|
2588
|
+
</Tooltip>
|
|
2589
|
+
}
|
|
2590
|
+
/>
|
|
2616
2591
|
{/* {config.visualizationType === 'Box Plot' &&
|
|
2617
2592
|
<>
|
|
2618
2593
|
<CheckBox value={config.boxplot.legend.displayHowToReadText} fieldName='displayHowToReadText' section='boxplot' subsection='legend' label='Display How To Read Text' updateField={updateField} />
|
|
@@ -2697,7 +2672,7 @@ const EditorPanel = () => {
|
|
|
2697
2672
|
{/* end: isolated values */}
|
|
2698
2673
|
|
|
2699
2674
|
<TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
|
|
2700
|
-
<Select value={config.legend
|
|
2675
|
+
<Select value={config.legend?.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
|
|
2701
2676
|
{config.legend.position === 'bottom' && (
|
|
2702
2677
|
<>
|
|
2703
2678
|
<CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />
|
|
@@ -2714,161 +2689,7 @@ const EditorPanel = () => {
|
|
|
2714
2689
|
<AccordionItemButton>Filters</AccordionItemButton>
|
|
2715
2690
|
</AccordionItemHeading>
|
|
2716
2691
|
<AccordionItemPanel>
|
|
2717
|
-
{config
|
|
2718
|
-
<>
|
|
2719
|
-
{/* prettier-ignore */}
|
|
2720
|
-
<Select
|
|
2721
|
-
value={config.filterBehavior}
|
|
2722
|
-
fieldName='filterBehavior'
|
|
2723
|
-
label='Filter Behavior'
|
|
2724
|
-
updateField={updateField}
|
|
2725
|
-
options={['Apply Button', 'Filter Change']}
|
|
2726
|
-
tooltip={
|
|
2727
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2728
|
-
<Tooltip.Target>
|
|
2729
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2730
|
-
</Tooltip.Target>
|
|
2731
|
-
<Tooltip.Content>
|
|
2732
|
-
<p>The Apply Button option changes the visualization when the user clicks "apply". The Filter Change option immediately changes the visualization when the selection is changed.</p>
|
|
2733
|
-
</Tooltip.Content>
|
|
2734
|
-
</Tooltip>
|
|
2735
|
-
}
|
|
2736
|
-
/>
|
|
2737
|
-
<br />
|
|
2738
|
-
</>
|
|
2739
|
-
)}
|
|
2740
|
-
{config.filters && (
|
|
2741
|
-
<ul className='filters-list'>
|
|
2742
|
-
{/* Whether filters should apply onChange or Apply Button */}
|
|
2743
|
-
|
|
2744
|
-
{config.filters.map((filter, index) => {
|
|
2745
|
-
if (filter.type === 'url') return <></>
|
|
2746
|
-
|
|
2747
|
-
return (
|
|
2748
|
-
<fieldset className='edit-block' key={index}>
|
|
2749
|
-
<button
|
|
2750
|
-
type='button'
|
|
2751
|
-
className='remove-column'
|
|
2752
|
-
onClick={() => {
|
|
2753
|
-
removeFilter(index)
|
|
2754
|
-
}}
|
|
2755
|
-
>
|
|
2756
|
-
Remove
|
|
2757
|
-
</button>
|
|
2758
|
-
<label>
|
|
2759
|
-
<span className='edit-label column-heading'>Filter</span>
|
|
2760
|
-
<select
|
|
2761
|
-
value={filter.columnName}
|
|
2762
|
-
onChange={e => {
|
|
2763
|
-
updateFilterProp('columnName', index, e.target.value)
|
|
2764
|
-
}}
|
|
2765
|
-
>
|
|
2766
|
-
<option value=''>- Select Option -</option>
|
|
2767
|
-
{getFilters().map((dataKey, index) => (
|
|
2768
|
-
<option value={dataKey} key={index}>
|
|
2769
|
-
{dataKey}
|
|
2770
|
-
</option>
|
|
2771
|
-
))}
|
|
2772
|
-
</select>
|
|
2773
|
-
</label>
|
|
2774
|
-
|
|
2775
|
-
<label>
|
|
2776
|
-
<span className='edit-showDropdown column-heading'>Show Filter Input</span>
|
|
2777
|
-
<input
|
|
2778
|
-
type='checkbox'
|
|
2779
|
-
checked={filter.showDropdown === undefined ? true : filter.showDropdown}
|
|
2780
|
-
onChange={e => {
|
|
2781
|
-
updateFilterProp('showDropdown', index, e.target.checked)
|
|
2782
|
-
}}
|
|
2783
|
-
/>
|
|
2784
|
-
</label>
|
|
2785
|
-
|
|
2786
|
-
<label>
|
|
2787
|
-
<span className='edit-label column-heading'>Filter Style</span>
|
|
2788
|
-
|
|
2789
|
-
<select
|
|
2790
|
-
value={filter.filterStyle}
|
|
2791
|
-
onChange={e => {
|
|
2792
|
-
updateFilterProp('filterStyle', index, e.target.value)
|
|
2793
|
-
}}
|
|
2794
|
-
>
|
|
2795
|
-
{filterStyleOptions.map((item, index) => {
|
|
2796
|
-
return (
|
|
2797
|
-
<option key={`filter-style-${index}`} value={item}>
|
|
2798
|
-
{item}
|
|
2799
|
-
</option>
|
|
2800
|
-
)
|
|
2801
|
-
})}
|
|
2802
|
-
</select>
|
|
2803
|
-
</label>
|
|
2804
|
-
<label>
|
|
2805
|
-
<span className='edit-label column-heading'>Label</span>
|
|
2806
|
-
<input
|
|
2807
|
-
type='text'
|
|
2808
|
-
value={filter.label}
|
|
2809
|
-
onChange={e => {
|
|
2810
|
-
updateFilterProp('label', index, e.target.value)
|
|
2811
|
-
}}
|
|
2812
|
-
/>
|
|
2813
|
-
</label>
|
|
2814
|
-
|
|
2815
|
-
<label>
|
|
2816
|
-
<span className='edit-label column-heading'>Default Value Set By Query String Parameter</span>
|
|
2817
|
-
<input
|
|
2818
|
-
type='text'
|
|
2819
|
-
value={filter.setByQueryParameter}
|
|
2820
|
-
onChange={e => {
|
|
2821
|
-
updateFilterProp('setByQueryParameter', index, e.target.value)
|
|
2822
|
-
}}
|
|
2823
|
-
/>
|
|
2824
|
-
</label>
|
|
2825
|
-
|
|
2826
|
-
<label>
|
|
2827
|
-
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
2828
|
-
<select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
|
|
2829
|
-
{filterOrderOptions.map((option, index) => {
|
|
2830
|
-
return (
|
|
2831
|
-
<option value={option.value} key={`filter-${index}`}>
|
|
2832
|
-
{option.label}
|
|
2833
|
-
</option>
|
|
2834
|
-
)
|
|
2835
|
-
})}
|
|
2836
|
-
</select>
|
|
2837
|
-
|
|
2838
|
-
{filter.order === 'cust' && (
|
|
2839
|
-
<DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
|
|
2840
|
-
<Droppable droppableId='filter_order'>
|
|
2841
|
-
{provided => (
|
|
2842
|
-
<ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
2843
|
-
{config.filters[index]?.values.map((value, index) => {
|
|
2844
|
-
return (
|
|
2845
|
-
<Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
|
|
2846
|
-
{(provided, snapshot) => (
|
|
2847
|
-
<li>
|
|
2848
|
-
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
2849
|
-
{value}
|
|
2850
|
-
</div>
|
|
2851
|
-
</li>
|
|
2852
|
-
)}
|
|
2853
|
-
</Draggable>
|
|
2854
|
-
)
|
|
2855
|
-
})}
|
|
2856
|
-
{provided.placeholder}
|
|
2857
|
-
</ul>
|
|
2858
|
-
)}
|
|
2859
|
-
</Droppable>
|
|
2860
|
-
</DragDropContext>
|
|
2861
|
-
)}
|
|
2862
|
-
</label>
|
|
2863
|
-
</fieldset>
|
|
2864
|
-
)
|
|
2865
|
-
})}
|
|
2866
|
-
</ul>
|
|
2867
|
-
)}
|
|
2868
|
-
{!config.filters && <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
|
|
2869
|
-
<button type='button' onClick={addNewFilter} className='btn full-width'>
|
|
2870
|
-
Add Filter
|
|
2871
|
-
</button>
|
|
2692
|
+
<VizFilterEditor config={config} updateField={updateField} rawData={rawData} />
|
|
2872
2693
|
</AccordionItemPanel>
|
|
2873
2694
|
</AccordionItem>
|
|
2874
2695
|
)}
|
|
@@ -2884,9 +2705,10 @@ const EditorPanel = () => {
|
|
|
2884
2705
|
</AccordionItemPanel>
|
|
2885
2706
|
</AccordionItem>
|
|
2886
2707
|
)}
|
|
2708
|
+
<Panels.Annotate name='Text Annotations' />
|
|
2887
2709
|
{/* {(config.visualizationType === 'Bar' || config.visualizationType === 'Line') && <Panels.DateHighlighting name='Date Highlighting' />} */}
|
|
2888
2710
|
</Accordion>
|
|
2889
|
-
{config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig}
|
|
2711
|
+
{config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig} config={config} convertStateToConfig={convertStateToConfig} />}
|
|
2890
2712
|
</Layout.Sidebar>
|
|
2891
2713
|
</ErrorBoundary>
|
|
2892
2714
|
</EditorPanelContext.Provider>
|