@cdc/chart 4.26.3 → 4.26.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONFIG.md +169 -0
- package/README.md +42 -17
- package/dist/cdcchart.js +34725 -33730
- package/examples/feature/bar/additional-column-tooltip.json +3 -3
- package/examples/feature/deviation/planet-deviation-config.json +2 -2
- package/examples/feature/paired-bar/paired-bar-example.json +2 -2
- package/examples/feature/tests-case-rate/case-rate-example-config.json +2 -2
- package/examples/feature/tests-covid/covid-confidence-example-config.json +2 -2
- package/examples/feature/tests-covid/covid-example-config.json +2 -2
- package/examples/feature/tests-cutoff/cutoff-example-config.json +2 -2
- package/examples/feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json +2 -2
- package/examples/metadata-variables.json +1 -1
- package/examples/minimal-example.json +24 -0
- package/examples/private/test2.json +35012 -0
- package/package.json +4 -4
- package/src/CdcChartComponent.tsx +9 -6
- package/src/_stories/{Chart.HTMLInDataTable.stories.tsx → Chart.HTMLInDataTable.smoke.stories.tsx} +10 -0
- package/src/_stories/Chart.Minimal.smoke.stories.tsx +25 -0
- package/src/_stories/{Chart.SmallMultiples.stories.tsx → Chart.SmallMultiples.smoke.stories.tsx} +17 -1
- package/src/_stories/{Chart.stories.tsx → Chart.smoke.stories.tsx} +12 -0
- package/src/_stories/{Chart.tooltip.stories.tsx → Chart.tooltip.smoke.stories.tsx} +68 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +88 -85
- package/src/_stories/ChartEditor.Editor.stories.tsx +23 -0
- package/src/_stories/ChartLine.DashedDates.smoke.stories.tsx +23 -0
- package/src/_stories/_mock/line_chart_dashed_dates.json +276 -0
- package/src/_stories/_mock/paired-bar-abbr.json +1 -1
- package/src/_stories/_mock/paired-bar.json +1 -1
- package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -1
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -2
- package/src/components/Axis/BottomAxis.tsx +1 -1
- package/src/components/Axis/LeftAxis.tsx +2 -4
- package/src/components/Axis/LeftAxisGridlines.tsx +1 -3
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +9 -5
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +9 -5
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +9 -5
- package/src/components/BarChart/components/BarChart.Vertical.tsx +9 -6
- package/src/components/BarChart/components/BarChart.tsx +2 -6
- package/src/components/BarChart/helpers/useBarChart.ts +1 -1
- package/src/components/BoxPlot/BoxPlot.Vertical.tsx +3 -3
- package/src/components/EditorPanel/EditorPanel.tsx +633 -908
- package/src/components/EditorPanel/EditorPanelContext.ts +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +216 -165
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +168 -116
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +154 -109
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +12 -26
- package/src/components/EditorPanel/useEditorPermissions.ts +1 -10
- package/src/components/Forecasting/Forecasting.tsx +2 -2
- package/src/components/HorizonChart/HorizonChart.tsx +10 -2
- package/src/components/HoverLine/HoverLine.tsx +6 -8
- package/src/components/Legend/Legend.Component.tsx +4 -4
- package/src/components/Legend/LegendGroup/LegendGroup.styles.css +5 -0
- package/src/components/Legend/LegendGroup/LegendGroup.tsx +3 -1
- package/src/components/Legend/helpers/index.ts +0 -2
- package/src/components/LineChart/LineChartProps.ts +1 -0
- package/src/components/LineChart/components/LineChart.BumpCircle.tsx +3 -2
- package/src/components/LineChart/index.tsx +11 -4
- package/src/components/LinearChart/VisualizationRenderer.tsx +11 -1
- package/src/components/LinearChart/tests/LinearChart.test.tsx +147 -0
- package/src/components/LinearChart.tsx +98 -41
- package/src/components/PairedBarChart.jsx +2 -2
- package/src/components/PieChart/PieChart.tsx +11 -9
- package/src/components/Regions/components/Regions.tsx +30 -20
- package/src/components/ScatterPlot/ScatterPlot.jsx +19 -17
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +1 -0
- package/src/components/Sparkline/components/SparkLine.tsx +1 -1
- package/src/components/WarmingStripes/WarmingStripes.tsx +5 -3
- package/src/data/initial-state.js +1 -0
- package/src/helpers/calculateLeftYAxisWidth.ts +193 -0
- package/src/helpers/tests/tooltipHelpers.test.ts +151 -0
- package/src/helpers/tooltipHelpers.ts +176 -0
- package/src/hooks/useHighlightedBars.ts +9 -16
- package/src/hooks/useProgrammaticTooltip.ts +16 -2
- package/src/hooks/useSmallMultipleSynchronization.ts +3 -4
- package/src/hooks/useTooltip.tsx +167 -38
- package/src/test/CdcChart.test.jsx +24 -0
- package/src/types/ChartConfig.ts +1 -0
- package/LICENSE +0 -201
- package/examples/chart-regression-2.json +0 -2360
- package/examples/feature/__data__/age-adjusted-rates.json +0 -1486
- package/examples/feature/__data__/city-temperature.json +0 -2198
- package/examples/feature/bar/Barchart_with_negative.json +0 -34
- package/examples/feature/boxplot/box-plot-data.json +0 -71
- package/examples/feature/boxplot/boxplot-data.json +0 -156
- package/examples/feature/combo/combochart-categories_are_numbers .json +0 -18
- package/examples/feature/forest-plot/log.json +0 -26
- package/examples/feature/tests-date-exclusions/date-exclusions-data.json +0 -162
- package/examples/region-issue.json +0 -2065
- package/examples/xaxis.json +0 -493
- /package/examples/{data → __data__}/data-with-metadata.json +0 -0
- /package/examples/feature/bar/{tall-data.json → __data__/tall-data.json} +0 -0
- /package/examples/feature/deviation/{planet-deviation-data.json → __data__/planet-deviation-data.json} +0 -0
- /package/examples/feature/paired-bar/{paired-bar-data.json → __data__/paired-bar-data.json} +0 -0
- /package/examples/feature/paired-bar/{paired-bar-formatted.json → __data__/paired-bar-formatted.json} +0 -0
- /package/examples/feature/tests-case-rate/{case-rate-example-data.json → __data__/case-rate-example-data.json} +0 -0
- /package/examples/feature/tests-covid/{covid-example-data-confidence.json → __data__/covid-example-data-confidence.json} +0 -0
- /package/examples/feature/tests-covid/{covid-example-data.json → __data__/covid-example-data.json} +0 -0
- /package/examples/feature/tests-cutoff/{cutoff-example-data.json → __data__/cutoff-example-data.json} +0 -0
- /package/examples/feature/tests-non-numerics/{planet-example-data-nonnumeric.json → __data__/planet-example-data-nonnumeric.json} +0 -0
- /package/src/_stories/{Chart.Anchors.stories.tsx → Chart.Anchors.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.BoxPlot.stories.tsx → Chart.BoxPlot.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.CI.stories.tsx → Chart.CI.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Combo.stories.tsx → Chart.Combo.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.CustomColors.stories.tsx → Chart.CustomColors.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Defaults.stories.tsx → Chart.Defaults.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.DynamicSeries.stories.tsx → Chart.DynamicSeries.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Filters.stories.tsx → Chart.Filters.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Forecast.stories.tsx → Chart.Forecast.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Legend.Gradient.stories.tsx → Chart.Legend.Gradient.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Patterns.stories.tsx → Chart.Patterns.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.PreserveDecimals.stories.tsx → Chart.PreserveDecimals.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Regions.Categorical.stories.tsx → Chart.Regions.Categorical.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Regions.DateScale.stories.tsx → Chart.Regions.DateScale.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Regions.DateTimeScale.stories.tsx → Chart.Regions.DateTimeScale.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.ScatterPlot.stories.tsx → Chart.ScatterPlot.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.SmallestLeftAxisMax.stories.tsx → Chart.SmallestLeftAxisMax.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartAnnotation.stories.tsx → ChartAnnotation.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartAxisLabels.stories.tsx → ChartAxisLabels.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartAxisTitles.stories.tsx → ChartAxisTitles.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartBrush.Matrix.Continuous.stories.tsx → ChartBrush.Matrix.Continuous.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartBrush.Matrix.Date.stories.tsx → ChartBrush.Matrix.Date.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartBrush.Matrix.DateTime.stories.tsx → ChartBrush.Matrix.DateTime.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartBrush.stories.tsx → ChartBrush.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartLine.QuadrantAngles.stories.tsx → ChartLine.QuadrantAngles.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartLine.Suppression.stories.tsx → ChartLine.Suppression.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartLine.Symbols.stories.tsx → ChartLine.Symbols.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartPrefixSuffix.stories.tsx → ChartPrefixSuffix.smoke.stories.tsx} +0 -0
- /package/src/_stories/{TechAdoptionWithLinks.stories.tsx → TechAdoptionWithLinks.smoke.stories.tsx} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState, useEffect, useCallback, memo, useContext, useMemo } from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import { Draggable } from '@hello-pangea/dnd'
|
|
3
3
|
import chroma from 'chroma-js'
|
|
4
|
-
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
4
|
+
import { getAutoDetectedDateParseFormat, isDateScale } from '@cdc/core/helpers/cove/date'
|
|
5
5
|
import {
|
|
6
6
|
Accordion,
|
|
7
7
|
AccordionItem,
|
|
@@ -16,10 +16,12 @@ import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
|
16
16
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
17
17
|
import ColumnsEditor from '@cdc/core/components/EditorPanel/ColumnsEditor'
|
|
18
18
|
import DataTableEditor from '@cdc/core/components/EditorPanel/DataTableEditor'
|
|
19
|
+
import GroupedList from '@cdc/core/components/EditorPanel/GroupedList'
|
|
19
20
|
import VizFilterEditor from '@cdc/core/components/EditorPanel/VizFilterEditor'
|
|
20
21
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
21
22
|
import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
22
23
|
import MultiSelect from '@cdc/core/components/MultiSelect'
|
|
24
|
+
import Button from '@cdc/core/components/elements/Button'
|
|
23
25
|
import { viewports } from '@cdc/core/helpers/getViewport'
|
|
24
26
|
import { approvedCurveTypes } from '@cdc/core/helpers/lineChartHelpers'
|
|
25
27
|
import PanelMarkup from '@cdc/core/components/EditorPanel/components/PanelMarkup'
|
|
@@ -158,324 +160,363 @@ const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, dat
|
|
|
158
160
|
updateConfig({ ...config, preliminaryData })
|
|
159
161
|
}
|
|
160
162
|
|
|
163
|
+
const moveColumn = (sourceIndex, destinationIndex) => {
|
|
164
|
+
const preliminaryData = config.preliminaryData ? [...config.preliminaryData] : []
|
|
165
|
+
const [movedItem] = preliminaryData.splice(sourceIndex, 1)
|
|
166
|
+
preliminaryData.splice(destinationIndex, 0, movedItem)
|
|
167
|
+
updateConfig({ ...config, preliminaryData })
|
|
168
|
+
}
|
|
169
|
+
|
|
161
170
|
return (
|
|
162
171
|
<>
|
|
163
|
-
|
|
164
|
-
config.preliminaryData
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
</Tooltip>
|
|
223
|
-
}
|
|
224
|
-
value={column}
|
|
225
|
-
initial='Select'
|
|
226
|
-
fieldName='column'
|
|
227
|
-
label='Add Data Series'
|
|
228
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
229
|
-
options={config.runtime?.seriesKeys}
|
|
230
|
-
/>
|
|
231
|
-
<TextField
|
|
232
|
-
value={value}
|
|
233
|
-
fieldName='value'
|
|
234
|
-
label='Suppressed Data Value'
|
|
235
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
236
|
-
/>
|
|
237
|
-
{(hasComboLineSeries || config.visualizationType === 'Line') && (
|
|
238
|
-
<>
|
|
239
|
-
<Select
|
|
240
|
-
tooltip={
|
|
241
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
242
|
-
<Tooltip.Target>
|
|
243
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
244
|
-
</Tooltip.Target>
|
|
245
|
-
<Tooltip.Content>
|
|
246
|
-
<p>
|
|
247
|
-
The recommended approach for presenting data is to include a footnote indicating any
|
|
248
|
-
data suppression.
|
|
249
|
-
</p>
|
|
250
|
-
</Tooltip.Content>
|
|
251
|
-
</Tooltip>
|
|
252
|
-
}
|
|
253
|
-
value={style}
|
|
254
|
-
initial='Select'
|
|
255
|
-
fieldName='style'
|
|
256
|
-
label={'suppression line style'}
|
|
257
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
258
|
-
options={getStyleOptions(type)}
|
|
259
|
-
/>
|
|
260
|
-
<CheckBox
|
|
261
|
-
value={hideLineStyle}
|
|
262
|
-
fieldName='hideLineStyle'
|
|
263
|
-
label='Hide Suppressed line Style'
|
|
264
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
265
|
-
/>
|
|
266
|
-
</>
|
|
267
|
-
)}
|
|
268
|
-
|
|
269
|
-
{(hasComboBarSeries || config.visualizationType === 'Bar') && (
|
|
270
|
-
<>
|
|
271
|
-
<Select
|
|
272
|
-
tooltip={
|
|
273
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
274
|
-
<Tooltip.Target>
|
|
275
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
276
|
-
</Tooltip.Target>
|
|
277
|
-
<Tooltip.Content>
|
|
278
|
-
<p>
|
|
279
|
-
A symbol is <i>required</i> to indicate suppressed data. We suggest "double
|
|
280
|
-
asterisks." If "double asterisks" are already used elsewhere (e.g., footnotes), please
|
|
281
|
-
select an alternative symbol from the menu to denote data suppression.
|
|
282
|
-
</p>
|
|
283
|
-
</Tooltip.Content>
|
|
284
|
-
</Tooltip>
|
|
285
|
-
}
|
|
286
|
-
value={symbol}
|
|
287
|
-
initial='Select'
|
|
288
|
-
fieldName='symbol'
|
|
289
|
-
label={config.visualizationType === 'Combo' ? 'suppression bar symbol' : 'suppression symbol'}
|
|
290
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
291
|
-
options={getSymbolOptions()}
|
|
292
|
-
/>
|
|
293
|
-
<CheckBox
|
|
294
|
-
value={hideBarSymbol}
|
|
295
|
-
fieldName='hideBarSymbol'
|
|
296
|
-
label='Hide Suppressed Bar Symbol '
|
|
297
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
298
|
-
/>
|
|
299
|
-
</>
|
|
300
|
-
)}
|
|
172
|
+
<GroupedList
|
|
173
|
+
items={config.preliminaryData}
|
|
174
|
+
label='Suppressed Data'
|
|
175
|
+
droppableId='chart-preliminary-data-order'
|
|
176
|
+
onDragEnd={({ source, destination }) => {
|
|
177
|
+
if (!destination || source.index === destination.index) return
|
|
178
|
+
moveColumn(source.index, destination.index)
|
|
179
|
+
}}
|
|
180
|
+
renderItem={(
|
|
181
|
+
{
|
|
182
|
+
displayGray,
|
|
183
|
+
circleSize,
|
|
184
|
+
column,
|
|
185
|
+
displayLegend,
|
|
186
|
+
displayTable,
|
|
187
|
+
displayTooltip,
|
|
188
|
+
label,
|
|
189
|
+
seriesKeys,
|
|
190
|
+
style,
|
|
191
|
+
symbol,
|
|
192
|
+
type,
|
|
193
|
+
value,
|
|
194
|
+
hideBarSymbol,
|
|
195
|
+
hideLineStyle
|
|
196
|
+
},
|
|
197
|
+
i
|
|
198
|
+
) => (
|
|
199
|
+
<Draggable key={`preliminaryData-${i}`} draggableId={`preliminaryData-${i}`} index={i}>
|
|
200
|
+
{(provided, snapshot) => (
|
|
201
|
+
<div
|
|
202
|
+
className={snapshot.isDragging ? 'currently-dragging' : ''}
|
|
203
|
+
style={provided.draggableProps.style}
|
|
204
|
+
ref={provided.innerRef}
|
|
205
|
+
{...provided.draggableProps}
|
|
206
|
+
{...provided.dragHandleProps}
|
|
207
|
+
>
|
|
208
|
+
<Accordion allowZeroExpanded>
|
|
209
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
210
|
+
<AccordionItemHeading className='series-item__title'>
|
|
211
|
+
<AccordionItemButton className='accordion__button'>
|
|
212
|
+
<Icon display='move' size={15} style={{ cursor: 'default' }} />
|
|
213
|
+
{type === 'suppression' ? 'Suppressed Data' : `Effect Data ${i + 1}`}
|
|
214
|
+
</AccordionItemButton>
|
|
215
|
+
</AccordionItemHeading>
|
|
216
|
+
<AccordionItemPanel>
|
|
217
|
+
<div className='series-item__panel-actions'>
|
|
218
|
+
<Button
|
|
219
|
+
type='button'
|
|
220
|
+
variant='danger'
|
|
221
|
+
size='sm'
|
|
222
|
+
className='grouped-list__remove'
|
|
223
|
+
onClick={event => {
|
|
224
|
+
event.preventDefault()
|
|
225
|
+
removeColumn(i)
|
|
226
|
+
}}
|
|
227
|
+
>
|
|
228
|
+
Remove
|
|
229
|
+
</Button>
|
|
230
|
+
</div>
|
|
301
231
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
</Tooltip.Target>
|
|
308
|
-
<Tooltip.Content>
|
|
309
|
-
<p>This label will display in the tooltip and legend.</p>
|
|
310
|
-
</Tooltip.Content>
|
|
311
|
-
</Tooltip>
|
|
312
|
-
}
|
|
313
|
-
value={label ? label : 'Suppressed'}
|
|
314
|
-
fieldName='label'
|
|
315
|
-
label='Suppressed Data Label'
|
|
316
|
-
placeholder=''
|
|
317
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
318
|
-
/>
|
|
319
|
-
<CheckBox
|
|
320
|
-
display={config.visualizationSubType === 'regular'}
|
|
321
|
-
tooltip={
|
|
322
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
323
|
-
<Tooltip.Target>
|
|
324
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
325
|
-
</Tooltip.Target>
|
|
326
|
-
<Tooltip.Content>
|
|
327
|
-
<p>
|
|
328
|
-
Deselecting the "Display In Tooltips" option prevents suppressed values from appearing in
|
|
329
|
-
tooltips.
|
|
330
|
-
</p>
|
|
331
|
-
</Tooltip.Content>
|
|
332
|
-
</Tooltip>
|
|
333
|
-
}
|
|
334
|
-
value={displayTooltip}
|
|
335
|
-
fieldName='displayTooltip'
|
|
336
|
-
label='Display in tooltips'
|
|
337
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
338
|
-
/>
|
|
339
|
-
<CheckBox
|
|
340
|
-
display={config.visualizationSubType === 'regular'}
|
|
341
|
-
tooltip={
|
|
342
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
343
|
-
<Tooltip.Target>
|
|
344
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
345
|
-
</Tooltip.Target>
|
|
346
|
-
<Tooltip.Content>
|
|
347
|
-
<p>
|
|
348
|
-
Deselecting "Display in Legend" indicates that you do not want to display suppressed data
|
|
349
|
-
in the legend.
|
|
350
|
-
</p>
|
|
351
|
-
</Tooltip.Content>
|
|
352
|
-
</Tooltip>
|
|
353
|
-
}
|
|
354
|
-
value={displayLegend}
|
|
355
|
-
fieldName='displayLegend'
|
|
356
|
-
label='Display in legend'
|
|
357
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
358
|
-
/>
|
|
359
|
-
<CheckBox
|
|
360
|
-
display={config.visualizationSubType === 'regular'}
|
|
361
|
-
tooltip={
|
|
362
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
363
|
-
<Tooltip.Target>
|
|
364
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
365
|
-
</Tooltip.Target>
|
|
366
|
-
<Tooltip.Content>
|
|
367
|
-
<p>
|
|
368
|
-
Deselecting "Display In Data Table" indicates that you do not want to display suppressed
|
|
369
|
-
data in the data table.
|
|
370
|
-
</p>
|
|
371
|
-
</Tooltip.Content>
|
|
372
|
-
</Tooltip>
|
|
373
|
-
}
|
|
374
|
-
value={displayTable}
|
|
375
|
-
fieldName='displayTable'
|
|
376
|
-
label='Display in table'
|
|
377
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
378
|
-
/>
|
|
379
|
-
<CheckBox
|
|
380
|
-
display={config.visualizationSubType === 'regular'}
|
|
381
|
-
tooltip={
|
|
382
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
383
|
-
<Tooltip.Target>
|
|
384
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
385
|
-
</Tooltip.Target>
|
|
386
|
-
<Tooltip.Content>
|
|
387
|
-
<p>Selecting this option will apply to chart, tooltip hover, legend, and data table.</p>
|
|
388
|
-
</Tooltip.Content>
|
|
389
|
-
</Tooltip>
|
|
390
|
-
}
|
|
391
|
-
value={displayGray}
|
|
392
|
-
fieldName='displayGray'
|
|
393
|
-
label='Highlight Suppressed Data In Gray'
|
|
394
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
395
|
-
/>
|
|
396
|
-
</>
|
|
397
|
-
) : (
|
|
398
|
-
<>
|
|
399
|
-
<label>
|
|
400
|
-
<span className='edit-label'>ASSOCIATE TO THESE SERIES</span>
|
|
401
|
-
<MultiSelect
|
|
402
|
-
fieldName='seriesKeys'
|
|
403
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
404
|
-
options={(config.runtime.lineSeriesKeys ?? config.runtime?.seriesKeys).map(c => ({
|
|
405
|
-
label: c,
|
|
406
|
-
value: c
|
|
407
|
-
}))}
|
|
408
|
-
selected={seriesKeys}
|
|
409
|
-
/>
|
|
410
|
-
</label>
|
|
411
|
-
<Select
|
|
412
|
-
value={column}
|
|
413
|
-
initial='Select'
|
|
414
|
-
fieldName='column'
|
|
415
|
-
label='COLUMN WITH CONFIGURATION VALUE'
|
|
416
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
417
|
-
options={getColumnOptions()}
|
|
418
|
-
/>
|
|
419
|
-
<TextField
|
|
420
|
-
tooltip={
|
|
421
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
422
|
-
<Tooltip.Target>
|
|
423
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
424
|
-
</Tooltip.Target>
|
|
425
|
-
<Tooltip.Content>
|
|
426
|
-
<p>
|
|
427
|
-
If 'Filled Circles' is selected as the style, this field is optional, and the style
|
|
428
|
-
'Filled Circles' will apply to all points within the associated series data.
|
|
429
|
-
</p>
|
|
430
|
-
</Tooltip.Content>
|
|
431
|
-
</Tooltip>
|
|
432
|
-
}
|
|
433
|
-
value={value}
|
|
434
|
-
fieldName='value'
|
|
435
|
-
label='VALUE TO TRIGGER'
|
|
436
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
437
|
-
/>
|
|
438
|
-
<Select
|
|
439
|
-
value={style}
|
|
440
|
-
initial='Select'
|
|
441
|
-
fieldName='style'
|
|
442
|
-
label='Style'
|
|
443
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
444
|
-
options={getStyleOptions(type)}
|
|
445
|
-
/>
|
|
446
|
-
{style.includes('Circles') && (
|
|
447
|
-
<TextField
|
|
448
|
-
className='number-narrow'
|
|
449
|
-
type='number'
|
|
450
|
-
value={circleSize}
|
|
451
|
-
fieldName='circleSize'
|
|
452
|
-
label='circle size'
|
|
453
|
-
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
454
|
-
/>
|
|
455
|
-
)}
|
|
456
|
-
{style !== 'Filled Circles' && (
|
|
457
|
-
<TextField
|
|
458
|
-
value={label}
|
|
459
|
-
fieldName='label'
|
|
460
|
-
label='Label'
|
|
461
|
-
placeholder=''
|
|
232
|
+
<Select
|
|
233
|
+
value={type}
|
|
234
|
+
initial={config.visualizationType == 'Bar' ? '' : 'Select'}
|
|
235
|
+
fieldName='type'
|
|
236
|
+
label='Type'
|
|
462
237
|
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
238
|
+
options={getTypeOptions()}
|
|
463
239
|
/>
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
240
|
+
{type === 'suppression' ? (
|
|
241
|
+
<>
|
|
242
|
+
<Select
|
|
243
|
+
tooltip={
|
|
244
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
245
|
+
<Tooltip.Target>
|
|
246
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
247
|
+
</Tooltip.Target>
|
|
248
|
+
<Tooltip.Content>
|
|
249
|
+
<p>
|
|
250
|
+
{' '}
|
|
251
|
+
Without a selected "Data Series", the suppression symbol will be applied for all
|
|
252
|
+
series in the current dataset visualization. However, choosing a specific "data
|
|
253
|
+
series" will isolate the suppression to that series.
|
|
254
|
+
</p>
|
|
255
|
+
</Tooltip.Content>
|
|
256
|
+
</Tooltip>
|
|
257
|
+
}
|
|
258
|
+
value={column}
|
|
259
|
+
initial='Select'
|
|
260
|
+
fieldName='column'
|
|
261
|
+
label='Add Data Series'
|
|
262
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
263
|
+
options={config.runtime?.seriesKeys}
|
|
264
|
+
/>
|
|
265
|
+
<TextField
|
|
266
|
+
value={value}
|
|
267
|
+
fieldName='value'
|
|
268
|
+
label='Suppressed Data Value'
|
|
269
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
270
|
+
/>
|
|
271
|
+
{(hasComboLineSeries || config.visualizationType === 'Line') && (
|
|
272
|
+
<>
|
|
273
|
+
<Select
|
|
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>
|
|
281
|
+
The recommended approach for presenting data is to include a footnote indicating
|
|
282
|
+
any data suppression.
|
|
283
|
+
</p>
|
|
284
|
+
</Tooltip.Content>
|
|
285
|
+
</Tooltip>
|
|
286
|
+
}
|
|
287
|
+
value={style}
|
|
288
|
+
initial='Select'
|
|
289
|
+
fieldName='style'
|
|
290
|
+
label={'suppression line style'}
|
|
291
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
292
|
+
options={getStyleOptions(type)}
|
|
293
|
+
/>
|
|
294
|
+
<CheckBox
|
|
295
|
+
value={hideLineStyle}
|
|
296
|
+
fieldName='hideLineStyle'
|
|
297
|
+
label='Hide Suppressed line Style'
|
|
298
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
299
|
+
/>
|
|
300
|
+
</>
|
|
301
|
+
)}
|
|
302
|
+
|
|
303
|
+
{(hasComboBarSeries || config.visualizationType === 'Bar') && (
|
|
304
|
+
<>
|
|
305
|
+
<Select
|
|
306
|
+
tooltip={
|
|
307
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
308
|
+
<Tooltip.Target>
|
|
309
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
310
|
+
</Tooltip.Target>
|
|
311
|
+
<Tooltip.Content>
|
|
312
|
+
<p>
|
|
313
|
+
A symbol is <i>required</i> to indicate suppressed data. We suggest "double
|
|
314
|
+
asterisks." If "double asterisks" are already used elsewhere (e.g., footnotes),
|
|
315
|
+
please select an alternative symbol from the menu to denote data suppression.
|
|
316
|
+
</p>
|
|
317
|
+
</Tooltip.Content>
|
|
318
|
+
</Tooltip>
|
|
319
|
+
}
|
|
320
|
+
value={symbol}
|
|
321
|
+
initial='Select'
|
|
322
|
+
fieldName='symbol'
|
|
323
|
+
label={
|
|
324
|
+
config.visualizationType === 'Combo' ? 'suppression bar symbol' : 'suppression symbol'
|
|
325
|
+
}
|
|
326
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
327
|
+
options={getSymbolOptions()}
|
|
328
|
+
/>
|
|
329
|
+
<CheckBox
|
|
330
|
+
value={hideBarSymbol}
|
|
331
|
+
fieldName='hideBarSymbol'
|
|
332
|
+
label='Hide Suppressed Bar Symbol '
|
|
333
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
334
|
+
/>
|
|
335
|
+
</>
|
|
336
|
+
)}
|
|
337
|
+
|
|
338
|
+
<TextField
|
|
339
|
+
tooltip={
|
|
340
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
341
|
+
<Tooltip.Target>
|
|
342
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
343
|
+
</Tooltip.Target>
|
|
344
|
+
<Tooltip.Content>
|
|
345
|
+
<p>This label will display in the tooltip and legend.</p>
|
|
346
|
+
</Tooltip.Content>
|
|
347
|
+
</Tooltip>
|
|
348
|
+
}
|
|
349
|
+
value={label ? label : 'Suppressed'}
|
|
350
|
+
fieldName='label'
|
|
351
|
+
label='Suppressed Data Label'
|
|
352
|
+
placeholder=''
|
|
353
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
354
|
+
/>
|
|
355
|
+
<CheckBox
|
|
356
|
+
display={config.visualizationSubType === 'regular'}
|
|
357
|
+
tooltip={
|
|
358
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
359
|
+
<Tooltip.Target>
|
|
360
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
361
|
+
</Tooltip.Target>
|
|
362
|
+
<Tooltip.Content>
|
|
363
|
+
<p>
|
|
364
|
+
Deselecting the "Display In Tooltips" option prevents suppressed values from
|
|
365
|
+
appearing in tooltips.
|
|
366
|
+
</p>
|
|
367
|
+
</Tooltip.Content>
|
|
368
|
+
</Tooltip>
|
|
369
|
+
}
|
|
370
|
+
value={displayTooltip}
|
|
371
|
+
fieldName='displayTooltip'
|
|
372
|
+
label='Display in tooltips'
|
|
373
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
374
|
+
/>
|
|
375
|
+
<CheckBox
|
|
376
|
+
display={config.visualizationSubType === 'regular'}
|
|
377
|
+
tooltip={
|
|
378
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
379
|
+
<Tooltip.Target>
|
|
380
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
381
|
+
</Tooltip.Target>
|
|
382
|
+
<Tooltip.Content>
|
|
383
|
+
<p>
|
|
384
|
+
Deselecting "Display in Legend" indicates that you do not want to display suppressed
|
|
385
|
+
data in the legend.
|
|
386
|
+
</p>
|
|
387
|
+
</Tooltip.Content>
|
|
388
|
+
</Tooltip>
|
|
389
|
+
}
|
|
390
|
+
value={displayLegend}
|
|
391
|
+
fieldName='displayLegend'
|
|
392
|
+
label='Display in legend'
|
|
393
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
394
|
+
/>
|
|
395
|
+
<CheckBox
|
|
396
|
+
display={config.visualizationSubType === 'regular'}
|
|
397
|
+
tooltip={
|
|
398
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
399
|
+
<Tooltip.Target>
|
|
400
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
401
|
+
</Tooltip.Target>
|
|
402
|
+
<Tooltip.Content>
|
|
403
|
+
<p>
|
|
404
|
+
Deselecting "Display In Data Table" indicates that you do not want to display
|
|
405
|
+
suppressed data in the data table.
|
|
406
|
+
</p>
|
|
407
|
+
</Tooltip.Content>
|
|
408
|
+
</Tooltip>
|
|
409
|
+
}
|
|
410
|
+
value={displayTable}
|
|
411
|
+
fieldName='displayTable'
|
|
412
|
+
label='Display in table'
|
|
413
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
414
|
+
/>
|
|
415
|
+
<CheckBox
|
|
416
|
+
display={config.visualizationSubType === 'regular'}
|
|
417
|
+
tooltip={
|
|
418
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
419
|
+
<Tooltip.Target>
|
|
420
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
421
|
+
</Tooltip.Target>
|
|
422
|
+
<Tooltip.Content>
|
|
423
|
+
<p>
|
|
424
|
+
Selecting this option will apply to chart, tooltip hover, legend, and data table.
|
|
425
|
+
</p>
|
|
426
|
+
</Tooltip.Content>
|
|
427
|
+
</Tooltip>
|
|
428
|
+
}
|
|
429
|
+
value={displayGray}
|
|
430
|
+
fieldName='displayGray'
|
|
431
|
+
label='Highlight Suppressed Data In Gray'
|
|
432
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
433
|
+
/>
|
|
434
|
+
</>
|
|
435
|
+
) : (
|
|
436
|
+
<>
|
|
437
|
+
<label>
|
|
438
|
+
<span className='edit-label'>ASSOCIATE TO THESE SERIES</span>
|
|
439
|
+
<MultiSelect
|
|
440
|
+
fieldName='seriesKeys'
|
|
441
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
442
|
+
options={(config.runtime.lineSeriesKeys ?? config.runtime?.seriesKeys).map(c => ({
|
|
443
|
+
label: c,
|
|
444
|
+
value: c
|
|
445
|
+
}))}
|
|
446
|
+
selected={seriesKeys}
|
|
447
|
+
/>
|
|
448
|
+
</label>
|
|
449
|
+
<Select
|
|
450
|
+
value={column}
|
|
451
|
+
initial='Select'
|
|
452
|
+
fieldName='column'
|
|
453
|
+
label='COLUMN WITH CONFIGURATION VALUE'
|
|
454
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
455
|
+
options={getColumnOptions()}
|
|
456
|
+
/>
|
|
457
|
+
<TextField
|
|
458
|
+
tooltip={
|
|
459
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
460
|
+
<Tooltip.Target>
|
|
461
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
462
|
+
</Tooltip.Target>
|
|
463
|
+
<Tooltip.Content>
|
|
464
|
+
<p>
|
|
465
|
+
If 'Filled Circles' is selected as the style, this field is optional, and the style
|
|
466
|
+
'Filled Circles' will apply to all points within the associated series data.
|
|
467
|
+
</p>
|
|
468
|
+
</Tooltip.Content>
|
|
469
|
+
</Tooltip>
|
|
470
|
+
}
|
|
471
|
+
value={value}
|
|
472
|
+
fieldName='value'
|
|
473
|
+
label='VALUE TO TRIGGER'
|
|
474
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
475
|
+
/>
|
|
476
|
+
<Select
|
|
477
|
+
value={style}
|
|
478
|
+
initial='Select'
|
|
479
|
+
fieldName='style'
|
|
480
|
+
label='Style'
|
|
481
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
482
|
+
options={getStyleOptions(type)}
|
|
483
|
+
/>
|
|
484
|
+
{style?.includes('Circles') && (
|
|
485
|
+
<TextField
|
|
486
|
+
className='number-narrow'
|
|
487
|
+
type='number'
|
|
488
|
+
value={circleSize}
|
|
489
|
+
fieldName='circleSize'
|
|
490
|
+
label='circle size'
|
|
491
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
492
|
+
/>
|
|
493
|
+
)}
|
|
494
|
+
{style !== 'Filled Circles' && (
|
|
495
|
+
<TextField
|
|
496
|
+
value={label}
|
|
497
|
+
fieldName='label'
|
|
498
|
+
label='Label'
|
|
499
|
+
placeholder=''
|
|
500
|
+
updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
|
|
501
|
+
/>
|
|
502
|
+
)}
|
|
503
|
+
</>
|
|
504
|
+
)}
|
|
505
|
+
</AccordionItemPanel>
|
|
506
|
+
</AccordionItem>
|
|
507
|
+
</Accordion>
|
|
467
508
|
</div>
|
|
468
|
-
)
|
|
469
|
-
|
|
509
|
+
)}
|
|
510
|
+
</Draggable>
|
|
470
511
|
)}
|
|
471
|
-
|
|
472
|
-
<
|
|
512
|
+
/>
|
|
513
|
+
<Button type='button' variant='editor-primary' onClick={addColumn}>
|
|
473
514
|
{config.visualizationType === 'Line'
|
|
474
515
|
? 'Add Special Line'
|
|
475
516
|
: config.visualizationType === 'Bar'
|
|
476
517
|
? ' Add Special Bar'
|
|
477
518
|
: 'Add Special Bar/Line'}
|
|
478
|
-
</
|
|
519
|
+
</Button>
|
|
479
520
|
</>
|
|
480
521
|
)
|
|
481
522
|
}
|
|
@@ -486,6 +527,158 @@ interface CategoricalAxisProps {
|
|
|
486
527
|
display: boolean
|
|
487
528
|
}
|
|
488
529
|
|
|
530
|
+
type AxisAnchorEditorProps = {
|
|
531
|
+
axisKey: 'xAxis' | 'yAxis'
|
|
532
|
+
config: ChartConfig
|
|
533
|
+
lineOptions: { value: string; label?: string }[]
|
|
534
|
+
updateConfig: Function
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
const AxisAnchorEditor: React.FC<AxisAnchorEditorProps> = ({ axisKey, config, lineOptions, updateConfig }) => {
|
|
538
|
+
const anchors = config[axisKey]?.anchors || []
|
|
539
|
+
|
|
540
|
+
const updateAnchors = (nextAnchors: Anchor[]) => {
|
|
541
|
+
updateConfig({
|
|
542
|
+
...config,
|
|
543
|
+
[axisKey]: {
|
|
544
|
+
...config[axisKey],
|
|
545
|
+
anchors: nextAnchors
|
|
546
|
+
}
|
|
547
|
+
})
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const updateAnchorField = (index: number, field: keyof Anchor, value: string) => {
|
|
551
|
+
const copiedAnchors = [...anchors]
|
|
552
|
+
copiedAnchors[index] = {
|
|
553
|
+
...copiedAnchors[index],
|
|
554
|
+
[field]: value
|
|
555
|
+
}
|
|
556
|
+
updateAnchors(copiedAnchors)
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const removeAnchor = (index: number) => {
|
|
560
|
+
const copiedAnchors = [...anchors]
|
|
561
|
+
copiedAnchors.splice(index, 1)
|
|
562
|
+
updateAnchors(copiedAnchors)
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const addAnchor = () => {
|
|
566
|
+
updateAnchors([...anchors, {} as Anchor])
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const reorderAnchors = (sourceIndex: number, destinationIndex: number) => {
|
|
570
|
+
const copiedAnchors = [...anchors]
|
|
571
|
+
const [movedAnchor] = copiedAnchors.splice(sourceIndex, 1)
|
|
572
|
+
copiedAnchors.splice(destinationIndex, 0, movedAnchor)
|
|
573
|
+
updateAnchors(copiedAnchors)
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
return (
|
|
577
|
+
<>
|
|
578
|
+
<GroupedList
|
|
579
|
+
items={anchors}
|
|
580
|
+
label='Anchors'
|
|
581
|
+
droppableId={`${axisKey}-anchors-order`}
|
|
582
|
+
onDragEnd={({ source, destination }) => {
|
|
583
|
+
if (!destination || source.index === destination.index) return
|
|
584
|
+
reorderAnchors(source.index, destination.index)
|
|
585
|
+
}}
|
|
586
|
+
renderItem={(anchor, index) => (
|
|
587
|
+
<Draggable key={`${axisKey}-anchor-${index}`} draggableId={`${axisKey}-anchor-${index}`} index={index}>
|
|
588
|
+
{(provided, snapshot) => (
|
|
589
|
+
<div
|
|
590
|
+
ref={provided.innerRef}
|
|
591
|
+
{...provided.draggableProps}
|
|
592
|
+
{...provided.dragHandleProps}
|
|
593
|
+
className={snapshot.isDragging ? 'currently-dragging' : ''}
|
|
594
|
+
style={provided.draggableProps.style}
|
|
595
|
+
>
|
|
596
|
+
<Accordion allowZeroExpanded>
|
|
597
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
598
|
+
<AccordionItemHeading className='series-item__title'>
|
|
599
|
+
<AccordionItemButton className='accordion__button'>
|
|
600
|
+
<Icon display='move' size={15} style={{ cursor: 'default' }} />
|
|
601
|
+
{`Anchor ${index + 1}`}
|
|
602
|
+
</AccordionItemButton>
|
|
603
|
+
</AccordionItemHeading>
|
|
604
|
+
<AccordionItemPanel>
|
|
605
|
+
<div className='series-item__panel-actions'>
|
|
606
|
+
<Button
|
|
607
|
+
type='button'
|
|
608
|
+
variant='danger'
|
|
609
|
+
size='sm'
|
|
610
|
+
className='grouped-list__remove'
|
|
611
|
+
onClick={e => {
|
|
612
|
+
e.preventDefault()
|
|
613
|
+
removeAnchor(index)
|
|
614
|
+
}}
|
|
615
|
+
>
|
|
616
|
+
Remove
|
|
617
|
+
</Button>
|
|
618
|
+
</div>
|
|
619
|
+
<label>
|
|
620
|
+
<span>Anchor Value</span>
|
|
621
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
622
|
+
<Tooltip.Target>
|
|
623
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
624
|
+
</Tooltip.Target>
|
|
625
|
+
<Tooltip.Content>
|
|
626
|
+
<p>Enter the value as its shown in the data column</p>
|
|
627
|
+
</Tooltip.Content>
|
|
628
|
+
</Tooltip>
|
|
629
|
+
<input
|
|
630
|
+
type='text'
|
|
631
|
+
value={anchor?.value || ''}
|
|
632
|
+
onChange={e => {
|
|
633
|
+
e.preventDefault()
|
|
634
|
+
updateAnchorField(index, 'value', e.target.value)
|
|
635
|
+
}}
|
|
636
|
+
/>
|
|
637
|
+
</label>
|
|
638
|
+
|
|
639
|
+
<label>
|
|
640
|
+
<span>Anchor Color</span>
|
|
641
|
+
<input
|
|
642
|
+
type='text'
|
|
643
|
+
value={anchor?.color || ''}
|
|
644
|
+
onChange={e => {
|
|
645
|
+
e.preventDefault()
|
|
646
|
+
updateAnchorField(index, 'color', e.target.value)
|
|
647
|
+
}}
|
|
648
|
+
/>
|
|
649
|
+
</label>
|
|
650
|
+
|
|
651
|
+
<Select
|
|
652
|
+
value={anchor?.lineStyle || ''}
|
|
653
|
+
label='Anchor Line Style'
|
|
654
|
+
onChange={e => updateAnchorField(index, 'lineStyle', e.target.value)}
|
|
655
|
+
options={[
|
|
656
|
+
{ value: '', label: 'Select' },
|
|
657
|
+
...lineOptions.map(line => ({ value: line.value, label: line.value }))
|
|
658
|
+
]}
|
|
659
|
+
/>
|
|
660
|
+
</AccordionItemPanel>
|
|
661
|
+
</AccordionItem>
|
|
662
|
+
</Accordion>
|
|
663
|
+
</div>
|
|
664
|
+
)}
|
|
665
|
+
</Draggable>
|
|
666
|
+
)}
|
|
667
|
+
/>
|
|
668
|
+
|
|
669
|
+
<Button
|
|
670
|
+
variant='editor-primary'
|
|
671
|
+
onClick={e => {
|
|
672
|
+
e.preventDefault()
|
|
673
|
+
addAnchor()
|
|
674
|
+
}}
|
|
675
|
+
>
|
|
676
|
+
Add Anchor
|
|
677
|
+
</Button>
|
|
678
|
+
</>
|
|
679
|
+
)
|
|
680
|
+
}
|
|
681
|
+
|
|
489
682
|
const CategoricalAxis: React.FC<CategoricalAxisProps> = ({ config, updateConfig, display }) => {
|
|
490
683
|
const maxHeight = config?.yAxis?.maxValue
|
|
491
684
|
|
|
@@ -547,7 +740,7 @@ const CategoricalAxis: React.FC<CategoricalAxisProps> = ({ config, updateConfig,
|
|
|
547
740
|
return (
|
|
548
741
|
<div key={`preliminaryData-${i}`} className='edit-block'>
|
|
549
742
|
<p>Axis Category {i + 1}</p>
|
|
550
|
-
<
|
|
743
|
+
<Button
|
|
551
744
|
type='button'
|
|
552
745
|
className='btn btn-danger'
|
|
553
746
|
onClick={event => {
|
|
@@ -556,7 +749,7 @@ const CategoricalAxis: React.FC<CategoricalAxisProps> = ({ config, updateConfig,
|
|
|
556
749
|
}}
|
|
557
750
|
>
|
|
558
751
|
Remove
|
|
559
|
-
</
|
|
752
|
+
</Button>
|
|
560
753
|
<TextField
|
|
561
754
|
tooltip={
|
|
562
755
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
@@ -602,9 +795,9 @@ const CategoricalAxis: React.FC<CategoricalAxisProps> = ({ config, updateConfig,
|
|
|
602
795
|
)
|
|
603
796
|
})}
|
|
604
797
|
|
|
605
|
-
<
|
|
798
|
+
<Button type='button' variant='editor-primary' onClick={addColumn}>
|
|
606
799
|
Add Axis Category
|
|
607
|
-
</
|
|
800
|
+
</Button>
|
|
608
801
|
</>
|
|
609
802
|
)
|
|
610
803
|
}
|
|
@@ -725,7 +918,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
725
918
|
}
|
|
726
919
|
}, [config.visualizationType])
|
|
727
920
|
|
|
728
|
-
const { hasRightAxis } = useRightAxis({ config: config, yMax:
|
|
921
|
+
const { hasRightAxis } = useRightAxis({ config: config, yMax: 0, data: config.data, updateConfig })
|
|
729
922
|
|
|
730
923
|
const getItemStyle = (isDragging, draggableStyle) => ({
|
|
731
924
|
...draggableStyle
|
|
@@ -774,6 +967,17 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
774
967
|
}
|
|
775
968
|
|
|
776
969
|
const updateField = updateFieldFactory(config, updateConfig)
|
|
970
|
+
const getAutoDetectedXAxisDateParseFormat = (dataKey = config.xAxis.dataKey, axisType = config.xAxis.type) => {
|
|
971
|
+
const hasExistingDateParseFormat =
|
|
972
|
+
typeof config.xAxis.dateParseFormat === 'string' && config.xAxis.dateParseFormat.trim() !== ''
|
|
973
|
+
|
|
974
|
+
if (hasExistingDateParseFormat || !['date', 'date-time'].includes(axisType)) {
|
|
975
|
+
return undefined
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
return getAutoDetectedDateParseFormat(config.data, dataKey)
|
|
979
|
+
}
|
|
980
|
+
|
|
777
981
|
const updateFieldDeprecated = (section, subsection, fieldName, newValue) => {
|
|
778
982
|
if (isDebug)
|
|
779
983
|
console.error(
|
|
@@ -816,6 +1020,23 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
816
1020
|
})
|
|
817
1021
|
return
|
|
818
1022
|
}
|
|
1023
|
+
|
|
1024
|
+
if (section === 'xAxis' && !truthy(subsection) && fieldName === 'dataKey') {
|
|
1025
|
+
const autoDetectedDateParseFormat = getAutoDetectedXAxisDateParseFormat(newValue)
|
|
1026
|
+
const updatedConfig = {
|
|
1027
|
+
...config,
|
|
1028
|
+
xAxis: {
|
|
1029
|
+
...config.xAxis,
|
|
1030
|
+
dataKey: newValue,
|
|
1031
|
+
...(autoDetectedDateParseFormat ? { dateParseFormat: autoDetectedDateParseFormat } : {})
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
enforceRestrictions(updatedConfig)
|
|
1036
|
+
updateConfig(updatedConfig)
|
|
1037
|
+
return
|
|
1038
|
+
}
|
|
1039
|
+
|
|
819
1040
|
if (null === section && null === subsection) {
|
|
820
1041
|
// special case that allows for updating the config object directly
|
|
821
1042
|
if (!truthy(fieldName)) console.error('fieldName is required')
|
|
@@ -1024,7 +1245,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1024
1245
|
// prettier-ignore
|
|
1025
1246
|
const {
|
|
1026
1247
|
highlightedBarValues,
|
|
1027
|
-
|
|
1248
|
+
getHighlightedSeriesValues,
|
|
1028
1249
|
handleUpdateHighlightedBar,
|
|
1029
1250
|
handleAddNewHighlightedBar,
|
|
1030
1251
|
handleRemoveHighlightedBar,
|
|
@@ -1634,6 +1855,27 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1634
1855
|
const hasDynamicCategory = ![undefined, '- Select - '].includes(config.series?.[0]?.dynamicCategory)
|
|
1635
1856
|
const hasMultipleSeries = config.series?.length > 1
|
|
1636
1857
|
|
|
1858
|
+
const highlightedSeriesOptions = useMemo(() => {
|
|
1859
|
+
if (
|
|
1860
|
+
!(
|
|
1861
|
+
config.visualizationType === 'Bar' &&
|
|
1862
|
+
config.series?.length === 1 &&
|
|
1863
|
+
config.highlightedBarValues?.length > 0 &&
|
|
1864
|
+
getHighlightedSeriesValues
|
|
1865
|
+
)
|
|
1866
|
+
) {
|
|
1867
|
+
return []
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
return [...new Set(getHighlightedSeriesValues())].sort().map(option => ({ value: option, label: option }))
|
|
1871
|
+
}, [
|
|
1872
|
+
config.visualizationType,
|
|
1873
|
+
config.series?.length,
|
|
1874
|
+
config.highlightedBarValues?.length,
|
|
1875
|
+
config.data,
|
|
1876
|
+
config.xAxis.dataKey
|
|
1877
|
+
])
|
|
1878
|
+
|
|
1637
1879
|
const editorContextValues = {
|
|
1638
1880
|
addNewExclusion,
|
|
1639
1881
|
data,
|
|
@@ -1652,7 +1894,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1652
1894
|
handleUpdateHighlightedBar,
|
|
1653
1895
|
handleRemoveHighlightedBar,
|
|
1654
1896
|
isPaletteReversed: config.general?.palette?.isReversed,
|
|
1655
|
-
|
|
1897
|
+
getHighlightedSeriesValues,
|
|
1656
1898
|
handleUpdateHighlightedBorderWidth,
|
|
1657
1899
|
handleUpdateHighlightedBarColor,
|
|
1658
1900
|
setLollipopShape,
|
|
@@ -1775,49 +2017,40 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1775
2017
|
getColumns={getColumns}
|
|
1776
2018
|
handleForecastPaletteSelection={handleForecastPaletteSelection}
|
|
1777
2019
|
>
|
|
1778
|
-
<
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
onDragEnd={({ source, destination }) =>
|
|
1797
|
-
handleSeriesChange(source.index, destination.index)
|
|
2020
|
+
<GroupedList
|
|
2021
|
+
items={config.series}
|
|
2022
|
+
droppableId='chart-series-order'
|
|
2023
|
+
label={
|
|
2024
|
+
<>
|
|
2025
|
+
Displaying
|
|
2026
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2027
|
+
<Tooltip.Target>
|
|
2028
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2029
|
+
</Tooltip.Target>
|
|
2030
|
+
<Tooltip.Content>
|
|
2031
|
+
<p>
|
|
2032
|
+
A data series is a set of related data points plotted in a chart and
|
|
2033
|
+
typically represented in the chart legend.
|
|
2034
|
+
</p>
|
|
2035
|
+
</Tooltip.Content>
|
|
2036
|
+
</Tooltip>
|
|
2037
|
+
</>
|
|
1798
2038
|
}
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
/>
|
|
1815
|
-
{provided.placeholder}
|
|
1816
|
-
</ul>
|
|
1817
|
-
)
|
|
1818
|
-
}}
|
|
1819
|
-
</Droppable>
|
|
1820
|
-
</DragDropContext>
|
|
2039
|
+
onDragEnd={({ source, destination }) => {
|
|
2040
|
+
if (!destination || source.index === destination.index) return
|
|
2041
|
+
handleSeriesChange(source.index, destination.index)
|
|
2042
|
+
}}
|
|
2043
|
+
renderItem={(series, index) => (
|
|
2044
|
+
<Panels.Series.Item
|
|
2045
|
+
getItemStyle={getItemStyle}
|
|
2046
|
+
sortableItemStyles={sortableItemStyles}
|
|
2047
|
+
chartsWithOptions={chartsWithOptions}
|
|
2048
|
+
series={series}
|
|
2049
|
+
index={index}
|
|
2050
|
+
key={`series-list-${index}`}
|
|
2051
|
+
/>
|
|
2052
|
+
)}
|
|
2053
|
+
/>
|
|
1821
2054
|
</Panels.Series.Wrapper>
|
|
1822
2055
|
)}
|
|
1823
2056
|
</>
|
|
@@ -2045,38 +2278,6 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2045
2278
|
}
|
|
2046
2279
|
updateField={updateFieldDeprecated}
|
|
2047
2280
|
/>
|
|
2048
|
-
<TextField
|
|
2049
|
-
value={config.yAxis.size}
|
|
2050
|
-
type='number'
|
|
2051
|
-
section='yAxis'
|
|
2052
|
-
fieldName='size'
|
|
2053
|
-
label={config.orientation === 'horizontal' ? 'Size (Height)' : 'Size (Width)'}
|
|
2054
|
-
className='number-narrow'
|
|
2055
|
-
updateField={updateFieldDeprecated}
|
|
2056
|
-
tooltip={
|
|
2057
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2058
|
-
<Tooltip.Target>
|
|
2059
|
-
<Icon
|
|
2060
|
-
display='question'
|
|
2061
|
-
style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
|
|
2062
|
-
/>
|
|
2063
|
-
</Tooltip.Target>
|
|
2064
|
-
<Tooltip.Content>
|
|
2065
|
-
<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>
|
|
2066
|
-
</Tooltip.Content>
|
|
2067
|
-
</Tooltip>
|
|
2068
|
-
}
|
|
2069
|
-
/>
|
|
2070
|
-
<TextField
|
|
2071
|
-
display={!visHasCategoricalAxis()}
|
|
2072
|
-
value={config.yAxis.labelOffset}
|
|
2073
|
-
section='yAxis'
|
|
2074
|
-
fieldName='labelOffset'
|
|
2075
|
-
label='Label offset'
|
|
2076
|
-
type='number'
|
|
2077
|
-
className='number-narrow'
|
|
2078
|
-
updateField={updateFieldDeprecated}
|
|
2079
|
-
/>
|
|
2080
2281
|
{config.orientation === 'horizontal' && (
|
|
2081
2282
|
<CheckBox
|
|
2082
2283
|
value={config.isResponsiveTicks}
|
|
@@ -2481,251 +2682,20 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2481
2682
|
)}
|
|
2482
2683
|
{/* start: anchors */}
|
|
2483
2684
|
{visHasAnchors() && config.orientation !== 'horizontal' && (
|
|
2484
|
-
<
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
key={`yaxis-anchors-2-${index}`}
|
|
2491
|
-
>
|
|
2492
|
-
<AccordionItemHeading className='series-item__title'>
|
|
2493
|
-
<>
|
|
2494
|
-
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
2495
|
-
Anchor {index + 1}
|
|
2496
|
-
<button
|
|
2497
|
-
className='series-list__remove'
|
|
2498
|
-
onClick={e => {
|
|
2499
|
-
e.preventDefault()
|
|
2500
|
-
const copiedAnchorGroups = [...config.yAxis.anchors]
|
|
2501
|
-
copiedAnchorGroups.splice(index, 1)
|
|
2502
|
-
updateConfig({
|
|
2503
|
-
...config,
|
|
2504
|
-
yAxis: {
|
|
2505
|
-
...config.yAxis,
|
|
2506
|
-
anchors: copiedAnchorGroups
|
|
2507
|
-
}
|
|
2508
|
-
})
|
|
2509
|
-
}}
|
|
2510
|
-
>
|
|
2511
|
-
Remove
|
|
2512
|
-
</button>
|
|
2513
|
-
</AccordionItemButton>
|
|
2514
|
-
</>
|
|
2515
|
-
</AccordionItemHeading>
|
|
2516
|
-
<AccordionItemPanel>
|
|
2517
|
-
<label>
|
|
2518
|
-
<span>Anchor Value</span>
|
|
2519
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2520
|
-
<Tooltip.Target>
|
|
2521
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2522
|
-
</Tooltip.Target>
|
|
2523
|
-
<Tooltip.Content>
|
|
2524
|
-
<p>Enter the value as its shown in the data column</p>
|
|
2525
|
-
</Tooltip.Content>
|
|
2526
|
-
</Tooltip>
|
|
2527
|
-
<input
|
|
2528
|
-
type='text'
|
|
2529
|
-
value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
|
|
2530
|
-
onChange={e => {
|
|
2531
|
-
e.preventDefault()
|
|
2532
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
2533
|
-
copiedAnchors[index].value = e.target.value
|
|
2534
|
-
updateConfig({
|
|
2535
|
-
...config,
|
|
2536
|
-
yAxis: {
|
|
2537
|
-
...config.yAxis,
|
|
2538
|
-
anchors: copiedAnchors
|
|
2539
|
-
}
|
|
2540
|
-
})
|
|
2541
|
-
}}
|
|
2542
|
-
/>
|
|
2543
|
-
</label>
|
|
2544
|
-
|
|
2545
|
-
<label>
|
|
2546
|
-
<span>Anchor Color</span>
|
|
2547
|
-
<input
|
|
2548
|
-
type='text'
|
|
2549
|
-
value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
|
|
2550
|
-
onChange={e => {
|
|
2551
|
-
e.preventDefault()
|
|
2552
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
2553
|
-
copiedAnchors[index].color = e.target.value
|
|
2554
|
-
updateConfig({
|
|
2555
|
-
...config,
|
|
2556
|
-
yAxis: {
|
|
2557
|
-
...config.yAxis,
|
|
2558
|
-
anchors: copiedAnchors
|
|
2559
|
-
}
|
|
2560
|
-
})
|
|
2561
|
-
}}
|
|
2562
|
-
/>
|
|
2563
|
-
</label>
|
|
2564
|
-
|
|
2565
|
-
<Select
|
|
2566
|
-
value={config.yAxis.anchors[index].lineStyle || ''}
|
|
2567
|
-
label='Anchor Line Style'
|
|
2568
|
-
onChange={e => {
|
|
2569
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
2570
|
-
copiedAnchors[index].lineStyle = e.target.value
|
|
2571
|
-
updateConfig({
|
|
2572
|
-
...config,
|
|
2573
|
-
yAxis: {
|
|
2574
|
-
...config.yAxis,
|
|
2575
|
-
anchors: copiedAnchors
|
|
2576
|
-
}
|
|
2577
|
-
})
|
|
2578
|
-
}}
|
|
2579
|
-
options={[
|
|
2580
|
-
{ value: '', label: 'Select' },
|
|
2581
|
-
...lineOptions.map(line => ({ value: line.value, label: line.value }))
|
|
2582
|
-
]}
|
|
2583
|
-
/>
|
|
2584
|
-
</AccordionItemPanel>
|
|
2585
|
-
</AccordionItem>
|
|
2586
|
-
))}
|
|
2587
|
-
</Accordion>
|
|
2588
|
-
|
|
2589
|
-
<button
|
|
2590
|
-
className='btn btn-primary full-width'
|
|
2591
|
-
onClick={e => {
|
|
2592
|
-
e.preventDefault()
|
|
2593
|
-
const anchors = [...config.yAxis.anchors]
|
|
2594
|
-
anchors.push({} as Anchor)
|
|
2595
|
-
updateConfig({
|
|
2596
|
-
...config,
|
|
2597
|
-
yAxis: {
|
|
2598
|
-
...config.yAxis,
|
|
2599
|
-
anchors
|
|
2600
|
-
}
|
|
2601
|
-
})
|
|
2602
|
-
}}
|
|
2603
|
-
>
|
|
2604
|
-
Add Anchor
|
|
2605
|
-
</button>
|
|
2606
|
-
</div>
|
|
2685
|
+
<AxisAnchorEditor
|
|
2686
|
+
axisKey='yAxis'
|
|
2687
|
+
config={config}
|
|
2688
|
+
lineOptions={lineOptions}
|
|
2689
|
+
updateConfig={updateConfig}
|
|
2690
|
+
/>
|
|
2607
2691
|
)}
|
|
2608
2692
|
{visHasAnchors() && config.orientation === 'horizontal' && (
|
|
2609
|
-
<
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
<>
|
|
2616
|
-
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
2617
|
-
Anchor {index + 1}
|
|
2618
|
-
<button
|
|
2619
|
-
className='series-list__remove'
|
|
2620
|
-
onClick={e => {
|
|
2621
|
-
e.preventDefault()
|
|
2622
|
-
const copiedAnchorGroups = [...config.xAxis.anchors]
|
|
2623
|
-
copiedAnchorGroups.splice(index, 1)
|
|
2624
|
-
updateConfig({
|
|
2625
|
-
...config,
|
|
2626
|
-
xAxis: {
|
|
2627
|
-
...config.xAxis,
|
|
2628
|
-
anchors: copiedAnchorGroups
|
|
2629
|
-
}
|
|
2630
|
-
})
|
|
2631
|
-
}}
|
|
2632
|
-
>
|
|
2633
|
-
Remove
|
|
2634
|
-
</button>
|
|
2635
|
-
</AccordionItemButton>
|
|
2636
|
-
</>
|
|
2637
|
-
</AccordionItemHeading>
|
|
2638
|
-
<AccordionItemPanel>
|
|
2639
|
-
<label>
|
|
2640
|
-
<span>Anchor Value</span>
|
|
2641
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2642
|
-
<Tooltip.Target>
|
|
2643
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2644
|
-
</Tooltip.Target>
|
|
2645
|
-
<Tooltip.Content>
|
|
2646
|
-
<p>Enter the value as its shown in the data column</p>
|
|
2647
|
-
</Tooltip.Content>
|
|
2648
|
-
</Tooltip>
|
|
2649
|
-
<input
|
|
2650
|
-
type='text'
|
|
2651
|
-
value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
|
|
2652
|
-
onChange={e => {
|
|
2653
|
-
e.preventDefault()
|
|
2654
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
2655
|
-
copiedAnchors[index].value = e.target.value
|
|
2656
|
-
updateConfig({
|
|
2657
|
-
...config,
|
|
2658
|
-
xAxis: {
|
|
2659
|
-
...config.xAxis,
|
|
2660
|
-
anchors: copiedAnchors
|
|
2661
|
-
}
|
|
2662
|
-
})
|
|
2663
|
-
}}
|
|
2664
|
-
/>
|
|
2665
|
-
</label>
|
|
2666
|
-
|
|
2667
|
-
<label>
|
|
2668
|
-
<span>Anchor Color</span>
|
|
2669
|
-
<input
|
|
2670
|
-
type='text'
|
|
2671
|
-
value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
|
|
2672
|
-
onChange={e => {
|
|
2673
|
-
e.preventDefault()
|
|
2674
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
2675
|
-
copiedAnchors[index].color = e.target.value
|
|
2676
|
-
updateConfig({
|
|
2677
|
-
...config,
|
|
2678
|
-
xAxis: {
|
|
2679
|
-
...config.xAxis,
|
|
2680
|
-
anchors: copiedAnchors
|
|
2681
|
-
}
|
|
2682
|
-
})
|
|
2683
|
-
}}
|
|
2684
|
-
/>
|
|
2685
|
-
</label>
|
|
2686
|
-
|
|
2687
|
-
<Select
|
|
2688
|
-
value={config.xAxis.anchors[index].lineStyle || ''}
|
|
2689
|
-
label='Anchor Line Style'
|
|
2690
|
-
onChange={e => {
|
|
2691
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
2692
|
-
copiedAnchors[index].lineStyle = e.target.value
|
|
2693
|
-
updateConfig({
|
|
2694
|
-
...config,
|
|
2695
|
-
xAxis: {
|
|
2696
|
-
...config.xAxis,
|
|
2697
|
-
anchors: copiedAnchors
|
|
2698
|
-
}
|
|
2699
|
-
})
|
|
2700
|
-
}}
|
|
2701
|
-
options={[
|
|
2702
|
-
{ value: '', label: 'Select' },
|
|
2703
|
-
...lineOptions.map(line => ({ value: line.value, label: line.value }))
|
|
2704
|
-
]}
|
|
2705
|
-
/>
|
|
2706
|
-
</AccordionItemPanel>
|
|
2707
|
-
</AccordionItem>
|
|
2708
|
-
))}
|
|
2709
|
-
</Accordion>
|
|
2710
|
-
|
|
2711
|
-
<button
|
|
2712
|
-
className='btn btn-primary full-width'
|
|
2713
|
-
onClick={e => {
|
|
2714
|
-
e.preventDefault()
|
|
2715
|
-
const anchors = [...config.xAxis.anchors]
|
|
2716
|
-
anchors.push({} as Anchor)
|
|
2717
|
-
updateConfig({
|
|
2718
|
-
...config,
|
|
2719
|
-
xAxis: {
|
|
2720
|
-
...config.xAxis,
|
|
2721
|
-
anchors
|
|
2722
|
-
}
|
|
2723
|
-
})
|
|
2724
|
-
}}
|
|
2725
|
-
>
|
|
2726
|
-
Add Anchor
|
|
2727
|
-
</button>
|
|
2728
|
-
</div>
|
|
2693
|
+
<AxisAnchorEditor
|
|
2694
|
+
axisKey='xAxis'
|
|
2695
|
+
config={config}
|
|
2696
|
+
lineOptions={lineOptions}
|
|
2697
|
+
updateConfig={updateConfig}
|
|
2698
|
+
/>
|
|
2729
2699
|
)}
|
|
2730
2700
|
{/* end: anchors */}
|
|
2731
2701
|
</AccordionItemPanel>
|
|
@@ -2961,11 +2931,19 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2961
2931
|
section='xAxis'
|
|
2962
2932
|
fieldName='type'
|
|
2963
2933
|
updateField={(_section, _subsection, _fieldName, value) => {
|
|
2934
|
+
const autoDetectedDateParseFormat = getAutoDetectedXAxisDateParseFormat(
|
|
2935
|
+
config.xAxis.dataKey,
|
|
2936
|
+
value
|
|
2937
|
+
)
|
|
2938
|
+
|
|
2964
2939
|
updateConfig({
|
|
2965
2940
|
...config,
|
|
2966
2941
|
xAxis: {
|
|
2967
2942
|
...config.xAxis,
|
|
2968
|
-
type: value
|
|
2943
|
+
type: value,
|
|
2944
|
+
...(autoDetectedDateParseFormat
|
|
2945
|
+
? { dateParseFormat: autoDetectedDateParseFormat }
|
|
2946
|
+
: {})
|
|
2969
2947
|
}
|
|
2970
2948
|
})
|
|
2971
2949
|
}}
|
|
@@ -3587,18 +3565,6 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3587
3565
|
updateField={updateFieldDeprecated}
|
|
3588
3566
|
/>
|
|
3589
3567
|
)}
|
|
3590
|
-
{config.orientation === 'horizontal' && (
|
|
3591
|
-
<TextField
|
|
3592
|
-
value={config.xAxis.labelOffset}
|
|
3593
|
-
section='xAxis'
|
|
3594
|
-
fieldName='labelOffset'
|
|
3595
|
-
label='Label offset'
|
|
3596
|
-
type='number'
|
|
3597
|
-
className='number-narrow'
|
|
3598
|
-
updateField={updateFieldDeprecated}
|
|
3599
|
-
/>
|
|
3600
|
-
)}
|
|
3601
|
-
|
|
3602
3568
|
{/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
|
|
3603
3569
|
{/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateFieldDeprecated} /> */}
|
|
3604
3570
|
{(config.xAxis.type === 'continuous' || config.forestPlot.type === 'Logarithmic') && (
|
|
@@ -3737,12 +3703,12 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3737
3703
|
highlightedBarValues.map((highlightedBarValue, i) => (
|
|
3738
3704
|
<fieldset>
|
|
3739
3705
|
<div className='edit-block' key={`highlighted-bar-${i}`}>
|
|
3740
|
-
<
|
|
3706
|
+
<Button
|
|
3741
3707
|
className='btn btn-danger'
|
|
3742
3708
|
onClick={e => handleRemoveHighlightedBar(e, i)}
|
|
3743
3709
|
>
|
|
3744
3710
|
Remove
|
|
3745
|
-
</
|
|
3711
|
+
</Button>
|
|
3746
3712
|
<p>Highlighted Bar {i + 1}</p>
|
|
3747
3713
|
<Select
|
|
3748
3714
|
value={config.highlightedBarValues[i].value}
|
|
@@ -3750,11 +3716,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3750
3716
|
onChange={e => handleUpdateHighlightedBar(e, i)}
|
|
3751
3717
|
options={[
|
|
3752
3718
|
{ value: '', label: '- Select Value -' },
|
|
3753
|
-
...
|
|
3754
|
-
? [...new Set(highlightedSeriesValues)]
|
|
3755
|
-
.sort()
|
|
3756
|
-
.map(option => ({ value: option, label: option }))
|
|
3757
|
-
: [])
|
|
3719
|
+
...highlightedSeriesOptions
|
|
3758
3720
|
]}
|
|
3759
3721
|
/>
|
|
3760
3722
|
<label>
|
|
@@ -3798,12 +3760,9 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3798
3760
|
</div>
|
|
3799
3761
|
</fieldset>
|
|
3800
3762
|
))}
|
|
3801
|
-
<
|
|
3802
|
-
className='btn btn-primary full-width'
|
|
3803
|
-
onClick={e => handleAddNewHighlightedBar(e)}
|
|
3804
|
-
>
|
|
3763
|
+
<Button variant='editor-primary' onClick={e => handleAddNewHighlightedBar(e)}>
|
|
3805
3764
|
Add Highlighted Bar
|
|
3806
|
-
</
|
|
3765
|
+
</Button>
|
|
3807
3766
|
</>
|
|
3808
3767
|
)}
|
|
3809
3768
|
</>
|
|
@@ -3888,255 +3847,21 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3888
3847
|
|
|
3889
3848
|
{/* anchors */}
|
|
3890
3849
|
{visHasAnchors() && config.orientation !== 'horizontal' && (
|
|
3891
|
-
<
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
key={`xaxis-anchors-2-${index}`}
|
|
3898
|
-
>
|
|
3899
|
-
<AccordionItemHeading className='series-item__title'>
|
|
3900
|
-
<>
|
|
3901
|
-
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
3902
|
-
Anchor {index + 1}
|
|
3903
|
-
<button
|
|
3904
|
-
className='series-list__remove'
|
|
3905
|
-
onClick={e => {
|
|
3906
|
-
e.preventDefault()
|
|
3907
|
-
const copiedAnchorGroups = [...config.xAxis.anchors]
|
|
3908
|
-
copiedAnchorGroups.splice(index, 1)
|
|
3909
|
-
updateConfig({
|
|
3910
|
-
...config,
|
|
3911
|
-
xAxis: {
|
|
3912
|
-
...config.xAxis,
|
|
3913
|
-
anchors: copiedAnchorGroups
|
|
3914
|
-
}
|
|
3915
|
-
})
|
|
3916
|
-
}}
|
|
3917
|
-
>
|
|
3918
|
-
Remove
|
|
3919
|
-
</button>
|
|
3920
|
-
</AccordionItemButton>
|
|
3921
|
-
</>
|
|
3922
|
-
</AccordionItemHeading>
|
|
3923
|
-
<AccordionItemPanel>
|
|
3924
|
-
<label>
|
|
3925
|
-
<span>Anchor Value</span>
|
|
3926
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
3927
|
-
<Tooltip.Target>
|
|
3928
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
3929
|
-
</Tooltip.Target>
|
|
3930
|
-
<Tooltip.Content>
|
|
3931
|
-
<p>Enter the value as its shown in the data column</p>
|
|
3932
|
-
</Tooltip.Content>
|
|
3933
|
-
</Tooltip>
|
|
3934
|
-
<input
|
|
3935
|
-
type='text'
|
|
3936
|
-
value={config.xAxis.anchors[index].value ? config.xAxis.anchors[index].value : ''}
|
|
3937
|
-
onChange={e => {
|
|
3938
|
-
e.preventDefault()
|
|
3939
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
3940
|
-
copiedAnchors[index].value = e.target.value
|
|
3941
|
-
updateConfig({
|
|
3942
|
-
...config,
|
|
3943
|
-
xAxis: {
|
|
3944
|
-
...config.xAxis,
|
|
3945
|
-
anchors: copiedAnchors
|
|
3946
|
-
}
|
|
3947
|
-
})
|
|
3948
|
-
}}
|
|
3949
|
-
/>
|
|
3950
|
-
</label>
|
|
3951
|
-
|
|
3952
|
-
<label>
|
|
3953
|
-
<span>Anchor Color</span>
|
|
3954
|
-
<input
|
|
3955
|
-
type='text'
|
|
3956
|
-
value={config.xAxis.anchors[index].color ? config.xAxis.anchors[index].color : ''}
|
|
3957
|
-
onChange={e => {
|
|
3958
|
-
e.preventDefault()
|
|
3959
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
3960
|
-
copiedAnchors[index].color = e.target.value
|
|
3961
|
-
updateConfig({
|
|
3962
|
-
...config,
|
|
3963
|
-
xAxis: {
|
|
3964
|
-
...config.xAxis,
|
|
3965
|
-
anchors: copiedAnchors
|
|
3966
|
-
}
|
|
3967
|
-
})
|
|
3968
|
-
}}
|
|
3969
|
-
/>
|
|
3970
|
-
</label>
|
|
3971
|
-
|
|
3972
|
-
<Select
|
|
3973
|
-
value={config.xAxis.anchors[index].lineStyle || ''}
|
|
3974
|
-
label='Anchor Line Style'
|
|
3975
|
-
onChange={e => {
|
|
3976
|
-
const copiedAnchors = [...config.xAxis.anchors]
|
|
3977
|
-
copiedAnchors[index].lineStyle = e.target.value
|
|
3978
|
-
updateConfig({
|
|
3979
|
-
...config,
|
|
3980
|
-
xAxis: {
|
|
3981
|
-
...config.xAxis,
|
|
3982
|
-
anchors: copiedAnchors
|
|
3983
|
-
}
|
|
3984
|
-
})
|
|
3985
|
-
}}
|
|
3986
|
-
options={[
|
|
3987
|
-
{ value: '', label: 'Select' },
|
|
3988
|
-
...lineOptions.map(line => ({ value: line.value, label: line.value }))
|
|
3989
|
-
]}
|
|
3990
|
-
/>
|
|
3991
|
-
</AccordionItemPanel>
|
|
3992
|
-
</AccordionItem>
|
|
3993
|
-
))}
|
|
3994
|
-
</Accordion>
|
|
3995
|
-
|
|
3996
|
-
<button
|
|
3997
|
-
className='btn btn-primary full-width'
|
|
3998
|
-
onClick={e => {
|
|
3999
|
-
e.preventDefault()
|
|
4000
|
-
const anchors = [...config.xAxis.anchors]
|
|
4001
|
-
anchors.push({} as Anchor)
|
|
4002
|
-
updateConfig({
|
|
4003
|
-
...config,
|
|
4004
|
-
xAxis: {
|
|
4005
|
-
...config.xAxis,
|
|
4006
|
-
anchors
|
|
4007
|
-
}
|
|
4008
|
-
})
|
|
4009
|
-
}}
|
|
4010
|
-
>
|
|
4011
|
-
Add Anchor
|
|
4012
|
-
</button>
|
|
4013
|
-
</div>
|
|
3850
|
+
<AxisAnchorEditor
|
|
3851
|
+
axisKey='xAxis'
|
|
3852
|
+
config={config}
|
|
3853
|
+
lineOptions={lineOptions}
|
|
3854
|
+
updateConfig={updateConfig}
|
|
3855
|
+
/>
|
|
4014
3856
|
)}
|
|
4015
3857
|
|
|
4016
3858
|
{visHasAnchors() && config.orientation === 'horizontal' && (
|
|
4017
|
-
<
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
key={`accordion-yaxis-anchors-${index}`}
|
|
4024
|
-
>
|
|
4025
|
-
<AccordionItemHeading className='series-item__title'>
|
|
4026
|
-
<>
|
|
4027
|
-
<AccordionItemButton className={'accordion__button accordion__button'}>
|
|
4028
|
-
Anchor {index + 1}
|
|
4029
|
-
<button
|
|
4030
|
-
className='series-list__remove'
|
|
4031
|
-
onClick={e => {
|
|
4032
|
-
e.preventDefault()
|
|
4033
|
-
const copiedAnchorGroups = [...config.yAxis.anchors]
|
|
4034
|
-
copiedAnchorGroups.splice(index, 1)
|
|
4035
|
-
updateConfig({
|
|
4036
|
-
...config,
|
|
4037
|
-
yAxis: {
|
|
4038
|
-
...config.yAxis,
|
|
4039
|
-
anchors: copiedAnchorGroups
|
|
4040
|
-
}
|
|
4041
|
-
})
|
|
4042
|
-
}}
|
|
4043
|
-
>
|
|
4044
|
-
Remove
|
|
4045
|
-
</button>
|
|
4046
|
-
</AccordionItemButton>
|
|
4047
|
-
</>
|
|
4048
|
-
</AccordionItemHeading>
|
|
4049
|
-
<AccordionItemPanel>
|
|
4050
|
-
<label>
|
|
4051
|
-
<span>Anchor Value</span>
|
|
4052
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
4053
|
-
<Tooltip.Target>
|
|
4054
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
4055
|
-
</Tooltip.Target>
|
|
4056
|
-
<Tooltip.Content>
|
|
4057
|
-
<p>Enter the value as its shown in the data column</p>
|
|
4058
|
-
</Tooltip.Content>
|
|
4059
|
-
</Tooltip>
|
|
4060
|
-
<input
|
|
4061
|
-
type='text'
|
|
4062
|
-
value={config.yAxis.anchors[index].value ? config.yAxis.anchors[index].value : ''}
|
|
4063
|
-
onChange={e => {
|
|
4064
|
-
e.preventDefault()
|
|
4065
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
4066
|
-
copiedAnchors[index].value = e.target.value
|
|
4067
|
-
updateConfig({
|
|
4068
|
-
...config,
|
|
4069
|
-
yAxis: {
|
|
4070
|
-
...config.yAxis,
|
|
4071
|
-
anchors: copiedAnchors
|
|
4072
|
-
}
|
|
4073
|
-
})
|
|
4074
|
-
}}
|
|
4075
|
-
/>
|
|
4076
|
-
</label>
|
|
4077
|
-
|
|
4078
|
-
<label>
|
|
4079
|
-
<span>Anchor Color</span>
|
|
4080
|
-
<input
|
|
4081
|
-
type='text'
|
|
4082
|
-
value={config.yAxis.anchors[index].color ? config.yAxis.anchors[index].color : ''}
|
|
4083
|
-
onChange={e => {
|
|
4084
|
-
e.preventDefault()
|
|
4085
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
4086
|
-
copiedAnchors[index].color = e.target.value
|
|
4087
|
-
updateConfig({
|
|
4088
|
-
...config,
|
|
4089
|
-
yAxis: {
|
|
4090
|
-
...config.yAxis,
|
|
4091
|
-
anchors: copiedAnchors
|
|
4092
|
-
}
|
|
4093
|
-
})
|
|
4094
|
-
}}
|
|
4095
|
-
/>
|
|
4096
|
-
</label>
|
|
4097
|
-
|
|
4098
|
-
<Select
|
|
4099
|
-
value={config.yAxis.anchors[index].lineStyle || ''}
|
|
4100
|
-
label='Anchor Line Style'
|
|
4101
|
-
onChange={e => {
|
|
4102
|
-
const copiedAnchors = [...config.yAxis.anchors]
|
|
4103
|
-
copiedAnchors[index].lineStyle = e.target.value
|
|
4104
|
-
updateConfig({
|
|
4105
|
-
...config,
|
|
4106
|
-
yAxis: {
|
|
4107
|
-
...config.yAxis,
|
|
4108
|
-
anchors: copiedAnchors
|
|
4109
|
-
}
|
|
4110
|
-
})
|
|
4111
|
-
}}
|
|
4112
|
-
options={[
|
|
4113
|
-
{ value: '', label: 'Select' },
|
|
4114
|
-
...lineOptions.map(line => ({ value: line.value, label: line.value }))
|
|
4115
|
-
]}
|
|
4116
|
-
/>
|
|
4117
|
-
</AccordionItemPanel>
|
|
4118
|
-
</AccordionItem>
|
|
4119
|
-
))}
|
|
4120
|
-
</Accordion>
|
|
4121
|
-
|
|
4122
|
-
<button
|
|
4123
|
-
className='btn btn-primary full-width'
|
|
4124
|
-
onClick={e => {
|
|
4125
|
-
e.preventDefault()
|
|
4126
|
-
const anchors = [...config.yAxis.anchors]
|
|
4127
|
-
anchors.push({} as Anchor)
|
|
4128
|
-
updateConfig({
|
|
4129
|
-
...config,
|
|
4130
|
-
yAxis: {
|
|
4131
|
-
...config.yAxis,
|
|
4132
|
-
anchors
|
|
4133
|
-
}
|
|
4134
|
-
})
|
|
4135
|
-
}}
|
|
4136
|
-
>
|
|
4137
|
-
Add Anchor
|
|
4138
|
-
</button>
|
|
4139
|
-
</div>
|
|
3859
|
+
<AxisAnchorEditor
|
|
3860
|
+
axisKey='yAxis'
|
|
3861
|
+
config={config}
|
|
3862
|
+
lineOptions={lineOptions}
|
|
3863
|
+
updateConfig={updateConfig}
|
|
3864
|
+
/>
|
|
4140
3865
|
)}
|
|
4141
3866
|
</AccordionItemPanel>
|
|
4142
3867
|
</AccordionItem>
|
|
@@ -4379,7 +4104,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
4379
4104
|
{config.legend.seriesHighlight &&
|
|
4380
4105
|
config.legend.seriesHighlight.map((val, i) => (
|
|
4381
4106
|
<fieldset className='edit-block' key={`${val}-${i}`}>
|
|
4382
|
-
<
|
|
4107
|
+
<Button
|
|
4383
4108
|
className='btn btn-danger'
|
|
4384
4109
|
onClick={event => {
|
|
4385
4110
|
event.preventDefault()
|
|
@@ -4392,7 +4117,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
4392
4117
|
}}
|
|
4393
4118
|
>
|
|
4394
4119
|
Remove
|
|
4395
|
-
</
|
|
4120
|
+
</Button>
|
|
4396
4121
|
<Select
|
|
4397
4122
|
value={config.legend.seriesHighlight[i]}
|
|
4398
4123
|
fieldName='seriesHighlight'
|
|
@@ -4408,8 +4133,8 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
4408
4133
|
/>
|
|
4409
4134
|
</fieldset>
|
|
4410
4135
|
))}
|
|
4411
|
-
<
|
|
4412
|
-
|
|
4136
|
+
<Button
|
|
4137
|
+
variant='editor-primary'
|
|
4413
4138
|
onClick={event => {
|
|
4414
4139
|
event.preventDefault()
|
|
4415
4140
|
const legendColumns = getLegendColumns()
|
|
@@ -4425,7 +4150,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
4425
4150
|
}}
|
|
4426
4151
|
>
|
|
4427
4152
|
Add Isolate Value
|
|
4428
|
-
</
|
|
4153
|
+
</Button>
|
|
4429
4154
|
</fieldset>
|
|
4430
4155
|
)}
|
|
4431
4156
|
{/* end: isolated values */}
|