@cdc/chart 1.3.4 → 9.22.9
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 +6 -6
- package/examples/cutoff-example-config.json +2 -0
- package/examples/cutoff-example-data.json +1 -1
- package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json +198 -0
- package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +241 -0
- package/examples/gallery/bar-chart-horizontal/horizontal-stacked.json +248 -0
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +137 -0
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +80 -0
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +81 -0
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +68 -0
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +111 -0
- package/examples/gallery/lollipop/lollipop-style-horizontal.json +220 -0
- package/examples/gallery/paired-bar/paired-bar-chart.json +196 -0
- package/examples/horizontal-chart.json +3 -0
- package/examples/paired-bar-data.json +1 -1
- package/examples/paired-bar-example.json +2 -0
- package/examples/planet-combo-example-config.json +2 -0
- package/examples/planet-example-config.json +2 -2
- package/examples/planet-example-data.json +1 -1
- package/examples/planet-pie-example-config.json +2 -0
- package/examples/private/line-test-data.json +22 -0
- package/examples/private/line-test-two.json +216 -0
- package/examples/private/line-test.json +102 -0
- package/examples/stacked-vertical-bar-example.json +228 -0
- package/package.json +3 -3
- package/src/CdcChart.tsx +79 -47
- package/src/components/BarChart.tsx +82 -39
- package/src/components/DataTable.tsx +17 -10
- package/src/components/EditorPanel.js +233 -169
- package/src/components/LineChart.tsx +3 -0
- package/src/components/LinearChart.tsx +171 -77
- package/src/components/PairedBarChart.tsx +139 -42
- package/src/components/PieChart.tsx +31 -6
- package/src/components/SparkLine.js +4 -1
- package/src/components/useIntersectionObserver.tsx +32 -0
- package/src/data/initial-state.js +17 -7
- package/src/hooks/useReduceData.ts +50 -23
- package/src/index.html +5 -9
- package/src/scss/editor-panel.scss +34 -4
- package/src/scss/main.scss +165 -5
- package/src/components/BarStackVertical.js +0 -0
|
@@ -16,8 +16,10 @@ import Context from '../context'
|
|
|
16
16
|
import WarningImage from '../images/warning.svg'
|
|
17
17
|
import AdvancedEditor from '@cdc/core/components/AdvancedEditor';
|
|
18
18
|
|
|
19
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
20
|
-
import
|
|
19
|
+
import ErrorBoundary from '@cdc/core/components/ErrorBoundary';
|
|
20
|
+
import Waiting from '@cdc/core/components/Waiting';
|
|
21
|
+
import QuestionIcon from '@cdc/core/assets/icon-question-circle.svg'; //TODO: Update with Icon component
|
|
22
|
+
import {useColorPalette} from '../hooks/useColorPalette';
|
|
21
23
|
|
|
22
24
|
import InputCheckbox from '@cdc/core/components/inputs/InputCheckbox';
|
|
23
25
|
import InputToggle from '@cdc/core/components/inputs/InputToggle';
|
|
@@ -26,7 +28,7 @@ import Icon from '@cdc/core/components/ui/Icon'
|
|
|
26
28
|
import useReduceData from '../hooks/useReduceData';
|
|
27
29
|
|
|
28
30
|
const TextField = memo(({label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = "input", i = null, min = null, ...attributes}) => {
|
|
29
|
-
const [ value, setValue ] = useState(stateValue);
|
|
31
|
+
const [ value, setValue ] = useState(stateValue);
|
|
30
32
|
|
|
31
33
|
const [ debouncedValue ] = useDebounce(value, 500);
|
|
32
34
|
|
|
@@ -39,7 +41,6 @@ const TextField = memo(({label, tooltip, section = null, subsection = null, fiel
|
|
|
39
41
|
let name = subsection ? `${section}-${subsection}-${fieldName}` : `${section}-${subsection}-${fieldName}`
|
|
40
42
|
|
|
41
43
|
const onChange = (e) => {
|
|
42
|
-
|
|
43
44
|
if ('number' !== type || min === null) {
|
|
44
45
|
setValue(e.target.value)
|
|
45
46
|
} else {
|
|
@@ -190,20 +191,15 @@ const EditorPanel = () => {
|
|
|
190
191
|
setFilteredData
|
|
191
192
|
} = useContext(Context)
|
|
192
193
|
|
|
193
|
-
const {minValue,maxValue} = useReduceData(config,
|
|
194
|
+
const {minValue,maxValue,existPositiveValue} = useReduceData(config,unfilteredData);
|
|
194
195
|
const {paletteName,isPaletteReversed,filteredPallets,filteredQualitative,dispatch} = useColorPalette(colorPalettes,config);
|
|
195
196
|
useEffect(()=>{
|
|
196
197
|
if(paletteName) updateConfig({...config, palette:paletteName})
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
}, [paletteName])
|
|
199
|
+
|
|
199
200
|
useEffect(()=>{
|
|
200
201
|
dispatch({type:"GET_PALETTE",payload:colorPalettes,paletteName:config.palette})
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
useEffect(() => {
|
|
204
|
-
dispatch({ type: 'GET_PALETTE', payload: colorPalettes, paletteName: config.palette })
|
|
205
|
-
}, [ dispatch, config.palette ])
|
|
206
|
-
|
|
202
|
+
}, [dispatch, config.palette]);
|
|
207
203
|
|
|
208
204
|
const filterOptions = [
|
|
209
205
|
{
|
|
@@ -225,6 +221,8 @@ const EditorPanel = () => {
|
|
|
225
221
|
})
|
|
226
222
|
|
|
227
223
|
const sortableItemStyles = {
|
|
224
|
+
animate: false,
|
|
225
|
+
animateReplay: true,
|
|
228
226
|
display: 'block',
|
|
229
227
|
boxSizing: 'border-box',
|
|
230
228
|
border: '1px solid #D1D1D1',
|
|
@@ -315,19 +313,25 @@ const EditorPanel = () => {
|
|
|
315
313
|
const addNewFilter = () => {
|
|
316
314
|
let filters = config.filters ? [ ...config.filters ] : []
|
|
317
315
|
|
|
318
|
-
filters.push({ values: [] })
|
|
316
|
+
filters.push({ values: [] });
|
|
319
317
|
|
|
320
|
-
updateConfig({ ...config, filters })
|
|
318
|
+
updateConfig({ ...config, filters });
|
|
321
319
|
}
|
|
322
320
|
|
|
323
321
|
const addNewSeries = (seriesKey) => {
|
|
324
322
|
let newSeries = config.series ? [ ...config.series ] : []
|
|
325
|
-
newSeries.push({ dataKey: seriesKey, type: 'Bar' })
|
|
326
|
-
updateConfig({ ...config, series: newSeries })
|
|
323
|
+
newSeries.push({ dataKey: seriesKey, type: 'Bar' });
|
|
324
|
+
updateConfig({ ...config, series: newSeries });
|
|
327
325
|
}
|
|
328
326
|
|
|
329
|
-
const
|
|
327
|
+
const sortSeries = (e) => {
|
|
328
|
+
const series = config.series[0].dataKey
|
|
329
|
+
const sorted = data.sort((a, b) => a[series] - b[series]);
|
|
330
|
+
const newData = e === "asc" ? sorted : sorted.reverse();
|
|
331
|
+
updateConfig({ ...config }, newData);
|
|
332
|
+
}
|
|
330
333
|
|
|
334
|
+
const removeSeries = (seriesKey) => {
|
|
331
335
|
|
|
332
336
|
let series = [ ...config.series ]
|
|
333
337
|
let seriesIndex = -1
|
|
@@ -428,13 +432,11 @@ const EditorPanel = () => {
|
|
|
428
432
|
return unique ? [ ...new Set(values) ] : values
|
|
429
433
|
}
|
|
430
434
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (config.visualizationType === 'Bar' && (config.orientation === 'horizontal' || config.orientation === 'regular') && config.visualizationSubType !== 'stacked') {
|
|
435
|
-
return true
|
|
435
|
+
const showBarStyleOptions = ()=>{
|
|
436
|
+
if (config.visualizationType === 'Bar' && config.visualizationSubType !== 'stacked' && (config.orientation==='horizontal' || config.orientation==='vertical') ) {
|
|
437
|
+
return ['flat','rounded','lollipop']
|
|
436
438
|
} else {
|
|
437
|
-
return
|
|
439
|
+
return ['flat','rounded']
|
|
438
440
|
}
|
|
439
441
|
}
|
|
440
442
|
|
|
@@ -494,6 +496,16 @@ const EditorPanel = () => {
|
|
|
494
496
|
|
|
495
497
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
496
498
|
}, [ config ])
|
|
499
|
+
|
|
500
|
+
// Set paired bars to be horizontal, even though that option doesn't display
|
|
501
|
+
useEffect(() => {
|
|
502
|
+
if(config.visualizationType === 'Paired Bar') {
|
|
503
|
+
updateConfig({
|
|
504
|
+
...config,
|
|
505
|
+
orientation: 'horizontal'
|
|
506
|
+
})
|
|
507
|
+
}
|
|
508
|
+
}, []);
|
|
497
509
|
|
|
498
510
|
useEffect(() => {
|
|
499
511
|
if (config.orientation === 'horizontal') {
|
|
@@ -516,7 +528,7 @@ const EditorPanel = () => {
|
|
|
516
528
|
{exclusion}
|
|
517
529
|
</div>
|
|
518
530
|
</div>
|
|
519
|
-
<
|
|
531
|
+
<button className="series-list__remove" onClick={() => removeExclusion(exclusion)}>×</button>
|
|
520
532
|
</li>
|
|
521
533
|
)
|
|
522
534
|
})}
|
|
@@ -534,8 +546,8 @@ const EditorPanel = () => {
|
|
|
534
546
|
</section>
|
|
535
547
|
)
|
|
536
548
|
}
|
|
537
|
-
const handleFilterChange = (idx1, idx2, filterIndex, filter) => {
|
|
538
549
|
|
|
550
|
+
const handleFilterChange = (idx1, idx2, filterIndex, filter) => {
|
|
539
551
|
let filterOrder = filter.values
|
|
540
552
|
let [ movedItem ] = filterOrder.splice(idx1, 1)
|
|
541
553
|
filterOrder.splice(idx2, 0, movedItem)
|
|
@@ -556,94 +568,51 @@ const EditorPanel = () => {
|
|
|
556
568
|
config.runtime.editorErrorMessage = 'Add a data series'
|
|
557
569
|
}
|
|
558
570
|
|
|
559
|
-
const section = config.orientation
|
|
560
|
-
const [warningMsg,
|
|
561
|
-
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
} else {
|
|
604
|
-
value = enteredValue
|
|
605
|
-
updateWarningMsg(function (presMsg) { return { ...presMsg, minMsg: '' } })
|
|
606
|
-
}
|
|
607
|
-
} else {
|
|
608
|
-
if (Number(enteredValue) > minValue) {
|
|
609
|
-
updateWarningMsg(function (presMsg) { return { ...presMsg, minMsg: 'Value must be less than '+ minValue }})
|
|
610
|
-
} else if (Number(enteredValue) > 0 ) {
|
|
611
|
-
updateWarningMsg(function (presMsg) { return { ...presMsg, minMsg: 'Value must be less than or equal to 0' }})
|
|
612
|
-
} else {
|
|
613
|
-
value = enteredValue
|
|
614
|
-
updateWarningMsg(function (presMsg) { return { ...presMsg, minMsg: '' }})
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
}
|
|
618
|
-
updateField(section, null, 'min', value)
|
|
619
|
-
|
|
620
|
-
if (!enteredValue.length) {
|
|
621
|
-
updateWarningMsg(function (presMsg) { return {...presMsg, minMsg: ''}})
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
571
|
+
const section = config.orientation==='horizontal' ? 'xAxis' : 'yAxis';
|
|
572
|
+
const [warningMsg,setWarningMsg] = useState({maxMsg:'',minMsg:''});
|
|
573
|
+
|
|
574
|
+
const validateMaxValue = () => {
|
|
575
|
+
const enteredValue = config[section].max;
|
|
576
|
+
let message = '';
|
|
577
|
+
|
|
578
|
+
switch(true){
|
|
579
|
+
case (enteredValue && parseFloat(enteredValue) < parseFloat(maxValue) && existPositiveValue):
|
|
580
|
+
message = 'Max value must be more than '+ maxValue;
|
|
581
|
+
break;
|
|
582
|
+
case (enteredValue && parseFloat(enteredValue) < 0 && !existPositiveValue):
|
|
583
|
+
message = 'Value must be more than or equal to 0';
|
|
584
|
+
break;
|
|
585
|
+
default : message = '' ;
|
|
586
|
+
}
|
|
587
|
+
setWarningMsg(function(prevMsg){return{...prevMsg,maxMsg:message}});
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
const validateMinValue = ()=>{
|
|
592
|
+
const enteredValue = config[section].min;
|
|
593
|
+
let minVal = Number(minValue);
|
|
594
|
+
let message = '';
|
|
595
|
+
|
|
596
|
+
switch(true){
|
|
597
|
+
case (config.visualizationType === 'Line' && (enteredValue && parseFloat(enteredValue) > minVal)):
|
|
598
|
+
message = 'Value must be less than ' + minValue;
|
|
599
|
+
break;
|
|
600
|
+
case (enteredValue && minVal > 0 && parseFloat(enteredValue) > 0):
|
|
601
|
+
message = 'Value must be less than or equal to 0';
|
|
602
|
+
break;
|
|
603
|
+
case ( enteredValue && minVal < 0 && parseFloat(enteredValue) > minVal) :
|
|
604
|
+
message = 'Value must be less than ' + minValue;
|
|
605
|
+
break;
|
|
606
|
+
default : message = ''
|
|
607
|
+
};
|
|
608
|
+
setWarningMsg(function (prevMsg) { return {...prevMsg, minMsg: message}});
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
useEffect(()=>{
|
|
612
|
+
validateMinValue();
|
|
613
|
+
validateMaxValue();
|
|
614
|
+
},[minValue,maxValue,config]);
|
|
625
615
|
|
|
626
|
-
useEffect(() => {
|
|
627
|
-
if (config[section].max && config[section].max < maxValue) {
|
|
628
|
-
updateField(section,null,'max',maxValue)
|
|
629
|
-
updateWarningMsg(function (presMsg) {return {...presMsg, maxMsg: `Entered value ${config[section].max} is not valid `}})
|
|
630
|
-
}
|
|
631
|
-
}, [data,maxValue])
|
|
632
|
-
|
|
633
|
-
useEffect(() => {
|
|
634
|
-
if (config.visualizationType === 'Line') {
|
|
635
|
-
if (config[section].min && config[section].min > minValue) {
|
|
636
|
-
updateWarningMsg(function (presMsg) { return { ...presMsg, minMsg: `Entered value ${config[section].min} is not valid`}})
|
|
637
|
-
updateField(section,null,'min',minValue)
|
|
638
|
-
}
|
|
639
|
-
} else {
|
|
640
|
-
if (config[section].min && config[section].min < minValue) {
|
|
641
|
-
updateWarningMsg(function (presMsg) { return { ...presMsg, minMsg: `Entered value ${config[section].min} is not valid`}})
|
|
642
|
-
updateField(section,null,'min',minValue)
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}, [data,minValue])
|
|
646
|
-
|
|
647
616
|
return (
|
|
648
617
|
<ErrorBoundary component="EditorPanel">
|
|
649
618
|
{config.newViz && <Confirm/>}
|
|
@@ -661,27 +630,54 @@ const EditorPanel = () => {
|
|
|
661
630
|
</AccordionItemButton>
|
|
662
631
|
</AccordionItemHeading>
|
|
663
632
|
<AccordionItemPanel>
|
|
664
|
-
<Select value={config.visualizationType} fieldName="visualizationType" label="Chart Type" updateField={updateField} options={[ 'Pie', 'Line', 'Bar', 'Combo', 'Paired Bar']}/>
|
|
633
|
+
<Select value={config.visualizationType} fieldName="visualizationType" label="Chart Type" updateField={updateField} options={[ 'Pie', 'Line', 'Bar', 'Combo', 'Paired Bar' ]}/>
|
|
665
634
|
{config.visualizationType === 'Bar' && <Select value={config.visualizationSubType || 'Regular'} fieldName="visualizationSubType" label="Chart Subtype" updateField={updateField} options={[ 'regular', 'stacked' ]}/>}
|
|
666
635
|
{config.visualizationType === 'Bar' && <Select value={config.orientation || 'vertical'} fieldName="orientation" label="Orientation" updateField={updateField} options={[ 'vertical', 'horizontal' ]}/>}
|
|
636
|
+
{config.visualizationType === 'Bar' && <Select value={ config.isLollipopChart? 'lollipop': config.barStyle || 'flat'} fieldName="barStyle" label="bar style" updateField={updateField} options={showBarStyleOptions()}/>}
|
|
637
|
+
{(config.visualizationType === 'Bar' && config.barStyle==='rounded' ) && <Select value={config.tipRounding||'top'} fieldName="tipRounding" label="tip rounding" updateField={updateField} options={['top','full']}/>}
|
|
638
|
+
{(config.visualizationType === 'Bar' && config.barStyle==='rounded' ) && <Select value={config.roundingStyle||'standard'} fieldName="roundingStyle" label="rounding style" updateField={updateField} options={['standard','shallow','finger']}/>}
|
|
667
639
|
{(config.visualizationType === 'Bar' && config.orientation === 'horizontal') &&
|
|
668
640
|
<Select value={config.yAxis.labelPlacement || 'Below Bar'} section="yAxis" fieldName="labelPlacement" label="Label Placement" updateField={updateField} options={[ 'Below Bar', 'On Date/Category Axis' ]}/>
|
|
669
641
|
}
|
|
670
|
-
{(
|
|
671
|
-
<CheckBox value={config.
|
|
672
|
-
|
|
673
|
-
|
|
642
|
+
{config.orientation === 'horizontal' && (config.yAxis.labelPlacement === 'Below Bar' || config.yAxis.labelPlacement === 'On Date/Category Axis' || config.visualizationType === 'Paired Bar' ) ? (
|
|
643
|
+
<CheckBox value={config.yAxis.displayNumbersOnBar} section="yAxis" fieldName="displayNumbersOnBar" label={config.isLollipopChart ? 'Display Numbers after Bar' : 'Display Numbers on Bar'} updateField={updateField}/>
|
|
644
|
+
): config.visualizationType !== 'Pie' && (
|
|
645
|
+
<CheckBox value={config.labels} fieldName="labels" label="Display label on data" updateField={updateField}/>
|
|
646
|
+
)}
|
|
647
|
+
{config.visualizationType === 'Pie' && <Select fieldName="pieType" label="Pie Chart Type" updateField={updateField} options={[ 'Regular', 'Donut' ]}/>}
|
|
648
|
+
<TextField value={config.title} fieldName="title" label="Title" updateField={updateField} />
|
|
649
|
+
|
|
650
|
+
<TextField
|
|
651
|
+
value={config.superTitle}
|
|
652
|
+
updateField={updateField}
|
|
653
|
+
fieldName='superTitle'
|
|
654
|
+
label='Super Title'
|
|
655
|
+
placeholder='Super Title'
|
|
656
|
+
tooltip={
|
|
657
|
+
<Tooltip style={{textTransform: 'none'}}>
|
|
658
|
+
<Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
|
|
674
659
|
<Tooltip.Content>
|
|
675
|
-
|
|
660
|
+
<p>Super Title</p>
|
|
676
661
|
</Tooltip.Content>
|
|
677
662
|
</Tooltip>
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
663
|
+
}
|
|
664
|
+
/>
|
|
665
|
+
|
|
666
|
+
<TextField
|
|
667
|
+
type='textarea'
|
|
668
|
+
value={config.introText}
|
|
669
|
+
updateField={updateField}
|
|
670
|
+
fieldName='introText'
|
|
671
|
+
label='Intro Text'
|
|
672
|
+
tooltip={
|
|
673
|
+
<Tooltip style={{textTransform: 'none'}}>
|
|
674
|
+
<Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
|
|
675
|
+
<Tooltip.Content>
|
|
676
|
+
<p>Intro Text</p>
|
|
677
|
+
</Tooltip.Content>
|
|
678
|
+
</Tooltip>
|
|
679
|
+
}
|
|
680
|
+
/>
|
|
685
681
|
|
|
686
682
|
<TextField type="textarea" value={config.description} fieldName="description" label="Subtext" updateField={updateField} tooltip={
|
|
687
683
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
@@ -690,7 +686,23 @@ const EditorPanel = () => {
|
|
|
690
686
|
<p>Enter supporting text to display below the data visualization, if applicable. The following HTML tags are supported: strong, em, sup, and sub.</p>
|
|
691
687
|
</Tooltip.Content>
|
|
692
688
|
</Tooltip>
|
|
693
|
-
}/>
|
|
689
|
+
} />
|
|
690
|
+
|
|
691
|
+
<TextField
|
|
692
|
+
type='textarea'
|
|
693
|
+
value={config.footnotes}
|
|
694
|
+
updateField={updateField}
|
|
695
|
+
fieldName='footnotes'
|
|
696
|
+
label='Footnotes'
|
|
697
|
+
tooltip={
|
|
698
|
+
<Tooltip style={{textTransform: 'none'}}>
|
|
699
|
+
<Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
|
|
700
|
+
<Tooltip.Content>
|
|
701
|
+
<p>Footnotes</p>
|
|
702
|
+
</Tooltip.Content>
|
|
703
|
+
</Tooltip>
|
|
704
|
+
}
|
|
705
|
+
/>
|
|
694
706
|
|
|
695
707
|
{config.visualizationSubType !== 'horizontal' &&
|
|
696
708
|
<TextField type="number" value={config.height} fieldName="height" label="Chart Height" updateField={updateField}/>
|
|
@@ -711,17 +723,17 @@ const EditorPanel = () => {
|
|
|
711
723
|
{((!config.series || config.series.length === 0 || config.series.length < 2) && (config.visualizationType === 'Paired Bar')) && <p className="warning">Select two data series for paired bar chart (e.g., Male and Female).</p>}
|
|
712
724
|
{config.series && config.series.length !== 0 && (
|
|
713
725
|
<>
|
|
714
|
-
<
|
|
715
|
-
<
|
|
726
|
+
<fieldset>
|
|
727
|
+
<legend className="edit-label float-left">
|
|
716
728
|
Displaying
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
</Tooltip>
|
|
723
|
-
</
|
|
724
|
-
</
|
|
729
|
+
</legend>
|
|
730
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
731
|
+
<Tooltip.Target><Icon display="question" style={{ marginLeft: '0.5rem' }}/></Tooltip.Target>
|
|
732
|
+
<Tooltip.Content>
|
|
733
|
+
<p>A data series is a set of related data points plotted in a chart and typically represented in the chart legend.</p>
|
|
734
|
+
</Tooltip.Content>
|
|
735
|
+
</Tooltip>
|
|
736
|
+
</fieldset>
|
|
725
737
|
<ul className="series-list">
|
|
726
738
|
{config.series.map((series, i) => {
|
|
727
739
|
|
|
@@ -749,8 +761,8 @@ const EditorPanel = () => {
|
|
|
749
761
|
</div>
|
|
750
762
|
<span>
|
|
751
763
|
<span className="series-list__dropdown">{typeDropdown}</span>
|
|
752
|
-
{config.series.length > 1 &&
|
|
753
|
-
<
|
|
764
|
+
{config.series && config.series.length > 1 &&
|
|
765
|
+
<button className="series-list__remove" onClick={() => removeSeries(series.dataKey)}>×</button>
|
|
754
766
|
}
|
|
755
767
|
</span>
|
|
756
768
|
</li>
|
|
@@ -764,8 +776,8 @@ const EditorPanel = () => {
|
|
|
764
776
|
{series.dataKey}
|
|
765
777
|
</div>
|
|
766
778
|
</div>
|
|
767
|
-
{config.series.length > 1 &&
|
|
768
|
-
<
|
|
779
|
+
{config.series && config.series.length > 1 &&
|
|
780
|
+
<button className="series-list__remove" onClick={() => removeSeries(series.dataKey)}>×</button>
|
|
769
781
|
}
|
|
770
782
|
</li>
|
|
771
783
|
)
|
|
@@ -786,6 +798,14 @@ const EditorPanel = () => {
|
|
|
786
798
|
<Select value={config.confidenceKeys.lower || ''} section="confidenceKeys" fieldName="lower" label="Lower" updateField={updateField} initial="Select" options={getColumns()}/>
|
|
787
799
|
</>
|
|
788
800
|
)}
|
|
801
|
+
|
|
802
|
+
{config.series && config.series.length === 1 && <Select
|
|
803
|
+
fieldName="visualizationType"
|
|
804
|
+
label="Rank by Value"
|
|
805
|
+
initial="Select"
|
|
806
|
+
onChange={(e) => sortSeries(e.target.value)}
|
|
807
|
+
options={['asc', 'desc']} />}
|
|
808
|
+
|
|
789
809
|
</AccordionItemPanel>
|
|
790
810
|
</AccordionItem>
|
|
791
811
|
}
|
|
@@ -848,17 +868,17 @@ const EditorPanel = () => {
|
|
|
848
868
|
<CheckBox value={config.xAxis.hideAxis} section="xAxis" fieldName="hideAxis" label="Hide Axis" updateField={updateField} />
|
|
849
869
|
<CheckBox value={config.xAxis.hideLabel} section="xAxis" fieldName="hideLabel" label="Hide Label" updateField={updateField} />
|
|
850
870
|
<CheckBox value={config.xAxis.hideTicks} section="xAxis" fieldName="hideTicks" label="Hide Ticks" updateField={updateField} />
|
|
851
|
-
<TextField value={config.xAxis.max}
|
|
871
|
+
<TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='update max value' type='number' placeholder='Auto' updateField={updateField} />
|
|
852
872
|
<span style={{color:'red',display:'block'}} >{warningMsg.maxMsg}</span>
|
|
853
873
|
</>
|
|
854
|
-
: config.visualizationType !=='Pie' &&
|
|
874
|
+
: (config.visualizationType !=='Pie') &&
|
|
855
875
|
<>
|
|
856
876
|
<CheckBox value={config.yAxis.hideAxis} section="yAxis" fieldName="hideAxis" label="Hide Axis" updateField={updateField} />
|
|
857
877
|
<CheckBox value={config.yAxis.hideLabel} section="yAxis" fieldName="hideLabel" label="Hide Label" updateField={updateField} />
|
|
858
878
|
<CheckBox value={config.yAxis.hideTicks} section="yAxis" fieldName="hideTicks" label="Hide Ticks" updateField={updateField} />
|
|
859
|
-
<TextField value={config.yAxis.max} type='number' label='update max value' placeholder='Auto'
|
|
879
|
+
<TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='update max value' placeholder='Auto' updateField={updateField} />
|
|
860
880
|
<span style={{color:'red',display:'block'}} >{warningMsg.maxMsg}</span>
|
|
861
|
-
<TextField value={config.yAxis.min} type='number' label='update min value' placeholder='Auto'
|
|
881
|
+
<TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='update min value' placeholder='Auto' updateField={updateField} />
|
|
862
882
|
<span style={{color:'red',display:'block'}} >{warningMsg.minMsg}</span>
|
|
863
883
|
</>
|
|
864
884
|
}
|
|
@@ -926,7 +946,9 @@ const EditorPanel = () => {
|
|
|
926
946
|
<>
|
|
927
947
|
{config.exclusions.keys.length > 0 &&
|
|
928
948
|
<>
|
|
929
|
-
<
|
|
949
|
+
<fieldset>
|
|
950
|
+
<legend className="edit-label">Excluded Keys</legend>
|
|
951
|
+
</fieldset>
|
|
930
952
|
<ExclusionsList/>
|
|
931
953
|
</>
|
|
932
954
|
}
|
|
@@ -989,7 +1011,9 @@ const EditorPanel = () => {
|
|
|
989
1011
|
<>
|
|
990
1012
|
{config.exclusions.keys.length > 0 &&
|
|
991
1013
|
<>
|
|
992
|
-
<
|
|
1014
|
+
<fieldset>
|
|
1015
|
+
<legend className="edit-label">Excluded Keys</legend>
|
|
1016
|
+
</fieldset>
|
|
993
1017
|
<ExclusionsList/>
|
|
994
1018
|
</>
|
|
995
1019
|
}
|
|
@@ -1039,6 +1063,7 @@ const EditorPanel = () => {
|
|
|
1039
1063
|
<Select value={config.legend.behavior} section="legend" fieldName="behavior" label="Legend Behavior (When clicked)" updateField={updateField} options={[ 'highlight', 'isolate' ]}/>
|
|
1040
1064
|
<TextField value={config.legend.label} section="legend" fieldName="label" label="Title" updateField={updateField}/>
|
|
1041
1065
|
<Select value={config.legend.position} section="legend" fieldName="position" label="Position" updateField={updateField} options={[ 'right', 'left' ]}/>
|
|
1066
|
+
<TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
|
|
1042
1067
|
</AccordionItemPanel>
|
|
1043
1068
|
</AccordionItem>
|
|
1044
1069
|
|
|
@@ -1139,12 +1164,12 @@ const EditorPanel = () => {
|
|
|
1139
1164
|
|
|
1140
1165
|
{config.isLollipopChart &&
|
|
1141
1166
|
<>
|
|
1142
|
-
<
|
|
1143
|
-
<
|
|
1167
|
+
<fieldset className="header">
|
|
1168
|
+
<legend className="edit-label">Lollipop Shape</legend>
|
|
1144
1169
|
<div onChange={(e) => {
|
|
1145
1170
|
setLollipopShape(e.target.value)
|
|
1146
1171
|
}}>
|
|
1147
|
-
<label>
|
|
1172
|
+
<label className="radio-label">
|
|
1148
1173
|
<input
|
|
1149
1174
|
type="radio"
|
|
1150
1175
|
name="lollipopShape"
|
|
@@ -1153,7 +1178,7 @@ const EditorPanel = () => {
|
|
|
1153
1178
|
/>
|
|
1154
1179
|
Circle
|
|
1155
1180
|
</label>
|
|
1156
|
-
<label>
|
|
1181
|
+
<label className="radio-label">
|
|
1157
1182
|
<input
|
|
1158
1183
|
type="radio"
|
|
1159
1184
|
name="lollipopShape"
|
|
@@ -1164,7 +1189,7 @@ const EditorPanel = () => {
|
|
|
1164
1189
|
</label>
|
|
1165
1190
|
</div>
|
|
1166
1191
|
|
|
1167
|
-
</
|
|
1192
|
+
</fieldset>
|
|
1168
1193
|
<Select value={config.lollipopColorStyle ? config.lollipopColorStyle : 'two-tone'} fieldName="lollipopColorStyle" label="Lollipop Color Style" updateField={updateField} options={[ 'regular', 'two-tone' ]}/>
|
|
1169
1194
|
<Select value={config.lollipopSize ? config.lollipopSize : 'small'} fieldName="lollipopSize" label="Lollipop Size" updateField={updateField} options={[ 'small', 'medium', 'large' ]}/>
|
|
1170
1195
|
</>
|
|
@@ -1172,10 +1197,14 @@ const EditorPanel = () => {
|
|
|
1172
1197
|
|
|
1173
1198
|
<Select value={config.fontSize} fieldName="fontSize" label="Font Size" updateField={updateField} options={[ 'small', 'medium', 'large' ]}/>
|
|
1174
1199
|
|
|
1175
|
-
{config.series?.some(series => series.type === 'Bar') &&
|
|
1200
|
+
{config.series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar') &&
|
|
1176
1201
|
<Select value={config.barHasBorder} fieldName="barHasBorder" label="Bar Borders" updateField={updateField} options={[ 'true', 'false' ]}/>
|
|
1177
1202
|
}
|
|
1178
1203
|
|
|
1204
|
+
{/*<CheckBox value={config.animate} fieldName="animate" label="Animate Visualization" updateField={updateField} />*/}
|
|
1205
|
+
|
|
1206
|
+
{/*<CheckBox value={config.animateReplay} fieldName="animateReplay" label="Replay Animation When Filters Are Changed" updateField={updateField} />*/}
|
|
1207
|
+
|
|
1179
1208
|
{((config.series?.some(series => series.type === 'Line') && config.visualizationType === 'Combo') || config.visualizationType === 'Line') &&
|
|
1180
1209
|
<Select value={config.lineDatapointStyle} fieldName="lineDatapointStyle" label="Line Datapoint Style" updateField={updateField} options={[ 'hidden', 'hover', 'always show' ]}/>
|
|
1181
1210
|
}
|
|
@@ -1184,10 +1213,15 @@ const EditorPanel = () => {
|
|
|
1184
1213
|
<span className="edit-label">Header Theme</span>
|
|
1185
1214
|
<ul className="color-palette">
|
|
1186
1215
|
{headerColors.map((palette) => (
|
|
1187
|
-
<
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1216
|
+
<button
|
|
1217
|
+
title={palette}
|
|
1218
|
+
key={palette}
|
|
1219
|
+
onClick={(e) => {
|
|
1220
|
+
e.preventDefault();
|
|
1221
|
+
updateConfig({ ...config, theme: palette })
|
|
1222
|
+
}}
|
|
1223
|
+
className={config.theme === palette ? 'selected ' + palette : palette}>
|
|
1224
|
+
</button>
|
|
1191
1225
|
))}
|
|
1192
1226
|
</ul>
|
|
1193
1227
|
</label>
|
|
@@ -1213,13 +1247,19 @@ const EditorPanel = () => {
|
|
|
1213
1247
|
}
|
|
1214
1248
|
|
|
1215
1249
|
return (
|
|
1216
|
-
<
|
|
1217
|
-
|
|
1218
|
-
|
|
1250
|
+
<button
|
|
1251
|
+
title={palette}
|
|
1252
|
+
key={palette}
|
|
1253
|
+
onClick={(e) => {
|
|
1254
|
+
e.preventDefault();
|
|
1255
|
+
updateConfig({ ...config, palette })
|
|
1256
|
+
}}
|
|
1257
|
+
className={config.palette === palette ? 'selected' : ''}
|
|
1258
|
+
>
|
|
1219
1259
|
<span style={colorOne}></span>
|
|
1220
1260
|
<span style={colorTwo}></span>
|
|
1221
1261
|
<span style={colorThree}></span>
|
|
1222
|
-
</
|
|
1262
|
+
</button>
|
|
1223
1263
|
)
|
|
1224
1264
|
})}
|
|
1225
1265
|
</ul>
|
|
@@ -1241,22 +1281,25 @@ const EditorPanel = () => {
|
|
|
1241
1281
|
|
|
1242
1282
|
|
|
1243
1283
|
return (
|
|
1244
|
-
<
|
|
1245
|
-
|
|
1246
|
-
|
|
1284
|
+
<button
|
|
1285
|
+
title={palette}
|
|
1286
|
+
key={palette}
|
|
1287
|
+
onClick={(e) => {
|
|
1288
|
+
e.preventDefault();
|
|
1289
|
+
updateConfig({ ...config, palette })
|
|
1290
|
+
}}
|
|
1291
|
+
className={config.palette === palette ? 'selected' : ''}
|
|
1292
|
+
>
|
|
1247
1293
|
<span style={colorOne}></span>
|
|
1248
1294
|
<span style={colorTwo}></span>
|
|
1249
1295
|
<span style={colorThree}></span>
|
|
1250
|
-
</
|
|
1296
|
+
</button>
|
|
1251
1297
|
)
|
|
1252
1298
|
})}
|
|
1253
1299
|
</ul>
|
|
1254
1300
|
|
|
1255
1301
|
{config.visualizationType !== 'Pie' && (
|
|
1256
1302
|
<>
|
|
1257
|
-
{config.orientation !== 'horizontal' &&
|
|
1258
|
-
<CheckBox value={config.labels} fieldName="labels" label="Display label on data" updateField={updateField}/>
|
|
1259
|
-
}
|
|
1260
1303
|
<TextField value={config.dataCutoff} type="number" fieldName="dataCutoff" className="number-narrow" label="Data Cutoff" updateField={updateField} tooltip={
|
|
1261
1304
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
1262
1305
|
<Tooltip.Target><Icon display="question" style={{ marginLeft: '0.5rem' }}/></Tooltip.Target>
|
|
@@ -1299,10 +1342,31 @@ const EditorPanel = () => {
|
|
|
1299
1342
|
</Tooltip.Content>
|
|
1300
1343
|
</Tooltip>
|
|
1301
1344
|
}/>
|
|
1345
|
+
<TextField
|
|
1346
|
+
value={config.table.caption}
|
|
1347
|
+
updateField={updateField}
|
|
1348
|
+
section='table'
|
|
1349
|
+
type='textarea'
|
|
1350
|
+
fieldName='caption'
|
|
1351
|
+
label='Data Table Caption'
|
|
1352
|
+
placeholder=' Data table'
|
|
1353
|
+
tooltip={
|
|
1354
|
+
<Tooltip style={{textTransform: 'none'}}>
|
|
1355
|
+
<Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
|
|
1356
|
+
<Tooltip.Content>
|
|
1357
|
+
<p>Enter a description of the data table to be read by screen readers.</p>
|
|
1358
|
+
</Tooltip.Content>
|
|
1359
|
+
</Tooltip>
|
|
1360
|
+
}
|
|
1361
|
+
/>
|
|
1362
|
+
<CheckBox value={config.table.limitHeight} section="table" fieldName="limitHeight" label="Limit Table Height" updateField={updateField}/>
|
|
1363
|
+
{config.table.limitHeight && (
|
|
1364
|
+
<TextField value={config.table.height} section="table" fieldName='height' label='Data Table Height' type="number" min="0" max="500" placeholder='Height(px)' updateField={updateField}/>
|
|
1365
|
+
)}
|
|
1302
1366
|
<CheckBox value={config.table.expanded} section="table" fieldName="expanded" label="Expanded by Default" updateField={updateField}/>
|
|
1303
1367
|
<CheckBox value={config.table.download} section="table" fieldName="download" label="Display Download Button" updateField={updateField}/>
|
|
1304
1368
|
<TextField value={config.table.label} section="table" fieldName="label" label="Label" updateField={updateField}/>
|
|
1305
|
-
|
|
1369
|
+
{config.visualizationType !== 'Pie' && <TextField value={config.table.indexLabel} section="table" fieldName="indexLabel" label="Index Column Header" updateField={updateField}/>}
|
|
1306
1370
|
</AccordionItemPanel>
|
|
1307
1371
|
</AccordionItem>
|
|
1308
1372
|
</Accordion>
|