@cdc/core 4.23.10 → 4.23.11
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/LICENSE +201 -0
- package/assets/icon-deviation-bar.svg +1 -0
- package/components/DataTable/DataTable.tsx +205 -0
- package/components/DataTable/components/BoxplotHeader.tsx +16 -0
- package/components/DataTable/components/CellAnchor.tsx +44 -0
- package/components/DataTable/components/ChartHeader.tsx +91 -0
- package/components/DataTable/components/ExpandCollapse.tsx +21 -0
- package/components/DataTable/components/Icons.tsx +10 -0
- package/components/DataTable/components/MapHeader.tsx +56 -0
- package/components/DataTable/components/SkipNav.tsx +7 -0
- package/components/DataTable/helpers/boxplotCellMatrix.tsx +64 -0
- package/components/DataTable/helpers/chartCellMatrix.tsx +78 -0
- package/components/DataTable/helpers/customSort.ts +55 -0
- package/components/DataTable/helpers/getChartCellValue.ts +55 -0
- package/components/DataTable/helpers/getDataSeriesColumns.ts +28 -0
- package/components/DataTable/helpers/getSeriesName.ts +26 -0
- package/components/DataTable/helpers/mapCellMatrix.tsx +56 -0
- package/components/DataTable/helpers/regionCellMatrix.tsx +13 -0
- package/components/DataTable/helpers/standardizeState.js +76 -0
- package/components/DataTable/index.ts +1 -0
- package/components/DataTable/types/TableConfig.ts +57 -0
- package/components/DownloadButton.tsx +29 -0
- package/components/LegendCircle.jsx +2 -2
- package/components/Table/Table.tsx +49 -0
- package/components/Table/components/Cell.tsx +9 -0
- package/components/Table/components/GroupRow.tsx +16 -0
- package/components/Table/components/Row.tsx +19 -0
- package/components/Table/index.ts +1 -0
- package/components/Table/types/CellMatrix.ts +4 -0
- package/components/_stories/DataTable.stories.tsx +62 -0
- package/components/_stories/Table.stories.tsx +53 -0
- package/components/_stories/_mocks/dashboard_no_filter.json +121 -0
- package/components/_stories/_mocks/example-city-state.json +808 -0
- package/components/_stories/styles.scss +9 -0
- package/components/managers/{DataDesigner.jsx → DataDesigner.tsx} +96 -87
- package/components/ui/Title/Title.scss +95 -0
- package/components/ui/Title/index.tsx +34 -0
- package/components/ui/_stories/Title.stories.tsx +21 -0
- package/helpers/DataTransform.ts +45 -18
- package/helpers/cove/string.ts +11 -0
- package/helpers/fetchRemoteData.js +1 -1
- package/package.json +2 -2
- package/styles/_data-table.scss +1 -0
- package/styles/heading-colors.scss +0 -3
- package/styles/v2/layout/_component.scss +0 -11
- package/types/Axis.ts +6 -0
- package/types/Color.ts +5 -0
- package/types/ComponentStyles.ts +7 -0
- package/types/ComponentThemes.ts +13 -0
- package/types/EditorColumnProperties.ts +8 -0
- package/types/Runtime.ts +9 -0
- package/types/Series.ts +1 -0
- package/types/Visualization.ts +21 -0
- package/components/DataTable.jsx +0 -754
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect } from 'react'
|
|
2
2
|
|
|
3
3
|
import Button from '../elements/Button'
|
|
4
4
|
import Card from '../elements/Card'
|
|
@@ -6,77 +6,109 @@ import Card from '../elements/Card'
|
|
|
6
6
|
import { DATA_TABLE_VERTICAL, DATA_TABLE_HORIZONTAL, DATA_TABLE_SINGLE_ROW, DATA_TABLE_MULTI_ROW } from '../../templates/dataDesignerTables'
|
|
7
7
|
import '../../styles/v2/components/data-designer.scss'
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type DataDesignerProps = {
|
|
10
|
+
configureData?: any // todo: add description here when understood better
|
|
11
|
+
updateDescriptionProp?: () => void // used to update data description fields
|
|
12
|
+
visualizationKey?: any // todo: add description here when understood better
|
|
13
|
+
dataKey?: string // appears to be the data file name, ie valid-data.csv
|
|
14
|
+
config?: any // can be one of many different types of chart configs that aren't fully established yet
|
|
15
|
+
setConfig?: (newConfig: any) => void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const DataDesigner = (props: DataDesignerProps) => {
|
|
10
19
|
const { configureData, updateDescriptionProp, visualizationKey, dataKey, config, setConfig } = props
|
|
20
|
+
const hasDataOrientation = config?.visualizationType !== 'Forest Plot'
|
|
21
|
+
const hasMultipleSeries = config?.visualizationType !== 'Forest Plot'
|
|
22
|
+
const hasRowSelection = config?.visualizationType !== 'Forest Plot'
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (config?.visualizationType === 'Forest Plot') {
|
|
26
|
+
// needed to properly set data up?
|
|
27
|
+
setConfig({
|
|
28
|
+
...config,
|
|
29
|
+
dataDescription: {
|
|
30
|
+
series: true,
|
|
31
|
+
horizontal: false,
|
|
32
|
+
singleRow: true
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
}, [])
|
|
11
37
|
|
|
12
38
|
return (
|
|
13
39
|
<div className='cove-data-designer__container'>
|
|
14
40
|
<div className='mb-2'>
|
|
15
41
|
<div className='cove-heading--3 fw-bold mb-1'>Describe Data</div>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
className=
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
className=
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
{hasDataOrientation && (
|
|
43
|
+
<>
|
|
44
|
+
<div className='cove-heading--3 fw-normal mb-1'>Data Orientation</div>
|
|
45
|
+
<div className='grid grid-gap-2 mb-4'>
|
|
46
|
+
<div className='column'>
|
|
47
|
+
<button
|
|
48
|
+
className={'cove-data-designer__button' + (configureData.dataDescription && configureData.dataDescription.horizontal === false ? ' active' : '')}
|
|
49
|
+
onClick={() => {
|
|
50
|
+
updateDescriptionProp(visualizationKey, dataKey, 'horizontal', false)
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
<Card>
|
|
54
|
+
<strong className='cove-heading--3'>Vertical</strong>
|
|
55
|
+
<p className='mb-1'>
|
|
56
|
+
Values for map geography or chart date/category axis are contained in a single <em>column</em>.
|
|
57
|
+
</p>
|
|
58
|
+
{DATA_TABLE_VERTICAL}
|
|
59
|
+
</Card>
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
62
|
+
<div className='column'>
|
|
63
|
+
<button
|
|
64
|
+
className={'cove-data-designer__button' + (configureData.dataDescription && configureData.dataDescription.horizontal === true ? ' active' : '')}
|
|
65
|
+
onClick={() => {
|
|
66
|
+
updateDescriptionProp(visualizationKey, dataKey, 'horizontal', true)
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
<Card>
|
|
70
|
+
<strong className='cove-heading--3'>Horizontal</strong>
|
|
71
|
+
<p className='mb-1'>
|
|
72
|
+
Values for map geography or chart date/category axis are contained in a single <em>row</em>
|
|
73
|
+
</p>
|
|
74
|
+
{DATA_TABLE_HORIZONTAL}
|
|
75
|
+
</Card>
|
|
76
|
+
</button>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</>
|
|
80
|
+
)}
|
|
51
81
|
</div>
|
|
52
82
|
{configureData.dataDescription && (
|
|
53
83
|
<>
|
|
54
|
-
|
|
55
|
-
<div className='mb-
|
|
56
|
-
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
{hasMultipleSeries && (
|
|
85
|
+
<div className='mb-2'>
|
|
86
|
+
<div className='mb-1'>Are there multiple series represented in your data?</div>
|
|
87
|
+
<div>
|
|
88
|
+
<Button
|
|
89
|
+
style={{ backgroundColor: '#00345d' }}
|
|
90
|
+
hoverStyle={{ backgroundColor: '#015daa' }}
|
|
91
|
+
className='mr-1'
|
|
92
|
+
onClick={() => {
|
|
93
|
+
updateDescriptionProp(visualizationKey, dataKey, 'series', true)
|
|
94
|
+
}}
|
|
95
|
+
active={configureData.dataDescription.series === true}
|
|
96
|
+
>
|
|
97
|
+
Yes
|
|
98
|
+
</Button>
|
|
99
|
+
<Button
|
|
100
|
+
style={{ backgroundColor: '#00345d' }}
|
|
101
|
+
hoverStyle={{ backgroundColor: '#015daa' }}
|
|
102
|
+
onClick={() => {
|
|
103
|
+
updateDescriptionProp(visualizationKey, dataKey, 'series', false)
|
|
104
|
+
}}
|
|
105
|
+
active={configureData.dataDescription.series === false}
|
|
106
|
+
>
|
|
107
|
+
No
|
|
108
|
+
</Button>
|
|
109
|
+
</div>
|
|
78
110
|
</div>
|
|
79
|
-
|
|
111
|
+
)}
|
|
80
112
|
{configureData.dataDescription.horizontal === true && configureData.dataDescription.series === true && (
|
|
81
113
|
<div className='mb-2'>
|
|
82
114
|
<div className='mb-1'>Which property in the dataset represents which series the row is describing?</div>
|
|
@@ -95,7 +127,7 @@ const DataDesigner = props => {
|
|
|
95
127
|
</select>
|
|
96
128
|
</div>
|
|
97
129
|
)}
|
|
98
|
-
{configureData.dataDescription.horizontal === false && configureData.dataDescription.series === true && (
|
|
130
|
+
{configureData.dataDescription.horizontal === false && configureData.dataDescription.series === true && hasRowSelection && (
|
|
99
131
|
<>
|
|
100
132
|
<div className='mb-2'>
|
|
101
133
|
<div className='mb-1'>Are the series values in your data represented in a single row, or across multiple rows?</div>
|
|
@@ -247,7 +279,7 @@ const DataDesigner = props => {
|
|
|
247
279
|
{config?.visualizationType === 'Forest Plot' && (
|
|
248
280
|
<>
|
|
249
281
|
<div className='mb-2'>
|
|
250
|
-
<div className='mb-1'>Which column represents the
|
|
282
|
+
<div className='mb-1'>Which column represents the Study ID?</div>
|
|
251
283
|
<select
|
|
252
284
|
onChange={e => {
|
|
253
285
|
setConfig({
|
|
@@ -337,29 +369,6 @@ const DataDesigner = props => {
|
|
|
337
369
|
))}
|
|
338
370
|
</select>
|
|
339
371
|
</div>
|
|
340
|
-
|
|
341
|
-
<div className='mb-2'>
|
|
342
|
-
<div className='mb-1'>Which shape do you want to use in your forest plot?</div>
|
|
343
|
-
<select
|
|
344
|
-
onChange={e => {
|
|
345
|
-
setConfig({
|
|
346
|
-
...config,
|
|
347
|
-
forestPlot: {
|
|
348
|
-
...config.forestPlot,
|
|
349
|
-
shape: e.target.value
|
|
350
|
-
}
|
|
351
|
-
})
|
|
352
|
-
}}
|
|
353
|
-
defaultValue={'Select'}
|
|
354
|
-
>
|
|
355
|
-
<option value=''>Choose an option</option>
|
|
356
|
-
{['text', 'circle', 'square', 'diamond'].map((value, index) => (
|
|
357
|
-
<option value={value} key={index}>
|
|
358
|
-
{value}
|
|
359
|
-
</option>
|
|
360
|
-
))}
|
|
361
|
-
</select>
|
|
362
|
-
</div>
|
|
363
372
|
</>
|
|
364
373
|
)}
|
|
365
374
|
</>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
.cove-component__header {
|
|
2
|
+
position: relative;
|
|
3
|
+
padding: 0.6em 0.8em;
|
|
4
|
+
margin: 0;
|
|
5
|
+
color: #fff;
|
|
6
|
+
font-size: 1.1em;
|
|
7
|
+
|
|
8
|
+
border-top-left-radius: 3px;
|
|
9
|
+
border-top-right-radius: 3px;
|
|
10
|
+
|
|
11
|
+
&.mb-0 {
|
|
12
|
+
margin-bottom: 0 !important;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
em {
|
|
16
|
+
font-style: italic;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
strong {
|
|
20
|
+
font-weight: bold;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&:not(:empty) {
|
|
24
|
+
padding: 0.6em 0.8em;
|
|
25
|
+
border-bottom-width: 4px;
|
|
26
|
+
border-bottom-style: solid;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&.bite-header {
|
|
30
|
+
margin-bottom: 0 !important;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// THEMES
|
|
34
|
+
&.theme-purple {
|
|
35
|
+
background: #712177;
|
|
36
|
+
border-bottom-color: #b890bb;
|
|
37
|
+
}
|
|
38
|
+
&.theme-brown {
|
|
39
|
+
background: #705043;
|
|
40
|
+
border-bottom-color: #ad907b;
|
|
41
|
+
}
|
|
42
|
+
&.theme-teal {
|
|
43
|
+
background: #00695c;
|
|
44
|
+
border-bottom-color: #4ebaaa;
|
|
45
|
+
}
|
|
46
|
+
&.theme-pink {
|
|
47
|
+
background: #af4448;
|
|
48
|
+
border-bottom-color: #e57373;
|
|
49
|
+
}
|
|
50
|
+
&.theme-orange {
|
|
51
|
+
background: #bb4d00;
|
|
52
|
+
border-bottom-color: #ffad42;
|
|
53
|
+
}
|
|
54
|
+
&.theme-slate {
|
|
55
|
+
background: #29434e;
|
|
56
|
+
border-bottom-color: #7e9ba5;
|
|
57
|
+
}
|
|
58
|
+
&.theme-indigo {
|
|
59
|
+
background: #26418f;
|
|
60
|
+
border-bottom-color: #92a6dd;
|
|
61
|
+
}
|
|
62
|
+
&.theme-cyan {
|
|
63
|
+
background: #007b91;
|
|
64
|
+
border-bottom-color: #65b0bd;
|
|
65
|
+
}
|
|
66
|
+
&.theme-green {
|
|
67
|
+
background: #4b830d;
|
|
68
|
+
border-bottom-color: #84bc49;
|
|
69
|
+
}
|
|
70
|
+
&.theme-amber {
|
|
71
|
+
background: #fbab18;
|
|
72
|
+
border-bottom-color: #ffd54f;
|
|
73
|
+
}
|
|
74
|
+
&.theme-blue {
|
|
75
|
+
background: #005eaa;
|
|
76
|
+
border-bottom-color: #88c3ea;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
&.mb-0 {
|
|
80
|
+
margin-bottom: 0 !important;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// add additional space below title if needed
|
|
85
|
+
.map-title.cove-component__header,
|
|
86
|
+
.type-chart .cove-component__header {
|
|
87
|
+
&:not(:empty) {
|
|
88
|
+
margin: 0 0 1rem 0 !important;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// fix sparkline bottom margin gap
|
|
93
|
+
.type-sparkline.type-chart .cove-component__header {
|
|
94
|
+
margin: 0px !important;
|
|
95
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import parse from 'html-react-parser'
|
|
3
|
+
import './Title.scss'
|
|
4
|
+
|
|
5
|
+
type HeaderProps = {
|
|
6
|
+
title?: string
|
|
7
|
+
isDashboard?: boolean
|
|
8
|
+
superTitle?: string
|
|
9
|
+
classes?: string[]
|
|
10
|
+
style?: React.CSSProperties
|
|
11
|
+
showTitle?: boolean
|
|
12
|
+
ariaLevel?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const Title = (props: HeaderProps) => {
|
|
16
|
+
const { isDashboard, title, superTitle, classes = [], showTitle = true, ariaLevel = 2 } = props
|
|
17
|
+
|
|
18
|
+
// standard classes every vis should have
|
|
19
|
+
const updatedClasses = ['cove-component__header', 'component__header', ...classes]
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
title &&
|
|
23
|
+
showTitle && (
|
|
24
|
+
<header className={updatedClasses.join(' ')} aria-hidden='true' style={props.style} aria-level={ariaLevel}>
|
|
25
|
+
{superTitle && <sup>{parse(superTitle)}</sup>}
|
|
26
|
+
<div>
|
|
27
|
+
{parse(title)} {isDashboard}
|
|
28
|
+
</div>
|
|
29
|
+
</header>
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default Title
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
|
|
3
|
+
import Title from '../Title'
|
|
4
|
+
|
|
5
|
+
const meta: Meta = {
|
|
6
|
+
title: 'Components/Atoms/Title',
|
|
7
|
+
component: Title
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type Story = StoryObj
|
|
11
|
+
|
|
12
|
+
export const Primary: Story = {
|
|
13
|
+
args: {
|
|
14
|
+
title: 'My Title',
|
|
15
|
+
superTitle: 'My super title',
|
|
16
|
+
isDashboard: false,
|
|
17
|
+
classes: ['theme-blue']
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default meta
|
package/helpers/DataTransform.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type DataArray = Record<string,any>[]
|
|
1
|
+
type DataArray = Record<string, any>[]
|
|
2
2
|
|
|
3
3
|
export class DataTransform {
|
|
4
4
|
constants: any
|
|
@@ -17,12 +17,12 @@ export class DataTransform {
|
|
|
17
17
|
const errorsFound: any[] = []
|
|
18
18
|
|
|
19
19
|
// Empty data
|
|
20
|
-
if (0 === data.length) {
|
|
20
|
+
if (!data || 0 === data.length) {
|
|
21
21
|
errorsFound.push(this.constants.errorMessageEmptyData)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
// Does it have the correct data structure?
|
|
25
|
-
if (!data
|
|
25
|
+
if (!data?.filter || data.filter(row => typeof row !== 'object').length > 0) {
|
|
26
26
|
errorsFound.push(this.constants.errorMessageFormat)
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -49,6 +49,10 @@ export class DataTransform {
|
|
|
49
49
|
|
|
50
50
|
//Performs standardizations based on developer provided description of the data
|
|
51
51
|
developerStandardize(data, description) {
|
|
52
|
+
if (!data) {
|
|
53
|
+
return []
|
|
54
|
+
}
|
|
55
|
+
|
|
52
56
|
//Validate the description object
|
|
53
57
|
if (!description) {
|
|
54
58
|
return undefined
|
|
@@ -98,7 +102,7 @@ export class DataTransform {
|
|
|
98
102
|
|
|
99
103
|
return standardized
|
|
100
104
|
} else {
|
|
101
|
-
let standardized: {key: string
|
|
105
|
+
let standardized: { key: string; value: any }[] = []
|
|
102
106
|
|
|
103
107
|
data.forEach(row => {
|
|
104
108
|
let nonNumericKeys: string[] = []
|
|
@@ -218,7 +222,7 @@ export class DataTransform {
|
|
|
218
222
|
*/
|
|
219
223
|
cleanData(data: DataArray, excludeKey, testing = false): DataArray {
|
|
220
224
|
let cleanedupData: DataArray = []
|
|
221
|
-
if(!Array.isArray(data)) debugger
|
|
225
|
+
if (!Array.isArray(data)) debugger
|
|
222
226
|
if (testing) console.log('## Data to clean=', data)
|
|
223
227
|
if (excludeKey === undefined) {
|
|
224
228
|
console.log('COVE: cleanData excludeKey undefined')
|
|
@@ -228,7 +232,7 @@ export class DataTransform {
|
|
|
228
232
|
if (testing) console.log('clean', i, ' d', d)
|
|
229
233
|
let cleaned = {}
|
|
230
234
|
Object.keys(d).forEach(function (key) {
|
|
231
|
-
const value = d[key]
|
|
235
|
+
const value = d[key]
|
|
232
236
|
if (key === excludeKey) {
|
|
233
237
|
// pass thru
|
|
234
238
|
cleaned[key] = value
|
|
@@ -259,21 +263,44 @@ export class DataTransform {
|
|
|
259
263
|
return cleanedupData
|
|
260
264
|
}
|
|
261
265
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (testing) console.log('clean', data)
|
|
265
|
-
let cleaned = ''
|
|
266
|
+
applySuppression = (data, suppressedData) => {
|
|
267
|
+
if (!suppressedData || suppressedData.length === 0) return data
|
|
266
268
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
269
|
+
// Create a new array to store the result without modifying the original data
|
|
270
|
+
const result = data.map(item => {
|
|
271
|
+
// Create a new object to store the updated item without modifying the original item
|
|
272
|
+
const newItem = { ...item }
|
|
273
|
+
|
|
274
|
+
// For each suppressedData item
|
|
275
|
+
for (let i = 0; i < suppressedData.length; i++) {
|
|
276
|
+
// If the object contains the column and its value matches the suppressed one
|
|
277
|
+
if (newItem[suppressedData[i].column] && newItem[suppressedData[i].column] === suppressedData[i].value) {
|
|
278
|
+
// Replace the value with the label in the new object
|
|
279
|
+
newItem[suppressedData[i].column] = suppressedData[i].label
|
|
280
|
+
}
|
|
273
281
|
}
|
|
274
282
|
|
|
275
|
-
|
|
276
|
-
|
|
283
|
+
return newItem
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
return result
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// clean out %, $, commas from numbers when needing to do sorting!
|
|
290
|
+
cleanDataPoint(data, testing = false) {
|
|
291
|
+
if (testing) console.log('clean', data)
|
|
292
|
+
let cleaned = ''
|
|
293
|
+
|
|
294
|
+
// remove comma and dollar signs
|
|
295
|
+
let tmp = ''
|
|
296
|
+
if (typeof data === 'string') {
|
|
297
|
+
tmp = data !== null && data !== '' ? data.replace(/[,\$\%]/g, '') : ''
|
|
298
|
+
} else {
|
|
299
|
+
tmp = data !== null && data !== '' ? data : ''
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (testing) console.log('## cleanedData =', tmp)
|
|
303
|
+
return tmp
|
|
277
304
|
}
|
|
278
305
|
}
|
|
279
306
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* regex
|
|
3
|
+
* - /\w\S* replaces zero or more whitespace characters
|
|
4
|
+
* - g makes it find all matches in the string
|
|
5
|
+
* - the callback function capitalizes the word
|
|
6
|
+
* */
|
|
7
|
+
export const capitalizeSplitAndJoin = function (splittingCharacter: string = ' ', joiningCharacter: string = '') {
|
|
8
|
+
return this.split(splittingCharacter)
|
|
9
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
10
|
+
.join(joiningCharacter)
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/core",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.11",
|
|
4
4
|
"description": "Core components, styles, hooks, and helpers, for the CDC Open Visualization project",
|
|
5
5
|
"moduleName": "CdcCore",
|
|
6
6
|
"main": "dist/cdccore",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"react": "^18.2.0",
|
|
31
31
|
"react-dom": "^18.2.0"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "ecad213667a3cb96c921eaddba43a31c84caaa08"
|
|
34
34
|
}
|
package/styles/_data-table.scss
CHANGED
|
@@ -3,17 +3,6 @@
|
|
|
3
3
|
// box-shadow: rgba(0, 0, 0, 0.2) 3px 6px 10px; // no box shadows
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
.cove-component__header {
|
|
7
|
-
width: 100%;
|
|
8
|
-
padding: 0.6rem 0.8rem;
|
|
9
|
-
border-bottom-width: 3px;
|
|
10
|
-
border-bottom-style: solid;
|
|
11
|
-
border-radius: 3px 3px 0 0;
|
|
12
|
-
font-size: 1.1rem;
|
|
13
|
-
transition: background-color 200ms ease, border-color 200ms ease;
|
|
14
|
-
color: #fff;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
6
|
.cove-component__content {
|
|
18
7
|
padding-top: 1rem;
|
|
19
8
|
border: solid 1px #ccc;
|
package/types/Axis.ts
ADDED
package/types/Color.ts
ADDED
package/types/Runtime.ts
ADDED
package/types/Series.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Series = { dataKey: string; name: string; axis: string }[]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type Visualization = {
|
|
2
|
+
visualizationType: string
|
|
3
|
+
dataKey: string
|
|
4
|
+
formattedData: any
|
|
5
|
+
dataDescription: Object
|
|
6
|
+
data: any
|
|
7
|
+
originalFormattedData: any
|
|
8
|
+
editing: boolean
|
|
9
|
+
type: 'chart' | 'map' | 'data-bite' | 'waffle-chart' | 'markup-include' | 'filtered-text' | 'filter-dropdowns'
|
|
10
|
+
newViz: boolean
|
|
11
|
+
openModal: boolean
|
|
12
|
+
hide: any[]
|
|
13
|
+
autoLoad: boolean
|
|
14
|
+
table: {
|
|
15
|
+
showDataTableLink: boolean
|
|
16
|
+
}
|
|
17
|
+
general: any
|
|
18
|
+
title: string
|
|
19
|
+
uid: string
|
|
20
|
+
usesSharedFilter: any
|
|
21
|
+
}
|