@cdc/chart 4.24.12 → 4.25.2-25
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 +79900 -78999
- package/examples/feature/boxplot/boxplot.json +2 -157
- package/examples/feature/boxplot/testing.csv +23 -38
- package/examples/feature/tests-non-numerics/example-combo-bar-nonnumeric.json +579 -49
- package/examples/private/ehdi.json +29939 -0
- package/examples/private/line-issue.json +497 -0
- package/examples/private/not-loading.json +360 -0
- package/index.html +11 -15
- package/package.json +2 -2
- package/src/CdcChart.tsx +92 -1512
- package/src/CdcChartComponent.tsx +1113 -0
- package/src/ConfigContext.tsx +6 -1
- package/src/_stories/Chart.Anchors.stories.tsx +1 -1
- package/src/_stories/Chart.CustomColors.stories.tsx +1 -1
- package/src/_stories/Chart.DynamicSeries.stories.tsx +17 -2
- package/src/_stories/Chart.Filters.stories.tsx +19 -0
- package/src/_stories/Chart.Legend.Gradient.stories.tsx +2 -2
- package/src/_stories/Chart.ScatterPlot.stories.tsx +19 -0
- package/src/_stories/Chart.tooltip.stories.tsx +1 -2
- package/src/_stories/ChartAnnotation.stories.tsx +1 -1
- package/src/_stories/ChartAxisLabels.stories.tsx +1 -1
- package/src/_stories/ChartAxisTitles.stories.tsx +1 -1
- package/src/_stories/ChartEditor.stories.tsx +1 -1
- package/src/_stories/ChartLine.Suppression.stories.tsx +1 -1
- package/src/_stories/ChartLine.Symbols.stories.tsx +18 -0
- package/src/_stories/ChartPrefixSuffix.stories.tsx +1 -1
- package/src/_stories/_mock/line_chart_symbols.json +437 -0
- package/src/_stories/_mock/scatterplot-image-download.json +1244 -0
- package/src/components/Annotations/components/AnnotationDraggable.tsx +3 -11
- package/src/components/Annotations/components/AnnotationDropdown.tsx +3 -3
- package/src/components/Axis/Categorical.Axis.tsx +3 -4
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +14 -5
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +10 -4
- package/src/components/BarChart/components/BarChart.Vertical.tsx +5 -7
- package/src/components/BarChart/components/BarChart.jsx +24 -4
- package/src/components/BarChart/components/context.tsx +1 -0
- package/src/components/BoxPlot/BoxPlot.tsx +34 -32
- package/src/components/BoxPlot/helpers/index.ts +108 -18
- package/src/components/BrushChart.tsx +44 -24
- package/src/components/DeviationBar.jsx +2 -6
- package/src/components/EditorPanel/EditorPanel.tsx +64 -8
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +4 -0
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +3 -1
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +44 -7
- package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +6 -1
- package/src/components/ForestPlot/ForestPlot.tsx +176 -26
- package/src/components/Legend/Legend.Component.tsx +29 -38
- package/src/components/Legend/Legend.Suppression.tsx +3 -5
- package/src/components/Legend/Legend.tsx +2 -2
- package/src/components/Legend/LegendLine.Shape.tsx +51 -0
- package/src/components/Legend/helpers/createFormatLabels.tsx +29 -26
- package/src/components/Legend/helpers/getLegendClasses.ts +20 -38
- package/src/components/Legend/helpers/index.ts +22 -9
- package/src/components/Legend/tests/getLegendClasses.test.ts +3 -20
- package/src/components/LineChart/components/LineChart.Circle.tsx +104 -94
- package/src/components/LineChart/index.tsx +6 -2
- package/src/components/LinearChart.tsx +77 -43
- package/src/components/PairedBarChart.jsx +2 -9
- package/src/components/ZoomBrush.tsx +5 -7
- package/src/data/initial-state.js +6 -3
- package/src/helpers/getBoxPlotConfig.ts +68 -0
- package/src/helpers/getColorScale.ts +24 -0
- package/src/helpers/getComboChartConfig.ts +42 -0
- package/src/helpers/getExcludedData.ts +37 -0
- package/src/helpers/getTopAxis.ts +7 -0
- package/src/helpers/isConvertLineToBarGraph.ts +10 -3
- package/src/hooks/useBarChart.ts +40 -13
- package/src/hooks/{useHighlightedBars.js → useHighlightedBars.ts} +2 -1
- package/src/hooks/useIntersectionObserver.ts +37 -0
- package/src/hooks/useMinMax.ts +11 -8
- package/src/hooks/useReduceData.ts +1 -1
- package/src/hooks/useScales.ts +10 -0
- package/src/hooks/useTooltip.tsx +21 -2
- package/src/index.jsx +1 -0
- package/src/scss/DataTable.scss +0 -5
- package/src/scss/main.scss +31 -116
- package/src/store/chart.actions.ts +40 -0
- package/src/store/chart.reducer.ts +83 -0
- package/src/types/ChartConfig.ts +6 -3
- package/src/types/ChartContext.ts +1 -3
- package/src/helpers/getQuartiles.ts +0 -27
- package/src/hooks/useColorScale.ts +0 -50
- package/src/hooks/useIntersectionObserver.jsx +0 -29
- package/src/hooks/useTopAxis.js +0 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Group } from '@visx/group'
|
|
2
2
|
import { useContext, useEffect, useRef, useState } from 'react'
|
|
3
|
-
import ConfigContext from '../ConfigContext'
|
|
3
|
+
import ConfigContext, { ChartDispatchContext } from '../ConfigContext'
|
|
4
4
|
import * as d3 from 'd3'
|
|
5
5
|
import { Text } from '@visx/text'
|
|
6
6
|
import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
|
|
@@ -12,7 +12,8 @@ interface BrushChartProps {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const BrushChart = ({ xMax, yMax }: BrushChartProps) => {
|
|
15
|
-
const { tableData, config,
|
|
15
|
+
const { tableData, config, dashboardConfig, formatDate, parseDate } = useContext(ConfigContext)
|
|
16
|
+
const dispatch = useContext(ChartDispatchContext)
|
|
16
17
|
const [brushState, setBrushState] = useState({ isBrushing: false, selection: [] })
|
|
17
18
|
const [brushKey, setBrushKey] = useState(0)
|
|
18
19
|
const sharedFilters = dashboardConfig?.dashboard?.sharedFilters ?? []
|
|
@@ -54,6 +55,9 @@ const BrushChart = ({ xMax, yMax }: BrushChartProps) => {
|
|
|
54
55
|
|
|
55
56
|
const brushHandle = (g, selection, firstDate, lastDate) => {
|
|
56
57
|
const textWidth = getTextWidth(firstDate, `normal ${16 / 1.1}px sans-serif`)
|
|
58
|
+
const textPositionLeft = selection[0] < textWidth ? 0 : -textWidth
|
|
59
|
+
const textPositionRight = xMax - selection[1] < textWidth ? -textWidth : 0
|
|
60
|
+
|
|
57
61
|
return g
|
|
58
62
|
.selectAll('.handle--custom')
|
|
59
63
|
.data([{ side: 'left' }, { side: 'right' }])
|
|
@@ -61,7 +65,7 @@ const BrushChart = ({ xMax, yMax }: BrushChartProps) => {
|
|
|
61
65
|
const handleGroup = enter.append('g').attr('class', 'handle--custom')
|
|
62
66
|
handleGroup
|
|
63
67
|
.append('text')
|
|
64
|
-
.attr('x', d => (d.side === 'left' ?
|
|
68
|
+
.attr('x', d => (d.side === 'left' ? textPositionLeft : textPositionRight))
|
|
65
69
|
.attr('y', 30)
|
|
66
70
|
.text(d => (d.side === 'left' ? firstDate : lastDate))
|
|
67
71
|
.attr('font-size', '13px')
|
|
@@ -102,22 +106,25 @@ const BrushChart = ({ xMax, yMax }: BrushChartProps) => {
|
|
|
102
106
|
const sortedData = _.sortBy(newFilteredData, item => new Date(item[config.xAxis.dataKey]))
|
|
103
107
|
|
|
104
108
|
// If ascending is false, reverse the sorted array
|
|
105
|
-
const finalData = !sortByRecentDate ? sortedData : sortedData.reverse()
|
|
109
|
+
const finalData: object[] = !sortByRecentDate ? sortedData : sortedData.reverse()
|
|
106
110
|
|
|
107
111
|
// Retrieve the start and end dates based on the sorted data array
|
|
108
|
-
const startDate = _.get(_.first(finalData), config.xAxis.dataKey, '')
|
|
109
|
-
const endDate = _.get(_.last(finalData), config.xAxis.dataKey, '')
|
|
112
|
+
const startDate: string = _.get(_.first(finalData), config.xAxis.dataKey, '')
|
|
113
|
+
const endDate: string = _.get(_.last(finalData), config.xAxis.dataKey, '')
|
|
110
114
|
// add custom blue colored handlers to each corners of brush
|
|
111
115
|
svg.selectAll('.handle--custom').remove()
|
|
112
|
-
//
|
|
113
|
-
const
|
|
116
|
+
// Parse and format the dates, setting them to an empty string if undefined
|
|
117
|
+
const parseAndFormatDate = date => (date ? formatDate(parseDate(date)) : '')
|
|
118
|
+
const formattedStartDate = parseAndFormatDate(startDate)
|
|
119
|
+
const formattedEndDate = parseAndFormatDate(endDate)
|
|
114
120
|
svg.call(brushHandle, selection, formattedStartDate, formattedEndDate)
|
|
115
121
|
|
|
116
|
-
|
|
122
|
+
const payload = {
|
|
117
123
|
active: config.brush.active,
|
|
118
124
|
isBrushing: isUserBrushing,
|
|
119
125
|
data: finalData
|
|
120
|
-
}
|
|
126
|
+
}
|
|
127
|
+
dispatch({ type: 'SET_BRUSH_CONFIG', payload: payload })
|
|
121
128
|
setBrushState({
|
|
122
129
|
isBrushing: true,
|
|
123
130
|
selection
|
|
@@ -150,22 +157,35 @@ const BrushChart = ({ xMax, yMax }: BrushChartProps) => {
|
|
|
150
157
|
|
|
151
158
|
if ((isFiltersActive || isExclusionsActive || isDashboardFilters) && config.brush?.active) {
|
|
152
159
|
setBrushKey(prevKey => prevKey + 1)
|
|
153
|
-
setBrushConfig(prev => {
|
|
154
|
-
return {
|
|
155
|
-
...prev,
|
|
156
|
-
data: tableData
|
|
157
|
-
}
|
|
158
|
-
})
|
|
159
160
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
...prev,
|
|
164
|
-
data: []
|
|
165
|
-
}
|
|
166
|
-
})
|
|
161
|
+
dispatch({ type: 'SET_BRUSH_CONFIG', payload: { ...config.brush, data: tableData } })
|
|
162
|
+
|
|
163
|
+
return () => dispatch({ type: 'SET_BRUSH_CONFIG', payload: { ...config.brush, data: [] } })
|
|
167
164
|
}, [config.filters, config.exclusions, config.brush?.active, isDashboardFilters])
|
|
168
|
-
|
|
165
|
+
|
|
166
|
+
// this effect handles where brush chart is missing on production. it helpes re render
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
let timeoutId = null
|
|
169
|
+
|
|
170
|
+
const checkAndInitializeBrush = () => {
|
|
171
|
+
if (xMax > 0) {
|
|
172
|
+
initializeBrush()
|
|
173
|
+
} else {
|
|
174
|
+
// Clear the existing timeout and set a new one
|
|
175
|
+
clearTimeout(timeoutId)
|
|
176
|
+
timeoutId = setTimeout(checkAndInitializeBrush, 500)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
checkAndInitializeBrush()
|
|
181
|
+
|
|
182
|
+
// Cleanup function to clear timeout
|
|
183
|
+
return () => {
|
|
184
|
+
if (timeoutId) {
|
|
185
|
+
clearTimeout(timeoutId)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}, [xMax])
|
|
169
189
|
|
|
170
190
|
// reset brush on keychange
|
|
171
191
|
useEffect(() => {
|
|
@@ -30,7 +30,6 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
30
30
|
: roundingStyle === 'finger'
|
|
31
31
|
? '15px'
|
|
32
32
|
: '0px'
|
|
33
|
-
const fontSize = { small: 16, medium: 18, large: 20 }
|
|
34
33
|
const isRounded = config.barStyle === 'rounded'
|
|
35
34
|
const target = Number(config.xAxis.target)
|
|
36
35
|
const seriesKey = config.series[0].dataKey
|
|
@@ -65,7 +64,7 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
65
64
|
const firstBarValue = data[0][seriesKey]
|
|
66
65
|
const barPosition = firstBarValue < target ? 'left' : 'right'
|
|
67
66
|
const label = `${config.xAxis.targetLabel} ${formatNumber(config.xAxis.target || 0, 'left')}`
|
|
68
|
-
const labelWidth = getTextWidth(label, `bold ${
|
|
67
|
+
const labelWidth = getTextWidth(label, `bold ${20}px sans-serif`)
|
|
69
68
|
let labelY = config.isLollipopChart ? lollipopBarHeight / 2 : Number(config.barHeight) / 2
|
|
70
69
|
let paddingX = 0
|
|
71
70
|
let labelX = 0
|
|
@@ -165,10 +164,7 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
165
164
|
config.heights.horizontal = totalheight
|
|
166
165
|
|
|
167
166
|
// text,labels postiions
|
|
168
|
-
const textWidth = getTextWidth(
|
|
169
|
-
formatNumber(barValue, 'left'),
|
|
170
|
-
`normal ${fontSize[config.fontSize]}px sans-serif`
|
|
171
|
-
)
|
|
167
|
+
const textWidth = getTextWidth(formatNumber(barValue, 'left'), `normal ${16}px sans-serif`)
|
|
172
168
|
const textFits = textWidth < barWidth - 6
|
|
173
169
|
const textX = barBaseX
|
|
174
170
|
const textY = barY + barHeight / 2
|
|
@@ -596,7 +596,7 @@ const EditorPanel = () => {
|
|
|
596
596
|
updateConfig,
|
|
597
597
|
tableData,
|
|
598
598
|
transformedData: data,
|
|
599
|
-
|
|
599
|
+
isLoading,
|
|
600
600
|
colorScale,
|
|
601
601
|
colorPalettes,
|
|
602
602
|
twoColorPalette,
|
|
@@ -610,7 +610,7 @@ const EditorPanel = () => {
|
|
|
610
610
|
lineOptions,
|
|
611
611
|
rawData,
|
|
612
612
|
highlight,
|
|
613
|
-
|
|
613
|
+
handleShowAll,
|
|
614
614
|
dimensions
|
|
615
615
|
} = useContext<ChartContext>(ConfigContext)
|
|
616
616
|
|
|
@@ -813,7 +813,7 @@ const EditorPanel = () => {
|
|
|
813
813
|
const [displayPanel, setDisplayPanel] = useState(true)
|
|
814
814
|
const [displayViewportOverrides, setDisplayViewportOverrides] = useState(false)
|
|
815
815
|
|
|
816
|
-
if (
|
|
816
|
+
if (isLoading) {
|
|
817
817
|
return null
|
|
818
818
|
}
|
|
819
819
|
|
|
@@ -906,7 +906,7 @@ const EditorPanel = () => {
|
|
|
906
906
|
return Object.keys(columns)
|
|
907
907
|
}
|
|
908
908
|
|
|
909
|
-
const getLegendStyleOptions = (option: 'style' | 'subStyle'): string[] => {
|
|
909
|
+
const getLegendStyleOptions = (option: 'style' | 'subStyle' | 'shapes'): string[] => {
|
|
910
910
|
const options: string[] = []
|
|
911
911
|
|
|
912
912
|
switch (option) {
|
|
@@ -963,7 +963,7 @@ const EditorPanel = () => {
|
|
|
963
963
|
|
|
964
964
|
const convertStateToConfig = () => {
|
|
965
965
|
let strippedState = JSON.parse(JSON.stringify(config))
|
|
966
|
-
if (false === missingRequiredSections()) {
|
|
966
|
+
if (false === missingRequiredSections(config)) {
|
|
967
967
|
delete strippedState.newViz
|
|
968
968
|
}
|
|
969
969
|
delete strippedState.runtime
|
|
@@ -1631,8 +1631,19 @@ const EditorPanel = () => {
|
|
|
1631
1631
|
value={config.yAxis.label}
|
|
1632
1632
|
section='yAxis'
|
|
1633
1633
|
fieldName='label'
|
|
1634
|
-
label='Label
|
|
1634
|
+
label='Label'
|
|
1635
1635
|
updateField={updateField}
|
|
1636
|
+
maxLength={35}
|
|
1637
|
+
tooltip={
|
|
1638
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1639
|
+
<Tooltip.Target>
|
|
1640
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1641
|
+
</Tooltip.Target>
|
|
1642
|
+
<Tooltip.Content>
|
|
1643
|
+
<p>35 character limit</p>
|
|
1644
|
+
</Tooltip.Content>
|
|
1645
|
+
</Tooltip>
|
|
1646
|
+
}
|
|
1636
1647
|
/>
|
|
1637
1648
|
{config.runtime.seriesKeys &&
|
|
1638
1649
|
config.runtime.seriesKeys.length === 1 &&
|
|
@@ -2306,6 +2317,17 @@ const EditorPanel = () => {
|
|
|
2306
2317
|
fieldName='rightLabel'
|
|
2307
2318
|
label='Label'
|
|
2308
2319
|
updateField={updateField}
|
|
2320
|
+
maxLength={35}
|
|
2321
|
+
tooltip={
|
|
2322
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2323
|
+
<Tooltip.Target>
|
|
2324
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2325
|
+
</Tooltip.Target>
|
|
2326
|
+
<Tooltip.Content>
|
|
2327
|
+
<p>35 character limit</p>
|
|
2328
|
+
</Tooltip.Content>
|
|
2329
|
+
</Tooltip>
|
|
2330
|
+
}
|
|
2309
2331
|
/>
|
|
2310
2332
|
<TextField
|
|
2311
2333
|
value={config.yAxis.rightNumTicks}
|
|
@@ -2596,6 +2618,17 @@ const EditorPanel = () => {
|
|
|
2596
2618
|
fieldName='label'
|
|
2597
2619
|
label='Label'
|
|
2598
2620
|
updateField={updateField}
|
|
2621
|
+
maxLength={35}
|
|
2622
|
+
tooltip={
|
|
2623
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2624
|
+
<Tooltip.Target>
|
|
2625
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2626
|
+
</Tooltip.Target>
|
|
2627
|
+
<Tooltip.Content>
|
|
2628
|
+
<p>35 character limit</p>
|
|
2629
|
+
</Tooltip.Content>
|
|
2630
|
+
</Tooltip>
|
|
2631
|
+
}
|
|
2599
2632
|
/>
|
|
2600
2633
|
|
|
2601
2634
|
{config.xAxis.type === 'continuous' && (
|
|
@@ -3658,6 +3691,27 @@ const EditorPanel = () => {
|
|
|
3658
3691
|
updateField={updateField}
|
|
3659
3692
|
options={getLegendStyleOptions('style')}
|
|
3660
3693
|
/>
|
|
3694
|
+
<CheckBox
|
|
3695
|
+
tooltip={
|
|
3696
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3697
|
+
<Tooltip.Target>
|
|
3698
|
+
<Icon
|
|
3699
|
+
display='question'
|
|
3700
|
+
style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
|
|
3701
|
+
/>
|
|
3702
|
+
</Tooltip.Target>
|
|
3703
|
+
<Tooltip.Content>
|
|
3704
|
+
<p>Choose option Shapes in Line Datapoint Symbols to display.</p>
|
|
3705
|
+
</Tooltip.Content>
|
|
3706
|
+
</Tooltip>
|
|
3707
|
+
}
|
|
3708
|
+
display={!config.legend.hide && config.legend.style === 'lines'}
|
|
3709
|
+
value={config.legend.hasShape}
|
|
3710
|
+
section='legend'
|
|
3711
|
+
fieldName='hasShape'
|
|
3712
|
+
label='Shapes'
|
|
3713
|
+
updateField={updateField}
|
|
3714
|
+
/>
|
|
3661
3715
|
|
|
3662
3716
|
<Select
|
|
3663
3717
|
display={!config.legend.hide && config.legend.style === 'gradient'}
|
|
@@ -3797,7 +3851,7 @@ const EditorPanel = () => {
|
|
|
3797
3851
|
updatedSeriesHighlight.splice(i, 1)
|
|
3798
3852
|
updateField('legend', null, 'seriesHighlight', updatedSeriesHighlight)
|
|
3799
3853
|
if (!updatedSeriesHighlight.length) {
|
|
3800
|
-
|
|
3854
|
+
handleShowAll()
|
|
3801
3855
|
}
|
|
3802
3856
|
}}
|
|
3803
3857
|
>
|
|
@@ -3887,7 +3941,9 @@ const EditorPanel = () => {
|
|
|
3887
3941
|
display={
|
|
3888
3942
|
['bottom', 'top'].includes(config.legend.position) &&
|
|
3889
3943
|
!config.legend.hide &&
|
|
3890
|
-
config.legend.style !== 'gradient'
|
|
3944
|
+
config.legend.style !== 'gradient' &&
|
|
3945
|
+
!config.legend.singleRow &&
|
|
3946
|
+
!config.legend.singleRow
|
|
3891
3947
|
}
|
|
3892
3948
|
value={config.legend.verticalSorted}
|
|
3893
3949
|
section='legend'
|
|
@@ -209,6 +209,10 @@ const PanelGeneral: FC<PanelProps> = props => {
|
|
|
209
209
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
210
210
|
</Tooltip.Target>
|
|
211
211
|
<Tooltip.Content>
|
|
212
|
+
<p>
|
|
213
|
+
Recommended set to display for Section 508 compliance.
|
|
214
|
+
</p>
|
|
215
|
+
<hr/>
|
|
212
216
|
<p>
|
|
213
217
|
Selecting this option will <i> not </i> hide the display of "zero value", "suppressed data", or
|
|
214
218
|
"missing data" indicators on the chart (if applicable).
|
|
@@ -500,6 +500,8 @@ const SeriesInputName = props => {
|
|
|
500
500
|
|
|
501
501
|
updateConfig(newConfig)
|
|
502
502
|
}
|
|
503
|
+
// if series name is emty show default data value.
|
|
504
|
+
const value = series.name !== undefined && series.name !== series.dataKey ? series.name : series.dataKey
|
|
503
505
|
|
|
504
506
|
return (
|
|
505
507
|
<>
|
|
@@ -507,7 +509,7 @@ const SeriesInputName = props => {
|
|
|
507
509
|
<input
|
|
508
510
|
type='text'
|
|
509
511
|
key={`series-name-${i}`}
|
|
510
|
-
value={
|
|
512
|
+
value={value}
|
|
511
513
|
onChange={event => {
|
|
512
514
|
changeSeriesName(i, event.target.value)
|
|
513
515
|
}}
|
|
@@ -136,15 +136,23 @@ const PanelVisual: FC<PanelProps> = props => {
|
|
|
136
136
|
/>
|
|
137
137
|
</fieldset>
|
|
138
138
|
)}
|
|
139
|
-
<Select
|
|
140
|
-
value={config.fontSize}
|
|
141
|
-
fieldName='fontSize'
|
|
142
|
-
label='Font Size'
|
|
143
|
-
updateField={updateField}
|
|
144
|
-
options={['small', 'medium', 'large']}
|
|
145
|
-
/>
|
|
146
139
|
{visHasBarBorders() && (
|
|
147
140
|
<Select
|
|
141
|
+
tooltip={
|
|
142
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
143
|
+
<Tooltip.Target>
|
|
144
|
+
<Icon
|
|
145
|
+
display='question'
|
|
146
|
+
style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
|
|
147
|
+
/>
|
|
148
|
+
</Tooltip.Target>
|
|
149
|
+
<Tooltip.Content>
|
|
150
|
+
<p>
|
|
151
|
+
Recommended set to display for Section 508 compliance.
|
|
152
|
+
</p>
|
|
153
|
+
</Tooltip.Content>
|
|
154
|
+
</Tooltip>
|
|
155
|
+
}
|
|
148
156
|
value={config.barHasBorder}
|
|
149
157
|
fieldName='barHasBorder'
|
|
150
158
|
label='Bar Borders'
|
|
@@ -171,6 +179,35 @@ const PanelVisual: FC<PanelProps> = props => {
|
|
|
171
179
|
config.visualizationType === 'Combo') ||
|
|
172
180
|
config.visualizationType === 'Line') && (
|
|
173
181
|
<>
|
|
182
|
+
<Select
|
|
183
|
+
tooltip={
|
|
184
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
185
|
+
<Tooltip.Target>
|
|
186
|
+
<Icon
|
|
187
|
+
display='question'
|
|
188
|
+
style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
|
|
189
|
+
/>
|
|
190
|
+
</Tooltip.Target>
|
|
191
|
+
<Tooltip.Content>
|
|
192
|
+
<p>
|
|
193
|
+
Shapes will appear in the following order: circle, square, triangle, diamond, and inverted
|
|
194
|
+
triangle. Use with a maximum of 5 data points.
|
|
195
|
+
</p>
|
|
196
|
+
</Tooltip.Content>
|
|
197
|
+
</Tooltip>
|
|
198
|
+
}
|
|
199
|
+
value={config.visual.lineDatapointSymbol}
|
|
200
|
+
section='visual'
|
|
201
|
+
fieldName='lineDatapointSymbol'
|
|
202
|
+
label='Line Datapoint Symbols'
|
|
203
|
+
updateField={updateField}
|
|
204
|
+
options={['none', 'standard']}
|
|
205
|
+
/>
|
|
206
|
+
{config.series.length > config.visual.maximumShapeAmount &&
|
|
207
|
+
config.visual.lineDatapointSymbol === 'standard' && (
|
|
208
|
+
<small className='text-danger'>Standard only supports up to 7 data points</small>
|
|
209
|
+
)}
|
|
210
|
+
|
|
174
211
|
<Select
|
|
175
212
|
value={config.lineDatapointStyle}
|
|
176
213
|
fieldName='lineDatapointStyle'
|
|
@@ -30,7 +30,12 @@ export const updateFieldRankByValue = (
|
|
|
30
30
|
newConfig.rankByValue = newValue
|
|
31
31
|
|
|
32
32
|
if (config.rankByValue && !newValue) {
|
|
33
|
-
const
|
|
33
|
+
const CIkeys: string[] = Object.values(config.confidenceKeys) as string[]
|
|
34
|
+
const seriesKeys: string[] = config.series.map(s => s.dataKey)
|
|
35
|
+
const keysToClean: string[] = seriesKeys.concat(CIkeys)
|
|
36
|
+
const cleanData = config?.xAxis?.dataKey
|
|
37
|
+
? transform.cleanData(config.data, config.xAxis.dataKey, keysToClean)
|
|
38
|
+
: config.data
|
|
34
39
|
const newData = preTransformedData.sort((a, b) => {
|
|
35
40
|
const aIndex = indexOfObj(cleanData, a)
|
|
36
41
|
const bIndex = indexOfObj(cleanData, b)
|