@cdc/map 4.25.3 → 4.25.6
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/.idea/map.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/dist/cdcmap.js +31254 -32242
- package/examples/hex-colors.json +3 -3
- package/examples/m2.json +32904 -0
- package/examples/private/test.json +470 -1457
- package/examples/private/{mmr.json → wastewatermap.json} +86 -115
- package/index.html +36 -63
- package/package.json +7 -19
- package/src/CdcMap.tsx +56 -1552
- package/src/CdcMapComponent.tsx +608 -0
- package/src/_stories/CdcMap.Legend.Gradient.stories.tsx +10 -0
- package/src/_stories/CdcMap.Legend.stories.tsx +67 -0
- package/src/_stories/CdcMap.Table.stories.tsx +19 -0
- package/src/_stories/CdcMap.stories.tsx +12 -1
- package/src/_stories/UsaMap.NoData.stories.tsx +4 -4
- package/src/_stories/_mock/default-patterns.json +8 -5
- package/src/_stories/_mock/legend-bins.json +428 -0
- package/{examples/private/default-patterns.json → src/_stories/_mock/legends/legend-tests.json} +36 -131
- package/src/cdcMapComponent.styles.css +9 -0
- package/src/components/Annotation/Annotation.Draggable.tsx +27 -26
- package/src/components/Annotation/AnnotationDropdown.tsx +5 -6
- package/src/components/BubbleList.tsx +135 -49
- package/src/components/CityList.tsx +89 -87
- package/src/components/DataTable.tsx +8 -8
- package/src/components/EditorPanel/components/EditorPanel.tsx +823 -885
- package/src/components/EditorPanel/components/Error.tsx +9 -2
- package/src/components/EditorPanel/components/HexShapeSettings.tsx +127 -141
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +55 -86
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +89 -75
- package/src/components/EditorPanel/components/editorPanel.styles.css +95 -0
- package/src/components/Geo.tsx +9 -1
- package/src/components/GoogleMap/components/GoogleMap.tsx +1 -1
- package/src/components/Legend/components/Legend.tsx +92 -87
- package/src/components/Legend/components/LegendGroup/Legend.Group.tsx +128 -0
- package/src/components/Legend/components/LegendGroup/legend.group.css +27 -0
- package/src/components/Legend/components/LegendItem.Hex.tsx +4 -1
- package/src/components/Legend/components/index.scss +74 -17
- package/src/components/Modal.tsx +17 -7
- package/src/components/NavigationMenu.tsx +11 -9
- package/src/components/UsaMap/components/SingleState/SingleState.CountyOutput.tsx +12 -8
- package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +4 -4
- package/src/components/UsaMap/components/TerritoriesSection.tsx +33 -10
- package/src/components/UsaMap/components/Territory/Territory.Hexagon.tsx +12 -10
- package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +12 -14
- package/src/components/UsaMap/components/Territory/TerritoryShape.ts +2 -1
- package/src/components/UsaMap/components/UsaMap.County.tsx +138 -96
- package/src/components/UsaMap/components/UsaMap.Region.styles.css +72 -0
- package/src/components/UsaMap/components/UsaMap.Region.tsx +56 -103
- package/src/components/UsaMap/components/UsaMap.SingleState.styles.css +10 -0
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +65 -74
- package/src/components/UsaMap/components/UsaMap.State.tsx +112 -91
- package/src/components/UsaMap/helpers/map.ts +1 -1
- package/src/components/UsaMap/helpers/shapes.ts +20 -7
- package/src/components/WorldMap/WorldMap.tsx +64 -118
- package/src/components/WorldMap/worldMap.styles.css +28 -0
- package/src/components/ZoomControls.tsx +15 -13
- package/src/components/zoomControls.styles.css +53 -0
- package/src/context.ts +17 -9
- package/src/data/initial-state.js +5 -2
- package/src/helpers/addUIDs.ts +150 -0
- package/src/helpers/applyColorToLegend.ts +39 -64
- package/src/helpers/applyLegendToRow.ts +51 -0
- package/src/helpers/colorDistributions.ts +12 -0
- package/src/helpers/constants.ts +44 -0
- package/src/helpers/displayGeoName.ts +9 -2
- package/src/helpers/formatLegendLocation.ts +3 -2
- package/src/helpers/generateColorsArray.ts +2 -1
- package/src/helpers/generateRuntimeData.ts +78 -0
- package/src/helpers/generateRuntimeFilters.ts +63 -0
- package/src/helpers/generateRuntimeLegend.ts +566 -0
- package/src/helpers/generateRuntimeLegendHash.ts +16 -15
- package/src/helpers/getColumnNames.ts +19 -0
- package/src/helpers/getMapContainerClasses.ts +23 -0
- package/src/helpers/getStatePicked.ts +8 -0
- package/src/helpers/handleMapTabbing.ts +31 -0
- package/src/helpers/hashObj.ts +1 -1
- package/src/helpers/index.ts +22 -0
- package/src/helpers/navigationHandler.ts +3 -3
- package/src/helpers/resetLegendToggles.ts +13 -0
- package/src/helpers/setBinNumbers.ts +5 -0
- package/src/helpers/sortSpecialClassesLast.ts +7 -0
- package/src/helpers/tests/getColumnNames.test.ts +52 -0
- package/src/helpers/titleCase.ts +1 -1
- package/src/helpers/toggleLegendActive.ts +25 -0
- package/src/hooks/useApplyTooltipsToGeo.tsx +51 -0
- package/src/hooks/useColumnsRequiredChecker.ts +51 -0
- package/src/hooks/useGeoClickHandler.ts +45 -0
- package/src/hooks/useLegendSeparators.ts +26 -0
- package/src/hooks/useMapLayers.tsx +34 -60
- package/src/hooks/useModal.ts +22 -0
- package/src/hooks/useResizeObserver.ts +4 -5
- package/src/hooks/useStateZoom.tsx +52 -75
- package/src/hooks/useTooltip.ts +2 -3
- package/src/index.jsx +3 -9
- package/src/scss/editor-panel.scss +3 -99
- package/src/scss/main.scss +1 -19
- package/src/scss/map.scss +15 -220
- package/src/store/map.actions.ts +46 -0
- package/src/store/map.reducer.ts +96 -0
- package/src/types/Annotations.ts +24 -0
- package/src/types/MapConfig.ts +23 -3
- package/src/types/MapContext.ts +36 -35
- package/src/types/Modal.ts +1 -0
- package/src/types/RuntimeData.ts +3 -0
- package/examples/private/DEV-9644.json +0 -184
- package/examples/private/DEV-9989.json +0 -229
- package/examples/private/ardi.json +0 -180
- package/examples/private/colors 2.json +0 -416
- package/examples/private/colors.json +0 -416
- package/examples/private/colors.json.zip +0 -0
- package/examples/private/customColors.json +0 -45348
- package/examples/test.json +0 -183
- package/src/helpers/closeModal.ts +0 -9
- package/src/scss/btn.scss +0 -69
- package/src/scss/filters.scss +0 -27
- package/src/scss/variables.scss +0 -1
- /package/src/hooks/{useActiveElement.js → useActiveElement.ts} +0 -0
|
@@ -1,80 +1,55 @@
|
|
|
1
1
|
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
2
2
|
import chroma from 'chroma-js'
|
|
3
|
-
import { type
|
|
4
|
-
import
|
|
3
|
+
import { type MapConfig } from '@cdc/map/src/types/MapConfig'
|
|
4
|
+
import { colorDistributions } from './colorDistributions'
|
|
5
|
+
|
|
6
|
+
type LegendItem = {
|
|
7
|
+
special: boolean
|
|
8
|
+
}
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
11
|
* applyColorToLegend
|
|
8
12
|
* @param legendIdx legend item index
|
|
9
13
|
* @param config chart config
|
|
10
14
|
* @param result hash of legend items
|
|
11
|
-
* @returns
|
|
15
|
+
* @returns string - the corresponding color for the legend item
|
|
12
16
|
*/
|
|
13
|
-
export const applyColorToLegend = (legendIdx: number, config:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const specialClasses = config?.legend?.specialClasses
|
|
31
|
-
const { general } = config || {}
|
|
32
|
-
// Default to "bluegreen" color scheme if the passed color isn't valid
|
|
33
|
-
let mapColorPalette = config.customColors || colorPalettes[config.color] || colorPalettes['bluegreen']
|
|
34
|
-
|
|
35
|
-
// Handle Region Maps need for a 10th color
|
|
36
|
-
if (general.geoType === 'us-region' && mapColorPalette.length < 10 && mapColorPalette.length > 8) {
|
|
37
|
-
if (!general.palette.isReversed) {
|
|
38
|
-
mapColorPalette.push(chroma(mapColorPalette[8]).darken(0.75).hex())
|
|
39
|
-
} else {
|
|
40
|
-
mapColorPalette.unshift(chroma(mapColorPalette[0]).darken(0.75).hex())
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
let colorIdx = legendIdx - specialClasses.length
|
|
17
|
+
export const applyColorToLegend = (legendIdx: number, config: MapConfig, result: LegendItem[] = []): string => {
|
|
18
|
+
if (!config) throw new Error('Config is required')
|
|
19
|
+
|
|
20
|
+
const { legend, customColors, general, color } = config
|
|
21
|
+
const { geoType, palette } = general
|
|
22
|
+
const specialClasses = legend?.specialClasses ?? []
|
|
23
|
+
const mapColorPalette = customColors ?? colorPalettes[color] ?? colorPalettes['bluegreen']
|
|
24
|
+
|
|
25
|
+
// Handle Region Maps need for a 10th color
|
|
26
|
+
if (geoType === 'us-region' && mapColorPalette.length < 10 && mapColorPalette.length > 8) {
|
|
27
|
+
const newColor = chroma(mapColorPalette[palette.isReversed ? 0 : 8])
|
|
28
|
+
.darken(0.75)
|
|
29
|
+
.hex()
|
|
30
|
+
palette.isReversed ? mapColorPalette.unshift(newColor) : mapColorPalette.push(newColor)
|
|
31
|
+
}
|
|
45
32
|
|
|
46
|
-
|
|
47
|
-
if (result[legendIdx].special) {
|
|
48
|
-
if (!config?.migrations?.addColorMigration) {
|
|
49
|
-
const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(specialClasses)
|
|
50
|
-
return specialClassColors[legendIdx]
|
|
51
|
-
} else {
|
|
52
|
-
const specialClassColors = ['#A9AEB1', '#71767A']
|
|
53
|
-
return specialClassColors[legendIdx]
|
|
54
|
-
}
|
|
55
|
-
}
|
|
33
|
+
const colorIdx = legendIdx - specialClasses.length
|
|
56
34
|
|
|
57
|
-
|
|
35
|
+
// Handle special classes coloring
|
|
36
|
+
if (result[legendIdx]?.special) {
|
|
37
|
+
const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(specialClasses.length)
|
|
38
|
+
return specialClassColors[legendIdx]
|
|
39
|
+
}
|
|
58
40
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (config.customColors) return mapColorPalette[legendIdx - specialClasses.length]
|
|
62
|
-
}
|
|
41
|
+
// Use qualitative color palettes directly
|
|
42
|
+
if (color.includes('qualitative')) return mapColorPalette[colorIdx]
|
|
63
43
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
44
|
+
// Determine color distribution
|
|
45
|
+
const amt =
|
|
46
|
+
Math.max(result.length - specialClasses.length, 1) < 10
|
|
47
|
+
? Math.max(result.length - specialClasses.length, 1)
|
|
48
|
+
: Object.keys(colorDistributions).length
|
|
49
|
+
const distributionArray = colorDistributions[amt] ?? []
|
|
67
50
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} else if (mapColorPalette[colorIdx]) {
|
|
71
|
-
specificColor = colorIdx
|
|
72
|
-
} else {
|
|
73
|
-
specificColor = mapColorPalette.length - 1
|
|
74
|
-
}
|
|
51
|
+
const specificColor =
|
|
52
|
+
distributionArray[legendIdx - specialClasses.length] ?? mapColorPalette[colorIdx] ?? mapColorPalette.at(-1)
|
|
75
53
|
|
|
76
|
-
|
|
77
|
-
} catch (error) {
|
|
78
|
-
console.error('Error in applyColorToLegend', error)
|
|
79
|
-
}
|
|
54
|
+
return mapColorPalette[specificColor]
|
|
80
55
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { generateColorsArray, hashObj } from '../helpers'
|
|
2
|
+
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
3
|
+
import { MapConfig } from '../types/MapConfig'
|
|
4
|
+
import { type RuntimeLegend } from '../types/runtimeLegend'
|
|
5
|
+
|
|
6
|
+
type Memo<T> = { current: Map<string, T> }
|
|
7
|
+
|
|
8
|
+
export const applyLegendToRow = (
|
|
9
|
+
rowObj: Record<string, any>,
|
|
10
|
+
config: MapConfig,
|
|
11
|
+
runtimeLegend: RuntimeLegend,
|
|
12
|
+
legendMemo: Memo<number>,
|
|
13
|
+
legendSpecialClassLastMemo: Memo<number>
|
|
14
|
+
): string[] => {
|
|
15
|
+
if (!config) return null
|
|
16
|
+
|
|
17
|
+
const { general, color, legend } = config
|
|
18
|
+
const { type } = general
|
|
19
|
+
const { showSpecialClassesLast } = legend
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
if (!rowObj) {
|
|
23
|
+
console.error('COVE: No rowObj in applyLegendToRow')
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (type === 'navigation') {
|
|
28
|
+
const mapColorPalette = colorPalettes[color] ?? colorPalettes['bluegreenreverse']
|
|
29
|
+
return generateColorsArray(mapColorPalette[3])
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const hash = hashObj(rowObj)
|
|
33
|
+
|
|
34
|
+
if (!legendMemo.current.has(hash)) {
|
|
35
|
+
return generateColorsArray()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const idx = legendMemo.current.get(hash)!
|
|
39
|
+
const disabledIdx = showSpecialClassesLast ? legendSpecialClassLastMemo.current.get(hash) ?? idx : idx
|
|
40
|
+
|
|
41
|
+
if (runtimeLegend.items?.[disabledIdx]?.disabled) {
|
|
42
|
+
return generateColorsArray()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const legendBinColor = runtimeLegend.items.find(o => o.bin === idx)?.color
|
|
46
|
+
return generateColorsArray(legendBinColor, runtimeLegend.items[idx]?.special)
|
|
47
|
+
} catch (e) {
|
|
48
|
+
console.error('COVE: ', e)
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const colorDistributions = {
|
|
2
|
+
1: [1],
|
|
3
|
+
2: [1, 3],
|
|
4
|
+
3: [1, 3, 5],
|
|
5
|
+
4: [0, 2, 4, 6],
|
|
6
|
+
5: [0, 2, 4, 6, 7],
|
|
7
|
+
6: [0, 2, 3, 4, 5, 7],
|
|
8
|
+
7: [0, 2, 3, 4, 5, 6, 7],
|
|
9
|
+
8: [0, 2, 3, 4, 5, 6, 7, 8],
|
|
10
|
+
9: [0, 1, 2, 3, 4, 5, 6, 7, 8],
|
|
11
|
+
10: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
12
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const SVG_WIDTH = 880
|
|
2
|
+
export const SVG_HEIGHT = 500
|
|
3
|
+
export const SVG_PADDING = 50
|
|
4
|
+
export const SVG_VIEWBOX = `0 0 ${SVG_WIDTH} ${SVG_HEIGHT}`
|
|
5
|
+
export const HEADER_COLORS = [
|
|
6
|
+
'theme-blue',
|
|
7
|
+
'theme-purple',
|
|
8
|
+
'theme-brown',
|
|
9
|
+
'theme-teal',
|
|
10
|
+
'theme-pink',
|
|
11
|
+
'theme-orange',
|
|
12
|
+
'theme-slate',
|
|
13
|
+
'theme-indigo',
|
|
14
|
+
'theme-cyan',
|
|
15
|
+
'theme-green',
|
|
16
|
+
'theme-amber'
|
|
17
|
+
]
|
|
18
|
+
export const MAX_ZOOM_LEVEL = 4
|
|
19
|
+
|
|
20
|
+
export const SUPPORTED_DC_NAMES = [
|
|
21
|
+
'WASHINGTON D.C.',
|
|
22
|
+
'DISTRICT OF COLUMBIA',
|
|
23
|
+
'WASHINGTON DC',
|
|
24
|
+
'DC',
|
|
25
|
+
'WASHINGTON DC.',
|
|
26
|
+
'D.C.',
|
|
27
|
+
'D.C'
|
|
28
|
+
] as const
|
|
29
|
+
|
|
30
|
+
export const GEO_TYPES = {
|
|
31
|
+
US: 'us',
|
|
32
|
+
US_REGION: 'us-region',
|
|
33
|
+
WORLD: 'world',
|
|
34
|
+
US_COUNTY: 'us-county',
|
|
35
|
+
SINGLE_STATE: 'single-state',
|
|
36
|
+
GOOGLE_MAP: 'google-map'
|
|
37
|
+
} as const
|
|
38
|
+
|
|
39
|
+
export const GEOCODE_TYPES = {
|
|
40
|
+
WORLD: 'world-geocode',
|
|
41
|
+
US: 'us-geocode'
|
|
42
|
+
} as const
|
|
43
|
+
|
|
44
|
+
export const DEFAULT_MAP_BACKGROUND = '#DFE1E2'
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { titleCase } from './titleCase'
|
|
2
2
|
import { supportedStates, supportedTerritories, supportedCountries, supportedCounties } from '../data/supported-geos'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Converts a geographic key to its display name.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} key - The geographic key to convert.
|
|
8
|
+
* @param {boolean} [convertFipsCodes=true] - Whether to convert FIPS codes.
|
|
9
|
+
* @returns {string} - The display name for the geographic key.
|
|
10
|
+
*/
|
|
11
|
+
export const displayGeoName = (key: string, convertFipsCodes = true): string => {
|
|
5
12
|
if (!convertFipsCodes) return key
|
|
6
13
|
const stateKeys = Object.keys(supportedStates)
|
|
7
14
|
const territoryKeys = Object.keys(supportedTerritories)
|
|
@@ -41,7 +48,7 @@ export const displayGeoName = (key, convertFipsCodes = true): string => {
|
|
|
41
48
|
value = dict[value]
|
|
42
49
|
}
|
|
43
50
|
// if you get here and it's 2 letters then DONT titleCase state abbreviations like "AL"
|
|
44
|
-
if (value
|
|
51
|
+
if (value?.length === 2 || value === 'U.S. Virgin Islands') {
|
|
45
52
|
return value
|
|
46
53
|
} else {
|
|
47
54
|
return titleCase(value)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { stateFipsToTwoDigit, supportedCounties } from '../data/supported-geos'
|
|
2
2
|
import { titleCase } from './titleCase'
|
|
3
3
|
|
|
4
|
+
const countyKeySet = new Set(Object.keys(supportedCounties))
|
|
5
|
+
|
|
4
6
|
export const formatLegendLocation = (key, runtimeLookup) => {
|
|
5
7
|
let formattedName = ''
|
|
6
8
|
|
|
@@ -9,8 +11,7 @@ export const formatLegendLocation = (key, runtimeLookup) => {
|
|
|
9
11
|
formattedName += stateName
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
if (countyKeys.includes(key)) {
|
|
14
|
+
if (countyKeySet.has(key)) {
|
|
14
15
|
formattedName += ', ' + titleCase(supportedCounties[key])
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chroma from 'chroma-js'
|
|
2
|
+
import { DEFAULT_MAP_BACKGROUND } from './constants'
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Generate an array of colors based on a given color [color, hoverColor, darkColor]
|
|
@@ -6,7 +7,7 @@ import chroma from 'chroma-js'
|
|
|
6
7
|
* @param {boolean} special - A flag to determine if the hover color should be brighter or saturated
|
|
7
8
|
* @returns {string[]} - An array of colors
|
|
8
9
|
*/
|
|
9
|
-
export const generateColorsArray = (color: string =
|
|
10
|
+
export const generateColorsArray = (color: string = DEFAULT_MAP_BACKGROUND, special: boolean = false) => {
|
|
10
11
|
let colorObj = chroma(color)
|
|
11
12
|
let hoverColor = special ? colorObj.brighten(0.5).hex() : colorObj.saturate(1.3).hex()
|
|
12
13
|
return [color, hoverColor, colorObj.darken(0.3).hex()]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { addUIDs } from '.'
|
|
2
|
+
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
3
|
+
import { MapConfig } from '../types/MapConfig'
|
|
4
|
+
import { VizFilter } from '@cdc/core/types/VizFilter'
|
|
5
|
+
import { DataRow } from '../types/MapConfig'
|
|
6
|
+
|
|
7
|
+
const generateRuntimeData = (
|
|
8
|
+
configObj: MapConfig,
|
|
9
|
+
filters: VizFilter[],
|
|
10
|
+
hash: number,
|
|
11
|
+
isCategoryLegend: boolean,
|
|
12
|
+
keepNoUidRows = false
|
|
13
|
+
): {
|
|
14
|
+
[uid: string]: DataRow
|
|
15
|
+
} => {
|
|
16
|
+
try {
|
|
17
|
+
const result: { [uid: string]: DataRow } = {}
|
|
18
|
+
|
|
19
|
+
// Adding property this way prevents it from being enumerated
|
|
20
|
+
Object.defineProperty(result, 'fromHash', {
|
|
21
|
+
value: hash
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
addUIDs(configObj, configObj.columns.geo.name)
|
|
25
|
+
|
|
26
|
+
configObj.data.forEach((row: DataRow) => {
|
|
27
|
+
if (!row.uid) {
|
|
28
|
+
if (!keepNoUidRows) return false // No UID for this row, we can't use for mapping
|
|
29
|
+
row.uid = row[configObj.columns.geo.name]
|
|
30
|
+
}
|
|
31
|
+
const configPrimaryName = configObj.columns.primary.name
|
|
32
|
+
const value = row[configPrimaryName]
|
|
33
|
+
const categoryLegend = typeof value === 'string' && isCategoryLegend
|
|
34
|
+
if (value && !categoryLegend) {
|
|
35
|
+
row[configPrimaryName] = numberFromString(value)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// If this is a navigation only map, skip if it doesn't have a URL
|
|
39
|
+
|
|
40
|
+
if ('navigation' === configObj.general.type) {
|
|
41
|
+
let navigateUrl = row[configObj.columns.navigate.name] || ''
|
|
42
|
+
|
|
43
|
+
if (undefined !== navigateUrl && typeof navigateUrl === 'string') {
|
|
44
|
+
// Strip hidden characters before we check length
|
|
45
|
+
navigateUrl = navigateUrl.replace(/(\r\n|\n|\r)/gm, '')
|
|
46
|
+
}
|
|
47
|
+
if (0 === navigateUrl?.length) {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Filters
|
|
53
|
+
if (filters?.length) {
|
|
54
|
+
for (let i = 0; i < filters.length; i++) {
|
|
55
|
+
const { columnName, active, type, filterStyle, subGrouping } = filters[i]
|
|
56
|
+
const isDataFilter = type !== 'url'
|
|
57
|
+
const matchingValue = String(active) === String(row[columnName]) // Group
|
|
58
|
+
if (isDataFilter && !matchingValue) return false // Bail out, data doesn't match the filter selection
|
|
59
|
+
if (filterStyle == 'nested-dropdown') {
|
|
60
|
+
const matchingSubValue = String(row[subGrouping?.columnName]) === String(subGrouping?.active)
|
|
61
|
+
if (subGrouping?.active && !matchingSubValue) {
|
|
62
|
+
return false // Bail out, data doesn't match the subgroup selection
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Don't add additional rows with same UID
|
|
68
|
+
if (result[row.uid] === undefined) {
|
|
69
|
+
result[row.uid] = row
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
return result
|
|
73
|
+
} catch (e) {
|
|
74
|
+
console.error('COVE: ', e) // eslint-disable-line
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default generateRuntimeData
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { getUniqueValues } from './index'
|
|
2
|
+
import { handleSorting } from '@cdc/core/components/Filters'
|
|
3
|
+
|
|
4
|
+
export const generateRuntimeFilters = (state, hash, runtimeFilters) => {
|
|
5
|
+
if (typeof state === 'undefined' || undefined === state.filters || state.filters.length === 0) return []
|
|
6
|
+
|
|
7
|
+
const filters = state?.filters.map(
|
|
8
|
+
(
|
|
9
|
+
{
|
|
10
|
+
columnName,
|
|
11
|
+
label,
|
|
12
|
+
labels,
|
|
13
|
+
queryParameter,
|
|
14
|
+
orderedValues,
|
|
15
|
+
active,
|
|
16
|
+
values,
|
|
17
|
+
type,
|
|
18
|
+
showDropdown,
|
|
19
|
+
setByQueryParameter,
|
|
20
|
+
order
|
|
21
|
+
},
|
|
22
|
+
idx
|
|
23
|
+
) => {
|
|
24
|
+
const newFilter = runtimeFilters[idx] || {}
|
|
25
|
+
|
|
26
|
+
const sort = (a, b) => {
|
|
27
|
+
const asc = order !== 'desc'
|
|
28
|
+
return String(asc ? a : b).localeCompare(String(asc ? b : a), 'en', { numeric: true })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (type !== 'url') {
|
|
32
|
+
values = getUniqueValues(state.data, columnName)
|
|
33
|
+
|
|
34
|
+
if (state.filters[idx].order === 'cust') {
|
|
35
|
+
if (state.filters[idx]?.values.length > 0) {
|
|
36
|
+
values = state.filters[idx].values
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
values = values.sort(sort)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
newFilter.order = state.filters[idx].order ? state.filters[idx].order : 'asc'
|
|
44
|
+
newFilter.type = type
|
|
45
|
+
newFilter.label = label ?? ''
|
|
46
|
+
newFilter.columnName = columnName
|
|
47
|
+
newFilter.orderedValues = orderedValues
|
|
48
|
+
newFilter.queryParameter = queryParameter
|
|
49
|
+
newFilter.labels = labels
|
|
50
|
+
newFilter.values = values
|
|
51
|
+
newFilter.setByQueryParameter = setByQueryParameter
|
|
52
|
+
handleSorting(newFilter)
|
|
53
|
+
newFilter.active = active ?? values[0] // Default to first found value
|
|
54
|
+
newFilter.filterStyle = state.filters[idx].filterStyle ? state.filters[idx].filterStyle : 'dropdown'
|
|
55
|
+
newFilter.showDropdown = showDropdown
|
|
56
|
+
newFilter.subGrouping = state.filters[idx].subGrouping
|
|
57
|
+
|
|
58
|
+
return newFilter
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
if (hash) filters.fromHash = hash
|
|
62
|
+
return filters
|
|
63
|
+
}
|