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 }) => (
+
+ )}
+ 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",
- }}
- >
-
-
- );
-};
From 776089a4c82a9b0ecb0bea0232068e40740ffe77 Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Fri, 26 Apr 2024 15:23:14 -0400
Subject: [PATCH 03/14] Updated to React18 (#231)
---
.env | 5 +
Dockerfile | 6 +-
package-lock.json | 39 +-
package.json | 4 +-
src/App.test.js | 9 +-
src/header/Header.jsx | 3 +-
src/helpers/AttributeTable.jsx | 40 +-
src/helpers/FloatingMenu.jsx | 23 +-
src/helpers/ModalWindowR.jsx | 37 +-
src/helpers/Popup.jsx | 17 +-
src/helpers/ShowMessage.jsx | 1 +
src/helpers/helpers.js | 120 ++-
src/index.js | 22 +-
src/layerInfo/App.test.js | 10 +-
src/layerInfo/index.js | 9 +-
src/legend/App.test.js | 9 +-
src/map/BasicBasemapSwitcher.jsx | 3 +-
src/map/SCMap.jsx | 4 +-
src/sidebar/Sidebar.jsx | 834 +++++++++---------
src/sidebar/components/mymaps/ColorPicker.jsx | 89 +-
src/sidebar/components/mymaps/MyMaps.jsx | 11 +-
.../components/mymaps/MyMapsFooter.jsx | 12 +-
.../localrealestate/LocalRealEstate.jsx | 11 +-
src/sidebar/components/toc/TOC.jsx | 13 +-
.../components/toc/common/LayerLegend.jsx | 81 +-
.../components/toc/common/TOCHeader.jsx | 4 +-
.../toc/toc-folder-view/GroupItem.jsx | 3 +-
.../components/toc/toc-folder-view/Layers.jsx | 2 +-
.../toc/toc-folder-view/TOCFolderView.css | 6 +-
29 files changed, 764 insertions(+), 663 deletions(-)
create mode 100644 .env
diff --git a/.env b/.env
new file mode 100644
index 00000000..87c01f4e
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+REACT_APP_SECURED="false"
+REACT_APP_TENANT="TENANT_ID"
+REACT_APP_DEFAULT_SCOPE="DEFAULT_SCOPE"
+REACT_APP_CLIENTID="CLIENT_ID"
+REACT_APP_AUTHORITY="AUTHORITY"
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 674242c7..ccb3f74c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,7 @@
#Stage 1
-FROM node:18-alpine
-# Create app directory
-WORKDIR /app
+# FROM node:18-alpine
+# # Create app directory
+# WORKDIR /app
FROM nginx:1.25.0-alpine
WORKDIR /usr/share/nginx/html
RUN rm -rf ./*
diff --git a/package-lock.json b/package-lock.json
index 1ef0c98f..d8d8b9b6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,13 +25,13 @@
"rc-menu": "^9.11.1",
"rc-slider": "^9.7.5",
"re-resizable": "^6.9.1",
- "react": "^17.0.2",
+ "react": "^18.2.0",
"react-collapsible": "^2.10.0",
"react-color": "^2.19.3",
"react-copy-to-clipboard": "^5.0.4",
"react-datepicker": "^4.16.0",
"react-device-detect": "^2.2.3",
- "react-dom": "^17.0.2",
+ "react-dom": "^18.2.0",
"react-ga4": "^2.0.0",
"react-highlight-words": "^0.20.0",
"react-icons": "^4.8.0",
@@ -3903,9 +3903,9 @@
}
},
"node_modules/@rc-component/trigger": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.0.0.tgz",
- "integrity": "sha512-niwKADPdY5dhdIblV6uwSayVivwo2uUISfJqri+/ovYQcH/omxDYBJKo755QKeoIIsWptxnRpgr7reEnNEZGFg==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.1.1.tgz",
+ "integrity": "sha512-UjHkedkgtEcgQu87w1VuWug1idoDJV7VUt0swxHXRcmei2uu1AuUzGBPEUlmOmXGJ+YtTgZfVLi7kuAUKoZTMA==",
"dependencies": {
"@babel/runtime": "^7.23.2",
"@rc-component/portal": "^1.1.0",
@@ -15372,12 +15372,11 @@
}
},
"node_modules/react": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
- "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"dependencies": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1"
+ "loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
@@ -15562,16 +15561,15 @@
}
},
"node_modules/react-dom": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
- "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"dependencies": {
"loose-envify": "^1.1.0",
- "object-assign": "^4.1.1",
- "scheduler": "^0.20.2"
+ "scheduler": "^0.23.0"
},
"peerDependencies": {
- "react": "17.0.2"
+ "react": "^18.2.0"
}
},
"node_modules/react-error-overlay": {
@@ -16534,12 +16532,11 @@
}
},
"node_modules/scheduler": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
- "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"dependencies": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1"
+ "loose-envify": "^1.1.0"
}
},
"node_modules/schema-utils": {
diff --git a/package.json b/package.json
index 3b204cfd..eceeef0c 100644
--- a/package.json
+++ b/package.json
@@ -21,13 +21,13 @@
"rc-menu": "^9.11.1",
"rc-slider": "^9.7.5",
"re-resizable": "^6.9.1",
- "react": "^17.0.2",
+ "react": "^18.2.0",
"react-collapsible": "^2.10.0",
"react-color": "^2.19.3",
"react-copy-to-clipboard": "^5.0.4",
"react-datepicker": "^4.16.0",
"react-device-detect": "^2.2.3",
- "react-dom": "^17.0.2",
+ "react-dom": "^18.2.0",
"react-ga4": "^2.0.0",
"react-highlight-words": "^0.20.0",
"react-icons": "^4.8.0",
diff --git a/src/App.test.js b/src/App.test.js
index 635a333f..0d5b554a 100644
--- a/src/App.test.js
+++ b/src/App.test.js
@@ -1,9 +1,10 @@
import React from "react";
-import ReactDOM from "react-dom";
+import { createRoot } from "react-dom/client";
import App from "./App";
it("renders without crashing", () => {
- const div = document.createElement("div");
- ReactDOM.render(
, div);
- ReactDOM.unmountComponentAtNode(div);
+ const div = document.createElement("div");
+ const root = createRoot(div); // createRoot(container!) if you use TypeScript
+ root.render(
);
+ root.unmount();
});
diff --git a/src/header/Header.jsx b/src/header/Header.jsx
index 9875d130..375c3a6d 100644
--- a/src/header/Header.jsx
+++ b/src/header/Header.jsx
@@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react";
-import ReactDOM from "react-dom";
import "./Header.css";
import Search from "./Search.jsx";
import * as helpers from "../helpers/helpers";
@@ -50,7 +49,7 @@ const Header = (props) => {
);
- ReactDOM.render(menu, document.getElementById("portal-root"));
+ window.portalRoot.render(menu);
helpers.addAppStat("Header Dot Menu", "Click");
};
diff --git a/src/helpers/AttributeTable.jsx b/src/helpers/AttributeTable.jsx
index 10723d42..e07dbdfb 100644
--- a/src/helpers/AttributeTable.jsx
+++ b/src/helpers/AttributeTable.jsx
@@ -1,4 +1,4 @@
-import React, { Component } from "react";
+import React, { Component, useEffect } from "react";
import * as helpers from "./helpers";
import "./AttributeTable.css";
import { Resizable } from "re-resizable";
@@ -6,12 +6,12 @@ import AttributeTableTabs from "./AttributeTableTabs.jsx";
import FloatingMenu, { FloatingMenuItem } from "../helpers/FloatingMenu.jsx";
import { Item as MenuItem } from "rc-menu";
import Portal from "../helpers/Portal.jsx";
-import ReactDOM from "react-dom";
+import { createRoot } from "react-dom/client";
class AttrbuteTable extends Component {
constructor(props) {
super(props);
-
+ this.resizable = {};
this.numRecordsToPull = 200;
this.state = {
visible: false,
@@ -44,6 +44,7 @@ class AttrbuteTable extends Component {
resizeFromMap = () => {
const mapWidth = document.getElementById("map").offsetWidth;
+ if (!this.resizable) return;
this.resizable.updateSize({
width: mapWidth,
height: this.resizable.resizable.offsetHeight,
@@ -195,7 +196,21 @@ class AttrbuteTable extends Component {
);
- ReactDOM.render(menu, document.getElementById("portal-root"));
+ const uniqueId = `portal-root-${"attribute-table-header"}}`;
+ const element = document.createElement("div");
+ element.setAttribute("id", uniqueId);
+ document.getElementById("portal-root").appendChild(element);
+ const root = createRoot(document.getElementById(uniqueId));
+ const MenuWithCallback = () => {
+ useEffect(() => {
+ return () => {
+ root.unmount();
+ document.getElementById(uniqueId).remove();
+ };
+ }, []);
+ return menu;
+ };
+ root.render(
);
};
onRowClick = (evt, item, rowIndex) => {
@@ -217,7 +232,22 @@ class AttrbuteTable extends Component {
);
- ReactDOM.render(menu, document.getElementById("portal-root"));
+ const uniqueId = `portal-root-${"attribute-table-row"}`;
+ const element = document.createElement("div");
+ element.setAttribute("id", uniqueId);
+ document.getElementById("portal-root").appendChild(element);
+ const root = createRoot(document.getElementById(uniqueId));
+ const MenuWithCallback = () => {
+ useEffect(() => {
+ return () => {
+ root.unmount();
+ document.getElementById(uniqueId).remove();
+ };
+ }, []);
+ return menu;
+ };
+
+ root.render(
);
};
onRowMenuItemClick = (key, item, rowIndex) => {
diff --git a/src/helpers/FloatingMenu.jsx b/src/helpers/FloatingMenu.jsx
index 752ea046..ae4c123d 100644
--- a/src/helpers/FloatingMenu.jsx
+++ b/src/helpers/FloatingMenu.jsx
@@ -7,13 +7,16 @@ import { waitForLoad } from "./helpers";
// PROPER USE OF THIS COMPONENT IS TO USE A PORTAL. HAVE A LOOK AT MyMapsItem FOR AN EXAMPLE.
const FloatingMenu = (props) => {
+ let { positionX, positionY } = props;
+ if (positionX === undefined) positionX = props.buttonEvent.pageX;
+ if (positionY === undefined) positionY = props.buttonEvent.pageY;
const isMounted = useRef(false);
const [isVisible, setIsVisible] = useState(true);
const [style, setStyle] = useState({
position: "absolute",
zIndex: 10000,
- top: props.buttonEvent.pageY,
- left: props.buttonEvent.pageX,
+ top: positionY,
+ left: positionX,
backgroundColor: "white",
width: "180px",
});
@@ -36,7 +39,7 @@ const FloatingMenu = (props) => {
getStyle((newStyle) => {
setStyle(newStyle);
});
- }, [props.autoX, props.autoY, props.buttonEvent.pageX, props.buttonEvent.pageY, props.styleMode]);
+ }, [props.autoX, props.autoY, props.buttonEvent.pageX, props.buttonEvent.pageY, props.styleMode, props.positionX, props.positionY, props.yOffset, props.xOffset, props.width]);
const cleanup = () => {
document.body.removeEventListener("click", handleClickAway, true);
container.current = null;
@@ -89,17 +92,17 @@ const FloatingMenu = (props) => {
}
if (props.styleMode === "right") {
- xOffset = props.buttonEvent.pageX;
+ xOffset = positionX;
} else if (props.styleMode === "left") {
- xOffset = props.buttonEvent.pageX - 180;
+ xOffset = positionX - 180;
} else if (props.autoX) {
- if (props.buttonEvent.pageX < 180) {
- xOffset = props.buttonEvent.pageX;
+ if (positionX < 180) {
+ xOffset = positionX;
} else {
- xOffset = props.buttonEvent.pageX - 180;
+ xOffset = positionX - 180;
}
} else {
- xOffset = props.buttonEvent.pageX;
+ xOffset = positionX;
}
if (props.yOffset !== undefined) yOffset = props.yOffset;
@@ -108,7 +111,7 @@ const FloatingMenu = (props) => {
style = {
position: "absolute",
zIndex: 1000,
- top: props.buttonEvent.pageY - yOffset,
+ top: positionY - yOffset,
//left: this.state.styleMode === "right" ? this.props.buttonEvent.pageX : this.props.buttonEvent.pageX - 180,
left: xOffset,
backgroundColor: "white",
diff --git a/src/helpers/ModalWindowR.jsx b/src/helpers/ModalWindowR.jsx
index c54dfc06..801aa436 100644
--- a/src/helpers/ModalWindowR.jsx
+++ b/src/helpers/ModalWindowR.jsx
@@ -1,28 +1,25 @@
import React from "react";
-import ReactDOM from "react-dom";
import Modal from "react-responsive-modal";
export default class ModalWindowR extends React.Component {
- state = {
- open: this.props.open ? true : false,
- };
+ state = {
+ open: this.props.open ? true : false,
+ };
- onOpenModal = () => {
- this.setState({ open: true });
- };
+ onOpenModal = () => {
+ this.setState({ open: true });
+ };
- onCloseModal = () => {
- this.setState({ open: false });
- };
+ onCloseModal = () => {
+ this.setState({ open: false });
+ };
- render() {
- const { open } = this.state;
- return (
-
- Simple centered modal
-
- );
- }
+ render() {
+ const { open } = this.state;
+ return (
+
+ Simple centered modal
+
+ );
+ }
}
-
-//ReactDOM.render(
, document.getElementById('root'));
diff --git a/src/helpers/Popup.jsx b/src/helpers/Popup.jsx
index bc8729ee..01e52b8b 100644
--- a/src/helpers/Popup.jsx
+++ b/src/helpers/Popup.jsx
@@ -1,6 +1,7 @@
// THIS CODE WAS PULLED FROM https://github.com/walkermatt/ol-popup
import React from "react";
-import ReactDOM from "react-dom";
+import { createRoot } from "react-dom/client";
+
import Overlay from "ol/Overlay";
import "./Popup.css";
import { getWidth } from "ol/extent.js";
@@ -67,7 +68,6 @@ export default class Popup extends Overlay {
this.contentNextButton.href = "#";
this.contentNextButtonContainer.appendChild(this.contentNextButton);
this.contentPrevButtonContainer.appendChild(this.contentPrevButton);
-
this.contentNextButton.addEventListener("click", () => {
this.contentIndex++;
if (this.contentIndex >= this.contentArray.length) {
@@ -84,16 +84,14 @@ export default class Popup extends Overlay {
this.contentNextButtonContainer.className = "sc-popup-content-next-button";
this.contentPrevButtonContainer.className = "sc-popup-content-prev-button";
}
-
this.headerTitle.innerHTML = this.contentArray[this.contentIndex].title || "Info";
- //ReactDOM.render(html, this.content);
if (isDOMTypeElement(this.contentArray[this.contentIndex].html)) {
// REGULAR HTML
this.content.innerHTML = "";
this.content.appendChild(this.contentArray[this.contentIndex].html);
} else {
// REACT COMPONENT
- ReactDOM.render(this.contentArray[this.contentIndex].html, this.content);
+ this.root.render(this.contentArray[this.contentIndex].html);
}
});
this.contentPrevButton.addEventListener("click", () => {
@@ -113,14 +111,13 @@ export default class Popup extends Overlay {
}
// SET TITLE
this.headerTitle.innerHTML = this.contentArray[this.contentIndex].title;
- //ReactDOM.render(html, this.content);
if (isDOMTypeElement(this.contentArray[this.contentIndex].html)) {
// REGULAR HTML
this.content.innerHTML = "";
this.content.appendChild(this.contentArray[this.contentIndex].html);
} else {
// REACT COMPONENT
- ReactDOM.render(this.contentArray[this.contentIndex].html, this.content);
+ this.root.render(this.contentArray[this.contentIndex].html);
}
});
this.headerCloseContainer = document.createElement("div");
@@ -162,6 +159,9 @@ export default class Popup extends Overlay {
this.content = document.createElement("div");
this.content.className = "ol-popup-content";
+ this.uniqueId = `sc-popup-content-${helpers.getUID()}}`;
+ this.content.setAttribute("id", this.uniqueId);
+ this.root = createRoot(this.content);
this.container.appendChild(this.content);
// Apply workaround to enable scrolling of content div on touch devices
@@ -225,14 +225,13 @@ export default class Popup extends Overlay {
// SET TITLE
this.headerTitle.innerHTML = title;
- //ReactDOM.render(html, this.content);
if (isDOMTypeElement(html)) {
// REGULAR HTML
this.content.innerHTML = "";
this.content.appendChild(html);
} else {
// REACT COMPONENT
- ReactDOM.render(html, this.content);
+ this.root.render(html);
}
this.container.style.display = "block";
diff --git a/src/helpers/ShowMessage.jsx b/src/helpers/ShowMessage.jsx
index 39997a21..cafb725b 100644
--- a/src/helpers/ShowMessage.jsx
+++ b/src/helpers/ShowMessage.jsx
@@ -27,6 +27,7 @@ class ShowMessage extends Component {
this._isMounted = false;
}
onCloseClick = (value) => {
+ if (this.props.onClose) this.props.onClose(value);
if (this._isMounted) this.setState({ hide: true });
};
diff --git a/src/helpers/helpers.js b/src/helpers/helpers.js
index a90683c0..baa2e699 100644
--- a/src/helpers/helpers.js
+++ b/src/helpers/helpers.js
@@ -1,6 +1,6 @@
// REACT
-import React from "react";
-import ReactDOM from "react-dom";
+import React, { useEffect } from "react";
+import { createRoot } from "react-dom/client";
// OPEN LAYERS
import Feature from "ol/Feature";
@@ -123,22 +123,58 @@ export function isMobile() {
// SHOW CONTENT WINDOW
export function showWindow(contents, options = { title: "Information", showFooter: false, mode: "normal", hideScroll: false }) {
- ReactDOM.render(
-
,
- document.getElementById("map-modal-window")
- );
+ const uniqueId = `map-modal-window-${getUID()}}`;
+ const element = document.createElement("div");
+ element.setAttribute("id", uniqueId);
+ document.getElementById("map-modal-window").appendChild(element);
+ const root = createRoot(document.getElementById(uniqueId));
+
+ const ShowWindowWithCallback = (props) => {
+ useEffect(() => {
+ return () => {
+ try {
+ root.unmount();
+ document.getElementById(uniqueId).remove();
+ } catch (err) {
+ console.log(err);
+ }
+ };
+ }, []);
+ return
;
+ };
+ root.render(
);
}
// SHOW URL WINDOW
export function showURLWindow(url, showFooter = false, mode = "normal", honorDontShow = false, hideScroll = false) {
let isSameOrigin = true;
+ const uniqueId = `map-modal-window-${getUID()}}`;
+ const element = document.createElement("div");
+ element.setAttribute("id", uniqueId);
+ document.getElementById("map-modal-window").appendChild(element);
+ const root = createRoot(document.getElementById(uniqueId));
+
+ const URLWindowWithCallback = (props) => {
+ useEffect(() => {
+ return () => {
+ try {
+ root.unmount();
+ document.getElementById(uniqueId).remove();
+ } catch (err) {
+ console.log(err);
+ }
+ };
+ }, []);
+ return
;
+ };
+
waitForLoad("settings", Date.now(), 30, () => {
if (window.config.restrictOriginForUrlWindow) {
if (url !== undefined) isSameOrigin = url.toLowerCase().indexOf(window.location.origin.toLowerCase()) !== -1;
}
if (isSameOrigin) {
- ReactDOM.render(
, document.getElementById("map-modal-window"));
+ root.render(
);
} else {
window.open(url, "_blank");
}
@@ -414,7 +450,7 @@ export function showTerms(title = "Terms and Condition", messageText = "Message"
const domId = "portal-root";
const termsDomId = "sc-show-terms-root";
- ReactDOM.render(
+ window.portalRoot.render(
{
try {
- ReactDOM.unmountComponentAtNode(ref.current.parentNode);
+ window.portalRoot.unmount();
} catch (err) {
console.log(err);
}
}}
- />,
- document.getElementById("portal-root")
+ />
);
}
@@ -442,24 +477,42 @@ export function showMessage(title = "Info", messageText = "Message", color = mes
const domId = "sc-show-message-content";
var existingMsg = document.getElementById(domId);
if (existingMsg !== undefined && existingMsg !== null) existingMsg.remove();
- try {
- ReactDOM.unmountComponentAtNode(document.getElementById("sc-sidebar-message-container"));
- } catch {}
- const message = ReactDOM.render(
- ,
- document.getElementById("sc-sidebar-message-container"),
- () => {
+ const uniqueId = `sc-sidebar-message-container-${getUID()}}`;
+ const messageElement = document.createElement("div");
+ messageElement.setAttribute("id", uniqueId);
+ document.getElementById("sc-sidebar-message-container").appendChild(messageElement);
+
+ const root = createRoot(document.getElementById(uniqueId), { identifierPrefix: getUID() });
+
+ const ShowMessageWithCallback = (props) => {
+ const handleOnClose = () => {
+ try {
+ root.unmount();
+ document.getElementById(uniqueId).remove();
+ } catch (err) {
+ console.log(err);
+ }
+ };
+ useEffect(() => {
setTimeout(() => {
try {
- ReactDOM.unmountComponentAtNode(document.getElementById("sc-sidebar-message-container"));
+ handleOnClose();
} catch (err) {
console.log(err);
}
- }, timeout);
- }
- );
+ }, props.timeout);
+ return () => {
+ try {
+ if (props.onClose) props.onClose();
+ } catch (err) {
+ console.log(err);
+ }
+ };
+ }, [props.timeout]);
+ return ;
+ };
+ root.render();
}
-
export function searchArrayByKey(nameKey, myArray) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i].name === nameKey) {
@@ -1184,7 +1237,7 @@ function _escapeRegExp(str) {
}
export function showFeaturePopup(coord, feature) {
- window.popup.show(coord, );
+ window.popup.show(coord, , feature.get("layerDisplayName") || "Feature Info");
}
export function removeURLParameter(url, parameter) {
@@ -1211,7 +1264,22 @@ export function FilterKeys(feature) {
//WILDCARD = .*
//LITERAL STRING = [] EG: [_][.]
//NOT STRING = (?!string) EG: geostasis[.](?!test).*
- const filterKeys = ["[_].*", "id", "geometry", "geom", "extent_geom", ".*gid.*", "globalid", "objectid.*", "shape.*", "displayfieldname", "displayfieldvalue", "geostasis[.].*", ".*fid.*"];
+ const filterKeys = [
+ "[_].*",
+ "id",
+ "geometry",
+ "geom",
+ "extent_geom",
+ ".*gid.*",
+ "globalid",
+ "objectid.*",
+ "shape.*",
+ "displayfieldname",
+ "displayfieldvalue",
+ "layerdisplayname",
+ "geostasis[.].*",
+ ".*fid.*",
+ ];
const featureProps = feature.getProperties();
let keys = Object.keys(featureProps);
@@ -1403,7 +1471,7 @@ export function getBase64FromImageUrl(url, callback) {
export function waitForLoad(items, startTime = Date.now(), timeout = 30, callback) {
if (startTime + timeout * 1000 <= Date.now()) {
showMessage("Timeout", "Items Failed to load in a timely manner. Please reload the page", messageColors.red);
- console.error("timeout loading", items);
+ console.error("timeout loading", items, window.loaded);
} else {
if (isLoaded(items)) {
callback();
diff --git a/src/index.js b/src/index.js
index df59ac05..76656eba 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,28 +1,36 @@
// import 'react-app-polyfill/ie11';
import React from "react";
-import ReactDOM from "react-dom";
+import { createRoot } from "react-dom/client";
+
import "./index.css";
import * as serviceWorker from "./serviceWorker";
import { MsalProvider } from "@azure/msal-react";
import { Configuration, PublicClientApplication } from "@azure/msal-browser";
import "alertifyjs/build/css/alertify.css";
import "alertifyjs/build/css/themes/default.min.css";
+
+const root = createRoot(document.getElementById("root"));
+let element = document.createElement("div");
+element.setAttribute("id", "portal-root");
+document.getElementById("root").appendChild(element);
+window.portalRoot = createRoot(document.getElementById("portal-root"));
+
if (process.env.REACT_APP_SECURED === "true") {
import(`./AppSecure.jsx`)
.then((module) => {
const AppSecure = module.default;
// MSAL configuration
- const configuration: Configuration = {
+ const configuration = Configuration({
auth: {
clientId: process.env.REACT_APP_CLIENTID,
},
- };
+ });
const pca = new PublicClientApplication(configuration);
- ReactDOM.render(
+
+ root.render(
- ,
- document.getElementById("root")
+
);
})
.catch((error) => {
@@ -32,7 +40,7 @@ if (process.env.REACT_APP_SECURED === "true") {
import(`./App.js`)
.then((module) => {
const App = module.default;
- ReactDOM.render(, document.getElementById("root"));
+ root.render();
})
.catch((error) => {
console.log(error);
diff --git a/src/layerInfo/App.test.js b/src/layerInfo/App.test.js
index 635a333f..bb0dc284 100644
--- a/src/layerInfo/App.test.js
+++ b/src/layerInfo/App.test.js
@@ -1,9 +1,11 @@
import React from "react";
-import ReactDOM from "react-dom";
+import { createRoot } from "react-dom/client";
import App from "./App";
it("renders without crashing", () => {
- const div = document.createElement("div");
- ReactDOM.render(, div);
- ReactDOM.unmountComponentAtNode(div);
+ const div = document.createElement("div");
+
+ const root = createRoot(div); // createRoot(container!) if you use TypeScript
+ root.render();
+ root.unmount();
});
diff --git a/src/layerInfo/index.js b/src/layerInfo/index.js
index 781cb802..cecbde2b 100644
--- a/src/layerInfo/index.js
+++ b/src/layerInfo/index.js
@@ -1,10 +1,15 @@
import React from "react";
-import ReactDOM from "react-dom";
+import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
-ReactDOM.render(, document.getElementById("root"));
+const uniqueId = `root-${"layerInfo"}}`;
+const element = document.createElement("div");
+element.setAttribute("id", uniqueId);
+document.getElementById("root").appendChild(element);
+const root = createRoot(document.getElementById(uniqueId));
+root.render();
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
diff --git a/src/legend/App.test.js b/src/legend/App.test.js
index 635a333f..0d5b554a 100644
--- a/src/legend/App.test.js
+++ b/src/legend/App.test.js
@@ -1,9 +1,10 @@
import React from "react";
-import ReactDOM from "react-dom";
+import { createRoot } from "react-dom/client";
import App from "./App";
it("renders without crashing", () => {
- const div = document.createElement("div");
- ReactDOM.render(, div);
- ReactDOM.unmountComponentAtNode(div);
+ const div = document.createElement("div");
+ const root = createRoot(div); // createRoot(container!) if you use TypeScript
+ root.render();
+ root.unmount();
});
diff --git a/src/map/BasicBasemapSwitcher.jsx b/src/map/BasicBasemapSwitcher.jsx
index b42bbc5e..48d10e59 100644
--- a/src/map/BasicBasemapSwitcher.jsx
+++ b/src/map/BasicBasemapSwitcher.jsx
@@ -1,5 +1,4 @@
import React, { useState, useRef, useContext, useEffect } from "react";
-import ReactDOM from "react-dom";
import Slider from "rc-slider";
import "./BasicBasemapSwitcher.css";
import * as helpers from "../helpers/helpers";
@@ -186,7 +185,7 @@ const BasicBasemapSwitcher = (props) => {
);
- ReactDOM.render(menu, document.getElementById("portal-root"));
+ window.portalRoot.render(menu);
};
const controlStateChange = (control, state) => {
diff --git a/src/map/SCMap.jsx b/src/map/SCMap.jsx
index f0bddbd1..550d4dfa 100644
--- a/src/map/SCMap.jsx
+++ b/src/map/SCMap.jsx
@@ -1,5 +1,4 @@
import React, { useState, useRef, useEffect, Fragment } from "react";
-import ReactDOM from "react-dom";
// import GitHubButton from "react-github-btn";
import GitHubButton from "../components/sc-github-btn";
//OPENLAYERS
@@ -230,7 +229,8 @@ const SCMap = (props) => {
);
- ReactDOM.render(menu, document.getElementById("portal-root"));
+
+ window.portalRoot.render(menu);
});
// APP STAT
diff --git a/src/sidebar/Sidebar.jsx b/src/sidebar/Sidebar.jsx
index 599c4488..6d61cc50 100644
--- a/src/sidebar/Sidebar.jsx
+++ b/src/sidebar/Sidebar.jsx
@@ -1,4 +1,5 @@
-import React, { Component } from "react";
+import React, { useState, useRef, useEffect } from "react";
+import { flushSync } from "react-dom";
import "./Sidebar.css";
import * as helpers from "../helpers/helpers";
@@ -13,179 +14,165 @@ import SidebarComponent from "../components/sc-sidebar.jsx";
import SidebarSlim from "./SidebarSlim.jsx";
import MenuButton from "./MenuButton.jsx";
-class Sidebar extends Component {
- constructor(props) {
- super(props);
-
- // BIND THIS FUNCTIONS
- this.togglePanelVisibility = this.togglePanelVisibility.bind(this);
- this.activateSidebarItem = this.activateSidebarItem.bind(this);
- this.onPanelComponentClose = this.onPanelComponentClose.bind(this);
- this.onSetSidebarOpen = this.onSetSidebarOpen.bind(this);
-
- this.state = {
- // TOOLS AND THEMES ARE IN HERE
- toolComponents: [],
-
- // CLASSES
- tabClassName: "sidebar-advanced-tab",
- sidebarOpen: false,
- tocLoaded: false,
- // SELECTED TAB
- tabIndex: 0,
- isMyMapsEditing: false,
- //hide components
- hideTools: false,
- hideThemes: false,
- hideLayers: false,
- hideMyMaps: false,
- hideReports: false,
- //TAB CONFIG ITEMS
- layers: {
- title: "Layers",
- icon: "legend-32x32.png",
- },
- tools: {
- title: "Tools",
- icon: "tools-32x32.png",
- },
- myMaps: {
- title: "My Maps",
- icon: "map-32x32.png",
- },
- themes: {
- title: "Themes",
- icon: "theme-32x32.png",
- },
- reports: {
- title: "Reports",
- icon: "report-32x32.png",
- },
- // COMPONENTS
- activeTabComponents: {
- layers: ,
- mymaps: ,
- reports: {
- default: ,
- loadedComponent: null,
- },
- tools: {
- default: ,
- loadedComponent: null,
- },
- themes: {
- default: ,
- loadedComponent: null,
- },
- },
- };
- // LISTEN FOR TOC TO LOAD
- window.emitter.addListener("tocLoaded", () => this.setState({ tocLoaded: true }));
- }
-
- onMyMapsEditing = (isMyMapsEditing) => {
+const Sidebar = (props) => {
+ const toolComponentsRef = useRef([]);
+
+ const toolComponentsLoaded = useRef(false);
+ const mapLoadingRef = useRef(props.mapLoading);
+ const headerLoadingRef = useRef(props.headerLoading);
+
+ const tabClassName = "sidebar-advanced-tab";
+ const [sidebarOpen, setSidebarOpen] = useState(false);
+ const [tabIndex, setTabIndex] = useState(0);
+ const [isMyMapsEditing, setIsMyMapsEditing] = useState(false);
+ const [hideTools, setHideTools] = useState(false);
+ const [hideThemes, setHideThemes] = useState(false);
+ const [hideLayers, setHideLayers] = useState(false);
+ const [hideMyMaps, setHideMyMaps] = useState(false);
+ const [hideReports, setHideReports] = useState(false);
+
+ const layers = {
+ title: "Layers",
+ icon: "legend-32x32.png",
+ };
+ const [tools, setTools] = useState({
+ title: "Tools",
+ icon: "tools-32x32.png",
+ });
+ const myMaps = {
+ title: "My Maps",
+ icon: "map-32x32.png",
+ };
+ const [themes, setThemes] = useState({
+ title: "Themes",
+ icon: "theme-32x32.png",
+ });
+ const reports = {
+ title: "Reports",
+ icon: "report-32x32.png",
+ };
+ const onMyMapsEditing = (isMyMapsEditingLocal) => {
// DISABLE PARCEL CLICK
- window.disableParcelClick = isMyMapsEditing;
+ window.disableParcelClick = isMyMapsEditingLocal;
// DISABLE POPUPS
- window.isDrawingOrEditing = isMyMapsEditing;
-
- this.setState({ isMyMapsEditing });
+ window.isDrawingOrEditing = isMyMapsEditingLocal;
+ setIsMyMapsEditing(isMyMapsEditingLocal);
};
+ // TOOL AND THEME ITEMS CLICK
+ const activateSidebarItem = (name, type, options = undefined) => {
+ // THIS HANDLES WHAT TOOL/THEME IS LOADED IN THE SIDEBAR
+ if (type === "tools") {
+ toolComponentsRef.current.map((Component) => {
+ if (Component.props.name.toLowerCase() === name.toLowerCase()) {
+ // CREATE TOOL COMPONENT
+ var comp = (
+ togglePanelVisibility()}
+ config={Component.props.config}
+ options={options}
+ />
+ );
+ setToolTabComponent(comp);
+ return comp;
+ } else return null;
+ });
- onSetSidebarOpen(open) {
- this.setState({ sidebarOpen: open });
- }
-
- addComponent = (componentConfig, typeFolder, callback = undefined) => {
- // THIS IMPORTS THE COMPONENTS
- //console.log(`Loading ${componentConfig.name} component...`);
- const typeLowerCase = `${componentConfig.componentName}`.toLowerCase().replace(/\s/g, "");
- const path = `./components/${typeFolder}/${typeLowerCase}/${componentConfig.componentName}.jsx`;
-
- import(`${path}`)
- .then((component) => {
- // SET PROPS FROM CONFIG
- let comp = component.default;
- comp.props = [];
- comp.props.active = false;
- comp.props.id = helpers.getUID();
- comp.props.description = componentConfig.description;
- comp.props.name = componentConfig.name;
- comp.props.componentName = componentConfig.componentName;
- comp.props.helpLink = componentConfig.helpLink;
- comp.props.config = componentConfig.config;
- if (componentConfig.hideHeader !== undefined) comp.props.hideHeader = componentConfig.hideHeader;
-
- // ADD COMPONENT TO LIST
- this.setState(
- {
- toolComponents: this.state.toolComponents.concat(comp),
- },
- callback("success")
- );
- })
- .catch((error) => {
- console.log(error);
- console.error(`"${componentConfig.name}" not yet supported`);
- callback("failure");
- })
- .finally(() => {
- if (callback === undefined) return "Done";
+ helpers.addAppStat("Tool", name);
+ } else {
+ toolComponentsRef.current.map((Component) => {
+ if (Component.props.name.toLowerCase() === name.toLowerCase()) {
+ // CREATE THEME COMPONENT
+ var comp = (
+ togglePanelVisibility()}
+ config={Component.props.config}
+ options={options}
+ />
+ );
+ setThemeTabComponent(comp);
+ return comp;
+ } else return null;
});
- };
- componentDidMount() {
+ helpers.addAppStat("Theme", name);
+ }
+ };
+ const defaultLayersTabComponentGUID = helpers.getUID();
+ const defaultToolTabComponentGUID = helpers.getUID();
+ const defaultThemeTabComponentGUID = helpers.getUID();
+ const defaultMyMapTabComponentGUID = helpers.getUID();
+ const defaultReportTabComponentGUID = helpers.getUID();
+ const defaultLayersTabComponent = ;
+ const defaultToolTabComponent = ;
+ const defaultThemeTabComponent = ;
+ const defaultMyMapTabComponent = ;
+ const defaultReportTabComponent = ;
+
+ const [activeLayersTabComponent, setLayersTabComponent] = useState(defaultLayersTabComponent);
+ const [activeToolTabComponent, setToolTabComponent] = useState(null);
+ const [activeThemeTabComponent, setThemeTabComponent] = useState(null);
+ const [activeMyMapTabComponent, setMyMapTabComponent] = useState(defaultMyMapTabComponent);
+ const [activeReportTabComponent, setReportTabComponent] = useState(null);
+
+ useEffect(() => {
// LISTEN FOR ITEM ACTIVATION FROM OTHER COMPONENTS
- window.emitter.addListener("activateSidebarItem", (name, type, options = undefined) => {
- helpers.waitForLoad("sidebar", Date.now(), 30, () => {
- this.activateItemFromEmmiter(name, type, options);
- });
- });
+ window.emitter.addListener("activateSidebarItem", activateItemFromEmmiter);
+
// LISTEN FOR OPEN OR CLOSE FROM OTHER COMPONENTS (CLOSE OR OPEN)
- window.emitter.addListener("setSidebarVisiblity", (openOrClose) => {
- helpers.waitForLoad("sidebar", Date.now(), 30, () => {
- this.sidebarVisiblityEventHandler(openOrClose);
- });
- });
+ window.emitter.addListener("setSidebarVisiblity", sidebarVisiblityEventHandler);
// LISTEN FOR TAB ACTIVATION FROM OTHER COMPONENTS
- window.emitter.addListener("activateTab", (tabName) => {
- helpers.waitForLoad("sidebar", Date.now(), 30, () => {
- this.activateTab(tabName);
- });
- });
+ window.emitter.addListener("activateTab", activateTab);
// LISTEN FOR REPORT LOADING
- window.emitter.addListener("loadReport", (content) => {
- helpers.waitForLoad("sidebar", Date.now(), 30, () => {
- this.loadReport(content);
- });
- });
+ window.emitter.addListener("loadReport", loadReport);
+ initSidebar();
+
+ return () => {
+ window.emitter.removeListener("activateSidebarItem", activateItemFromEmmiter);
+ window.emitter.removeListener("setSidebarVisiblity", sidebarVisiblityEventHandler);
+ window.emitter.removeListener("activateTab", activateTab);
+ window.emitter.removeListener("loadReport", loadReport);
+ };
+ }, []);
+
+ const initSidebar = () => {
helpers.waitForLoad("settings", Date.now(), 30, () => {
// IMPORT TOOLS FROM CONFIG and CHECK VISIBILITY
let tools = window.config.sidebarToolComponents;
tools = tools.filter((item) => item.enabled === undefined || item.enabled);
if (tools.length === 1) {
- this.setState({ tools: { title: tools[0].name, icon: tools[0].imageName } });
+ setTools({ title: tools[0].name, icon: tools[0].imageName });
tools[0]["hideHeader"] = true;
}
- if (tools.length === 0 || (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideTools"])) this.setState({ hideTools: true });
- let loadedTools = [];
- let toolsProcessed = 0;
- tools.map((component) =>
- this.addComponent(component, "tools", (result) => {
- if (result === "success") loadedTools.push(component);
- else {
- window.config.sidebarToolComponents = window.config.sidebarToolComponents.map((item) => {
- if (component.name === item.name) item["enabled"] = false;
- return item;
+ if (tools.length === 0 || (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideTools"])) setHideTools(true);
+ let componentPromises = [];
+ componentPromises.push(
+ ...tools.map((component) => {
+ return new Promise((resolve, reject) => {
+ addComponent(component, "tools", (result) => {
+ if (result) {
+ resolve({ component: result, type: "tools", loadedComponent: component });
+ } else {
+ window.config.sidebarToolComponents = window.config.sidebarToolComponents.map((item) => {
+ if (component.name === item.name) item["enabled"] = false;
+ return item;
+ });
+ reject();
+ }
});
- }
- toolsProcessed++;
- if (toolsProcessed >= tools.length) {
- helpers.addIsLoaded("tools");
- }
+ });
})
);
@@ -193,68 +180,132 @@ class Sidebar extends Component {
let themes = window.config.sidebarThemeComponents;
themes = themes.filter((item) => item.enabled === undefined || item.enabled);
if (themes.length === 1) {
- this.setState({ themes: { title: themes[0].name, icon: themes[0].imageName } });
+ setThemes({ title: themes[0].name, icon: themes[0].imageName });
themes[0]["hideHeader"] = true;
}
- if (themes.length === 0 || (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideThemes"])) this.setState({ hideThemes: true });
- let loadedThemes = [];
- let themesProcessed = 0;
- themes.map((component) =>
- this.addComponent(component, "themes", (result) => {
- if (result === "success") loadedThemes.push(component);
- else {
- window.config.sidebarThemeComponents = window.config.sidebarThemeComponents.map((item) => {
- if (component.name === item.name) item["enabled"] = false;
- return item;
+ if (themes.length === 0 || (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideThemes"])) setHideThemes(true);
+ componentPromises.push(
+ ...themes.map((component) => {
+ return new Promise((resolve, reject) => {
+ addComponent(component, "themes", (result) => {
+ if (result) {
+ resolve({ component: result, type: "themes", loadedComponent: component });
+ } else {
+ window.config.sidebarThemeComponents = window.config.sidebarThemeComponents.map((item) => {
+ if (component.name === item.name) item["enabled"] = false;
+ return item;
+ });
+ reject();
+ }
});
- }
- themesProcessed++;
- if (themesProcessed >= themes.length) {
- helpers.addIsLoaded("themes");
- }
+ });
})
);
+ let loadedThemes = [];
+ let loadedTools = [];
+ Promise.allSettled(componentPromises).then((results) => {
+ let loadedComponents = [];
+ results
+ .filter((result) => result.status === "fulfilled")
+ .forEach((result) => {
+ const { value } = result;
+ if (value.type === "themes") loadedThemes.push(value.loadedComponent);
+ if (value.type === "tools") loadedTools.push(value.loadedComponent);
+ loadedComponents.push(value.component);
+ });
+
+ toolComponentsLoaded.current = true;
+ toolComponentsRef.current = loadedComponents;
+ });
+
// CHECK VISIBILITY OF LAYERS MENUE
- if (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideLayers"]) this.setState({ hideLayers: true });
+ if (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideLayers"]) setHideLayers(true);
// CHECK VISIBILITY OF MY MAPS
- if (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideMyMaps"]) this.setState({ hideMyMaps: true });
+ if (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideMyMaps"]) setHideMyMaps(true);
// CHECK VISIBILITY OF REPORTS
- if (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideReports"]) this.setState({ hideReports: true });
+ if (window.config.mainSidebarItems !== undefined && window.config.mainSidebarItems["hideReports"]) setHideReports(true);
const shortcuts = window.config.sidebarShortcutParams;
// HANDLE ADVANCED MODE PARAMETER
window.sidebarOpen = false;
if (window.config.viewerMode !== undefined && window.config.viewerMode !== null) {
- if (window.config.viewerMode.toUpperCase() === "ADVANCED") this.sidebarVisiblityEventHandler("OPEN");
+ if (window.config.viewerMode.toUpperCase() === "ADVANCED") sidebarVisiblityEventHandler("OPEN");
}
- helpers.waitForLoad(["tools", "themes"], Date.now(), 30, () => {
- this.initToolAndThemeUrlParameter({ tools: loadedTools, themes: loadedThemes, shortcuts: shortcuts }, () => {
+
+ helpers.waitForLoad(["tools", "themes", "header", "map"], Date.now(), 30, () => {
+ initToolAndThemeUrlParameter({ tools: loadedTools, themes: loadedThemes, shortcuts: shortcuts }, () => {
// TAB PARAMETER
const tabNameParameter = helpers.getURLParameter("TAB");
if (tabNameParameter != null) {
- this.sidebarVisiblityEventHandler("OPEN", () => {
- this.activateTab(tabNameParameter.toLowerCase());
+ sidebarVisiblityEventHandler("OPEN", () => {
+ activateTab(tabNameParameter.toLowerCase());
});
}
-
window.emitter.emit("sidebarLoaded");
helpers.addIsLoaded("sidebar");
});
});
});
- }
+ };
+
+ useEffect(() => {
+ helpers.addIsLoaded("tools");
+ helpers.addIsLoaded("themes");
+ }, [toolComponentsRef]);
- initToolAndThemeUrlParameter = (components, callback) => {
- if (components.tools.length + components.themes.length === this.state.toolComponents.length && !this.props.mapLoading && !this.props.headerLoading) {
+ useEffect(() => {
+ mapLoadingRef.current = props.mapLoading;
+ }, [props.mapLoading]);
+
+ useEffect(() => {
+ headerLoadingRef.current = props.headerLoading;
+ }, [props.headerLoading]);
+ const onSetSidebarOpen = (open) => {
+ setSidebarOpen(open);
+ };
+
+ const addComponent = (componentConfig, typeFolder, callback = undefined) => {
+ // THIS IMPORTS THE COMPONENTS
+ const typeLowerCase = `${componentConfig.componentName}`.toLowerCase().replace(/\s/g, "");
+ const path = `./components/${typeFolder}/${typeLowerCase}/${componentConfig.componentName}.jsx`;
+
+ import(`${path}`)
+ .then((component) => {
+ // SET PROPS FROM CONFIG
+ let comp = component.default;
+ comp.props = [];
+ comp.props.active = false;
+ comp.props.id = helpers.getUID();
+ comp.props.description = componentConfig.description;
+ comp.props.name = componentConfig.name;
+ comp.props.componentName = componentConfig.componentName;
+ comp.props.helpLink = componentConfig.helpLink;
+ comp.props.config = componentConfig.config;
+ if (componentConfig.hideHeader !== undefined) comp.props.hideHeader = componentConfig.hideHeader;
+
+ // ADD COMPONENT TO LIST
+ callback(comp);
+ })
+ .catch((error) => {
+ console.log(error);
+ console.error(`"${componentConfig.name}" not yet supported`);
+ callback();
+ })
+ .finally(() => {
+ if (callback === undefined) return "Done";
+ });
+ };
+
+ const initToolAndThemeUrlParameter = (components, callback) => {
+ if (components.tools.length + components.themes.length === toolComponentsRef.current.length && !mapLoadingRef.current && !headerLoadingRef.current) {
// HANDLE ADVANCED MODE PARAMETER
callback();
const queryString = window.location.search;
if (queryString !== "") {
const urlParams = new URLSearchParams(queryString.toLowerCase());
- const item = undefined;
let shortcuts = [];
let params = [];
- components.tools.map((item) => {
+ components.tools.forEach((item) => {
shortcuts.push({
name: item.name.toLowerCase(),
component: item.name,
@@ -263,7 +314,7 @@ class Sidebar extends Component {
});
if (!params.includes("tool")) params.push("tool");
});
- components.themes.map((item) => {
+ components.themes.forEach((item) => {
shortcuts.push({
name: item.name.toLowerCase(),
component: item.name,
@@ -272,7 +323,7 @@ class Sidebar extends Component {
});
if (!params.includes("theme")) params.push("theme");
});
- components.shortcuts.map((item) => {
+ components.shortcuts.forEach((item) => {
shortcuts.push({
name: item.matchValue,
component: item.component,
@@ -283,7 +334,7 @@ class Sidebar extends Component {
});
if (!params.includes(item.url_param.toLowerCase())) params.push(item.url_param.toLowerCase());
});
- params.map((param) => {
+ params.forEach((param) => {
var shortcutParam = urlParams.get(param);
if (shortcutParam !== null) {
const shortcut = shortcuts.filter(
@@ -293,8 +344,8 @@ class Sidebar extends Component {
if (shortcut.type === "search") {
window.emitter.emit("searchItem", shortcut.component, shortcutParam, shortcut.hidden, shortcut.timeout);
} else {
- this.sidebarVisiblityEventHandler("OPEN", () => {
- this.activateItemFromEmmiter(shortcut.component, shortcut.type);
+ sidebarVisiblityEventHandler("OPEN", () => {
+ activateItemFromEmmiter(shortcut.component, shortcut.type);
});
}
}
@@ -303,273 +354,206 @@ class Sidebar extends Component {
}
} else {
setTimeout(() => {
- this.initToolAndThemeUrlParameter(components, callback);
- }, 50);
+ initToolAndThemeUrlParameter(components, callback);
+ }, 500);
}
};
- loadReport = (content) => {
- let activeTabComponents = this.state.activeTabComponents;
- activeTabComponents.reports.loadedComponent = {content};
- this.setState({ activeTabComponents: activeTabComponents });
- this.sidebarVisiblityEventHandler("OPEN");
- this.activateTab("reports");
+ const loadReport = (content) => {
+ helpers.waitForLoad("sidebar", Date.now(), 30, () => {
+ setReportTabComponent({content});
+ sidebarVisiblityEventHandler("OPEN");
+ activateTab("reports");
+ });
};
- activateItemFromEmmiter(name, type, options = undefined) {
- const active = this.state.activeTabComponents;
- if (type === "tools") {
- //SAME TOOL WAS SELECTED
- if (active.tools.loadedComponent != null && type === "tools" && active.tools.loadedComponent.props.name === name) {
- this.activateTab("tools");
- return;
- }
-
- this.setState({ tabIndex: 1 }, () => {
- //CLEAR LOADED TOOL
- let activeTabComponents = this.state.activeTabComponents;
- activeTabComponents.tools.loadedComponent = null;
- this.setState({ activeTabComponents: activeTabComponents }, () => {
- // ASK TOOLS TO CLOSE
- window.emitter.emit("closeToolsOrThemes", type);
-
- // ACTIVATE THE NEW ITEM
- this.activateSidebarItem(name, type, options);
+ const activateItemFromEmmiter = (name, type, options = undefined) => {
+ helpers.waitForLoad("sidebar", Date.now(), 30, () => {
+ if (type === "tools") {
+ //SAME TOOL WAS SELECTED
+ if (activeToolTabComponent != null && type === "tools" && activeToolTabComponent.props.name === name) {
+ activateTab("tools");
+ return;
+ }
+ flushSync(() => {
+ setTabIndex(1);
+ //CLEAR LOADED TOOL
+ setToolTabComponent(null);
});
- });
- } else if (type === "themes") {
- // SAME THEME WAS SELECTED
- if (active.themes.loadedComponent != null && type === "themes" && active.themes.loadedComponent.props.name === name) {
- this.activateTab("themes");
- return;
- }
-
- this.setState({ tabIndex: 3 }, () => {
- //CLEAR LOADED THEME
- let activeTabComponents = this.state.activeTabComponents;
- activeTabComponents.themes.loadedComponent = null;
- this.setState({ activeTabComponents: activeTabComponents });
+ // ASK TOOLS TO CLOSE
+ window.emitter.emit("closeToolsOrThemes", type);
+ // ACTIVATE THE NEW ITEM
+ activateSidebarItem(name, type, options);
+ } else if (type === "themes") {
+ // SAME THEME WAS SELECTED
+ if (activeThemeTabComponent != null && type === "themes" && activeThemeTabComponent.props.name === name) {
+ activateTab("themes");
+ return;
+ }
+ flushSync(() => {
+ setTabIndex(3);
+ //CLEAR LOADED THEME
+ setThemeTabComponent(null);
+ });
// ASK THEMES TO CLOSE
window.emitter.emit("closeToolsOrThemes", type);
// ACTIVATE THE NEW ITEM
- this.activateSidebarItem(name, type, options);
- });
- } else if (type === "mymaps") {
- this.activateTab("mymaps");
- } else if (type === "reports") {
- this.activateTab("reports");
- }
+ activateSidebarItem(name, type, options);
+ } else if (type === "mymaps") {
+ activateTab("mymaps");
+ } else if (type === "reports") {
+ activateTab("reports");
+ }
- // OPEN PANEL
- this.sidebarVisiblityEventHandler("OPEN");
- }
-
- activateTab(tabName) {
- // OPEN PANEL
- this.sidebarVisiblityEventHandler("OPEN");
-
- // SET SELECTED TAB
- if (tabName === "layers") this.setState({ tabIndex: 0 });
- else if (tabName === "tools") this.setState({ tabIndex: 1 });
- else if (tabName === "mymaps") this.setState({ tabIndex: 2 });
- else if (tabName === "themes") this.setState({ tabIndex: 3 });
- else if (tabName === "reports") this.setState({ tabIndex: 4 });
- else console.log("NO VALID TAB FOUND");
- }
-
- sidebarVisiblityEventHandler(openOrClose, callback = undefined) {
- // CHECK IF NEED TO DO ANYTHING
- if ((openOrClose === "CLOSE" && window.sidebarOpen === false) || (openOrClose === "OPEN" && window.sidebarOpen === true)) {
- if (callback === undefined) return;
- else callback();
- } else {
- // TOGGLE IT
- this.togglePanelVisibility(callback);
- }
- }
+ // OPEN PANEL
+ sidebarVisiblityEventHandler("OPEN");
+ });
+ };
- togglePanelVisibility(callback = undefined) {
- // PANEL IN AND OUT CLASSES
- window.sidebarOpen = !window.sidebarOpen;
- this.setState({ sidebarOpen: window.sidebarOpen }, () => {
- // EMIT A CHANGE IN THE SIDEBAR (IN OR OUT)
- window.emitter.emit("sidebarChanged", window.sidebarOpen);
- if (callback !== undefined && typeof callback === "function") callback();
+ const activateTab = (tabName) => {
+ helpers.waitForLoad("sidebar", Date.now(), 30, () => {
+ // OPEN PANEL
+ sidebarVisiblityEventHandler("OPEN");
+ flushSync(() => {
+ // SET SELECTED TAB
+ if (tabName === "layers") setTabIndex(0);
+ else if (tabName === "tools") setTabIndex(1);
+ else if (tabName === "mymaps") setTabIndex(2);
+ else if (tabName === "themes") setTabIndex(3);
+ else if (tabName === "reports") setTabIndex(4);
+ else console.log("NO VALID TAB FOUND");
+ });
});
- }
+ };
- // TOOL AND THEME ITEMS CLICK
- activateSidebarItem(name, type, options = undefined) {
- // THIS HANDLES WHAT TOOL/THEME IS LOADED IN THE SIDEBAR
- if (type === "tools") {
- var loadedTool = this.state.activeTabComponents.tools.loadedComponent;
- if (loadedTool != null) {
- this.setState({ activeComponent: loadedTool });
+ const sidebarVisiblityEventHandler = (openOrClose, callback = undefined) => {
+ helpers.waitForLoad("sidebar", Date.now(), 30, () => {
+ // CHECK IF NEED TO DO ANYTHING
+ if ((openOrClose === "CLOSE" && window.sidebarOpen === false) || (openOrClose === "OPEN" && window.sidebarOpen === true)) {
+ if (callback === undefined) return;
+ else callback();
} else {
- this.state.toolComponents.map((Component) => {
- if (Component.props.name.toLowerCase() === name.toLowerCase()) {
- // CREATE TOOL COMPONENT
- var comp = (
- this.togglePanelVisibility()}
- config={Component.props.config}
- options={options}
- />
- );
- let activeTabComponents = this.state.activeTabComponents;
- activeTabComponents.tools.loadedComponent = comp;
- this.setState({ activeTabComponents: activeTabComponents });
- return comp;
- } else return null;
- });
+ // TOGGLE IT
+ togglePanelVisibility(callback);
}
+ });
+ };
- helpers.addAppStat("Tool", name);
- } else {
- var loadedTheme = this.state.activeTabComponents.themes.loadedComponent;
- if (loadedTheme != null) this.setState({ activeComponent: loadedTheme });
- else {
- this.state.toolComponents.map((Component) => {
- if (Component.props.name.toLowerCase() === name.toLowerCase()) {
- // CREATE THEME COMPONENT
- var comp = (
- this.togglePanelVisibility()}
- config={Component.props.config}
- options={options}
- />
- );
- let activeTabComponents = this.state.activeTabComponents;
- activeTabComponents.themes.loadedComponent = comp;
- this.setState({ activeTabComponents: activeTabComponents });
- //helpers.showMessage("Property Report", "Property Report Click is disabled while theme is active.", "green" , 5000);
- return comp;
- } else return null;
- });
- }
- helpers.addAppStat("Theme", name);
- }
- }
+ const togglePanelVisibility = (callback = undefined) => {
+ // PANEL IN AND OUT CLASSES
+ window.sidebarOpen = !window.sidebarOpen;
+ setSidebarOpen(window.sidebarOpen);
+ // EMIT A CHANGE IN THE SIDEBAR (IN OR OUT)
+ window.emitter.emit("sidebarChanged", window.sidebarOpen);
+ if (callback !== undefined && typeof callback === "function") callback();
+ };
- onPanelComponentClose(evt) {
+ const onPanelComponentClose = (evt) => {
// HANDLES UNLOADING OF TOOL/THEME
- if (this.state.tabIndex === 1) {
+ if (tabIndex === 1) {
// SET TOOLS
- let activeTabComponents = this.state.activeTabComponents;
- activeTabComponents.tools.loadedComponent = null;
- this.setState({ activeTabComponents: activeTabComponents });
- } else if (this.state.tabIndex === 3) {
+ setToolTabComponent(null);
+ } else if (tabIndex === 3) {
// SET THEMES
- let activeTabComponents = this.state.activeTabComponents;
- activeTabComponents.themes.loadedComponent = null;
- this.setState({ activeTabComponents: activeTabComponents });
+ setThemeTabComponent(null);
}
- }
+ };
- slimSidebarButtonClick = (name) => {
- this.sidebarVisiblityEventHandler("OPEN", () => {
- this.activateTab(name);
+ const slimSidebarButtonClick = (name) => {
+ sidebarVisiblityEventHandler("OPEN", () => {
+ activateTab(name);
helpers.addAppStat("Sidebar Slim", name);
});
};
- onTabSelect = (tabIndex) => {
- this.setState({ tabIndex });
- if (tabIndex === 0) helpers.addAppStat("Tab", "Layers");
- else if (tabIndex === 1) helpers.addAppStat("Tab", "Tools");
- else if (tabIndex === 2) helpers.addAppStat("Tab", "MyMaps");
- else if (tabIndex === 3) helpers.addAppStat("Tab", "Themes");
- else if (tabIndex === 4) helpers.addAppStat("Tab", "Reports");
+ const onTabSelect = (tabIndexLocal) => {
+ setTabIndex(tabIndexLocal);
+ if (tabIndexLocal === 0) helpers.addAppStat("Tab", "Layers");
+ else if (tabIndexLocal === 1) helpers.addAppStat("Tab", "Tools");
+ else if (tabIndexLocal === 2) helpers.addAppStat("Tab", "MyMaps");
+ else if (tabIndexLocal === 3) helpers.addAppStat("Tab", "Themes");
+ else if (tabIndexLocal === 4) helpers.addAppStat("Tab", "Reports");
};
- // this.setState({ tabIndex })} selectedIndex={this.state.tabIndex}>
- render() {
- return (
-
diff --git a/src/sidebar/components/themes/localrealestate/LocalRealEstate.jsx b/src/sidebar/components/themes/localrealestate/LocalRealEstate.jsx
index c18d6870..252e171f 100644
--- a/src/sidebar/components/themes/localrealestate/LocalRealEstate.jsx
+++ b/src/sidebar/components/themes/localrealestate/LocalRealEstate.jsx
@@ -1,10 +1,11 @@
import React, { Component } from "react";
+import { createRoot } from "react-dom/client";
+
import "./LocalRealEstate.css";
import PanelComponent from "../../../PanelComponent";
import config from "./config.json";
import LocalRealEstateLayerToggler from "./LocalRealEstateLayerToggler.jsx";
import * as helpers from "../../../../helpers/helpers";
-import ReactDOM from "react-dom";
import LocalRealEstateImageSlider from "./LocalRealEstateImageSlider.jsx";
import LocalRealEstateRecents from "./LocalRealEstateRecents.jsx";
import LocalRealEstatePopupContent from "./LocalRealEstatePopupContent.jsx";
@@ -26,13 +27,14 @@ class LocalRealEstate extends Component {
this.imageSlider.id = "sc-theme-real-estate-photo-slider";
this.storageKey = "theme-real-estate";
this.state = { visibleLayers: null, viewedItems: [] };
+ this.root = null;
}
componentDidMount() {
//window.disableParcelClick = true;
// CREATE DIV FOR SLIDER
document.body.appendChild(this.imageSlider);
-
+ this.root = createRoot(document.getElementById(this.imageSlider.id));
let visibleLayers = [];
config.layers.forEach((layer) => {
if (layer.visible && layer.displayName !== "All") visibleLayers.push(layer.displayName);
@@ -46,10 +48,7 @@ class LocalRealEstate extends Component {
}
renderImageSlider = () => {
- ReactDOM.render(
-
,
- document.getElementById(this.imageSlider.id)
- );
+ this.root.render(
);
};
componentWillUnmount() {
//window.disableParcelClick = false;
diff --git a/src/sidebar/components/toc/TOC.jsx b/src/sidebar/components/toc/TOC.jsx
index 15a3c238..193db79d 100644
--- a/src/sidebar/components/toc/TOC.jsx
+++ b/src/sidebar/components/toc/TOC.jsx
@@ -1,6 +1,5 @@
// REACT
import React, { Component } from "react";
-import ReactDOM from "react-dom";
import { isMobile } from "react-device-detect";
//CUSTOM
@@ -98,7 +97,10 @@ class TOC extends Component {
layers.forEach((layer) => {
if (layer.visible && layer.liveLayer) {
LayerHelpers.identifyFeatures(layer.layer, evt.coordinate, (feature) => {
- if (feature !== undefined) helpers.showFeaturePopup(evt.coordinate, feature);
+ if (feature !== undefined) {
+ feature.setProperties({ layerDisplayName: layer.displayName });
+ helpers.showFeaturePopup(evt.coordinate, feature);
+ }
});
}
});
@@ -494,7 +496,10 @@ class TOC extends Component {
allLayers.forEach((layer) => {
if (layer.visible && layer.liveLayer) {
LayerHelpers.identifyFeatures(layer.layer, evt.coordinate, (feature) => {
- if (feature !== undefined) helpers.showFeaturePopup(evt.coordinate, feature);
+ if (feature !== undefined) {
+ feature.setProperties({ layerDisplayName: layer.displayName });
+ helpers.showFeaturePopup(evt.coordinate, feature);
+ }
});
}
});
@@ -923,7 +928,7 @@ class TOC extends Component {
onLayerOptionsClick = (evt, layerInfo) => {
var evtClone = Object.assign({}, evt);
const menu =
;
- ReactDOM.render(menu, document.getElementById("portal-root"));
+ window.portalRoot.render(menu);
};
//#endregion
//#region HANDLE HEADER CALLBACKS
diff --git a/src/sidebar/components/toc/common/LayerLegend.jsx b/src/sidebar/components/toc/common/LayerLegend.jsx
index 9fa93eb7..ce5302b4 100644
--- a/src/sidebar/components/toc/common/LayerLegend.jsx
+++ b/src/sidebar/components/toc/common/LayerLegend.jsx
@@ -1,55 +1,54 @@
// REACT
import React, { Component } from "react";
-import ReactDOM from "react-dom";
import * as helpers from "../../../../helpers/helpers";
import "./LayerLegend.css";
class LayerLegend extends Component {
- constructor(props) {
- super(props);
- this.state = {};
- }
+ constructor(props) {
+ super(props);
+ this.state = {};
+ }
- render() {
- return (
-
+ );
+ }
}
export default LayerLegend;
const Legend = ({ legendImage, legendObj }) => {
- if (legendImage !== undefined && legendImage !== null) {
- return
;
- } else if (legendObj !== undefined) {
- if (legendObj.legend === undefined) return
;
+ } else if (legendObj !== undefined) {
+ if (legendObj.legend === undefined) return
+ );
};
diff --git a/src/sidebar/components/toc/common/TOCHeader.jsx b/src/sidebar/components/toc/common/TOCHeader.jsx
index c3e435c3..2e032664 100644
--- a/src/sidebar/components/toc/common/TOCHeader.jsx
+++ b/src/sidebar/components/toc/common/TOCHeader.jsx
@@ -1,6 +1,5 @@
// REACT
import React, { Component } from "react";
-import ReactDOM from "react-dom";
import Switch from "react-switch";
import { Item as MenuItem } from "rc-menu";
import { Tooltip as ReactTooltip } from "react-tooltip";
@@ -19,7 +18,6 @@ class TOCHeader extends Component {
searchText: "",
};
}
-
onSettingsClick = (evt) => {
var evtClone = Object.assign({}, evt);
var switchMenuLabel = `Switch to ${this.props.tocType === "LIST" ? "Folder" : "List"} View`;
@@ -61,7 +59,7 @@ class TOCHeader extends Component {
);
- ReactDOM.render(menu, document.getElementById("portal-root"));
+ window.portalRoot.render(menu);
};
onSettingsMenuItemClick = (action) => {
diff --git a/src/sidebar/components/toc/toc-folder-view/GroupItem.jsx b/src/sidebar/components/toc/toc-folder-view/GroupItem.jsx
index fb5b0466..8bb79d85 100644
--- a/src/sidebar/components/toc/toc-folder-view/GroupItem.jsx
+++ b/src/sidebar/components/toc/toc-folder-view/GroupItem.jsx
@@ -1,5 +1,4 @@
import React, { Component } from "react";
-import ReactDOM from "react-dom";
import * as helpers from "../../../../helpers/helpers";
import FloatingMenu, { FloatingMenuItem } from "../../../../helpers/FloatingMenu.jsx";
import { Item as MenuItem } from "rc-menu";
@@ -104,7 +103,7 @@ class GroupItem extends Component {
);
- ReactDOM.render(menu, document.getElementById("portal-root"));
+ window.portalRoot.render(menu);
};
componentDidMount() {
this._isMounted = true;
diff --git a/src/sidebar/components/toc/toc-folder-view/Layers.jsx b/src/sidebar/components/toc/toc-folder-view/Layers.jsx
index 4dcf1275..7ee4e12f 100644
--- a/src/sidebar/components/toc/toc-folder-view/Layers.jsx
+++ b/src/sidebar/components/toc/toc-folder-view/Layers.jsx
@@ -53,7 +53,7 @@ class Layers extends Component {
});
return (
-
+
{layers.map((layer) => (
div > div {
+.sc-toc-layer-container-folder > div > div {
height: unset;
}
-.sc-toc-layer-container > div > div > div {
+.sc-toc-layer-container-folder > div > div > div {
max-height: unset;
}
From 4a39e4f6a4519885fcc537b5a1cbb4834eaef2b9 Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Tue, 30 Apr 2024 08:37:18 -0400
Subject: [PATCH 04/14] fixed table of contents styling issue
---
src/sidebar/components/toc/toc-list-new/LayerItem.css | 4 ++--
src/sidebar/components/toc/toc-list-new/LayerItem.jsx | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/sidebar/components/toc/toc-list-new/LayerItem.css b/src/sidebar/components/toc/toc-list-new/LayerItem.css
index dfb26cac..da349c1b 100644
--- a/src/sidebar/components/toc/toc-list-new/LayerItem.css
+++ b/src/sidebar/components/toc/toc-list-new/LayerItem.css
@@ -83,7 +83,7 @@
vertical-align: text-top;
}
-.sc-toc-item-layer-info-container-open-vertical-lines {
+.sc-toc-item-layer-list-info-container-open-vertical-lines {
height: 22px;
width: 11px;
position: relative;
@@ -93,7 +93,7 @@
background: url(../images/verticle_dots.png) 0px repeat-y;
}
-.sc-toc-item-layer-info-container-open-horizontal-lines {
+.sc-toc-item-layer-list-info-container-open-horizontal-lines {
height: 5px;
width: 11px;
position: relative;
diff --git a/src/sidebar/components/toc/toc-list-new/LayerItem.jsx b/src/sidebar/components/toc/toc-list-new/LayerItem.jsx
index 433af6f4..8139cc6b 100644
--- a/src/sidebar/components/toc/toc-list-new/LayerItem.jsx
+++ b/src/sidebar/components/toc/toc-list-new/LayerItem.jsx
@@ -129,8 +129,8 @@ class LayerItem extends Component {
From b8ef07b72ebabd0597ba208e4669351c13626b4d Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Tue, 30 Apr 2024 10:38:32 -0400
Subject: [PATCH 05/14] fixed my maps item selection issue
---
src/sidebar/components/mymaps/MyMapsItem.jsx | 26 +++++++++-----------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/src/sidebar/components/mymaps/MyMapsItem.jsx b/src/sidebar/components/mymaps/MyMapsItem.jsx
index d87b14dc..fa52fd66 100644
--- a/src/sidebar/components/mymaps/MyMapsItem.jsx
+++ b/src/sidebar/components/mymaps/MyMapsItem.jsx
@@ -10,15 +10,14 @@ import * as helpers from "../../../helpers/helpers";
function MyMapsItem(props) {
const [label, setLabel] = useState(props.info.label);
const [checked, setChecked] = useState(props.info.visible);
- const [vectorLayer, setVectorLayer] = useState(null);
-
+ const vectorLayerRef = React.createRef();
useEffect(() => {
return () => {
- if (vectorLayer !== null) {
- window.map.removeLayer(vectorLayer);
+ if (vectorLayerRef.current !== null) {
+ window.map.removeLayer(vectorLayerRef.current);
}
};
- }, [vectorLayer]);
+ }, []);
const onLabelTextChange = (evt) => {
const newLabel = evt.target.value;
@@ -28,9 +27,9 @@ function MyMapsItem(props) {
const onItemDelete = (evt) => {
props.onItemDelete && props.onItemDelete(props.info.id);
- if (vectorLayer !== null) {
- window.map.removeLayer(vectorLayer);
- setVectorLayer(null);
+ if (vectorLayerRef.current !== null) {
+ window.map.removeLayer(vectorLayerRef.current);
+ vectorLayerRef.current = null;
}
};
@@ -81,7 +80,7 @@ function MyMapsItem(props) {
geometry: feature.getGeometry(),
});
- const highlightLayer = new VectorLayer({
+ vectorLayerRef.current = new VectorLayer({
source: new VectorSource({
features: [highlightFeature],
}),
@@ -89,14 +88,13 @@ function MyMapsItem(props) {
style: shadowStyle,
});
- setVectorLayer(highlightLayer);
- window.map.addLayer(highlightLayer);
+ window.map.addLayer(vectorLayerRef.current);
};
const onMouseOut = (evt) => {
- if (vectorLayer !== null) {
- window.map.removeLayer(vectorLayer);
- setVectorLayer(null);
+ if (vectorLayerRef.current !== null) {
+ window.map.removeLayer(vectorLayerRef.current);
+ vectorLayerRef.current = null;
}
};
From 86fb1d9337491675aa17f1d348b48ea528e0b402 Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Tue, 30 Apr 2024 11:52:55 -0400
Subject: [PATCH 06/14] fixed crash when saving layers on an invalid map_id
---
src/sidebar/components/toc/TOC.jsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/sidebar/components/toc/TOC.jsx b/src/sidebar/components/toc/TOC.jsx
index 193db79d..6d360e21 100644
--- a/src/sidebar/components/toc/TOC.jsx
+++ b/src/sidebar/components/toc/TOC.jsx
@@ -1066,7 +1066,7 @@ class TOC extends Component {
savedLayers[layer.name] = saveLayer;
});
let currentGroup = currentGroupList.filter((item) => item.value === group)[0];
-
+ if (currentGroup === undefined) continue;
savedGroup["name"] = groupName;
savedGroup["value"] = currentGroup.value;
savedGroup["label"] = currentGroup.label;
From d91ec8b31d6c31d7c495c85b597e2b97f56971a7 Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Tue, 30 Apr 2024 11:53:23 -0400
Subject: [PATCH 07/14] fixed showWindow bug
---
src/helpers/helpers.js | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/helpers/helpers.js b/src/helpers/helpers.js
index baa2e699..76c6f783 100644
--- a/src/helpers/helpers.js
+++ b/src/helpers/helpers.js
@@ -123,7 +123,9 @@ export function isMobile() {
// SHOW CONTENT WINDOW
export function showWindow(contents, options = { title: "Information", showFooter: false, mode: "normal", hideScroll: false }) {
- const uniqueId = `map-modal-window-${getUID()}}`;
+ const uniqueId = `map-modal-window-${"show-window"}}`;
+ if (document.getElementById(uniqueId) !== null) document.getElementById(uniqueId).remove();
+
const element = document.createElement("div");
element.setAttribute("id", uniqueId);
document.getElementById("map-modal-window").appendChild(element);
@@ -140,9 +142,9 @@ export function showWindow(contents, options = { title: "Information", showFoote
}
};
}, []);
- return
;
+ return
;
};
- root.render(
);
+ root.render(
);
}
// SHOW URL WINDOW
@@ -1586,6 +1588,7 @@ export function loadConfig(configSecured = {}, callback) {
}, 1500);
window.config = config;
callback();
+ return;
}
const settings = JSON.parse(result.json);
if (settings.name !== undefined) document.title = settings.name;
From d938377637c1e0a6bcf7b7679f9a84f0b3090b9d Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Tue, 30 Apr 2024 13:05:34 -0400
Subject: [PATCH 08/14] removed unused imports
---
src/sidebar/components/mymaps/MyMaps.jsx | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/sidebar/components/mymaps/MyMaps.jsx b/src/sidebar/components/mymaps/MyMaps.jsx
index ac0aa92d..22b5ccc2 100644
--- a/src/sidebar/components/mymaps/MyMaps.jsx
+++ b/src/sidebar/components/mymaps/MyMaps.jsx
@@ -1,6 +1,5 @@
// REACT
-import React, { Component, Fragment, useEffect } from "react";
-import { createRoot } from "react-dom/client";
+import React, { Component, Fragment } from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import { SubMenu, Item as MenuItem } from "rc-menu";
From f643d961c6e0faf473b2e0470ae93f87891eaa70 Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Fri, 3 May 2024 10:42:50 -0400
Subject: [PATCH 09/14] fixed render bug in popup
---
src/helpers/Popup.jsx | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/helpers/Popup.jsx b/src/helpers/Popup.jsx
index 01e52b8b..cd33b24a 100644
--- a/src/helpers/Popup.jsx
+++ b/src/helpers/Popup.jsx
@@ -39,10 +39,10 @@ export default class Popup extends Overlay {
}
//options.stopEvent = false;
-
var element = document.createElement("div");
options.element = element;
super(options);
+ this.root = null;
this.container = element;
this.container.className = "ol-popup";
this.container.id = "sc-window-popup";
@@ -91,7 +91,7 @@ export default class Popup extends Overlay {
this.content.appendChild(this.contentArray[this.contentIndex].html);
} else {
// REACT COMPONENT
- this.root.render(this.contentArray[this.contentIndex].html);
+ this.renderRoot(this.contentArray[this.contentIndex].html);
}
});
this.contentPrevButton.addEventListener("click", () => {
@@ -117,7 +117,7 @@ export default class Popup extends Overlay {
this.content.appendChild(this.contentArray[this.contentIndex].html);
} else {
// REACT COMPONENT
- this.root.render(this.contentArray[this.contentIndex].html);
+ this.renderRoot(this.contentArray[this.contentIndex].html);
}
});
this.headerCloseContainer = document.createElement("div");
@@ -159,11 +159,9 @@ export default class Popup extends Overlay {
this.content = document.createElement("div");
this.content.className = "ol-popup-content";
- this.uniqueId = `sc-popup-content-${helpers.getUID()}}`;
+ this.uniqueId = `sc-window-popup-content`;
this.content.setAttribute("id", this.uniqueId);
- this.root = createRoot(this.content);
this.container.appendChild(this.content);
-
// Apply workaround to enable scrolling of content div on touch devices
Popup.enableTouchScroll_(this.content);
@@ -183,7 +181,21 @@ export default class Popup extends Overlay {
window.popupActive = false;
};
}
-
+ renderRoot(child) {
+ if (isDOMTypeElement(child)) {
+ // REGULAR HTML
+ this.content.innerHTML = "";
+ this.content.appendChild(child);
+ } else {
+ // REACT COMPONENT
+ if (this.root !== null) {
+ this.root.render(child);
+ } else {
+ this.root = createRoot(this.content);
+ this.root.render(child);
+ }
+ }
+ }
/**
* Show the popup.
* @param {ol.Coordinate} coord Where to anchor the popup.
@@ -231,7 +243,7 @@ export default class Popup extends Overlay {
this.content.appendChild(html);
} else {
// REACT COMPONENT
- this.root.render(html);
+ this.renderRoot(html);
}
this.container.style.display = "block";
From 5e26b7e6f4e8390764b5201694756b1a3af2606f Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Fri, 3 May 2024 10:58:20 -0400
Subject: [PATCH 10/14] fixed styling issue on point sytle symbolizer popup
---
src/map/OLOverrides.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/map/OLOverrides.css b/src/map/OLOverrides.css
index da8a424a..184f4d93 100644
--- a/src/map/OLOverrides.css
+++ b/src/map/OLOverrides.css
@@ -62,7 +62,7 @@
z-index: 1;
padding: 6px !important;
background-color: #fff !important;
- max-height: 275px !important;
+ max-height: 276px !important;
min-height: 50px !important;
overflow: hidden;
overflow-y: auto;
From 6f95a16cd7d4055d9e4f7ef6273f913f2c8afdd0 Mon Sep 17 00:00:00 2001
From: Tom <58078313+reed-tom@users.noreply.github.com>
Date: Fri, 3 May 2024 11:24:00 -0400
Subject: [PATCH 11/14] fixed rerender issue with right click menu
---
src/map/SCMap.jsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/map/SCMap.jsx b/src/map/SCMap.jsx
index 550d4dfa..b806c99c 100644
--- a/src/map/SCMap.jsx
+++ b/src/map/SCMap.jsx
@@ -181,7 +181,7 @@ const SCMap = (props) => {
const menu = (
-
+