@cdc/map 4.23.3 → 4.23.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdcmap.js +25301 -29100
- package/examples/custom-map-layers.json +764 -0
- package/examples/default-county.json +169 -155
- package/examples/example-city-state.json +34 -12
- package/examples/testing-layer-2.json +1 -0
- package/examples/testing-layer.json +96 -0
- package/index.html +6 -5
- package/package.json +3 -3
- package/src/CdcMap.jsx +201 -105
- package/src/components/CountyMap.jsx +31 -6
- package/src/components/DataTable.jsx +185 -218
- package/src/components/EditorPanel.jsx +293 -162
- package/src/components/UsaMap.jsx +17 -11
- package/src/data/initial-state.js +16 -8
- 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/components/Filters.jsx +0 -113
|
@@ -27,6 +27,9 @@ import AlabamaGraphic from '@cdc/core/assets/icon-map-alabama.svg'
|
|
|
27
27
|
import worldDefaultConfig from '../../examples/default-world.json'
|
|
28
28
|
import usaDefaultConfig from '../../examples/default-usa.json'
|
|
29
29
|
import countyDefaultConfig from '../../examples/default-county.json'
|
|
30
|
+
import useMapLayers from '../hooks/useMapLayers'
|
|
31
|
+
|
|
32
|
+
import { useFilters } from '@cdc/core/components/Filters'
|
|
30
33
|
|
|
31
34
|
const TextField = ({ label, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', tooltip, ...attributes }) => {
|
|
32
35
|
const [value, setValue] = useState(stateValue)
|
|
@@ -65,9 +68,9 @@ const TextField = ({ label, section = null, subsection = null, fieldName, update
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
const EditorPanel = props => {
|
|
68
|
-
const { state, columnsInData = [], loadConfig, setState, isDashboard, setParentConfig,
|
|
71
|
+
const { state, columnsInData = [], loadConfig, setState, isDashboard, setParentConfig, runtimeFilters, runtimeLegend, changeFilterActive, isDebug, setRuntimeFilters } = props
|
|
69
72
|
|
|
70
|
-
const { general, columns, legend,
|
|
73
|
+
const { general, columns, legend, table, tooltips } = state
|
|
71
74
|
|
|
72
75
|
const [requiredColumns, setRequiredColumns] = useState(null) // Simple state so we know if we need more information before parsing the map
|
|
73
76
|
|
|
@@ -79,8 +82,22 @@ const EditorPanel = props => {
|
|
|
79
82
|
|
|
80
83
|
const [activeFilterValueForDescription, setActiveFilterValueForDescription] = useState([0, 0])
|
|
81
84
|
|
|
85
|
+
const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({ config: state, setConfig: setState, filteredData: runtimeFilters, setFilteredData: setRuntimeFilters })
|
|
86
|
+
|
|
82
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']
|
|
83
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
|
+
|
|
84
101
|
const categoryMove = (idx1, idx2) => {
|
|
85
102
|
let categoryValuesOrder = [...state.legend.categoryValuesOrder]
|
|
86
103
|
|
|
@@ -119,7 +136,7 @@ const EditorPanel = props => {
|
|
|
119
136
|
}
|
|
120
137
|
|
|
121
138
|
const CheckBox = memo(({ label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes }) => (
|
|
122
|
-
<label className='checkbox'>
|
|
139
|
+
<label className='checkbox column-heading'>
|
|
123
140
|
<input
|
|
124
141
|
type='checkbox'
|
|
125
142
|
name={fieldName}
|
|
@@ -136,23 +153,6 @@ const EditorPanel = props => {
|
|
|
136
153
|
</label>
|
|
137
154
|
))
|
|
138
155
|
|
|
139
|
-
const handleFilterOrder = (idx1, idx2, filterIndex, filter) => {
|
|
140
|
-
let filterOrder = filter.values
|
|
141
|
-
let [movedItem] = filterOrder.splice(idx1, 1)
|
|
142
|
-
filterOrder.splice(idx2, 0, movedItem)
|
|
143
|
-
let filters = [...runtimeFilters]
|
|
144
|
-
let filterItem = { ...runtimeFilters[filterIndex] }
|
|
145
|
-
filterItem.active = filter.values[0]
|
|
146
|
-
filterItem.values = filterOrder
|
|
147
|
-
filterItem.order = 'cust'
|
|
148
|
-
filters[filterIndex] = filterItem
|
|
149
|
-
|
|
150
|
-
setState({
|
|
151
|
-
...state,
|
|
152
|
-
filters
|
|
153
|
-
})
|
|
154
|
-
}
|
|
155
|
-
|
|
156
156
|
const DynamicDesc = ({ label, fieldName, value: stateValue, type = 'input', ...attributes }) => {
|
|
157
157
|
const [value, setValue] = useState(stateValue)
|
|
158
158
|
|
|
@@ -201,6 +201,17 @@ const EditorPanel = props => {
|
|
|
201
201
|
}
|
|
202
202
|
})
|
|
203
203
|
break
|
|
204
|
+
|
|
205
|
+
case 'toggleDataTableLink':
|
|
206
|
+
setState({
|
|
207
|
+
...state,
|
|
208
|
+
table: {
|
|
209
|
+
...state.table,
|
|
210
|
+
showDataTableLink: value
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
break
|
|
214
|
+
|
|
204
215
|
case 'toggleDataUrl':
|
|
205
216
|
setState({
|
|
206
217
|
...state,
|
|
@@ -276,9 +287,9 @@ const EditorPanel = props => {
|
|
|
276
287
|
case 'expandDataTable':
|
|
277
288
|
setState({
|
|
278
289
|
...state,
|
|
279
|
-
|
|
280
|
-
...state.
|
|
281
|
-
|
|
290
|
+
table: {
|
|
291
|
+
...state.table,
|
|
292
|
+
expanded: value
|
|
282
293
|
}
|
|
283
294
|
})
|
|
284
295
|
break
|
|
@@ -409,6 +420,11 @@ const EditorPanel = props => {
|
|
|
409
420
|
general: {
|
|
410
421
|
...state.general,
|
|
411
422
|
showDownloadButton: !state.general.showDownloadButton
|
|
423
|
+
},
|
|
424
|
+
table: {
|
|
425
|
+
// setting both bc DataTable new core needs it here
|
|
426
|
+
...state.table,
|
|
427
|
+
download: !state.general.showDownloadButton
|
|
412
428
|
}
|
|
413
429
|
})
|
|
414
430
|
break
|
|
@@ -498,7 +514,7 @@ const EditorPanel = props => {
|
|
|
498
514
|
})
|
|
499
515
|
break
|
|
500
516
|
default:
|
|
501
|
-
console.warn('Map type not set')
|
|
517
|
+
console.warn('COVE: Map type not set') // eslint-disable-line
|
|
502
518
|
break
|
|
503
519
|
}
|
|
504
520
|
break
|
|
@@ -528,8 +544,8 @@ const EditorPanel = props => {
|
|
|
528
544
|
geoType: 'us',
|
|
529
545
|
type: state.type === 'us-geocode' ? 'data' : state.type
|
|
530
546
|
},
|
|
531
|
-
|
|
532
|
-
...state.
|
|
547
|
+
table: {
|
|
548
|
+
...state.table,
|
|
533
549
|
forceDisplay: true
|
|
534
550
|
}
|
|
535
551
|
})
|
|
@@ -541,8 +557,8 @@ const EditorPanel = props => {
|
|
|
541
557
|
...state.general,
|
|
542
558
|
geoType: 'us-region'
|
|
543
559
|
},
|
|
544
|
-
|
|
545
|
-
...state.
|
|
560
|
+
table: {
|
|
561
|
+
...state.table,
|
|
546
562
|
forceDisplay: true
|
|
547
563
|
}
|
|
548
564
|
})
|
|
@@ -554,8 +570,8 @@ const EditorPanel = props => {
|
|
|
554
570
|
...state.general,
|
|
555
571
|
geoType: 'world'
|
|
556
572
|
},
|
|
557
|
-
|
|
558
|
-
...state.
|
|
573
|
+
table: {
|
|
574
|
+
...state.table,
|
|
559
575
|
forceDisplay: true
|
|
560
576
|
}
|
|
561
577
|
})
|
|
@@ -565,11 +581,11 @@ const EditorPanel = props => {
|
|
|
565
581
|
...state,
|
|
566
582
|
general: {
|
|
567
583
|
...state.general,
|
|
568
|
-
geoType: 'us-county'
|
|
569
|
-
expandDataTable: false
|
|
584
|
+
geoType: 'us-county'
|
|
570
585
|
},
|
|
571
|
-
|
|
572
|
-
...state.
|
|
586
|
+
table: {
|
|
587
|
+
...state.table,
|
|
588
|
+
expanded: false,
|
|
573
589
|
forceDisplay: true
|
|
574
590
|
}
|
|
575
591
|
})
|
|
@@ -579,11 +595,11 @@ const EditorPanel = props => {
|
|
|
579
595
|
...state,
|
|
580
596
|
general: {
|
|
581
597
|
...state.general,
|
|
582
|
-
geoType: 'single-state'
|
|
583
|
-
expandDataTable: false
|
|
598
|
+
geoType: 'single-state'
|
|
584
599
|
},
|
|
585
|
-
|
|
586
|
-
...state.
|
|
600
|
+
table: {
|
|
601
|
+
...state.table,
|
|
602
|
+
expanded: false,
|
|
587
603
|
forceDisplay: true
|
|
588
604
|
}
|
|
589
605
|
})
|
|
@@ -687,8 +703,8 @@ const EditorPanel = props => {
|
|
|
687
703
|
case 'showDataTable':
|
|
688
704
|
setState({
|
|
689
705
|
...state,
|
|
690
|
-
|
|
691
|
-
...state.
|
|
706
|
+
table: {
|
|
707
|
+
...state.table,
|
|
692
708
|
forceDisplay: value
|
|
693
709
|
}
|
|
694
710
|
})
|
|
@@ -696,8 +712,8 @@ const EditorPanel = props => {
|
|
|
696
712
|
case 'limitDataTableHeight':
|
|
697
713
|
setState({
|
|
698
714
|
...state,
|
|
699
|
-
|
|
700
|
-
...state.
|
|
715
|
+
table: {
|
|
716
|
+
...state.table,
|
|
701
717
|
limitHeight: value
|
|
702
718
|
}
|
|
703
719
|
})
|
|
@@ -733,8 +749,14 @@ const EditorPanel = props => {
|
|
|
733
749
|
}
|
|
734
750
|
})
|
|
735
751
|
break
|
|
752
|
+
case 'filterBehavior':
|
|
753
|
+
setState({
|
|
754
|
+
...state,
|
|
755
|
+
filterBehavior: value
|
|
756
|
+
})
|
|
757
|
+
break
|
|
736
758
|
default:
|
|
737
|
-
console.warn(`Did not recognize editor property.`)
|
|
759
|
+
console.warn(`COVE: Did not recognize editor property.`) // eslint-disable-line
|
|
738
760
|
break
|
|
739
761
|
}
|
|
740
762
|
}
|
|
@@ -857,6 +879,10 @@ const EditorPanel = props => {
|
|
|
857
879
|
newFilters.splice(idx, 1)
|
|
858
880
|
}
|
|
859
881
|
break
|
|
882
|
+
case 'filterStyle':
|
|
883
|
+
newFilters[idx] = { ...newFilters[idx] }
|
|
884
|
+
newFilters[idx].filterStyle = value
|
|
885
|
+
break
|
|
860
886
|
case 'columnName':
|
|
861
887
|
newFilters[idx] = { ...newFilters[idx] }
|
|
862
888
|
newFilters[idx].columnName = value
|
|
@@ -889,6 +915,7 @@ const EditorPanel = props => {
|
|
|
889
915
|
})
|
|
890
916
|
}
|
|
891
917
|
|
|
918
|
+
// just adds a new column but not set to any data yet
|
|
892
919
|
const addAdditionalColumn = number => {
|
|
893
920
|
const columnKey = `additionalColumn${number}`
|
|
894
921
|
|
|
@@ -907,6 +934,33 @@ const EditorPanel = props => {
|
|
|
907
934
|
})
|
|
908
935
|
}
|
|
909
936
|
|
|
937
|
+
const MapFilters = () => {
|
|
938
|
+
return (
|
|
939
|
+
<>
|
|
940
|
+
<label>
|
|
941
|
+
Filter Behavior
|
|
942
|
+
<select
|
|
943
|
+
value={state.filterBehavior}
|
|
944
|
+
onChange={e => {
|
|
945
|
+
setState({
|
|
946
|
+
...state,
|
|
947
|
+
filterBehavior: e.target.value
|
|
948
|
+
})
|
|
949
|
+
}}
|
|
950
|
+
>
|
|
951
|
+
<option key='Apply Button' value='Apply Button'>
|
|
952
|
+
Apply Button
|
|
953
|
+
</option>
|
|
954
|
+
<option key='Filter Change' value='Filter Change'>
|
|
955
|
+
Filter Change
|
|
956
|
+
</option>
|
|
957
|
+
</select>
|
|
958
|
+
</label>
|
|
959
|
+
{filtersJSX}
|
|
960
|
+
</>
|
|
961
|
+
)
|
|
962
|
+
}
|
|
963
|
+
|
|
910
964
|
const removeAdditionalColumn = columnName => {
|
|
911
965
|
const newColumns = state.columns
|
|
912
966
|
|
|
@@ -1008,7 +1062,7 @@ const EditorPanel = props => {
|
|
|
1008
1062
|
if (!isReversed && state.color.endsWith('reverse')) {
|
|
1009
1063
|
paletteName = state.color.slice(0, -7)
|
|
1010
1064
|
}
|
|
1011
|
-
if(paletteName){
|
|
1065
|
+
if (paletteName) {
|
|
1012
1066
|
handleEditorChanges('color', paletteName)
|
|
1013
1067
|
}
|
|
1014
1068
|
}, [isReversed])
|
|
@@ -1136,103 +1190,110 @@ const EditorPanel = props => {
|
|
|
1136
1190
|
const usedFilterColumns = {}
|
|
1137
1191
|
|
|
1138
1192
|
const filtersJSX = state.filters.map((filter, index) => {
|
|
1193
|
+
if (filter.type === 'url') return <></>
|
|
1194
|
+
|
|
1139
1195
|
if (filter.columnName) {
|
|
1140
1196
|
usedFilterColumns[filter.columnName] = true
|
|
1141
1197
|
}
|
|
1142
1198
|
|
|
1143
|
-
const filterOptions = [
|
|
1144
|
-
{
|
|
1145
|
-
label: 'Ascending Alphanumeric',
|
|
1146
|
-
value: 'asc'
|
|
1147
|
-
},
|
|
1148
|
-
{
|
|
1149
|
-
label: 'Descending Alphanumeric',
|
|
1150
|
-
value: 'desc'
|
|
1151
|
-
},
|
|
1152
|
-
{
|
|
1153
|
-
label: 'Custom',
|
|
1154
|
-
value: 'cust'
|
|
1155
|
-
}
|
|
1156
|
-
]
|
|
1157
|
-
|
|
1158
1199
|
return (
|
|
1159
|
-
|
|
1160
|
-
<
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
e
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
>
|
|
1167
|
-
Remove
|
|
1168
|
-
</button>
|
|
1169
|
-
<TextField value={state.filters[index].label} section='filters' subsection={index} fieldName='label' label='Label' updateField={updateField} />
|
|
1170
|
-
<label>
|
|
1171
|
-
<span className='edit-label column-heading'>
|
|
1172
|
-
Filter Column
|
|
1173
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
1174
|
-
<Tooltip.Target>
|
|
1175
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1176
|
-
</Tooltip.Target>
|
|
1177
|
-
<Tooltip.Content>
|
|
1178
|
-
<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>
|
|
1179
|
-
</Tooltip.Content>
|
|
1180
|
-
</Tooltip>
|
|
1181
|
-
</span>
|
|
1182
|
-
<select
|
|
1183
|
-
value={filter.columnName}
|
|
1184
|
-
onChange={event => {
|
|
1185
|
-
changeFilter(index, 'columnName', event.target.value)
|
|
1186
|
-
}}
|
|
1187
|
-
>
|
|
1188
|
-
{columnsOptions.filter(({ key }) => undefined === usedFilterColumns[key] || filter.columnName === key)}
|
|
1189
|
-
</select>
|
|
1190
|
-
</label>
|
|
1191
|
-
|
|
1192
|
-
<label>
|
|
1193
|
-
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
1194
|
-
<select
|
|
1195
|
-
value={filter.order}
|
|
1196
|
-
onChange={e => {
|
|
1197
|
-
changeFilter(index, 'filterOrder', e.target.value)
|
|
1198
|
-
changeFilterActive(index, filter.values[0])
|
|
1200
|
+
<>
|
|
1201
|
+
<fieldset className='edit-block' key={`filter-${index}`}>
|
|
1202
|
+
<button
|
|
1203
|
+
className='remove-column'
|
|
1204
|
+
onClick={e => {
|
|
1205
|
+
e.preventDefault()
|
|
1206
|
+
changeFilter(index, 'remove')
|
|
1199
1207
|
}}
|
|
1200
1208
|
>
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1209
|
+
Remove
|
|
1210
|
+
</button>
|
|
1211
|
+
<TextField value={state.filters[index].label} section='filters' subsection={index} fieldName='label' label='Label' updateField={updateField} />
|
|
1212
|
+
<label>
|
|
1213
|
+
<span className='edit-label column-heading'>
|
|
1214
|
+
Filter Column
|
|
1215
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1216
|
+
<Tooltip.Target>
|
|
1217
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1218
|
+
</Tooltip.Target>
|
|
1219
|
+
<Tooltip.Content>
|
|
1220
|
+
<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>
|
|
1221
|
+
</Tooltip.Content>
|
|
1222
|
+
</Tooltip>
|
|
1223
|
+
</span>
|
|
1224
|
+
<select
|
|
1225
|
+
value={filter.columnName}
|
|
1226
|
+
onChange={event => {
|
|
1227
|
+
changeFilter(index, 'columnName', event.target.value)
|
|
1228
|
+
}}
|
|
1229
|
+
>
|
|
1230
|
+
{columnsOptions.filter(({ key }) => undefined === usedFilterColumns[key] || filter.columnName === key)}
|
|
1231
|
+
</select>
|
|
1232
|
+
</label>
|
|
1233
|
+
|
|
1234
|
+
<label>
|
|
1235
|
+
<span className='edit-filterOrder column-heading'>Filter Style</span>
|
|
1236
|
+
<select
|
|
1237
|
+
value={filter.filterStyle}
|
|
1238
|
+
onChange={e => {
|
|
1239
|
+
changeFilter(index, 'filterStyle', e.target.value)
|
|
1240
|
+
}}
|
|
1241
|
+
>
|
|
1242
|
+
{filterStyleOptions.map((option, index) => {
|
|
1243
|
+
return (
|
|
1244
|
+
<option value={option} key={`filter-${option}--${index}`}>
|
|
1245
|
+
{option}
|
|
1246
|
+
</option>
|
|
1247
|
+
)
|
|
1248
|
+
})}
|
|
1249
|
+
</select>
|
|
1250
|
+
</label>
|
|
1251
|
+
|
|
1252
|
+
<label>
|
|
1253
|
+
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
1254
|
+
<select
|
|
1255
|
+
value={filter.order}
|
|
1256
|
+
onChange={e => {
|
|
1257
|
+
changeFilter(index, 'filterOrder', e.target.value)
|
|
1258
|
+
changeFilterActive(index, filter.values[0])
|
|
1259
|
+
}}
|
|
1260
|
+
>
|
|
1261
|
+
{filterOrderOptions.map((option, index) => {
|
|
1262
|
+
return (
|
|
1263
|
+
<option value={option.value} key={`filter-${index}`}>
|
|
1264
|
+
{option.label}
|
|
1265
|
+
</option>
|
|
1266
|
+
)
|
|
1267
|
+
})}
|
|
1268
|
+
</select>
|
|
1269
|
+
</label>
|
|
1270
|
+
|
|
1271
|
+
{filter.order === 'cust' && (
|
|
1272
|
+
<DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, state.filters[index])}>
|
|
1273
|
+
<Droppable droppableId='filter_order'>
|
|
1274
|
+
{provided => (
|
|
1275
|
+
<ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
1276
|
+
{state.filters[index]?.values.map((value, index) => {
|
|
1277
|
+
return (
|
|
1278
|
+
<Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
|
|
1279
|
+
{(provided, snapshot) => (
|
|
1280
|
+
<li>
|
|
1281
|
+
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
1282
|
+
{value}
|
|
1283
|
+
</div>
|
|
1284
|
+
</li>
|
|
1285
|
+
)}
|
|
1286
|
+
</Draggable>
|
|
1287
|
+
)
|
|
1288
|
+
})}
|
|
1289
|
+
{provided.placeholder}
|
|
1290
|
+
</ul>
|
|
1291
|
+
)}
|
|
1292
|
+
</Droppable>
|
|
1293
|
+
</DragDropContext>
|
|
1294
|
+
)}
|
|
1295
|
+
</fieldset>
|
|
1296
|
+
</>
|
|
1236
1297
|
)
|
|
1237
1298
|
})
|
|
1238
1299
|
|
|
@@ -1315,6 +1376,24 @@ const EditorPanel = props => {
|
|
|
1315
1376
|
)
|
|
1316
1377
|
}
|
|
1317
1378
|
|
|
1379
|
+
const isLoadedFromUrl = state?.dataKey?.includes('http://') || state?.dataKey?.includes('https://')
|
|
1380
|
+
|
|
1381
|
+
// if isDebug = true, then try to set the Geography Col and Data col to reduce clicking
|
|
1382
|
+
const setGeoColumn = () => {
|
|
1383
|
+
// only for debug mode
|
|
1384
|
+
let geoColFound = columnsInData.includes(state.columns.geo.name)
|
|
1385
|
+
if (undefined !== isDebug && isDebug && !geoColFound) {
|
|
1386
|
+
// then try to set the x axis to appropriate value so we dont have to manually do it
|
|
1387
|
+
let mapcols = columnsInData[0]
|
|
1388
|
+
if (mapcols !== '') editColumn('geo', 'name', mapcols)
|
|
1389
|
+
|
|
1390
|
+
if (!state.columns.hasOwnProperty('primary') || undefined === state.columns.primary.name || '' === state.columns.primary.name || !state.columns.primary.name) {
|
|
1391
|
+
editColumn('primary', 'name', columnsInData[1]) // blindly picks first value col
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
if (isDebug) setGeoColumn()
|
|
1396
|
+
|
|
1318
1397
|
return (
|
|
1319
1398
|
<ErrorBoundary component='EditorPanel'>
|
|
1320
1399
|
{state?.runtime?.editorErrorMessage.length > 0 && <Error />}
|
|
@@ -2131,6 +2210,7 @@ const EditorPanel = props => {
|
|
|
2131
2210
|
</label>
|
|
2132
2211
|
)}
|
|
2133
2212
|
{/* always show */}
|
|
2213
|
+
{/*
|
|
2134
2214
|
<label className='checkbox'>
|
|
2135
2215
|
<input
|
|
2136
2216
|
type='checkbox'
|
|
@@ -2140,7 +2220,7 @@ const EditorPanel = props => {
|
|
|
2140
2220
|
}}
|
|
2141
2221
|
/>
|
|
2142
2222
|
<span className='edit-label'>Show Special Classes Last</span>
|
|
2143
|
-
</label>
|
|
2223
|
+
</label> */}
|
|
2144
2224
|
{'category' !== legend.type && (
|
|
2145
2225
|
<label className='checkbox'>
|
|
2146
2226
|
<input type='checkbox' checked={legend.separateZero || false} onChange={event => handleEditorChanges('separateZero', event.target.checked)} />
|
|
@@ -2158,7 +2238,6 @@ const EditorPanel = props => {
|
|
|
2158
2238
|
</label>
|
|
2159
2239
|
)}
|
|
2160
2240
|
{/* Temp Checkbox */}
|
|
2161
|
-
|
|
2162
2241
|
{state.legend.type === 'equalnumber' && (
|
|
2163
2242
|
<label className='checkbox mt-4'>
|
|
2164
2243
|
<input
|
|
@@ -2322,7 +2401,7 @@ const EditorPanel = props => {
|
|
|
2322
2401
|
<AccordionItemButton>Filters</AccordionItemButton>
|
|
2323
2402
|
</AccordionItemHeading>
|
|
2324
2403
|
<AccordionItemPanel>
|
|
2325
|
-
{filtersJSX.length > 0 ?
|
|
2404
|
+
{filtersJSX.length > 0 ? <MapFilters /> : <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
|
|
2326
2405
|
<button
|
|
2327
2406
|
className={'btn full-width'}
|
|
2328
2407
|
onClick={event => {
|
|
@@ -2344,10 +2423,10 @@ const EditorPanel = props => {
|
|
|
2344
2423
|
</AccordionItemHeading>
|
|
2345
2424
|
<AccordionItemPanel>
|
|
2346
2425
|
<TextField
|
|
2347
|
-
value={
|
|
2426
|
+
value={table.label}
|
|
2348
2427
|
updateField={updateField}
|
|
2349
|
-
section='
|
|
2350
|
-
fieldName='
|
|
2428
|
+
section='table'
|
|
2429
|
+
fieldName='label'
|
|
2351
2430
|
id='dataTableTitle'
|
|
2352
2431
|
label='Data Table Title'
|
|
2353
2432
|
placeholder='Data Table'
|
|
@@ -2365,16 +2444,16 @@ const EditorPanel = props => {
|
|
|
2365
2444
|
<label className='checkbox'>
|
|
2366
2445
|
<input
|
|
2367
2446
|
type='checkbox'
|
|
2368
|
-
checked={state.
|
|
2447
|
+
checked={state.table.forceDisplay !== undefined ? state.table.forceDisplay : !isDashboard}
|
|
2369
2448
|
onChange={event => {
|
|
2370
2449
|
handleEditorChanges('showDataTable', event.target.checked)
|
|
2371
2450
|
}}
|
|
2372
2451
|
/>
|
|
2373
|
-
<span className='edit-label'>
|
|
2374
|
-
Show Table
|
|
2452
|
+
<span className='edit-label column-heading'>
|
|
2453
|
+
Show Data Table
|
|
2375
2454
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
2376
2455
|
<Tooltip.Target>
|
|
2377
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2456
|
+
<Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
|
|
2378
2457
|
</Tooltip.Target>
|
|
2379
2458
|
<Tooltip.Content>
|
|
2380
2459
|
<p>Data tables are required for 508 compliance. When choosing to hide this data table, replace with your own version.</p>
|
|
@@ -2383,9 +2462,9 @@ const EditorPanel = props => {
|
|
|
2383
2462
|
</span>
|
|
2384
2463
|
</label>
|
|
2385
2464
|
<TextField
|
|
2386
|
-
value={
|
|
2465
|
+
value={table.indexLabel || ''}
|
|
2387
2466
|
updateField={updateField}
|
|
2388
|
-
section='
|
|
2467
|
+
section='table'
|
|
2389
2468
|
fieldName='indexLabel'
|
|
2390
2469
|
label='Index Column Header'
|
|
2391
2470
|
placeholder='Location'
|
|
@@ -2401,9 +2480,9 @@ const EditorPanel = props => {
|
|
|
2401
2480
|
}
|
|
2402
2481
|
/>
|
|
2403
2482
|
<TextField
|
|
2404
|
-
value={
|
|
2483
|
+
value={state.table.caption}
|
|
2405
2484
|
updateField={updateField}
|
|
2406
|
-
section='
|
|
2485
|
+
section='table'
|
|
2407
2486
|
fieldName='caption'
|
|
2408
2487
|
label='Data Table Caption'
|
|
2409
2488
|
placeholder='Data Table'
|
|
@@ -2422,34 +2501,48 @@ const EditorPanel = props => {
|
|
|
2422
2501
|
<label className='checkbox'>
|
|
2423
2502
|
<input
|
|
2424
2503
|
type='checkbox'
|
|
2425
|
-
checked={state.
|
|
2504
|
+
checked={state.table.limitHeight}
|
|
2426
2505
|
onChange={event => {
|
|
2427
2506
|
handleEditorChanges('limitDataTableHeight', event.target.checked)
|
|
2428
2507
|
}}
|
|
2429
2508
|
/>
|
|
2430
2509
|
<span className='edit-label'>Limit Table Height</span>
|
|
2431
2510
|
</label>
|
|
2432
|
-
{state.
|
|
2511
|
+
{state.table.limitHeight && <TextField value={table.height} updateField={updateField} section='table' fieldName='height' label='Data Table Height' placeholder='Height(px)' type='number' min='0' max='500' />}
|
|
2433
2512
|
<label className='checkbox'>
|
|
2434
2513
|
<input
|
|
2435
2514
|
type='checkbox'
|
|
2436
|
-
checked={state.
|
|
2515
|
+
checked={state.table.expanded || false}
|
|
2437
2516
|
onChange={event => {
|
|
2438
2517
|
handleEditorChanges('expandDataTable', event.target.checked)
|
|
2439
2518
|
}}
|
|
2440
2519
|
/>
|
|
2441
2520
|
<span className='edit-label'>Map loads with data table expanded</span>
|
|
2442
2521
|
</label>
|
|
2443
|
-
|
|
2444
|
-
<
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2522
|
+
{isDashboard && (
|
|
2523
|
+
<label className='checkbox'>
|
|
2524
|
+
<input
|
|
2525
|
+
type='checkbox'
|
|
2526
|
+
checked={state.table.showDataTableLink}
|
|
2527
|
+
onChange={event => {
|
|
2528
|
+
handleEditorChanges('toggleDataTableLink', event.target.checked)
|
|
2529
|
+
}}
|
|
2530
|
+
/>
|
|
2531
|
+
<span className='edit-label'>Show Data Table Name & Link</span>
|
|
2532
|
+
</label>
|
|
2533
|
+
)}
|
|
2534
|
+
{isLoadedFromUrl && (
|
|
2535
|
+
<label className='checkbox'>
|
|
2536
|
+
<input
|
|
2537
|
+
type='checkbox'
|
|
2538
|
+
checked={state.table.showDownloadUrl}
|
|
2539
|
+
onChange={event => {
|
|
2540
|
+
handleEditorChanges('toggleDataUrl', event.target.checked)
|
|
2541
|
+
}}
|
|
2542
|
+
/>
|
|
2543
|
+
<span className='edit-label'>Show URL to Automatically Updated Data</span>
|
|
2544
|
+
</label>
|
|
2545
|
+
)}
|
|
2453
2546
|
<label className='checkbox'>
|
|
2454
2547
|
<input
|
|
2455
2548
|
type='checkbox'
|
|
@@ -2458,7 +2551,7 @@ const EditorPanel = props => {
|
|
|
2458
2551
|
handleEditorChanges('toggleDownloadButton', event.target.checked)
|
|
2459
2552
|
}}
|
|
2460
2553
|
/>
|
|
2461
|
-
<span className='edit-label'>
|
|
2554
|
+
<span className='edit-label'>Show Download CSV Link</span>
|
|
2462
2555
|
</label>
|
|
2463
2556
|
{/* <label className='checkbox'>
|
|
2464
2557
|
<input
|
|
@@ -2722,6 +2815,44 @@ const EditorPanel = props => {
|
|
|
2722
2815
|
))}
|
|
2723
2816
|
</AccordionItemPanel>
|
|
2724
2817
|
</AccordionItem>
|
|
2818
|
+
{/* <AccordionItem>
|
|
2819
|
+
<AccordionItemHeading>
|
|
2820
|
+
<AccordionItemButton>Custom Map Layers</AccordionItemButton>
|
|
2821
|
+
</AccordionItemHeading>
|
|
2822
|
+
<AccordionItemPanel>
|
|
2823
|
+
{state.map.layers.length === 0 && <p>There are currently no layers.</p>}
|
|
2824
|
+
|
|
2825
|
+
{state.map.layers.map((layer, index) => {
|
|
2826
|
+
return (
|
|
2827
|
+
<>
|
|
2828
|
+
<Accordion allowZeroExpanded>
|
|
2829
|
+
<AccordionItem className='series-item map-layers-list'>
|
|
2830
|
+
<AccordionItemHeading className='series-item__title map-layers-list--title'>
|
|
2831
|
+
<AccordionItemButton>{`Layer ${index + 1}: ${layer.name}`}</AccordionItemButton>
|
|
2832
|
+
</AccordionItemHeading>
|
|
2833
|
+
<AccordionItemPanel>
|
|
2834
|
+
<div className='map-layers-panel'>
|
|
2835
|
+
<label htmlFor='layerName'>Layer Name:</label>
|
|
2836
|
+
<input type='text' name='layerName' value={layer.name} onChange={e => handleMapLayerName(e, index)} />
|
|
2837
|
+
<label htmlFor='layerFilename'>File:</label>
|
|
2838
|
+
<input type='text' name='layerFilename' value={layer.url} onChange={e => handleMapLayerUrl(e, index)} />
|
|
2839
|
+
<label htmlFor='layerNamespace'>TOPOJSON Namespace:</label>
|
|
2840
|
+
<input type='text' name='layerNamespace' value={layer.namespace} onChange={e => handleMapLayerNamespace(e, index)} />
|
|
2841
|
+
<label htmlFor='layerTooltip'>Tooltip:</label>
|
|
2842
|
+
<textarea name='layerTooltip' value={layer.tooltip} onChange={e => handleMapLayerTooltip(e, index)}></textarea>
|
|
2843
|
+
<button onClick={e => handleRemoveLayer(e, index)}>Remove Layer</button>
|
|
2844
|
+
</div>
|
|
2845
|
+
</AccordionItemPanel>
|
|
2846
|
+
</AccordionItem>
|
|
2847
|
+
</Accordion>
|
|
2848
|
+
</>
|
|
2849
|
+
)
|
|
2850
|
+
})}
|
|
2851
|
+
<button className={'btn full-width'} onClick={handleAddLayer}>
|
|
2852
|
+
Add Map Layer
|
|
2853
|
+
</button>
|
|
2854
|
+
</AccordionItemPanel>
|
|
2855
|
+
</AccordionItem> */}
|
|
2725
2856
|
</Accordion>
|
|
2726
2857
|
</form>
|
|
2727
2858
|
<AdvancedEditor loadConfig={loadConfig} state={state} convertStateToConfig={convertStateToConfig} />
|