@cdc/core 4.24.3 → 4.24.5

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.
Files changed (72) hide show
  1. package/assets/icon-command.svg +3 -0
  2. package/assets/icon-rotate-left.svg +3 -0
  3. package/components/AdvancedEditor.jsx +9 -0
  4. package/components/DataTable/DataTable.tsx +20 -15
  5. package/components/DataTable/DataTableStandAlone.tsx +51 -4
  6. package/components/DataTable/components/ChartHeader.tsx +3 -2
  7. package/components/DataTable/components/DataTableEditorPanel.tsx +20 -3
  8. package/components/DataTable/components/ExpandCollapse.tsx +22 -16
  9. package/components/DataTable/helpers/chartCellMatrix.tsx +3 -2
  10. package/components/DataTable/helpers/getChartCellValue.ts +21 -1
  11. package/components/DataTable/helpers/getDataSeriesColumns.ts +37 -16
  12. package/components/DataTable/helpers/getSeriesName.ts +2 -1
  13. package/components/DataTable/helpers/mapCellMatrix.tsx +2 -2
  14. package/components/DataTable/helpers/{customColumns.ts → removeNullColumns.ts} +3 -3
  15. package/components/DataTable/types/TableConfig.ts +11 -21
  16. package/components/EditorPanel/ColumnsEditor.tsx +304 -260
  17. package/components/EditorPanel/DataTableEditor.tsx +119 -48
  18. package/components/EditorPanel/VizFilterEditor.tsx +234 -0
  19. package/components/EditorWrapper/EditorWrapper.tsx +48 -0
  20. package/components/EditorWrapper/editor-wrapper.style.css +14 -0
  21. package/components/Filters.jsx +78 -61
  22. package/components/Layout/components/Responsive.tsx +184 -0
  23. package/components/Layout/components/Sidebar/components/Sidebar.tsx +47 -0
  24. package/components/Layout/components/Sidebar/components/sidebar.styles.scss +902 -0
  25. package/components/Layout/components/Sidebar/index.tsx +3 -0
  26. package/components/Layout/components/Visualization/index.tsx +81 -0
  27. package/components/Layout/components/Visualization/visualizations.scss +33 -0
  28. package/components/Layout/index.tsx +11 -0
  29. package/components/Layout/styles/editor-grid-view.scss +156 -0
  30. package/components/Layout/styles/editor-utils.scss +197 -0
  31. package/components/Layout/styles/editor.scss +144 -0
  32. package/components/LegendCircle.jsx +4 -3
  33. package/components/MediaControls.jsx +1 -1
  34. package/components/Table/Table.tsx +7 -5
  35. package/components/Table/components/Row.tsx +6 -2
  36. package/components/Table/types/RowType.ts +3 -0
  37. package/components/Waiting.jsx +11 -1
  38. package/components/_stories/DataTable.stories.tsx +1 -2
  39. package/components/_stories/EditorPanel.stories.tsx +1 -0
  40. package/components/createBarElement.jsx +37 -34
  41. package/components/elements/SkipTo.tsx +37 -5
  42. package/components/managers/DataDesigner.tsx +18 -18
  43. package/components/ui/Icon.tsx +5 -1
  44. package/helpers/DataTransform.ts +9 -32
  45. package/helpers/coveUpdateWorker.ts +21 -0
  46. package/helpers/footnoteSymbols.ts +11 -0
  47. package/helpers/useDataVizClasses.js +1 -5
  48. package/helpers/ver/4.23.4.ts +27 -0
  49. package/helpers/ver/4.24.3.ts +56 -0
  50. package/helpers/ver/4.24.5.ts +32 -0
  51. package/package.json +2 -2
  52. package/styles/_data-table.scss +8 -0
  53. package/styles/_global.scss +7 -4
  54. package/styles/_reset.scss +7 -6
  55. package/styles/_variables.scss +3 -0
  56. package/styles/base.scss +0 -18
  57. package/styles/v2/base/index.scss +1 -1
  58. package/styles/v2/components/ui/tooltip.scss +0 -21
  59. package/types/Axis.ts +4 -0
  60. package/types/Column.ts +1 -0
  61. package/types/ConfigureData.ts +8 -0
  62. package/types/DataDescription.ts +9 -0
  63. package/types/Legend.ts +1 -0
  64. package/types/MarkupInclude.ts +26 -0
  65. package/types/Runtime.ts +1 -0
  66. package/types/Series.ts +1 -1
  67. package/types/Table.ts +15 -13
  68. package/types/Visualization.ts +14 -10
  69. package/types/VizFilter.ts +13 -0
  70. package/helpers/coveUpdateWorker.js +0 -19
  71. package/helpers/ver/4.23.js +0 -10
  72. package/helpers/ver/4.24.3.js +0 -25
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" aria-hidden="true" focusable="false" role="img" fill="currentColor">
2
+ <path d="M404.83356,297.97872H354.67715V214.177h50.15641a107.08854,107.08854,0,1,0,0-214.177C345.64284,0,297.51145,47.97571,297.82294,107.01074v50.46778H214.33287V107.01074A107.09452,107.09452,0,0,0,107.32225,0C47.97572,0,0,47.97571,0,107.01074c0,59.3464,48.28721,107.6336,107.32225,107.16629h50.15628v83.80169H107.32225C47.97572,297.97872,0,345.79862,0,404.83352a107.16644,107.16644,0,1,0,214.33287,0V354.83291h83.49007v50.00061a107.08879,107.08879,0,1,0,107.01062-106.8548ZM354.67715,106.85493a50.2348,50.2348,0,1,1,50.0006,50.46791h-50.0006ZM157.47853,404.83352a50.2348,50.2348,0,1,1-50.0006-50.00061h50.0006Zm0-247.51068h-50.0006a50.2348,50.2348,0,1,1,50.0006-50.46791ZM297.97862,297.97872H214.33287V214.33285h83.64575Zm106.69913,157.3227a50.15888,50.15888,0,0,1-50.0006-50.4679V354.83291h50.0006a50.2348,50.2348,0,1,1,0,100.46851Z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" aria-hidden="true" focusable="false" role="img" fill="currentColor">
2
+ <path d="M480 256c0 123.4-100.5 223.9-223.9 223.9c-48.84 0-95.17-15.58-134.2-44.86c-14.12-10.59-16.97-30.66-6.375-44.81c10.59-14.12 30.62-16.94 44.81-6.375c27.84 20.91 61 31.94 95.88 31.94C344.3 415.8 416 344.1 416 256s-71.69-159.8-159.8-159.8c-37.46 0-73.09 13.49-101.3 36.64l45.12 45.14c17.01 17.02 4.955 46.1-19.1 46.1H35.17C24.58 224.1 16 215.5 16 204.9V59.04c0-24.04 29.07-36.08 46.07-19.07l47.6 47.63C149.9 52.71 201.5 32.11 256.1 32.11C379.5 32.11 480 132.6 480 256z"/>
3
+ </svg>
@@ -51,6 +51,15 @@ export const AdvancedEditor = ({ loadConfig, state, convertStateToConfig }) => {
51
51
  <p className='pb-2'>
52
52
  This tool displays the actual <acronym title='JavaScript Object Notation'>JSON</acronym> configuration that is generated by this editor and allows you to edit properties directly and apply them.
53
53
  </p>
54
+ <button
55
+ className='btn'
56
+ onClick={() => {
57
+ navigator.clipboard.writeText(configTextboxValue)
58
+ alert('Copied!')
59
+ }}
60
+ >
61
+ Copy to Clipboard
62
+ </button>
54
63
  <textarea value={configTextboxValue} onChange={event => setConfigTextbox(event.target.value)} />
55
64
  <button className='btn full-width' onClick={() => loadConfig(JSON.parse(configTextboxValue))}>
56
65
  Apply
@@ -16,7 +16,7 @@ import Table from '../Table'
16
16
  import chartCellMatrix from './helpers/chartCellMatrix'
17
17
  import regionCellMatrix from './helpers/regionCellMatrix'
18
18
  import boxplotCellMatrix from './helpers/boxplotCellMatrix'
19
- import customColumns from './helpers/customColumns'
19
+ import removeNullColumns from './helpers/removeNullColumns'
20
20
  import { TableConfig } from './types/TableConfig'
21
21
  import { Column } from '../../types/Column'
22
22
 
@@ -44,7 +44,7 @@ export type DataTableProps = {
44
44
  showDownloadButton?: boolean
45
45
  tabbingId: string
46
46
  tableTitle: string
47
- viewport: string
47
+ viewport: 'lg' | 'md' | 'sm' | 'xs' | 'xxs'
48
48
  vizTitle?: string
49
49
  // determines if columns should be wrapped in the table
50
50
  wrapColumns?: boolean
@@ -52,7 +52,8 @@ export type DataTableProps = {
52
52
 
53
53
  /* eslint-disable jsx-a11y/no-noninteractive-tabindex, jsx-a11y/no-static-element-interactions */
54
54
  const DataTable = (props: DataTableProps) => {
55
- const { config, dataConfig, tableTitle, vizTitle, rawData, runtimeData, headerColor, expandDataTable, columns, viewport, formatLegendLocation, tabbingId, wrapColumns } = props
55
+ const { config, dataConfig, tableTitle, vizTitle, rawData, runtimeData: parentRuntimeData, headerColor, expandDataTable, columns, viewport, formatLegendLocation, tabbingId, wrapColumns } = props
56
+ const runtimeData = removeNullColumns(parentRuntimeData)
56
57
  const [expanded, setExpanded] = useState(expandDataTable)
57
58
 
58
59
  const [sortBy, setSortBy] = useState<any>({ column: config.type === 'map' ? 'geo' : 'date', asc: false, colIndex: null })
@@ -98,25 +99,23 @@ const DataTable = (props: DataTableProps) => {
98
99
  break
99
100
  }
100
101
 
101
- const _runtimeData = config.table.customTableConfig ? customColumns(rawData, config.table.excludeColumns) : runtimeData
102
-
103
- const rawRows = Object.keys(_runtimeData).filter(column => column != 'columns')
102
+ const rawRows = Object.keys(runtimeData).filter(column => column != 'columns')
104
103
  const rows = isVertical
105
104
  ? rawRows.sort((a, b) => {
106
105
  let dataA
107
106
  let dataB
108
107
  if (config.type === 'map' && config.columns) {
109
108
  const sortByColName = config.columns[sortBy.column].name
110
- dataA = _runtimeData[a][sortByColName]
111
- dataB = _runtimeData[b][sortByColName]
109
+ dataA = runtimeData[a][sortByColName]
110
+ dataB = runtimeData[b][sortByColName]
112
111
  }
113
112
  if (config.type === 'chart' || config.type === 'dashboard') {
114
- dataA = _runtimeData[a][sortBy.column]
115
- dataB = _runtimeData[b][sortBy.column]
113
+ dataA = runtimeData[a][sortBy.column]
114
+ dataB = runtimeData[b][sortBy.column]
116
115
  }
117
116
  if (!dataA && !dataB && config.type === 'chart' && config.xAxis && config.xAxis.type === 'date-time') {
118
- dataA = timeParse(config.runtime.xAxis.dateParseFormat)(_runtimeData[a][config.xAxis.dataKey])
119
- dataB = timeParse(config.runtime.xAxis.dateParseFormat)(_runtimeData[b][config.xAxis.dataKey])
117
+ dataA = timeParse(config.runtime.xAxis.dateParseFormat)(runtimeData[a][config.xAxis.dataKey])
118
+ dataB = timeParse(config.runtime.xAxis.dateParseFormat)(runtimeData[b][config.xAxis.dataKey])
120
119
  }
121
120
  return dataA && dataB ? customSort(dataA, dataB, sortBy, config) : 0
122
121
  })
@@ -185,22 +184,25 @@ const DataTable = (props: DataTableProps) => {
185
184
  </MediaControls.Section>
186
185
  <section id={tabbingId.replace('#', '')} className={`data-table-container ${viewport}`} aria-label={accessibilityLabel}>
187
186
  <SkipTo skipId={skipId} skipMessage='Skip Data Table' />
188
- <ExpandCollapse expanded={expanded} setExpanded={setExpanded} tableTitle={tableTitle} />
187
+ {config.table.collapsible !== false && <ExpandCollapse expanded={expanded} setExpanded={setExpanded} fontSize={config.fontSize} tableTitle={tableTitle} viewport={viewport} />}
189
188
  <div className='table-container' style={limitHeight}>
190
189
  <Table
190
+ viewport={viewport}
191
191
  wrapColumns={wrapColumns}
192
- childrenMatrix={config.type === 'map' ? mapCellMatrix({ rows, wrapColumns, ...props, runtimeData: _runtimeData }) : chartCellMatrix({ rows, ...props, runtimeData: _runtimeData, isVertical, sortBy, hasRowType })}
192
+ childrenMatrix={config.type === 'map' ? mapCellMatrix({ rows, wrapColumns, ...props, runtimeData, viewport }) : chartCellMatrix({ rows, ...props, runtimeData, isVertical, sortBy, hasRowType, viewport })}
193
193
  tableName={config.type}
194
194
  caption={caption}
195
195
  stickyHeader
196
196
  hasRowType={hasRowType}
197
- headContent={config.type === 'map' ? <MapHeader columns={columns} {...props} sortBy={sortBy} setSortBy={setSortBy} /> : <ChartHeader data={_runtimeData} {...props} hasRowType={hasRowType} isVertical={isVertical} sortBy={sortBy} setSortBy={setSortBy} />}
197
+ headContent={config.type === 'map' ? <MapHeader columns={columns} {...props} sortBy={sortBy} setSortBy={setSortBy} /> : <ChartHeader data={runtimeData} {...props} hasRowType={hasRowType} isVertical={isVertical} sortBy={sortBy} setSortBy={setSortBy} />}
198
198
  tableOptions={{ className: `${expanded ? 'data-table' : 'data-table cdcdataviz-sr-only'}${isVertical ? '' : ' horizontal'}`, 'aria-live': 'assertive', 'aria-rowcount': config?.data?.length ? config.data.length : -1, hidden: !expanded }}
199
+ fontSize={config.fontSize}
199
200
  />
200
201
 
201
202
  {/* REGION Data Table */}
202
203
  {noRelativeRegions && config.regions && config.regions.length > 0 && config.visualizationType !== 'Box Plot' && (
203
204
  <Table
205
+ viewport={viewport}
204
206
  wrapColumns={wrapColumns}
205
207
  childrenMatrix={regionCellMatrix({ config })}
206
208
  tableName={config.visualizationType}
@@ -213,6 +215,7 @@ const DataTable = (props: DataTableProps) => {
213
215
  </tr>
214
216
  }
215
217
  tableOptions={{ className: 'region-table data-table' }}
218
+ fontSize={config.fontSize}
216
219
  />
217
220
  )}
218
221
  </div>
@@ -231,6 +234,7 @@ const DataTable = (props: DataTableProps) => {
231
234
  <ExpandCollapse expanded={expanded} setExpanded={setExpanded} tableTitle={tableTitle} />
232
235
  <div className='table-container' style={limitHeight}>
233
236
  <Table
237
+ viewport={viewport}
234
238
  wrapColumns={wrapColumns}
235
239
  childrenMatrix={boxplotCellMatrix({ rows: tableData, config })}
236
240
  tableName={config.visualizationType}
@@ -238,6 +242,7 @@ const DataTable = (props: DataTableProps) => {
238
242
  stickyHeader
239
243
  headContent={<BoxplotHeader categories={config.boxplot.categories} />}
240
244
  tableOptions={{ className: `${expanded ? 'data-table' : 'data-table cdcdataviz-sr-only'}`, 'aria-live': 'assertive', 'aria-rowcount': 11, hidden: !expanded }}
245
+ fontSize={config.fontSize}
241
246
  />
242
247
  </div>
243
248
  </section>
@@ -1,15 +1,62 @@
1
+ import { useEffect, useState } from 'react'
1
2
  import { ViewPort } from '../../types/ViewPort'
2
- import { Visualization } from '../../types/Visualization'
3
+ import EditorWrapper from '../EditorWrapper/EditorWrapper'
3
4
  import DataTable from './DataTable'
5
+ import DataTableEditorPanel from './components/DataTableEditorPanel'
6
+ import Filters from '../Filters'
7
+ import { TableConfig } from './types/TableConfig'
4
8
 
5
9
  type StandAloneProps = {
6
10
  visualizationKey: string
7
- config: Visualization
11
+ config: TableConfig
8
12
  viewport?: ViewPort
13
+ isEditor?: boolean
14
+ updateConfig?: (Visualization) => void
9
15
  }
10
16
 
11
- const DataTableStandAlone: React.FC<StandAloneProps> = ({ visualizationKey, config, viewport }) => {
12
- return <DataTable expandDataTable={true} config={config} rawData={config.data} runtimeData={config.formattedData} tabbingId={visualizationKey} tableTitle={config.table.label} viewport={viewport || 'lg'} />
17
+ // filterData is copied from ./packages/chart/src/helpers/filterData.ts
18
+ // consider moving this to a shared location
19
+ const filterData = (filters, data) => {
20
+ if (!filters) return data
21
+ const filteredData: any[] = []
22
+
23
+ data.forEach(row => {
24
+ let add = true
25
+ filters
26
+ .filter(filter => filter.type !== 'url')
27
+ .forEach(filter => {
28
+ if (row[filter.columnName] != filter.active) {
29
+ add = false
30
+ }
31
+ })
32
+
33
+ if (add) filteredData.push(row)
34
+ })
35
+
36
+ return filteredData
37
+ }
38
+
39
+ const DataTableStandAlone: React.FC<StandAloneProps> = ({ visualizationKey, config, updateConfig, viewport, isEditor }) => {
40
+ const [filteredData, setFilteredData] = useState<Record<string, any>[]>(filterData(config.filters, config.formattedData))
41
+
42
+ useEffect(() => {
43
+ // when using editor changes to filter should update the data
44
+ setFilteredData(filterData(config.filters, config.formattedData))
45
+ }, [config.filters])
46
+
47
+ if (isEditor)
48
+ return (
49
+ <EditorWrapper component={DataTableStandAlone} visualizationKey={visualizationKey} visualizationConfig={config} updateConfig={updateConfig} type={'Table'} viewport={viewport}>
50
+ <DataTableEditorPanel key={visualizationKey} config={config} updateConfig={updateConfig} />
51
+ </EditorWrapper>
52
+ )
53
+
54
+ return (
55
+ <>
56
+ <Filters config={config} setConfig={updateConfig} setFilteredData={setFilteredData} filterData={filterData} filteredData={filteredData} excludedData={config.formattedData} />
57
+ <DataTable expandDataTable={true} config={config} rawData={config.data} runtimeData={filteredData} tabbingId={visualizationKey} tableTitle={config.table.label} viewport={viewport || 'lg'} />
58
+ </>
59
+ )
13
60
  }
14
61
 
15
62
  export default DataTableStandAlone
@@ -4,9 +4,10 @@ import { getDataSeriesColumns } from '../helpers/getDataSeriesColumns'
4
4
  import { DownIcon, UpIcon } from './Icons'
5
5
  import ScreenReaderText from '@cdc/core/components/elements/ScreenReaderText'
6
6
 
7
- type ChartHeaderProps = { data; isVertical; config; setSortBy; sortBy; groupBy?; hasRowType? }
7
+ type ChartHeaderProps = { data; isVertical; config; setSortBy; sortBy; hasRowType? }
8
8
 
9
- const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, groupBy, hasRowType }: ChartHeaderProps) => {
9
+ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }: ChartHeaderProps) => {
10
+ const groupBy = config.table?.groupBy
10
11
  if (!data) return
11
12
  let dataSeriesColumns = getDataSeriesColumns(config, isVertical, data)
12
13
  if (groupBy) {
@@ -4,6 +4,8 @@ import { Visualization } from '@cdc/core/types/Visualization'
4
4
  import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
5
5
  import { useMemo } from 'react'
6
6
  import ColumnsEditor from '../../EditorPanel/ColumnsEditor'
7
+ import VizFilterEditor from '../../EditorPanel/VizFilterEditor'
8
+ import _ from 'lodash'
7
9
 
8
10
  type DataTableEditorProps = {
9
11
  config: Visualization
@@ -13,7 +15,7 @@ type DataTableEditorProps = {
13
15
  const DataTableEditorPanel: React.FC<DataTableEditorProps> = ({ config, updateConfig }) => {
14
16
  const updateField = useMemo(() => updateFieldFactory(config, updateConfig), [JSON.stringify(config)])
15
17
  const deleteColumn = columnName => {
16
- const newColumns = config.columns
18
+ const newColumns = _.cloneDeep(config.columns)
17
19
 
18
20
  delete newColumns[columnName]
19
21
 
@@ -23,10 +25,25 @@ const DataTableEditorPanel: React.FC<DataTableEditorProps> = ({ config, updateCo
23
25
  })
24
26
  }
25
27
 
26
- const columns = Object.keys(config.columns || {})
28
+ const columns = Object.keys(config.originalFormattedData[0] || {})
27
29
  return (
28
30
  <>
29
- <ColumnsEditor config={config} updateField={updateField} deleteColumn={deleteColumn} />
31
+ <AccordionItem>
32
+ <AccordionItemHeading>
33
+ <AccordionItemButton>Filters</AccordionItemButton>
34
+ </AccordionItemHeading>
35
+ <AccordionItemPanel>
36
+ <VizFilterEditor config={config} updateField={updateField} rawData={config.originalFormattedData} />
37
+ </AccordionItemPanel>
38
+ </AccordionItem>
39
+ <AccordionItem>
40
+ <AccordionItemHeading>
41
+ <AccordionItemButton>Columns</AccordionItemButton>
42
+ </AccordionItemHeading>
43
+ <AccordionItemPanel>
44
+ <ColumnsEditor config={config} updateField={updateField} deleteColumn={deleteColumn} />
45
+ </AccordionItemPanel>
46
+ </AccordionItem>
30
47
  <AccordionItem>
31
48
  <AccordionItemHeading>
32
49
  <AccordionItemButton>Data Table</AccordionItemButton>
@@ -1,21 +1,27 @@
1
1
  import Icon from '../../ui/Icon'
2
2
 
3
- const ExpandCollapse = ({ expanded, setExpanded, tableTitle }) => (
4
- <div
5
- className={expanded ? 'data-table-heading' : 'collapsed data-table-heading'}
6
- onClick={() => {
7
- setExpanded(!expanded)
8
- }}
9
- tabIndex={0}
10
- onKeyDown={e => {
11
- if (e.keyCode === 13) {
3
+ const ExpandCollapse = ({ expanded, setExpanded, tableTitle, fontSize, viewport }) => {
4
+ const fontSizes = { small: 16, medium: 18, large: 20 }
5
+ const titleFontSize = ['sm', 'xs', 'xxs'].includes(viewport) ? '13px' : `${fontSizes[fontSize]}px`
6
+ return (
7
+ <div
8
+ style={{ fontSize: titleFontSize }}
9
+ role='button'
10
+ className={expanded ? 'data-table-heading' : 'collapsed data-table-heading'}
11
+ onClick={() => {
12
12
  setExpanded(!expanded)
13
- }
14
- }}
15
- >
16
- <Icon display={expanded ? 'minus' : 'plus'} base />
17
- {tableTitle}
18
- </div>
19
- )
13
+ }}
14
+ tabIndex={0}
15
+ onKeyDown={e => {
16
+ if (e.keyCode === 13) {
17
+ setExpanded(!expanded)
18
+ }
19
+ }}
20
+ >
21
+ <Icon display={expanded ? 'minus' : 'plus'} base />
22
+ {tableTitle}
23
+ </div>
24
+ )
25
+ }
20
26
 
21
27
  export default ExpandCollapse
@@ -15,7 +15,8 @@ type ChartRowsProps = DataTableProps & {
15
15
  hasRowType?: boolean
16
16
  }
17
17
 
18
- const chartCellArray = ({ rows, runtimeData, config, isVertical, sortBy, colorScale, groupBy, hasRowType }: ChartRowsProps): CellMatrix | GroupCellMatrix => {
18
+ const chartCellArray = ({ rows, runtimeData, config, isVertical, sortBy, colorScale, hasRowType, viewport }: ChartRowsProps): CellMatrix | GroupCellMatrix => {
19
+ const groupBy = config.table?.groupBy
19
20
  const dataSeriesColumns = getDataSeriesColumns(config, isVertical, runtimeData)
20
21
 
21
22
  const dataSeriesColumnsSorted = () => {
@@ -79,7 +80,7 @@ const chartCellArray = ({ rows, runtimeData, config, isVertical, sortBy, colorSc
79
80
  config.visualizationType !== 'Pie'
80
81
  ? [
81
82
  <>
82
- {colorScale && colorScale(seriesName) && <LegendCircle fill={colorScale(seriesName)} />}
83
+ {colorScale && colorScale(seriesName) && <LegendCircle viewport={viewport} fill={colorScale(seriesName)} />}
83
84
  {seriesName}
84
85
  </>
85
86
  ]
@@ -25,7 +25,7 @@ const isAdditionalColumn = (column, config) => {
25
25
  }
26
26
 
27
27
  export const getChartCellValue = (row: string, column: string, config: TableConfig, runtimeData: Object[]) => {
28
- if (config.table.customTableConfig || config.visualizationType === 'Sankey' || runtimeData?.[0]?.tableData) return runtimeData[row][column]
28
+ if (config.visualizationType === 'Sankey' || runtimeData?.[0]?.tableData) return runtimeData[row][column]
29
29
 
30
30
  const rowObj = runtimeData[row]
31
31
  let cellValue // placeholder for formatting below
@@ -54,5 +54,25 @@ export const getChartCellValue = (row: string, column: string, config: TableConf
54
54
  }
55
55
  }
56
56
 
57
+ // suppress cell value
58
+ config.preliminaryData?.forEach(pd => {
59
+ // check entered suppression value against cell value
60
+ const isValueMatch = String(pd.value) === String(labelValue)
61
+ // check entered suppression column against table key
62
+ const isColumnMatch = !pd.column || pd.column === column
63
+ if (isValueMatch && isColumnMatch && pd.displayTable && pd.type === 'suppression') {
64
+ switch (config.visualizationType) {
65
+ case 'Combo':
66
+ cellValue = config.runtime.barSeriesKeys.includes(column) ? pd.iconCode : config.runtime.lineSeriesKeys.includes(column) ? pd.lineCode : ''
67
+ break
68
+ case 'Bar':
69
+ cellValue = pd.iconCode
70
+ break
71
+ case 'Line':
72
+ cellValue = pd.lineCode
73
+ break
74
+ }
75
+ }
76
+ })
57
77
  return cellValue
58
78
  }
@@ -1,14 +1,13 @@
1
1
  import { TableConfig } from '../types/TableConfig'
2
+ import _ from 'lodash'
3
+ import { Column } from '../../../types/Column'
2
4
 
3
5
  export const getDataSeriesColumns = (config: TableConfig, isVertical: boolean, runtimeData: Object[]): string[] => {
4
- if (config.table.customTableConfig) return runtimeData[0] ? Object.keys(runtimeData[0]) : []
5
- if (config.type === 'table') {
6
- const excludeColumns = Object.values(config.columns)
7
- .filter(column => column.dataTable === false)
8
- .map(column => column.name)
9
- return Object.keys(runtimeData[0]).filter(columnName => !excludeColumns.includes(columnName))
10
- }
11
- let tmpSeriesColumns
6
+ const configColumns: Record<string, Column> = _.cloneDeep(config.columns) || {}
7
+ const excludeColumns = Object.values(configColumns)
8
+ .filter(column => column.dataTable === false)
9
+ .map(column => column.name)
10
+ let tmpSeriesColumns: string[] = []
12
11
  if (config.visualizationType !== 'Pie') {
13
12
  tmpSeriesColumns = isVertical ? [config.xAxis?.dataKey] : [] //, ...config.runtime.seriesLabelsAll
14
13
  if (config.series) {
@@ -23,15 +22,37 @@ export const getDataSeriesColumns = (config: TableConfig, isVertical: boolean, r
23
22
  }
24
23
 
25
24
  // then add the additional Columns
26
- if (config.columns && Object.keys(config.columns).length > 0) {
27
- Object.keys(config.columns).forEach(function (key) {
28
- var value = config.columns[key]
29
- // add if not the index AND it is enabled to be added to data table
30
- if (value.name !== config.xAxis?.dataKey && value.dataTable === true) {
31
- tmpSeriesColumns.push(value.name)
25
+ Object.keys(configColumns).forEach(function (key) {
26
+ var value = configColumns[key]
27
+ // add if not the index AND it is enabled to be added to data table
28
+ const alreadyAdded = tmpSeriesColumns.includes(value.name)
29
+ if (value.name !== config.xAxis?.dataKey && value.dataTable === true && !alreadyAdded) {
30
+ tmpSeriesColumns.push(value.name)
31
+ }
32
+ })
33
+
34
+ const columnOrderingHash = Object.values(configColumns).reduce((acc, column) => {
35
+ // subtract 1 to switch from cardinal positioning to index
36
+ if (column.order !== undefined) {
37
+ acc[column.name] = column.order - 1
38
+ }
39
+ return acc
40
+ }, {})
41
+
42
+ tmpSeriesColumns = tmpSeriesColumns.filter(columnName => !excludeColumns.includes(columnName))
43
+
44
+ tmpSeriesColumns.forEach((columnName, index) => {
45
+ if (columnOrderingHash[columnName] === undefined) {
46
+ if (Object.values(columnOrderingHash).includes(index)) {
47
+ // add 1 to place unsorted columns behind sorted columns
48
+ columnOrderingHash[columnName] = index + 1
49
+ } else {
50
+ columnOrderingHash[columnName] = index
32
51
  }
33
- })
34
- }
52
+ }
53
+ })
54
+
55
+ tmpSeriesColumns.sort((a, b) => columnOrderingHash[a] - columnOrderingHash[b])
35
56
 
36
57
  return tmpSeriesColumns
37
58
  }
@@ -17,5 +17,6 @@ export const getSeriesName = (column: string, config: TableConfig) => {
17
17
  }
18
18
  if (config.runtimeSeriesLabels && config.runtimeSeriesLabels[column]) return config.runtimeSeriesLabels[column]
19
19
  const columnIsDataKey = column === config.xAxis?.dataKey
20
- return columnIsDataKey ? config.table.indexLabel : getLabel(column, config)
20
+ const indexLabel = config.table?.indexLabel
21
+ return columnIsDataKey && indexLabel ? indexLabel : getLabel(column, config)
21
22
  }
@@ -7,7 +7,7 @@ type MapRowsProps = DataTableProps & {
7
7
  rows: string[]
8
8
  }
9
9
 
10
- const mapCellArray = ({ rows, columns, runtimeData, config, applyLegendToRow, displayGeoName, formatLegendLocation, displayDataAsText, navigationHandler, setFilteredCountryCode }: MapRowsProps): ReactNode[][] => {
10
+ const mapCellArray = ({ rows, columns, runtimeData, config, applyLegendToRow, displayGeoName, formatLegendLocation, displayDataAsText, navigationHandler, setFilteredCountryCode, viewport }: MapRowsProps): ReactNode[][] => {
11
11
  return rows.map(row =>
12
12
  Object.keys(columns)
13
13
  .filter(column => columns[column].dataTable === true && columns[column].name)
@@ -31,7 +31,7 @@ const mapCellArray = ({ rows, columns, runtimeData, config, applyLegendToRow, di
31
31
  }
32
32
  cellValue = (
33
33
  <div className='col-12'>
34
- <LegendCircle fill={legendColor[0]} />
34
+ <LegendCircle viewport={viewport} fill={legendColor[0]} />
35
35
  <CellAnchor markup={labelValue} row={rowObj} columns={columns} navigationHandler={navigationHandler} mapZoomHandler={mapZoomHandler} />
36
36
  </div>
37
37
  )
@@ -1,7 +1,7 @@
1
1
  type RuntimeData = Object[] & Record<string, Object>
2
2
 
3
3
  // removes null and excluded columns
4
- const customColumns = (runtimeData: Object[] | RuntimeData, excludeColumns: string[] = []): RuntimeData => {
4
+ const removeNullColumns = (runtimeData: Object[] | RuntimeData): RuntimeData => {
5
5
  if (!Array.isArray(runtimeData)) {
6
6
  // currently we don't support Record types
7
7
  return runtimeData
@@ -10,7 +10,7 @@ const customColumns = (runtimeData: Object[] | RuntimeData, excludeColumns: stri
10
10
  runtimeData.forEach(row => {
11
11
  Object.keys(row).forEach(key => {
12
12
  if (runtimeDataMemo[key] === undefined) runtimeDataMemo[key] = null
13
- if (row[key] !== null && !excludeColumns.includes(key)) runtimeDataMemo[key] = true
13
+ if (row[key] !== null) runtimeDataMemo[key] = true
14
14
  })
15
15
  })
16
16
  return runtimeData.map(d => {
@@ -24,4 +24,4 @@ const customColumns = (runtimeData: Object[] | RuntimeData, excludeColumns: stri
24
24
  }
25
25
  }
26
26
 
27
- export default customColumns
27
+ export default removeNullColumns
@@ -1,27 +1,17 @@
1
- import { Axis } from '@cdc/core/types/Axis'
2
- import { Series } from '@cdc/core/types/Series'
3
- import { Runtime } from '@cdc/core/types/Runtime'
4
- import { Table } from '@cdc/core/types/Table'
5
- import { Region } from '@cdc/core/types/Region'
1
+ import { Axis } from '../../../types/Axis'
2
+ import { Runtime } from '../../../types/Runtime'
3
+ import { Region } from '../../../types/Region'
6
4
  import { BoxPlot } from '../../../types/BoxPlot'
7
- import { General } from '../../../types/General'
8
- import { Column } from '../../../types/Column'
9
- import { Legend } from '@cdc/core/types/Legend'
5
+ import { PreliminaryDataItem } from '@cdc/chart/src/components/LineChart/LineChartProps'
6
+ import { Visualization } from '../../../types/Visualization'
10
7
 
11
- export type TableConfig = {
12
- type?: string
13
- table: Table
14
- xAxis?: Axis
15
- yAxis?: Axis
8
+ export type TableConfig = Visualization & {
16
9
  boxplot?: BoxPlot
17
- visualizationType: string
18
- general?: General
19
- columns?: Record<string, Column>
20
- legend?: Legend
21
- series?: Series
10
+ fontSize: 'small' | 'medium' | 'large'
22
11
  regions?: Region[]
23
- runtimeSeriesLabels?: Object
24
- dataFormat?: Object
25
12
  runtime?: Runtime
26
- data: Object[]
13
+ runtimeSeriesLabels?: Object
14
+ xAxis?: Axis
15
+ yAxis?: Axis
16
+ preliminaryData: PreliminaryDataItem[]
27
17
  }