@cdc/map 4.23.4 → 4.23.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,7 +70,7 @@ const TextField = ({ label, section = null, subsection = null, fieldName, update
70
70
  const EditorPanel = props => {
71
71
  const { state, columnsInData = [], loadConfig, setState, isDashboard, setParentConfig, runtimeFilters, runtimeLegend, changeFilterActive, isDebug, setRuntimeFilters } = props
72
72
 
73
- const { general, columns, legend, dataTable, tooltips } = state
73
+ const { general, columns, legend, table, 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
 
@@ -89,12 +89,9 @@ const EditorPanel = props => {
89
89
  const {
90
90
  // prettier-ignore
91
91
  MapLayerHandlers: {
92
+ handleMapLayer,
92
93
  handleAddLayer,
93
- handleMapLayerName,
94
- handleMapLayerUrl,
95
- handleRemoveLayer,
96
- handleMapLayerNamespace,
97
- handleMapLayerTooltip
94
+ handleRemoveLayer
98
95
  }
99
96
  } = useMapLayers(state, setState, false, true)
100
97
 
@@ -287,9 +284,9 @@ const EditorPanel = props => {
287
284
  case 'expandDataTable':
288
285
  setState({
289
286
  ...state,
290
- general: {
291
- ...state.general,
292
- expandDataTable: value
287
+ table: {
288
+ ...state.table,
289
+ expanded: value
293
290
  }
294
291
  })
295
292
  break
@@ -420,6 +417,21 @@ const EditorPanel = props => {
420
417
  general: {
421
418
  ...state.general,
422
419
  showDownloadButton: !state.general.showDownloadButton
420
+ },
421
+ table: {
422
+ // setting both bc DataTable new core needs it here
423
+ ...state.table,
424
+ download: !state.general.showDownloadButton
425
+ }
426
+ })
427
+ break
428
+ case 'toggleShowFullGeoNameInCSV':
429
+ setState({
430
+ ...state,
431
+ table: {
432
+ // setting both bc DataTable new core needs it here
433
+ ...state.table,
434
+ showFullGeoNameInCSV: !state.table.showFullGeoNameInCSV
423
435
  }
424
436
  })
425
437
  break
@@ -539,8 +551,8 @@ const EditorPanel = props => {
539
551
  geoType: 'us',
540
552
  type: state.type === 'us-geocode' ? 'data' : state.type
541
553
  },
542
- dataTable: {
543
- ...state.dataTable,
554
+ table: {
555
+ ...state.table,
544
556
  forceDisplay: true
545
557
  }
546
558
  })
@@ -552,8 +564,8 @@ const EditorPanel = props => {
552
564
  ...state.general,
553
565
  geoType: 'us-region'
554
566
  },
555
- dataTable: {
556
- ...state.dataTable,
567
+ table: {
568
+ ...state.table,
557
569
  forceDisplay: true
558
570
  }
559
571
  })
@@ -565,8 +577,8 @@ const EditorPanel = props => {
565
577
  ...state.general,
566
578
  geoType: 'world'
567
579
  },
568
- dataTable: {
569
- ...state.dataTable,
580
+ table: {
581
+ ...state.table,
570
582
  forceDisplay: true
571
583
  }
572
584
  })
@@ -576,11 +588,11 @@ const EditorPanel = props => {
576
588
  ...state,
577
589
  general: {
578
590
  ...state.general,
579
- geoType: 'us-county',
580
- expandDataTable: false
591
+ geoType: 'us-county'
581
592
  },
582
- dataTable: {
583
- ...state.dataTable,
593
+ table: {
594
+ ...state.table,
595
+ expanded: false,
584
596
  forceDisplay: true
585
597
  }
586
598
  })
@@ -590,11 +602,11 @@ const EditorPanel = props => {
590
602
  ...state,
591
603
  general: {
592
604
  ...state.general,
593
- geoType: 'single-state',
594
- expandDataTable: false
605
+ geoType: 'single-state'
595
606
  },
596
- dataTable: {
597
- ...state.dataTable,
607
+ table: {
608
+ ...state.table,
609
+ expanded: false,
598
610
  forceDisplay: true
599
611
  }
600
612
  })
@@ -698,8 +710,8 @@ const EditorPanel = props => {
698
710
  case 'showDataTable':
699
711
  setState({
700
712
  ...state,
701
- dataTable: {
702
- ...state.dataTable,
713
+ table: {
714
+ ...state.table,
703
715
  forceDisplay: value
704
716
  }
705
717
  })
@@ -707,8 +719,8 @@ const EditorPanel = props => {
707
719
  case 'limitDataTableHeight':
708
720
  setState({
709
721
  ...state,
710
- dataTable: {
711
- ...state.dataTable,
722
+ table: {
723
+ ...state.table,
712
724
  limitHeight: value
713
725
  }
714
726
  })
@@ -878,6 +890,10 @@ const EditorPanel = props => {
878
890
  newFilters[idx] = { ...newFilters[idx] }
879
891
  newFilters[idx].filterStyle = value
880
892
  break
893
+ case 'showDropdown':
894
+ newFilters[idx] = { ...newFilters[idx] }
895
+ newFilters[idx].showDropdown = value
896
+ break
881
897
  case 'columnName':
882
898
  newFilters[idx] = { ...newFilters[idx] }
883
899
  newFilters[idx].columnName = value
@@ -910,6 +926,7 @@ const EditorPanel = props => {
910
926
  })
911
927
  }
912
928
 
929
+ // just adds a new column but not set to any data yet
913
930
  const addAdditionalColumn = number => {
914
931
  const columnKey = `additionalColumn${number}`
915
932
 
@@ -1184,6 +1201,8 @@ const EditorPanel = props => {
1184
1201
  const usedFilterColumns = {}
1185
1202
 
1186
1203
  const filtersJSX = state.filters.map((filter, index) => {
1204
+ if (filter.type === 'url') return <></>
1205
+
1187
1206
  if (filter.columnName) {
1188
1207
  usedFilterColumns[filter.columnName] = true
1189
1208
  }
@@ -1223,9 +1242,18 @@ const EditorPanel = props => {
1223
1242
  </select>
1224
1243
  </label>
1225
1244
 
1226
- {/* COMING SOON: 4.23.5: FILTER STYLES */}
1245
+ <label>
1246
+ <span className='edit-showDropdown column-heading'>Show Filter Input</span>
1247
+ <input
1248
+ type='checkbox'
1249
+ checked={filter.showDropdown === undefined ? true : filter.showDropdown}
1250
+ onChange={e => {
1251
+ changeFilter(index, 'showDropdown', e.target.checked)
1252
+ }}
1253
+ />
1254
+ </label>
1227
1255
 
1228
- {/* <label>
1256
+ <label>
1229
1257
  <span className='edit-filterOrder column-heading'>Filter Style</span>
1230
1258
  <select
1231
1259
  value={filter.filterStyle}
@@ -1241,7 +1269,7 @@ const EditorPanel = props => {
1241
1269
  )
1242
1270
  })}
1243
1271
  </select>
1244
- </label> */}
1272
+ </label>
1245
1273
 
1246
1274
  <label>
1247
1275
  <span className='edit-filterOrder column-heading'>Filter Order</span>
@@ -1398,310 +1426,361 @@ const EditorPanel = props => {
1398
1426
  <ReactTooltip multiline={true} />
1399
1427
  <span className='base-label'>Configure Map</span>
1400
1428
  <section className='form-container'>
1401
- <form>
1402
- <Accordion allowZeroExpanded={true}>
1403
- <AccordionItem>
1404
- {' '}
1429
+ <Accordion allowZeroExpanded={true}>
1430
+ <AccordionItem>
1431
+ {' '}
1432
+ {/* Type */}
1433
+ <AccordionItemHeading>
1434
+ <AccordionItemButton>Type</AccordionItemButton>
1435
+ </AccordionItemHeading>
1436
+ <AccordionItemPanel>
1437
+ {/* Geography */}
1438
+ <label>
1439
+ <span className='edit-label column-heading'>
1440
+ <span>Geography</span>
1441
+ </span>
1442
+ <ul className='geo-buttons'>
1443
+ <button
1444
+ className={state.general.geoType === 'us' || state.general.geoType === 'us-county' ? 'active' : ''}
1445
+ onClick={e => {
1446
+ e.preventDefault()
1447
+ handleEditorChanges('geoType', 'us')
1448
+ }}
1449
+ >
1450
+ <UsaGraphic />
1451
+ <span>United States</span>
1452
+ </button>
1453
+ <button
1454
+ className={state.general.geoType === 'us-region' ? 'active' : ''}
1455
+ onClick={e => {
1456
+ e.preventDefault()
1457
+ handleEditorChanges('geoType', 'us-region')
1458
+ }}
1459
+ >
1460
+ <UsaRegionGraphic />
1461
+ <span>U.S. Region</span>
1462
+ </button>
1463
+ <button
1464
+ className={state.general.geoType === 'world' ? 'active' : ''}
1465
+ onClick={e => {
1466
+ e.preventDefault()
1467
+ handleEditorChanges('geoType', 'world')
1468
+ }}
1469
+ >
1470
+ <WorldGraphic />
1471
+ <span>World</span>
1472
+ </button>
1473
+ <button
1474
+ className={state.general.geoType === 'single-state' ? 'active' : ''}
1475
+ onClick={e => {
1476
+ e.preventDefault()
1477
+ handleEditorChanges('geoType', 'single-state')
1478
+ }}
1479
+ >
1480
+ <AlabamaGraphic />
1481
+ <span>U.S. State</span>
1482
+ </button>
1483
+ </ul>
1484
+ </label>
1485
+ {/* Select > State or County Map */}
1486
+ {(state.general.geoType === 'us' || state.general.geoType === 'us-county') && (
1487
+ <label>
1488
+ <span className='edit-label column-heading'>Geography Subtype</span>
1489
+ <select
1490
+ value={state.general.geoType}
1491
+ onChange={event => {
1492
+ handleEditorChanges('geoType', event.target.value)
1493
+ }}
1494
+ >
1495
+ <option value='us'>US State-Level</option>
1496
+ <option value='us-county'>US County-Level</option>
1497
+ </select>
1498
+ </label>
1499
+ )}
1405
1500
  {/* Type */}
1406
- <AccordionItemHeading>
1407
- <AccordionItemButton>Type</AccordionItemButton>
1408
- </AccordionItemHeading>
1409
- <AccordionItemPanel>
1410
- {/* Geography */}
1501
+ {/* Select > Filter a state */}
1502
+ {state.general.geoType === 'single-state' && (
1411
1503
  <label>
1412
- <span className='edit-label column-heading'>
1413
- <span>Geography</span>
1414
- </span>
1415
- <ul className='geo-buttons'>
1416
- <button
1417
- className={state.general.geoType === 'us' || state.general.geoType === 'us-county' ? 'active' : ''}
1418
- onClick={e => {
1419
- e.preventDefault()
1420
- handleEditorChanges('geoType', 'us')
1421
- }}
1422
- >
1423
- <UsaGraphic />
1424
- <span>United States</span>
1425
- </button>
1426
- <button
1427
- className={state.general.geoType === 'us-region' ? 'active' : ''}
1428
- onClick={e => {
1429
- e.preventDefault()
1430
- handleEditorChanges('geoType', 'us-region')
1431
- }}
1432
- >
1433
- <UsaRegionGraphic />
1434
- <span>U.S. Region</span>
1435
- </button>
1436
- <button
1437
- className={state.general.geoType === 'world' ? 'active' : ''}
1438
- onClick={e => {
1439
- e.preventDefault()
1440
- handleEditorChanges('geoType', 'world')
1441
- }}
1442
- >
1443
- <WorldGraphic />
1444
- <span>World</span>
1445
- </button>
1446
- <button
1447
- className={state.general.geoType === 'single-state' ? 'active' : ''}
1448
- onClick={e => {
1449
- e.preventDefault()
1450
- handleEditorChanges('geoType', 'single-state')
1451
- }}
1452
- >
1453
- <AlabamaGraphic />
1454
- <span>U.S. State</span>
1455
- </button>
1456
- </ul>
1504
+ <span className='edit-label column-heading'>State Selector</span>
1505
+ <select
1506
+ value={state.general.hasOwnProperty('statePicked') ? state.general.statePicked.stateName : { fipsCode: '04', stateName: 'Alabama' }}
1507
+ onChange={event => {
1508
+ handleEditorChanges('chooseState', event.target.value)
1509
+ }}
1510
+ >
1511
+ <StateOptionList />
1512
+ </select>
1457
1513
  </label>
1458
- {/* Select > State or County Map */}
1459
- {(state.general.geoType === 'us' || state.general.geoType === 'us-county') && (
1514
+ )}
1515
+ {/* Type */}
1516
+ <label>
1517
+ <span className='edit-label column-heading'>
1518
+ Map Type
1519
+ <Tooltip style={{ textTransform: 'none' }}>
1520
+ <Tooltip.Target>
1521
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1522
+ </Tooltip.Target>
1523
+ <Tooltip.Content>
1524
+ <p>Select "Data" to create a color-coded data map. To create a navigation-only map, select "Navigation."</p>
1525
+ </Tooltip.Content>
1526
+ </Tooltip>
1527
+ </span>
1528
+ <select
1529
+ value={state.general.type}
1530
+ onChange={event => {
1531
+ handleEditorChanges('editorMapType', event.target.value)
1532
+ }}
1533
+ >
1534
+ <option value='data'>Data</option>
1535
+ {state.general.geoType === 'us-county' && <option value='us-geocode'>Geocode</option>}
1536
+ {state.general.geoType === 'world' && <option value='world-geocode'>Geocode</option>}
1537
+ <option value='navigation'>Navigation</option>
1538
+ {(state.general.geoType === 'world' || state.general.geoType === 'us') && <option value='bubble'>Bubble</option>}
1539
+ </select>
1540
+ </label>
1541
+ <label>
1542
+ <span className='edit-label'>Data Classification Type</span>
1543
+ <div>
1460
1544
  <label>
1461
- <span className='edit-label column-heading'>Geography Subtype</span>
1462
- <select
1463
- value={state.general.geoType}
1464
- onChange={event => {
1465
- handleEditorChanges('geoType', event.target.value)
1466
- }}
1467
- >
1468
- <option value='us'>US State-Level</option>
1469
- <option value='us-county'>US County-Level</option>
1470
- </select>
1545
+ <input type='radio' name='equalnumber' value='equalnumber' checked={state.legend.type === 'equalnumber'} onChange={e => handleEditorChanges('classificationType', e.target.value)} />
1546
+ Numeric/Quantitative
1471
1547
  </label>
1472
- )}
1473
- {/* Type */}
1474
- {/* Select > Filter a state */}
1475
- {state.general.geoType === 'single-state' && (
1476
1548
  <label>
1477
- <span className='edit-label column-heading'>State Selector</span>
1478
- <select
1479
- value={state.general.hasOwnProperty('statePicked') ? state.general.statePicked.stateName : { fipsCode: '04', stateName: 'Alabama' }}
1480
- onChange={event => {
1481
- handleEditorChanges('chooseState', event.target.value)
1482
- }}
1483
- >
1484
- <StateOptionList />
1485
- </select>
1549
+ <input type='radio' name='category' value='category' checked={state.legend.type === 'category'} onChange={e => handleEditorChanges('classificationType', e.target.value)} />
1550
+ Categorical
1486
1551
  </label>
1487
- )}
1488
- {/* Type */}
1552
+ </div>
1553
+ </label>
1554
+ {/* SubType */}
1555
+ {'us' === state.general.geoType && 'data' === state.general.type && (
1556
+ <label className='checkbox mt-4'>
1557
+ <input
1558
+ type='checkbox'
1559
+ checked={state.general.displayAsHex}
1560
+ onChange={event => {
1561
+ handleEditorChanges('displayAsHex', event.target.checked)
1562
+ }}
1563
+ />
1564
+ <span className='edit-label'>Display As Hex Map</span>
1565
+ </label>
1566
+ )}
1567
+ {'us' === state.general.geoType && 'bubble' !== state.general.type && false === state.general.displayAsHex && (
1568
+ <label className='checkbox'>
1569
+ <input
1570
+ type='checkbox'
1571
+ checked={state.general.displayStateLabels}
1572
+ onChange={event => {
1573
+ handleEditorChanges('displayStateLabels', event.target.checked)
1574
+ }}
1575
+ />
1576
+ <span className='edit-label'>Display state labels</span>
1577
+ </label>
1578
+ )}
1579
+ </AccordionItemPanel>
1580
+ </AccordionItem>
1581
+ <AccordionItem>
1582
+ {' '}
1583
+ {/* General */}
1584
+ <AccordionItemHeading>
1585
+ <AccordionItemButton>General</AccordionItemButton>
1586
+ </AccordionItemHeading>
1587
+ <AccordionItemPanel>
1588
+ <TextField
1589
+ value={general.title}
1590
+ data-testid='title-input'
1591
+ updateField={updateField}
1592
+ section='general'
1593
+ fieldName='title'
1594
+ id='title'
1595
+ label='Title'
1596
+ placeholder='Map Title'
1597
+ tooltip={
1598
+ <Tooltip style={{ textTransform: 'none' }}>
1599
+ <Tooltip.Target>
1600
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1601
+ </Tooltip.Target>
1602
+ <Tooltip.Content>
1603
+ <p>Title is required to set the name of the download file but can be hidden using the option below.</p>
1604
+ </Tooltip.Content>
1605
+ </Tooltip>
1606
+ }
1607
+ />
1608
+ <label className='checkbox'>
1609
+ <input
1610
+ type='checkbox'
1611
+ checked={state.general.showTitle || false}
1612
+ onChange={event => {
1613
+ handleEditorChanges('showTitle', event.target.checked)
1614
+ }}
1615
+ />
1616
+ <span className='edit-label'>Show Title</span>
1617
+ </label>
1618
+ <TextField
1619
+ value={general.superTitle || ''}
1620
+ updateField={updateField}
1621
+ section='general'
1622
+ fieldName='superTitle'
1623
+ label='Super Title'
1624
+ tooltip={
1625
+ <Tooltip style={{ textTransform: 'none' }}>
1626
+ <Tooltip.Target>
1627
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1628
+ </Tooltip.Target>
1629
+ <Tooltip.Content>
1630
+ <p>Super Title</p>
1631
+ </Tooltip.Content>
1632
+ </Tooltip>
1633
+ }
1634
+ />
1635
+ <TextField
1636
+ type='textarea'
1637
+ value={general.introText}
1638
+ updateField={updateField}
1639
+ section='general'
1640
+ fieldName='introText'
1641
+ label='Intro Text'
1642
+ tooltip={
1643
+ <Tooltip style={{ textTransform: 'none' }}>
1644
+ <Tooltip.Target>
1645
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1646
+ </Tooltip.Target>
1647
+ <Tooltip.Content>
1648
+ <p>Intro Text</p>
1649
+ </Tooltip.Content>
1650
+ </Tooltip>
1651
+ }
1652
+ />
1653
+ <TextField
1654
+ type='textarea'
1655
+ value={general.subtext}
1656
+ updateField={updateField}
1657
+ section='general'
1658
+ fieldName='subtext'
1659
+ label='Subtext'
1660
+ tooltip={
1661
+ <Tooltip style={{ textTransform: 'none' }}>
1662
+ <Tooltip.Target>
1663
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1664
+ </Tooltip.Target>
1665
+ <Tooltip.Content>
1666
+ <p>Enter supporting text to display below the data visualization, if applicable. The following HTML tags are supported: strong, em, sup, and sub.</p>
1667
+ </Tooltip.Content>
1668
+ </Tooltip>
1669
+ }
1670
+ />
1671
+ <TextField
1672
+ type='textarea'
1673
+ value={general.footnotes}
1674
+ updateField={updateField}
1675
+ section='general'
1676
+ fieldName='footnotes'
1677
+ label='Footnotes'
1678
+ tooltip={
1679
+ <Tooltip style={{ textTransform: 'none' }}>
1680
+ <Tooltip.Target>
1681
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1682
+ </Tooltip.Target>
1683
+ <Tooltip.Content>
1684
+ <p>Footnotes</p>
1685
+ </Tooltip.Content>
1686
+ </Tooltip>
1687
+ }
1688
+ />
1689
+ {'us' === state.general.geoType && <TextField value={general.territoriesLabel} updateField={updateField} section='general' fieldName='territoriesLabel' label='Territories Label' placeholder='Territories' />}
1690
+ {'us' === state.general.geoType && (
1691
+ <label className='checkbox'>
1692
+ <input
1693
+ type='checkbox'
1694
+ checked={general.territoriesAlwaysShow || false}
1695
+ onChange={event => {
1696
+ handleEditorChanges('territoriesAlwaysShow', event.target.checked)
1697
+ }}
1698
+ />
1699
+ <span className='edit-label'>Show All Territories</span>
1700
+ </label>
1701
+ )}
1702
+ {/* <label className="checkbox mt-4">
1703
+ <input type="checkbox" checked={ state.general.showDownloadMediaButton } onChange={(event) => { handleEditorChanges("toggleDownloadMediaButton", event.target.checked) }} />
1704
+ <span className="edit-label">Enable Media Download</span>
1705
+ </label> */}
1706
+ </AccordionItemPanel>
1707
+ </AccordionItem>
1708
+ <AccordionItem>
1709
+ {' '}
1710
+ {/* Columns */}
1711
+ <AccordionItemHeading>
1712
+ <AccordionItemButton>Columns</AccordionItemButton>
1713
+ </AccordionItemHeading>
1714
+ <AccordionItemPanel>
1715
+ <fieldset className='primary-fieldset edit-block'>
1489
1716
  <label>
1490
1717
  <span className='edit-label column-heading'>
1491
- Map Type
1718
+ Geography
1492
1719
  <Tooltip style={{ textTransform: 'none' }}>
1493
1720
  <Tooltip.Target>
1494
1721
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1495
1722
  </Tooltip.Target>
1496
1723
  <Tooltip.Content>
1497
- <p>Select "Data" to create a color-coded data map. To create a navigation-only map, select "Navigation."</p>
1724
+ <p>Select the source column containing the map location names or, for county-level maps, the FIPS codes.</p>
1498
1725
  </Tooltip.Content>
1499
1726
  </Tooltip>
1500
1727
  </span>
1501
1728
  <select
1502
- value={state.general.type}
1729
+ value={state.columns.geo ? state.columns.geo.name : columnsOptions[0]}
1503
1730
  onChange={event => {
1504
- handleEditorChanges('editorMapType', event.target.value)
1731
+ editColumn('geo', 'name', event.target.value)
1505
1732
  }}
1506
1733
  >
1507
- <option value='data'>Data</option>
1508
- {state.general.geoType === 'us-county' && <option value='us-geocode'>Geocode</option>}
1509
- {state.general.geoType === 'world' && <option value='world-geocode'>Geocode</option>}
1510
- <option value='navigation'>Navigation</option>
1511
- {(state.general.geoType === 'world' || state.general.geoType === 'us') && <option value='bubble'>Bubble</option>}
1734
+ {columnsOptions}
1512
1735
  </select>
1513
1736
  </label>
1514
- <label>
1515
- <span className='edit-label'>Data Classification Type</span>
1516
- <div>
1517
- <label>
1518
- <input type='radio' name='equalnumber' value='equalnumber' checked={state.legend.type === 'equalnumber'} onChange={e => handleEditorChanges('classificationType', e.target.value)} />
1519
- Numeric/Quantitative
1520
- </label>
1521
- <label>
1522
- <input type='radio' name='category' value='category' checked={state.legend.type === 'category'} onChange={e => handleEditorChanges('classificationType', e.target.value)} />
1523
- Categorical
1524
- </label>
1525
- </div>
1526
- </label>
1527
- {/* SubType */}
1528
- {'us' === state.general.geoType && 'data' === state.general.type && (
1529
- <label className='checkbox mt-4'>
1530
- <input
1531
- type='checkbox'
1532
- checked={state.general.displayAsHex}
1533
- onChange={event => {
1534
- handleEditorChanges('displayAsHex', event.target.checked)
1535
- }}
1536
- />
1537
- <span className='edit-label'>Display As Hex Map</span>
1538
- </label>
1539
- )}
1540
- {'us' === state.general.geoType && 'bubble' !== state.general.type && false === state.general.displayAsHex && (
1541
- <label className='checkbox'>
1542
- <input
1543
- type='checkbox'
1544
- checked={state.general.displayStateLabels}
1545
- onChange={event => {
1546
- handleEditorChanges('displayStateLabels', event.target.checked)
1547
- }}
1548
- />
1549
- <span className='edit-label'>Display state labels</span>
1550
- </label>
1551
- )}
1552
- </AccordionItemPanel>
1553
- </AccordionItem>
1554
- <AccordionItem>
1555
- {' '}
1556
- {/* General */}
1557
- <AccordionItemHeading>
1558
- <AccordionItemButton>General</AccordionItemButton>
1559
- </AccordionItemHeading>
1560
- <AccordionItemPanel>
1561
- <TextField
1562
- value={general.title}
1563
- data-testid='title-input'
1564
- updateField={updateField}
1565
- section='general'
1566
- fieldName='title'
1567
- id='title'
1568
- label='Title'
1569
- placeholder='Map Title'
1570
- tooltip={
1571
- <Tooltip style={{ textTransform: 'none' }}>
1572
- <Tooltip.Target>
1573
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1574
- </Tooltip.Target>
1575
- <Tooltip.Content>
1576
- <p>Title is required to set the name of the download file but can be hidden using the option below.</p>
1577
- </Tooltip.Content>
1578
- </Tooltip>
1579
- }
1580
- />
1581
1737
  <label className='checkbox'>
1582
1738
  <input
1583
1739
  type='checkbox'
1584
- checked={state.general.showTitle || false}
1740
+ checked={state.general.hideGeoColumnInTooltip || false}
1585
1741
  onChange={event => {
1586
- handleEditorChanges('showTitle', event.target.checked)
1742
+ handleEditorChanges('hideGeoColumnInTooltip', event.target.checked)
1587
1743
  }}
1588
1744
  />
1589
- <span className='edit-label'>Show Title</span>
1745
+ <span className='edit-label'>Hide Geography Column Name in Tooltip</span>
1590
1746
  </label>
1591
1747
  <TextField
1592
- value={general.superTitle || ''}
1593
- updateField={updateField}
1594
- section='general'
1595
- fieldName='superTitle'
1596
- label='Super Title'
1597
- tooltip={
1598
- <Tooltip style={{ textTransform: 'none' }}>
1599
- <Tooltip.Target>
1600
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1601
- </Tooltip.Target>
1602
- <Tooltip.Content>
1603
- <p>Super Title</p>
1604
- </Tooltip.Content>
1605
- </Tooltip>
1606
- }
1607
- />
1608
- <TextField
1609
- type='textarea'
1610
- value={general.introText}
1611
- updateField={updateField}
1612
- section='general'
1613
- fieldName='introText'
1614
- label='Intro Text'
1615
- tooltip={
1616
- <Tooltip style={{ textTransform: 'none' }}>
1617
- <Tooltip.Target>
1618
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1619
- </Tooltip.Target>
1620
- <Tooltip.Content>
1621
- <p>Intro Text</p>
1622
- </Tooltip.Content>
1623
- </Tooltip>
1624
- }
1625
- />
1626
- <TextField
1627
- type='textarea'
1628
- value={general.subtext}
1629
- updateField={updateField}
1748
+ value={state.general.geoLabelOverride}
1630
1749
  section='general'
1631
- fieldName='subtext'
1632
- label='Subtext'
1633
- tooltip={
1634
- <Tooltip style={{ textTransform: 'none' }}>
1635
- <Tooltip.Target>
1636
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1637
- </Tooltip.Target>
1638
- <Tooltip.Content>
1639
- <p>Enter supporting text to display below the data visualization, if applicable. The following HTML tags are supported: strong, em, sup, and sub.</p>
1640
- </Tooltip.Content>
1641
- </Tooltip>
1642
- }
1643
- />
1644
- <TextField
1645
- type='textarea'
1646
- value={general.footnotes}
1750
+ fieldName='geoLabelOverride'
1751
+ label='Geography Label'
1752
+ className='edit-label'
1647
1753
  updateField={updateField}
1648
- section='general'
1649
- fieldName='footnotes'
1650
- label='Footnotes'
1651
1754
  tooltip={
1652
1755
  <Tooltip style={{ textTransform: 'none' }}>
1653
1756
  <Tooltip.Target>
1654
1757
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1655
1758
  </Tooltip.Target>
1656
1759
  <Tooltip.Content>
1657
- <p>Footnotes</p>
1760
+ <p>Enter a geography label for use in tooltips.</p>
1658
1761
  </Tooltip.Content>
1659
1762
  </Tooltip>
1660
1763
  }
1661
1764
  />
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
- )}
1675
- {/* <label className="checkbox mt-4">
1676
- <input type="checkbox" checked={ state.general.showDownloadMediaButton } onChange={(event) => { handleEditorChanges("toggleDownloadMediaButton", event.target.checked) }} />
1677
- <span className="edit-label">Enable Media Download</span>
1678
- </label> */}
1679
- </AccordionItemPanel>
1680
- </AccordionItem>
1681
- <AccordionItem>
1682
- {' '}
1683
- {/* Columns */}
1684
- <AccordionItemHeading>
1685
- <AccordionItemButton>Columns</AccordionItemButton>
1686
- </AccordionItemHeading>
1687
- <AccordionItemPanel>
1765
+ </fieldset>
1766
+ {'navigation' !== state.general.type && (
1688
1767
  <fieldset className='primary-fieldset edit-block'>
1689
1768
  <label>
1690
1769
  <span className='edit-label column-heading'>
1691
- Geography
1770
+ Data Column
1692
1771
  <Tooltip style={{ textTransform: 'none' }}>
1693
1772
  <Tooltip.Target>
1694
1773
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1695
1774
  </Tooltip.Target>
1696
1775
  <Tooltip.Content>
1697
- <p>Select the source column containing the map location names or, for county-level maps, the FIPS codes.</p>
1776
+ <p>Select the source column containing the categorical or numeric values to be mapped.</p>
1698
1777
  </Tooltip.Content>
1699
1778
  </Tooltip>
1700
1779
  </span>
1701
1780
  <select
1702
- value={state.columns.geo ? state.columns.geo.name : columnsOptions[0]}
1781
+ value={state.columns.primary ? state.columns.primary.name : columnsOptions[0]}
1703
1782
  onChange={event => {
1704
- editColumn('geo', 'name', event.target.value)
1783
+ editColumn('primary', 'name', event.target.value)
1705
1784
  }}
1706
1785
  >
1707
1786
  {columnsOptions}
@@ -1710,19 +1789,19 @@ const EditorPanel = props => {
1710
1789
  <label className='checkbox'>
1711
1790
  <input
1712
1791
  type='checkbox'
1713
- checked={state.general.hideGeoColumnInTooltip || false}
1792
+ checked={state.general.hidePrimaryColumnInTooltip || false}
1714
1793
  onChange={event => {
1715
- handleEditorChanges('hideGeoColumnInTooltip', event.target.checked)
1794
+ handleEditorChanges('hidePrimaryColumnInTooltip', event.target.checked)
1716
1795
  }}
1717
1796
  />
1718
- <span className='edit-label'>Hide Geography Column Name in Tooltip</span>
1797
+ <span className='edit-label'>Hide Data Column Name in Tooltip</span>
1719
1798
  </label>
1720
1799
  <TextField
1721
- value={state.general.geoLabelOverride}
1722
- section='general'
1723
- fieldName='geoLabelOverride'
1724
- label='Geography Label'
1725
- className='edit-label'
1800
+ value={columns.primary.label}
1801
+ section='columns'
1802
+ subsection='primary'
1803
+ fieldName='label'
1804
+ label='Data Label'
1726
1805
  updateField={updateField}
1727
1806
  tooltip={
1728
1807
  <Tooltip style={{ textTransform: 'none' }}>
@@ -1730,1087 +1809,1045 @@ const EditorPanel = props => {
1730
1809
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1731
1810
  </Tooltip.Target>
1732
1811
  <Tooltip.Content>
1733
- <p>Enter a geography label for use in tooltips.</p>
1812
+ <p>Enter a data label for use in tooltips and the data table.</p>
1734
1813
  </Tooltip.Content>
1735
1814
  </Tooltip>
1736
1815
  }
1737
1816
  />
1817
+ <ul className='column-edit'>
1818
+ <li className='three-col'>
1819
+ <TextField value={columns.primary.prefix} section='columns' subsection='primary' fieldName='prefix' label='Prefix' updateField={updateField} />
1820
+ <TextField value={columns.primary.suffix} section='columns' subsection='primary' fieldName='suffix' label='Suffix' updateField={updateField} />
1821
+ <TextField type='number' value={columns.primary.roundToPlace} section='columns' subsection='primary' fieldName='roundToPlace' label='Round' updateField={updateField} min={0} />
1822
+ </li>
1823
+ <li>
1824
+ <label className='checkbox'>
1825
+ <input
1826
+ type='checkbox'
1827
+ checked={state.columns.primary.useCommas}
1828
+ onChange={event => {
1829
+ editColumn('primary', 'useCommas', event.target.checked)
1830
+ }}
1831
+ />
1832
+ <span className='edit-label'>Add Commas to Numbers</span>
1833
+ </label>
1834
+ </li>
1835
+ <li>
1836
+ <label className='checkbox'>
1837
+ <input
1838
+ type='checkbox'
1839
+ checked={state.columns.primary.dataTable || false}
1840
+ onChange={event => {
1841
+ editColumn('primary', 'dataTable', event.target.checked)
1842
+ }}
1843
+ />
1844
+ <span className='edit-label'>Display in Data Table</span>
1845
+ </label>
1846
+ </li>
1847
+ <li>
1848
+ <label className='checkbox'>
1849
+ <input
1850
+ type='checkbox'
1851
+ checked={state.columns.primary.tooltip || false}
1852
+ onChange={event => {
1853
+ editColumn('primary', 'tooltip', event.target.checked)
1854
+ }}
1855
+ />
1856
+ <span className='edit-label'>Display in Tooltips</span>
1857
+ </label>
1858
+ </li>
1859
+ </ul>
1738
1860
  </fieldset>
1739
- {'navigation' !== state.general.type && (
1740
- <fieldset className='primary-fieldset edit-block'>
1741
- <label>
1742
- <span className='edit-label column-heading'>
1743
- Data Column
1744
- <Tooltip style={{ textTransform: 'none' }}>
1745
- <Tooltip.Target>
1746
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1747
- </Tooltip.Target>
1748
- <Tooltip.Content>
1749
- <p>Select the source column containing the categorical or numeric values to be mapped.</p>
1750
- </Tooltip.Content>
1751
- </Tooltip>
1752
- </span>
1753
- <select
1754
- value={state.columns.primary ? state.columns.primary.name : columnsOptions[0]}
1755
- onChange={event => {
1756
- editColumn('primary', 'name', event.target.value)
1757
- }}
1758
- >
1759
- {columnsOptions}
1760
- </select>
1761
- </label>
1762
- <label className='checkbox'>
1763
- <input
1764
- type='checkbox'
1765
- checked={state.general.hidePrimaryColumnInTooltip || false}
1766
- onChange={event => {
1767
- handleEditorChanges('hidePrimaryColumnInTooltip', event.target.checked)
1768
- }}
1769
- />
1770
- <span className='edit-label'>Hide Data Column Name in Tooltip</span>
1771
- </label>
1772
- <TextField
1773
- value={columns.primary.label}
1774
- section='columns'
1775
- subsection='primary'
1776
- fieldName='label'
1777
- label='Data Label'
1778
- updateField={updateField}
1779
- tooltip={
1780
- <Tooltip style={{ textTransform: 'none' }}>
1781
- <Tooltip.Target>
1782
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1783
- </Tooltip.Target>
1784
- <Tooltip.Content>
1785
- <p>Enter a data label for use in tooltips and the data table.</p>
1786
- </Tooltip.Content>
1787
- </Tooltip>
1788
- }
1789
- />
1790
- <ul className='column-edit'>
1791
- <li className='three-col'>
1792
- <TextField value={columns.primary.prefix} section='columns' subsection='primary' fieldName='prefix' label='Prefix' updateField={updateField} />
1793
- <TextField value={columns.primary.suffix} section='columns' subsection='primary' fieldName='suffix' label='Suffix' updateField={updateField} />
1794
- <TextField type='number' value={columns.primary.roundToPlace} section='columns' subsection='primary' fieldName='roundToPlace' label='Round' updateField={updateField} min={0} />
1795
- </li>
1796
- <li>
1797
- <label className='checkbox'>
1798
- <input
1799
- type='checkbox'
1800
- checked={state.columns.primary.useCommas}
1801
- onChange={event => {
1802
- editColumn('primary', 'useCommas', event.target.checked)
1803
- }}
1804
- />
1805
- <span className='edit-label'>Add Commas to Numbers</span>
1806
- </label>
1807
- </li>
1808
- <li>
1809
- <label className='checkbox'>
1810
- <input
1811
- type='checkbox'
1812
- checked={state.columns.primary.dataTable || false}
1813
- onChange={event => {
1814
- editColumn('primary', 'dataTable', event.target.checked)
1815
- }}
1816
- />
1817
- <span className='edit-label'>Display in Data Table</span>
1818
- </label>
1819
- </li>
1820
- <li>
1821
- <label className='checkbox'>
1822
- <input
1823
- type='checkbox'
1824
- checked={state.columns.primary.tooltip || false}
1825
- onChange={event => {
1826
- editColumn('primary', 'tooltip', event.target.checked)
1827
- }}
1828
- />
1829
- <span className='edit-label'>Display in Tooltips</span>
1830
- </label>
1831
- </li>
1832
- </ul>
1833
- </fieldset>
1834
- )}
1861
+ )}
1835
1862
 
1836
- {state.general.type === 'bubble' && state.legend.type === 'category' && (
1837
- <fieldset className='primary-fieldset edit-block'>
1838
- <label>
1839
- <span className='edit-label column-heading'>
1840
- Category Column
1841
- <Tooltip style={{ textTransform: 'none' }}>
1842
- <Tooltip.Target>
1843
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1844
- </Tooltip.Target>
1845
- <Tooltip.Content>
1846
- <p>Select the source column containing the categorical bubble values to be mapped.</p>
1847
- </Tooltip.Content>
1848
- </Tooltip>
1849
- </span>
1850
- <select
1851
- value={state.columns.categorical ? state.columns.categorical.name : columnsOptions[0]}
1852
- onChange={event => {
1853
- editColumn('categorical', 'name', event.target.value)
1854
- }}
1855
- >
1856
- {columnsOptions}
1857
- </select>
1858
- </label>
1859
- </fieldset>
1860
- )}
1861
- {('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && (
1862
- <>
1863
- <label>Latitude Column</label>
1864
- <select
1865
- value={state.columns.latitude.name ? state.columns.latitude.name : ''}
1866
- onChange={e => {
1867
- editColumn('latitude', 'name', e.target.value)
1868
- }}
1869
- >
1870
- {columnsOptions}
1871
- </select>
1872
- <label>Longitude Column</label>
1863
+ {state.general.type === 'bubble' && state.legend.type === 'category' && (
1864
+ <fieldset className='primary-fieldset edit-block'>
1865
+ <label>
1866
+ <span className='edit-label column-heading'>
1867
+ Category Column
1868
+ <Tooltip style={{ textTransform: 'none' }}>
1869
+ <Tooltip.Target>
1870
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1871
+ </Tooltip.Target>
1872
+ <Tooltip.Content>
1873
+ <p>Select the source column containing the categorical bubble values to be mapped.</p>
1874
+ </Tooltip.Content>
1875
+ </Tooltip>
1876
+ </span>
1873
1877
  <select
1874
- value={state.columns.longitude.name ? state.columns.longitude.name : ''}
1875
- onChange={e => {
1876
- editColumn('longitude', 'name', e.target.value)
1878
+ value={state.columns.categorical ? state.columns.categorical.name : columnsOptions[0]}
1879
+ onChange={event => {
1880
+ editColumn('categorical', 'name', event.target.value)
1877
1881
  }}
1878
1882
  >
1879
1883
  {columnsOptions}
1880
1884
  </select>
1881
- </>
1882
- )}
1883
-
1884
- {'navigation' !== state.general.type && (
1885
- <fieldset className='primary-fieldset edit-block'>
1886
- <label>
1887
- <span className='edit-label'>
1888
- Special Classes
1889
- <Tooltip style={{ textTransform: 'none' }}>
1890
- <Tooltip.Target>
1891
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1892
- </Tooltip.Target>
1893
- <Tooltip.Content>
1894
- <p>For secondary values such as "NA", the system can automatically color-code them in shades of gray, one shade for each special class.</p>
1895
- </Tooltip.Content>
1896
- </Tooltip>
1897
- </span>
1898
- </label>
1899
- {specialClasses.map((specialClass, i) => (
1900
- <div className='edit-block' key={`special-class-${i}`}>
1901
- <button
1902
- className='remove-column'
1903
- onClick={e => {
1904
- e.preventDefault()
1905
- editColumn('primary', 'specialClassDelete', i)
1906
- }}
1907
- >
1908
- Remove
1909
- </button>
1910
- <p>Special Class {i + 1}</p>
1911
- <label>
1912
- <span className='edit-label column-heading'>Data Key</span>
1913
- <select
1914
- value={specialClass.key}
1915
- onChange={e => {
1916
- editColumn('primary', 'specialClassEdit', { prop: 'key', index: i, value: e.target.value })
1917
- }}
1918
- >
1919
- {columnsOptions}
1920
- </select>
1921
- </label>
1922
- <label>
1923
- <span className='edit-label column-heading'>Value</span>
1924
- <select
1925
- value={specialClass.value}
1926
- onChange={e => {
1927
- editColumn('primary', 'specialClassEdit', { prop: 'value', index: i, value: e.target.value })
1928
- }}
1929
- >
1930
- <option value=''>- Select Value -</option>
1931
- {columnsByKey[specialClass.key] && columnsByKey[specialClass.key].sort().map(option => <option key={`special-class-value-option-${i}-${option}`}>{option}</option>)}
1932
- </select>
1933
- </label>
1934
- <label>
1935
- <span className='edit-label column-heading'>Label</span>
1936
- <input
1937
- type='text'
1938
- value={specialClass.label}
1939
- onChange={e => {
1940
- editColumn('primary', 'specialClassEdit', { prop: 'label', index: i, value: e.target.value })
1941
- }}
1942
- />
1943
- </label>
1944
- </div>
1945
- ))}
1946
- <button
1947
- className='btn full-width'
1948
- onClick={e => {
1949
- e.preventDefault()
1950
- editColumn('primary', 'specialClassAdd', {})
1951
- }}
1952
- >
1953
- Add Special Class
1954
- </button>
1955
- </fieldset>
1956
- )}
1957
-
1958
- <label className='edit-block navigate column-heading'>
1959
- <span className='edit-label column-heading'>
1960
- Navigation
1961
- <Tooltip style={{ textTransform: 'none' }}>
1962
- <Tooltip.Target>
1963
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1964
- </Tooltip.Target>
1965
- <Tooltip.Content>
1966
- <p>To provide end users with navigation functionality, select the source column containing the navigation URLs.</p>
1967
- </Tooltip.Content>
1968
- </Tooltip>
1969
- </span>
1885
+ </label>
1886
+ </fieldset>
1887
+ )}
1888
+ {('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && (
1889
+ <>
1890
+ <label>Latitude Column</label>
1970
1891
  <select
1971
- value={state.columns.navigate ? state.columns.navigate.name : columnsOptions[0]}
1972
- onChange={event => {
1973
- editColumn('navigate', 'name', event.target.value)
1892
+ value={state.columns.latitude.name ? state.columns.latitude.name : ''}
1893
+ onChange={e => {
1894
+ editColumn('latitude', 'name', e.target.value)
1974
1895
  }}
1975
1896
  >
1976
1897
  {columnsOptions}
1977
1898
  </select>
1978
- </label>
1979
- {'navigation' !== state.general.type && (
1980
- <fieldset className='primary-fieldset edit-block'>
1981
- <label>
1982
- <span className='edit-label'>
1983
- Additional Columns
1984
- <Tooltip style={{ textTransform: 'none' }}>
1985
- <Tooltip.Target>
1986
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1987
- </Tooltip.Target>
1988
- <Tooltip.Content>
1989
- <p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
1990
- </Tooltip.Content>
1991
- </Tooltip>
1992
- </span>
1993
- </label>
1994
- {additionalColumns.map(val => (
1995
- <fieldset className='edit-block' key={val}>
1996
- <button
1997
- className='remove-column'
1998
- onClick={event => {
1999
- event.preventDefault()
2000
- removeAdditionalColumn(val)
2001
- }}
2002
- >
2003
- Remove
2004
- </button>
2005
- <label>
2006
- <span className='edit-label column-heading'>Column</span>
2007
- <select
2008
- value={state.columns[val] ? state.columns[val].name : columnsOptions[0]}
2009
- onChange={event => {
2010
- editColumn(val, 'name', event.target.value)
2011
- }}
2012
- >
2013
- {columnsOptions}
2014
- </select>
2015
- </label>
2016
- <TextField value={columns[val].label} section='columns' subsection={val} fieldName='label' label='Label' updateField={updateField} />
2017
- <ul className='column-edit'>
2018
- <li className='three-col'>
2019
- <TextField value={columns[val].prefix} section='columns' subsection={val} fieldName='prefix' label='Prefix' updateField={updateField} />
2020
- <TextField value={columns[val].suffix} section='columns' subsection={val} fieldName='suffix' label='Suffix' updateField={updateField} />
2021
- <TextField type='number' value={columns[val].roundToPlace} section='columns' subsection={val} fieldName='roundToPlace' label='Round' updateField={updateField} />
2022
- </li>
2023
- <li>
2024
- <label className='checkbox'>
2025
- <input
2026
- type='checkbox'
2027
- checked={state.columns[val].useCommas}
2028
- onChange={event => {
2029
- editColumn(val, 'useCommas', event.target.checked)
2030
- }}
2031
- />
2032
- <span className='edit-label'>Add Commas to Numbers</span>
2033
- </label>
2034
- </li>
2035
- <li>
2036
- <label className='checkbox'>
2037
- <input
2038
- type='checkbox'
2039
- checked={state.columns[val].dataTable}
2040
- onChange={event => {
2041
- editColumn(val, 'dataTable', event.target.checked)
2042
- }}
2043
- />
2044
- <span className='edit-label'>Display in Data Table</span>
2045
- </label>
2046
- </li>
2047
- <li>
2048
- <label className='checkbox'>
2049
- <input
2050
- type='checkbox'
2051
- checked={state.columns[val].tooltip}
2052
- onChange={event => {
2053
- editColumn(val, 'tooltip', event.target.checked)
2054
- }}
2055
- />
2056
- <span className='edit-label'>Display in Tooltips</span>
2057
- </label>
2058
- </li>
2059
- </ul>
2060
- </fieldset>
2061
- ))}
2062
- <button
2063
- className={'btn full-width'}
2064
- onClick={event => {
2065
- event.preventDefault()
2066
- addAdditionalColumn(additionalColumns.length + 1)
2067
- }}
2068
- >
2069
- Add Column
2070
- </button>
2071
- </fieldset>
2072
- )}
2073
- {'category' === state.legend.type && (
2074
- <fieldset className='primary-fieldset edit-block'>
2075
- <label>
2076
- <span className='edit-label'>
2077
- Additional Category
2078
- <Tooltip style={{ textTransform: 'none' }}>
2079
- <Tooltip.Target>
2080
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2081
- </Tooltip.Target>
2082
- <Tooltip.Content>
2083
- <p>You can provide additional categories to ensure they appear in the legend</p>
2084
- </Tooltip.Content>
2085
- </Tooltip>
2086
- </span>
2087
- </label>
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
- ))}
2118
- <button
2119
- className={'btn full-width'}
2120
- onClick={event => {
2121
- event.preventDefault()
2122
- const updatedAdditionaCategories = [...(state.legend.additionalCategories || [])]
2123
- updatedAdditionaCategories.push('')
2124
- updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
2125
- }}
2126
- >
2127
- Add Category
2128
- </button>
2129
- </fieldset>
2130
- )}
2131
- </AccordionItemPanel>
2132
- </AccordionItem>{' '}
2133
- {/* Columns */}
2134
- {'navigation' !== state.general.type && (
2135
- <AccordionItem>
2136
- {' '}
2137
- {/* Legend */}
2138
- <AccordionItemHeading>
2139
- <AccordionItemButton>Legend</AccordionItemButton>
2140
- </AccordionItemHeading>
2141
- <AccordionItemPanel>
2142
- {(state.legend.type === 'equalnumber' || state.legend.type === 'equalinterval') && (
2143
- <label>
2144
- <span className='edit-label'>Legend Type</span>
2145
- <select
2146
- value={legend.type}
2147
- onChange={event => {
2148
- handleEditorChanges('legendType', event.target.value)
2149
- }}
2150
- >
2151
- <option value='equalnumber'>Equal Number (Quantiles)</option>
2152
- <option value='equalinterval'>Equal Interval</option>
2153
- </select>
2154
- </label>
2155
- )}
2156
- {'navigation' !== state.general.type && (
2157
- <label className='checkbox'>
2158
- <input
2159
- type='checkbox'
2160
- checked={state.general.showSidebar || false}
2161
- onChange={event => {
2162
- handleEditorChanges('showSidebar', event.target.checked)
2163
- }}
2164
- />
2165
- <span className='edit-label'>Show Legend</span>
2166
- </label>
2167
- )}
2168
- {'navigation' !== state.general.type && (
2169
- <label>
2170
- <span className='edit-label'>Legend Position</span>
2171
- <select
2172
- value={legend.position || false}
2173
- onChange={event => {
2174
- handleEditorChanges('sidebarPosition', event.target.value)
2175
- }}
2176
- >
2177
- <option value='side'>Side</option>
2178
- <option value='bottom'>Bottom</option>
2179
- </select>
2180
- </label>
2181
- )}
2182
- {'side' === legend.position && (
2183
- <label className='checkbox'>
2184
- <input
2185
- type='checkbox'
2186
- checked={legend.singleColumn}
2187
- onChange={event => {
2188
- handleEditorChanges('singleColumnLegend', event.target.checked)
2189
- }}
2190
- />
2191
- <span className='edit-label'>Single Column Legend</span>
2192
- </label>
2193
- )}
2194
- {'bottom' === legend.position && (
2195
- <label className='checkbox'>
2196
- <input
2197
- type='checkbox'
2198
- checked={legend.singleRow}
2199
- onChange={event => {
2200
- handleEditorChanges('singleRowLegend', event.target.checked)
2201
- }}
2202
- />
2203
- <span className='edit-label'>Single Row Legend</span>
2204
- </label>
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> */}
2218
- {'category' !== legend.type && (
2219
- <label className='checkbox'>
2220
- <input type='checkbox' checked={legend.separateZero || false} onChange={event => handleEditorChanges('separateZero', event.target.checked)} />
2221
- <span className='edit-label'>
2222
- Separate Zero
2223
- <Tooltip style={{ textTransform: 'none' }}>
2224
- <Tooltip.Target>
2225
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2226
- </Tooltip.Target>
2227
- <Tooltip.Content>
2228
- <p>For numeric data, you can separate the zero value as its own data class.</p>
2229
- </Tooltip.Content>
2230
- </Tooltip>
2231
- </span>
2232
- </label>
2233
- )}
2234
- {/* Temp Checkbox */}
2235
- {state.legend.type === 'equalnumber' && (
2236
- <label className='checkbox mt-4'>
2237
- <input
2238
- type='checkbox'
2239
- checked={state.general.equalNumberOptIn}
2240
- onChange={event => {
2241
- handleEditorChanges('showEqualNumber', event.target.checked)
2242
- }}
2243
- />
2244
- <span className='edit-label'>Use new quantile legend</span>
1899
+ <label>Longitude Column</label>
1900
+ <select
1901
+ value={state.columns.longitude.name ? state.columns.longitude.name : ''}
1902
+ onChange={e => {
1903
+ editColumn('longitude', 'name', e.target.value)
1904
+ }}
1905
+ >
1906
+ {columnsOptions}
1907
+ </select>
1908
+ </>
1909
+ )}
1910
+
1911
+ {'navigation' !== state.general.type && (
1912
+ <fieldset className='primary-fieldset edit-block'>
1913
+ <label>
1914
+ <span className='edit-label'>
1915
+ Special Classes
2245
1916
  <Tooltip style={{ textTransform: 'none' }}>
2246
1917
  <Tooltip.Target>
2247
1918
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2248
1919
  </Tooltip.Target>
2249
1920
  <Tooltip.Content>
2250
- <p>This prevents numbers from being used in more than one category (ie. 0-1, 1-2, 2-3) </p>
1921
+ <p>For secondary values such as "NA", the system can automatically color-code them in shades of gray, one shade for each special class.</p>
2251
1922
  </Tooltip.Content>
2252
1923
  </Tooltip>
2253
- </label>
2254
- )}
2255
- {'category' !== legend.type && (
2256
- <label>
2257
- <span className='edit-label'>
2258
- Number of Items
2259
- <Tooltip style={{ textTransform: 'none' }}>
2260
- <Tooltip.Target>
2261
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2262
- </Tooltip.Target>
2263
- <Tooltip.Content>
2264
- <p>For numeric maps, select the number of data classes. Do not include designated special classes.</p>
2265
- </Tooltip.Content>
2266
- </Tooltip>
2267
- </span>
2268
- <select
2269
- value={legend.numberOfItems}
2270
- onChange={event => {
2271
- handleEditorChanges('legendNumber', event.target.value)
1924
+ </span>
1925
+ </label>
1926
+ {specialClasses.map((specialClass, i) => (
1927
+ <div className='edit-block' key={`special-class-${i}`}>
1928
+ <button
1929
+ className='remove-column'
1930
+ onClick={e => {
1931
+ e.preventDefault()
1932
+ editColumn('primary', 'specialClassDelete', i)
2272
1933
  }}
2273
1934
  >
2274
- {[...Array(numberOfItemsLimit).keys()].map(num => {
2275
- return (
2276
- <option value={num + 1} key={num + 1}>
2277
- {num + 1}
2278
- </option>
2279
- )
2280
- })}
2281
- </select>
2282
- </label>
2283
- )}
2284
- {'category' === legend.type && (
2285
- <React.Fragment>
1935
+ Remove
1936
+ </button>
1937
+ <p>Special Class {i + 1}</p>
2286
1938
  <label>
2287
- <span className='edit-label'>
2288
- Category Order
2289
- <Tooltip style={{ textTransform: 'none' }}>
2290
- <Tooltip.Target>
2291
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2292
- </Tooltip.Target>
2293
- <Tooltip.Content>
2294
- <p>Drag map categories into preferred legend order. </p>
2295
- </Tooltip.Content>
2296
- </Tooltip>
2297
- </span>
1939
+ <span className='edit-label column-heading'>Data Key</span>
1940
+ <select
1941
+ value={specialClass.key}
1942
+ onChange={e => {
1943
+ editColumn('primary', 'specialClassEdit', { prop: 'key', index: i, value: e.target.value })
1944
+ }}
1945
+ >
1946
+ {columnsOptions}
1947
+ </select>
2298
1948
  </label>
2299
- {/* TODO: Swap out this drag and drop library back to something simpler. I had to remove the old one because it hadn't been updated and wouldn't work with Webpack 5. This is overkill for our needs. */}
2300
- <DragDropContext onDragEnd={({ source, destination }) => categoryMove(source.index, destination.index)}>
2301
- <Droppable droppableId='category_order'>
2302
- {provided => (
2303
- <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef}>
2304
- <CategoryList />
2305
- {provided.placeholder}
2306
- </ul>
2307
- )}
2308
- </Droppable>
2309
- </DragDropContext>
2310
- {state.legend.categoryValuesOrder && state.legend.categoryValuesOrder.length >= 10 && (
2311
- <section className='error-box my-2'>
2312
- <div>
2313
- <strong className='pt-1'>Warning</strong>
2314
- <p>The maximum number of categorical legend items is 10. If your data has more than 10 categories your map will not display properly.</p>
2315
- </div>
2316
- </section>
2317
- )}
2318
- </React.Fragment>
2319
- )}
2320
- <TextField value={legend.title} updateField={updateField} section='legend' fieldName='title' label='Legend Title' placeholder='Legend Title' />
2321
- {false === legend.dynamicDescription && <TextField type='textarea' value={legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />}
2322
- {true === legend.dynamicDescription && (
2323
- <React.Fragment>
2324
1949
  <label>
2325
- <span>Legend Description</span>
2326
- <span className='subtext'>For {displayFilterLegendValue(activeFilterValueForDescription)}</span>
2327
- <DynamicDesc value={legend.descriptions[String(activeFilterValueForDescription)]} />
1950
+ <span className='edit-label column-heading'>Value</span>
1951
+ <select
1952
+ value={specialClass.value}
1953
+ onChange={e => {
1954
+ editColumn('primary', 'specialClassEdit', { prop: 'value', index: i, value: e.target.value })
1955
+ }}
1956
+ >
1957
+ <option value=''>- Select Value -</option>
1958
+ {columnsByKey[specialClass.key] && columnsByKey[specialClass.key].sort().map(option => <option key={`special-class-value-option-${i}-${option}`}>{option}</option>)}
1959
+ </select>
2328
1960
  </label>
2329
1961
  <label>
1962
+ <span className='edit-label column-heading'>Label</span>
1963
+ <input
1964
+ type='text'
1965
+ value={specialClass.label}
1966
+ onChange={e => {
1967
+ editColumn('primary', 'specialClassEdit', { prop: 'label', index: i, value: e.target.value })
1968
+ }}
1969
+ />
1970
+ </label>
1971
+ </div>
1972
+ ))}
1973
+ <button
1974
+ className='btn full-width'
1975
+ onClick={e => {
1976
+ e.preventDefault()
1977
+ editColumn('primary', 'specialClassAdd', {})
1978
+ }}
1979
+ >
1980
+ Add Special Class
1981
+ </button>
1982
+ </fieldset>
1983
+ )}
1984
+
1985
+ <label className='edit-block navigate column-heading'>
1986
+ <span className='edit-label column-heading'>
1987
+ Navigation
1988
+ <Tooltip style={{ textTransform: 'none' }}>
1989
+ <Tooltip.Target>
1990
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1991
+ </Tooltip.Target>
1992
+ <Tooltip.Content>
1993
+ <p>To provide end users with navigation functionality, select the source column containing the navigation URLs.</p>
1994
+ </Tooltip.Content>
1995
+ </Tooltip>
1996
+ </span>
1997
+ <select
1998
+ value={state.columns.navigate ? state.columns.navigate.name : columnsOptions[0]}
1999
+ onChange={event => {
2000
+ editColumn('navigate', 'name', event.target.value)
2001
+ }}
2002
+ >
2003
+ {columnsOptions}
2004
+ </select>
2005
+ </label>
2006
+ {'navigation' !== state.general.type && (
2007
+ <fieldset className='primary-fieldset edit-block'>
2008
+ <label>
2009
+ <span className='edit-label'>
2010
+ Additional Columns
2011
+ <Tooltip style={{ textTransform: 'none' }}>
2012
+ <Tooltip.Target>
2013
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2014
+ </Tooltip.Target>
2015
+ <Tooltip.Content>
2016
+ <p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
2017
+ </Tooltip.Content>
2018
+ </Tooltip>
2019
+ </span>
2020
+ </label>
2021
+ {additionalColumns.map(val => (
2022
+ <fieldset className='edit-block' key={val}>
2023
+ <button
2024
+ className='remove-column'
2025
+ onClick={event => {
2026
+ event.preventDefault()
2027
+ removeAdditionalColumn(val)
2028
+ }}
2029
+ >
2030
+ Remove
2031
+ </button>
2032
+ <label>
2033
+ <span className='edit-label column-heading'>Column</span>
2330
2034
  <select
2331
- value={String(activeFilterValueForDescription)}
2035
+ value={state.columns[val] ? state.columns[val].name : columnsOptions[0]}
2332
2036
  onChange={event => {
2333
- handleEditorChanges('changeActiveFilterValue', event.target.value)
2037
+ editColumn(val, 'name', event.target.value)
2334
2038
  }}
2335
2039
  >
2336
- {filterValueOptionList.map((arr, i) => {
2337
- return (
2338
- <option value={arr} key={i}>
2339
- {displayFilterLegendValue(arr)}
2340
- </option>
2341
- )
2342
- })}
2040
+ {columnsOptions}
2343
2041
  </select>
2344
2042
  </label>
2345
- </React.Fragment>
2346
- )}
2347
- {filtersJSX.length > 0 && (
2348
- <label className='checkbox'>
2349
- <input
2350
- type='checkbox'
2351
- checked={legend.dynamicDescription}
2352
- onChange={() => {
2353
- handleEditorChanges('dynamicDescription', filterValueOptionList[0])
2354
- }}
2355
- />
2356
- <span className='edit-label'>
2357
- Dynamic Legend Description
2358
- <Tooltip style={{ textTransform: 'none' }}>
2359
- <Tooltip.Target>
2360
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2361
- </Tooltip.Target>
2362
- <Tooltip.Content>
2363
- <p>Check this option if the map has multiple filter controls and you want to specify a description for each filter selection.</p>
2364
- </Tooltip.Content>
2365
- </Tooltip>
2366
- </span>
2367
- </label>
2368
- )}
2369
- {(filtersJSX.length > 0 || state.general.type === 'bubble' || state.general.geoType === 'us') && (
2370
- <label className='checkbox'>
2371
- <input type='checkbox' checked={legend.unified} onChange={event => handleEditorChanges('unifiedLegend', event.target.checked)} />
2372
- <span className='edit-label'>
2373
- Unified Legend
2374
- <Tooltip style={{ textTransform: 'none' }}>
2375
- <Tooltip.Target>
2376
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2377
- </Tooltip.Target>
2378
- <Tooltip.Content>
2379
- <p>
2380
- For a map with filters, check this option if you want the high and low values in the legend to be based on <em>all</em> mapped values.
2381
- </p>
2382
- </Tooltip.Content>
2383
- </Tooltip>
2384
- </span>
2385
- </label>
2386
- )}
2387
- </AccordionItemPanel>
2388
- </AccordionItem>
2389
- )}
2390
- {'navigation' !== state.general.type && (
2391
- <AccordionItem>
2392
- {' '}
2393
- {/* Filters */}
2394
- <AccordionItemHeading>
2395
- <AccordionItemButton>Filters</AccordionItemButton>
2396
- </AccordionItemHeading>
2397
- <AccordionItemPanel>
2398
- {filtersJSX.length > 0 ? <MapFilters /> : <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
2043
+ <TextField value={columns[val].label} section='columns' subsection={val} fieldName='label' label='Label' updateField={updateField} />
2044
+ <ul className='column-edit'>
2045
+ <li className='three-col'>
2046
+ <TextField value={columns[val].prefix} section='columns' subsection={val} fieldName='prefix' label='Prefix' updateField={updateField} />
2047
+ <TextField value={columns[val].suffix} section='columns' subsection={val} fieldName='suffix' label='Suffix' updateField={updateField} />
2048
+ <TextField type='number' value={columns[val].roundToPlace} section='columns' subsection={val} fieldName='roundToPlace' label='Round' updateField={updateField} />
2049
+ </li>
2050
+ <li>
2051
+ <label className='checkbox'>
2052
+ <input
2053
+ type='checkbox'
2054
+ checked={state.columns[val].useCommas}
2055
+ onChange={event => {
2056
+ editColumn(val, 'useCommas', event.target.checked)
2057
+ }}
2058
+ />
2059
+ <span className='edit-label'>Add Commas to Numbers</span>
2060
+ </label>
2061
+ </li>
2062
+ <li>
2063
+ <label className='checkbox'>
2064
+ <input
2065
+ type='checkbox'
2066
+ checked={state.columns[val].dataTable}
2067
+ onChange={event => {
2068
+ editColumn(val, 'dataTable', event.target.checked)
2069
+ }}
2070
+ />
2071
+ <span className='edit-label'>Display in Data Table</span>
2072
+ </label>
2073
+ </li>
2074
+ <li>
2075
+ <label className='checkbox'>
2076
+ <input
2077
+ type='checkbox'
2078
+ checked={state.columns[val].tooltip}
2079
+ onChange={event => {
2080
+ editColumn(val, 'tooltip', event.target.checked)
2081
+ }}
2082
+ />
2083
+ <span className='edit-label'>Display in Tooltips</span>
2084
+ </label>
2085
+ </li>
2086
+ </ul>
2087
+ </fieldset>
2088
+ ))}
2399
2089
  <button
2400
2090
  className={'btn full-width'}
2401
2091
  onClick={event => {
2402
2092
  event.preventDefault()
2403
- changeFilter(null, 'addNew')
2093
+ addAdditionalColumn(additionalColumns.length + 1)
2404
2094
  }}
2405
2095
  >
2406
- Add Filter
2096
+ Add Column
2407
2097
  </button>
2408
- </AccordionItemPanel>
2409
- </AccordionItem>
2410
- )}
2411
- {'navigation' !== state.general.type && (
2412
- <AccordionItem>
2413
- {' '}
2414
- {/* Data Table */}
2415
- <AccordionItemHeading>
2416
- <AccordionItemButton>Data Table</AccordionItemButton>
2417
- </AccordionItemHeading>
2418
- <AccordionItemPanel>
2419
- <TextField
2420
- value={dataTable.title}
2421
- updateField={updateField}
2422
- section='dataTable'
2423
- fieldName='title'
2424
- id='dataTableTitle'
2425
- label='Data Table Title'
2426
- placeholder='Data Table'
2427
- tooltip={
2098
+ </fieldset>
2099
+ )}
2100
+ {'category' === state.legend.type && (
2101
+ <fieldset className='primary-fieldset edit-block'>
2102
+ <label>
2103
+ <span className='edit-label'>
2104
+ Additional Category
2428
2105
  <Tooltip style={{ textTransform: 'none' }}>
2429
2106
  <Tooltip.Target>
2430
2107
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2431
2108
  </Tooltip.Target>
2432
2109
  <Tooltip.Content>
2433
- <p>Label is required for Data Table for 508 Compliance</p>
2110
+ <p>You can provide additional categories to ensure they appear in the legend</p>
2434
2111
  </Tooltip.Content>
2435
2112
  </Tooltip>
2436
- }
2437
- />
2113
+ </span>
2114
+ </label>
2115
+ {state.legend.additionalCategories &&
2116
+ state.legend.additionalCategories.map((val, i) => (
2117
+ <fieldset className='edit-block' key={val}>
2118
+ <button
2119
+ className='remove-column'
2120
+ onClick={event => {
2121
+ event.preventDefault()
2122
+ const updatedAdditionaCategories = [...state.legend.additionalCategories]
2123
+ updatedAdditionaCategories.splice(i, 1)
2124
+ updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
2125
+ }}
2126
+ >
2127
+ Remove
2128
+ </button>
2129
+ <label>
2130
+ <span className='edit-label column-heading'>Category</span>
2131
+ <TextField
2132
+ value={val}
2133
+ section='legend'
2134
+ subsection={null}
2135
+ fieldName='additionalCategories'
2136
+ updateField={(section, subsection, fieldName, value) => {
2137
+ const updatedAdditionaCategories = [...state.legend.additionalCategories]
2138
+ updatedAdditionaCategories[i] = value
2139
+ updateField(section, subsection, fieldName, updatedAdditionaCategories)
2140
+ }}
2141
+ />
2142
+ </label>
2143
+ </fieldset>
2144
+ ))}
2145
+ <button
2146
+ className={'btn full-width'}
2147
+ onClick={event => {
2148
+ event.preventDefault()
2149
+ const updatedAdditionaCategories = [...(state.legend.additionalCategories || [])]
2150
+ updatedAdditionaCategories.push('')
2151
+ updateField('legend', null, 'additionalCategories', updatedAdditionaCategories)
2152
+ }}
2153
+ >
2154
+ Add Category
2155
+ </button>
2156
+ </fieldset>
2157
+ )}
2158
+ </AccordionItemPanel>
2159
+ </AccordionItem>{' '}
2160
+ {/* Columns */}
2161
+ {'navigation' !== state.general.type && (
2162
+ <AccordionItem>
2163
+ {' '}
2164
+ {/* Legend */}
2165
+ <AccordionItemHeading>
2166
+ <AccordionItemButton>Legend</AccordionItemButton>
2167
+ </AccordionItemHeading>
2168
+ <AccordionItemPanel>
2169
+ {(state.legend.type === 'equalnumber' || state.legend.type === 'equalinterval') && (
2170
+ <label>
2171
+ <span className='edit-label'>Legend Type</span>
2172
+ <select
2173
+ value={legend.type}
2174
+ onChange={event => {
2175
+ handleEditorChanges('legendType', event.target.value)
2176
+ }}
2177
+ >
2178
+ <option value='equalnumber'>Equal Number (Quantiles)</option>
2179
+ <option value='equalinterval'>Equal Interval</option>
2180
+ </select>
2181
+ </label>
2182
+ )}
2183
+ {'navigation' !== state.general.type && (
2438
2184
  <label className='checkbox'>
2439
2185
  <input
2440
2186
  type='checkbox'
2441
- checked={state.dataTable.forceDisplay !== undefined ? state.dataTable.forceDisplay : !isDashboard}
2187
+ checked={state.general.showSidebar || false}
2442
2188
  onChange={event => {
2443
- handleEditorChanges('showDataTable', event.target.checked)
2189
+ handleEditorChanges('showSidebar', event.target.checked)
2444
2190
  }}
2445
2191
  />
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>
2192
+ <span className='edit-label'>Show Legend</span>
2457
2193
  </label>
2458
- <TextField
2459
- value={dataTable.indexLabel || ''}
2460
- updateField={updateField}
2461
- section='dataTable'
2462
- fieldName='indexLabel'
2463
- label='Index Column Header'
2464
- placeholder='Location'
2465
- tooltip={
2466
- <Tooltip style={{ textTransform: 'none' }}>
2467
- <Tooltip.Target>
2468
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2469
- </Tooltip.Target>
2470
- <Tooltip.Content>
2471
- <p>To comply with 508 standards, if the first column in the data table has no header, enter a brief one here.</p>
2472
- </Tooltip.Content>
2473
- </Tooltip>
2474
- }
2475
- />
2476
- <TextField
2477
- value={dataTable.caption}
2478
- updateField={updateField}
2479
- section='dataTable'
2480
- fieldName='caption'
2481
- label='Data Table Caption'
2482
- placeholder='Data Table'
2483
- tooltip={
2484
- <Tooltip style={{ textTransform: 'none' }}>
2485
- <Tooltip.Target>
2486
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2487
- </Tooltip.Target>
2488
- <Tooltip.Content>
2489
- <p>Enter a description of the data table to be read by screen readers.</p>
2490
- </Tooltip.Content>
2491
- </Tooltip>
2492
- }
2493
- type='textarea'
2494
- />
2194
+ )}
2195
+ {'navigation' !== state.general.type && (
2196
+ <label>
2197
+ <span className='edit-label'>Legend Position</span>
2198
+ <select
2199
+ value={legend.position || false}
2200
+ onChange={event => {
2201
+ handleEditorChanges('sidebarPosition', event.target.value)
2202
+ }}
2203
+ >
2204
+ <option value='side'>Side</option>
2205
+ <option value='bottom'>Bottom</option>
2206
+ </select>
2207
+ </label>
2208
+ )}
2209
+ {'side' === legend.position && (
2495
2210
  <label className='checkbox'>
2496
2211
  <input
2497
2212
  type='checkbox'
2498
- checked={state.dataTable.limitHeight}
2213
+ checked={legend.singleColumn}
2499
2214
  onChange={event => {
2500
- handleEditorChanges('limitDataTableHeight', event.target.checked)
2215
+ handleEditorChanges('singleColumnLegend', event.target.checked)
2501
2216
  }}
2502
2217
  />
2503
- <span className='edit-label'>Limit Table Height</span>
2218
+ <span className='edit-label'>Single Column Legend</span>
2504
2219
  </label>
2505
- {state.dataTable.limitHeight && <TextField value={dataTable.height} updateField={updateField} section='dataTable' fieldName='height' label='Data Table Height' placeholder='Height(px)' type='number' min='0' max='500' />}
2220
+ )}
2221
+ {'bottom' === legend.position && (
2506
2222
  <label className='checkbox'>
2507
2223
  <input
2508
2224
  type='checkbox'
2509
- checked={state.general.expandDataTable || false}
2225
+ checked={legend.singleRow}
2510
2226
  onChange={event => {
2511
- handleEditorChanges('expandDataTable', event.target.checked)
2227
+ handleEditorChanges('singleRowLegend', event.target.checked)
2512
2228
  }}
2513
2229
  />
2514
- <span className='edit-label'>Map loads with data table expanded</span>
2230
+ <span className='edit-label'>Single Row Legend</span>
2515
2231
  </label>
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
- )}
2232
+ )}
2233
+ {/* always show */}
2234
+ {
2540
2235
  <label className='checkbox'>
2541
2236
  <input
2542
2237
  type='checkbox'
2543
- checked={state.general.showDownloadButton}
2238
+ checked={legend.showSpecialClassesLast}
2544
2239
  onChange={event => {
2545
- handleEditorChanges('toggleDownloadButton', event.target.checked)
2240
+ handleEditorChanges('legendShowSpecialClassesLast', event.target.checked)
2546
2241
  }}
2547
2242
  />
2548
- <span className='edit-label'>Show Download CSV Link</span>
2243
+ <span className='edit-label'>Show Special Classes Last</span>
2244
+ </label>
2245
+ }
2246
+ {'category' !== legend.type && (
2247
+ <label className='checkbox'>
2248
+ <input type='checkbox' checked={legend.separateZero || false} onChange={event => handleEditorChanges('separateZero', event.target.checked)} />
2249
+ <span className='edit-label column-heading'>
2250
+ Separate Zero
2251
+ <Tooltip style={{ textTransform: 'none' }}>
2252
+ <Tooltip.Target>
2253
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2254
+ </Tooltip.Target>
2255
+ <Tooltip.Content>
2256
+ <p>For numeric data, you can separate the zero value as its own data class.</p>
2257
+ </Tooltip.Content>
2258
+ </Tooltip>
2259
+ </span>
2549
2260
  </label>
2550
- {/* <label className='checkbox'>
2261
+ )}
2262
+ {/* Temp Checkbox */}
2263
+ {state.legend.type === 'equalnumber' && (
2264
+ <label className='checkbox'>
2551
2265
  <input
2552
2266
  type='checkbox'
2553
- checked={state.general.showDownloadImgButton}
2267
+ checked={state.general.equalNumberOptIn}
2554
2268
  onChange={event => {
2555
- handleEditorChanges('toggleDownloadImgButton', event.target.checked)
2269
+ handleEditorChanges('showEqualNumber', event.target.checked)
2556
2270
  }}
2557
2271
  />
2558
- <span className='edit-label'>Enable Image Download</span>
2559
- </label> */}
2560
- {/* <label className='checkbox'>
2272
+ <span className='edit-label column-heading'>Use new quantile legend</span>
2273
+ <Tooltip style={{ textTransform: 'none' }}>
2274
+ <Tooltip.Target>
2275
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2276
+ </Tooltip.Target>
2277
+ <Tooltip.Content>
2278
+ <p>This prevents numbers from being used in more than one category (ie. 0-1, 1-2, 2-3) </p>
2279
+ </Tooltip.Content>
2280
+ </Tooltip>
2281
+ </label>
2282
+ )}
2283
+ {'category' !== legend.type && (
2284
+ <label>
2285
+ <span className='edit-label'>
2286
+ Number of Items
2287
+ <Tooltip style={{ textTransform: 'none' }}>
2288
+ <Tooltip.Target>
2289
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2290
+ </Tooltip.Target>
2291
+ <Tooltip.Content>
2292
+ <p>For numeric maps, select the number of data classes. Do not include designated special classes.</p>
2293
+ </Tooltip.Content>
2294
+ </Tooltip>
2295
+ </span>
2296
+ <select
2297
+ value={legend.numberOfItems}
2298
+ onChange={event => {
2299
+ handleEditorChanges('legendNumber', event.target.value)
2300
+ }}
2301
+ >
2302
+ {[...Array(numberOfItemsLimit).keys()].map(num => {
2303
+ return (
2304
+ <option value={num + 1} key={num + 1}>
2305
+ {num + 1}
2306
+ </option>
2307
+ )
2308
+ })}
2309
+ </select>
2310
+ </label>
2311
+ )}
2312
+ {'category' === legend.type && (
2313
+ <React.Fragment>
2314
+ <label>
2315
+ <span className='edit-label'>
2316
+ Category Order
2317
+ <Tooltip style={{ textTransform: 'none' }}>
2318
+ <Tooltip.Target>
2319
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2320
+ </Tooltip.Target>
2321
+ <Tooltip.Content>
2322
+ <p>Drag map categories into preferred legend order. </p>
2323
+ </Tooltip.Content>
2324
+ </Tooltip>
2325
+ </span>
2326
+ </label>
2327
+ {/* TODO: Swap out this drag and drop library back to something simpler. I had to remove the old one because it hadn't been updated and wouldn't work with Webpack 5. This is overkill for our needs. */}
2328
+ <DragDropContext onDragEnd={({ source, destination }) => categoryMove(source.index, destination.index)}>
2329
+ <Droppable droppableId='category_order'>
2330
+ {provided => (
2331
+ <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef}>
2332
+ <CategoryList />
2333
+ {provided.placeholder}
2334
+ </ul>
2335
+ )}
2336
+ </Droppable>
2337
+ </DragDropContext>
2338
+ {state.legend.categoryValuesOrder && state.legend.categoryValuesOrder.length >= 10 && (
2339
+ <section className='error-box my-2'>
2340
+ <div>
2341
+ <strong className='pt-1'>Warning</strong>
2342
+ <p>The maximum number of categorical legend items is 10. If your data has more than 10 categories your map will not display properly.</p>
2343
+ </div>
2344
+ </section>
2345
+ )}
2346
+ </React.Fragment>
2347
+ )}
2348
+ <TextField value={legend.title} updateField={updateField} section='legend' fieldName='title' label='Legend Title' placeholder='Legend Title' />
2349
+ {false === legend.dynamicDescription && <TextField type='textarea' value={legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />}
2350
+ {true === legend.dynamicDescription && (
2351
+ <React.Fragment>
2352
+ <label>
2353
+ <span>Legend Description</span>
2354
+ <span className='subtext'>For {displayFilterLegendValue(activeFilterValueForDescription)}</span>
2355
+ <DynamicDesc value={legend.descriptions[String(activeFilterValueForDescription)]} />
2356
+ </label>
2357
+ <label>
2358
+ <select
2359
+ value={String(activeFilterValueForDescription)}
2360
+ onChange={event => {
2361
+ handleEditorChanges('changeActiveFilterValue', event.target.value)
2362
+ }}
2363
+ >
2364
+ {filterValueOptionList.map((arr, i) => {
2365
+ return (
2366
+ <option value={arr} key={i}>
2367
+ {displayFilterLegendValue(arr)}
2368
+ </option>
2369
+ )
2370
+ })}
2371
+ </select>
2372
+ </label>
2373
+ </React.Fragment>
2374
+ )}
2375
+ {filtersJSX.length > 0 && (
2376
+ <label className='checkbox'>
2561
2377
  <input
2562
2378
  type='checkbox'
2563
- checked={state.general.showDownloadPdfButton}
2564
- onChange={event => {
2565
- handleEditorChanges('toggleDownloadPdfButton', event.target.checked)
2379
+ checked={legend.dynamicDescription}
2380
+ onChange={() => {
2381
+ handleEditorChanges('dynamicDescription', filterValueOptionList[0])
2566
2382
  }}
2567
2383
  />
2568
- <span className='edit-label'>Enable Pdf Download</span>
2569
- </label> */}
2570
- </AccordionItemPanel>
2571
- </AccordionItem>
2572
- )}
2384
+ <span className='edit-label column-heading'>
2385
+ Dynamic Legend Description
2386
+ <Tooltip style={{ textTransform: 'none' }}>
2387
+ <Tooltip.Target>
2388
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2389
+ </Tooltip.Target>
2390
+ <Tooltip.Content>
2391
+ <p>Check this option if the map has multiple filter controls and you want to specify a description for each filter selection.</p>
2392
+ </Tooltip.Content>
2393
+ </Tooltip>
2394
+ </span>
2395
+ </label>
2396
+ )}
2397
+ {(filtersJSX.length > 0 || state.general.type === 'bubble' || state.general.geoType === 'us') && (
2398
+ <label className='checkbox'>
2399
+ <input type='checkbox' checked={legend.unified} onChange={event => handleEditorChanges('unifiedLegend', event.target.checked)} />
2400
+ <span className='edit-label column-heading'>
2401
+ Unified Legend
2402
+ <Tooltip style={{ textTransform: 'none' }}>
2403
+ <Tooltip.Target>
2404
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2405
+ </Tooltip.Target>
2406
+ <Tooltip.Content>
2407
+ <p>
2408
+ For a map with filters, check this option if you want the high and low values in the legend to be based on <em>all</em> mapped values.
2409
+ </p>
2410
+ </Tooltip.Content>
2411
+ </Tooltip>
2412
+ </span>
2413
+ </label>
2414
+ )}
2415
+ </AccordionItemPanel>
2416
+ </AccordionItem>
2417
+ )}
2418
+ {'navigation' !== state.general.type && (
2573
2419
  <AccordionItem>
2574
2420
  {' '}
2575
- {/* Tooltips */}
2421
+ {/* Filters */}
2576
2422
  <AccordionItemHeading>
2577
- <AccordionItemButton>Interactivity</AccordionItemButton>
2423
+ <AccordionItemButton>Filters</AccordionItemButton>
2578
2424
  </AccordionItemHeading>
2579
2425
  <AccordionItemPanel>
2580
- <label>
2581
- <span className='edit-label'>
2582
- Detail displays on{' '}
2426
+ {filtersJSX.length > 0 ? <MapFilters /> : <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
2427
+ <button
2428
+ className={'btn full-width'}
2429
+ onClick={event => {
2430
+ event.preventDefault()
2431
+ changeFilter(null, 'addNew')
2432
+ }}
2433
+ >
2434
+ Add Filter
2435
+ </button>
2436
+ </AccordionItemPanel>
2437
+ </AccordionItem>
2438
+ )}
2439
+ {'navigation' !== state.general.type && (
2440
+ <AccordionItem>
2441
+ {' '}
2442
+ {/* Data Table */}
2443
+ <AccordionItemHeading>
2444
+ <AccordionItemButton>Data Table</AccordionItemButton>
2445
+ </AccordionItemHeading>
2446
+ <AccordionItemPanel>
2447
+ <TextField
2448
+ value={table.label}
2449
+ updateField={updateField}
2450
+ section='table'
2451
+ fieldName='label'
2452
+ id='dataTableTitle'
2453
+ label='Data Table Title'
2454
+ placeholder='Data Table'
2455
+ tooltip={
2583
2456
  <Tooltip style={{ textTransform: 'none' }}>
2584
2457
  <Tooltip.Target>
2585
2458
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2586
2459
  </Tooltip.Target>
2587
2460
  <Tooltip.Content>
2588
- <p>At mobile sizes, information always appears in a popover modal when a user taps on an item.</p>
2461
+ <p>Label is required for Data Table for 508 Compliance</p>
2589
2462
  </Tooltip.Content>
2590
2463
  </Tooltip>
2591
- </span>
2592
- <select
2593
- value={state.tooltips.appearanceType}
2464
+ }
2465
+ />
2466
+ <label className='checkbox'>
2467
+ <input
2468
+ type='checkbox'
2469
+ checked={state.table.forceDisplay !== undefined ? state.table.forceDisplay : !isDashboard}
2594
2470
  onChange={event => {
2595
- handleEditorChanges('appearanceType', event.target.value)
2471
+ handleEditorChanges('showDataTable', event.target.checked)
2596
2472
  }}
2597
- >
2598
- <option value='hover'>Hover - Tooltip</option>
2599
- <option value='click'>Click - Popover Modal</option>
2600
- </select>
2473
+ />
2474
+ <span className='edit-label column-heading'>
2475
+ Show Data Table
2476
+ <Tooltip style={{ textTransform: 'none' }}>
2477
+ <Tooltip.Target>
2478
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2479
+ </Tooltip.Target>
2480
+ <Tooltip.Content>
2481
+ <p>Data tables are required for 508 compliance. When choosing to hide this data table, replace with your own version.</p>
2482
+ </Tooltip.Content>
2483
+ </Tooltip>
2484
+ </span>
2601
2485
  </label>
2602
- {'click' === state.tooltips.appearanceType && <TextField value={tooltips.linkLabel} section='tooltips' fieldName='linkLabel' label='Tooltips Link Label' updateField={updateField} />}
2486
+ <TextField
2487
+ value={table.indexLabel || ''}
2488
+ updateField={updateField}
2489
+ section='table'
2490
+ fieldName='indexLabel'
2491
+ label='Index Column Header'
2492
+ placeholder='Location'
2493
+ tooltip={
2494
+ <Tooltip style={{ textTransform: 'none' }}>
2495
+ <Tooltip.Target>
2496
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2497
+ </Tooltip.Target>
2498
+ <Tooltip.Content>
2499
+ <p>To comply with 508 standards, if the first column in the data table has no header, enter a brief one here.</p>
2500
+ </Tooltip.Content>
2501
+ </Tooltip>
2502
+ }
2503
+ />
2504
+ <TextField
2505
+ value={state.table.caption}
2506
+ updateField={updateField}
2507
+ section='table'
2508
+ fieldName='caption'
2509
+ label='Data Table Caption'
2510
+ placeholder='Data Table'
2511
+ tooltip={
2512
+ <Tooltip style={{ textTransform: 'none' }}>
2513
+ <Tooltip.Target>
2514
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2515
+ </Tooltip.Target>
2516
+ <Tooltip.Content>
2517
+ <p>Enter a description of the data table to be read by screen readers.</p>
2518
+ </Tooltip.Content>
2519
+ </Tooltip>
2520
+ }
2521
+ type='textarea'
2522
+ />
2603
2523
  <label className='checkbox'>
2604
2524
  <input
2605
2525
  type='checkbox'
2606
- checked={state.tooltips.capitalizeLabels}
2526
+ checked={state.table.limitHeight}
2607
2527
  onChange={event => {
2608
- handleEditorChanges('capitalizeLabels', event.target.checked)
2528
+ handleEditorChanges('limitDataTableHeight', event.target.checked)
2609
2529
  }}
2610
2530
  />
2611
- <span className='edit-label'>Capitalize text inside tooltip</span>
2612
- </label>
2613
- </AccordionItemPanel>
2614
- </AccordionItem>
2615
- <AccordionItem>
2616
- {' '}
2617
- {/* Visual */}
2618
- <AccordionItemHeading>
2619
- <AccordionItemButton>Visual</AccordionItemButton>
2620
- </AccordionItemHeading>
2621
- <AccordionItemPanel>
2622
- <label>
2623
- <span className='edit-label'>Header Theme</span>
2624
- <ul className='color-palette'>
2625
- {headerColors.map(palette => {
2626
- return (
2627
- <li
2628
- title={palette}
2629
- key={palette}
2630
- onClick={() => {
2631
- handleEditorChanges('headerColor', palette)
2632
- }}
2633
- className={state.general.headerColor === palette ? 'selected ' + palette : palette}
2634
- ></li>
2635
- )
2636
- })}
2637
- </ul>
2531
+ <span className='edit-label'>Limit Table Height</span>
2638
2532
  </label>
2533
+ {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' />}
2639
2534
  <label className='checkbox'>
2640
2535
  <input
2641
2536
  type='checkbox'
2642
- checked={state.general.showTitle || false}
2537
+ checked={state.table.expanded || false}
2643
2538
  onChange={event => {
2644
- handleEditorChanges('showTitle', event.target.checked)
2539
+ handleEditorChanges('expandDataTable', event.target.checked)
2645
2540
  }}
2646
2541
  />
2647
- <span className='edit-label'>Show Title</span>
2542
+ <span className='edit-label'>Map loads with data table expanded</span>
2648
2543
  </label>
2649
-
2650
- {'navigation' === state.general.type && (
2544
+ {isDashboard && (
2651
2545
  <label className='checkbox'>
2652
2546
  <input
2653
2547
  type='checkbox'
2654
- checked={state.general.fullBorder || false}
2548
+ checked={state.table.showDataTableLink}
2655
2549
  onChange={event => {
2656
- handleEditorChanges('fullBorder', event.target.checked)
2550
+ handleEditorChanges('toggleDataTableLink', event.target.checked)
2657
2551
  }}
2658
2552
  />
2659
- <span className='edit-label'>Add border around map</span>
2553
+ <span className='edit-label'>Show Data Table Name & Link</span>
2660
2554
  </label>
2661
2555
  )}
2662
- <label>
2663
- <span className='edit-label'>Geo Border Color</span>
2664
- <select
2665
- value={state.general.geoBorderColor || false}
2556
+ {isLoadedFromUrl && (
2557
+ <label className='checkbox'>
2558
+ <input
2559
+ type='checkbox'
2560
+ checked={state.table.showDownloadUrl}
2561
+ onChange={event => {
2562
+ handleEditorChanges('toggleDataUrl', event.target.checked)
2563
+ }}
2564
+ />
2565
+ <span className='edit-label'>Show URL to Automatically Updated Data</span>
2566
+ </label>
2567
+ )}
2568
+ <label className='checkbox'>
2569
+ <input
2570
+ type='checkbox'
2571
+ checked={state.general.showDownloadButton}
2666
2572
  onChange={event => {
2667
- handleEditorChanges('geoBorderColor', event.target.value)
2573
+ handleEditorChanges('toggleDownloadButton', event.target.checked)
2668
2574
  }}
2669
- >
2670
- <option value='darkGray'>Dark Gray (Default)</option>
2671
- <option value='sameAsBackground'>White</option>
2672
- </select>
2575
+ />
2576
+ <span className='edit-label'>Show Download CSV Link</span>
2673
2577
  </label>
2674
- <label>
2675
- <span className='edit-label'>Map Color Palette</span>
2578
+ <label className='checkbox'>
2579
+ <input
2580
+ type='checkbox'
2581
+ checked={state.general.showFullGeoNameInCSV}
2582
+ onChange={event => {
2583
+ handleEditorChanges('toggleShowFullGeoNameInCSV', event.target.checked)
2584
+ }}
2585
+ />
2586
+ <span className='edit-label'>Include Full Geo Name in CSV Download</span>
2676
2587
  </label>
2677
- {/* <InputCheckbox section="general" subsection="palette" fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} /> */}
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} />
2679
- <span>Sequential</span>
2588
+ {/* <label className='checkbox'>
2589
+ <input
2590
+ type='checkbox'
2591
+ checked={state.general.showDownloadImgButton}
2592
+ onChange={event => {
2593
+ handleEditorChanges('toggleDownloadImgButton', event.target.checked)
2594
+ }}
2595
+ />
2596
+ <span className='edit-label'>Enable Image Download</span>
2597
+ </label> */}
2598
+ {/* <label className='checkbox'>
2599
+ <input
2600
+ type='checkbox'
2601
+ checked={state.general.showDownloadPdfButton}
2602
+ onChange={event => {
2603
+ handleEditorChanges('toggleDownloadPdfButton', event.target.checked)
2604
+ }}
2605
+ />
2606
+ <span className='edit-label'>Enable Pdf Download</span>
2607
+ </label> */}
2608
+ </AccordionItemPanel>
2609
+ </AccordionItem>
2610
+ )}
2611
+ <AccordionItem>
2612
+ {' '}
2613
+ {/* Tooltips */}
2614
+ <AccordionItemHeading>
2615
+ <AccordionItemButton>Interactivity</AccordionItemButton>
2616
+ </AccordionItemHeading>
2617
+ <AccordionItemPanel>
2618
+ <label>
2619
+ <span className='edit-label'>
2620
+ Detail displays on{' '}
2621
+ <Tooltip style={{ textTransform: 'none' }}>
2622
+ <Tooltip.Target>
2623
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2624
+ </Tooltip.Target>
2625
+ <Tooltip.Content>
2626
+ <p>At mobile sizes, information always appears in a popover modal when a user taps on an item.</p>
2627
+ </Tooltip.Content>
2628
+ </Tooltip>
2629
+ </span>
2630
+ <select
2631
+ value={state.tooltips.appearanceType}
2632
+ onChange={event => {
2633
+ handleEditorChanges('appearanceType', event.target.value)
2634
+ }}
2635
+ >
2636
+ <option value='hover'>Hover - Tooltip</option>
2637
+ <option value='click'>Click - Popover Modal</option>
2638
+ </select>
2639
+ </label>
2640
+ {'click' === state.tooltips.appearanceType && <TextField value={tooltips.linkLabel} section='tooltips' fieldName='linkLabel' label='Tooltips Link Label' updateField={updateField} />}
2641
+ <label className='checkbox'>
2642
+ <input
2643
+ type='checkbox'
2644
+ checked={state.tooltips.capitalizeLabels}
2645
+ onChange={event => {
2646
+ handleEditorChanges('capitalizeLabels', event.target.checked)
2647
+ }}
2648
+ />
2649
+ <span className='edit-label'>Capitalize text inside tooltip</span>
2650
+ </label>
2651
+ </AccordionItemPanel>
2652
+ </AccordionItem>
2653
+ <AccordionItem>
2654
+ {' '}
2655
+ {/* Visual */}
2656
+ <AccordionItemHeading>
2657
+ <AccordionItemButton>Visual</AccordionItemButton>
2658
+ </AccordionItemHeading>
2659
+ <AccordionItemPanel>
2660
+ <label>
2661
+ <span className='edit-label'>Header Theme</span>
2680
2662
  <ul className='color-palette'>
2681
- {sequential.map(palette => {
2682
- const colorOne = {
2683
- backgroundColor: colorPalettes[palette][2]
2684
- }
2685
-
2686
- const colorTwo = {
2687
- backgroundColor: colorPalettes[palette][4]
2688
- }
2689
-
2690
- const colorThree = {
2691
- backgroundColor: colorPalettes[palette][6]
2692
- }
2693
-
2663
+ {headerColors.map(palette => {
2694
2664
  return (
2695
2665
  <li
2696
2666
  title={palette}
2697
2667
  key={palette}
2698
2668
  onClick={() => {
2699
- handleEditorChanges('color', palette)
2669
+ handleEditorChanges('headerColor', palette)
2700
2670
  }}
2701
- className={state.color === palette ? 'selected' : ''}
2702
- >
2703
- <span style={colorOne}></span>
2704
- <span style={colorTwo}></span>
2705
- <span style={colorThree}></span>
2706
- </li>
2671
+ className={state.general.headerColor === palette ? 'selected ' + palette : palette}
2672
+ ></li>
2707
2673
  )
2708
2674
  })}
2709
2675
  </ul>
2710
- <span>Non-Sequential</span>
2711
- <ul className='color-palette'>
2712
- {nonSequential.map(palette => {
2713
- const colorOne = {
2714
- backgroundColor: colorPalettes[palette][2]
2715
- }
2676
+ </label>
2677
+ <label className='checkbox'>
2678
+ <input
2679
+ type='checkbox'
2680
+ checked={state.general.showTitle || false}
2681
+ onChange={event => {
2682
+ handleEditorChanges('showTitle', event.target.checked)
2683
+ }}
2684
+ />
2685
+ <span className='edit-label'>Show Title</span>
2686
+ </label>
2716
2687
 
2717
- const colorTwo = {
2718
- backgroundColor: colorPalettes[palette][4]
2719
- }
2688
+ {'navigation' === state.general.type && (
2689
+ <label className='checkbox'>
2690
+ <input
2691
+ type='checkbox'
2692
+ checked={state.general.fullBorder || false}
2693
+ onChange={event => {
2694
+ handleEditorChanges('fullBorder', event.target.checked)
2695
+ }}
2696
+ />
2697
+ <span className='edit-label'>Add border around map</span>
2698
+ </label>
2699
+ )}
2700
+ <label>
2701
+ <span className='edit-label'>Geo Border Color</span>
2702
+ <select
2703
+ value={state.general.geoBorderColor || false}
2704
+ onChange={event => {
2705
+ handleEditorChanges('geoBorderColor', event.target.value)
2706
+ }}
2707
+ >
2708
+ <option value='darkGray'>Dark Gray (Default)</option>
2709
+ <option value='sameAsBackground'>White</option>
2710
+ </select>
2711
+ </label>
2712
+ <label>
2713
+ <span className='edit-label'>Map Color Palette</span>
2714
+ </label>
2715
+ {/* <InputCheckbox section="general" subsection="palette" fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} /> */}
2716
+ <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} />
2717
+ <span>Sequential</span>
2718
+ <ul className='color-palette'>
2719
+ {sequential.map(palette => {
2720
+ const colorOne = {
2721
+ backgroundColor: colorPalettes[palette][2]
2722
+ }
2720
2723
 
2721
- const colorThree = {
2722
- backgroundColor: colorPalettes[palette][6]
2723
- }
2724
+ const colorTwo = {
2725
+ backgroundColor: colorPalettes[palette][4]
2726
+ }
2724
2727
 
2725
- // hide palettes with too few colors for region maps
2726
- if (colorPalettes[palette].length <= 8 && state.general.geoType === 'us-region') {
2727
- return ''
2728
- }
2729
- return (
2730
- <li
2731
- title={palette}
2732
- key={palette}
2733
- onClick={() => {
2734
- handleEditorChanges('color', palette)
2735
- }}
2736
- className={state.color === palette ? 'selected' : ''}
2737
- >
2738
- <span style={colorOne}></span>
2739
- <span style={colorTwo}></span>
2740
- <span style={colorThree}></span>
2741
- </li>
2742
- )
2743
- })}
2744
- </ul>
2745
- {('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && (
2746
- <label>
2747
- Geocode Settings
2748
- <TextField type='number' value={state.visual.geoCodeCircleSize} section='visual' max='10' fieldName='geoCodeCircleSize' label='Geocode Circle Size' updateField={updateField} />
2749
- </label>
2750
- )}
2728
+ const colorThree = {
2729
+ backgroundColor: colorPalettes[palette][6]
2730
+ }
2751
2731
 
2752
- {state.general.type === 'bubble' && (
2753
- <>
2754
- <TextField type='number' value={state.visual.minBubbleSize} section='visual' fieldName='minBubbleSize' label='Minimum Bubble Size' updateField={updateField} />
2755
- <TextField type='number' value={state.visual.maxBubbleSize} section='visual' fieldName='maxBubbleSize' label='Maximum Bubble Size' updateField={updateField} />
2756
- </>
2757
- )}
2758
- {(state.general.geoType === 'world' || (state.general.geoType === 'us' && state.general.type === 'bubble')) && (
2759
- <label className='checkbox'>
2760
- <input
2761
- type='checkbox'
2762
- checked={state.visual.showBubbleZeros}
2763
- onChange={event => {
2764
- handleEditorChanges('showBubbleZeros', event.target.checked)
2732
+ return (
2733
+ <li
2734
+ title={palette}
2735
+ key={palette}
2736
+ onClick={() => {
2737
+ handleEditorChanges('color', palette)
2765
2738
  }}
2766
- />
2767
- <span className='edit-label'>Show Data with Zero's on Bubble Map</span>
2768
- </label>
2769
- )}
2770
- {state.general.geoType === 'world' && (
2771
- <label className='checkbox'>
2772
- <input
2773
- type='checkbox'
2774
- checked={state.general.allowMapZoom}
2775
- onChange={event => {
2776
- handleEditorChanges('allowMapZoom', event.target.checked)
2739
+ className={state.color === palette ? 'selected' : ''}
2740
+ >
2741
+ <span style={colorOne}></span>
2742
+ <span style={colorTwo}></span>
2743
+ <span style={colorThree}></span>
2744
+ </li>
2745
+ )
2746
+ })}
2747
+ </ul>
2748
+ <span>Non-Sequential</span>
2749
+ <ul className='color-palette'>
2750
+ {nonSequential.map(palette => {
2751
+ const colorOne = {
2752
+ backgroundColor: colorPalettes[palette][2]
2753
+ }
2754
+
2755
+ const colorTwo = {
2756
+ backgroundColor: colorPalettes[palette][4]
2757
+ }
2758
+
2759
+ const colorThree = {
2760
+ backgroundColor: colorPalettes[palette][6]
2761
+ }
2762
+
2763
+ // hide palettes with too few colors for region maps
2764
+ if (colorPalettes[palette].length <= 8 && state.general.geoType === 'us-region') {
2765
+ return ''
2766
+ }
2767
+ return (
2768
+ <li
2769
+ title={palette}
2770
+ key={palette}
2771
+ onClick={() => {
2772
+ handleEditorChanges('color', palette)
2777
2773
  }}
2778
- />
2779
- <span className='edit-label'>Allow Map Zooming</span>
2780
- </label>
2781
- )}
2782
- {state.general.type === 'bubble' && (
2783
- <label className='checkbox'>
2784
- <input
2785
- type='checkbox'
2786
- checked={state.visual.extraBubbleBorder}
2774
+ className={state.color === palette ? 'selected' : ''}
2775
+ >
2776
+ <span style={colorOne}></span>
2777
+ <span style={colorTwo}></span>
2778
+ <span style={colorThree}></span>
2779
+ </li>
2780
+ )
2781
+ })}
2782
+ </ul>
2783
+ {('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && (
2784
+ <label>
2785
+ Geocode Settings
2786
+ <TextField type='number' value={state.visual.geoCodeCircleSize} section='visual' max='10' fieldName='geoCodeCircleSize' label='Geocode Circle Size' updateField={updateField} />
2787
+ </label>
2788
+ )}
2789
+
2790
+ {state.general.type === 'bubble' && (
2791
+ <>
2792
+ <TextField type='number' value={state.visual.minBubbleSize} section='visual' fieldName='minBubbleSize' label='Minimum Bubble Size' updateField={updateField} />
2793
+ <TextField type='number' value={state.visual.maxBubbleSize} section='visual' fieldName='maxBubbleSize' label='Maximum Bubble Size' updateField={updateField} />
2794
+ </>
2795
+ )}
2796
+ {(state.general.geoType === 'world' || (state.general.geoType === 'us' && state.general.type === 'bubble')) && (
2797
+ <label className='checkbox'>
2798
+ <input
2799
+ type='checkbox'
2800
+ checked={state.visual.showBubbleZeros}
2801
+ onChange={event => {
2802
+ handleEditorChanges('showBubbleZeros', event.target.checked)
2803
+ }}
2804
+ />
2805
+ <span className='edit-label'>Show Data with Zero's on Bubble Map</span>
2806
+ </label>
2807
+ )}
2808
+ {state.general.geoType === 'world' && (
2809
+ <label className='checkbox'>
2810
+ <input
2811
+ type='checkbox'
2812
+ checked={state.general.allowMapZoom}
2813
+ onChange={event => {
2814
+ handleEditorChanges('allowMapZoom', event.target.checked)
2815
+ }}
2816
+ />
2817
+ <span className='edit-label'>Allow Map Zooming</span>
2818
+ </label>
2819
+ )}
2820
+ {state.general.type === 'bubble' && (
2821
+ <label className='checkbox'>
2822
+ <input
2823
+ type='checkbox'
2824
+ checked={state.visual.extraBubbleBorder}
2825
+ onChange={event => {
2826
+ handleEditorChanges('toggleExtraBubbleBorder', event.target.checked)
2827
+ }}
2828
+ />
2829
+ <span className='edit-label'>Bubble Map has extra border</span>
2830
+ </label>
2831
+ )}
2832
+ {state.general.geoType === 'us' ||
2833
+ state.general.geoType === 'us-county' ||
2834
+ (state.general.geoType === 'world' && (
2835
+ <label>
2836
+ <span className='edit-label'>City Style</span>
2837
+ <select
2838
+ value={state.visual.cityStyle || false}
2787
2839
  onChange={event => {
2788
- handleEditorChanges('toggleExtraBubbleBorder', event.target.checked)
2840
+ handleEditorChanges('handleCityStyle', event.target.value)
2789
2841
  }}
2790
- />
2791
- <span className='edit-label'>Bubble Map has extra border</span>
2842
+ >
2843
+ <option value='circle'>Circle</option>
2844
+ <option value='pin'>Pin</option>
2845
+ </select>
2792
2846
  </label>
2793
- )}
2794
- {state.general.geoType === 'us' ||
2795
- state.general.geoType === 'us-county' ||
2796
- (state.general.geoType === 'world' && (
2797
- <label>
2798
- <span className='edit-label'>City Style</span>
2799
- <select
2800
- value={state.visual.cityStyle || false}
2801
- onChange={event => {
2802
- handleEditorChanges('handleCityStyle', event.target.value)
2803
- }}
2804
- >
2805
- <option value='circle'>Circle</option>
2806
- <option value='pin'>Pin</option>
2807
- </select>
2808
- </label>
2809
- ))}
2810
- </AccordionItemPanel>
2811
- </AccordionItem>
2812
- {/* HIDING FOR 4.23.4 */}
2813
- {/* <AccordionItem>
2847
+ ))}
2848
+ </AccordionItemPanel>
2849
+ </AccordionItem>
2850
+ {/* <AccordionItem>
2814
2851
  <AccordionItemHeading>
2815
2852
  <AccordionItemButton>Custom Map Layers</AccordionItemButton>
2816
2853
  </AccordionItemHeading>
@@ -2828,13 +2865,21 @@ const EditorPanel = props => {
2828
2865
  <AccordionItemPanel>
2829
2866
  <div className='map-layers-panel'>
2830
2867
  <label htmlFor='layerName'>Layer Name:</label>
2831
- <input type='text' name='layerName' value={layer.name} onChange={e => handleMapLayerName(e, index)} />
2868
+ <input type='text' name='layerName' value={layer.name} onChange={e => handleMapLayer(e, index, 'name')} />
2832
2869
  <label htmlFor='layerFilename'>File:</label>
2833
- <input type='text' name='layerFilename' value={layer.url} onChange={e => handleMapLayerUrl(e, index)} />
2870
+ <input type='text' name='layerFilename' value={layer.url} onChange={e => handleMapLayer(e, index, 'url')} />
2834
2871
  <label htmlFor='layerNamespace'>TOPOJSON Namespace:</label>
2835
- <input type='text' name='layerNamespace' value={layer.namespace} onChange={e => handleMapLayerNamespace(e, index)} />
2872
+ <input type='text' name='layerNamespace' value={layer.namespace} onChange={e => handleMapLayer(e, index, 'namespace')} />
2873
+ <label htmlFor='layerFill'>Fill Color:</label>
2874
+ <input type='text' name='layerFill' value={layer.fill} onChange={e => handleMapLayer(e, index, 'fill')} />
2875
+ <label htmlFor='layerFill'>Fill Opacity (%):</label>
2876
+ <input type='number' min={0} max={100} name='layerFill' value={layer.fillOpacity ? layer.fillOpacity * 100 : ''} onChange={e => handleMapLayer(e, index, 'fillOpacity')} />
2877
+ <label htmlFor='layerStroke'>Stroke Color:</label>
2878
+ <input type='text' name='layerStroke' value={layer.stroke} onChange={e => handleMapLayer(e, index, 'stroke')} />
2879
+ <label htmlFor='layerStroke'>Stroke Width:</label>
2880
+ <input type='number' min={0} max={5} name='layerStrokeWidth' value={layer.strokeWidth} onChange={e => handleMapLayer(e, index, 'strokeWidth')} />
2836
2881
  <label htmlFor='layerTooltip'>Tooltip:</label>
2837
- <textarea name='layerTooltip' value={layer.tooltip} onChange={e => handleMapLayerTooltip(e, index)}></textarea>
2882
+ <textarea name='layerTooltip' value={layer.tooltip} onChange={e => handleMapLayer(e, index, 'tooltip')}></textarea>
2838
2883
  <button onClick={e => handleRemoveLayer(e, index)}>Remove Layer</button>
2839
2884
  </div>
2840
2885
  </AccordionItemPanel>
@@ -2848,8 +2893,7 @@ const EditorPanel = props => {
2848
2893
  </button>
2849
2894
  </AccordionItemPanel>
2850
2895
  </AccordionItem> */}
2851
- </Accordion>
2852
- </form>
2896
+ </Accordion>
2853
2897
  <AdvancedEditor loadConfig={loadConfig} state={state} convertStateToConfig={convertStateToConfig} />
2854
2898
  </section>
2855
2899
  </section>