@cdc/map 4.22.10-alpha.1 → 4.22.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdcmap.js +10 -10
- package/examples/private/atsdr.json +19 -29
- package/examples/private/atsdr_new.json +1 -1
- package/examples/private/bubble.json +282 -284
- package/examples/private/city-state.json +427 -427
- package/examples/private/city-state2.json +433 -433
- package/examples/private/cty-issue.json +42765 -42768
- package/examples/private/default-usa.json +2 -5
- package/examples/private/default-world-data.json +1443 -1443
- package/examples/private/default.json +965 -965
- package/examples/private/diff.json +226 -0
- package/examples/private/filters.json +1 -0
- package/examples/private/legend-issue.json +3271 -1
- package/examples/private/map-issue.json +166 -0
- package/examples/private/map-rounding-error.json +42756 -42759
- package/examples/private/mdx.json +209 -209
- package/examples/private/monkeypox.json +375 -375
- package/examples/private/regions.json +51 -51
- package/examples/private/wcmsrd-13881-data.json +2856 -2856
- package/examples/private/wcmsrd-13881.json +5818 -5822
- package/examples/private/wcmsrd-14492-data.json +291 -291
- package/examples/private/wcmsrd-14492.json +103 -113
- package/examples/private/wcmsrd-test.json +264 -267
- package/examples/private/world.json +1579 -1579
- package/examples/private/worldmap.json +1489 -1489
- package/package.json +3 -3
- package/src/CdcMap.js +231 -315
- package/src/components/BubbleList.js +199 -240
- package/src/components/CityList.js +50 -96
- package/src/components/CountyMap.js +511 -600
- package/src/components/DataTable.js +218 -253
- package/src/components/EditorPanel.js +2338 -2551
- package/src/components/Geo.js +4 -14
- package/src/components/Modal.js +13 -23
- package/src/components/NavigationMenu.js +43 -39
- package/src/components/Sidebar.js +83 -93
- package/src/components/SingleStateMap.js +95 -151
- package/src/components/UsaMap.js +165 -214
- package/src/components/UsaRegionMap.js +122 -160
- package/src/components/WorldMap.js +96 -179
- package/src/components/ZoomableGroup.js +6 -26
- package/src/data/initial-state.js +1 -0
- package/src/hooks/useActiveElement.js +13 -13
- package/src/hooks/useColorPalette.ts +66 -74
- package/src/hooks/useZoomPan.js +22 -23
- package/src/index.html +1 -2
- package/src/scss/sidebar.scss +22 -0
package/src/CdcMap.js
CHANGED
|
@@ -17,16 +17,7 @@ import Canvg from 'canvg'
|
|
|
17
17
|
// Data
|
|
18
18
|
import colorPalettes from '../../core/data/colorPalettes'
|
|
19
19
|
import ExternalIcon from './images/external-link.svg'
|
|
20
|
-
import {
|
|
21
|
-
supportedStates,
|
|
22
|
-
supportedTerritories,
|
|
23
|
-
supportedCountries,
|
|
24
|
-
supportedCounties,
|
|
25
|
-
supportedCities,
|
|
26
|
-
supportedStatesFipsCodes,
|
|
27
|
-
stateFipsToTwoDigit,
|
|
28
|
-
supportedRegions
|
|
29
|
-
} from './data/supported-geos'
|
|
20
|
+
import { supportedStates, supportedTerritories, supportedCountries, supportedCounties, supportedCities, supportedStatesFipsCodes, stateFipsToTwoDigit, supportedRegions } from './data/supported-geos'
|
|
30
21
|
import initialState from './data/initial-state'
|
|
31
22
|
import { countryCoordinates } from './data/country-coordinates'
|
|
32
23
|
|
|
@@ -40,12 +31,12 @@ import DownloadImg from './images/icon-download-img.svg'
|
|
|
40
31
|
import DownloadPdf from './images/icon-download-pdf.svg'
|
|
41
32
|
|
|
42
33
|
// Core
|
|
43
|
-
import Loading from '@cdc/core/components/Loading'
|
|
44
|
-
import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
45
|
-
import getViewport from '@cdc/core/helpers/getViewport'
|
|
46
|
-
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
47
|
-
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
48
|
-
import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
|
|
34
|
+
import Loading from '@cdc/core/components/Loading'
|
|
35
|
+
import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
36
|
+
import getViewport from '@cdc/core/helpers/getViewport'
|
|
37
|
+
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
38
|
+
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
39
|
+
import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
|
|
49
40
|
|
|
50
41
|
// Child Components
|
|
51
42
|
import Sidebar from './components/Sidebar'
|
|
@@ -73,14 +64,10 @@ const generateColorsArray = (color = '#000000', special = false) => {
|
|
|
73
64
|
let colorObj = chroma(color)
|
|
74
65
|
let hoverColor = special ? colorObj.brighten(0.5).hex() : colorObj.saturate(1.3).hex()
|
|
75
66
|
|
|
76
|
-
return [
|
|
77
|
-
color,
|
|
78
|
-
hoverColor,
|
|
79
|
-
colorObj.darken(0.3).hex()
|
|
80
|
-
]
|
|
67
|
+
return [color, hoverColor, colorObj.darken(0.3).hex()]
|
|
81
68
|
}
|
|
82
69
|
|
|
83
|
-
const hashObj =
|
|
70
|
+
const hashObj = row => {
|
|
84
71
|
try {
|
|
85
72
|
if (!row) throw new Error('No row supplied to hashObj')
|
|
86
73
|
|
|
@@ -91,7 +78,7 @@ const hashObj = (row) => {
|
|
|
91
78
|
|
|
92
79
|
for (let i = 0; i < str.length; i++) {
|
|
93
80
|
let char = str.charCodeAt(i)
|
|
94
|
-
hash = (
|
|
81
|
+
hash = (hash << 5) - hash + char
|
|
95
82
|
hash = hash & hash
|
|
96
83
|
}
|
|
97
84
|
|
|
@@ -119,20 +106,20 @@ const getUniqueValues = (data, columnName) => {
|
|
|
119
106
|
}
|
|
120
107
|
|
|
121
108
|
const CdcMap = ({ className, config, navigationHandler: customNavigationHandler, isDashboard = false, isEditor = false, configUrl, logo = null, setConfig, setSharedFilter, setSharedFilterValue, hostname = 'localhost:8080', link }) => {
|
|
122
|
-
const [
|
|
109
|
+
const [showLoadingMessage, setShowLoadingMessage] = useState(false)
|
|
123
110
|
const transform = new DataTransform()
|
|
124
|
-
const [
|
|
125
|
-
const [
|
|
126
|
-
const [
|
|
127
|
-
const [
|
|
128
|
-
const [
|
|
129
|
-
const [
|
|
130
|
-
const [
|
|
131
|
-
const [
|
|
132
|
-
const [
|
|
133
|
-
const [
|
|
134
|
-
const [
|
|
135
|
-
const [
|
|
111
|
+
const [state, setState] = useState({ ...initialState })
|
|
112
|
+
const [loading, setLoading] = useState(true)
|
|
113
|
+
const [currentViewport, setCurrentViewport] = useState()
|
|
114
|
+
const [runtimeFilters, setRuntimeFilters] = useState([])
|
|
115
|
+
const [runtimeLegend, setRuntimeLegend] = useState([])
|
|
116
|
+
const [runtimeData, setRuntimeData] = useState({ init: true })
|
|
117
|
+
const [modal, setModal] = useState(null)
|
|
118
|
+
const [accessibleStatus, setAccessibleStatus] = useState('')
|
|
119
|
+
const [filteredCountryCode, setFilteredCountryCode] = useState()
|
|
120
|
+
const [position, setPosition] = useState(state.mapPosition)
|
|
121
|
+
const [coveLoadedHasRan, setCoveLoadedHasRan] = useState(false)
|
|
122
|
+
const [container, setContainer] = useState()
|
|
136
123
|
|
|
137
124
|
let legendMemo = useRef(new Map())
|
|
138
125
|
|
|
@@ -143,7 +130,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
143
130
|
const coordinates = countryCoordinates[filteredCountryCode]
|
|
144
131
|
const long = coordinates[1]
|
|
145
132
|
const lat = coordinates[0]
|
|
146
|
-
const reversedCoordinates = [
|
|
133
|
+
const reversedCoordinates = [long, lat]
|
|
147
134
|
|
|
148
135
|
setState({
|
|
149
136
|
...state,
|
|
@@ -153,7 +140,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
153
140
|
} catch (e) {
|
|
154
141
|
console.error('Failed to set world map zoom.')
|
|
155
142
|
}
|
|
156
|
-
}, [
|
|
143
|
+
}, [filteredCountryCode])
|
|
157
144
|
|
|
158
145
|
useEffect(() => {
|
|
159
146
|
setTimeout(() => {
|
|
@@ -165,15 +152,15 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
165
152
|
setRuntimeData(tmpData)
|
|
166
153
|
}
|
|
167
154
|
}, 100)
|
|
168
|
-
}, [
|
|
155
|
+
}, [filteredCountryCode])
|
|
169
156
|
|
|
170
157
|
useEffect(() => {
|
|
171
158
|
if (state.mapPosition) {
|
|
172
159
|
setPosition(state.mapPosition)
|
|
173
160
|
}
|
|
174
|
-
}, [
|
|
161
|
+
}, [state.mapPosition, setPosition])
|
|
175
162
|
|
|
176
|
-
const setZoom =
|
|
163
|
+
const setZoom = reversedCoordinates => {
|
|
177
164
|
setState({
|
|
178
165
|
...state,
|
|
179
166
|
mapPosition: { coordinates: reversedCoordinates, zoom: 3 }
|
|
@@ -207,16 +194,16 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
207
194
|
}
|
|
208
195
|
|
|
209
196
|
// States
|
|
210
|
-
uid = stateKeys.find(
|
|
197
|
+
uid = stateKeys.find(key => supportedStates[key].includes(geoName))
|
|
211
198
|
|
|
212
199
|
// Territories
|
|
213
200
|
if (!uid) {
|
|
214
|
-
uid = territoryKeys.find(
|
|
201
|
+
uid = territoryKeys.find(key => supportedTerritories[key].includes(geoName))
|
|
215
202
|
}
|
|
216
203
|
|
|
217
204
|
// Cities
|
|
218
205
|
if (!uid) {
|
|
219
|
-
uid = cityKeys.find(
|
|
206
|
+
uid = cityKeys.find(key => key === geoName)
|
|
220
207
|
}
|
|
221
208
|
}
|
|
222
209
|
|
|
@@ -230,20 +217,20 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
230
217
|
}
|
|
231
218
|
|
|
232
219
|
// Regions
|
|
233
|
-
uid = regionKeys.find(
|
|
220
|
+
uid = regionKeys.find(key => supportedRegions[key].includes(geoName))
|
|
234
221
|
}
|
|
235
222
|
|
|
236
223
|
// World Check
|
|
237
224
|
if ('world' === obj.general.geoType) {
|
|
238
225
|
const geoName = row[obj.columns.geo.name]
|
|
239
226
|
|
|
240
|
-
uid = countryKeys.find(
|
|
227
|
+
uid = countryKeys.find(key => supportedCountries[key].includes(geoName))
|
|
241
228
|
}
|
|
242
229
|
|
|
243
230
|
// County Check
|
|
244
231
|
if (('us-county' === obj.general.geoType || 'single-state' === obj.general.geoType) && 'us-geocode' !== obj.general.type) {
|
|
245
232
|
const fips = row[obj.columns.geo.name]
|
|
246
|
-
uid = countyKeys.find(
|
|
233
|
+
uid = countyKeys.find(key => key === fips)
|
|
247
234
|
}
|
|
248
235
|
|
|
249
236
|
if ('us-geocode' === state.general.type) {
|
|
@@ -263,8 +250,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
263
250
|
|
|
264
251
|
const generateRuntimeLegend = useCallback((obj, runtimeData, hash) => {
|
|
265
252
|
const newLegendMemo = new Map() // Reset memoization
|
|
266
|
-
const
|
|
267
|
-
primaryCol = obj.columns.primary.name,
|
|
253
|
+
const primaryCol = obj.columns.primary.name,
|
|
268
254
|
isData = obj.general.type === 'data',
|
|
269
255
|
isBubble = obj.general.type === 'bubble',
|
|
270
256
|
categoricalCol = obj.columns.categorical ? obj.columns.categorical.name : undefined,
|
|
@@ -281,19 +267,19 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
281
267
|
let dataSet = obj.legend.unified ? obj.data : Object.values(runtimeData)
|
|
282
268
|
|
|
283
269
|
const colorDistributions = {
|
|
284
|
-
1: [
|
|
285
|
-
2: [
|
|
286
|
-
3: [
|
|
287
|
-
4: [
|
|
288
|
-
5: [
|
|
289
|
-
6: [
|
|
290
|
-
7: [
|
|
291
|
-
8: [
|
|
292
|
-
9: [
|
|
293
|
-
10: [
|
|
270
|
+
1: [1],
|
|
271
|
+
2: [1, 3],
|
|
272
|
+
3: [1, 3, 5],
|
|
273
|
+
4: [0, 2, 4, 6],
|
|
274
|
+
5: [0, 2, 4, 6, 7],
|
|
275
|
+
6: [0, 2, 3, 4, 5, 7],
|
|
276
|
+
7: [0, 2, 3, 4, 5, 6, 7],
|
|
277
|
+
8: [0, 2, 3, 4, 5, 6, 7, 8],
|
|
278
|
+
9: [0, 1, 2, 3, 4, 5, 6, 7, 8],
|
|
279
|
+
10: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
294
280
|
}
|
|
295
281
|
|
|
296
|
-
const applyColorToLegend =
|
|
282
|
+
const applyColorToLegend = legendIdx => {
|
|
297
283
|
// Default to "bluegreen" color scheme if the passed color isn't valid
|
|
298
284
|
let mapColorPalette = obj.customColors || colorPalettes[obj.color] || colorPalettes['bluegreen']
|
|
299
285
|
|
|
@@ -310,7 +296,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
310
296
|
|
|
311
297
|
// Special Classes (No Data)
|
|
312
298
|
if (result[legendIdx].special) {
|
|
313
|
-
const specialClassColors = chroma.scale([
|
|
299
|
+
const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(specialClasses)
|
|
314
300
|
|
|
315
301
|
return specialClassColors[legendIdx]
|
|
316
302
|
}
|
|
@@ -410,7 +396,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
410
396
|
if (undefined === value) continue
|
|
411
397
|
|
|
412
398
|
if (false === uniqueValues.has(value)) {
|
|
413
|
-
uniqueValues.set(value, [
|
|
399
|
+
uniqueValues.set(value, [hashObj(row)])
|
|
414
400
|
count++
|
|
415
401
|
} else {
|
|
416
402
|
uniqueValues.get(value).push(hashObj(row))
|
|
@@ -419,15 +405,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
419
405
|
if (count === 10) break // Can only have 10 categorical items for now
|
|
420
406
|
}
|
|
421
407
|
|
|
422
|
-
let sorted = [
|
|
408
|
+
let sorted = [...uniqueValues.keys()]
|
|
423
409
|
|
|
424
410
|
// Apply custom sorting or regular sorting
|
|
425
411
|
let configuredOrder = obj.legend.categoryValuesOrder ?? []
|
|
426
412
|
|
|
427
|
-
// Coerce strings to numbers inside configuredOrder property
|
|
428
|
-
for(let i = 0; i < configuredOrder.length; i++) {
|
|
429
|
-
configuredOrder[i] = numberFromString(configuredOrder[i])
|
|
430
|
-
}
|
|
431
413
|
|
|
432
414
|
if (configuredOrder.length) {
|
|
433
415
|
sorted.sort((a, b) => {
|
|
@@ -438,9 +420,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
438
420
|
}
|
|
439
421
|
|
|
440
422
|
// Add legend item for each
|
|
441
|
-
sorted.forEach(
|
|
423
|
+
sorted.forEach(val => {
|
|
442
424
|
result.push({
|
|
443
|
-
value: val
|
|
425
|
+
value: val
|
|
444
426
|
})
|
|
445
427
|
|
|
446
428
|
let lastIdx = result.length - 1
|
|
@@ -500,12 +482,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
500
482
|
|
|
501
483
|
// Sort data for use in equalnumber or equalinterval
|
|
502
484
|
if (state.general.type !== 'us-geocode') {
|
|
503
|
-
dataSet = dataSet
|
|
504
|
-
|
|
505
|
-
|
|
485
|
+
dataSet = dataSet
|
|
486
|
+
.filter(row => typeof row[primaryCol] === 'number')
|
|
487
|
+
.sort((a, b) => {
|
|
488
|
+
let aNum = a[primaryCol]
|
|
489
|
+
let bNum = b[primaryCol]
|
|
506
490
|
|
|
507
|
-
|
|
508
|
-
|
|
491
|
+
return aNum - bNum
|
|
492
|
+
})
|
|
509
493
|
}
|
|
510
494
|
|
|
511
495
|
// Equal Number
|
|
@@ -558,8 +542,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
558
542
|
let colors = colorPalettes[state.color]
|
|
559
543
|
let colorRange = colors.slice(0, state.legend.numberOfItems)
|
|
560
544
|
|
|
561
|
-
let scale = d3
|
|
562
|
-
.
|
|
545
|
+
let scale = d3
|
|
546
|
+
.scaleQuantile()
|
|
547
|
+
.domain([...new Set(dataSet.map(item => Math.round(item[state.columns.primary.name])))]) // min/max values
|
|
563
548
|
.range(colorRange) // set range to our colors array
|
|
564
549
|
|
|
565
550
|
let breaks = scale.quantiles()
|
|
@@ -572,7 +557,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
572
557
|
}
|
|
573
558
|
|
|
574
559
|
breaks.map((item, index) => {
|
|
575
|
-
const setMin =
|
|
560
|
+
const setMin = index => {
|
|
576
561
|
//debugger;
|
|
577
562
|
let min = breaks[index]
|
|
578
563
|
|
|
@@ -665,7 +650,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
665
650
|
for (let i = 0; i < legendNumber; i++) {
|
|
666
651
|
let interval = Math.abs(dataMax - dataMin) / legendNumber
|
|
667
652
|
|
|
668
|
-
let min = dataMin +
|
|
653
|
+
let min = dataMin + interval * i
|
|
669
654
|
let max = min + interval
|
|
670
655
|
|
|
671
656
|
// If this is the last loop, assign actual max of data as the end point
|
|
@@ -679,7 +664,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
679
664
|
|
|
680
665
|
let range = {
|
|
681
666
|
min: Math.round(min * 100) / 100,
|
|
682
|
-
max: Math.round(max * 100) / 100
|
|
667
|
+
max: Math.round(max * 100) / 100
|
|
683
668
|
}
|
|
684
669
|
|
|
685
670
|
result.push(range)
|
|
@@ -768,11 +753,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
768
753
|
if (undefined === row.uid) return false // No UID for this row, we can't use for mapping
|
|
769
754
|
|
|
770
755
|
// When on a single state map filter runtime data by state
|
|
771
|
-
if (
|
|
772
|
-
!(String(row[obj.columns.geo.name]).substring(0, 2) === obj.general?.statePicked?.fipsCode) &&
|
|
773
|
-
obj.general.geoType === 'single-state' &&
|
|
774
|
-
obj.general.type !== 'us-geocode'
|
|
775
|
-
) {
|
|
756
|
+
if (!(String(row[obj.columns.geo.name]).substring(0, 2) === obj.general?.statePicked?.fipsCode) && obj.general.geoType === 'single-state' && obj.general.type !== 'us-geocode') {
|
|
776
757
|
return false
|
|
777
758
|
}
|
|
778
759
|
|
|
@@ -832,10 +813,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
832
813
|
const ie = navigator.userAgent.match(/MSIE\s([\d.]+)/)
|
|
833
814
|
const ie11 = navigator.userAgent.match(/Trident\/7.0/) && navigator.userAgent.match(/rv:11/)
|
|
834
815
|
const ieEdge = navigator.userAgent.match(/Edge/g)
|
|
835
|
-
const ieVer =
|
|
816
|
+
const ieVer = ie ? ie[1] : ie11 ? 11 : ieEdge ? 12 : -1
|
|
836
817
|
|
|
837
818
|
if (ieVer > -1) {
|
|
838
|
-
const fileAsBlob = new Blob([
|
|
819
|
+
const fileAsBlob = new Blob([uri], {
|
|
839
820
|
type: 'image/png'
|
|
840
821
|
})
|
|
841
822
|
window.navigator.msSaveBlob(fileAsBlob, filename)
|
|
@@ -844,7 +825,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
844
825
|
if (typeof link.download === 'string') {
|
|
845
826
|
link.href = uri
|
|
846
827
|
link.download = filename
|
|
847
|
-
link.onclick =
|
|
828
|
+
link.onclick = e => document.body.removeChild(e.target)
|
|
848
829
|
document.body.appendChild(link)
|
|
849
830
|
link.click()
|
|
850
831
|
} else {
|
|
@@ -891,12 +872,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
891
872
|
windowWidth: 1440,
|
|
892
873
|
scale: 1,
|
|
893
874
|
logging: false
|
|
894
|
-
}).then(canvas => {
|
|
895
|
-
saveImageAs(canvas.toDataURL(), filename + '.png')
|
|
896
|
-
}).then(() => {
|
|
897
|
-
generatedImage.remove() // Remove generated png
|
|
898
|
-
baseSvg.style.display = null // Re-display initial svg map
|
|
899
875
|
})
|
|
876
|
+
.then(canvas => {
|
|
877
|
+
saveImageAs(canvas.toDataURL(), filename + '.png')
|
|
878
|
+
})
|
|
879
|
+
.then(() => {
|
|
880
|
+
generatedImage.remove() // Remove generated png
|
|
881
|
+
baseSvg.style.display = null // Re-display initial svg map
|
|
882
|
+
})
|
|
900
883
|
case 'pdf':
|
|
901
884
|
let opt = {
|
|
902
885
|
margin: 0.2,
|
|
@@ -906,13 +889,17 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
906
889
|
jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
|
|
907
890
|
}
|
|
908
891
|
|
|
909
|
-
html2pdf()
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
892
|
+
html2pdf()
|
|
893
|
+
.set(opt)
|
|
894
|
+
.from(target)
|
|
895
|
+
.save()
|
|
896
|
+
.then(() => {
|
|
897
|
+
generatedImage.remove() // Remove generated png
|
|
898
|
+
baseSvg.style.display = null // Re-display initial svg map
|
|
899
|
+
})
|
|
913
900
|
break
|
|
914
901
|
default:
|
|
915
|
-
console.warn(
|
|
902
|
+
console.warn("generateMedia param 2 type must be 'image' or 'pdf'")
|
|
916
903
|
break
|
|
917
904
|
}
|
|
918
905
|
}
|
|
@@ -922,11 +909,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
922
909
|
resetLegendToggles()
|
|
923
910
|
|
|
924
911
|
try {
|
|
925
|
-
const isEmpty =
|
|
912
|
+
const isEmpty = obj => {
|
|
926
913
|
return Object.keys(obj).length === 0
|
|
927
914
|
}
|
|
928
915
|
|
|
929
|
-
let filters = [
|
|
916
|
+
let filters = [...runtimeFilters]
|
|
930
917
|
|
|
931
918
|
filters[idx] = { ...filters[idx] }
|
|
932
919
|
filters[idx].active = activeValue
|
|
@@ -988,7 +975,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
988
975
|
return formattedValue
|
|
989
976
|
}
|
|
990
977
|
|
|
991
|
-
const applyLegendToRow =
|
|
978
|
+
const applyLegendToRow = rowObj => {
|
|
992
979
|
try {
|
|
993
980
|
if (!rowObj) throw new Error('COVE: No rowObj in applyLegendToRow')
|
|
994
981
|
// Navigation map
|
|
@@ -1013,16 +1000,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1013
1000
|
}
|
|
1014
1001
|
|
|
1015
1002
|
const applyTooltipsToGeo = (geoName, row, returnType = 'string') => {
|
|
1016
|
-
|
|
1017
|
-
if(!row) return;
|
|
1003
|
+
if (!row) return
|
|
1018
1004
|
let toolTipText = ''
|
|
1019
1005
|
|
|
1020
1006
|
// Adds geo label, ie State: Georgia
|
|
1021
|
-
let stateOrCounty = state.general.geoType === 'us'
|
|
1022
|
-
? 'State: '
|
|
1023
|
-
: (state.general.geoType === 'us-county' || state.general.geoType === 'single-state')
|
|
1024
|
-
? 'County: '
|
|
1025
|
-
: ''
|
|
1007
|
+
let stateOrCounty = state.general.geoType === 'us' ? 'State: ' : state.general.geoType === 'us-county' || state.general.geoType === 'single-state' ? 'County: ' : ''
|
|
1026
1008
|
|
|
1027
1009
|
if (state.general.geoType === 'us-county' && state.general.type !== 'us-geocode') {
|
|
1028
1010
|
let stateFipsCode = row[state.columns.geo.name].substring(0, 2)
|
|
@@ -1036,7 +1018,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1036
1018
|
if (('data' === state.general.type || state.general.type === 'bubble' || state.general.type === 'us-geocode') && undefined !== row) {
|
|
1037
1019
|
toolTipText += `<dl>`
|
|
1038
1020
|
|
|
1039
|
-
Object.keys(state.columns).forEach(
|
|
1021
|
+
Object.keys(state.columns).forEach(columnKey => {
|
|
1040
1022
|
const column = state.columns[columnKey]
|
|
1041
1023
|
|
|
1042
1024
|
if (true === column.tooltip) {
|
|
@@ -1057,7 +1039,8 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1057
1039
|
value = displayDataAsText(row[column.name], columnKey)
|
|
1058
1040
|
}
|
|
1059
1041
|
|
|
1060
|
-
if (0 < value.length) {
|
|
1042
|
+
if (0 < value.length) {
|
|
1043
|
+
// Only spit out the tooltip if there's a value there
|
|
1061
1044
|
toolTipText += state.general.hidePrimaryColumnInTooltip ? `<div><dd>${value}</dd></div>` : `<div><dt>${label}</dt><dd>${value}</dd></div>`
|
|
1062
1045
|
}
|
|
1063
1046
|
}
|
|
@@ -1067,23 +1050,31 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1067
1050
|
|
|
1068
1051
|
// We convert the markup into JSX and add a navigation link if it's going into a modal.
|
|
1069
1052
|
if ('jsx' === returnType) {
|
|
1070
|
-
toolTipText = [
|
|
1053
|
+
toolTipText = [<div key='modal-content'>{parse(toolTipText)}</div>]
|
|
1071
1054
|
|
|
1072
1055
|
if (state.columns.hasOwnProperty('navigate') && row[state.columns.navigate.name]) {
|
|
1073
|
-
toolTipText.push(
|
|
1056
|
+
toolTipText.push(
|
|
1057
|
+
<span className='navigation-link' key='modal-navigation-link' onClick={() => navigationHandler(row[state.columns.navigate.name])}>
|
|
1058
|
+
{state.tooltips.linkLabel}
|
|
1059
|
+
<ExternalIcon className='inline-icon ml-1' />
|
|
1060
|
+
</span>
|
|
1061
|
+
)
|
|
1074
1062
|
}
|
|
1075
1063
|
}
|
|
1076
1064
|
|
|
1077
1065
|
return toolTipText
|
|
1078
1066
|
}
|
|
1079
1067
|
|
|
1080
|
-
const titleCase =
|
|
1081
|
-
return string
|
|
1068
|
+
const titleCase = string => {
|
|
1069
|
+
return string
|
|
1070
|
+
.split(' ')
|
|
1071
|
+
.map(word => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase())
|
|
1072
|
+
.join(' ')
|
|
1082
1073
|
}
|
|
1083
1074
|
|
|
1084
1075
|
// This resets all active legend toggles.
|
|
1085
1076
|
const resetLegendToggles = async () => {
|
|
1086
|
-
let newLegend = [
|
|
1077
|
+
let newLegend = [...runtimeLegend]
|
|
1087
1078
|
|
|
1088
1079
|
newLegend.forEach(legendItem => {
|
|
1089
1080
|
delete legendItem.disabled
|
|
@@ -1092,7 +1083,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1092
1083
|
setRuntimeLegend(newLegend)
|
|
1093
1084
|
}
|
|
1094
1085
|
|
|
1095
|
-
const formatLegendLocation =
|
|
1086
|
+
const formatLegendLocation = key => {
|
|
1096
1087
|
let value = key
|
|
1097
1088
|
let formattedName = ''
|
|
1098
1089
|
let stateName = stateFipsToTwoDigit[key.substring(0, 2)]
|
|
@@ -1109,7 +1100,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1109
1100
|
}
|
|
1110
1101
|
|
|
1111
1102
|
// Attempts to find the corresponding value
|
|
1112
|
-
const displayGeoName =
|
|
1103
|
+
const displayGeoName = key => {
|
|
1113
1104
|
let value = key
|
|
1114
1105
|
|
|
1115
1106
|
// Map to first item in values array which is the preferred label
|
|
@@ -1132,9 +1123,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1132
1123
|
const dict = {
|
|
1133
1124
|
'Washington D.C.': 'District of Columbia',
|
|
1134
1125
|
'WASHINGTON DC': 'District of Columbia',
|
|
1135
|
-
|
|
1126
|
+
DC: 'District of Columbia',
|
|
1136
1127
|
'WASHINGTON DC.': 'District of Columbia',
|
|
1137
|
-
|
|
1128
|
+
Congo: 'Republic of the Congo'
|
|
1138
1129
|
}
|
|
1139
1130
|
|
|
1140
1131
|
if (true === Object.keys(dict).includes(value)) {
|
|
@@ -1143,7 +1134,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1143
1134
|
return titleCase(value)
|
|
1144
1135
|
}
|
|
1145
1136
|
|
|
1146
|
-
const navigationHandler =
|
|
1137
|
+
const navigationHandler = urlString => {
|
|
1147
1138
|
// Call custom navigation method if passed
|
|
1148
1139
|
if (customNavigationHandler) {
|
|
1149
1140
|
customNavigationHandler(urlString)
|
|
@@ -1182,12 +1173,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1182
1173
|
}
|
|
1183
1174
|
}
|
|
1184
1175
|
|
|
1185
|
-
const validateFipsCodeLength =
|
|
1186
|
-
if (newState.general.geoType === 'us-county' || newState.general.geoType === 'single-state' || newState.general.geoType === 'us' && newState?.data) {
|
|
1187
|
-
|
|
1176
|
+
const validateFipsCodeLength = newState => {
|
|
1177
|
+
if (newState.general.geoType === 'us-county' || newState.general.geoType === 'single-state' || (newState.general.geoType === 'us' && newState?.data)) {
|
|
1188
1178
|
newState?.data.forEach(dataPiece => {
|
|
1189
1179
|
if (dataPiece[newState.columns.geo.name]) {
|
|
1190
|
-
|
|
1191
1180
|
if (!isNaN(parseInt(dataPiece[newState.columns.geo.name])) && dataPiece[newState.columns.geo.name].length === 4) {
|
|
1192
1181
|
dataPiece[newState.columns.geo.name] = 0 + dataPiece[newState.columns.geo.name]
|
|
1193
1182
|
}
|
|
@@ -1234,7 +1223,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1234
1223
|
}
|
|
1235
1224
|
}
|
|
1236
1225
|
|
|
1237
|
-
const loadConfig = async
|
|
1226
|
+
const loadConfig = async configObj => {
|
|
1238
1227
|
// Set loading flag
|
|
1239
1228
|
if (!loading) setLoading(true)
|
|
1240
1229
|
|
|
@@ -1244,16 +1233,15 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1244
1233
|
...configObj
|
|
1245
1234
|
}
|
|
1246
1235
|
|
|
1236
|
+
// If a dataUrl property exists, always pull from that.
|
|
1237
|
+
if (newState.dataUrl) {
|
|
1238
|
+
if (newState.dataUrl[0] === '/') {
|
|
1239
|
+
newState.dataUrl = 'http://' + hostname + newState.dataUrl
|
|
1240
|
+
}
|
|
1247
1241
|
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
newState.dataUrl = 'http://' + hostname + newState.dataUrl
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
// handle urls with spaces in the name.
|
|
1255
|
-
if (newState.dataUrl) newState.dataUrl = encodeURI(`${newState.dataUrl}?v=${cacheBustingString()}`)
|
|
1256
|
-
let newData = await fetchRemoteData(newState.dataUrl )
|
|
1242
|
+
// handle urls with spaces in the name.
|
|
1243
|
+
if (newState.dataUrl) newState.dataUrl = encodeURI(`${newState.dataUrl}?v=${cacheBustingString()}`)
|
|
1244
|
+
let newData = await fetchRemoteData(newState.dataUrl)
|
|
1257
1245
|
|
|
1258
1246
|
if (newData && newState.dataDescription) {
|
|
1259
1247
|
newData = transform.autoStandardize(newData)
|
|
@@ -1268,10 +1256,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1268
1256
|
// This code goes through and adds the defaults for every property declaring in the initial state at the top.
|
|
1269
1257
|
// This allows you to easily add new properties to the config without having to worry about accounting for backwards compatibility.
|
|
1270
1258
|
// Right now this does not work recursively -- only on first and second level properties. So state -> prop1 -> childprop1
|
|
1271
|
-
Object.keys(newState).forEach(
|
|
1259
|
+
Object.keys(newState).forEach(key => {
|
|
1272
1260
|
if ('object' === typeof newState[key] && false === Array.isArray(newState[key])) {
|
|
1273
1261
|
if (initialState[key]) {
|
|
1274
|
-
Object.keys(initialState[key]).forEach(
|
|
1262
|
+
Object.keys(initialState[key]).forEach(property => {
|
|
1275
1263
|
if (undefined === newState[key][property]) {
|
|
1276
1264
|
newState[key][property] = initialState[key][property]
|
|
1277
1265
|
}
|
|
@@ -1323,14 +1311,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1323
1311
|
publish('cove_loaded', { config: state })
|
|
1324
1312
|
setCoveLoadedHasRan(true)
|
|
1325
1313
|
}
|
|
1326
|
-
}, [
|
|
1314
|
+
}, [state, container])
|
|
1327
1315
|
|
|
1328
1316
|
useEffect(() => {
|
|
1329
1317
|
if (state.data) {
|
|
1330
1318
|
let newData = generateRuntimeData(state)
|
|
1331
1319
|
setRuntimeData(newData)
|
|
1332
1320
|
}
|
|
1333
|
-
}, [
|
|
1321
|
+
}, [state.general.statePicked])
|
|
1334
1322
|
|
|
1335
1323
|
// When geotype changes
|
|
1336
1324
|
useEffect(() => {
|
|
@@ -1338,7 +1326,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1338
1326
|
if (state.data && state.columns.geo.name) {
|
|
1339
1327
|
addUIDs(state, state.columns.geo.name)
|
|
1340
1328
|
}
|
|
1341
|
-
}, [
|
|
1329
|
+
}, [state])
|
|
1342
1330
|
|
|
1343
1331
|
useEffect(() => {
|
|
1344
1332
|
// UID
|
|
@@ -1394,8 +1382,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1394
1382
|
const legend = generateRuntimeLegend(state, newRuntimeData || runtimeData, hashLegend)
|
|
1395
1383
|
setRuntimeLegend(legend)
|
|
1396
1384
|
}
|
|
1397
|
-
|
|
1398
|
-
}, [ state ])
|
|
1385
|
+
}, [state])
|
|
1399
1386
|
|
|
1400
1387
|
useEffect(() => {
|
|
1401
1388
|
const hashLegend = hashObj({
|
|
@@ -1415,13 +1402,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1415
1402
|
const legend = generateRuntimeLegend(state, runtimeData)
|
|
1416
1403
|
setRuntimeLegend(legend)
|
|
1417
1404
|
}
|
|
1418
|
-
|
|
1419
|
-
}, [ runtimeData ])
|
|
1405
|
+
}, [runtimeData])
|
|
1420
1406
|
|
|
1421
1407
|
if (config) {
|
|
1422
1408
|
useEffect(() => {
|
|
1423
1409
|
loadConfig(config)
|
|
1424
|
-
}, [
|
|
1410
|
+
}, [config.data])
|
|
1425
1411
|
}
|
|
1426
1412
|
|
|
1427
1413
|
// Destructuring for more readable JSX
|
|
@@ -1429,24 +1415,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1429
1415
|
const { title = '', subtext = '' } = general
|
|
1430
1416
|
|
|
1431
1417
|
// Outer container classes
|
|
1432
|
-
let outerContainerClasses = [
|
|
1433
|
-
'cdc-open-viz-module',
|
|
1434
|
-
'cdc-map-outer-container',
|
|
1435
|
-
currentViewport
|
|
1436
|
-
]
|
|
1418
|
+
let outerContainerClasses = ['cdc-open-viz-module', 'cdc-map-outer-container', currentViewport]
|
|
1437
1419
|
|
|
1438
1420
|
if (className) {
|
|
1439
1421
|
outerContainerClasses.push(className)
|
|
1440
1422
|
}
|
|
1441
1423
|
|
|
1442
1424
|
// Map container classes
|
|
1443
|
-
let mapContainerClasses = [
|
|
1444
|
-
'map-container',
|
|
1445
|
-
state.legend.position,
|
|
1446
|
-
state.general.type,
|
|
1447
|
-
state.general.geoType,
|
|
1448
|
-
'outline-none'
|
|
1449
|
-
]
|
|
1425
|
+
let mapContainerClasses = ['map-container', state.legend.position, state.general.type, state.general.geoType, 'outline-none']
|
|
1450
1426
|
|
|
1451
1427
|
if (modal) {
|
|
1452
1428
|
mapContainerClasses.push('modal-background')
|
|
@@ -1482,7 +1458,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1482
1458
|
handleMapAriaLabels
|
|
1483
1459
|
}
|
|
1484
1460
|
|
|
1485
|
-
if (!mapProps.data || !state.data) return <Loading/>
|
|
1461
|
+
if (!mapProps.data || !state.data) return <Loading />
|
|
1486
1462
|
|
|
1487
1463
|
const hasDataTable = state.runtime.editorErrorMessage.length === 0 && true === dataTable.forceDisplay && general.type !== 'navigation' && false === loading
|
|
1488
1464
|
|
|
@@ -1512,178 +1488,118 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1512
1488
|
|
|
1513
1489
|
return (
|
|
1514
1490
|
<div className={outerContainerClasses.join(' ')} ref={outerContainerRef}>
|
|
1515
|
-
{isEditor && (
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
runtimeLegend={runtimeLegend}
|
|
1525
|
-
columnsInData={Object.keys(state.data[0])}
|
|
1526
|
-
/>
|
|
1527
|
-
)}
|
|
1528
|
-
{!runtimeData.init && (general.type === 'navigation' || runtimeLegend) && <section className={`cdc-map-inner-container ${currentViewport}`} aria-label={'Map: ' + title}>
|
|
1529
|
-
{!window.matchMedia('(any-hover: none)').matches && 'hover' === tooltips.appearanceType && (
|
|
1530
|
-
<ReactTooltip
|
|
1531
|
-
id="tooltip"
|
|
1532
|
-
place="right"
|
|
1533
|
-
type="light"
|
|
1534
|
-
html={true}
|
|
1535
|
-
className={tooltips.capitalizeLabels ? 'capitalize tooltip' : 'tooltip'}
|
|
1536
|
-
/>
|
|
1537
|
-
)}
|
|
1538
|
-
{state.general.title &&
|
|
1539
|
-
<header className={general.showTitle === true ? 'visible' : 'hidden'} {...(!general.showTitle || !state.general.title ? { 'aria-hidden': true } : { 'aria-hidden': false })}>
|
|
1540
|
-
<div role="heading" className={'map-title ' + general.headerColor} tabIndex="0" aria-level="2">
|
|
1541
|
-
<sup>{general.superTitle}</sup>
|
|
1542
|
-
<div>{parse(title)}</div>
|
|
1543
|
-
</div>
|
|
1544
|
-
</header>
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
<div>
|
|
1548
|
-
{general.introText && <section className="introText">{parse(general.introText)}</section>}
|
|
1549
|
-
</div>
|
|
1550
|
-
|
|
1551
|
-
<section
|
|
1552
|
-
role="button"
|
|
1553
|
-
tabIndex="0"
|
|
1554
|
-
className={mapContainerClasses.join(' ')}
|
|
1555
|
-
onClick={(e) => closeModal(e)}
|
|
1556
|
-
onKeyDown={(e) => {
|
|
1557
|
-
if (e.keyCode === 13) {
|
|
1558
|
-
closeModal(e)
|
|
1559
|
-
}
|
|
1560
|
-
}}
|
|
1561
|
-
>
|
|
1562
|
-
{general.showDownloadMediaButton === true && (
|
|
1563
|
-
<div className="map-downloads" data-html2canvas-ignore>
|
|
1564
|
-
<div className="map-downloads__ui btn-group">
|
|
1565
|
-
<button
|
|
1566
|
-
className="btn"
|
|
1567
|
-
title="Download Map as Image"
|
|
1568
|
-
onClick={() => generateMedia(outerContainerRef.current, 'image')}
|
|
1569
|
-
>
|
|
1570
|
-
<DownloadImg className="btn__icon" title="Download Map as Image"/>
|
|
1571
|
-
</button>
|
|
1572
|
-
<button
|
|
1573
|
-
className="btn"
|
|
1574
|
-
title="Download Map as PDF"
|
|
1575
|
-
onClick={() => generateMedia(outerContainerRef.current, 'pdf')}
|
|
1576
|
-
>
|
|
1577
|
-
<DownloadPdf className="btn__icon" title="Download Map as PDF"/>
|
|
1578
|
-
</button>
|
|
1491
|
+
{isEditor && <EditorPanel isDashboard={isDashboard} state={state} setState={setState} loadConfig={loadConfig} setParentConfig={setConfig} setRuntimeFilters={setRuntimeFilters} runtimeFilters={runtimeFilters} runtimeLegend={runtimeLegend} columnsInData={Object.keys(state.data[0])} />}
|
|
1492
|
+
{!runtimeData.init && (general.type === 'navigation' || runtimeLegend) && (
|
|
1493
|
+
<section className={`cdc-map-inner-container ${currentViewport}`} aria-label={'Map: ' + title}>
|
|
1494
|
+
{!window.matchMedia('(any-hover: none)').matches && 'hover' === tooltips.appearanceType && <ReactTooltip id='tooltip' place='right' type='light' html={true} className={tooltips.capitalizeLabels ? 'capitalize tooltip' : 'tooltip'} />}
|
|
1495
|
+
{state.general.title && (
|
|
1496
|
+
<header className={general.showTitle === true ? 'visible' : 'hidden'} {...(!general.showTitle || !state.general.title ? { 'aria-hidden': true } : { 'aria-hidden': false })}>
|
|
1497
|
+
<div role='heading' className={'map-title ' + general.headerColor} tabIndex='0' aria-level='2'>
|
|
1498
|
+
<sup>{general.superTitle}</sup>
|
|
1499
|
+
<div>{parse(title)}</div>
|
|
1579
1500
|
</div>
|
|
1580
|
-
</
|
|
1501
|
+
</header>
|
|
1581
1502
|
)}
|
|
1582
1503
|
|
|
1583
|
-
<
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
{
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
)}
|
|
1609
|
-
{'world' === general.geoType && (
|
|
1610
|
-
<WorldMap supportedCountries={supportedCountries} {...mapProps} />
|
|
1611
|
-
)}
|
|
1612
|
-
{('us-county' === general.geoType) && (
|
|
1613
|
-
<CountyMap
|
|
1614
|
-
supportedCountries={supportedCountries}
|
|
1615
|
-
{...mapProps}
|
|
1616
|
-
/>
|
|
1617
|
-
)}
|
|
1618
|
-
{'data' === general.type && logo && <img src={logo} alt="" className="map-logo"/>}
|
|
1619
|
-
</section>
|
|
1504
|
+
<div>{general.introText && <section className='introText'>{parse(general.introText)}</section>}</div>
|
|
1505
|
+
|
|
1506
|
+
<section
|
|
1507
|
+
role='button'
|
|
1508
|
+
tabIndex='0'
|
|
1509
|
+
className={mapContainerClasses.join(' ')}
|
|
1510
|
+
onClick={e => closeModal(e)}
|
|
1511
|
+
onKeyDown={e => {
|
|
1512
|
+
if (e.keyCode === 13) {
|
|
1513
|
+
closeModal(e)
|
|
1514
|
+
}
|
|
1515
|
+
}}
|
|
1516
|
+
>
|
|
1517
|
+
{general.showDownloadMediaButton === true && (
|
|
1518
|
+
<div className='map-downloads' data-html2canvas-ignore>
|
|
1519
|
+
<div className='map-downloads__ui btn-group'>
|
|
1520
|
+
<button className='btn' title='Download Map as Image' onClick={() => generateMedia(outerContainerRef.current, 'image')}>
|
|
1521
|
+
<DownloadImg className='btn__icon' title='Download Map as Image' />
|
|
1522
|
+
</button>
|
|
1523
|
+
<button className='btn' title='Download Map as PDF' onClick={() => generateMedia(outerContainerRef.current, 'pdf')}>
|
|
1524
|
+
<DownloadPdf className='btn__icon' title='Download Map as PDF' />
|
|
1525
|
+
</button>
|
|
1526
|
+
</div>
|
|
1527
|
+
</div>
|
|
1528
|
+
)}
|
|
1620
1529
|
|
|
1530
|
+
<a id='skip-geo-container' className='cdcdataviz-sr-only-focusable' href={tabId}>
|
|
1531
|
+
Skip Over Map Container
|
|
1532
|
+
</a>
|
|
1533
|
+
|
|
1534
|
+
<section className='geography-container outline-none' ref={mapSvg} tabIndex='0'>
|
|
1535
|
+
{currentViewport && (
|
|
1536
|
+
<section className='geography-container' ref={mapSvg}>
|
|
1537
|
+
{modal && <Modal type={general.type} viewport={currentViewport} applyTooltipsToGeo={applyTooltipsToGeo} applyLegendToRow={applyLegendToRow} capitalize={state.tooltips.capitalizeLabels} content={modal} />}
|
|
1538
|
+
{'single-state' === general.geoType && <SingleStateMap supportedTerritories={supportedTerritories} {...mapProps} />}
|
|
1539
|
+
{'us' === general.geoType && 'us-geocode' !== state.general.type && <UsaMap supportedTerritories={supportedTerritories} {...mapProps} />}
|
|
1540
|
+
{'us-region' === general.geoType && <UsaRegionMap supportedTerritories={supportedTerritories} {...mapProps} />}
|
|
1541
|
+
{'world' === general.geoType && <WorldMap supportedCountries={supportedCountries} {...mapProps} />}
|
|
1542
|
+
{'us-county' === general.geoType && <CountyMap supportedCountries={supportedCountries} {...mapProps} />}
|
|
1543
|
+
{'data' === general.type && logo && <img src={logo} alt='' className='map-logo' />}
|
|
1544
|
+
</section>
|
|
1545
|
+
)}
|
|
1546
|
+
</section>
|
|
1547
|
+
|
|
1548
|
+
{general.showSidebar && 'navigation' !== general.type && (
|
|
1549
|
+
<Sidebar
|
|
1550
|
+
viewport={currentViewport}
|
|
1551
|
+
legend={state.legend}
|
|
1552
|
+
runtimeLegend={runtimeLegend}
|
|
1553
|
+
setRuntimeLegend={setRuntimeLegend}
|
|
1554
|
+
runtimeFilters={runtimeFilters}
|
|
1555
|
+
columns={state.columns}
|
|
1556
|
+
sharing={state.sharing}
|
|
1557
|
+
prefix={state.columns.primary.prefix}
|
|
1558
|
+
suffix={state.columns.primary.suffix}
|
|
1559
|
+
setState={setState}
|
|
1560
|
+
resetLegendToggles={resetLegendToggles}
|
|
1561
|
+
changeFilterActive={changeFilterActive}
|
|
1562
|
+
setAccessibleStatus={setAccessibleStatus}
|
|
1563
|
+
displayDataAsText={displayDataAsText}
|
|
1564
|
+
/>
|
|
1621
1565
|
)}
|
|
1622
1566
|
</section>
|
|
1623
1567
|
|
|
1624
|
-
{
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1568
|
+
{'navigation' === general.type && <NavigationMenu mapTabbingID={tabId} displayGeoName={displayGeoName} data={runtimeData} options={general} columns={state.columns} navigationHandler={val => navigationHandler(val)} />}
|
|
1569
|
+
|
|
1570
|
+
{link && link}
|
|
1571
|
+
|
|
1572
|
+
{subtext.length > 0 && <p className='subtext'>{parse(subtext)}</p>}
|
|
1573
|
+
|
|
1574
|
+
{state.runtime.editorErrorMessage.length === 0 && true === dataTable.forceDisplay && general.type !== 'navigation' && false === loading && (
|
|
1575
|
+
<DataTable
|
|
1576
|
+
state={state}
|
|
1577
|
+
rawData={state.data}
|
|
1578
|
+
navigationHandler={navigationHandler}
|
|
1579
|
+
expandDataTable={general.expandDataTable}
|
|
1580
|
+
headerColor={general.headerColor}
|
|
1631
1581
|
columns={state.columns}
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
setState={setState}
|
|
1636
|
-
resetLegendToggles={resetLegendToggles}
|
|
1637
|
-
changeFilterActive={changeFilterActive}
|
|
1638
|
-
setAccessibleStatus={setAccessibleStatus}
|
|
1582
|
+
showDownloadButton={general.showDownloadButton}
|
|
1583
|
+
runtimeLegend={runtimeLegend}
|
|
1584
|
+
runtimeData={runtimeData}
|
|
1639
1585
|
displayDataAsText={displayDataAsText}
|
|
1586
|
+
displayGeoName={displayGeoName}
|
|
1587
|
+
applyLegendToRow={applyLegendToRow}
|
|
1588
|
+
tableTitle={dataTable.title}
|
|
1589
|
+
indexTitle={dataTable.indexLabel}
|
|
1590
|
+
mapTitle={general.title}
|
|
1591
|
+
viewport={currentViewport}
|
|
1592
|
+
formatLegendLocation={formatLegendLocation}
|
|
1593
|
+
setFilteredCountryCode={setFilteredCountryCode}
|
|
1594
|
+
tabbingId={tabId}
|
|
1640
1595
|
/>
|
|
1641
1596
|
)}
|
|
1597
|
+
|
|
1598
|
+
{general.footnotes && <section className='footnotes'>{parse(general.footnotes)}</section>}
|
|
1642
1599
|
</section>
|
|
1600
|
+
)}
|
|
1643
1601
|
|
|
1644
|
-
|
|
1645
|
-
<NavigationMenu
|
|
1646
|
-
mapTabbingID={tabId}
|
|
1647
|
-
displayGeoName={displayGeoName}
|
|
1648
|
-
data={runtimeData}
|
|
1649
|
-
options={general}
|
|
1650
|
-
columns={state.columns}
|
|
1651
|
-
navigationHandler={(val) => navigationHandler(val)}
|
|
1652
|
-
/>
|
|
1653
|
-
)}
|
|
1654
|
-
|
|
1655
|
-
{link && link}
|
|
1656
|
-
|
|
1657
|
-
{subtext.length > 0 && <p className="subtext">{parse(subtext)}</p>}
|
|
1658
|
-
|
|
1659
|
-
{state.runtime.editorErrorMessage.length === 0 && true === dataTable.forceDisplay && general.type !== 'navigation' && false === loading && (
|
|
1660
|
-
<DataTable
|
|
1661
|
-
state={state}
|
|
1662
|
-
rawData={state.data}
|
|
1663
|
-
navigationHandler={navigationHandler}
|
|
1664
|
-
expandDataTable={general.expandDataTable}
|
|
1665
|
-
headerColor={general.headerColor}
|
|
1666
|
-
columns={state.columns}
|
|
1667
|
-
showDownloadButton={general.showDownloadButton}
|
|
1668
|
-
runtimeLegend={runtimeLegend}
|
|
1669
|
-
runtimeData={runtimeData}
|
|
1670
|
-
displayDataAsText={displayDataAsText}
|
|
1671
|
-
displayGeoName={displayGeoName}
|
|
1672
|
-
applyLegendToRow={applyLegendToRow}
|
|
1673
|
-
tableTitle={dataTable.title}
|
|
1674
|
-
indexTitle={dataTable.indexLabel}
|
|
1675
|
-
mapTitle={general.title}
|
|
1676
|
-
viewport={currentViewport}
|
|
1677
|
-
formatLegendLocation={formatLegendLocation}
|
|
1678
|
-
setFilteredCountryCode={setFilteredCountryCode}
|
|
1679
|
-
tabbingId={tabId}
|
|
1680
|
-
/>
|
|
1681
|
-
)}
|
|
1682
|
-
|
|
1683
|
-
{general.footnotes && <section className="footnotes">{parse(general.footnotes)}</section>}
|
|
1684
|
-
</section>}
|
|
1685
|
-
|
|
1686
|
-
<div aria-live="assertive" className="cdcdataviz-sr-only">
|
|
1602
|
+
<div aria-live='assertive' className='cdcdataviz-sr-only'>
|
|
1687
1603
|
{accessibleStatus}
|
|
1688
1604
|
</div>
|
|
1689
1605
|
</div>
|