@cdc/core 4.24.12-2 → 4.25.1
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/components/DataTable/DataTable.tsx +26 -36
- package/components/DataTable/components/ChartHeader.tsx +3 -2
- package/components/DataTable/components/ExpandCollapse.tsx +1 -4
- package/components/DataTable/data-table.css +2 -7
- package/components/DataTable/helpers/customSort.ts +2 -2
- package/components/DataTable/helpers/mapCellMatrix.tsx +83 -60
- package/components/DataTable/types/TableConfig.ts +0 -1
- package/components/EditorPanel/FootnotesEditor.tsx +49 -7
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +3 -2
- package/components/Filters/Filters.tsx +16 -9
- package/components/Footnotes/Footnotes.tsx +1 -1
- package/components/Layout/components/Visualization/index.tsx +18 -4
- package/components/Layout/components/Visualization/visualizations.scss +1 -1
- package/components/Legend/Legend.Gradient.tsx +1 -4
- package/components/Legend/index.tsx +1 -1
- package/components/LegendShape.tsx +2 -3
- package/components/MediaControls.jsx +32 -8
- package/components/NestedDropdown/NestedDropdown.tsx +7 -12
- package/components/NestedDropdown/nesteddropdown.styles.css +11 -5
- package/components/Table/Table.tsx +0 -6
- package/components/Table/components/Row.tsx +2 -5
- package/components/_stories/DataTable.stories.tsx +1 -2
- package/components/elements/Button.jsx +38 -19
- package/components/elements/Confirm.tsx +45 -0
- package/components/elements/Error.tsx +24 -0
- package/components/managers/DataDesigner.tsx +198 -143
- package/components/ui/Title/Title.scss +12 -5
- package/components/ui/Title/index.tsx +1 -1
- package/dist/cove-main.css +77 -591
- package/dist/cove-main.css.map +1 -1
- package/helpers/DataTransform.ts +55 -63
- package/helpers/addValuesToFilters.ts +24 -9
- package/helpers/cove/accessibility.ts +24 -0
- package/helpers/cove/fontSettings.ts +1 -1
- package/helpers/cove/number.ts +1 -7
- package/helpers/coveUpdateWorker.ts +5 -1
- package/helpers/displayDataAsText.ts +64 -0
- package/helpers/formatConfigBeforeSave.ts +1 -1
- package/helpers/isOlderVersion.ts +20 -0
- package/helpers/missingRequiredSections.ts +20 -0
- package/helpers/tests/addValuesToFilters.test.ts +13 -0
- package/helpers/useDataVizClasses.ts +8 -4
- package/helpers/ver/4.24.11.ts +18 -0
- package/helpers/ver/4.25.1.ts +18 -0
- package/package.json +2 -2
- package/styles/_button-section.scss +2 -5
- package/styles/_global-variables.scss +17 -7
- package/styles/_global.scss +8 -12
- package/styles/_reset.scss +4 -5
- package/styles/_typography.scss +0 -20
- package/styles/_variables.scss +0 -3
- package/styles/base.scss +44 -5
- package/styles/cove-main.scss +1 -1
- package/styles/filters.scss +5 -6
- package/styles/v2/base/_general.scss +3 -2
- package/styles/v2/components/button.scss +0 -1
- package/styles/v2/main.scss +3 -4
- package/styles/v2/utils/index.scss +0 -1
- package/types/BoxPlot.ts +1 -0
- package/types/Runtime.ts +1 -0
- package/types/Table.ts +0 -1
- package/types/Version.ts +1 -1
- package/styles/v2/utils/_spacers.scss +0 -31
|
@@ -30,7 +30,7 @@ export type DataTableProps = {
|
|
|
30
30
|
columns?: Record<string, Column>
|
|
31
31
|
config: TableConfig
|
|
32
32
|
dataConfig?: Object
|
|
33
|
-
|
|
33
|
+
defaultSortBy?: string
|
|
34
34
|
displayGeoName?: Function
|
|
35
35
|
expandDataTable: boolean
|
|
36
36
|
formatLegendLocation?: Function
|
|
@@ -59,6 +59,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
59
59
|
const {
|
|
60
60
|
config,
|
|
61
61
|
dataConfig,
|
|
62
|
+
defaultSortBy,
|
|
62
63
|
tableTitle,
|
|
63
64
|
vizTitle,
|
|
64
65
|
rawData,
|
|
@@ -88,9 +89,8 @@ const DataTable = (props: DataTableProps) => {
|
|
|
88
89
|
}, [parentRuntimeData, config.table.pivot?.columnName, config.table.pivot?.valueColumn])
|
|
89
90
|
|
|
90
91
|
const [expanded, setExpanded] = useState(expandDataTable)
|
|
91
|
-
|
|
92
92
|
const [sortBy, setSortBy] = useState<any>({
|
|
93
|
-
column: '',
|
|
93
|
+
column: defaultSortBy || '',
|
|
94
94
|
asc: false,
|
|
95
95
|
colIndex: null
|
|
96
96
|
})
|
|
@@ -207,6 +207,24 @@ const DataTable = (props: DataTableProps) => {
|
|
|
207
207
|
[config.runtime?.seriesKeys]) // eslint-disable-line
|
|
208
208
|
|
|
209
209
|
const hasNoData = runtimeData.length === 0
|
|
210
|
+
|
|
211
|
+
const getClassNames = (): string => {
|
|
212
|
+
const classes = ['data-table-container']
|
|
213
|
+
|
|
214
|
+
if (config.table.showDownloadLinkBelow) {
|
|
215
|
+
classes.push('mt-4')
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const isBrushActive = config?.brush?.active && config.legend?.position !== 'bottom'
|
|
219
|
+
if (isBrushActive) {
|
|
220
|
+
classes.push('brush-active')
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
classes.push(viewport)
|
|
224
|
+
|
|
225
|
+
return classes.join(' ')
|
|
226
|
+
}
|
|
227
|
+
|
|
210
228
|
if (config.visualizationType !== 'Box Plot') {
|
|
211
229
|
const getDownloadData = () => {
|
|
212
230
|
// only use fullGeoName on County maps and no other
|
|
@@ -221,11 +239,12 @@ const DataTable = (props: DataTableProps) => {
|
|
|
221
239
|
const getMediaControlsClasses = belowTable => {
|
|
222
240
|
const classes = ['download-links']
|
|
223
241
|
if (!belowTable) {
|
|
242
|
+
classes.push('mt-4', 'mb-2')
|
|
224
243
|
const isLegendOnBottom = config?.legend?.position === 'bottom' || isLegendWrapViewport(viewport)
|
|
225
244
|
if (config.brush?.active && !isLegendOnBottom) classes.push('brush-active')
|
|
226
245
|
if (config.brush?.active && config.legend.hide) classes.push('brush-active')
|
|
227
246
|
} else {
|
|
228
|
-
classes.push('
|
|
247
|
+
classes.push('mt-2')
|
|
229
248
|
}
|
|
230
249
|
return classes
|
|
231
250
|
}
|
|
@@ -244,23 +263,6 @@ const DataTable = (props: DataTableProps) => {
|
|
|
244
263
|
</MediaControls.Section>
|
|
245
264
|
)
|
|
246
265
|
}
|
|
247
|
-
const getClassNames = (): string => {
|
|
248
|
-
const classes = ['data-table-container']
|
|
249
|
-
const isBrushActive = config?.brush?.active && config.legend?.position !== 'bottom'
|
|
250
|
-
|
|
251
|
-
if (isBrushActive) {
|
|
252
|
-
classes.push('brush-active')
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
classes.push(viewport)
|
|
256
|
-
|
|
257
|
-
const downloadLinkClass = !config.table.showDownloadLinkBelow ? 'download-link-above' : ''
|
|
258
|
-
if (downloadLinkClass) {
|
|
259
|
-
classes.push(downloadLinkClass)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return classes.join(' ')
|
|
263
|
-
}
|
|
264
266
|
|
|
265
267
|
return (
|
|
266
268
|
<ErrorBoundary component='DataTable'>
|
|
@@ -268,13 +270,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
268
270
|
<section id={tabbingId.replace('#', '')} className={getClassNames()} aria-label={accessibilityLabel}>
|
|
269
271
|
<SkipTo skipId={skipId} skipMessage='Skip Data Table' />
|
|
270
272
|
{config.table.collapsible !== false && (
|
|
271
|
-
<ExpandCollapse
|
|
272
|
-
expanded={expanded}
|
|
273
|
-
setExpanded={setExpanded}
|
|
274
|
-
fontSize={config.fontSize}
|
|
275
|
-
tableTitle={tableTitle}
|
|
276
|
-
viewport={viewport}
|
|
277
|
-
/>
|
|
273
|
+
<ExpandCollapse expanded={expanded} setExpanded={setExpanded} tableTitle={tableTitle} viewport={viewport} />
|
|
278
274
|
)}
|
|
279
275
|
<div className='table-container' style={limitHeight}>
|
|
280
276
|
<Table
|
|
@@ -302,6 +298,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
302
298
|
isVertical={isVertical}
|
|
303
299
|
sortBy={sortBy}
|
|
304
300
|
setSortBy={setSortBy}
|
|
301
|
+
viewport={viewport}
|
|
305
302
|
/>
|
|
306
303
|
)
|
|
307
304
|
}
|
|
@@ -313,7 +310,6 @@ const DataTable = (props: DataTableProps) => {
|
|
|
313
310
|
'aria-rowcount': config?.data?.length ? config.data.length : -1,
|
|
314
311
|
hidden: !expanded
|
|
315
312
|
}}
|
|
316
|
-
fontSize={config.fontSize}
|
|
317
313
|
/>
|
|
318
314
|
|
|
319
315
|
{/* REGION Data Table */}
|
|
@@ -336,7 +332,6 @@ const DataTable = (props: DataTableProps) => {
|
|
|
336
332
|
</tr>
|
|
337
333
|
}
|
|
338
334
|
tableOptions={{ className: 'table table-striped region-table data-table' }}
|
|
339
|
-
fontSize={config.fontSize}
|
|
340
335
|
/>
|
|
341
336
|
)}
|
|
342
337
|
</div>
|
|
@@ -351,11 +346,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
351
346
|
// Render Data Table for Box Plots
|
|
352
347
|
return (
|
|
353
348
|
<ErrorBoundary component='DataTable'>
|
|
354
|
-
<section
|
|
355
|
-
id={tabbingId.replace('#', '')}
|
|
356
|
-
className={`data-table-container ${viewport}`}
|
|
357
|
-
aria-label={accessibilityLabel}
|
|
358
|
-
>
|
|
349
|
+
<section id={tabbingId.replace('#', '')} className={getClassNames()} aria-label={accessibilityLabel}>
|
|
359
350
|
<SkipTo skipId={skipId} skipMessage='Skip Data Table' />
|
|
360
351
|
<ExpandCollapse expanded={expanded} setExpanded={setExpanded} tableTitle={tableTitle} />
|
|
361
352
|
<div className='table-container' style={limitHeight}>
|
|
@@ -374,7 +365,6 @@ const DataTable = (props: DataTableProps) => {
|
|
|
374
365
|
'aria-rowcount': 11,
|
|
375
366
|
hidden: !expanded
|
|
376
367
|
}}
|
|
377
|
-
fontSize={config.fontSize}
|
|
378
368
|
/>
|
|
379
369
|
</div>
|
|
380
370
|
</section>
|
|
@@ -5,9 +5,9 @@ import ScreenReaderText from '@cdc/core/components/elements/ScreenReaderText'
|
|
|
5
5
|
import { SortIcon } from './SortIcon'
|
|
6
6
|
import { getNewSortBy } from '../helpers/getNewSortBy'
|
|
7
7
|
|
|
8
|
-
type ChartHeaderProps = { data; isVertical; config; setSortBy; sortBy; hasRowType
|
|
8
|
+
type ChartHeaderProps = { data; isVertical; config; setSortBy; sortBy; hasRowType?; viewport }
|
|
9
9
|
|
|
10
|
-
const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }: ChartHeaderProps) => {
|
|
10
|
+
const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType, viewport }: ChartHeaderProps) => {
|
|
11
11
|
const groupBy = config.table?.groupBy
|
|
12
12
|
if (!data) return
|
|
13
13
|
let dataSeriesColumns = getDataSeriesColumns(config, isVertical, data)
|
|
@@ -69,6 +69,7 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
69
69
|
const text = getSeriesName(column, config)
|
|
70
70
|
const newSortBy = getNewSortBy(sortBy, column, index)
|
|
71
71
|
const sortByAsc = sortBy.column === column ? sortBy.asc : undefined
|
|
72
|
+
|
|
72
73
|
return (
|
|
73
74
|
<th
|
|
74
75
|
style={{ minWidth: (config.table.cellMinWidth || 0) + 'px' }}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import Icon from '../../ui/Icon'
|
|
2
|
-
import { fontSizes } from '../../../helpers/cove/fontSettings'
|
|
3
2
|
|
|
4
3
|
const ExpandCollapse = ({ expanded, setExpanded, tableTitle, fontSize, viewport }) => {
|
|
5
|
-
const titleFontSize = ['xs', 'xxs'].includes(viewport) ? '13px' : `${fontSizes[fontSize]}px`
|
|
6
4
|
return (
|
|
7
5
|
<div
|
|
8
|
-
style={{ fontSize: titleFontSize }}
|
|
9
6
|
role='button'
|
|
10
|
-
className={expanded ? 'data-table-heading' : 'collapsed data-table-heading'}
|
|
7
|
+
className={expanded ? 'data-table-heading p-3' : 'collapsed data-table-heading p-3'}
|
|
11
8
|
onClick={() => {
|
|
12
9
|
setExpanded(!expanded)
|
|
13
10
|
}}
|
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
.cdc-open-viz-module div.data-table-heading {
|
|
17
17
|
position: relative;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
border: var(--lightGray) 1px solid;
|
|
18
|
+
border: var(--cool-gray-10) 1px solid;
|
|
19
|
+
border-radius: 6px;
|
|
21
20
|
|
|
22
21
|
svg {
|
|
23
22
|
position: absolute;
|
|
@@ -31,9 +30,6 @@
|
|
|
31
30
|
z-index: 2;
|
|
32
31
|
position: relative;
|
|
33
32
|
}
|
|
34
|
-
@media (max-width: var(--breakpoint-sm)) {
|
|
35
|
-
font-size: var(--font-small) + 0.2em;
|
|
36
|
-
}
|
|
37
33
|
}
|
|
38
34
|
|
|
39
35
|
table.horizontal {
|
|
@@ -127,7 +123,6 @@ table.data-table {
|
|
|
127
123
|
&:last-child {
|
|
128
124
|
border-right: 0 !important;
|
|
129
125
|
}
|
|
130
|
-
font-size: var(--font-size);
|
|
131
126
|
}
|
|
132
127
|
|
|
133
128
|
td {
|
|
@@ -25,11 +25,11 @@ export const customSort = (a, b, sortBy, config) => {
|
|
|
25
25
|
const trimmedA = String(valueA).trim()
|
|
26
26
|
const trimmedB = String(valueB).trim()
|
|
27
27
|
|
|
28
|
-
if (config.xAxis?.dataKey === sortBy.column && config.xAxis.type
|
|
28
|
+
if (config.xAxis?.dataKey === sortBy.column && ['date', 'date-time'].includes(config.xAxis.type)) {
|
|
29
29
|
const dateA = parseDate(config.xAxis.dateParseFormat, trimmedA)?.getTime()
|
|
30
30
|
|
|
31
31
|
const dateB = parseDate(config.xAxis.dateParseFormat, trimmedB)?.getTime()
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
return sortBy.asc ? dateA - dateB : dateB - dateA
|
|
34
34
|
}
|
|
35
35
|
// Check if values are numbers
|
|
@@ -1,60 +1,83 @@
|
|
|
1
|
-
import LegendShape from '@cdc/core/components/LegendShape'
|
|
2
|
-
import CellAnchor from '../components/CellAnchor'
|
|
3
|
-
import { DataTableProps } from '../DataTable'
|
|
4
|
-
import { ReactNode } from 'react'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
import LegendShape from '@cdc/core/components/LegendShape'
|
|
2
|
+
import CellAnchor from '../components/CellAnchor'
|
|
3
|
+
import { DataTableProps } from '../DataTable'
|
|
4
|
+
import { ReactNode } from 'react'
|
|
5
|
+
import { displayDataAsText } from '@cdc/core/helpers/displayDataAsText'
|
|
6
|
+
|
|
7
|
+
type MapRowsProps = DataTableProps & {
|
|
8
|
+
rows: string[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const mapCellArray = ({
|
|
12
|
+
rows,
|
|
13
|
+
columns,
|
|
14
|
+
runtimeData,
|
|
15
|
+
config,
|
|
16
|
+
applyLegendToRow,
|
|
17
|
+
displayGeoName,
|
|
18
|
+
formatLegendLocation,
|
|
19
|
+
navigationHandler,
|
|
20
|
+
setFilteredCountryCode
|
|
21
|
+
}: MapRowsProps): ReactNode[][] => {
|
|
22
|
+
return rows.map(row =>
|
|
23
|
+
Object.keys(columns)
|
|
24
|
+
.filter(column => columns[column].dataTable === true && columns[column].name)
|
|
25
|
+
.map(column => {
|
|
26
|
+
let cellValue
|
|
27
|
+
|
|
28
|
+
if (column === 'geo') {
|
|
29
|
+
const rowObj = runtimeData[row]
|
|
30
|
+
const legendColor = applyLegendToRow(rowObj)
|
|
31
|
+
|
|
32
|
+
let labelValue
|
|
33
|
+
const mapZoomHandler =
|
|
34
|
+
config.general.type === 'bubble' && config.general.allowMapZoom && config.general.geoType === 'world'
|
|
35
|
+
? () => setFilteredCountryCode(row)
|
|
36
|
+
: undefined
|
|
37
|
+
if (
|
|
38
|
+
(config.general.geoType !== 'single-state' && config.general.geoType !== 'us-county') ||
|
|
39
|
+
config.general.type === 'us-geocode'
|
|
40
|
+
) {
|
|
41
|
+
const capitalize = str => {
|
|
42
|
+
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
43
|
+
}
|
|
44
|
+
labelValue = displayGeoName(row)
|
|
45
|
+
labelValue = String(labelValue).startsWith('region') ? capitalize(labelValue) : labelValue
|
|
46
|
+
} else {
|
|
47
|
+
labelValue = formatLegendLocation(row)
|
|
48
|
+
}
|
|
49
|
+
cellValue = (
|
|
50
|
+
<div className='col-12'>
|
|
51
|
+
<LegendShape fill={legendColor[0]} />
|
|
52
|
+
<CellAnchor
|
|
53
|
+
markup={labelValue}
|
|
54
|
+
row={rowObj}
|
|
55
|
+
columns={columns}
|
|
56
|
+
navigationHandler={navigationHandler}
|
|
57
|
+
mapZoomHandler={mapZoomHandler}
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
)
|
|
61
|
+
} else {
|
|
62
|
+
// check for special classes
|
|
63
|
+
let specialValFound = ''
|
|
64
|
+
let columnName = config.columns[column].name
|
|
65
|
+
const { specialClasses } = config.legend
|
|
66
|
+
if (specialClasses && specialClasses.length && typeof specialClasses[0] === 'object') {
|
|
67
|
+
specialClasses.forEach(specialClass => {
|
|
68
|
+
if (specialClass.key === columnName) {
|
|
69
|
+
if (String(runtimeData[row][specialClass.key]) === specialClass.value) {
|
|
70
|
+
specialValFound = specialClass.label
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
cellValue = displayDataAsText(specialValFound || runtimeData[row][columnName], column, config)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return cellValue
|
|
79
|
+
})
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default mapCellArray
|
|
@@ -39,13 +39,40 @@ const FootnotesEditor: React.FC<FootnotesEditorProps> = ({ config, updateField }
|
|
|
39
39
|
<>
|
|
40
40
|
<em>Dynamic Footnotes</em>
|
|
41
41
|
<div className='row border p-2'>
|
|
42
|
-
<InputSelect
|
|
42
|
+
<InputSelect
|
|
43
|
+
label='Select a Footnote Dataset'
|
|
44
|
+
value={config.dataKey}
|
|
45
|
+
options={dataSetOptions}
|
|
46
|
+
fieldName='dataKey'
|
|
47
|
+
updateField={updateField}
|
|
48
|
+
/>
|
|
43
49
|
|
|
44
50
|
{config.dataKey && (
|
|
45
51
|
<div className='p-3'>
|
|
46
|
-
<InputSelect
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
<InputSelect
|
|
53
|
+
label='Footnote Symbol Column'
|
|
54
|
+
value={config.dynamicFootnotes?.symbolColumn}
|
|
55
|
+
options={dataColumns}
|
|
56
|
+
section='dynamicFootnotes'
|
|
57
|
+
fieldName='symbolColumn'
|
|
58
|
+
updateField={updateField}
|
|
59
|
+
/>
|
|
60
|
+
<InputSelect
|
|
61
|
+
label='Footnote Text Column'
|
|
62
|
+
value={config.dynamicFootnotes?.textColumn}
|
|
63
|
+
options={dataColumns}
|
|
64
|
+
section='dynamicFootnotes'
|
|
65
|
+
fieldName='textColumn'
|
|
66
|
+
updateField={updateField}
|
|
67
|
+
/>
|
|
68
|
+
<InputSelect
|
|
69
|
+
label='Footnote Order Column'
|
|
70
|
+
value={config.dynamicFootnotes?.orderColumn}
|
|
71
|
+
options={dataColumns}
|
|
72
|
+
section='dynamicFootnotes'
|
|
73
|
+
fieldName='orderColumn'
|
|
74
|
+
updateField={updateField}
|
|
75
|
+
/>
|
|
49
76
|
</div>
|
|
50
77
|
)}
|
|
51
78
|
</div>
|
|
@@ -57,10 +84,25 @@ const FootnotesEditor: React.FC<FootnotesEditorProps> = ({ config, updateField }
|
|
|
57
84
|
{config.staticFootnotes?.map((note, index) => (
|
|
58
85
|
<div key={index} className='row border p-2'>
|
|
59
86
|
<div className='col-8'>
|
|
60
|
-
<InputSelect
|
|
61
|
-
|
|
87
|
+
<InputSelect
|
|
88
|
+
label='Symbol'
|
|
89
|
+
value={note.symbol}
|
|
90
|
+
options={[['', '--Select--'], ...footnotesSymbols]}
|
|
91
|
+
fieldName='symbol'
|
|
92
|
+
updateField={(section, subsection, fieldName, value) =>
|
|
93
|
+
updateStaticFootnote(index, { ...note, symbol: value })
|
|
94
|
+
}
|
|
95
|
+
/>{' '}
|
|
96
|
+
<TextField
|
|
97
|
+
label='Text'
|
|
98
|
+
value={note.text}
|
|
99
|
+
fieldName='text'
|
|
100
|
+
updateField={(section, subsection, fieldName, value) =>
|
|
101
|
+
updateStaticFootnote(index, { ...note, text: value })
|
|
102
|
+
}
|
|
103
|
+
/>
|
|
62
104
|
</div>
|
|
63
|
-
<div className='col-2
|
|
105
|
+
<div className='col-2 ms-4'>
|
|
64
106
|
<button className='btn btn-danger p-1' onClick={() => deleteStaticFootnote(index)}>
|
|
65
107
|
Delete
|
|
66
108
|
</button>
|
|
@@ -230,9 +230,10 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
230
230
|
value={filter.order || 'asc'}
|
|
231
231
|
fieldName='order'
|
|
232
232
|
label='Filter Order'
|
|
233
|
-
updateField={(_section, _subSection, _field, value) =>
|
|
233
|
+
updateField={(_section, _subSection, _field, value) => {
|
|
234
234
|
updateFilterProp('order', filterIndex, value)
|
|
235
|
-
|
|
235
|
+
if (filter.orderColumn && value !== 'column') updateFilterProp('orderColumn', filterIndex, '')
|
|
236
|
+
}}
|
|
236
237
|
options={filterOrderOptions}
|
|
237
238
|
/>
|
|
238
239
|
{filter.order === 'cust' && (
|
|
@@ -101,11 +101,11 @@ export const useFilters = props => {
|
|
|
101
101
|
const changeFilterActive = (index, value) => {
|
|
102
102
|
let newFilters = standaloneMap ? [...filteredData] : [...visualizationConfig.filters]
|
|
103
103
|
|
|
104
|
+
const newFilter = newFilters[index]
|
|
104
105
|
if (visualizationConfig.filterBehavior === 'Apply Button') {
|
|
105
|
-
|
|
106
|
+
newFilter.queuedActive = value
|
|
106
107
|
setShowApplyButton(true)
|
|
107
108
|
} else {
|
|
108
|
-
const newFilter = newFilters[index]
|
|
109
109
|
if (newFilter.filterStyle !== 'nested-dropdown') {
|
|
110
110
|
newFilter.active = value
|
|
111
111
|
} else {
|
|
@@ -436,16 +436,23 @@ const Filters = (props: FilterProps) => {
|
|
|
436
436
|
|
|
437
437
|
const classList = [
|
|
438
438
|
'single-filters',
|
|
439
|
-
'form-group
|
|
439
|
+
'form-group',
|
|
440
440
|
mobileFilterStyle ? 'single-filters--dropdown' : `single-filters--${filterStyle}`
|
|
441
441
|
]
|
|
442
442
|
const mobileExempt = ['nested-dropdown', 'multi-select'].includes(filterStyle)
|
|
443
443
|
const showDefaultDropdown = (filterStyle === 'dropdown' || mobileFilterStyle) && !mobileExempt
|
|
444
|
+
const [nestedActiveGroup, nestedActiveSubGroup] = useMemo<string[]>(() => {
|
|
445
|
+
if (filterStyle !== 'nested-dropdown') return []
|
|
446
|
+
return (singleFilter.queuedActive || [singleFilter.active, singleFilter.subGrouping?.active]) as [
|
|
447
|
+
string,
|
|
448
|
+
string
|
|
449
|
+
]
|
|
450
|
+
}, [singleFilter])
|
|
444
451
|
return (
|
|
445
452
|
<div className={classList.join(' ')} key={outerIndex}>
|
|
446
453
|
<>
|
|
447
454
|
{label && (
|
|
448
|
-
<label className='font-weight-bold
|
|
455
|
+
<label className='font-weight-bold mb-2' htmlFor={`filter-${outerIndex}`}>
|
|
449
456
|
{label}
|
|
450
457
|
</label>
|
|
451
458
|
)}
|
|
@@ -463,8 +470,8 @@ const Filters = (props: FilterProps) => {
|
|
|
463
470
|
)}
|
|
464
471
|
{filterStyle === 'nested-dropdown' && (
|
|
465
472
|
<NestedDropdown
|
|
466
|
-
activeGroup={
|
|
467
|
-
activeSubGroup={
|
|
473
|
+
activeGroup={nestedActiveGroup}
|
|
474
|
+
activeSubGroup={nestedActiveSubGroup}
|
|
468
475
|
filterIndex={outerIndex}
|
|
469
476
|
options={getNestedOptions(singleFilter)}
|
|
470
477
|
listLabel={label}
|
|
@@ -494,15 +501,15 @@ const Filters = (props: FilterProps) => {
|
|
|
494
501
|
const conditionalClass = standaloneMap ? general.headerColor : visualizationType === 'Spark Line' ? null : theme
|
|
495
502
|
const legendClass = legend && !legend.hide && legend.position === 'top' ? 'mb-0' : null
|
|
496
503
|
|
|
497
|
-
return [baseClass, conditionalClass, legendClass].filter(Boolean)
|
|
504
|
+
return [baseClass, conditionalClass, legendClass, 'w-100'].filter(Boolean)
|
|
498
505
|
}
|
|
499
506
|
|
|
500
507
|
return (
|
|
501
508
|
<section className={getClasses().join(' ')}>
|
|
502
509
|
{visualizationConfig.filterIntro && (
|
|
503
|
-
<p className='filters-section__intro-text'>{visualizationConfig.filterIntro}</p>
|
|
510
|
+
<p className='filters-section__intro-text mb-3'>{visualizationConfig.filterIntro}</p>
|
|
504
511
|
)}
|
|
505
|
-
<div className='d-flex flex-wrap w-100 filters-section__wrapper'>
|
|
512
|
+
<div className='d-flex flex-wrap w-100 mb-4 pb-2 filters-section__wrapper'>
|
|
506
513
|
{' '}
|
|
507
514
|
<>
|
|
508
515
|
<Style />
|
|
@@ -12,7 +12,7 @@ const Footnotes: React.FC<FootnotesProps> = ({ footnotes }) => {
|
|
|
12
12
|
{footnotes.map((note, i) => {
|
|
13
13
|
return (
|
|
14
14
|
<li key={note.symbol + i} className='mb-1'>
|
|
15
|
-
{note.symbol && <span className='
|
|
15
|
+
{note.symbol && <span className='me-1'>{note.symbol}</span>}
|
|
16
16
|
{note.text}
|
|
17
17
|
</li>
|
|
18
18
|
)
|
|
@@ -17,10 +17,17 @@ type VisualizationWrapper = {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const Visualization: React.FC<VisualizationWrapper> = forwardRef((props, ref) => {
|
|
20
|
-
const {
|
|
20
|
+
const {
|
|
21
|
+
config = {},
|
|
22
|
+
isEditor = false,
|
|
23
|
+
currentViewport = 'lg',
|
|
24
|
+
imageId = '',
|
|
25
|
+
showEditorPanel = true,
|
|
26
|
+
className
|
|
27
|
+
} = props
|
|
21
28
|
|
|
22
29
|
const getWrappingClasses = () => {
|
|
23
|
-
let classes = ['cdc-open-viz-module', `${currentViewport}`,
|
|
30
|
+
let classes = ['cdc-open-viz-module', `${currentViewport}`, `${config?.theme}`]
|
|
24
31
|
|
|
25
32
|
if (className) {
|
|
26
33
|
classes.push(className)
|
|
@@ -40,7 +47,7 @@ const Visualization: React.FC<VisualizationWrapper> = forwardRef((props, ref) =>
|
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
if (config.type === 'filtered-text') {
|
|
43
|
-
classes.push('type-filtered-text')
|
|
50
|
+
classes.push('type-filtered-text', `font-${config.fontSize}`)
|
|
44
51
|
classes = classes.filter(item => item !== 'cove-component__content')
|
|
45
52
|
return classes
|
|
46
53
|
}
|
|
@@ -67,7 +74,14 @@ const Visualization: React.FC<VisualizationWrapper> = forwardRef((props, ref) =>
|
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
if (config.type === 'waffle-chart') {
|
|
70
|
-
classes.push(
|
|
77
|
+
classes.push(
|
|
78
|
+
'cove',
|
|
79
|
+
'cdc-open-viz-module',
|
|
80
|
+
'type-waffle-chart',
|
|
81
|
+
currentViewport,
|
|
82
|
+
config.theme,
|
|
83
|
+
'font-' + config.overallFontSize
|
|
84
|
+
)
|
|
71
85
|
|
|
72
86
|
if (isEditor) {
|
|
73
87
|
classes.push('is-editor')
|
|
@@ -92,10 +92,7 @@ const LegendGradient = ({
|
|
|
92
92
|
|
|
93
93
|
if (style === 'gradient') {
|
|
94
94
|
return (
|
|
95
|
-
<svg
|
|
96
|
-
style={{ overflow: 'visible', width: '100%', marginTop: 10, marginBottom: hideBorder ? 10 : 0 }}
|
|
97
|
-
height={newHeight}
|
|
98
|
-
>
|
|
95
|
+
<svg className={'w-100 overflow-visible'} height={newHeight}>
|
|
99
96
|
{/* background border*/}
|
|
100
97
|
<rect x={0} y={0} width={legendWidth + MARGIN * 2} height={boxHeight + MARGIN * 2} fill='#d3d3d3' />
|
|
101
98
|
{/* Define the gradient */}
|
|
@@ -28,7 +28,7 @@ const ResetButton = props => {
|
|
|
28
28
|
if (config.runtime.disabledAmt === 0) return <></>
|
|
29
29
|
|
|
30
30
|
return (
|
|
31
|
-
<button onClick={handleReset} className={legendClasses.
|
|
31
|
+
<button onClick={handleReset} className={legendClasses.showAllButton.join(' ') || ''}>
|
|
32
32
|
Reset
|
|
33
33
|
</button>
|
|
34
34
|
)
|
|
@@ -10,9 +10,8 @@ interface LegendShapeProps {
|
|
|
10
10
|
const LegendShape: React.FC<LegendShapeProps> = props => {
|
|
11
11
|
const { fill, borderColor, display = 'inline-block', shape = 'circle' } = props
|
|
12
12
|
const dimensions = { width: '1em', height: '1em' }
|
|
13
|
-
const
|
|
13
|
+
const isCircleOrSquare = ['circle', 'square'].includes(shape)
|
|
14
14
|
const styles = {
|
|
15
|
-
marginRight: marginRight,
|
|
16
15
|
borderRadius: shape === 'circle' ? '50%' : '0px',
|
|
17
16
|
verticalAlign: 'middle',
|
|
18
17
|
display: display,
|
|
@@ -22,7 +21,7 @@ const LegendShape: React.FC<LegendShapeProps> = props => {
|
|
|
22
21
|
backgroundColor: fill
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
return <span className=
|
|
24
|
+
return <span className={`legend-item ${isCircleOrSquare ? 'me-2' : ''}`} style={styles} />
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
export default LegendShape
|