@cdc/map 4.23.5 → 4.23.7

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