@cdc/core 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/components/DataTable/DataTable.tsx +58 -45
- package/components/DataTable/DataTableStandAlone.tsx +3 -3
- package/components/DataTable/components/ChartHeader.tsx +26 -6
- package/components/DataTable/components/ExpandCollapse.tsx +1 -4
- package/components/DataTable/components/MapHeader.tsx +5 -1
- package/components/DataTable/data-table.css +3 -8
- package/components/DataTable/helpers/chartCellMatrix.tsx +14 -5
- 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/Inputs.tsx +4 -0
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +16 -3
- package/components/Filters/Filters.tsx +95 -51
- package/components/Filters/helpers/filterWrapping.ts +43 -0
- package/components/Filters/helpers/handleSorting.ts +6 -0
- package/components/Filters/helpers/tests/handleSorting.test.ts +26 -0
- 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 +25 -17
- package/components/NestedDropdown/nesteddropdown.styles.css +13 -7
- package/components/Table/Table.tsx +11 -11
- package/components/Table/components/Row.tsx +14 -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 +260 -723
- package/dist/cove-main.css.map +1 -1
- package/helpers/DataTransform.ts +55 -61
- package/helpers/addValuesToFilters.ts +45 -16
- 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/filterVizData.ts +2 -2
- package/helpers/formatConfigBeforeSave.ts +17 -2
- package/helpers/isOlderVersion.ts +20 -0
- package/helpers/isRightAlignedTableValue.js +14 -0
- package/helpers/missingRequiredSections.ts +20 -0
- package/helpers/queryStringUtils.ts +7 -0
- package/helpers/tests/addValuesToFilters.test.ts +19 -1
- package/helpers/useDataVizClasses.ts +8 -4
- package/helpers/ver/4.24.10.ts +12 -0
- package/helpers/ver/4.24.11.ts +18 -0
- package/helpers/ver/4.24.7.ts +19 -1
- 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 +65 -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/themes/_color-definitions.scss +4 -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/types/VizFilter.ts +3 -1
- package/styles/v2/utils/_spacers.scss +0 -31
|
@@ -21,6 +21,7 @@ import { TableConfig } from './types/TableConfig'
|
|
|
21
21
|
import { Column } from '../../types/Column'
|
|
22
22
|
import { pivotData } from '../../helpers/pivotData'
|
|
23
23
|
import { isLegendWrapViewport } from '@cdc/core/helpers/viewports'
|
|
24
|
+
import isRightAlignedTableValue from '@cdc/core/helpers/isRightAlignedTableValue'
|
|
24
25
|
import './data-table.css'
|
|
25
26
|
import _ from 'lodash'
|
|
26
27
|
|
|
@@ -30,7 +31,7 @@ export type DataTableProps = {
|
|
|
30
31
|
columns?: Record<string, Column>
|
|
31
32
|
config: TableConfig
|
|
32
33
|
dataConfig?: Object
|
|
33
|
-
|
|
34
|
+
defaultSortBy?: string
|
|
34
35
|
displayGeoName?: Function
|
|
35
36
|
expandDataTable: boolean
|
|
36
37
|
formatLegendLocation?: Function
|
|
@@ -59,6 +60,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
59
60
|
const {
|
|
60
61
|
config,
|
|
61
62
|
dataConfig,
|
|
63
|
+
defaultSortBy,
|
|
62
64
|
tableTitle,
|
|
63
65
|
vizTitle,
|
|
64
66
|
rawData,
|
|
@@ -88,9 +90,8 @@ const DataTable = (props: DataTableProps) => {
|
|
|
88
90
|
}, [parentRuntimeData, config.table.pivot?.columnName, config.table.pivot?.valueColumn])
|
|
89
91
|
|
|
90
92
|
const [expanded, setExpanded] = useState(expandDataTable)
|
|
91
|
-
|
|
92
93
|
const [sortBy, setSortBy] = useState<any>({
|
|
93
|
-
column: '',
|
|
94
|
+
column: defaultSortBy || '',
|
|
94
95
|
asc: false,
|
|
95
96
|
colIndex: null
|
|
96
97
|
})
|
|
@@ -171,7 +172,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
171
172
|
if (config.type === 'map') {
|
|
172
173
|
return config.table.caption
|
|
173
174
|
? config.table.caption
|
|
174
|
-
: `Data table showing data for the ${mapLookup[config.general
|
|
175
|
+
: `Data table showing data for the ${mapLookup[config.general?.geoType]} figure.`
|
|
175
176
|
} else {
|
|
176
177
|
return config.table.caption ? config.table.caption : `Data table showing data for the ${config.type} figure.`
|
|
177
178
|
}
|
|
@@ -207,6 +208,24 @@ const DataTable = (props: DataTableProps) => {
|
|
|
207
208
|
[config.runtime?.seriesKeys]) // eslint-disable-line
|
|
208
209
|
|
|
209
210
|
const hasNoData = runtimeData.length === 0
|
|
211
|
+
|
|
212
|
+
const getClassNames = (): string => {
|
|
213
|
+
const classes = ['data-table-container']
|
|
214
|
+
|
|
215
|
+
if (config.table.showDownloadLinkBelow) {
|
|
216
|
+
classes.push('mt-4')
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const isBrushActive = config?.brush?.active && config.legend?.position !== 'bottom'
|
|
220
|
+
if (isBrushActive) {
|
|
221
|
+
classes.push('brush-active')
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
classes.push(viewport)
|
|
225
|
+
|
|
226
|
+
return classes.join(' ')
|
|
227
|
+
}
|
|
228
|
+
|
|
210
229
|
if (config.visualizationType !== 'Box Plot') {
|
|
211
230
|
const getDownloadData = () => {
|
|
212
231
|
// only use fullGeoName on County maps and no other
|
|
@@ -221,15 +240,32 @@ const DataTable = (props: DataTableProps) => {
|
|
|
221
240
|
const getMediaControlsClasses = belowTable => {
|
|
222
241
|
const classes = ['download-links']
|
|
223
242
|
if (!belowTable) {
|
|
243
|
+
classes.push('mt-4', 'mb-2')
|
|
224
244
|
const isLegendOnBottom = config?.legend?.position === 'bottom' || isLegendWrapViewport(viewport)
|
|
225
245
|
if (config.brush?.active && !isLegendOnBottom) classes.push('brush-active')
|
|
226
246
|
if (config.brush?.active && config.legend.hide) classes.push('brush-active')
|
|
227
247
|
} else {
|
|
228
|
-
classes.push('
|
|
248
|
+
classes.push('mt-2')
|
|
229
249
|
}
|
|
230
250
|
return classes
|
|
231
251
|
}
|
|
232
252
|
|
|
253
|
+
const childrenMatrix =
|
|
254
|
+
config.type === 'map'
|
|
255
|
+
? mapCellMatrix({ rows, wrapColumns, ...props, runtimeData, viewport })
|
|
256
|
+
: chartCellMatrix({ rows, ...props, runtimeData, isVertical, sortBy, hasRowType, viewport })
|
|
257
|
+
|
|
258
|
+
// If every value in a column is a number, record the column index so the header and cells can be right-aligned
|
|
259
|
+
const rightAlignedCols = childrenMatrix.length
|
|
260
|
+
? Object.fromEntries(
|
|
261
|
+
Object.keys(childrenMatrix[0])
|
|
262
|
+
.filter(
|
|
263
|
+
i => childrenMatrix.filter(row => isRightAlignedTableValue(row[i])).length === childrenMatrix.length
|
|
264
|
+
)
|
|
265
|
+
.map(x => [x, true])
|
|
266
|
+
)
|
|
267
|
+
: {}
|
|
268
|
+
|
|
233
269
|
const TableMediaControls = ({ belowTable }) => {
|
|
234
270
|
return (
|
|
235
271
|
<MediaControls.Section classes={getMediaControlsClasses(belowTable)}>
|
|
@@ -244,37 +280,14 @@ const DataTable = (props: DataTableProps) => {
|
|
|
244
280
|
</MediaControls.Section>
|
|
245
281
|
)
|
|
246
282
|
}
|
|
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
283
|
|
|
265
284
|
return (
|
|
266
285
|
<ErrorBoundary component='DataTable'>
|
|
267
|
-
{!config.table.showDownloadLinkBelow && <TableMediaControls />}
|
|
286
|
+
{config.general?.showDownloadButton && !config.table.showDownloadLinkBelow && <TableMediaControls />}
|
|
268
287
|
<section id={tabbingId.replace('#', '')} className={getClassNames()} aria-label={accessibilityLabel}>
|
|
269
288
|
<SkipTo skipId={skipId} skipMessage='Skip Data Table' />
|
|
270
289
|
{config.table.collapsible !== false && (
|
|
271
|
-
<ExpandCollapse
|
|
272
|
-
expanded={expanded}
|
|
273
|
-
setExpanded={setExpanded}
|
|
274
|
-
fontSize={config.fontSize}
|
|
275
|
-
tableTitle={tableTitle}
|
|
276
|
-
viewport={viewport}
|
|
277
|
-
/>
|
|
290
|
+
<ExpandCollapse expanded={expanded} setExpanded={setExpanded} tableTitle={tableTitle} viewport={viewport} />
|
|
278
291
|
)}
|
|
279
292
|
<div className='table-container' style={limitHeight}>
|
|
280
293
|
<Table
|
|
@@ -282,18 +295,20 @@ const DataTable = (props: DataTableProps) => {
|
|
|
282
295
|
viewport={viewport}
|
|
283
296
|
wrapColumns={wrapColumns}
|
|
284
297
|
noData={hasNoData}
|
|
285
|
-
childrenMatrix={
|
|
286
|
-
config.type === 'map'
|
|
287
|
-
? mapCellMatrix({ rows, wrapColumns, ...props, runtimeData, viewport })
|
|
288
|
-
: chartCellMatrix({ rows, ...props, runtimeData, isVertical, sortBy, hasRowType, viewport })
|
|
289
|
-
}
|
|
298
|
+
childrenMatrix={childrenMatrix}
|
|
290
299
|
tableName={config.type}
|
|
291
300
|
caption={caption}
|
|
292
301
|
stickyHeader
|
|
293
302
|
hasRowType={hasRowType}
|
|
294
303
|
headContent={
|
|
295
304
|
config.type === 'map' ? (
|
|
296
|
-
<MapHeader
|
|
305
|
+
<MapHeader
|
|
306
|
+
columns={columns}
|
|
307
|
+
{...props}
|
|
308
|
+
sortBy={sortBy}
|
|
309
|
+
setSortBy={setSortBy}
|
|
310
|
+
rightAlignedCols={rightAlignedCols}
|
|
311
|
+
/>
|
|
297
312
|
) : (
|
|
298
313
|
<ChartHeader
|
|
299
314
|
data={runtimeData}
|
|
@@ -302,6 +317,8 @@ const DataTable = (props: DataTableProps) => {
|
|
|
302
317
|
isVertical={isVertical}
|
|
303
318
|
sortBy={sortBy}
|
|
304
319
|
setSortBy={setSortBy}
|
|
320
|
+
viewport={viewport}
|
|
321
|
+
rightAlignedCols={rightAlignedCols}
|
|
305
322
|
/>
|
|
306
323
|
)
|
|
307
324
|
}
|
|
@@ -313,7 +330,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
313
330
|
'aria-rowcount': config?.data?.length ? config.data.length : -1,
|
|
314
331
|
hidden: !expanded
|
|
315
332
|
}}
|
|
316
|
-
|
|
333
|
+
rightAlignedCols={rightAlignedCols}
|
|
317
334
|
/>
|
|
318
335
|
|
|
319
336
|
{/* REGION Data Table */}
|
|
@@ -336,12 +353,13 @@ const DataTable = (props: DataTableProps) => {
|
|
|
336
353
|
</tr>
|
|
337
354
|
}
|
|
338
355
|
tableOptions={{ className: 'table table-striped region-table data-table' }}
|
|
339
|
-
fontSize={config.fontSize}
|
|
340
356
|
/>
|
|
341
357
|
)}
|
|
342
358
|
</div>
|
|
343
359
|
</section>
|
|
344
|
-
{config.table.showDownloadLinkBelow &&
|
|
360
|
+
{config.general?.showDownloadButton && config.table.showDownloadLinkBelow && (
|
|
361
|
+
<TableMediaControls belowTable={true} />
|
|
362
|
+
)}
|
|
345
363
|
<div id={skipId} className='cdcdataviz-sr-only'>
|
|
346
364
|
Skipped data table.
|
|
347
365
|
</div>
|
|
@@ -351,11 +369,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
351
369
|
// Render Data Table for Box Plots
|
|
352
370
|
return (
|
|
353
371
|
<ErrorBoundary component='DataTable'>
|
|
354
|
-
<section
|
|
355
|
-
id={tabbingId.replace('#', '')}
|
|
356
|
-
className={`data-table-container ${viewport}`}
|
|
357
|
-
aria-label={accessibilityLabel}
|
|
358
|
-
>
|
|
372
|
+
<section id={tabbingId.replace('#', '')} className={getClassNames()} aria-label={accessibilityLabel}>
|
|
359
373
|
<SkipTo skipId={skipId} skipMessage='Skip Data Table' />
|
|
360
374
|
<ExpandCollapse expanded={expanded} setExpanded={setExpanded} tableTitle={tableTitle} />
|
|
361
375
|
<div className='table-container' style={limitHeight}>
|
|
@@ -374,7 +388,6 @@ const DataTable = (props: DataTableProps) => {
|
|
|
374
388
|
'aria-rowcount': 11,
|
|
375
389
|
hidden: !expanded
|
|
376
390
|
}}
|
|
377
|
-
fontSize={config.fontSize}
|
|
378
391
|
/>
|
|
379
392
|
</div>
|
|
380
393
|
</section>
|
|
@@ -6,6 +6,7 @@ import DataTableEditorPanel from './components/DataTableEditorPanel'
|
|
|
6
6
|
import Filters from '../Filters'
|
|
7
7
|
import { TableConfig } from './types/TableConfig'
|
|
8
8
|
import { filterVizData } from '../../helpers/filterVizData'
|
|
9
|
+
import { addValuesToFilters } from '../../helpers/addValuesToFilters'
|
|
9
10
|
|
|
10
11
|
type StandAloneProps = {
|
|
11
12
|
visualizationKey: string
|
|
@@ -28,9 +29,8 @@ const DataTableStandAlone: React.FC<StandAloneProps> = ({
|
|
|
28
29
|
|
|
29
30
|
useEffect(() => {
|
|
30
31
|
// when using editor changes to filter should update the data
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
32
|
+
const filters = addValuesToFilters(config.filters, config.data)
|
|
33
|
+
setFilteredData(filterVizData(filters, config?.formattedData?.length > 0 ? config.formattedData : config.data))
|
|
34
34
|
}, [config.filters])
|
|
35
35
|
|
|
36
36
|
if (isEditor)
|
|
@@ -5,9 +5,18 @@ 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; rightAlignedCols }
|
|
9
9
|
|
|
10
|
-
const ChartHeader = ({
|
|
10
|
+
const ChartHeader = ({
|
|
11
|
+
data,
|
|
12
|
+
isVertical,
|
|
13
|
+
config,
|
|
14
|
+
setSortBy,
|
|
15
|
+
sortBy,
|
|
16
|
+
hasRowType,
|
|
17
|
+
viewport,
|
|
18
|
+
rightAlignedCols
|
|
19
|
+
}: ChartHeaderProps) => {
|
|
11
20
|
const groupBy = config.table?.groupBy
|
|
12
21
|
if (!data) return
|
|
13
22
|
let dataSeriesColumns = getDataSeriesColumns(config, isVertical, data)
|
|
@@ -69,9 +78,15 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
69
78
|
const text = getSeriesName(column, config)
|
|
70
79
|
const newSortBy = getNewSortBy(sortBy, column, index)
|
|
71
80
|
const sortByAsc = sortBy.column === column ? sortBy.asc : undefined
|
|
81
|
+
const isSortedCol = column === sortBy.column && !hasRowType
|
|
82
|
+
|
|
72
83
|
return (
|
|
73
84
|
<th
|
|
74
|
-
style={{
|
|
85
|
+
style={{
|
|
86
|
+
minWidth: (config.table.cellMinWidth || 0) + 'px',
|
|
87
|
+
textAlign: rightAlignedCols && rightAlignedCols[index] ? 'right' : '',
|
|
88
|
+
paddingRight: isSortedCol ? '1.3em' : ''
|
|
89
|
+
}}
|
|
75
90
|
key={`col-header-${column}__${index}`}
|
|
76
91
|
tabIndex={0}
|
|
77
92
|
role='columnheader'
|
|
@@ -93,7 +108,7 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
93
108
|
: null)}
|
|
94
109
|
>
|
|
95
110
|
<ColumnHeadingText text={text} column={column} config={config} />
|
|
96
|
-
{
|
|
111
|
+
{isSortedCol && <SortIcon ascending={sortByAsc} />}
|
|
97
112
|
<ScreenReaderSortByText sortBy={sortBy} config={config} text={text} />
|
|
98
113
|
</th>
|
|
99
114
|
)
|
|
@@ -109,9 +124,14 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
109
124
|
let text = row !== '__series__' ? getChartCellValue(row, column, config, data) : '__series__'
|
|
110
125
|
const newSortBy = getNewSortBy(sortBy, column, index)
|
|
111
126
|
const sortByAsc = sortBy.colIndex === index ? sortBy.asc : undefined
|
|
127
|
+
const isSortedCol = index === sortBy.colIndex && !hasRowType
|
|
112
128
|
return (
|
|
113
129
|
<th
|
|
114
|
-
style={{
|
|
130
|
+
style={{
|
|
131
|
+
minWidth: (config.table.cellMinWidth || 0) + 'px',
|
|
132
|
+
textAlign: rightAlignedCols && rightAlignedCols[index] ? 'right' : '',
|
|
133
|
+
paddingRight: isSortedCol ? '1.3em' : ''
|
|
134
|
+
}}
|
|
115
135
|
key={`col-header-${text}__${index}`}
|
|
116
136
|
tabIndex={0}
|
|
117
137
|
role='columnheader'
|
|
@@ -131,7 +151,7 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
131
151
|
: null)}
|
|
132
152
|
>
|
|
133
153
|
<ColumnHeadingText text={text} column={column} config={config} />
|
|
134
|
-
{
|
|
154
|
+
{isSortedCol && <SortIcon ascending={sortByAsc} />}
|
|
135
155
|
|
|
136
156
|
<ScreenReaderSortByText text={text} config={config} sortBy={sortBy} />
|
|
137
157
|
</th>
|
|
@@ -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
|
}}
|
|
@@ -16,7 +16,7 @@ const ColumnHeadingText = ({ text, config }) => {
|
|
|
16
16
|
return text
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy }: MapHeaderProps) => {
|
|
19
|
+
const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy, rightAlignedCols }: MapHeaderProps) => {
|
|
20
20
|
return (
|
|
21
21
|
<tr>
|
|
22
22
|
{Object.keys(columns)
|
|
@@ -35,6 +35,10 @@ const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy }: MapHeader
|
|
|
35
35
|
const sortByAsc = sortBy.column === column ? sortBy.asc : undefined
|
|
36
36
|
return (
|
|
37
37
|
<th
|
|
38
|
+
style={{
|
|
39
|
+
textAlign: rightAlignedCols && rightAlignedCols[index] ? 'right' : '',
|
|
40
|
+
paddingRight: '1.3em'
|
|
41
|
+
}}
|
|
38
42
|
key={`col-header-${column}__${index}`}
|
|
39
43
|
id={column}
|
|
40
44
|
tabIndex={0}
|
|
@@ -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 {
|
|
@@ -87,7 +83,7 @@ table.data-table {
|
|
|
87
83
|
}
|
|
88
84
|
th,
|
|
89
85
|
td {
|
|
90
|
-
padding: 0.5em
|
|
86
|
+
padding: 0.5em 0.7em;
|
|
91
87
|
line-height: normal;
|
|
92
88
|
position: relative;
|
|
93
89
|
text-align: left;
|
|
@@ -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 {
|
|
@@ -16,7 +16,15 @@ type ChartRowsProps = DataTableProps & {
|
|
|
16
16
|
hasRowType?: boolean
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const chartCellArray = ({
|
|
19
|
+
const chartCellArray = ({
|
|
20
|
+
rows,
|
|
21
|
+
runtimeData,
|
|
22
|
+
config,
|
|
23
|
+
isVertical,
|
|
24
|
+
sortBy,
|
|
25
|
+
colorScale,
|
|
26
|
+
hasRowType
|
|
27
|
+
}: ChartRowsProps): CellMatrix | GroupCellMatrix => {
|
|
20
28
|
const groupBy = config.table?.groupBy
|
|
21
29
|
const dataSeriesColumns = getDataSeriesColumns(config, isVertical, runtimeData)
|
|
22
30
|
|
|
@@ -38,7 +46,7 @@ const chartCellArray = ({ rows, runtimeData, config, isVertical, sortBy, colorSc
|
|
|
38
46
|
|
|
39
47
|
if (isVertical) {
|
|
40
48
|
if (groupBy) {
|
|
41
|
-
const cellMatrix
|
|
49
|
+
const cellMatrix = new Map()
|
|
42
50
|
rows.forEach(row => {
|
|
43
51
|
let groupKey: string
|
|
44
52
|
let groupValues = []
|
|
@@ -49,10 +57,11 @@ const chartCellArray = ({ rows, runtimeData, config, isVertical, sortBy, colorSc
|
|
|
49
57
|
groupValues.push(getChartCellValue(row, column, config, runtimeData))
|
|
50
58
|
}
|
|
51
59
|
})
|
|
52
|
-
if (!cellMatrix
|
|
53
|
-
cellMatrix
|
|
60
|
+
if (!cellMatrix.has(groupKey)) {
|
|
61
|
+
cellMatrix.set(groupKey, [groupValues])
|
|
54
62
|
} else {
|
|
55
|
-
cellMatrix
|
|
63
|
+
const currentGroupValues = cellMatrix.get(groupKey)
|
|
64
|
+
cellMatrix.set(groupKey, [...currentGroupValues, groupValues])
|
|
56
65
|
}
|
|
57
66
|
})
|
|
58
67
|
return cellMatrix
|
|
@@ -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
|