From 200643f015af5c69ccf52244746aa313b64cdcc9 Mon Sep 17 00:00:00 2001 From: Tom <58078313+reed-tom@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:53:36 -0400 Subject: [PATCH] switched to react-movable for drag/drop functionality --- package-lock.json | 10 + package.json | 1 + src/helpers/SC.css | 4 + .../components/toc/toc-list-new/LayerItem.css | 3 + .../components/toc/toc-list-new/LayerItem.jsx | 11 +- .../components/toc/toc-list-new/Layers.css | 16 +- .../components/toc/toc-list-new/Layers.jsx | 199 +++++------------- 7 files changed, 85 insertions(+), 159 deletions(-) diff --git a/package-lock.json b/package-lock.json index bff356ec..1ef0c98f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "react-highlight-words": "^0.20.0", "react-icons": "^4.8.0", "react-masonry-css": "^1.0.16", + "react-movable": "^3.2.0", "react-responsive-modal": "^6.4.2", "react-router-dom": "^6.15.0", "react-scripts": "5.0.1", @@ -15627,6 +15628,15 @@ "react": ">=16.0.0" } }, + "node_modules/react-movable": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-movable/-/react-movable-3.2.0.tgz", + "integrity": "sha512-Z2C3O8ZTkJoqwGTmwpCd8WJjdugc5F0UNdCdQrVv/jZiIjHOpzgCWHtMo9xwjU0lioJT1donDIQaCPl4x31FtQ==", + "peerDependencies": { + "react": ">=16.3", + "react-dom": ">=16.3" + } + }, "node_modules/react-onclickoutside": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", diff --git a/package.json b/package.json index 7ea7470a..3b204cfd 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "react-highlight-words": "^0.20.0", "react-icons": "^4.8.0", "react-masonry-css": "^1.0.16", + "react-movable": "^3.2.0", "react-responsive-modal": "^6.4.2", "react-router-dom": "^6.15.0", "react-scripts": "5.0.1", diff --git a/src/helpers/SC.css b/src/helpers/SC.css index 1988c1c5..b5b8a0fa 100644 --- a/src/helpers/SC.css +++ b/src/helpers/SC.css @@ -494,6 +494,10 @@ input[type="number"]::-webkit-outer-spin-button { .sc-attachment-icon { color: #626262; } + +.sc-drag-icon { + color: #626262; +} @media print { .no-print, .no-print * { diff --git a/src/sidebar/components/toc/toc-list-new/LayerItem.css b/src/sidebar/components/toc/toc-list-new/LayerItem.css index 29671f80..dfb26cac 100644 --- a/src/sidebar/components/toc/toc-list-new/LayerItem.css +++ b/src/sidebar/components/toc/toc-list-new/LayerItem.css @@ -1,5 +1,8 @@ .sc-toc-item-container { display: table; + -webkit-user-select: none; /* Chrome all / Safari all */ + -moz-user-select: none; /* Firefox all */ + -ms-user-select: none; /* IE 10+ */ user-select: none; margin-right: 2px; margin-left: 2px; diff --git a/src/sidebar/components/toc/toc-list-new/LayerItem.jsx b/src/sidebar/components/toc/toc-list-new/LayerItem.jsx index 3548360e..433af6f4 100644 --- a/src/sidebar/components/toc/toc-list-new/LayerItem.jsx +++ b/src/sidebar/components/toc/toc-list-new/LayerItem.jsx @@ -4,6 +4,7 @@ import Highlighter from "react-highlight-words"; import LayerLegend from "../common/LayerLegend"; import { acceptDisclaimer } from "../common/TOCHelpers.jsx"; import { FaPaperclip } from "react-icons/fa"; +import { IoReorderThreeSharp } from "react-icons/io5"; import "./LayerItem.css"; class LayerItem extends Component { @@ -67,7 +68,9 @@ class LayerItem extends Component { return (
-
this.props.onLegendToggle(layerInfo, this.props.group)}> + + +
this.props.onLegendToggle(layerInfo, this.props.group)}>
-
-
this.props.onLayerOptionsClick(evt, layerInfo)}> +
this.props.onLayerOptionsClick(evt, layerInfo)}> more options
diff --git a/src/sidebar/components/toc/toc-list-new/Layers.css b/src/sidebar/components/toc/toc-list-new/Layers.css index f2563b15..e6d61c28 100644 --- a/src/sidebar/components/toc/toc-list-new/Layers.css +++ b/src/sidebar/components/toc/toc-list-new/Layers.css @@ -8,7 +8,17 @@ margin-left: 5px !important; } -.sc-dragover { - background-color: blueviolet; - padding-left: 10px; +#sc-toc-list-layers-sortablevirtuallist-virtual-layers { + list-style: none; + padding: 0; + margin: 0; +} + +.sc-toc-list-layers-sortablevirtuallist-virtual-layers-listitem { + min-height: 30px; + list-style: none; +} + +.sc-toc-list-layers-sortablevirtuallist-virtual-layers-listitem.sc-dragged { + z-index: 4 !important; /*override default z-index to show dragged item above sidebar*/ } diff --git a/src/sidebar/components/toc/toc-list-new/Layers.jsx b/src/sidebar/components/toc/toc-list-new/Layers.jsx index b7f96ce4..f133fc3c 100644 --- a/src/sidebar/components/toc/toc-list-new/Layers.jsx +++ b/src/sidebar/components/toc/toc-list-new/Layers.jsx @@ -2,31 +2,23 @@ //https://medium.com/nerd-for-tech/simple-drag-and-drop-in-react-without-an-external-library-ebf1c1b809e import React, { useState, useEffect, useRef } from "react"; import * as helpers from "../../../../helpers/helpers"; -import { debounce } from "../../../../helpers/react"; - +import { List, arrayMove } from "react-movable"; import LayerItem from "./LayerItem.jsx"; import "./Layers.css"; // CUSTOM import "./Layers.css"; -import { preventDefault } from "ol/events/Event.js"; -const Layers = (props) => { +const Layers = (layersProps) => { const storageKey = "Layers"; const lastPositionRef = useRef(null); const virtualId = "sc-toc-list-layers-sortablevirtuallist-virtual-layers"; const [recalcId, setRecalcId] = useState(""); const [layers, setLayers] = useState([]); const [allLayers, setAllLayers] = useState([]); - const startYRef = useRef(); - const draggedElementRef = useRef(); - const dragItemRef = useRef(); - const dragOverItemRef = useRef(); - const [dragItem, setDragItem] = useState(); - const [dragOverItem, setDragOverItem] = useState(); useEffect(() => { // LISTEN FOR SEARCH RESULT const activeTocLayerListener = (layerItem) => { - if (props.visible) onActivateLayer(layerItem); + if (layersProps.visible) onActivateLayer(layerItem); }; window.emitter.addListener("activeTocLayer", activeTocLayerListener); window.addEventListener("resize", updateRecalcId); @@ -37,20 +29,20 @@ const Layers = (props) => { }, []); useEffect(() => { - if (props.group.layers && props.group.layers.length > 0) { - setAllLayers(props.group.layers); + if (layersProps.group.layers && layersProps.group.layers.length > 0) { + setAllLayers(layersProps.group.layers); setLayers( - props.group.layers.filter((layer) => { - if (props.searchText === "") return true; - else if (layer.tocDisplayName.toUpperCase().indexOf(props.searchText.toUpperCase()) !== -1) return true; + layersProps.group.layers.filter((layer) => { + if (layersProps.searchText === "") return true; + else if (layer.tocDisplayName.toUpperCase().indexOf(layersProps.searchText.toUpperCase()) !== -1) return true; else return false; }) ); } - }, [props.searchText, props.group]); + }, [layersProps.searchText, layersProps.group]); const updateRecalcId = () => { - if (!props.visible) return; + if (!layersProps.visible) return; try { lastPositionRef.current = document.getElementById(virtualId).scrollTop; } catch (e) { @@ -63,7 +55,7 @@ const Layers = (props) => { }; const onActivateLayer = (layerItem) => { - if (!props.visible) return; + if (!layersProps.visible) return; const elementId = layerItem.fullName + "_" + layerItem.layerGroup + "-container"; allLayers.forEach((layer) => { @@ -94,144 +86,47 @@ const Layers = (props) => { }); }; - const handleDragStart = (e) => { - startYRef.current = e.clientY; - draggedElementRef.current = e.target; - e.dataTransfer.effectAllowed = "move"; - // e.dataTransfer.setDragImage(e.target.firstChild.firstChild, 10, 10); - var di = new Image(); - // di.src = toDataURL("image/png"); - e.dataTransfer.setDragImage(di, 10, 10); - dragItemRef.current = e.target.id; - setDragItem(e.target.id); - }; - const handleDragLeave = (callback) => { - callback(dragOverItemRef.current); - }; - const handleDragEnter = (e) => { - e.preventDefault(); - if (e.currentTarget.id === dragItemRef.current || dragOverItemRef.current === e.currentTarget.id) return; - dragOverItemRef.current = e.currentTarget.id; - setDragOverItem(e.currentTarget.id); - }; - const handleDragEnd = () => { - const oldIndex = allLayers.indexOf(allLayers.find((layer) => props.id + "-" + helpers.getHash(layer.name) + "-container" === dragItemRef.current)); - const newIndex = allLayers.indexOf(allLayers.find((layer) => props.id + "-" + helpers.getHash(layer.name) + "-container" === dragOverItemRef.current)); - const oldIndexFiltered = layers.indexOf(layers.find((layer) => props.id + "-" + helpers.getHash(layer.name) + "-container" === dragItemRef.current)); - const newIndexFiltered = layers.indexOf(layers.find((layer) => props.id + "-" + helpers.getHash(layer.name) + "-container" === dragOverItemRef.current)); - const newLayers = [...layers]; - const movedLayer = newLayers.splice(oldIndexFiltered, 1); - newLayers.splice(newIndexFiltered, 0, movedLayer[0]); - // setLayers(newLayers); - - props.onSortEnd({ oldIndex: oldIndex, newIndex: newIndex }); - draggedElementRef.current.style.transform = ""; - dragItemRef.current = null; - dragOverItemRef.current = null; - setDragOverItem(null); - setDragItem(null); - }; - const handleDragCancel = () => { - draggedElementRef.current.style.transform = ""; - dragItemRef.current = null; - dragOverItemRef.current = null; - setDragOverItem(null); - setDragItem(null); - }; - const handleDragOver = (e) => { - e.preventDefault(); - const deltaY = e.clientY - startYRef.current; - draggedElementRef.current.style.transform = `translateY(${deltaY}px)`; - }; - - if (props.group.layers === undefined) return
; + if (layersProps.group.layers === undefined) return
; else return (
-
    - {layers.map((layer) => ( - - ))} -
+ { + if (layersProps.sortAlpha) return; + const oldIndexAllLayers = allLayers.indexOf(layers[oldIndex]); + const newIndexAllLayers = allLayers.indexOf(layers[newIndex]); + + setLayers(arrayMove(layers, oldIndex, newIndex)); + layersProps.onSortEnd({ oldIndex: oldIndexAllLayers, newIndex: newIndexAllLayers }); + }} + lockVertically={true} + beforeDrag={() => { + if (layersProps.sortAlpha) return; + }} + renderList={({ children, props }) => ( +
    + {children} +
+ )} + renderItem={({ value, props, isDragged, isSelected }) => ( +
  • + +
  • + )} + />
    ); }; export default Layers; - -const LayerListItem = (props) => { - const [open, setOpen] = useState(false); - const { layer, parent } = props; - - useEffect(() => { - if (props.id !== props.currentSelection) setOpen(false); - }, [props.currentSelection]); - const handleDragEnter = (e) => { - e.preventDefault(); - if (props.id !== props.draggedItem) setOpen(true); - props.onDragEnter(e); - }; - const handleDragLeave = (e) => { - e.preventDefault(); - }; - const handleDragEnd = () => { - setOpen(false); - props.onDragEnd(); - }; - const handleDragExit = () => { - setOpen(false); - props.onDragExit(); - }; - - return ( -
  • props.onDragStart(e)} - onDragEnter={(e) => handleDragEnter(e)} - onDragEnd={() => handleDragEnd()} - onDragExit={() => handleDragExit()} - onDragOver={(e) => props.onDragOver(e)} - onDragLeave={(e) => handleDragLeave(e)} - id={props.id} - draggable - style={{ - minHeight: "30px", - transition: "padding 50ms linear 50ms", - padding: open ? "0px 0px 30px 0px" : "", - border: "1px dashed #000", - }} - > - -
  • - ); -};