diff --git a/map-viewer/package.json b/map-viewer/package.json index fcd475f..ff7fa12 100644 --- a/map-viewer/package.json +++ b/map-viewer/package.json @@ -4,12 +4,12 @@ "main": "src/index.js", "private": true, "dependencies": { - "@dnd-kit/core": "^3.1.1", "@mapbox/mapbox-gl-draw": "^1.3.0", "@mapbox/mapbox-gl-geocoder": "^4.7.0", "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.8.3", + "array-move": "^4.0.0", "bootstrap": "^4.6.0", "d3": "^6.7.0", "leaflet": "^1.7.1", @@ -17,11 +17,11 @@ "postcss": "^8.3.5", "prop-types": "^15.7.2", "react": "^17.0.2", - "react-beautiful-dnd": "^13.1.0", "react-bootstrap": "^1.6.1", "react-dom": "^17.0.2", "react-icons": "^4.2.0", "react-scripts": "4.0.3", + "react-sortable-hoc": "^2.0.0", "styled-components": "^5.2.3", "turf": "^3.0.14", "web-vitals": "^1.1.1", diff --git a/map-viewer/src/Map.css b/map-viewer/src/Map.css index 407e609..be8c9f5 100644 --- a/map-viewer/src/Map.css +++ b/map-viewer/src/Map.css @@ -181,7 +181,7 @@ background-color: #f5f6f7; border-radius: 4px; line-height: 18px; - max-height: 200px; + max-height: 300px; width: 340px; overflow-y: auto; } @@ -193,6 +193,7 @@ margin-right: 5px; } .legend-desc { + padding-left: 2px; padding-bottom: 5px; font-weight: bold; font-size: 13px; @@ -219,9 +220,34 @@ height: 20px; overflow-y: auto; } +.d3-x-axis { + font-size: 12px; +} .d3-x-axis:not(:last-child) { padding-right: 4.75rem; } +.legend-item { + font-size: 16px; +} +.sortable-container-helper { + z-index: 1; + font-family: 'Source Sans Pro', sans-serif; + line-height: 18px; + font-weight: 400; + padding-left: 20px; +} +.drag-handle { + font-size: 12px; + padding-left: 0; + padding-right: 0; + margin-right: 0; + cursor: grab; +} +.sortable-container { +} +.sortable-container:active { +} + .labelIcons { font-size: 30px; diff --git a/map-viewer/src/Map.jsx b/map-viewer/src/Map.jsx index 370be49..c1e443b 100644 --- a/map-viewer/src/Map.jsx +++ b/map-viewer/src/Map.jsx @@ -18,6 +18,9 @@ import mapLayers from './LayerDefinitions'; import { coastalHabitats } from './ScaleDefinitions'; import { protectedLayers } from './ScaleDefinitions'; +import {arrayMoveImmutable} from 'array-move'; + + // import MyComponent from './components/MyComponent'; //mapboxgl.workerClass = MapboxWorker; @@ -549,7 +552,8 @@ const Map = () => { setLayers({...visibleLayersUpdate}); } else { - selectedServicesUpdate.push(serviceResult); + //Using concat because we want newly added things in front of array + selectedServicesUpdate = [serviceResult].concat(selectedServicesUpdate); //You're calling setNumbers and passing it the array it already has. //You've changed one of its values but it's still the same array, and //I suspect React doesn't see any reason to re-render because state @@ -561,6 +565,7 @@ const Map = () => { // Check 'all' for coastal protection case where we want this one // layer visible across all scales if((layer.scaleID === scale.current || layer.scaleID === 'all') && layer.serviceType === serviceResult) { + map.moveLayer(layer.layerID); map.setLayoutProperty(layer.layerID, 'visibility', 'visible'); visibleLayersUpdate[serviceResult] = {...layer}; @@ -600,6 +605,60 @@ const Map = () => { setMap(map); } + const changeLayerOrder = (servicesSorted, oldIndex, newIndex) => { + console.log("change order"); + console.log(selectedServices); + console.log(oldIndex + " : " + newIndex); + console.log(visibleLayers); + // Reverse the sorted services to start with the layers in the back + const reversedServices = servicesSorted.slice().reverse(); + reversedServices.forEach((serviceType, i) => { + let zbackId = []; + // Add all layers from a service type if there are multiple of them + if(serviceType in multiFileLayers) { + multiFileLayers[serviceType].forEach((childLayer) => { + zbackId.push(childLayer.id); + }); + } + else { + zbackId.push(visibleLayers[serviceType].layerID); + } + + if(reversedServices.length < i+1) { + const nextService = reversedServices[i+1]; + let zfrontId = []; + // Add all layers from a service type if there are multiple of them + if(nextService in multiFileLayers) { + multiFileLayers[nextService].forEach((childLayer) => { + zfrontId.push(childLayer.id); + }); + } + else { + zfrontId.push(visibleLayers[nextService].layerID); + } + // Move each layer behind each next layer + zbackId.forEach((backLayerId) => { + zfrontId.forEach((frontLayerId) => { + map.moveLayer(backLayerId, frontLayerId); + }); + }); + } + else { + // We are at the most visible set of layers, just move them to the top. + zbackId.forEach((backLayerId) => { + map.moveLayer(backLayerId); + }); + } + }); + + setServices(() => { + return arrayMoveImmutable(selectedServices, oldIndex, newIndex); + }); + console.log("servicesSorted ", servicesSorted); + console.log("selectedServices: after order change ", [...selectedServices]); + setMap(map); + }; + return ( { + {}); + +const SortableItem = sortableElement(({value, index}) => ( + + + + + + + {legendStyle[value].desc} + + + + + + + + + + + +)); + +const SortableContainer = sortableContainer(({children}) => { + return
    {children}
; +}); + const Legend = (props) => { + function handleDragEnd({oldIndex, newIndex}) { + const sortedServices = arrayMoveImmutable(props.services, oldIndex, newIndex); + props.changeLayerOrder(sortedServices, oldIndex, newIndex); + } + const renderLegend = (serviceType, i) => { return ( - -
{legendStyle[serviceType].desc}
- - - - - - - - -
+ ); }; if (props.services.length > 0) { return ( - {props.services.map(renderLegend)} + + {props.services.map(renderLegend)} + ); } @@ -139,6 +185,7 @@ const Legend = (props) => { Legend.propTypes = { layers: PropTypes.object.isRequired, services: PropTypes.array.isRequired, + changeLayerOrder: PropTypes.func.isRequired, } export default Legend;