@cdc/map 4.23.2 → 4.23.4
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 +24661 -24191
- package/examples/custom-map-layers.json +764 -0
- package/examples/default-county.json +169 -155
- package/examples/default-geocode.json +744 -744
- package/examples/default-hex.json +3 -5
- package/examples/example-city-state-no-territories.json +703 -0
- package/examples/example-city-state.json +26 -7
- package/examples/example-city-stateBAD.json +744 -0
- package/examples/gallery/city-state.json +478 -478
- package/examples/testing-layer-2.json +1 -0
- package/examples/testing-layer.json +96 -0
- package/examples/world-geocode-data.json +18 -0
- package/examples/world-geocode.json +108 -0
- package/index.html +35 -29
- package/package.json +6 -3
- package/src/CdcMap.jsx +179 -111
- package/src/components/CityList.jsx +35 -35
- package/src/components/CountyMap.jsx +309 -446
- package/src/components/DataTable.jsx +7 -31
- package/src/components/EditorPanel.jsx +468 -217
- package/src/components/Sidebar.jsx +2 -0
- package/src/components/UsaMap.jsx +34 -23
- package/src/components/WorldMap.jsx +40 -8
- package/src/data/feature-test.json +73 -0
- package/src/data/initial-state.js +10 -3
- package/src/data/supported-geos.js +7 -7
- package/src/hooks/useMapLayers.jsx +243 -0
- package/src/index.jsx +4 -8
- package/src/scss/editor-panel.scss +97 -97
- package/src/scss/filters.scss +0 -2
- package/src/scss/main.scss +25 -26
- package/src/scss/map.scss +12 -0
- package/src/test/CdcMap.test.jsx +19 -0
- package/vite.config.js +3 -3
- package/src/components/Filters.jsx +0 -113
- package/src/hooks/useColorPalette.ts +0 -88
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback } from 'react'
|
|
1
|
+
import React, { useState, useEffect, useCallback, memo } from 'react'
|
|
2
2
|
|
|
3
3
|
// Third Party
|
|
4
4
|
import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
|
|
@@ -11,9 +11,6 @@ import { Tooltip as ReactTooltip } from 'react-tooltip'
|
|
|
11
11
|
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
12
12
|
import { supportedStatesFipsCodes } from '../data/supported-geos'
|
|
13
13
|
|
|
14
|
-
// Hooks
|
|
15
|
-
import { useColorPalette } from '../hooks/useColorPalette'
|
|
16
|
-
|
|
17
14
|
// Components - Core
|
|
18
15
|
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
19
16
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
@@ -30,6 +27,9 @@ import AlabamaGraphic from '@cdc/core/assets/icon-map-alabama.svg'
|
|
|
30
27
|
import worldDefaultConfig from '../../examples/default-world.json'
|
|
31
28
|
import usaDefaultConfig from '../../examples/default-usa.json'
|
|
32
29
|
import countyDefaultConfig from '../../examples/default-county.json'
|
|
30
|
+
import useMapLayers from '../hooks/useMapLayers'
|
|
31
|
+
|
|
32
|
+
import { useFilters } from '@cdc/core/components/Filters'
|
|
33
33
|
|
|
34
34
|
const TextField = ({ label, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', tooltip, ...attributes }) => {
|
|
35
35
|
const [value, setValue] = useState(stateValue)
|
|
@@ -40,7 +40,7 @@ const TextField = ({ label, section = null, subsection = null, fieldName, update
|
|
|
40
40
|
if ('string' === typeof debouncedValue && stateValue !== debouncedValue) {
|
|
41
41
|
updateField(section, subsection, fieldName, debouncedValue)
|
|
42
42
|
}
|
|
43
|
-
}, [debouncedValue])
|
|
43
|
+
}, [debouncedValue]) // eslint-disable-line
|
|
44
44
|
|
|
45
45
|
let name = subsection ? `${section}-${subsection}-${fieldName}` : `${section}-${subsection}-${fieldName}`
|
|
46
46
|
|
|
@@ -68,26 +68,36 @@ const TextField = ({ label, section = null, subsection = null, fieldName, update
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
const EditorPanel = props => {
|
|
71
|
-
const { state, columnsInData = [], loadConfig, setState, isDashboard, setParentConfig,
|
|
71
|
+
const { state, columnsInData = [], loadConfig, setState, isDashboard, setParentConfig, runtimeFilters, runtimeLegend, changeFilterActive, isDebug, setRuntimeFilters } = props
|
|
72
72
|
|
|
73
73
|
const { general, columns, legend, dataTable, tooltips } = state
|
|
74
74
|
|
|
75
75
|
const [requiredColumns, setRequiredColumns] = useState(null) // Simple state so we know if we need more information before parsing the map
|
|
76
76
|
|
|
77
|
-
const [configTextboxValue, setConfigTextbox] = useState({})
|
|
77
|
+
const [configTextboxValue, setConfigTextbox] = useState({}) // eslint-disable-line
|
|
78
78
|
|
|
79
79
|
const [loadedDefault, setLoadedDefault] = useState(false)
|
|
80
80
|
|
|
81
81
|
const [displayPanel, setDisplayPanel] = useState(true)
|
|
82
82
|
|
|
83
|
-
const [advancedToggle, setAdvancedToggle] = useState(false)
|
|
84
|
-
|
|
85
83
|
const [activeFilterValueForDescription, setActiveFilterValueForDescription] = useState([0, 0])
|
|
86
84
|
|
|
87
|
-
const {
|
|
85
|
+
const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({ config: state, setConfig: setState, filteredData: runtimeFilters, setFilteredData: setRuntimeFilters })
|
|
88
86
|
|
|
89
87
|
const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
|
|
90
88
|
|
|
89
|
+
const {
|
|
90
|
+
// prettier-ignore
|
|
91
|
+
MapLayerHandlers: {
|
|
92
|
+
handleAddLayer,
|
|
93
|
+
handleMapLayerName,
|
|
94
|
+
handleMapLayerUrl,
|
|
95
|
+
handleRemoveLayer,
|
|
96
|
+
handleMapLayerNamespace,
|
|
97
|
+
handleMapLayerTooltip
|
|
98
|
+
}
|
|
99
|
+
} = useMapLayers(state, setState, false, true)
|
|
100
|
+
|
|
91
101
|
const categoryMove = (idx1, idx2) => {
|
|
92
102
|
let categoryValuesOrder = [...state.legend.categoryValuesOrder]
|
|
93
103
|
|
|
@@ -104,23 +114,45 @@ const EditorPanel = props => {
|
|
|
104
114
|
})
|
|
105
115
|
}
|
|
106
116
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
let specialClasses = []
|
|
118
|
+
if (legend.specialClasses && legend.specialClasses.length && typeof legend.specialClasses[0] === 'string') {
|
|
119
|
+
legend.specialClasses.forEach(specialClass => {
|
|
120
|
+
specialClasses.push({
|
|
121
|
+
key: state.columns.primary && state.columns.primary.name ? state.columns.primary.name : columnsInData[0],
|
|
122
|
+
value: specialClass,
|
|
123
|
+
label: specialClass
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
// DEV-3303 - since the above was a repair of bad config - need to backpopulate into the state
|
|
118
127
|
setState({
|
|
119
128
|
...state,
|
|
120
|
-
|
|
129
|
+
legend: {
|
|
130
|
+
...state.legend,
|
|
131
|
+
specialClasses: specialClasses
|
|
132
|
+
}
|
|
121
133
|
})
|
|
134
|
+
} else {
|
|
135
|
+
specialClasses = legend.specialClasses || []
|
|
122
136
|
}
|
|
123
137
|
|
|
138
|
+
const CheckBox = memo(({ label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes }) => (
|
|
139
|
+
<label className='checkbox column-heading'>
|
|
140
|
+
<input
|
|
141
|
+
type='checkbox'
|
|
142
|
+
name={fieldName}
|
|
143
|
+
checked={value}
|
|
144
|
+
onChange={e => {
|
|
145
|
+
updateField(section, subsection, fieldName, !value)
|
|
146
|
+
}}
|
|
147
|
+
{...attributes}
|
|
148
|
+
/>
|
|
149
|
+
<span className='edit-label'>
|
|
150
|
+
{label}
|
|
151
|
+
{tooltip}
|
|
152
|
+
</span>
|
|
153
|
+
</label>
|
|
154
|
+
))
|
|
155
|
+
|
|
124
156
|
const DynamicDesc = ({ label, fieldName, value: stateValue, type = 'input', ...attributes }) => {
|
|
125
157
|
const [value, setValue] = useState(stateValue)
|
|
126
158
|
|
|
@@ -130,7 +162,7 @@ const EditorPanel = props => {
|
|
|
130
162
|
if ('string' === typeof debouncedValue && stateValue !== debouncedValue) {
|
|
131
163
|
handleEditorChanges('changeLegendDescription', [String(activeFilterValueForDescription), debouncedValue])
|
|
132
164
|
}
|
|
133
|
-
}, [debouncedValue])
|
|
165
|
+
}, [debouncedValue]) // eslint-disable-line
|
|
134
166
|
|
|
135
167
|
const onChange = e => setValue(e.target.value)
|
|
136
168
|
|
|
@@ -169,6 +201,17 @@ const EditorPanel = props => {
|
|
|
169
201
|
}
|
|
170
202
|
})
|
|
171
203
|
break
|
|
204
|
+
|
|
205
|
+
case 'toggleDataTableLink':
|
|
206
|
+
setState({
|
|
207
|
+
...state,
|
|
208
|
+
table: {
|
|
209
|
+
...state.table,
|
|
210
|
+
showDataTableLink: value
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
break
|
|
214
|
+
|
|
172
215
|
case 'toggleDataUrl':
|
|
173
216
|
setState({
|
|
174
217
|
...state,
|
|
@@ -418,6 +461,15 @@ const EditorPanel = props => {
|
|
|
418
461
|
}
|
|
419
462
|
})
|
|
420
463
|
break
|
|
464
|
+
case 'world-geocode':
|
|
465
|
+
setState({
|
|
466
|
+
...state,
|
|
467
|
+
general: {
|
|
468
|
+
...state.general,
|
|
469
|
+
type: value
|
|
470
|
+
}
|
|
471
|
+
})
|
|
472
|
+
break
|
|
421
473
|
case 'data':
|
|
422
474
|
setState({
|
|
423
475
|
...state,
|
|
@@ -457,7 +509,7 @@ const EditorPanel = props => {
|
|
|
457
509
|
})
|
|
458
510
|
break
|
|
459
511
|
default:
|
|
460
|
-
console.warn('Map type not set')
|
|
512
|
+
console.warn('COVE: Map type not set') // eslint-disable-line
|
|
461
513
|
break
|
|
462
514
|
}
|
|
463
515
|
break
|
|
@@ -484,7 +536,8 @@ const EditorPanel = props => {
|
|
|
484
536
|
...state,
|
|
485
537
|
general: {
|
|
486
538
|
...state.general,
|
|
487
|
-
geoType: 'us'
|
|
539
|
+
geoType: 'us',
|
|
540
|
+
type: state.type === 'us-geocode' ? 'data' : state.type
|
|
488
541
|
},
|
|
489
542
|
dataTable: {
|
|
490
543
|
...state.dataTable,
|
|
@@ -571,6 +624,15 @@ const EditorPanel = props => {
|
|
|
571
624
|
}
|
|
572
625
|
})
|
|
573
626
|
break
|
|
627
|
+
case 'legendShowSpecialClassesLast':
|
|
628
|
+
setState({
|
|
629
|
+
...state,
|
|
630
|
+
legend: {
|
|
631
|
+
...state.legend,
|
|
632
|
+
showSpecialClassesLast: !state.legend.showSpecialClassesLast
|
|
633
|
+
}
|
|
634
|
+
})
|
|
635
|
+
break
|
|
574
636
|
case 'dynamicDescription':
|
|
575
637
|
setState({
|
|
576
638
|
...state,
|
|
@@ -673,14 +735,28 @@ const EditorPanel = props => {
|
|
|
673
735
|
}
|
|
674
736
|
})
|
|
675
737
|
break
|
|
738
|
+
case 'territoriesAlwaysShow':
|
|
739
|
+
setState({
|
|
740
|
+
...state,
|
|
741
|
+
general: {
|
|
742
|
+
...state.general,
|
|
743
|
+
territoriesAlwaysShow: value
|
|
744
|
+
}
|
|
745
|
+
})
|
|
746
|
+
break
|
|
747
|
+
case 'filterBehavior':
|
|
748
|
+
setState({
|
|
749
|
+
...state,
|
|
750
|
+
filterBehavior: value
|
|
751
|
+
})
|
|
752
|
+
break
|
|
676
753
|
default:
|
|
677
|
-
console.warn(`Did not recognize editor property.`)
|
|
754
|
+
console.warn(`COVE: Did not recognize editor property.`) // eslint-disable-line
|
|
678
755
|
break
|
|
679
756
|
}
|
|
680
757
|
}
|
|
681
758
|
|
|
682
759
|
const columnsRequiredChecker = useCallback(() => {
|
|
683
|
-
console.info('Running columns required check.')
|
|
684
760
|
let columnList = []
|
|
685
761
|
|
|
686
762
|
// Geo is always required
|
|
@@ -698,11 +774,11 @@ const EditorPanel = props => {
|
|
|
698
774
|
columnList.push('Navigation')
|
|
699
775
|
}
|
|
700
776
|
|
|
701
|
-
if ('us-geocode' === state.general.type && '' === state.columns.latitude.name) {
|
|
777
|
+
if (('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && '' === state.columns.latitude.name) {
|
|
702
778
|
columnList.push('Latitude')
|
|
703
779
|
}
|
|
704
780
|
|
|
705
|
-
if ('us-geocode' === state.general.type && '' === state.columns.longitude.name) {
|
|
781
|
+
if (('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && '' === state.columns.longitude.name) {
|
|
706
782
|
columnList.push('Longitude')
|
|
707
783
|
}
|
|
708
784
|
|
|
@@ -713,10 +789,9 @@ const EditorPanel = props => {
|
|
|
713
789
|
|
|
714
790
|
const editColumn = async (columnName, editTarget, value) => {
|
|
715
791
|
let newSpecialClasses
|
|
716
|
-
|
|
717
792
|
switch (editTarget) {
|
|
718
793
|
case 'specialClassEdit':
|
|
719
|
-
newSpecialClasses = Array.from(
|
|
794
|
+
newSpecialClasses = Array.from(specialClasses)
|
|
720
795
|
|
|
721
796
|
newSpecialClasses[value.index][value.prop] = value.value
|
|
722
797
|
|
|
@@ -729,7 +804,7 @@ const EditorPanel = props => {
|
|
|
729
804
|
})
|
|
730
805
|
break
|
|
731
806
|
case 'specialClassDelete':
|
|
732
|
-
newSpecialClasses = Array.from(
|
|
807
|
+
newSpecialClasses = Array.from(specialClasses)
|
|
733
808
|
|
|
734
809
|
newSpecialClasses.splice(value, 1)
|
|
735
810
|
|
|
@@ -742,7 +817,7 @@ const EditorPanel = props => {
|
|
|
742
817
|
})
|
|
743
818
|
break
|
|
744
819
|
case 'specialClassAdd':
|
|
745
|
-
newSpecialClasses =
|
|
820
|
+
newSpecialClasses = specialClasses
|
|
746
821
|
|
|
747
822
|
newSpecialClasses.push(value)
|
|
748
823
|
|
|
@@ -799,6 +874,10 @@ const EditorPanel = props => {
|
|
|
799
874
|
newFilters.splice(idx, 1)
|
|
800
875
|
}
|
|
801
876
|
break
|
|
877
|
+
case 'filterStyle':
|
|
878
|
+
newFilters[idx] = { ...newFilters[idx] }
|
|
879
|
+
newFilters[idx].filterStyle = value
|
|
880
|
+
break
|
|
802
881
|
case 'columnName':
|
|
803
882
|
newFilters[idx] = { ...newFilters[idx] }
|
|
804
883
|
newFilters[idx].columnName = value
|
|
@@ -849,6 +928,33 @@ const EditorPanel = props => {
|
|
|
849
928
|
})
|
|
850
929
|
}
|
|
851
930
|
|
|
931
|
+
const MapFilters = () => {
|
|
932
|
+
return (
|
|
933
|
+
<>
|
|
934
|
+
<label>
|
|
935
|
+
Filter Behavior
|
|
936
|
+
<select
|
|
937
|
+
value={state.filterBehavior}
|
|
938
|
+
onChange={e => {
|
|
939
|
+
setState({
|
|
940
|
+
...state,
|
|
941
|
+
filterBehavior: e.target.value
|
|
942
|
+
})
|
|
943
|
+
}}
|
|
944
|
+
>
|
|
945
|
+
<option key='Apply Button' value='Apply Button'>
|
|
946
|
+
Apply Button
|
|
947
|
+
</option>
|
|
948
|
+
<option key='Filter Change' value='Filter Change'>
|
|
949
|
+
Filter Change
|
|
950
|
+
</option>
|
|
951
|
+
</select>
|
|
952
|
+
</label>
|
|
953
|
+
{filtersJSX}
|
|
954
|
+
</>
|
|
955
|
+
)
|
|
956
|
+
}
|
|
957
|
+
|
|
852
958
|
const removeAdditionalColumn = columnName => {
|
|
853
959
|
const newColumns = state.columns
|
|
854
960
|
|
|
@@ -915,11 +1021,51 @@ const EditorPanel = props => {
|
|
|
915
1021
|
return strippedState
|
|
916
1022
|
}
|
|
917
1023
|
|
|
1024
|
+
const isReversed = state.general.palette.isReversed
|
|
1025
|
+
function filterColorPalettes() {
|
|
1026
|
+
let sequential = []
|
|
1027
|
+
let nonSequential = []
|
|
1028
|
+
for (let paletteName in colorPalettes) {
|
|
1029
|
+
if (!isReversed) {
|
|
1030
|
+
if (paletteName.includes('qualitative') && !paletteName.endsWith('reverse')) {
|
|
1031
|
+
nonSequential.push(paletteName)
|
|
1032
|
+
}
|
|
1033
|
+
if (!paletteName.includes('qualitative') && !paletteName.endsWith('reverse')) {
|
|
1034
|
+
sequential.push(paletteName)
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
if (isReversed) {
|
|
1038
|
+
if (paletteName.includes('qualitative') && paletteName.endsWith('reverse')) {
|
|
1039
|
+
nonSequential.push(paletteName)
|
|
1040
|
+
}
|
|
1041
|
+
if (!paletteName.includes('qualitative') && paletteName.endsWith('reverse')) {
|
|
1042
|
+
sequential.push(paletteName)
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
return [sequential, nonSequential]
|
|
1048
|
+
}
|
|
1049
|
+
const [sequential, nonSequential] = filterColorPalettes()
|
|
1050
|
+
|
|
1051
|
+
useEffect(() => {
|
|
1052
|
+
let paletteName = ''
|
|
1053
|
+
if (isReversed && !state.color.endsWith('reverse')) {
|
|
1054
|
+
paletteName = state.color + 'reverse'
|
|
1055
|
+
}
|
|
1056
|
+
if (!isReversed && state.color.endsWith('reverse')) {
|
|
1057
|
+
paletteName = state.color.slice(0, -7)
|
|
1058
|
+
}
|
|
1059
|
+
if (paletteName) {
|
|
1060
|
+
handleEditorChanges('color', paletteName)
|
|
1061
|
+
}
|
|
1062
|
+
}, [isReversed])
|
|
1063
|
+
|
|
918
1064
|
useEffect(() => {
|
|
919
1065
|
setLoadedDefault(state.defaultData)
|
|
920
1066
|
|
|
921
1067
|
columnsRequiredChecker()
|
|
922
|
-
}, [state])
|
|
1068
|
+
}, [state]) // eslint-disable-line
|
|
923
1069
|
|
|
924
1070
|
useEffect(() => {
|
|
925
1071
|
//If a categorical map is used and the order is either not defined or incorrect, fix it
|
|
@@ -931,12 +1077,12 @@ const EditorPanel = props => {
|
|
|
931
1077
|
valid = false
|
|
932
1078
|
}
|
|
933
1079
|
})
|
|
934
|
-
let runtimeLegendKeys = runtimeLegend.map(item => item.value)
|
|
1080
|
+
let runtimeLegendKeys = runtimeLegend.map(item => item.value)
|
|
935
1081
|
state.legend.categoryValuesOrder.forEach(category => {
|
|
936
1082
|
if (runtimeLegendKeys.indexOf(category) === -1) {
|
|
937
|
-
valid = false
|
|
1083
|
+
valid = false
|
|
938
1084
|
}
|
|
939
|
-
})
|
|
1085
|
+
})
|
|
940
1086
|
} else {
|
|
941
1087
|
valid = false
|
|
942
1088
|
}
|
|
@@ -953,7 +1099,7 @@ const EditorPanel = props => {
|
|
|
953
1099
|
})
|
|
954
1100
|
}
|
|
955
1101
|
}
|
|
956
|
-
}, [runtimeLegend])
|
|
1102
|
+
}, [runtimeLegend]) // eslint-disable-line
|
|
957
1103
|
|
|
958
1104
|
// if no state choice by default show alabama
|
|
959
1105
|
useEffect(() => {
|
|
@@ -969,7 +1115,7 @@ const EditorPanel = props => {
|
|
|
969
1115
|
}
|
|
970
1116
|
})
|
|
971
1117
|
}
|
|
972
|
-
}, [])
|
|
1118
|
+
}, []) // eslint-disable-line
|
|
973
1119
|
|
|
974
1120
|
const columnsOptions = [
|
|
975
1121
|
<option value='' key={'Select Option'}>
|
|
@@ -978,7 +1124,7 @@ const EditorPanel = props => {
|
|
|
978
1124
|
]
|
|
979
1125
|
|
|
980
1126
|
columnsInData.map(colName => {
|
|
981
|
-
columnsOptions.push(
|
|
1127
|
+
return columnsOptions.push(
|
|
982
1128
|
<option value={colName} key={colName}>
|
|
983
1129
|
{colName}
|
|
984
1130
|
</option>
|
|
@@ -997,19 +1143,6 @@ const EditorPanel = props => {
|
|
|
997
1143
|
})
|
|
998
1144
|
})
|
|
999
1145
|
|
|
1000
|
-
let specialClasses = []
|
|
1001
|
-
if (legend.specialClasses && legend.specialClasses.length && typeof legend.specialClasses[0] === 'string') {
|
|
1002
|
-
legend.specialClasses.forEach(specialClass => {
|
|
1003
|
-
specialClasses.push({
|
|
1004
|
-
key: state.columns.primary && state.columns.primary.name ? state.columns.primary.name : columnsInData[0],
|
|
1005
|
-
value: specialClass,
|
|
1006
|
-
label: specialClass
|
|
1007
|
-
})
|
|
1008
|
-
})
|
|
1009
|
-
} else {
|
|
1010
|
-
specialClasses = legend.specialClasses || []
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
1146
|
const additionalColumns = Object.keys(state.columns).filter(value => {
|
|
1014
1147
|
const defaultCols = ['geo', 'navigate', 'primary', 'latitude', 'longitude']
|
|
1015
1148
|
|
|
@@ -1021,6 +1154,7 @@ const EditorPanel = props => {
|
|
|
1021
1154
|
|
|
1022
1155
|
const updateField = (section, subsection, fieldName, newValue) => {
|
|
1023
1156
|
const isArray = Array.isArray(state[section])
|
|
1157
|
+
|
|
1024
1158
|
let sectionValue = isArray ? [...state[section], newValue] : { ...state[section], [fieldName]: newValue }
|
|
1025
1159
|
|
|
1026
1160
|
if (null !== subsection) {
|
|
@@ -1054,98 +1188,106 @@ const EditorPanel = props => {
|
|
|
1054
1188
|
usedFilterColumns[filter.columnName] = true
|
|
1055
1189
|
}
|
|
1056
1190
|
|
|
1057
|
-
const filterOptions = [
|
|
1058
|
-
{
|
|
1059
|
-
label: 'Ascending Alphanumeric',
|
|
1060
|
-
value: 'asc'
|
|
1061
|
-
},
|
|
1062
|
-
{
|
|
1063
|
-
label: 'Descending Alphanumeric',
|
|
1064
|
-
value: 'desc'
|
|
1065
|
-
},
|
|
1066
|
-
{
|
|
1067
|
-
label: 'Custom',
|
|
1068
|
-
value: 'cust'
|
|
1069
|
-
}
|
|
1070
|
-
]
|
|
1071
|
-
|
|
1072
1191
|
return (
|
|
1073
|
-
|
|
1074
|
-
<
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
e
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
>
|
|
1081
|
-
Remove
|
|
1082
|
-
</button>
|
|
1083
|
-
<TextField value={state.filters[index].label} section='filters' subsection={index} fieldName='label' label='Label' updateField={updateField} />
|
|
1084
|
-
<label>
|
|
1085
|
-
<span className='edit-label column-heading'>
|
|
1086
|
-
Filter Column
|
|
1087
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1088
|
-
<Tooltip.Target>
|
|
1089
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1090
|
-
</Tooltip.Target>
|
|
1091
|
-
<Tooltip.Content>
|
|
1092
|
-
<p>Selecting a column will add a dropdown menu below the map legend and allow users to filter based on the values in this column.</p>
|
|
1093
|
-
</Tooltip.Content>
|
|
1094
|
-
</Tooltip>
|
|
1095
|
-
</span>
|
|
1096
|
-
<select
|
|
1097
|
-
value={filter.columnName}
|
|
1098
|
-
onChange={event => {
|
|
1099
|
-
changeFilter(index, 'columnName', event.target.value)
|
|
1192
|
+
<>
|
|
1193
|
+
<fieldset className='edit-block' key={`filter-${index}`}>
|
|
1194
|
+
<button
|
|
1195
|
+
className='remove-column'
|
|
1196
|
+
onClick={e => {
|
|
1197
|
+
e.preventDefault()
|
|
1198
|
+
changeFilter(index, 'remove')
|
|
1100
1199
|
}}
|
|
1101
1200
|
>
|
|
1102
|
-
|
|
1103
|
-
</
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1201
|
+
Remove
|
|
1202
|
+
</button>
|
|
1203
|
+
<TextField value={state.filters[index].label} section='filters' subsection={index} fieldName='label' label='Label' updateField={updateField} />
|
|
1204
|
+
<label>
|
|
1205
|
+
<span className='edit-label column-heading'>
|
|
1206
|
+
Filter Column
|
|
1207
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1208
|
+
<Tooltip.Target>
|
|
1209
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1210
|
+
</Tooltip.Target>
|
|
1211
|
+
<Tooltip.Content>
|
|
1212
|
+
<p>Selecting a column will add a dropdown menu below the map legend and allow users to filter based on the values in this column.</p>
|
|
1213
|
+
</Tooltip.Content>
|
|
1214
|
+
</Tooltip>
|
|
1215
|
+
</span>
|
|
1216
|
+
<select
|
|
1217
|
+
value={filter.columnName}
|
|
1218
|
+
onChange={event => {
|
|
1219
|
+
changeFilter(index, 'columnName', event.target.value)
|
|
1220
|
+
}}
|
|
1221
|
+
>
|
|
1222
|
+
{columnsOptions.filter(({ key }) => undefined === usedFilterColumns[key] || filter.columnName === key)}
|
|
1223
|
+
</select>
|
|
1224
|
+
</label>
|
|
1225
|
+
|
|
1226
|
+
{/* COMING SOON: 4.23.5: FILTER STYLES */}
|
|
1227
|
+
|
|
1228
|
+
{/* <label>
|
|
1229
|
+
<span className='edit-filterOrder column-heading'>Filter Style</span>
|
|
1230
|
+
<select
|
|
1231
|
+
value={filter.filterStyle}
|
|
1232
|
+
onChange={e => {
|
|
1233
|
+
changeFilter(index, 'filterStyle', e.target.value)
|
|
1234
|
+
}}
|
|
1235
|
+
>
|
|
1236
|
+
{filterStyleOptions.map((option, index) => {
|
|
1237
|
+
return (
|
|
1238
|
+
<option value={option} key={`filter-${option}--${index}`}>
|
|
1239
|
+
{option}
|
|
1240
|
+
</option>
|
|
1241
|
+
)
|
|
1242
|
+
})}
|
|
1243
|
+
</select>
|
|
1244
|
+
</label> */}
|
|
1245
|
+
|
|
1246
|
+
<label>
|
|
1247
|
+
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
1248
|
+
<select
|
|
1249
|
+
value={filter.order}
|
|
1250
|
+
onChange={e => {
|
|
1251
|
+
changeFilter(index, 'filterOrder', e.target.value)
|
|
1252
|
+
changeFilterActive(index, filter.values[0])
|
|
1253
|
+
}}
|
|
1254
|
+
>
|
|
1255
|
+
{filterOrderOptions.map((option, index) => {
|
|
1256
|
+
return (
|
|
1257
|
+
<option value={option.value} key={`filter-${index}`}>
|
|
1258
|
+
{option.label}
|
|
1259
|
+
</option>
|
|
1260
|
+
)
|
|
1261
|
+
})}
|
|
1262
|
+
</select>
|
|
1263
|
+
</label>
|
|
1264
|
+
|
|
1265
|
+
{filter.order === 'cust' && (
|
|
1266
|
+
<DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, state.filters[index])}>
|
|
1267
|
+
<Droppable droppableId='filter_order'>
|
|
1268
|
+
{provided => (
|
|
1269
|
+
<ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
1270
|
+
{state.filters[index]?.values.map((value, index) => {
|
|
1271
|
+
return (
|
|
1272
|
+
<Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
|
|
1273
|
+
{(provided, snapshot) => (
|
|
1274
|
+
<li>
|
|
1275
|
+
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
1276
|
+
{value}
|
|
1277
|
+
</div>
|
|
1278
|
+
</li>
|
|
1279
|
+
)}
|
|
1280
|
+
</Draggable>
|
|
1281
|
+
)
|
|
1282
|
+
})}
|
|
1283
|
+
{provided.placeholder}
|
|
1284
|
+
</ul>
|
|
1285
|
+
)}
|
|
1286
|
+
</Droppable>
|
|
1287
|
+
</DragDropContext>
|
|
1288
|
+
)}
|
|
1289
|
+
</fieldset>
|
|
1290
|
+
</>
|
|
1149
1291
|
)
|
|
1150
1292
|
})
|
|
1151
1293
|
|
|
@@ -1178,16 +1320,12 @@ const EditorPanel = props => {
|
|
|
1178
1320
|
})
|
|
1179
1321
|
}
|
|
1180
1322
|
|
|
1181
|
-
useEffect(() => {
|
|
1182
|
-
if (paletteName) handleEditorChanges('color', paletteName)
|
|
1183
|
-
}, [paletteName]) // dont add handleEditorChanges as a dependency even if it requires
|
|
1184
|
-
|
|
1185
1323
|
useEffect(() => {
|
|
1186
1324
|
const parsedData = convertStateToConfig()
|
|
1187
1325
|
const formattedData = JSON.stringify(parsedData, undefined, 2)
|
|
1188
1326
|
|
|
1189
1327
|
setConfigTextbox(formattedData)
|
|
1190
|
-
}, [state])
|
|
1328
|
+
}, [state]) // eslint-disable-line
|
|
1191
1329
|
|
|
1192
1330
|
useEffect(() => {
|
|
1193
1331
|
// Pass up to Editor if needed
|
|
@@ -1195,7 +1333,7 @@ const EditorPanel = props => {
|
|
|
1195
1333
|
const newConfig = convertStateToConfig()
|
|
1196
1334
|
setParentConfig(newConfig)
|
|
1197
1335
|
}
|
|
1198
|
-
}, [state])
|
|
1336
|
+
}, [state]) // eslint-disable-line
|
|
1199
1337
|
|
|
1200
1338
|
let numberOfItemsLimit = 8
|
|
1201
1339
|
|
|
@@ -1232,6 +1370,24 @@ const EditorPanel = props => {
|
|
|
1232
1370
|
)
|
|
1233
1371
|
}
|
|
1234
1372
|
|
|
1373
|
+
const isLoadedFromUrl = state?.dataKey?.includes('http://') || state?.dataKey?.includes('https://')
|
|
1374
|
+
|
|
1375
|
+
// if isDebug = true, then try to set the Geography Col and Data col to reduce clicking
|
|
1376
|
+
const setGeoColumn = () => {
|
|
1377
|
+
// only for debug mode
|
|
1378
|
+
let geoColFound = columnsInData.includes(state.columns.geo.name)
|
|
1379
|
+
if (undefined !== isDebug && isDebug && !geoColFound) {
|
|
1380
|
+
// then try to set the x axis to appropriate value so we dont have to manually do it
|
|
1381
|
+
let mapcols = columnsInData[0]
|
|
1382
|
+
if (mapcols !== '') editColumn('geo', 'name', mapcols)
|
|
1383
|
+
|
|
1384
|
+
if (!state.columns.hasOwnProperty('primary') || undefined === state.columns.primary.name || '' === state.columns.primary.name || !state.columns.primary.name) {
|
|
1385
|
+
editColumn('primary', 'name', columnsInData[1]) // blindly picks first value col
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
if (isDebug) setGeoColumn()
|
|
1390
|
+
|
|
1235
1391
|
return (
|
|
1236
1392
|
<ErrorBoundary component='EditorPanel'>
|
|
1237
1393
|
{state?.runtime?.editorErrorMessage.length > 0 && <Error />}
|
|
@@ -1349,7 +1505,8 @@ const EditorPanel = props => {
|
|
|
1349
1505
|
}}
|
|
1350
1506
|
>
|
|
1351
1507
|
<option value='data'>Data</option>
|
|
1352
|
-
<option value='us-geocode'>
|
|
1508
|
+
{state.general.geoType === 'us-county' && <option value='us-geocode'>Geocode</option>}
|
|
1509
|
+
{state.general.geoType === 'world' && <option value='world-geocode'>Geocode</option>}
|
|
1353
1510
|
<option value='navigation'>Navigation</option>
|
|
1354
1511
|
{(state.general.geoType === 'world' || state.general.geoType === 'us') && <option value='bubble'>Bubble</option>}
|
|
1355
1512
|
</select>
|
|
@@ -1403,9 +1560,11 @@ const EditorPanel = props => {
|
|
|
1403
1560
|
<AccordionItemPanel>
|
|
1404
1561
|
<TextField
|
|
1405
1562
|
value={general.title}
|
|
1563
|
+
data-testid='title-input'
|
|
1406
1564
|
updateField={updateField}
|
|
1407
1565
|
section='general'
|
|
1408
1566
|
fieldName='title'
|
|
1567
|
+
id='title'
|
|
1409
1568
|
label='Title'
|
|
1410
1569
|
placeholder='Map Title'
|
|
1411
1570
|
tooltip={
|
|
@@ -1414,11 +1573,21 @@ const EditorPanel = props => {
|
|
|
1414
1573
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1415
1574
|
</Tooltip.Target>
|
|
1416
1575
|
<Tooltip.Content>
|
|
1417
|
-
<p>
|
|
1576
|
+
<p>Title is required to set the name of the download file but can be hidden using the option below.</p>
|
|
1418
1577
|
</Tooltip.Content>
|
|
1419
1578
|
</Tooltip>
|
|
1420
1579
|
}
|
|
1421
1580
|
/>
|
|
1581
|
+
<label className='checkbox'>
|
|
1582
|
+
<input
|
|
1583
|
+
type='checkbox'
|
|
1584
|
+
checked={state.general.showTitle || false}
|
|
1585
|
+
onChange={event => {
|
|
1586
|
+
handleEditorChanges('showTitle', event.target.checked)
|
|
1587
|
+
}}
|
|
1588
|
+
/>
|
|
1589
|
+
<span className='edit-label'>Show Title</span>
|
|
1590
|
+
</label>
|
|
1422
1591
|
<TextField
|
|
1423
1592
|
value={general.superTitle || ''}
|
|
1424
1593
|
updateField={updateField}
|
|
@@ -1491,6 +1660,18 @@ const EditorPanel = props => {
|
|
|
1491
1660
|
}
|
|
1492
1661
|
/>
|
|
1493
1662
|
{'us' === state.general.geoType && <TextField value={general.territoriesLabel} updateField={updateField} section='general' fieldName='territoriesLabel' label='Territories Label' placeholder='Territories' />}
|
|
1663
|
+
{'us' === state.general.geoType && (
|
|
1664
|
+
<label className='checkbox'>
|
|
1665
|
+
<input
|
|
1666
|
+
type='checkbox'
|
|
1667
|
+
checked={general.territoriesAlwaysShow || false}
|
|
1668
|
+
onChange={event => {
|
|
1669
|
+
handleEditorChanges('territoriesAlwaysShow', event.target.checked)
|
|
1670
|
+
}}
|
|
1671
|
+
/>
|
|
1672
|
+
<span className='edit-label'>Show All Territories</span>
|
|
1673
|
+
</label>
|
|
1674
|
+
)}
|
|
1494
1675
|
{/* <label className="checkbox mt-4">
|
|
1495
1676
|
<input type="checkbox" checked={ state.general.showDownloadMediaButton } onChange={(event) => { handleEditorChanges("toggleDownloadMediaButton", event.target.checked) }} />
|
|
1496
1677
|
<span className="edit-label">Enable Media Download</span>
|
|
@@ -1677,8 +1858,7 @@ const EditorPanel = props => {
|
|
|
1677
1858
|
</label>
|
|
1678
1859
|
</fieldset>
|
|
1679
1860
|
)}
|
|
1680
|
-
|
|
1681
|
-
{'us-geocode' === state.general.type && (
|
|
1861
|
+
{('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && (
|
|
1682
1862
|
<>
|
|
1683
1863
|
<label>Latitude Column</label>
|
|
1684
1864
|
<select
|
|
@@ -1905,35 +2085,42 @@ const EditorPanel = props => {
|
|
|
1905
2085
|
</Tooltip>
|
|
1906
2086
|
</span>
|
|
1907
2087
|
</label>
|
|
1908
|
-
{state.legend.additionalCategories &&
|
|
1909
|
-
|
|
1910
|
-
<
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
event
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
<
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
2088
|
+
{state.legend.additionalCategories &&
|
|
2089
|
+
state.legend.additionalCategories.map((val, i) => (
|
|
2090
|
+
<fieldset className='edit-block' key={val}>
|
|
2091
|
+
<button
|
|
2092
|
+
className='remove-column'
|
|
2093
|
+
onClick={event => {
|
|
2094
|
+
event.preventDefault()
|
|
2095
|
+
const updatedAdditionaCategories = [...state.legend.additionalCategories]
|
|
2096
|
+
updatedAdditionaCategories.splice(i, 1)
|
|
2097
|
+
updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
|
|
2098
|
+
}}
|
|
2099
|
+
>
|
|
2100
|
+
Remove
|
|
2101
|
+
</button>
|
|
2102
|
+
<label>
|
|
2103
|
+
<span className='edit-label column-heading'>Category</span>
|
|
2104
|
+
<TextField
|
|
2105
|
+
value={val}
|
|
2106
|
+
section='legend'
|
|
2107
|
+
subsection={null}
|
|
2108
|
+
fieldName='additionalCategories'
|
|
2109
|
+
updateField={(section, subsection, fieldName, value) => {
|
|
2110
|
+
const updatedAdditionaCategories = [...state.legend.additionalCategories]
|
|
2111
|
+
updatedAdditionaCategories[i] = value
|
|
2112
|
+
updateField(section, subsection, fieldName, updatedAdditionaCategories)
|
|
2113
|
+
}}
|
|
2114
|
+
/>
|
|
2115
|
+
</label>
|
|
2116
|
+
</fieldset>
|
|
2117
|
+
))}
|
|
1931
2118
|
<button
|
|
1932
2119
|
className={'btn full-width'}
|
|
1933
2120
|
onClick={event => {
|
|
1934
2121
|
event.preventDefault()
|
|
1935
|
-
const updatedAdditionaCategories = [...(state.legend.additionalCategories || [])]
|
|
1936
|
-
updatedAdditionaCategories.push('')
|
|
2122
|
+
const updatedAdditionaCategories = [...(state.legend.additionalCategories || [])]
|
|
2123
|
+
updatedAdditionaCategories.push('')
|
|
1937
2124
|
updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
|
|
1938
2125
|
}}
|
|
1939
2126
|
>
|
|
@@ -2016,6 +2203,18 @@ const EditorPanel = props => {
|
|
|
2016
2203
|
<span className='edit-label'>Single Row Legend</span>
|
|
2017
2204
|
</label>
|
|
2018
2205
|
)}
|
|
2206
|
+
{/* always show */}
|
|
2207
|
+
{/*
|
|
2208
|
+
<label className='checkbox'>
|
|
2209
|
+
<input
|
|
2210
|
+
type='checkbox'
|
|
2211
|
+
checked={legend.showSpecialClassesLast}
|
|
2212
|
+
onChange={event => {
|
|
2213
|
+
handleEditorChanges('legendShowSpecialClassesLast', event.target.checked)
|
|
2214
|
+
}}
|
|
2215
|
+
/>
|
|
2216
|
+
<span className='edit-label'>Show Special Classes Last</span>
|
|
2217
|
+
</label> */}
|
|
2019
2218
|
{'category' !== legend.type && (
|
|
2020
2219
|
<label className='checkbox'>
|
|
2021
2220
|
<input type='checkbox' checked={legend.separateZero || false} onChange={event => handleEditorChanges('separateZero', event.target.checked)} />
|
|
@@ -2033,7 +2232,6 @@ const EditorPanel = props => {
|
|
|
2033
2232
|
</label>
|
|
2034
2233
|
)}
|
|
2035
2234
|
{/* Temp Checkbox */}
|
|
2036
|
-
|
|
2037
2235
|
{state.legend.type === 'equalnumber' && (
|
|
2038
2236
|
<label className='checkbox mt-4'>
|
|
2039
2237
|
<input
|
|
@@ -2197,7 +2395,7 @@ const EditorPanel = props => {
|
|
|
2197
2395
|
<AccordionItemButton>Filters</AccordionItemButton>
|
|
2198
2396
|
</AccordionItemHeading>
|
|
2199
2397
|
<AccordionItemPanel>
|
|
2200
|
-
{filtersJSX.length > 0 ?
|
|
2398
|
+
{filtersJSX.length > 0 ? <MapFilters /> : <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
|
|
2201
2399
|
<button
|
|
2202
2400
|
className={'btn full-width'}
|
|
2203
2401
|
onClick={event => {
|
|
@@ -2223,6 +2421,7 @@ const EditorPanel = props => {
|
|
|
2223
2421
|
updateField={updateField}
|
|
2224
2422
|
section='dataTable'
|
|
2225
2423
|
fieldName='title'
|
|
2424
|
+
id='dataTableTitle'
|
|
2226
2425
|
label='Data Table Title'
|
|
2227
2426
|
placeholder='Data Table'
|
|
2228
2427
|
tooltip={
|
|
@@ -2236,6 +2435,26 @@ const EditorPanel = props => {
|
|
|
2236
2435
|
</Tooltip>
|
|
2237
2436
|
}
|
|
2238
2437
|
/>
|
|
2438
|
+
<label className='checkbox'>
|
|
2439
|
+
<input
|
|
2440
|
+
type='checkbox'
|
|
2441
|
+
checked={state.dataTable.forceDisplay !== undefined ? state.dataTable.forceDisplay : !isDashboard}
|
|
2442
|
+
onChange={event => {
|
|
2443
|
+
handleEditorChanges('showDataTable', event.target.checked)
|
|
2444
|
+
}}
|
|
2445
|
+
/>
|
|
2446
|
+
<span className='edit-label column-heading'>
|
|
2447
|
+
Show Data Table
|
|
2448
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2449
|
+
<Tooltip.Target>
|
|
2450
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2451
|
+
</Tooltip.Target>
|
|
2452
|
+
<Tooltip.Content>
|
|
2453
|
+
<p>Data tables are required for 508 compliance. When choosing to hide this data table, replace with your own version.</p>
|
|
2454
|
+
</Tooltip.Content>
|
|
2455
|
+
</Tooltip>
|
|
2456
|
+
</span>
|
|
2457
|
+
</label>
|
|
2239
2458
|
<TextField
|
|
2240
2459
|
value={dataTable.indexLabel || ''}
|
|
2241
2460
|
updateField={updateField}
|
|
@@ -2273,26 +2492,6 @@ const EditorPanel = props => {
|
|
|
2273
2492
|
}
|
|
2274
2493
|
type='textarea'
|
|
2275
2494
|
/>
|
|
2276
|
-
<label className='checkbox'>
|
|
2277
|
-
<input
|
|
2278
|
-
type='checkbox'
|
|
2279
|
-
checked={state.dataTable.forceDisplay !== undefined ? state.dataTable.forceDisplay : !isDashboard}
|
|
2280
|
-
onChange={event => {
|
|
2281
|
-
handleEditorChanges('showDataTable', event.target.checked)
|
|
2282
|
-
}}
|
|
2283
|
-
/>
|
|
2284
|
-
<span className='edit-label'>
|
|
2285
|
-
Show Table
|
|
2286
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
2287
|
-
<Tooltip.Target>
|
|
2288
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2289
|
-
</Tooltip.Target>
|
|
2290
|
-
<Tooltip.Content>
|
|
2291
|
-
<p>Data tables are required for 508 compliance. When choosing to hide this data table, replace with your own version.</p>
|
|
2292
|
-
</Tooltip.Content>
|
|
2293
|
-
</Tooltip>
|
|
2294
|
-
</span>
|
|
2295
|
-
</label>
|
|
2296
2495
|
<label className='checkbox'>
|
|
2297
2496
|
<input
|
|
2298
2497
|
type='checkbox'
|
|
@@ -2314,16 +2513,30 @@ const EditorPanel = props => {
|
|
|
2314
2513
|
/>
|
|
2315
2514
|
<span className='edit-label'>Map loads with data table expanded</span>
|
|
2316
2515
|
</label>
|
|
2317
|
-
|
|
2318
|
-
<
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2516
|
+
{isDashboard && (
|
|
2517
|
+
<label className='checkbox'>
|
|
2518
|
+
<input
|
|
2519
|
+
type='checkbox'
|
|
2520
|
+
checked={state.table.showDataTableLink}
|
|
2521
|
+
onChange={event => {
|
|
2522
|
+
handleEditorChanges('toggleDataTableLink', event.target.checked)
|
|
2523
|
+
}}
|
|
2524
|
+
/>
|
|
2525
|
+
<span className='edit-label'>Show Data Table Name & Link</span>
|
|
2526
|
+
</label>
|
|
2527
|
+
)}
|
|
2528
|
+
{isLoadedFromUrl && (
|
|
2529
|
+
<label className='checkbox'>
|
|
2530
|
+
<input
|
|
2531
|
+
type='checkbox'
|
|
2532
|
+
checked={state.table.showDownloadUrl}
|
|
2533
|
+
onChange={event => {
|
|
2534
|
+
handleEditorChanges('toggleDataUrl', event.target.checked)
|
|
2535
|
+
}}
|
|
2536
|
+
/>
|
|
2537
|
+
<span className='edit-label'>Show URL to Automatically Updated Data</span>
|
|
2538
|
+
</label>
|
|
2539
|
+
)}
|
|
2327
2540
|
<label className='checkbox'>
|
|
2328
2541
|
<input
|
|
2329
2542
|
type='checkbox'
|
|
@@ -2332,7 +2545,7 @@ const EditorPanel = props => {
|
|
|
2332
2545
|
handleEditorChanges('toggleDownloadButton', event.target.checked)
|
|
2333
2546
|
}}
|
|
2334
2547
|
/>
|
|
2335
|
-
<span className='edit-label'>
|
|
2548
|
+
<span className='edit-label'>Show Download CSV Link</span>
|
|
2336
2549
|
</label>
|
|
2337
2550
|
{/* <label className='checkbox'>
|
|
2338
2551
|
<input
|
|
@@ -2434,8 +2647,6 @@ const EditorPanel = props => {
|
|
|
2434
2647
|
<span className='edit-label'>Show Title</span>
|
|
2435
2648
|
</label>
|
|
2436
2649
|
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
2650
|
{'navigation' === state.general.type && (
|
|
2440
2651
|
<label className='checkbox'>
|
|
2441
2652
|
<input
|
|
@@ -2464,10 +2675,10 @@ const EditorPanel = props => {
|
|
|
2464
2675
|
<span className='edit-label'>Map Color Palette</span>
|
|
2465
2676
|
</label>
|
|
2466
2677
|
{/* <InputCheckbox section="general" subsection="palette" fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} /> */}
|
|
2467
|
-
<InputToggle type='3d' section='general' subsection='palette' fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={
|
|
2678
|
+
<InputToggle type='3d' section='general' subsection='palette' fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={state.general.palette.isReversed} />
|
|
2468
2679
|
<span>Sequential</span>
|
|
2469
2680
|
<ul className='color-palette'>
|
|
2470
|
-
{
|
|
2681
|
+
{sequential.map(palette => {
|
|
2471
2682
|
const colorOne = {
|
|
2472
2683
|
backgroundColor: colorPalettes[palette][2]
|
|
2473
2684
|
}
|
|
@@ -2498,7 +2709,7 @@ const EditorPanel = props => {
|
|
|
2498
2709
|
</ul>
|
|
2499
2710
|
<span>Non-Sequential</span>
|
|
2500
2711
|
<ul className='color-palette'>
|
|
2501
|
-
{
|
|
2712
|
+
{nonSequential.map(palette => {
|
|
2502
2713
|
const colorOne = {
|
|
2503
2714
|
backgroundColor: colorPalettes[palette][2]
|
|
2504
2715
|
}
|
|
@@ -2531,7 +2742,7 @@ const EditorPanel = props => {
|
|
|
2531
2742
|
)
|
|
2532
2743
|
})}
|
|
2533
2744
|
</ul>
|
|
2534
|
-
{'us-geocode' === state.general.type && (
|
|
2745
|
+
{('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && (
|
|
2535
2746
|
<label>
|
|
2536
2747
|
Geocode Settings
|
|
2537
2748
|
<TextField type='number' value={state.visual.geoCodeCircleSize} section='visual' max='10' fieldName='geoCodeCircleSize' label='Geocode Circle Size' updateField={updateField} />
|
|
@@ -2581,7 +2792,8 @@ const EditorPanel = props => {
|
|
|
2581
2792
|
</label>
|
|
2582
2793
|
)}
|
|
2583
2794
|
{state.general.geoType === 'us' ||
|
|
2584
|
-
|
|
2795
|
+
state.general.geoType === 'us-county' ||
|
|
2796
|
+
(state.general.geoType === 'world' && (
|
|
2585
2797
|
<label>
|
|
2586
2798
|
<span className='edit-label'>City Style</span>
|
|
2587
2799
|
<select
|
|
@@ -2597,6 +2809,45 @@ const EditorPanel = props => {
|
|
|
2597
2809
|
))}
|
|
2598
2810
|
</AccordionItemPanel>
|
|
2599
2811
|
</AccordionItem>
|
|
2812
|
+
{/* HIDING FOR 4.23.4 */}
|
|
2813
|
+
{/* <AccordionItem>
|
|
2814
|
+
<AccordionItemHeading>
|
|
2815
|
+
<AccordionItemButton>Custom Map Layers</AccordionItemButton>
|
|
2816
|
+
</AccordionItemHeading>
|
|
2817
|
+
<AccordionItemPanel>
|
|
2818
|
+
{state.map.layers.length === 0 && <p>There are currently no layers.</p>}
|
|
2819
|
+
|
|
2820
|
+
{state.map.layers.map((layer, index) => {
|
|
2821
|
+
return (
|
|
2822
|
+
<>
|
|
2823
|
+
<Accordion allowZeroExpanded>
|
|
2824
|
+
<AccordionItem className='series-item map-layers-list'>
|
|
2825
|
+
<AccordionItemHeading className='series-item__title map-layers-list--title'>
|
|
2826
|
+
<AccordionItemButton>{`Layer ${index + 1}: ${layer.name}`}</AccordionItemButton>
|
|
2827
|
+
</AccordionItemHeading>
|
|
2828
|
+
<AccordionItemPanel>
|
|
2829
|
+
<div className='map-layers-panel'>
|
|
2830
|
+
<label htmlFor='layerName'>Layer Name:</label>
|
|
2831
|
+
<input type='text' name='layerName' value={layer.name} onChange={e => handleMapLayerName(e, index)} />
|
|
2832
|
+
<label htmlFor='layerFilename'>File:</label>
|
|
2833
|
+
<input type='text' name='layerFilename' value={layer.url} onChange={e => handleMapLayerUrl(e, index)} />
|
|
2834
|
+
<label htmlFor='layerNamespace'>TOPOJSON Namespace:</label>
|
|
2835
|
+
<input type='text' name='layerNamespace' value={layer.namespace} onChange={e => handleMapLayerNamespace(e, index)} />
|
|
2836
|
+
<label htmlFor='layerTooltip'>Tooltip:</label>
|
|
2837
|
+
<textarea name='layerTooltip' value={layer.tooltip} onChange={e => handleMapLayerTooltip(e, index)}></textarea>
|
|
2838
|
+
<button onClick={e => handleRemoveLayer(e, index)}>Remove Layer</button>
|
|
2839
|
+
</div>
|
|
2840
|
+
</AccordionItemPanel>
|
|
2841
|
+
</AccordionItem>
|
|
2842
|
+
</Accordion>
|
|
2843
|
+
</>
|
|
2844
|
+
)
|
|
2845
|
+
})}
|
|
2846
|
+
<button className={'btn full-width'} onClick={handleAddLayer}>
|
|
2847
|
+
Add Map Layer
|
|
2848
|
+
</button>
|
|
2849
|
+
</AccordionItemPanel>
|
|
2850
|
+
</AccordionItem> */}
|
|
2600
2851
|
</Accordion>
|
|
2601
2852
|
</form>
|
|
2602
2853
|
<AdvancedEditor loadConfig={loadConfig} state={state} convertStateToConfig={convertStateToConfig} />
|