From 4047af434a4eedd95855dc56379121a2eed61c09 Mon Sep 17 00:00:00 2001 From: Damon Ulmi Date: Wed, 14 Feb 2024 07:02:54 -0800 Subject: [PATCH] refactor(layerOrder): add flags to layerOrder Closes #1781 Closes #1722 --- common/config/rush/pnpm-lock.yaml | 495 ++++++++--------- .../public/templates/raw-feature-info.html | 3 +- packages/geoview-core/schema.json | 509 ++++-------------- .../feature-info-event-processor.ts | 8 +- .../geochart-event-processor.ts | 8 +- .../legend-event-processor.ts | 10 - .../map-event-processor.ts | 136 +++-- .../time-slider-event-processor.ts | 20 +- .../core/components/data-table/data-panel.tsx | 13 +- .../data-table/data-table-modal.tsx | 4 +- .../core/components/details/details-panel.tsx | 15 +- .../core/components/layers/hooks/helpers.ts | 22 +- .../core/components/layers/layers-panel.tsx | 4 +- .../core/components/layers/layers-toolbar.tsx | 4 +- .../add-new-layer/add-new-layer.tsx | 7 +- .../layers/left-panel/delete-undo-button.tsx | 18 +- .../layers/left-panel/layers-list.tsx | 16 +- .../layers/left-panel/left-panel.tsx | 26 +- .../layers/left-panel/single-layer.tsx | 20 +- .../layers/right-panel/layer-details.tsx | 8 +- .../src/core/components/layers/types.ts | 5 - .../core/components/legend/legend-layer.tsx | 8 +- .../src/core/components/legend/legend.tsx | 21 +- .../layer-state.ts | 159 ++---- .../map-state.ts | 132 ++++- .../layer/geoview-layers/esri-layer-common.ts | 1 + .../geo/layer/geoview-layers/raster/wms.ts | 1 + .../layer/geoview-layers/vector/geopackage.ts | 2 + packages/geoview-core/src/geo/layer/layer.ts | 70 ++- .../src/geo/map/map-schema-types.ts | 6 + .../geoview-core/src/geo/utils/layer-set.ts | 2 + .../geoview-geochart/src/geochart-panel.tsx | 15 +- .../src/time-slider-panel.tsx | 17 +- 33 files changed, 822 insertions(+), 963 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index dba073a6695..f6f6cbae5eb 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -73,7 +73,7 @@ importers: version: 7.23.9 '@types/react': specifier: ^18.2.0 - version: 18.2.55 + version: 18.2.57 '@types/react-dom': specifier: ^18.2.0 version: 18.2.19 @@ -127,28 +127,28 @@ importers: dependencies: '@emotion/react': specifier: ^11.11.0 - version: 11.11.3(@types/react@18.2.55)(react@18.2.0) + version: 11.11.3(@types/react@18.2.57)(react@18.2.0) '@emotion/styled': specifier: ^11.11.0 - version: 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.55)(react@18.2.0) + version: 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.57)(react@18.2.0) '@mui/base': specifier: 5.0.0-beta.24 - version: 5.0.0-beta.24(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) + version: 5.0.0-beta.24(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) '@mui/icons-material': specifier: ^5.14.6 - version: 5.15.10(@mui/material@5.15.10)(@types/react@18.2.55)(react@18.2.0) + version: 5.15.10(@mui/material@5.15.10)(@types/react@18.2.57)(react@18.2.0) '@mui/material': specifier: ^5.14.6 - version: 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) + version: 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) '@mui/styles': specifier: ^5.14.6 - version: 5.15.10(@types/react@18.2.55)(react@18.2.0) + version: 5.15.10(@types/react@18.2.57)(react@18.2.0) '@mui/system': specifier: ^5.14.6 - version: 5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react@18.2.0) + version: 5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react@18.2.0) '@mui/x-date-pickers': specifier: ^6.13.0 - version: 6.19.4(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@mui/material@5.15.10)(@mui/system@5.15.9)(@types/react@18.2.55)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) + version: 6.19.4(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@mui/material@5.15.10)(@mui/system@5.15.9)(@types/react@18.2.57)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) '@nieuwlandgeo/sldreader': specifier: ^0.3.1 version: 0.3.1(ol@8.2.0) @@ -244,7 +244,7 @@ importers: version: 3.17.0(react-dom@18.2.0)(react@18.2.0) zustand: specifier: ~4.4.1 - version: 4.4.7(@types/react@18.2.55)(react@18.2.0) + version: 4.4.7(@types/react@18.2.57)(react@18.2.0) devDependencies: '@babel/cli': specifier: ^7.17.0 @@ -347,7 +347,7 @@ importers: version: 2.5.5 '@types/react': specifier: ^18.2.0 - version: 18.2.55 + version: 18.2.57 '@types/react-beautiful-dnd': specifier: ~13.1.3 version: 13.1.8 @@ -374,7 +374,7 @@ importers: version: 27.5.1(@babel/core@7.23.9) babel-loader: specifier: ^8.2.3 - version: 8.3.0(@babel/core@7.23.9)(webpack@5.90.1) + version: 8.3.0(@babel/core@7.23.9)(webpack@5.90.3) babel-plugin-import: specifier: ^1.13.3 version: 1.13.8 @@ -383,13 +383,13 @@ importers: version: 3.3.4 compression-webpack-plugin: specifier: ^10.0.0 - version: 10.0.0(webpack@5.90.1) + version: 10.0.0(webpack@5.90.3) copy-webpack-plugin: specifier: ^10.2.4 - version: 10.2.4(webpack@5.90.1) + version: 10.2.4(webpack@5.90.3) css-loader: specifier: ^6.6.0 - version: 6.10.0(webpack@5.90.1) + version: 6.10.0(webpack@5.90.3) eslint: specifier: ^8.8.0 version: 8.56.0 @@ -419,7 +419,7 @@ importers: version: 4.6.0(eslint@8.56.0) file-loader: specifier: ^6.2.0 - version: 6.2.0(webpack@5.90.1) + version: 6.2.0(webpack@5.90.3) gh-pages: specifier: ^3.2.3 version: 3.2.3 @@ -428,37 +428,37 @@ importers: version: 7.2.3 html-loader: specifier: ~5.0.0 - version: 5.0.0(webpack@5.90.1) + version: 5.0.0(webpack@5.90.3) html-webpack-plugin: specifier: ^5.5.0 - version: 5.6.0(webpack@5.90.1) + version: 5.6.0(webpack@5.90.3) jest: specifier: ^27.4.7 version: 27.5.1 lodash-webpack-plugin: specifier: ^0.11.6 - version: 0.11.6(webpack@5.90.1) + version: 0.11.6(webpack@5.90.3) markdown-loader: specifier: ~8.0.0 - version: 8.0.0(webpack@5.90.1) + version: 8.0.0(webpack@5.90.3) prettier: specifier: ^2.6.0 version: 2.8.8 sass: specifier: ^1.49.7 - version: 1.70.0 + version: 1.71.0 sass-loader: specifier: ^12.4.0 - version: 12.6.0(sass@1.70.0)(webpack@5.90.1) + version: 12.6.0(sass@1.71.0)(webpack@5.90.3) simple-zustand-devtools: specifier: ^1.1.0 - version: 1.1.0(@types/react-dom@18.2.19)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)(zustand@4.4.7) + version: 1.1.0(@types/react-dom@18.2.19)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0)(zustand@4.4.7) style-loader: specifier: ^3.3.1 - version: 3.3.4(webpack@5.90.1) + version: 3.3.4(webpack@5.90.3) terser-webpack-plugin: specifier: ^5.3.1 - version: 5.3.10(webpack@5.90.1) + version: 5.3.10(webpack@5.90.3) typedoc: specifier: ^0.23.14 version: 0.23.28(typescript@4.9.5) @@ -467,7 +467,7 @@ importers: version: 4.9.5 webpack: specifier: ^5.68.0 - version: 5.90.1(webpack-cli@4.10.0) + version: 5.90.3(webpack-cli@4.10.0) webpack-bundle-analyzer: specifier: ^4.5.0 version: 4.10.1 @@ -476,10 +476,10 @@ importers: version: 3.1.0 webpack-cli: specifier: ^4.9.2 - version: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.1) + version: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.3) webpack-dev-server: specifier: ^4.15.1 - version: 4.15.1(webpack-cli@4.10.0)(webpack@5.90.1) + version: 4.15.1(webpack-cli@4.10.0)(webpack@5.90.3) webpack-merge: specifier: ^5.8.0 version: 5.10.0 @@ -488,10 +488,10 @@ importers: dependencies: '@mui/material': specifier: ^5.14.6 - version: 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) + version: 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) geochart: specifier: Canadian-Geospatial-Platform/geochart#develop - version: github.com/Canadian-Geospatial-Platform/geochart/13db37a4840c633125779b611050b75d13ccd93f(@types/react@18.2.55) + version: github.com/Canadian-Geospatial-Platform/geochart/13db37a4840c633125779b611050b75d13ccd93f(@types/react@18.2.57) geoview-core: specifier: workspace:~0.1.0 version: link:../geoview-core @@ -513,7 +513,7 @@ importers: version: 4.14.202 '@types/react': specifier: ^18.2.0 - version: 18.2.55 + version: 18.2.57 '@types/react-dom': specifier: ^18.2.0 version: 18.2.19 @@ -583,7 +583,7 @@ importers: version: 7.23.9 '@types/react': specifier: ^18.2.0 - version: 18.2.55 + version: 18.2.57 '@types/react-beautiful-dnd': specifier: ~13.1.3 version: 13.1.8 @@ -713,7 +713,7 @@ importers: dependencies: '@mui/material': specifier: ^5.14.6 - version: 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) + version: 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) geoview-core: specifier: workspace:~0.1.0 version: link:../geoview-core @@ -729,7 +729,7 @@ importers: version: 7.23.9 '@types/react': specifier: ^18.2.0 - version: 18.2.55 + version: 18.2.57 '@types/react-dom': specifier: ^18.2.0 version: 18.2.19 @@ -2323,7 +2323,7 @@ packages: resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} dev: false - /@emotion/react@11.11.3(@types/react@18.2.55)(react@18.2.0): + /@emotion/react@11.11.3(@types/react@18.2.57)(react@18.2.0): resolution: {integrity: sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==} peerDependencies: '@types/react': '*' @@ -2339,7 +2339,7 @@ packages: '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) '@emotion/utils': 1.2.1 '@emotion/weak-memoize': 0.3.1 - '@types/react': 18.2.55 + '@types/react': 18.2.57 hoist-non-react-statics: 3.3.2 react: 18.2.0 dev: false @@ -2358,7 +2358,7 @@ packages: resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} dev: false - /@emotion/styled@11.11.0(@emotion/react@11.11.3)(@types/react@18.2.55)(react@18.2.0): + /@emotion/styled@11.11.0(@emotion/react@11.11.3)(@types/react@18.2.57)(react@18.2.0): resolution: {integrity: sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==} peerDependencies: '@emotion/react': ^11.0.0-rc.0 @@ -2371,11 +2371,11 @@ packages: '@babel/runtime': 7.23.9 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 - '@emotion/react': 11.11.3(@types/react@18.2.55)(react@18.2.0) + '@emotion/react': 11.11.3(@types/react@18.2.57)(react@18.2.0) '@emotion/serialize': 1.1.3 '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) '@emotion/utils': 1.2.1 - '@types/react': 18.2.55 + '@types/react': 18.2.57 react: 18.2.0 dev: false @@ -2505,7 +2505,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 chalk: 4.1.2 jest-message-util: 27.5.1 jest-util: 27.5.1 @@ -2526,7 +2526,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.8.1 @@ -2563,7 +2563,7 @@ packages: dependencies: '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 jest-mock: 27.5.1 dev: true @@ -2573,7 +2573,7 @@ packages: dependencies: '@jest/types': 27.5.1 '@sinonjs/fake-timers': 8.1.0 - '@types/node': 20.11.17 + '@types/node': 20.11.19 jest-message-util: 27.5.1 jest-mock: 27.5.1 jest-util: 27.5.1 @@ -2602,7 +2602,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -2612,7 +2612,7 @@ packages: istanbul-lib-instrument: 5.2.1 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.6 + istanbul-reports: 3.1.7 jest-haste-map: 27.5.1 jest-resolve: 27.5.1 jest-util: 27.5.1 @@ -2686,7 +2686,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.11.17 + '@types/node': 20.11.19 '@types/yargs': 16.0.9 chalk: 4.1.2 dev: true @@ -2763,7 +2763,7 @@ packages: resolution: {integrity: sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==} dev: false - /@mui/base@5.0.0-beta.24(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): + /@mui/base@5.0.0-beta.24(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-bKt2pUADHGQtqWDZ8nvL2Lvg2GNJyd/ZUgZAJoYzRgmnxBL9j36MSlS3+exEdYkikcnvVafcBtD904RypFKb0w==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2776,17 +2776,17 @@ packages: dependencies: '@babel/runtime': 7.23.9 '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) - '@mui/types': 7.2.13(@types/react@18.2.55) - '@mui/utils': 5.15.9(@types/react@18.2.55)(react@18.2.0) + '@mui/types': 7.2.13(@types/react@18.2.57) + '@mui/utils': 5.15.9(@types/react@18.2.57)(react@18.2.0) '@popperjs/core': 2.11.8 - '@types/react': 18.2.55 + '@types/react': 18.2.57 clsx: 2.1.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /@mui/base@5.0.0-beta.36(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): + /@mui/base@5.0.0-beta.36(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-6A8fYiXgjqTO6pgj31Hc8wm1M3rFYCxDRh09dBVk0L0W4cb2lnurRJa3cAyic6hHY+we1S58OdGYRbKmOsDpGQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2799,10 +2799,10 @@ packages: dependencies: '@babel/runtime': 7.23.9 '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) - '@mui/types': 7.2.13(@types/react@18.2.55) - '@mui/utils': 5.15.9(@types/react@18.2.55)(react@18.2.0) + '@mui/types': 7.2.13(@types/react@18.2.57) + '@mui/utils': 5.15.9(@types/react@18.2.57)(react@18.2.0) '@popperjs/core': 2.11.8 - '@types/react': 18.2.55 + '@types/react': 18.2.57 clsx: 2.1.0 prop-types: 15.8.1 react: 18.2.0 @@ -2813,7 +2813,7 @@ packages: resolution: {integrity: sha512-qPv7B+LeMatYuzRjB3hlZUHqinHx/fX4YFBiaS19oC02A1e9JFuDKDvlyRQQ5oRSbJJt0QlaLTlr0IcauVcJRQ==} dev: false - /@mui/icons-material@5.15.10(@mui/material@5.15.10)(@types/react@18.2.55)(react@18.2.0): + /@mui/icons-material@5.15.10(@mui/material@5.15.10)(@types/react@18.2.57)(react@18.2.0): resolution: {integrity: sha512-9cF8oUHZKo9oQ7EQ3pxPELaZuZVmphskU4OI6NiJNDVN7zcuvrEsuWjYo1Zh4fLiC39Nrvm30h/B51rcUjvSGA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2825,12 +2825,12 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.9 - '@mui/material': 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.55 + '@mui/material': 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.57 react: 18.2.0 dev: false - /@mui/material@5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): + /@mui/material@5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-YJJGHjwDOucecjDEV5l9ISTCo+l9YeWrho623UajzoHRYxuKUmwrGVYOW4PKwGvCx9SU9oklZnbbi2Clc5XZHw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2848,14 +2848,14 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.9 - '@emotion/react': 11.11.3(@types/react@18.2.55)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.55)(react@18.2.0) - '@mui/base': 5.0.0-beta.36(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) + '@emotion/react': 11.11.3(@types/react@18.2.57)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.57)(react@18.2.0) + '@mui/base': 5.0.0-beta.36(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) '@mui/core-downloads-tracker': 5.15.10 - '@mui/system': 5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react@18.2.0) - '@mui/types': 7.2.13(@types/react@18.2.55) - '@mui/utils': 5.15.9(@types/react@18.2.55)(react@18.2.0) - '@types/react': 18.2.55 + '@mui/system': 5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react@18.2.0) + '@mui/types': 7.2.13(@types/react@18.2.57) + '@mui/utils': 5.15.9(@types/react@18.2.57)(react@18.2.0) + '@types/react': 18.2.57 '@types/react-transition-group': 4.4.10 clsx: 2.1.0 csstype: 3.1.3 @@ -2866,7 +2866,7 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false - /@mui/private-theming@5.15.9(@types/react@18.2.55)(react@18.2.0): + /@mui/private-theming@5.15.9(@types/react@18.2.57)(react@18.2.0): resolution: {integrity: sha512-/aMJlDOxOTAXyp4F2rIukW1O0anodAMCkv1DfBh/z9vaKHY3bd5fFf42wmP+0GRmwMinC5aWPpNfHXOED1fEtg==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2877,8 +2877,8 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.9 - '@mui/utils': 5.15.9(@types/react@18.2.55)(react@18.2.0) - '@types/react': 18.2.55 + '@mui/utils': 5.15.9(@types/react@18.2.57)(react@18.2.0) + '@types/react': 18.2.57 prop-types: 15.8.1 react: 18.2.0 dev: false @@ -2898,14 +2898,14 @@ packages: dependencies: '@babel/runtime': 7.23.9 '@emotion/cache': 11.11.0 - '@emotion/react': 11.11.3(@types/react@18.2.55)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.55)(react@18.2.0) + '@emotion/react': 11.11.3(@types/react@18.2.57)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.57)(react@18.2.0) csstype: 3.1.3 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/styles@5.15.10(@types/react@18.2.55)(react@18.2.0): + /@mui/styles@5.15.10(@types/react@18.2.57)(react@18.2.0): resolution: {integrity: sha512-VUl9rCK89lkCZ+ctYv1hSCN9gBke9CfnXF9BtGPkw9jTxPkrW6fQQYep2wcHdzLORE3w96oq9BbSXDqrOnSEPA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2917,10 +2917,10 @@ packages: dependencies: '@babel/runtime': 7.23.9 '@emotion/hash': 0.9.1 - '@mui/private-theming': 5.15.9(@types/react@18.2.55)(react@18.2.0) - '@mui/types': 7.2.13(@types/react@18.2.55) - '@mui/utils': 5.15.9(@types/react@18.2.55)(react@18.2.0) - '@types/react': 18.2.55 + '@mui/private-theming': 5.15.9(@types/react@18.2.57)(react@18.2.0) + '@mui/types': 7.2.13(@types/react@18.2.57) + '@mui/utils': 5.15.9(@types/react@18.2.57)(react@18.2.0) + '@types/react': 18.2.57 clsx: 2.1.0 csstype: 3.1.3 hoist-non-react-statics: 3.3.2 @@ -2936,7 +2936,7 @@ packages: react: 18.2.0 dev: false - /@mui/system@5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react@18.2.0): + /@mui/system@5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react@18.2.0): resolution: {integrity: sha512-SxkaaZ8jsnIJ77bBXttfG//LUf6nTfOcaOuIgItqfHv60ZCQy/Hu7moaob35kBb+guxVJnoSZ+7vQJrA/E7pKg==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2953,20 +2953,20 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.9 - '@emotion/react': 11.11.3(@types/react@18.2.55)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.55)(react@18.2.0) - '@mui/private-theming': 5.15.9(@types/react@18.2.55)(react@18.2.0) + '@emotion/react': 11.11.3(@types/react@18.2.57)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.57)(react@18.2.0) + '@mui/private-theming': 5.15.9(@types/react@18.2.57)(react@18.2.0) '@mui/styled-engine': 5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(react@18.2.0) - '@mui/types': 7.2.13(@types/react@18.2.55) - '@mui/utils': 5.15.9(@types/react@18.2.55)(react@18.2.0) - '@types/react': 18.2.55 + '@mui/types': 7.2.13(@types/react@18.2.57) + '@mui/utils': 5.15.9(@types/react@18.2.57)(react@18.2.0) + '@types/react': 18.2.57 clsx: 2.1.0 csstype: 3.1.3 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/types@7.2.13(@types/react@18.2.55): + /@mui/types@7.2.13(@types/react@18.2.57): resolution: {integrity: sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -2974,10 +2974,10 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.55 + '@types/react': 18.2.57 dev: false - /@mui/utils@5.15.9(@types/react@18.2.55)(react@18.2.0): + /@mui/utils@5.15.9(@types/react@18.2.57)(react@18.2.0): resolution: {integrity: sha512-yDYfr61bCYUz1QtwvpqYy/3687Z8/nS4zv7lv/ih/6ZFGMl1iolEvxRmR84v2lOYxlds+kq1IVYbXxDKh8Z9sg==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2989,13 +2989,13 @@ packages: dependencies: '@babel/runtime': 7.23.9 '@types/prop-types': 15.7.11 - '@types/react': 18.2.55 + '@types/react': 18.2.57 prop-types: 15.8.1 react: 18.2.0 react-is: 18.2.0 dev: false - /@mui/x-date-pickers@6.19.4(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@mui/material@5.15.10)(@mui/system@5.15.9)(@types/react@18.2.55)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0): + /@mui/x-date-pickers@6.19.4(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@mui/material@5.15.10)(@mui/system@5.15.9)(@types/react@18.2.57)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-LekaacLGnoQNN5hD6iXeHFL4LbZPnr1BM57hnUKy5UgKDHqzHzZSdPGc2p7Ktv/Z2NDbpPaLEAgrLwISKIYcow==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3033,12 +3033,12 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.9 - '@emotion/react': 11.11.3(@types/react@18.2.55)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.55)(react@18.2.0) - '@mui/base': 5.0.0-beta.24(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) - '@mui/material': 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) - '@mui/system': 5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react@18.2.0) - '@mui/utils': 5.15.9(@types/react@18.2.55)(react@18.2.0) + '@emotion/react': 11.11.3(@types/react@18.2.57)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.57)(react@18.2.0) + '@mui/base': 5.0.0-beta.24(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.15.9(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react@18.2.0) + '@mui/utils': 5.15.9(@types/react@18.2.57)(react@18.2.0) '@types/react-transition-group': 4.4.10 clsx: 2.1.0 dayjs: 1.11.10 @@ -3192,32 +3192,32 @@ packages: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: '@types/connect': 3.4.38 - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/bonjour@3.5.13: resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/connect-history-api-fallback@1.5.4: resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} dependencies: '@types/express-serve-static-core': 4.17.43 - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/create-react-class@15.6.7: resolution: {integrity: sha512-fM/HDjJCUCzjfn9Bi6s0xz0QF0ZKhpSeOhnewa6PjsSXQ4hyeLwTZKG83V2yk3vBNSneS7OvgS+BNFEKVrt45w==} dependencies: - '@types/react': 18.2.55 + '@types/react': 18.2.57 dev: true /@types/emscripten@1.39.10: @@ -3245,7 +3245,7 @@ packages: /@types/express-serve-static-core@4.17.43: resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 '@types/qs': 6.9.11 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -3268,20 +3268,20 @@ packages: resolution: {integrity: sha512-WRXN0kQPCnqxN0/PgNgc7WBF6c8rbSHsEep3/qBLpsQ824RONdOmTs0TV7XhIW2GDNRAHO2CqCgAFLR5PChosw==} dependencies: '@types/fbemitter': 2.0.35 - '@types/react': 18.2.55 + '@types/react': 18.2.57 dev: true /@types/glob@7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/graceful-fs@4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/history@4.7.11: @@ -3291,7 +3291,7 @@ packages: /@types/hoist-non-react-statics@3.3.5: resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==} dependencies: - '@types/react': 18.2.55 + '@types/react': 18.2.57 hoist-non-react-statics: 3.3.2 dev: false @@ -3306,7 +3306,7 @@ packages: /@types/http-proxy@1.17.14: resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/istanbul-lib-coverage@2.0.6: @@ -3365,11 +3365,11 @@ packages: /@types/node-forge@1.3.11: resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true - /@types/node@20.11.17: - resolution: {integrity: sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==} + /@types/node@20.11.19: + resolution: {integrity: sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==} dependencies: undici-types: 5.26.5 dev: true @@ -3400,20 +3400,20 @@ packages: /@types/react-beautiful-dnd@13.1.8: resolution: {integrity: sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==} dependencies: - '@types/react': 18.2.55 + '@types/react': 18.2.57 dev: true /@types/react-dom@18.2.19: resolution: {integrity: sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==} dependencies: - '@types/react': 18.2.55 + '@types/react': 18.2.57 dev: true /@types/react-redux@7.1.33: resolution: {integrity: sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==} dependencies: '@types/hoist-non-react-statics': 3.3.5 - '@types/react': 18.2.55 + '@types/react': 18.2.57 hoist-non-react-statics: 3.3.2 redux: 4.2.1 dev: false @@ -3422,7 +3422,7 @@ packages: resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.55 + '@types/react': 18.2.57 '@types/react-router': 5.1.20 dev: true @@ -3430,17 +3430,17 @@ packages: resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.55 + '@types/react': 18.2.57 dev: true /@types/react-transition-group@4.4.10: resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} dependencies: - '@types/react': 18.2.55 + '@types/react': 18.2.57 dev: false - /@types/react@18.2.55: - resolution: {integrity: sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==} + /@types/react@18.2.57: + resolution: {integrity: sha512-ZvQsktJgSYrQiMirAN60y4O/LRevIV8hUzSOSNB6gfR3/o3wCBFQx3sPwIYtuDMeiVgsSS3UzCV26tEzgnfvQw==} dependencies: '@types/prop-types': 15.7.11 '@types/scheduler': 0.16.8 @@ -3467,7 +3467,7 @@ packages: resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} dependencies: '@types/mime': 1.3.5 - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/serve-index@1.9.4: @@ -3481,13 +3481,13 @@ packages: dependencies: '@types/http-errors': 2.0.4 '@types/mime': 3.0.4 - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/sockjs@0.3.36: resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/source-list-map@0.1.6: @@ -3498,7 +3498,7 @@ packages: resolution: {integrity: sha512-ep8b36RKHlgWPqjNG9ToUrPiwkhwh0AEzy883mO5Xnd+cL6VBH1EvSjBAAuxLUFF2Vn/moE3Me6v9E1Lo+48GQ==} dependencies: '@types/emscripten': 1.39.10 - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/stack-utils@2.0.3: @@ -3518,7 +3518,7 @@ packages: /@types/webpack-sources@3.2.3: resolution: {integrity: sha512-4nZOdMwSPHZ4pTEZzSp0AsTM4K7Qmu40UKW4tJDiOVs20UzYF9l+qUe4s0ftfN0pin06n+5cWWDJXH+sbhAiDw==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 '@types/source-list-map': 0.1.6 source-map: 0.7.4 dev: true @@ -3526,7 +3526,7 @@ packages: /@types/webpack@4.41.38: resolution: {integrity: sha512-oOW7E931XJU1mVfCnxCVgv8GLFL768pDO5u2Gzk82i8yTIgX6i7cntyZOkZYb/JtYM8252SN9bQp9tgkVDSsRw==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 '@types/tapable': 1.0.12 '@types/uglify-js': 3.17.4 '@types/webpack-sources': 3.2.3 @@ -3537,7 +3537,7 @@ packages: /@types/ws@8.5.10: resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /@types/yargs-parser@21.0.3: @@ -3790,14 +3790,14 @@ packages: '@xtuc/long': 4.2.2 dev: true - /@webpack-cli/configtest@1.2.0(webpack-cli@4.10.0)(webpack@5.90.1): + /@webpack-cli/configtest@1.2.0(webpack-cli@4.10.0)(webpack@5.90.3): resolution: {integrity: sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==} peerDependencies: webpack: 4.x.x || 5.x.x webpack-cli: 4.x.x dependencies: - webpack: 5.90.1(webpack-cli@4.10.0) - webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.1) + webpack: 5.90.3(webpack-cli@4.10.0) + webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.3) dev: true /@webpack-cli/info@1.5.0(webpack-cli@4.10.0): @@ -3806,7 +3806,7 @@ packages: webpack-cli: 4.x.x dependencies: envinfo: 7.11.1 - webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.1) + webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.3) dev: true /@webpack-cli/serve@1.7.0(webpack-cli@4.10.0)(webpack-dev-server@4.15.1): @@ -3818,8 +3818,8 @@ packages: webpack-dev-server: optional: true dependencies: - webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.1) - webpack-dev-server: 4.15.1(webpack-cli@4.10.0)(webpack@5.90.1) + webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.3) + webpack-dev-server: 4.15.1(webpack-cli@4.10.0)(webpack@5.90.3) dev: true /@xtuc/ieee754@1.2.0: @@ -4135,9 +4135,11 @@ packages: engines: {node: '>=4'} dev: false - /available-typed-arrays@1.0.6: - resolution: {integrity: sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==} + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 dev: true /axe-core@4.7.0: @@ -4180,7 +4182,7 @@ packages: - supports-color dev: true - /babel-loader@8.3.0(@babel/core@7.23.9)(webpack@5.90.1): + /babel-loader@8.3.0(@babel/core@7.23.9)(webpack@5.90.3): resolution: {integrity: sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==} engines: {node: '>= 8.9'} peerDependencies: @@ -4192,7 +4194,7 @@ packages: loader-utils: 2.0.4 make-dir: 3.1.0 schema-utils: 2.7.1 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /babel-plugin-import@1.13.8: @@ -4386,8 +4388,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001587 - electron-to-chromium: 1.4.669 + caniuse-lite: 1.0.30001588 + electron-to-chromium: 1.4.676 node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.23.0) dev: true @@ -4444,8 +4446,8 @@ packages: engines: {node: '>=10'} dev: true - /caniuse-lite@1.0.30001587: - resolution: {integrity: sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==} + /caniuse-lite@1.0.30001588: + resolution: {integrity: sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==} dev: true /chalk@2.4.2: @@ -4638,7 +4640,7 @@ packages: mime-db: 1.52.0 dev: true - /compression-webpack-plugin@10.0.0(webpack@5.90.1): + /compression-webpack-plugin@10.0.0(webpack@5.90.3): resolution: {integrity: sha512-wLXLIBwpul/ALcm7Aj+69X0pYT3BYt6DdPn3qrgBIh9YejV9Bju9ShhlAsjujLyWMo6SAweFIWaUoFmXZNuNrg==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -4646,7 +4648,7 @@ packages: dependencies: schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /compression@1.7.4: @@ -4703,7 +4705,7 @@ packages: engines: {node: '>= 0.6'} dev: true - /copy-webpack-plugin@10.2.4(webpack@5.90.1): + /copy-webpack-plugin@10.2.4(webpack@5.90.3): resolution: {integrity: sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==} engines: {node: '>= 12.20.0'} peerDependencies: @@ -4715,7 +4717,7 @@ packages: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /core-js-compat@3.36.0: @@ -4767,7 +4769,7 @@ packages: tiny-invariant: 1.3.1 dev: false - /css-loader@6.10.0(webpack@5.90.1): + /css-loader@6.10.0(webpack@5.90.3): resolution: {integrity: sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -4787,7 +4789,7 @@ packages: postcss-modules-values: 4.0.0(postcss@8.4.35) postcss-value-parser: 4.2.0 semver: 7.6.0 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /css-select@4.3.0: @@ -5085,8 +5087,8 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: true - /electron-to-chromium@1.4.669: - resolution: {integrity: sha512-E2SmpffFPrZhBSgf8ibqanRS2mpuk3FIRDzLDwt7WFpfgJMKDHJs0hmacyP0PS1cWsq0dVkwIIzlscNaterkPg==} + /electron-to-chromium@1.4.676: + resolution: {integrity: sha512-uHt4FB8SeYdhcOsj2ix/C39S7sPSNFJpzShjxGOm1KdF4MHyGqGi389+T5cErsodsijojXilYaHIKKqJfqh7uQ==} dev: true /email-addresses@3.1.0: @@ -5153,7 +5155,7 @@ packages: dependencies: array-buffer-byte-length: 1.0.1 arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.6 + available-typed-arrays: 1.0.7 call-bind: 1.0.7 es-define-property: 1.0.0 es-errors: 1.3.0 @@ -5165,13 +5167,13 @@ packages: globalthis: 1.0.3 gopd: 1.0.1 has-property-descriptors: 1.0.2 - has-proto: 1.0.1 + has-proto: 1.0.3 has-symbols: 1.0.3 hasown: 2.0.1 internal-slot: 1.0.7 is-array-buffer: 3.0.4 is-callable: 1.2.7 - is-negative-zero: 2.0.2 + is-negative-zero: 2.0.3 is-regex: 1.1.4 is-shared-array-buffer: 1.0.2 is-string: 1.0.7 @@ -5186,9 +5188,9 @@ packages: string.prototype.trim: 1.2.8 string.prototype.trimend: 1.0.7 string.prototype.trimstart: 1.0.7 - typed-array-buffer: 1.0.1 + typed-array-buffer: 1.0.2 typed-array-byte-length: 1.0.0 - typed-array-byte-offset: 1.0.0 + typed-array-byte-offset: 1.0.1 typed-array-length: 1.0.4 unbox-primitive: 1.0.2 which-typed-array: 1.1.14 @@ -5224,7 +5226,7 @@ packages: get-intrinsic: 1.2.4 globalthis: 1.0.3 has-property-descriptors: 1.0.2 - has-proto: 1.0.1 + has-proto: 1.0.3 has-symbols: 1.0.3 internal-slot: 1.0.7 iterator.prototype: 1.1.2 @@ -5740,7 +5742,7 @@ packages: flat-cache: 3.2.0 dev: true - /file-loader@6.2.0(webpack@5.90.1): + /file-loader@6.2.0(webpack@5.90.3): resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -5748,7 +5750,7 @@ packages: dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /file-selector@0.6.0: @@ -5836,7 +5838,7 @@ packages: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: - flatted: 3.2.9 + flatted: 3.3.0 keyv: 4.5.4 rimraf: 3.0.2 dev: true @@ -5846,8 +5848,8 @@ packages: hasBin: true dev: true - /flatted@3.2.9: - resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + /flatted@3.3.0: + resolution: {integrity: sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==} dev: true /focus-trap-react@8.11.3(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0): @@ -5988,7 +5990,7 @@ packages: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 - has-proto: 1.0.1 + has-proto: 1.0.3 has-symbols: 1.0.3 hasown: 2.0.1 dev: true @@ -6153,8 +6155,8 @@ packages: es-define-property: 1.0.0 dev: true - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} engines: {node: '>= 0.4'} dev: true @@ -6223,7 +6225,7 @@ packages: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true - /html-loader@5.0.0(webpack@5.90.1): + /html-loader@5.0.0(webpack@5.90.3): resolution: {integrity: sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==} engines: {node: '>= 18.12.0'} peerDependencies: @@ -6231,7 +6233,7 @@ packages: dependencies: html-minifier-terser: 7.2.0 parse5: 7.1.2 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /html-minifier-terser@6.1.0: @@ -6245,7 +6247,7 @@ packages: he: 1.2.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.27.0 + terser: 5.27.2 dev: true /html-minifier-terser@7.2.0: @@ -6259,7 +6261,7 @@ packages: entities: 4.5.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.27.0 + terser: 5.27.2 dev: true /html-parse-stringify@3.0.1: @@ -6280,7 +6282,7 @@ packages: style-to-js: 1.1.1 dev: false - /html-webpack-plugin@5.6.0(webpack@5.90.1): + /html-webpack-plugin@5.6.0(webpack@5.90.3): resolution: {integrity: sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==} engines: {node: '>=10.13.0'} peerDependencies: @@ -6297,7 +6299,7 @@ packages: lodash: 4.17.21 pretty-error: 4.0.0 tapable: 2.2.1 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /htmlparser2@6.1.0: @@ -6433,8 +6435,8 @@ packages: '@babel/runtime': 7.23.9 dev: false - /i18next@23.8.2: - resolution: {integrity: sha512-Z84zyEangrlERm0ZugVy4bIt485e/H8VecGUZkZWrH7BDePG6jT73QdL9EA1tRTTVVMpry/MgWIP1FjEn0DRXA==} + /i18next@23.9.0: + resolution: {integrity: sha512-f3MUciKqwzNV//mHG6EtdSlC65+nqH/3zK8sOSWqNV6FVu2tmHhF/rFOp9UF8S4m1odojtuipKaKJrP0Loh60g==} dependencies: '@babel/runtime': 7.23.9 dev: false @@ -6637,8 +6639,8 @@ packages: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} dev: true - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + /is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} dev: true @@ -6807,8 +6809,8 @@ packages: - supports-color dev: true - /istanbul-reports@3.1.6: - resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + /istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} dependencies: html-escaper: 2.0.2 @@ -6822,7 +6824,7 @@ packages: get-intrinsic: 1.2.4 has-symbols: 1.0.3 reflect.getprototypeof: 1.0.5 - set-function-name: 2.0.1 + set-function-name: 2.0.2 dev: true /jest-changed-files@27.5.1: @@ -6841,7 +6843,7 @@ packages: '@jest/environment': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -6966,7 +6968,7 @@ packages: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 jest-mock: 27.5.1 jest-util: 27.5.1 jsdom: 16.7.0 @@ -6984,7 +6986,7 @@ packages: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 jest-mock: 27.5.1 jest-util: 27.5.1 dev: true @@ -7000,7 +7002,7 @@ packages: dependencies: '@jest/types': 27.5.1 '@types/graceful-fs': 4.1.9 - '@types/node': 20.11.17 + '@types/node': 20.11.19 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -7022,7 +7024,7 @@ packages: '@jest/source-map': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 chalk: 4.1.2 co: 4.6.0 expect: 27.5.1 @@ -7077,7 +7079,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 dev: true /jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): @@ -7133,7 +7135,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 chalk: 4.1.2 emittery: 0.8.1 graceful-fs: 4.2.11 @@ -7190,7 +7192,7 @@ packages: resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 graceful-fs: 4.2.11 dev: true @@ -7229,7 +7231,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -7254,7 +7256,7 @@ packages: dependencies: '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.11.17 + '@types/node': 20.11.19 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 27.5.1 @@ -7265,7 +7267,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.11.17 + '@types/node': 20.11.19 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -7578,13 +7580,13 @@ packages: p-locate: 5.0.0 dev: true - /lodash-webpack-plugin@0.11.6(webpack@5.90.1): + /lodash-webpack-plugin@0.11.6(webpack@5.90.3): resolution: {integrity: sha512-nsHN/+IxZK/C425vGC8pAxkKJ8KQH2+NJnhDul14zYNWr6HJcA95w+oRR7Cp0oZpOdMplDZXmjVROp8prPk7ig==} peerDependencies: webpack: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.1.0 dependencies: lodash: 4.17.21 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /lodash.debounce@4.0.8: @@ -7659,14 +7661,14 @@ packages: resolution: {integrity: sha512-X1dtuTuH2D1MRMuductMZCLV/fy9EoIgqW/lmu8vQSAhEatx/tdFebkYT3TVhdTwqFDHbLEgQBD3IKA4KI7aoQ==} dev: false - /markdown-loader@8.0.0(webpack@5.90.1): + /markdown-loader@8.0.0(webpack@5.90.3): resolution: {integrity: sha512-dxrR3WhK/hERbStPFb/yeNdEeWCKa2qUDdXiq3VTruBUWufOtERX04X0K44K4dnlN2i9pjSEzYIQJ3LjH0xkEw==} engines: {node: '>=12.22.9'} peerDependencies: webpack: ^5.0.0 dependencies: marked: 4.3.0 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /markdown-to-jsx@7.4.1(react@18.2.0): @@ -7696,11 +7698,11 @@ packages: react: '>=18.0' react-dom: '>=18.0' dependencies: - '@emotion/react': 11.11.3(@types/react@18.2.55)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.55)(react@18.2.0) - '@mui/icons-material': 5.15.10(@mui/material@5.15.10)(@types/react@18.2.55)(react@18.2.0) - '@mui/material': 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) - '@mui/x-date-pickers': 6.19.4(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@mui/material@5.15.10)(@mui/system@5.15.9)(@types/react@18.2.55)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) + '@emotion/react': 11.11.3(@types/react@18.2.57)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.57)(react@18.2.0) + '@mui/icons-material': 5.15.10(@mui/material@5.15.10)(@types/react@18.2.57)(react@18.2.0) + '@mui/material': 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) + '@mui/x-date-pickers': 6.19.4(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@mui/material@5.15.10)(@mui/system@5.15.9)(@types/react@18.2.57)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) '@tanstack/match-sorter-utils': 8.11.3 '@tanstack/react-table': 8.11.3(react-dom@18.2.0)(react@18.2.0) '@tanstack/react-virtual': 3.0.1(react-dom@18.2.0)(react@18.2.0) @@ -8217,6 +8219,11 @@ packages: find-up: 4.1.0 dev: true + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: true + /postcss-modules-extract-imports@3.0.0(postcss@8.4.35): resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==} engines: {node: ^10 || ^12 || >= 14} @@ -8509,7 +8516,7 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /react-i18next@13.5.0(i18next@23.8.2)(react-dom@18.2.0)(react@18.2.0): + /react-i18next@13.5.0(i18next@23.9.0)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-CFJ5NDGJ2MUyBohEHxljOq/39NQ972rh1ajnadG9BjTk+UXbHLq4z5DKEbEQBDoIhUmmbuS/fIMJKo6VOax1HA==} peerDependencies: i18next: '>= 23.2.3' @@ -8524,7 +8531,7 @@ packages: dependencies: '@babel/runtime': 7.23.9 html-parse-stringify: 3.0.1 - i18next: 23.8.2 + i18next: 23.9.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -8688,7 +8695,7 @@ packages: call-bind: 1.0.7 define-properties: 1.2.1 es-errors: 1.3.0 - set-function-name: 2.0.1 + set-function-name: 2.0.2 dev: true /regexpu-core@5.3.2: @@ -8859,7 +8866,7 @@ packages: postcss: 8.4.35 dev: false - /sass-loader@12.6.0(sass@1.70.0)(webpack@5.90.1): + /sass-loader@12.6.0(sass@1.71.0)(webpack@5.90.3): resolution: {integrity: sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -8880,12 +8887,12 @@ packages: dependencies: klona: 2.0.6 neo-async: 2.6.2 - sass: 1.70.0 - webpack: 5.90.1(webpack-cli@4.10.0) + sass: 1.71.0 + webpack: 5.90.3(webpack-cli@4.10.0) dev: true - /sass@1.70.0: - resolution: {integrity: sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==} + /sass@1.71.0: + resolution: {integrity: sha512-HKKIKf49Vkxlrav3F/w6qRuPcmImGVbIXJ2I3Kg0VMA+3Bav+8yE9G5XmP5lMj6nl4OlqbPftGAscNaNu28b8w==} engines: {node: '>=14.0.0'} hasBin: true dependencies: @@ -9024,11 +9031,12 @@ packages: has-property-descriptors: 1.0.2 dev: true - /set-function-name@2.0.1: - resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + /set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} dependencies: define-data-property: 1.1.4 + es-errors: 1.3.0 functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 dev: true @@ -9087,7 +9095,7 @@ packages: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true - /simple-zustand-devtools@1.1.0(@types/react-dom@18.2.19)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)(zustand@4.4.7): + /simple-zustand-devtools@1.1.0(@types/react-dom@18.2.19)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0)(zustand@4.4.7): resolution: {integrity: sha512-Axfcfr9L3YL3kto7aschCQLY2VUlXXMnIVtaTe9Y0qWbNmPsX/y7KsNprmxBZoB0pww5ZGs1u/ohcrvQ3tE6jA==} peerDependencies: '@types/react': '>=18.0.0' @@ -9096,11 +9104,11 @@ packages: react-dom: '>=18.0.0' zustand: '>=1.0.2' dependencies: - '@types/react': 18.2.55 + '@types/react': 18.2.57 '@types/react-dom': 18.2.19 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - zustand: 4.4.7(@types/react@18.2.55)(react@18.2.0) + zustand: 4.4.7(@types/react@18.2.57)(react@18.2.0) dev: true /sirv@2.0.4: @@ -9271,7 +9279,7 @@ packages: has-symbols: 1.0.3 internal-slot: 1.0.7 regexp.prototype.flags: 1.5.2 - set-function-name: 2.0.1 + set-function-name: 2.0.2 side-channel: 1.0.5 dev: true @@ -9346,13 +9354,13 @@ packages: escape-string-regexp: 1.0.5 dev: true - /style-loader@3.3.4(webpack@5.90.1): + /style-loader@3.3.4(webpack@5.90.3): resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 dependencies: - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true /style-to-js@1.1.1: @@ -9424,7 +9432,7 @@ packages: supports-hyperlinks: 2.3.0 dev: true - /terser-webpack-plugin@5.3.10(webpack@5.90.1): + /terser-webpack-plugin@5.3.10(webpack@5.90.3): resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -9444,12 +9452,12 @@ packages: jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 - terser: 5.27.0 - webpack: 5.90.1(webpack-cli@4.10.0) + terser: 5.27.2 + webpack: 5.90.3(webpack-cli@4.10.0) dev: true - /terser@5.27.0: - resolution: {integrity: sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==} + /terser@5.27.2: + resolution: {integrity: sha512-sHXmLSkImesJ4p5apTeT63DsV4Obe1s37qT8qvwHRmVxKTBH7Rv9Wr26VcAMmLbmk9UliiwK8z+657NyJHHy/w==} engines: {node: '>=10'} hasBin: true dependencies: @@ -9598,8 +9606,8 @@ packages: mime-types: 2.1.35 dev: true - /typed-array-buffer@1.0.1: - resolution: {integrity: sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==} + /typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.7 @@ -9613,18 +9621,19 @@ packages: dependencies: call-bind: 1.0.7 for-each: 0.3.3 - has-proto: 1.0.1 + has-proto: 1.0.3 is-typed-array: 1.1.13 dev: true - /typed-array-byte-offset@1.0.0: - resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + /typed-array-byte-offset@1.0.1: + resolution: {integrity: sha512-tcqKMrTRXjqvHN9S3553NPCaGL0VPgFI92lXszmrE8DMhiDPLBYLlvo8Uu4WZAAX/aGqp/T1sbA4ph8EWjDF9Q==} engines: {node: '>= 0.4'} dependencies: - available-typed-arrays: 1.0.6 + available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 - has-proto: 1.0.1 + gopd: 1.0.1 + has-proto: 1.0.3 is-typed-array: 1.1.13 dev: true @@ -9880,7 +9889,7 @@ packages: humanize: 0.0.9 dev: true - /webpack-cli@4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.1): + /webpack-cli@4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.3): resolution: {integrity: sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==} engines: {node: '>=10.13.0'} hasBin: true @@ -9901,7 +9910,7 @@ packages: optional: true dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 1.2.0(webpack-cli@4.10.0)(webpack@5.90.1) + '@webpack-cli/configtest': 1.2.0(webpack-cli@4.10.0)(webpack@5.90.3) '@webpack-cli/info': 1.5.0(webpack-cli@4.10.0) '@webpack-cli/serve': 1.7.0(webpack-cli@4.10.0)(webpack-dev-server@4.15.1) colorette: 2.0.20 @@ -9911,13 +9920,13 @@ packages: import-local: 3.1.0 interpret: 2.2.0 rechoir: 0.7.1 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) webpack-bundle-analyzer: 4.10.1 - webpack-dev-server: 4.15.1(webpack-cli@4.10.0)(webpack@5.90.1) + webpack-dev-server: 4.15.1(webpack-cli@4.10.0)(webpack@5.90.3) webpack-merge: 5.10.0 dev: true - /webpack-dev-middleware@5.3.3(webpack@5.90.1): + /webpack-dev-middleware@5.3.3(webpack@5.90.3): resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -9928,10 +9937,10 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.90.1(webpack-cli@4.10.0) + webpack: 5.90.3(webpack-cli@4.10.0) dev: true - /webpack-dev-server@4.15.1(webpack-cli@4.10.0)(webpack@5.90.1): + /webpack-dev-server@4.15.1(webpack-cli@4.10.0)(webpack@5.90.3): resolution: {integrity: sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==} engines: {node: '>= 12.13.0'} hasBin: true @@ -9972,9 +9981,9 @@ packages: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.90.1(webpack-cli@4.10.0) - webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.1) - webpack-dev-middleware: 5.3.3(webpack@5.90.1) + webpack: 5.90.3(webpack-cli@4.10.0) + webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.3) + webpack-dev-middleware: 5.3.3(webpack@5.90.3) ws: 8.16.0 transitivePeerDependencies: - bufferutil @@ -9997,8 +10006,8 @@ packages: engines: {node: '>=10.13.0'} dev: true - /webpack@5.90.1(webpack-cli@4.10.0): - resolution: {integrity: sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==} + /webpack@5.90.3(webpack-cli@4.10.0): + resolution: {integrity: sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -10028,9 +10037,9 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.90.1) + terser-webpack-plugin: 5.3.10(webpack@5.90.3) watchpack: 2.4.0 - webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.1) + webpack-cli: 4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.15.1)(webpack@5.90.3) webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' @@ -10119,7 +10128,7 @@ packages: resolution: {integrity: sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==} engines: {node: '>= 0.4'} dependencies: - available-typed-arrays: 1.0.6 + available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 @@ -10258,7 +10267,7 @@ packages: resolution: {integrity: sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==} dev: false - /zustand@4.4.7(@types/react@18.2.55)(react@18.2.0): + /zustand@4.4.7(@types/react@18.2.57)(react@18.2.0): resolution: {integrity: sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==} engines: {node: '>=12.7.0'} peerDependencies: @@ -10273,30 +10282,30 @@ packages: react: optional: true dependencies: - '@types/react': 18.2.55 + '@types/react': 18.2.57 react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) - github.com/Canadian-Geospatial-Platform/geochart/13db37a4840c633125779b611050b75d13ccd93f(@types/react@18.2.55): + github.com/Canadian-Geospatial-Platform/geochart/13db37a4840c633125779b611050b75d13ccd93f(@types/react@18.2.57): resolution: {tarball: https://codeload.github.com/Canadian-Geospatial-Platform/geochart/tar.gz/13db37a4840c633125779b611050b75d13ccd93f} id: github.com/Canadian-Geospatial-Platform/geochart/13db37a4840c633125779b611050b75d13ccd93f name: geoview-geochart version: 0.1.0 dependencies: - '@emotion/react': 11.11.3(@types/react@18.2.55)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.55)(react@18.2.0) - '@mui/icons-material': 5.15.10(@mui/material@5.15.10)(@types/react@18.2.55)(react@18.2.0) - '@mui/material': 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) + '@emotion/react': 11.11.3(@types/react@18.2.57)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.57)(react@18.2.0) + '@mui/icons-material': 5.15.10(@mui/material@5.15.10)(@types/react@18.2.57)(react@18.2.0) + '@mui/material': 5.15.10(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.57)(react-dom@18.2.0)(react@18.2.0) ajv: 8.12.0 ajv-formats: 2.1.1 chart.js: 4.4.1 chartjs-adapter-moment: 1.0.1(chart.js@4.4.1)(moment@2.30.1) - i18next: 23.8.2 + i18next: 23.9.0 moment: 2.30.1 react: 18.2.0 react-chartjs-2: 5.2.0(chart.js@4.4.1)(react@18.2.0) react-dom: 18.2.0(react@18.2.0) - react-i18next: 13.5.0(i18next@23.8.2)(react-dom@18.2.0)(react@18.2.0) + react-i18next: 13.5.0(i18next@23.9.0)(react-dom@18.2.0)(react@18.2.0) transitivePeerDependencies: - '@types/react' - react-native diff --git a/packages/geoview-core/public/templates/raw-feature-info.html b/packages/geoview-core/public/templates/raw-feature-info.html index ec9dc780d37..8d5a0fc1caf 100644 --- a/packages/geoview-core/public/templates/raw-feature-info.html +++ b/packages/geoview-core/public/templates/raw-feature-info.html @@ -92,7 +92,8 @@

1. Basic Map English Geo.ca theme

'geoviewLayerType': 'esriFeature', 'listOfLayerEntryConfig': [ { - 'layerId': '1' + 'layerId': '1', + 'initialSettings': { 'removable': false } } ] }, diff --git a/packages/geoview-core/schema.json b/packages/geoview-core/schema.json index 9b7493864d7..a96ecf9408c 100644 --- a/packages/geoview-core/schema.json +++ b/packages/geoview-core/schema.json @@ -36,9 +36,7 @@ "description": "A path to an html template (English/French) that will override default identify output." } }, - "required": [ - "template" - ] + "required": ["template"] }, "TypeFeatureInfoLayerConfig": { "additionalProperties": false, @@ -69,9 +67,7 @@ "description": "A comma separated list of attribute names (English/French) that should be use for alias. If empty, no alias will be set if not found." } }, - "required": [ - "queryable" - ] + "required": ["queryable"] }, "TypeFeatureInfoNotQueryable": { "additionalProperties": false, @@ -83,9 +79,7 @@ "description": "Do not allow querying." } }, - "required": [ - "queryable" - ] + "required": ["queryable"] }, "TypeStrokeSymbolConfig": { "minProperties": 1, @@ -121,27 +115,20 @@ "type": "object", "properties": { "type": { - "enum": [ - "lineString" - ] + "enum": ["lineString"] }, "stroke": { "$ref": "#/definitions/TypeStrokeSymbolConfig" } }, - "required": [ - "type", - "stroke" - ] + "required": ["type", "stroke"] }, "TypePolygonVectorConfig": { "additionalProperties": false, "type": "object", "properties": { "type": { - "enum": [ - "filledPolygon" - ] + "enum": ["filledPolygon"] }, "color": { "type": "string" @@ -158,32 +145,18 @@ "description": "Patern line width.default = 1." }, "fillStyle": { - "enum": [ - "solid", - "backwardDiagonal", - "cross", - "diagonalCross", - "forwardDiagonal", - "horizontal", - "null", - "vertical" - ], + "enum": ["solid", "backwardDiagonal", "cross", "diagonalCross", "forwardDiagonal", "horizontal", "null", "vertical"], "description": "Kind of filling for vector features. Default = solid. " } }, - "required": [ - "type", - "stroke" - ] + "required": ["type", "stroke"] }, "TypeSimpleSymbolVectorConfig": { "additionalProperties": false, "type": "object", "properties": { "type": { - "enum": [ - "simpleSymbol" - ] + "enum": ["simpleSymbol"] }, "rotation": { "type": "number", @@ -207,30 +180,17 @@ "maxItems": 2 }, "symbol": { - "enum": [ - "circle", - "+", - "diamond", - "square", - "triangle", - "X", - "star" - ] + "enum": ["circle", "+", "diamond", "square", "triangle", "X", "star"] } }, - "required": [ - "type", - "symbol" - ] + "required": ["type", "symbol"] }, "TypeIconSymbolVectorConfig": { "additionalProperties": false, "type": "object", "properties": { "type": { - "enum": [ - "iconSymbol" - ] + "enum": ["iconSymbol"] }, "mimeType": { "type": "string" @@ -269,11 +229,7 @@ "description": "The crossOrigin attribute for loaded images. Note that you must provide a crossOrigin value if you want to access pixel data with the Canvas renderer." } }, - "required": [ - "type", - "mimeType", - "src" - ] + "required": ["type", "mimeType", "src"] }, "TypeSimpleStyleConfig": { "additionalProperties": false, @@ -283,9 +239,7 @@ "type": "string" }, "styleType": { - "enum": [ - "simple" - ] + "enum": ["simple"] }, "label": { "type": "string" @@ -294,11 +248,7 @@ "$ref": "#/definitions/TypeKindOfVectorSettings" } }, - "required": [ - "styleType", - "label", - "settings" - ] + "required": ["styleType", "label", "settings"] }, "TypeUniqueValueStyleConfig": { "additionalProperties": false, @@ -308,20 +258,14 @@ "type": "string" }, "styleType": { - "enum": [ - "uniqueValue" - ] + "enum": ["uniqueValue"] }, "defaultLabel": { "type": "string", "description": "Label used if field/value association is not found." }, "defaultVisible": { - "enum": [ - "yes", - "no", - "always" - ], + "enum": ["yes", "no", "always"], "description": "Flag used to show/hide features associated to the default label (default: yes)." }, "defaultSettings": { @@ -339,11 +283,7 @@ "$ref": "#/definitions/TypeUniqueValueStyleInfo" } }, - "required": [ - "styleType", - "fields", - "uniqueValueStyleInfo" - ] + "required": ["styleType", "fields", "uniqueValueStyleInfo"] }, "TypeUniqueValueStyleInfo": { "type": "array", @@ -355,11 +295,7 @@ "type": "string" }, "visible": { - "enum": [ - "yes", - "no", - "always" - ], + "enum": ["yes", "no", "always"], "description": "Flag used to show/hide features associated to the label (default: yes)." }, "values": { @@ -382,11 +318,7 @@ } }, "minItems": 1, - "required": [ - "label", - "values", - "options" - ] + "required": ["label", "values", "options"] }, "TypeClassBreakStyleConfig": { "additionalProperties": false, @@ -396,20 +328,14 @@ "type": "string" }, "styleType": { - "enum": [ - "classBreaks" - ] + "enum": ["classBreaks"] }, "defaultLabel": { "type": "string", "description": "Label used if field/value association is not found." }, "defaultVisible": { - "enum": [ - "yes", - "no", - "always" - ], + "enum": ["yes", "no", "always"], "description": "Flag used to show/hide features associated to the default label (default: yes)." }, "defaultSettings": { @@ -423,11 +349,7 @@ "$ref": "#/definitions/TypeClassBreakStyleInfo" } }, - "required": [ - "styleType", - "field", - "classBreakStyleInfo" - ] + "required": ["styleType", "field", "classBreakStyleInfo"] }, "TypeClassBreakStyleInfo": { "additionalProperties": false, @@ -440,11 +362,7 @@ "type": "string" }, "visible": { - "enum": [ - "yes", - "no", - "always" - ], + "enum": ["yes", "no", "always"], "description": "Flag used to show/hide features associated to the label (default: yes)." }, "minValue": { @@ -473,12 +391,7 @@ } }, "minItems": 1, - "required": [ - "label", - "minValue", - "maxValue", - "settings" - ] + "required": ["label", "minValue", "maxValue", "settings"] }, "TypeKindOfVectorSettings": { "oneOf": [ @@ -537,11 +450,7 @@ "description": "Initial opacity setting." }, "visible": { - "enum": [ - "yes", - "no", - "always" - ], + "enum": ["yes", "no", "always"], "default": "yes", "description": "Initial visibility setting." }, @@ -578,19 +487,23 @@ "className": { "type": "string", "description": "A CSS class name to set to the layer element." + }, + "removable": { + "type": "boolean", + "description": "Is the layer removable." + }, + "hoverable": { + "type": "boolean", + "description": "Is the layer hoverable." + }, + "queryable": { + "type": "boolean", + "description": "Is the layer queryable." } } }, "TypeVectorSourceFormats": { - "enum": [ - "GeoJSON", - "EsriJSON", - "KML", - "WFS", - "featureAPI", - "GeoPackage", - "CSV" - ], + "enum": ["GeoJSON", "EsriJSON", "KML", "WFS", "featureAPI", "GeoPackage", "CSV"], "description": "The feature format used by the XHR feature loader when access path is set." }, "TypeVectorSourceInitialConfig": { @@ -623,10 +536,7 @@ "$ref": "#/definitions/TypeFeatureInfoLayerConfig" }, "strategy": { - "enum": [ - "all", - "bbox" - ], + "enum": ["all", "bbox"], "default": "all", "description": "The loading strategy to use. By default an all strategy is used, a one-off strategy which loads all features at once." }, @@ -677,11 +587,7 @@ } }, "TypeOfServer": { - "enum": [ - "mapserver", - "geoserver", - "qgis" - ], + "enum": ["mapserver", "geoserver", "qgis"], "description": "The type of the remote WMS server. The default value is mapserver." }, "TypeSourceImageStaticInitialConfig": { @@ -744,12 +650,7 @@ } }, "TypeEsriFormatParameter": { - "enum": [ - "png", - "jpg", - "gif", - "svg" - ], + "enum": ["png", "jpg", "gif", "svg"], "default": "png", "description": "The format of the exported image. The default format is png." }, @@ -815,31 +716,21 @@ "items": { "type": "number" }, - "default": [ - 256, - 256 - ], + "default": [256, 256], "description": "The tile grid origin, i.e. where the x and y axes meet ([z, 0, 0]). Tile coordinates increase left to right and downwards. If not specified, extent must be provided." } }, - "required": [ - "origin", - "resolutions" - ] + "required": ["origin", "resolutions"] }, "TypeVectorHeatmapLayerEntryConfig": { "additionalProperties": false, "type": "object", "properties": { "schemaTag": { - "enum": [ - "not used yet" - ] + "enum": ["not used yet"] }, "entryType": { - "enum": [ - "vector-heatmap" - ] + "enum": ["vector-heatmap"] }, "layerPathEnding": { "type": "string", @@ -867,13 +758,7 @@ }, "uniqueItems": true, "minItems": 2, - "default": [ - "#00f", - "#0ff", - "#0f0", - "#ff0", - "#f00" - ], + "default": ["#00f", "#0ff", "#0f0", "#ff0", "#f00"], "description": "Color gradient of the heatmap, specified as an array of CSS color strings." }, "radius": { @@ -895,30 +780,17 @@ } } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeVectorLayerEntryConfig": { "additionalProperties": false, "type": "object", "properties": { "schemaTag": { - "enum": [ - "CSV", - "GeoJSON", - "esriFeature", - "ogcWfs", - "ogcFeature", - "GeoPackage" - ] + "enum": ["CSV", "GeoJSON", "esriFeature", "ogcWfs", "ogcFeature", "GeoPackage"] }, "entryType": { - "enum": [ - "vector" - ] + "enum": ["vector"] }, "layerPathEnding": { "type": "string", @@ -953,11 +825,7 @@ } } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeVectorTileLayerEntryConfig": { "additionalProperties": false, @@ -965,14 +833,10 @@ "description": "Layer sources providing vector data divided into a tile grid.", "properties": { "schemaTag": { - "enum": [ - "not used yet" - ] + "enum": ["not used yet"] }, "entryType": { - "enum": [ - "vector-tile" - ] + "enum": ["vector-tile"] }, "layerPathEnding": { "type": "string", @@ -1008,11 +872,7 @@ } } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeVectorTileSourceInitialConfig": { "additionalProperties": false, @@ -1024,14 +884,7 @@ "description": "The path (English/French) to reach the data to display. If not specified, metadatAccessPath will be assigne dto it." }, "format": { - "enum": [ - "GeoJSON", - "EsriJSON", - "KML", - "WFS", - "MVT", - "featureAPI" - ], + "enum": ["GeoJSON", "EsriJSON", "KML", "WFS", "MVT", "featureAPI"], "description": "The feature format used by the XHR feature loader when access path is set." }, "dataProjection": { @@ -1051,14 +904,10 @@ "type": "object", "properties": { "schemaTag": { - "enum": [ - "ogcWms" - ] + "enum": ["ogcWms"] }, "entryType": { - "enum": [ - "raster-image" - ] + "enum": ["raster-image"] }, "layerId": { "type": "string", @@ -1093,25 +942,17 @@ } } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeEsriDynamicLayerEntryConfig": { "additionalProperties": false, "type": "object", "properties": { "schemaTag": { - "enum": [ - "esriDynamic" - ] + "enum": ["esriDynamic"] }, "entryType": { - "enum": [ - "raster-image" - ] + "enum": ["raster-image"] }, "layerId": { "type": "string", @@ -1146,25 +987,17 @@ } } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeEsriImageLayerEntryConfig": { "additionalProperties": false, "type": "object", "properties": { "schemaTag": { - "enum": [ - "esriImage" - ] + "enum": ["esriImage"] }, "entryType": { - "enum": [ - "raster-image" - ] + "enum": ["raster-image"] }, "layerId": { "type": "string", @@ -1199,25 +1032,17 @@ } } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeImageStaticLayerEntryConfig": { "additionalProperties": false, "type": "object", "properties": { "schemaTag": { - "enum": [ - "imageStatic" - ] + "enum": ["imageStatic"] }, "entryType": { - "enum": [ - "raster-image" - ] + "enum": ["raster-image"] }, "layerId": { "type": "string", @@ -1245,27 +1070,17 @@ } } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeTileLayerEntryConfig": { "additionalProperties": false, "type": "object", "properties": { "schemaTag": { - "enum": [ - "ogcWms", - "xyzTiles", - "vectorTiles" - ] + "enum": ["ogcWms", "xyzTiles", "vectorTiles"] }, "entryType": { - "enum": [ - "raster-tile" - ] + "enum": ["raster-tile"] }, "layerPathEnding": { "type": "string", @@ -1293,11 +1108,7 @@ } } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeGeocoreLayerEntryConfig": { "additionalProperties": false, @@ -1305,14 +1116,10 @@ "description": "Layer where configration is extracted by a configuration snippet stored on a server. The server configuration will handle bilangual informations.", "properties": { "schemaTag": { - "enum": [ - "geoCore" - ] + "enum": ["geoCore"] }, "entryType": { - "enum": [ - "geoCore" - ] + "enum": ["geoCore"] }, "layerId": { "type": "string", @@ -1334,11 +1141,7 @@ "description": "The list of layer entry configurations to use from the GeoView layer group." } }, - "required": [ - "schemaTag", - "entryType", - "layerId" - ] + "required": ["schemaTag", "entryType", "layerId"] }, "TypeSourceGeocoreConfig": { "additionalProperties": false, @@ -1355,14 +1158,7 @@ } }, "TypeLayerEntryType": { - "enum": [ - "vector", - "vector-tile", - "vector-heatmap", - "raster-tile", - "raster-image", - "geoCore" - ], + "enum": ["vector", "vector-tile", "vector-heatmap", "raster-tile", "raster-image", "geoCore"], "description": "Layer entry data type." }, "TypeLayerGroupEntryConfig": { @@ -1371,9 +1167,7 @@ "description": "Entry used to define a layer Group.", "properties": { "entryType": { - "enum": [ - "group" - ] + "enum": ["group"] }, "layerId": { "type": "string", @@ -1398,11 +1192,7 @@ "description": "The list of layer entry configurations to use from the GeoView layer group." } }, - "required": [ - "entryType", - "layerId", - "listOfLayerEntryConfig" - ] + "required": ["entryType", "layerId", "listOfLayerEntryConfig"] }, "TypeLayerEntryConfig": { "oneOf": [ @@ -1652,11 +1442,7 @@ "description": "Additional options used for OpenLayers map options" } }, - "required": [ - "basemapOptions", - "interaction", - "viewSettings" - ] + "required": ["basemapOptions", "interaction", "viewSettings"] }, "TypeBasemapOptions": { "additionalProperties": false, @@ -1676,28 +1462,15 @@ "description": "Enable or disable basemap labels" } }, - "required": [ - "basemapId", - "shaded", - "labeled" - ] + "required": ["basemapId", "shaded", "labeled"] }, "TypeBasemapId": { - "enum": [ - "transport", - "osm", - "simple", - "nogeom", - "shaded" - ], + "enum": ["transport", "osm", "simple", "nogeom", "shaded"], "default": "transport", "description": "Id of the basemap to use." }, "TypeInteraction": { - "enum": [ - "static", - "dynamic" - ], + "enum": ["static", "dynamic"], "default": "dynamic", "description": "If map is dynamic (pan/zoom) or static to act as a thumbnail (no nav bar)." }, @@ -1746,10 +1519,7 @@ "description": "The layer entries to use from the GeoView layer." } }, - "required": [ - "geoviewLayerType", - "listOfLayerEntryConfig" - ] + "required": ["geoviewLayerType", "listOfLayerEntryConfig"] }, "TypeGeoviewLayerType": { "type": "string", @@ -1794,10 +1564,7 @@ "description": "Initial latitude value for map center." } ], - "default": [ - -106, - 60 - ] + "default": [-106, 60] }, "enableRotation": { "type": "boolean", @@ -1843,16 +1610,10 @@ "description": "Initial map zoom level. Zoom level are define by the basemap zoom levels. Levels between whole numbers are supported to fine tune initial view." } }, - "required": [ - "zoom", - "center" - ] + "required": ["zoom", "center"] }, "TypeValidMapProjectionCodes": { - "enum": [ - 3978, - 3857 - ], + "enum": [3978, 3857], "default": 3978, "description": "Spatial Reference EPSG code supported (https://epsg.io/). We support Web Mercator and Lambert Conical Conform Canada." }, @@ -1860,19 +1621,9 @@ "type": "array", "uniqueItems": true, "items": { - "enum": [ - "zoom", - "fullscreen", - "home", - "location", - "export" - ] + "enum": ["zoom", "fullscreen", "home", "location", "export"] }, - "default": [ - "zoom", - "fullscreen", - "home" - ], + "default": ["zoom", "fullscreen", "home"], "description": "Controls availalbe on the navigation bar.", "minItems": 0 }, @@ -1888,22 +1639,10 @@ "type": "array", "items": { "type": "string", - "enum": [ - "legend", - "layers", - "details", - "data-table", - "time-slider", - "geochart" - ] + "enum": ["legend", "layers", "details", "data-table", "time-slider", "geochart"] }, "minItems": 1, - "default": [ - "legend", - "layers", - "details", - "data-table" - ], + "default": ["legend", "layers", "details", "data-table"], "uniqueItems": true, "description": "Default core tabs of footer bar to use. NOTE: config from packages for time-slider and geochart are in the same loaction as core config (<>-<>.json)." }, @@ -1937,9 +1676,7 @@ "description": "State of footer bar when map is loaded (expanded or collapsed)" } }, - "required": [ - "tabs" - ] + "required": ["tabs"] }, "TypeAppBarProps": { "type": "object", @@ -1953,20 +1690,10 @@ "type": "array", "items": { "type": "string", - "enum": [ - "geolocator", - "export", - "basemap-panel", - "geochart", - "details", - "legend", - "guide" - ] + "enum": ["geolocator", "export", "basemap-panel", "geochart", "details", "legend", "guide"] }, "minItems": 0, - "default": [ - "geolocator" - ], + "default": ["geolocator"], "uniqueItems": true, "description": "Default core tabs of app-bar to use. NOTE: config from packages like geochart are in the same loaction as core config (<>-<>.json)." } @@ -1974,9 +1701,7 @@ "additionalProperties": false } }, - "required": [ - "tabs" - ] + "required": ["tabs"] }, "TypeOverviewMapProps": { "type": "object", @@ -1995,15 +1720,9 @@ "type": "array", "uniqueItems": true, "items": { - "enum": [ - "overview-map", - "north-arrow" - ] + "enum": ["overview-map", "north-arrow"] }, - "default": [ - "overview-map", - "north-arrow" - ], + "default": ["overview-map", "north-arrow"], "description": "Core components to initialize on viewer load. The schema for those are inside this file.", "minItems": 0 }, @@ -2011,9 +1730,7 @@ "type": "array", "uniqueItems": true, "items": { - "enum": [ - "swiper" - ] + "enum": ["swiper"] }, "default": [], "description": "Core map packages to initialize on viewer load. The schema for those are on their own package. NOTE: config from packages are in the same loaction as core config (<>-<>.json).", @@ -2034,9 +1751,7 @@ "description": "The url to the external package configuration setting. The core package will read the configuration and pass it inside the package." } }, - "required": [ - "name" - ] + "required": ["name"] }, "default": [], "description": "List of external packages to initialize on viewer load.", @@ -2064,17 +1779,11 @@ "required": ["geocoreUrl"] }, "TypeDisplayLanguage": { - "enum": [ - "en", - "fr" - ], + "enum": ["en", "fr"], "description": "Display languages supported." }, "TypeLocalizedLanguages": { - "enum": [ - "en", - "fr" - ], + "enum": ["en", "fr"], "description": "ISO 639-1 code indicating the languages supported by the configuration file." }, "TypeListOfLocalizedLanguages": { @@ -2083,17 +1792,12 @@ "items": { "$ref": "#/definitions/TypeLocalizedLanguages" }, - "default": [ - "en", - "fr" - ], + "default": ["en", "fr"], "description": "ISO 639-1 code indicating the languages supported by the configuration file. It will use value(s) provided here to access bilangual configuration nodes. For value(s) provided here, each bilingual configuration node MUST provide a value.", "minItems": 1 }, "TypeValidVersions": { - "enum": [ - "1.0" - ], + "enum": ["1.0"], "description": "The schema version that can be used to validate the configuration file. The schema should enumerate the list of versions accepted by this version of the viewer." }, "TypeMapFeaturesInstance": { @@ -2108,11 +1812,7 @@ "$ref": "#/definitions/TypeMapConfig" }, "theme": { - "enum": [ - "dark", - "light", - "geo.ca" - ], + "enum": ["dark", "light", "geo.ca"], "default": "dark", "description": "Theme style the viewer." }, @@ -2147,10 +1847,7 @@ "$ref": "#/definitions/TypeValidVersions" } }, - "required": [ - "map", - "suportedLanguages" - ] + "required": ["map", "suportedLanguages"] } } -} \ No newline at end of file +} diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/feature-info-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/feature-info-event-processor.ts index f4e0ca43c66..ef9cc9433bb 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/feature-info-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/feature-info-event-processor.ts @@ -33,18 +33,20 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { protected onInitialize(store: GeoviewStoreType): Array<() => void> | void { // Checks for udpated layers in layer order const unsubLayerRemoved = store.subscribe( - (state) => state.mapState.layerOrder, + (state) => state.mapState.orderedLayerInfo, (cur, prev) => { // Log - logger.logTraceCoreStoreSubscription('FEATUREINFO EVENT PROCESSOR - layerOrder', cur); + logger.logTraceCoreStoreSubscription('FEATUREINFO EVENT PROCESSOR - orderedLayerInfo', cur); // For each layer path in the layer data array + const curOrderedLayerPaths = cur.map((layerInfo) => layerInfo.layerPath); + const prevOrderedLayerPaths = prev.map((layerInfo) => layerInfo.layerPath); store .getState() .detailsState.layerDataArray.map((layerInfo) => layerInfo.layerPath) .forEach((layerPath) => { // If it was in the layer data array and is not anymore - if (prev.includes(layerPath) && !cur.includes(layerPath)) { + if (prevOrderedLayerPaths.includes(layerPath) && !curOrderedLayerPaths.includes(layerPath)) { // Remove it from feature info array FeatureInfoEventProcessor.deleteFeatureInfo(store.getState().mapId, layerPath); diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts index e5fbc3f9785..846c0193e8a 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts @@ -34,15 +34,17 @@ export class GeochartEventProcessor extends AbstractEventProcessor { protected onInitialize(store: GeoviewStoreType): Array<() => void> | void { // Checks for udpated layers in layer order const unsubLayerRemoved = store.subscribe( - (state) => state.mapState.layerOrder, + (state) => state.mapState.orderedLayerInfo, (cur, prev) => { // Log - logger.logTraceCoreStoreSubscription('GEOCHART EVENT PROCESSOR - layerOrder', cur); + logger.logTraceCoreStoreSubscription('GEOCHART EVENT PROCESSOR - orderedLayerInfo', cur); // For each chart config keys + const curOrderedLayerPaths = cur.map((layerInfo) => layerInfo.layerPath); + const prevOrderedLayerPaths = prev.map((layerInfo) => layerInfo.layerPath); Object.keys(store.getState().geochartState.geochartChartsConfig).forEach((layerPath: string) => { // If it was in the layerdata array and is not anymore - if (prev.includes(layerPath) && !cur.includes(layerPath)) { + if (prevOrderedLayerPaths.includes(layerPath) && !curOrderedLayerPaths.includes(layerPath)) { // Remove it GeochartEventProcessor.removeGeochartChart(store.getState().mapId, layerPath); diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts index 7950d7fcb93..989bb2107e7 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts @@ -154,17 +154,12 @@ export class LegendEventProcessor extends AbstractEventProcessor { const legendLayerEntry: TypeLegendLayer = { bounds: undefined, layerId: layerConfig.layerId, - order: - api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath) !== -1 && !layerConfig.parentLayerConfig - ? api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath) - : existingEntries.length, // TODO: Why do we have the following line in the store? Do we have to fetch the metadata again since the GeoView layer read and keep them? metadataAccessPath: getLocalizedValue(layerConfig.geoviewLayerConfig?.metadataAccessPath, mapId) || '', layerPath: entryLayerPath, layerStatus: legendResultsSetEntry.layerStatus, layerName: getLocalizedValue(layerConfig.layerName, mapId) || layerConfig.layerId, type: layerConfig.entryType as TypeGeoviewLayerType, - isVisible: layerConfig.initialSettings?.visible ? layerConfig.initialSettings.visible : 'yes', canToggle: legendResultsSetEntry.data?.type !== 'esriImage', opacity: layerConfig.initialSettings?.opacity ? layerConfig.initialSettings.opacity : 1, items: [] as TypeLegendItem[], @@ -180,10 +175,6 @@ export class LegendEventProcessor extends AbstractEventProcessor { const newLegendLayer: TypeLegendLayer = { bounds: undefined, layerId: layerPathNodes[currentLevel], - order: - api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath) !== -1 && !layerConfig.parentLayerConfig - ? api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath) - : existingEntries.length, layerPath: entryLayerPath, layerAttribution: api.maps[mapId].layer.geoviewLayers[layerPathNodes[0]].attributions, // ! Why do we have metadataAccessPath here? Do we need to fetch the metadata again? The GeoView layer fetch them and store them in this.metadata. @@ -193,7 +184,6 @@ export class LegendEventProcessor extends AbstractEventProcessor { querySent: legendResultsSetEntry.querySent, styleConfig: legendResultsSetEntry.data?.styleConfig, type: legendResultsSetEntry.data?.type, - isVisible: layerConfig.initialSettings?.visible || 'yes', canToggle: legendResultsSetEntry.data?.type !== 'esriImage', opacity: layerConfig.initialSettings?.opacity || 1, items: [] as TypeLegendItem[], diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts index 69de269b8bb..120e67251a8 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts @@ -6,8 +6,24 @@ import View, { FitOptions } from 'ol/View'; import { KeyboardPan } from 'ol/interaction'; import { GeoviewStoreType } from '@/core/stores/geoview-store'; -import { api, Coordinate, NORTH_POLE_POSITION, TypeBasemapOptions, TypeBasemapProps, TypeClickMarker, TypeMapFeaturesConfig } from '@/app'; -import { TypeInteraction, TypeMapState, TypeValidMapProjectionCodes } from '@/geo/map/map-schema-types'; +import { + api, + Coordinate, + NORTH_POLE_POSITION, + TypeBasemapOptions, + TypeBasemapProps, + TypeClickMarker, + TypeMapFeaturesConfig, + TypeOrderedLayerInfo, +} from '@/app'; +import { + TypeGeoviewLayerConfig, + TypeInteraction, + TypeLayerEntryConfig, + TypeMapState, + TypeValidMapProjectionCodes, + TypeVisibilityFlags, +} from '@/geo/map/map-schema-types'; import { mapPayload, lngLatPayload, @@ -21,7 +37,6 @@ import { EVENT_NAMES } from '@/api/events/event-types'; import { getGeoViewStore } from '@/core/stores/stores-managers'; import { OL_ZOOM_DURATION, OL_ZOOM_PADDING } from '@/core/utils/constant'; import { AppEventProcessor } from './app-event-processor'; -import { TypeLegendLayer } from '@/core/components/layers/types'; import { logger } from '@/core/utils/logger'; import { AbstractEventProcessor } from '../abstract-event-processor'; @@ -158,27 +173,6 @@ export class MapEventProcessor extends AbstractEventProcessor { ); // #endregion FEATURE SELECTION - const unsubLegendLayers = store.subscribe( - (state) => state.layerState.legendLayers, - (cur) => { - // Log - logger.logTraceCoreStoreSubscription('MAP EVENT PROCESSOR - legendLayers', mapId, cur); - - const orderedLayerPaths = MapEventProcessor.evaluateLayerPathsFromLegendsArray(cur); - const prevLayerOrder = [...store.getState().mapState.layerOrder]; - if (JSON.stringify(prevLayerOrder) !== JSON.stringify(orderedLayerPaths)) - store.getState().mapState.actions.setLayerOrder(orderedLayerPaths); - const orderedVisibleLayers = orderedLayerPaths.filter( - (layerPath) => - store.getState().layerState.actions.getLayer(layerPath)?.isVisible === 'yes' || - store.getState().layerState.actions.getLayer(layerPath)?.isVisible === 'always' - ); - const prevVisibleLayers = [...store.getState().mapState.visibleLayers]; - if (JSON.stringify(prevVisibleLayers) !== JSON.stringify(orderedVisibleLayers)) - store.getState().mapState.actions.setVisibleLayers(orderedVisibleLayers); - } - ); - // Return the array of subscriptions so they can be destroyed later return [ unsubMapHighlightedFeatures, @@ -189,7 +183,6 @@ export class MapEventProcessor extends AbstractEventProcessor { unsubMapSelectedFeatures, unsubMapZoom, unsubMapSingleClick, - unsubLegendLayers, ]; } @@ -389,6 +382,76 @@ export class MapEventProcessor extends AbstractEventProcessor { static zoom(mapId: string, zoom: number): void { this.getMapStateProtected(mapId).actions.setZoom(zoom, OL_ZOOM_DURATION); } + + static getMapIndexFromOrderedLayerInfo(mapId: string, layerPath: string): number { + return this.getMapStateProtected(mapId).actions.getIndexFromOrderedLayerInfo(layerPath); + } + + static getMapVisibilityFromOrderedLayerInfo(mapId: string, layerPath: string): TypeVisibilityFlags { + return this.getMapStateProtected(mapId).actions.getVisibilityFromOrderedLayerInfo(layerPath); + } + + static setMapLayerHoverable(mapId: string, layerPath: string, hoverable: boolean): void { + this.getMapStateProtected(mapId).actions.setHoverable(layerPath, hoverable); + } + + static setMapOrderedLayerInfo(mapId: string, orderedLayerInfo: TypeOrderedLayerInfo[]): void { + this.getMapStateProtected(mapId).actions.setOrderedLayerInfo(orderedLayerInfo); + } + + static setMapLayerQueryable(mapId: string, layerPath: string, queryable: boolean): void { + this.getMapStateProtected(mapId).actions.setQueryable(layerPath, queryable); + } + + static setOrToggleMapVisibilty(mapId: string, layerPath: string, newValue?: TypeVisibilityFlags): void { + this.getMapStateProtected(mapId).actions.setOrToggleLayerVisibility(layerPath, newValue); + } + + /** + * Replace a layer in the orderedLayerInfo array. + * + * @param {string} mapId The ID of the map to add the layer to. + * @param {TypeGeoviewLayerConfig} geoviewLayerConfig The config of the layer to add. + * @return {void} + */ + static replaceOrderedLayerInfo(mapId: string, geoviewLayerConfig: TypeGeoviewLayerConfig | TypeLayerEntryConfig): void { + const { orderedLayerInfo } = this.getMapStateProtected(mapId); + const layerPath = (geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId + ? `${(geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId}/${(geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId}` + : (geoviewLayerConfig as TypeLayerEntryConfig).layerPath; + const index = this.getMapIndexFromOrderedLayerInfo(mapId, layerPath); + const newOrderedLayerInfo = api.maps[mapId].layer.generateArrayOfLayerOrderInfo(geoviewLayerConfig); + orderedLayerInfo.splice(index, 1, ...newOrderedLayerInfo); + this.setMapOrderedLayerInfo(mapId, orderedLayerInfo); + } + + /** + * Add a new layer to the front of the orderedLayerInfo array. + * + * @param {string} mapId The ID of the map to add the layer to. + * @param {TypeGeoviewLayerConfig} geoviewLayerConfig The config of the layer to add. + * @return {void} + */ + static addOrderedLayerInfo(mapId: string, geoviewLayerConfig: TypeGeoviewLayerConfig): void { + const { orderedLayerInfo } = this.getMapStateProtected(mapId); + const newOrderedLayerInfo = api.maps[mapId].layer.generateArrayOfLayerOrderInfo(geoviewLayerConfig); + orderedLayerInfo.unshift(...newOrderedLayerInfo); + this.setMapOrderedLayerInfo(mapId, orderedLayerInfo); + } + + /** + * Remove a layer from the orderedLayerInfo array. + * + * @param {string} mapId The ID of the map to remove the layer from. + * @param {string} layerPath The path of the layer to remove. + * @return {void} + */ + static removeOrderedLayerInfo(mapId: string, layerPath: string): void { + const { orderedLayerInfo } = this.getMapStateProtected(mapId); + const newOrderedLayerInfo = orderedLayerInfo.filter((layerInfo) => !layerInfo.layerPath.startsWith(layerPath)); + this.setMapOrderedLayerInfo(mapId, newOrderedLayerInfo); + } + // #endregion // ********************************************************** @@ -412,21 +475,6 @@ export class MapEventProcessor extends AbstractEventProcessor { api.maps[mapId].basemap.loadDefaultBasemaps(projection, language); } - static evaluateLayerPathsFromLegendsArray(legendsArray: TypeLegendLayer[]): string[] { - const layerPathList: string[] = []; - const maxOrder = Math.max(...legendsArray.map((legendLayer) => legendLayer.order)); - for (let i = 0; i <= maxOrder; i++) { - const nextLayerLegend = legendsArray.filter((layerLegend) => layerLegend.order === i)[0]; - if (nextLayerLegend) { - layerPathList.push(nextLayerLegend.layerPath); - if (nextLayerLegend.children.length) { - layerPathList.push(...this.evaluateLayerPathsFromLegendsArray(nextLayerLegend.children)); - } - } - } - return layerPathList; - } - static setMapKeyboardPanInteractions(mapId: string, panDelta: number): void { const mapElement = api.maps[mapId].map; @@ -556,10 +604,10 @@ export class MapEventProcessor extends AbstractEventProcessor { * @param {string} mapId Id of map to set layer Z indices */ static setLayerZIndices = (mapId: string) => { - const reversedLayers = [...this.getMapStateProtected(mapId).layerOrder].reverse(); - reversedLayers.forEach((layerPath, index) => { - if (api.maps[mapId].layer.registeredLayers[layerPath]?.olLayer) - api.maps[mapId].layer.registeredLayers[layerPath].olLayer?.setZIndex(index + 10); + const reversedLayers = [...this.getMapStateProtected(mapId).orderedLayerInfo].reverse(); + reversedLayers.forEach((orderedLayerInfo, index) => { + if (api.maps[mapId].layer.registeredLayers[orderedLayerInfo.layerPath]?.olLayer) + api.maps[mapId].layer.registeredLayers[orderedLayerInfo.layerPath].olLayer?.setZIndex(index + 10); }); }; diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts index 09550af7c3c..05bb42127d8 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts @@ -26,7 +26,7 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { // Log logger.logTraceCoreAPIEvent('TIME SLIDER EVENT PROCESSOR - EVENT_MAP_LOADED'); - const orderedLayers = store.getState().mapState.layerOrder; + const orderedLayers = store.getState().mapState.orderedLayerInfo.map((info) => info.layerPath); const initialTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers(mapId, orderedLayers); if (initialTimeSliderLayerPaths) { initialTimeSliderLayerPaths.forEach((layerPath) => { @@ -39,14 +39,20 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { ); // Checks for added and removed layers with time dimension - const unsubLayerOrder = store.subscribe( - (state) => state.mapState.layerOrder, + const unsubOrderedLayerInfo = store.subscribe( + (state) => state.mapState.orderedLayerInfo, (cur, prev) => { // Log - logger.logTraceCoreStoreSubscription('TIME SLIDER EVENT PROCESSOR - layerOrder', cur); + logger.logTraceCoreStoreSubscription('TIME SLIDER EVENT PROCESSOR - orderedLayerInfo', cur); - const newTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers(mapId, cur); - const oldTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers(mapId, prev); + const newTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers( + mapId, + cur.map((info) => info.layerPath) + ); + const oldTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers( + mapId, + prev.map((info) => info.layerPath) + ); const addedLayers = newTimeSliderLayerPaths.filter((layerPath) => !oldTimeSliderLayerPaths.includes(layerPath)); const removedLayers = oldTimeSliderLayerPaths.filter((layerPath) => !newTimeSliderLayerPaths.includes(layerPath)); if (addedLayers.length) { @@ -61,7 +67,7 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { ); // Return the array of subscriptions so they can be destroyed later - return [unsubLayerOrder]; + return [unsubOrderedLayerInfo]; } // ********************************************************** diff --git a/packages/geoview-core/src/core/components/data-table/data-panel.tsx b/packages/geoview-core/src/core/components/data-table/data-panel.tsx index fa34c0f8f48..5f39ca09863 100644 --- a/packages/geoview-core/src/core/components/data-table/data-panel.tsx +++ b/packages/geoview-core/src/core/components/data-table/data-panel.tsx @@ -11,7 +11,7 @@ import { useDataTableStoreRowsFiltered, useDataTableStoreSelectedLayerPath, useDetailsStoreLayerDataArray, - useMapVisibleLayers, + useMapOrderedLayerInfo, } from '@/core/stores'; import { ResponsiveGrid, EnlargeButton, CloseButton, LayerList, LayerListEntry, LayerTitle, useFooterPanelHeight } from '../common'; import { logger } from '@/core/utils/logger'; @@ -43,7 +43,7 @@ export function Datapanel() { const isEnlargeDataTable = useDataTableStoreIsEnlargeDataTable(); const mapFiltered = useDataTableStoreMapFilteredRecord(); const rowsFiltered = useDataTableStoreRowsFiltered(); - const visibleLayers = useMapVisibleLayers(); + const orderedLayerInfo = useMapOrderedLayerInfo(); const { setSelectedLayerPath, setIsEnlargeDataTable } = useDataTableStoreActions(); // Custom hook for calculating the height of footer panel @@ -53,10 +53,17 @@ export function Datapanel() { const mappedLayerData = useFeatureFieldInfos(layerData); const orderedLayerData = useMemo(() => { + const visibleLayers = orderedLayerInfo + .map((layerInfo) => { + if (layerInfo.visible !== 'no') return layerInfo.layerPath; + return undefined; + }) + .filter((layerPath) => layerPath !== undefined); + return visibleLayers .map((layerPath) => mappedLayerData.filter((data) => data.layerPath === layerPath)[0]) .filter((layer) => layer !== undefined); - }, [mappedLayerData, visibleLayers]); + }, [mappedLayerData, orderedLayerInfo]); const handleLayerChange = useCallback( (_layer: LayerListEntry) => { diff --git a/packages/geoview-core/src/core/components/data-table/data-table-modal.tsx b/packages/geoview-core/src/core/components/data-table/data-table-modal.tsx index 1f36b8d93b2..4579c247ee5 100644 --- a/packages/geoview-core/src/core/components/data-table/data-table-modal.tsx +++ b/packages/geoview-core/src/core/components/data-table/data-table-modal.tsx @@ -14,7 +14,7 @@ import { CircularProgress, } from '@/ui'; import { useUIActiveFocusItem, useUIStoreActions } from '@/core/stores/store-interface-and-intial-values/ui-state'; -import { useSelectedLayerPath } from '@/core/stores/store-interface-and-intial-values/layer-state'; +import { useLayerSelectedLayerPath } from '@/core/stores/store-interface-and-intial-values/layer-state'; import { FieldInfos } from './data-table'; import { getSxClasses } from './data-table-style'; @@ -44,7 +44,7 @@ export default function DataTableModal(): JSX.Element { // get store function const { closeModal } = useUIStoreActions(); const activeModalId = useUIActiveFocusItem().activeElementId; - const selectedLayer = useSelectedLayerPath(); + const selectedLayer = useLayerSelectedLayerPath(); // TODO:: update when correct data is available, mean time we will be using details store data. const layersData = useDetailsStoreLayerDataArray(); diff --git a/packages/geoview-core/src/core/components/details/details-panel.tsx b/packages/geoview-core/src/core/components/details/details-panel.tsx index 53dfa6bbecb..0403469db5a 100644 --- a/packages/geoview-core/src/core/components/details/details-panel.tsx +++ b/packages/geoview-core/src/core/components/details/details-panel.tsx @@ -14,7 +14,7 @@ import { import { TypeFeatureInfoEntry, TypeLayerData, TypeGeometry, TypeArrayOfFeatureInfoEntries } from '@/api/events/payloads'; import { useMapStoreActions, - useMapVisibleLayers, + useMapOrderedLayerInfo, useDetailsStoreActions, useDetailsStoreCheckedFeatures, useDetailsStoreLayerDataArrayBatch, @@ -48,7 +48,7 @@ export function DetailsPanel({ fullWidth }: DetailsPanelType): JSX.Element { const selectedLayerPath = useDetailsStoreSelectedLayerPath(); const arrayOfLayerDataBatch = useDetailsStoreLayerDataArrayBatch(); const checkedFeatures = useDetailsStoreCheckedFeatures(); - const visibleLayers = useMapVisibleLayers(); + const orderedLayerInfo = useMapOrderedLayerInfo(); const { setSelectedLayerPath, removeCheckedFeature, setLayerDataArrayBatchLayerPathBypass } = useDetailsStoreActions(); const { addSelectedFeature, removeSelectedFeature } = useMapStoreActions(); @@ -122,7 +122,14 @@ export function DetailsPanel({ fullWidth }: DetailsPanelType): JSX.Element { */ const memoLayersList = useMemo(() => { // Log - logger.logTraceUseMemo('DETAILS-PANEL - memoLayersList', visibleLayers, arrayOfLayerDataBatch); + logger.logTraceUseMemo('DETAILS-PANEL - memoLayersList', orderedLayerInfo, arrayOfLayerDataBatch); + + const visibleLayers = orderedLayerInfo + .map((layerInfo) => { + if (layerInfo.visible !== 'no') return layerInfo.layerPath; + return undefined; + }) + .filter((layerPath) => layerPath !== undefined); // Set the layers list return visibleLayers @@ -140,7 +147,7 @@ export function DetailsPanel({ fullWidth }: DetailsPanelType): JSX.Element { tooltip: `${layer!.layerName}, ${getNumFeaturesLabel(layer!)}`, } as LayerListEntry) ); - }, [visibleLayers, arrayOfLayerDataBatch, getNumFeaturesLabel]); + }, [orderedLayerInfo, arrayOfLayerDataBatch, getNumFeaturesLabel]); /** * Memoizes the selected layer for the LayerList component. diff --git a/packages/geoview-core/src/core/components/layers/hooks/helpers.ts b/packages/geoview-core/src/core/components/layers/hooks/helpers.ts index 8c947dbbbf3..165edb9c154 100644 --- a/packages/geoview-core/src/core/components/layers/hooks/helpers.ts +++ b/packages/geoview-core/src/core/components/layers/hooks/helpers.ts @@ -66,11 +66,9 @@ export function useLegendHelpers() { layerId: 'test_testLayerId', layerPath: 'testLayerPath', layerName: 'TEST--TestLayer1', - order: 20, type: 'GeoJSON', layerStatus: 'loaded', layerPhase: 'processed', - isVisible: 'yes', querySent: true, children: [], items: layerItems, @@ -80,11 +78,9 @@ export function useLegendHelpers() { layerId: 'test_geojsonLYR5', layerPath: 'geojsonLYR5', layerName: 'TEST--Layer with groups', - order: 21, type: 'GeoJSON', layerStatus: 'loaded', layerPhase: 'processed', - isVisible: 'yes', querySent: true, children: [], items: [], @@ -95,10 +91,8 @@ export function useLegendHelpers() { layerPath: 'Chris Sample Parent1', layerName: 'TEST--chrisparentlayer1', type: 'GeoJSON', - order: 22, layerStatus: 'loaded', layerPhase: 'processed', - isVisible: 'yes', querySent: true, children: [ { @@ -106,11 +100,9 @@ export function useLegendHelpers() { layerId: 'test_chrisChildLayer1', layerPath: 'ChrisSampleC3', layerName: 'TEST--chrisparentchild1', - order: 2, type: 'GeoJSON', layerStatus: 'loaded', layerPhase: 'processed', - isVisible: 'yes', querySent: true, children: [ { @@ -119,10 +111,8 @@ export function useLegendHelpers() { layerPath: 'Gran ChildChidl2', layerName: 'TEST--chris parent child2', type: 'GeoJSON', - order: 1, layerStatus: 'error', layerPhase: 'processed', - isVisible: 'no', querySent: true, children: [], items: layerItems, @@ -133,10 +123,8 @@ export function useLegendHelpers() { layerPath: 'Gran ChildChidl555', layerName: 'TEST--chris parent child25555', type: 'GeoJSON', - order: 2, layerStatus: 'processing', layerPhase: 'processed', - isVisible: 'no', querySent: true, children: [], items: layerItems, @@ -147,10 +135,8 @@ export function useLegendHelpers() { layerPath: 'Grand Child Chidl3', layerName: 'TEST--chris parent child3', type: 'GeoJSON', - order: 3, layerStatus: 'newInstance', layerPhase: 'processed', - isVisible: 'yes', querySent: true, children: [], items: layerItems, @@ -164,10 +150,8 @@ export function useLegendHelpers() { layerPath: 'Chris Sample Chidl2', layerName: 'TEST--chirslyerss', type: 'GeoJSON', - order: 24, layerStatus: 'loaded', layerPhase: 'processed', - isVisible: 'no', querySent: true, children: [], items: layerItems, @@ -178,10 +162,8 @@ export function useLegendHelpers() { layerPath: 'Chris Sample Chidl3', layerName: 'TEST--chris-child32edd', type: 'GeoJSON', - order: 25, layerStatus: 'loaded', layerPhase: 'processed', - isVisible: 'yes', querySent: true, children: [], items: layerItems, @@ -191,7 +173,7 @@ export function useLegendHelpers() { }, ]; - keys.forEach((i, index) => { + keys.forEach((i) => { const setData = legendInfo[i]; const items: TypeLegendItem[] = []; const legendData = setData.data?.legend ? (setData.data.legend as TypeVectorLayerStyles) : undefined; @@ -216,10 +198,8 @@ export function useLegendHelpers() { layerPath: `test_${setData.data?.layerPath ?? generateId()}`, layerName: `TEST---${setData.data?.layerName?.en ?? 'Uknown Laer name'}`, type: setData.data?.type ?? 'imageStatic', - order: 27 + index, layerStatus: setData.layerStatus, querySent: setData.querySent, - isVisible: 'yes', children: [], items, }; diff --git a/packages/geoview-core/src/core/components/layers/layers-panel.tsx b/packages/geoview-core/src/core/components/layers/layers-panel.tsx index d59df9bffc8..497513093cd 100644 --- a/packages/geoview-core/src/core/components/layers/layers-panel.tsx +++ b/packages/geoview-core/src/core/components/layers/layers-panel.tsx @@ -4,7 +4,7 @@ import { useTheme } from '@mui/material/styles'; import { CloseButton, ResponsiveGrid, useFooterPanelHeight } from '../common'; import { Box, DeleteOutlineIcon, IconButton, Paper } from '@/ui'; import { getSxClasses } from './layers-style'; -import { useLayersDisplayState, useSelectedLayer } from '@/core/stores/store-interface-and-intial-values/layer-state'; +import { useLayerDisplayState, useSelectedLayer } from '@/core/stores/store-interface-and-intial-values/layer-state'; import { LayersToolbar } from './layers-toolbar'; import { LayerDetails } from './right-panel/layer-details'; import { LeftPanel } from './left-panel/left-panel'; @@ -22,7 +22,7 @@ export function LayersPanel() { const [isLayersListPanelVisible, setIsLayersListPanelVisible] = useState(false); const selectedLayer = useSelectedLayer(); // get store value - const displayState = useLayersDisplayState(); + const displayState = useLayerDisplayState(); /* // Using helpers diff --git a/packages/geoview-core/src/core/components/layers/layers-toolbar.tsx b/packages/geoview-core/src/core/components/layers/layers-toolbar.tsx index 961b1bd8be0..b1affeaa73c 100644 --- a/packages/geoview-core/src/core/components/layers/layers-toolbar.tsx +++ b/packages/geoview-core/src/core/components/layers/layers-toolbar.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next'; import { Button } from '@mui/material'; import { useEffect, useState } from 'react'; import { Box, AddCircleOutlineIcon, ButtonGroup, DeleteOutlineIcon, HandleIcon, Tooltip, VisibilityOutlinedIcon } from '@/ui'; -import { useLayerStoreActions, useLayersDisplayState } from '@/core/stores/store-interface-and-intial-values/layer-state'; +import { useLayerStoreActions, useLayerDisplayState } from '@/core/stores/store-interface-and-intial-values/layer-state'; import { TypeLayersViewDisplayState } from './types'; import { logger } from '@/core/utils/logger'; @@ -25,7 +25,7 @@ function ResponsiveButton(props: ResponsiveButtonProps): JSX.Element { const [screenWidth, setScreenWidth] = useState(window.innerWidth); // access store - const displayState = useLayersDisplayState(); + const displayState = useLayerDisplayState(); const { setDisplayState } = useLayerStoreActions(); const handleSetDisplayState = (dispState: TypeLayersViewDisplayState): void => { diff --git a/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx b/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx index 8c1d191daf0..6e89af9ff4e 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx @@ -35,10 +35,11 @@ import { TypeCSVLayerConfig, TypeCsvLayerEntryConfig, CSV as CsvGeoviewClass } f import { ButtonPropsLayerPanel, SelectChangeEvent, TypeJsonArray, TypeJsonObject } from '@/core/types/global-types'; import { useGeoViewMapId } from '@/core/stores/geoview-store'; import { createLocalizedString } from '@/core/utils/utilities'; -import { useLayerStoreActions, useLayersList } from '@/core/stores/store-interface-and-intial-values/layer-state'; +import { useLayerStoreActions, useLayerLegendLayers } from '@/core/stores/store-interface-and-intial-values/layer-state'; import { Cast, Config, api } from '@/app'; import { logger } from '@/core/utils/logger'; import { EsriImage, TypeEsriImageLayerConfig } from '@/geo/layer/geoview-layers/raster/esri-image'; +import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor'; type EsriOptions = { err: string; @@ -70,7 +71,7 @@ export function AddNewLayer(): JSX.Element { // get values from store const mapId = useGeoViewMapId(); - const layersList = useLayersList(); + const layersList = useLayerLegendLayers(); const { setDisplayState, setSelectedLayerPath } = useLayerStoreActions(); const isMultiple = () => hasMetadata && (layerType === ESRI_DYNAMIC || layerType === WFS || layerType === WMS || layerType === GEOJSON); @@ -829,6 +830,7 @@ export function AddNewLayer(): JSX.Element { if (layerList.length > 1) { (layerList as TypeListOfGeoviewLayerConfig).forEach((geoviewLayerConfig) => { api.maps[mapId].layer.addGeoviewLayer(geoviewLayerConfig); + MapEventProcessor.addOrderedLayerInfo(mapId, geoviewLayerConfig); }); } else if (layerEntries.length > 0) { (layerEntries as TypeListOfGeoviewLayerConfig).forEach((geoviewLayerConfig) => { @@ -853,6 +855,7 @@ export function AddNewLayer(): JSX.Element { if (geoviewLayerInstance.olLayers) { logger.logDebug('Before addToMap', geoviewLayerInstance); api.maps[mapId].layer.addToMap(geoviewLayerInstance); + MapEventProcessor.addOrderedLayerInfo(mapId, geoviewLayerConfig); logger.logDebug('After addToMap', geoviewLayerInstance); } else emitErrorNotLoaded(); } diff --git a/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx b/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx index 7a258aa9937..dc41b6917be 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { Box, CircularProgressBase, DeleteOutlineIcon, IconButton, UndoIcon } from '@/ui'; import { TypeLegendLayer } from '../types'; -import { useLayerStoreActions } from '@/core/stores/store-interface-and-intial-values/layer-state'; +import { useLayerStoreActions, useMapStoreActions } from '@/core/stores'; import { logger } from '@/core/utils/logger'; interface DeleteUndoButtonProps { @@ -51,15 +51,16 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { const [inUndoState, setInUndoState] = useState(false); // get store actions - const { deleteLayer, toggleLayerVisibility } = useLayerStoreActions(); + const { deleteLayer } = useLayerStoreActions(); + const { getVisibilityFromOrderedLayerInfo, getRemovableFromOrderedLayerInfo, setOrToggleLayerVisibility } = useMapStoreActions(); const handleDeleteClick = () => { - if (layer.isVisible !== 'no') toggleLayerVisibility(layer.layerPath); + if (getVisibilityFromOrderedLayerInfo(layer.layerPath) !== 'no') setOrToggleLayerVisibility(layer.layerPath); setInUndoState(true); }; const handleUndoClick = () => { - toggleLayerVisibility(layer.layerPath); + setOrToggleLayerVisibility(layer.layerPath); setInUndoState(false); }; @@ -85,12 +86,19 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { return undefined; }, [inUndoState]); - if (!inUndoState) { + if (!inUndoState && getRemovableFromOrderedLayerInfo(layer.layerPath)) { return ( ); } + if (!inUndoState) { + return ( + + + + ); + } return ; } diff --git a/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx b/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx index 744c98c7e8c..0d13a7dda28 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx @@ -4,9 +4,9 @@ import { DragDropContext, Droppable, Draggable, DropResult, DraggingStyle, NotDr import { SingleLayer } from './single-layer'; import { getSxClasses } from './left-panel-styles'; import { Box } from '@/ui'; -import { TypeLegendLayer } from '../types'; -import { useLayerStoreActions, useLayersDisplayState } from '@/core/stores/'; +import { useMapStoreActions, useLayerDisplayState } from '@/core/stores/'; import { logger } from '@/core/utils/logger'; +import { TypeLegendLayer } from '../types'; interface LayerListProps { depth: number; @@ -22,19 +22,21 @@ export function LayersList({ layersList, setIsLayersListPanelVisible, parentLaye const theme = useTheme(); const sxClasses = getSxClasses(theme); - const displayState = useLayersDisplayState(); - const { reorderLayer } = useLayerStoreActions(); // get store actions + const displayState = useLayerDisplayState(); + const { getIndexFromOrderedLayerInfo, reorderLayer } = useMapStoreActions(); const isDragEnabled = displayState === 'order'; - const sortedLayers = layersList.sort((a, b) => (a.order > b.order ? 1 : -1)); + const sortedLayers = layersList.sort((a, b) => + getIndexFromOrderedLayerInfo(a.layerPath) > getIndexFromOrderedLayerInfo(b.layerPath) ? 1 : -1 + ); const onDragEnd = (result: DropResult) => { // dropped outside the list if (!result.destination) { return; } - reorderLayer(result.source.index, result.destination.index, result.draggableId); + reorderLayer(result.draggableId, result.destination.index - result.source.index); }; const textToSlug = (text: string): string => { @@ -82,7 +84,7 @@ export function LayersList({ layersList, setIsLayersListPanelVisible, parentLaye isDragDisabled={!isDragEnabled} key={textToSlug(`${index}${details.layerPath}`)} draggableId={details.layerPath} - index={details.order} + index={index} > {(provided, snapshot) => (
>; @@ -13,13 +14,28 @@ export function LeftPanel({ setIsLayersListPanelVisible }: LeftPanelProps): JSX. logger.logTraceRender('components/layers/left-panel/left-panel'); // get from the store - const legendLayers = useLayersList(); - const displayState = useLayersDisplayState(); + const legendLayers = useLayerLegendLayers(); + const displayState = useLayerDisplayState(); + const orderedLayerInfo = useMapOrderedLayerInfo(); + const { getIndexFromOrderedLayerInfo } = useMapStoreActions(); + const [orderedLegendLayers, setOrderedLegendLayers] = useState([]); + + useEffect(() => { + const sortedLayers = legendLayers.sort((a, b) => + getIndexFromOrderedLayerInfo(a.layerPath) > getIndexFromOrderedLayerInfo(b.layerPath) ? 1 : -1 + ); + setOrderedLegendLayers(sortedLayers); + }, [orderedLayerInfo, legendLayers, getIndexFromOrderedLayerInfo]); if (displayState === 'add') { return ; } return ( - + ); } diff --git a/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx b/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx index 58928b98f75..8b222582330 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx @@ -21,10 +21,11 @@ import { import { TypeLegendLayer } from '../types'; import { useLayerStoreActions, - useLayersDisplayState, - useSelectedLayerPath, + useLayerDisplayState, + useLayerSelectedLayerPath, } from '@/core/stores/store-interface-and-intial-values/layer-state'; import { useDataTableStoreMapFilteredRecord } from '@/core/stores/store-interface-and-intial-values/data-table-state'; +import { useMapStoreActions } from '@/core/stores/store-interface-and-intial-values/map-state'; import { DeleteUndoButton } from './delete-undo-button'; import { LayersList } from './layers-list'; import { LayerIcon } from '../layer-icon'; @@ -43,10 +44,11 @@ export function SingleLayer({ isDragging, depth, layer, setIsLayersListPanelVisi const { t } = useTranslation(); - const { toggleLayerVisibility, setSelectedLayerPath } = useLayerStoreActions(); // get store actions - - const selectedLayerPath = useSelectedLayerPath(); // get store value - const displayState = useLayersDisplayState(); + // Get store states + const { setSelectedLayerPath } = useLayerStoreActions(); + const { getVisibilityFromOrderedLayerInfo, setOrToggleLayerVisibility } = useMapStoreActions(); + const selectedLayerPath = useLayerSelectedLayerPath(); + const displayState = useLayerDisplayState(); const mapFiltered = useDataTableStoreMapFilteredRecord(); // if any of the chiild layers is selected return true @@ -69,7 +71,7 @@ export function SingleLayer({ isDragging, depth, layer, setIsLayersListPanelVisi // returns true if any of the layer children or items has visibility of 'always' const layerHasAlwaysVisible = (startingLayer: TypeLegendLayer): boolean => { - if (startingLayer.isVisible === 'always') { + if (getVisibilityFromOrderedLayerInfo(startingLayer.layerPath) === 'always') { return true; } let itemsHasAlways = false; @@ -138,7 +140,7 @@ export function SingleLayer({ isDragging, depth, layer, setIsLayersListPanelVisi }; const handleToggleVisibility = () => { - toggleLayerVisibility(layer.layerPath); + setOrToggleLayerVisibility(layer.layerPath); }; const handleReloadLayer = () => { @@ -194,7 +196,7 @@ export function SingleLayer({ isDragging, depth, layer, setIsLayersListPanelVisi className="style1" > {(() => { - if (layer.isVisible === 'no') return ; + if (getVisibilityFromOrderedLayerInfo(layer.layerPath) === 'no') return ; return ; })()} diff --git a/packages/geoview-core/src/core/components/layers/right-panel/layer-details.tsx b/packages/geoview-core/src/core/components/layers/right-panel/layer-details.tsx index 10bd5808331..794dc814526 100644 --- a/packages/geoview-core/src/core/components/layers/right-panel/layer-details.tsx +++ b/packages/geoview-core/src/core/components/layers/right-panel/layer-details.tsx @@ -23,8 +23,7 @@ import { ListItem, List, } from '@/ui'; -import { useLayerHighlightedLayer, useLayerStoreActions } from '@/core/stores/store-interface-and-intial-values/layer-state'; -import { useUIStoreActions } from '@/core/stores/store-interface-and-intial-values/ui-state'; +import { useLayerHighlightedLayer, useLayerStoreActions, useUIStoreActions, useMapStoreActions } from '@/core/stores'; import { generateId } from '@/core/utils/utilities'; import { LayerIcon } from '../layer-icon'; import { LayerOpacityControl } from './layer-opacity-control/layer-opacity-control'; @@ -49,6 +48,7 @@ export function LayerDetails(props: LayerDetailsProps): JSX.Element { const highlightedLayer = useLayerHighlightedLayer(); const { setAllItemsVisibility, toggleItemVisibility, setHighlightLayer, zoomToLayerExtent, getLayerBounds } = useLayerStoreActions(); const { openModal } = useUIStoreActions(); + const { getVisibilityFromOrderedLayerInfo } = useMapStoreActions(); const handleZoomTo = () => { zoomToLayerExtent(layerDetails.layerPath); @@ -94,7 +94,7 @@ export function LayerDetails(props: LayerDetailsProps): JSX.Element { ) { return null; } - if (item.isVisible === 'always' || layerDetails.isVisible === 'always' || !layerDetails.canToggle) { + if (item.isVisible === 'always' || getVisibilityFromOrderedLayerInfo(layerDetails.layerPath) === 'always' || !layerDetails.canToggle) { return ( {' '} @@ -112,7 +112,7 @@ export function LayerDetails(props: LayerDetailsProps): JSX.Element { function renderHeaderCheckbox() { const containsDisabled = _.some(layerDetails.items, (i) => i.isVisible === 'always'); - if (layerDetails.isVisible === 'always' || !layerDetails.canToggle || containsDisabled) { + if (getVisibilityFromOrderedLayerInfo(layerDetails.layerPath) === 'always' || !layerDetails.canToggle || containsDisabled) { return ( {' '} diff --git a/packages/geoview-core/src/core/components/layers/types.ts b/packages/geoview-core/src/core/components/layers/types.ts index aa4398fdbe5..0b1078d1055 100644 --- a/packages/geoview-core/src/core/components/layers/types.ts +++ b/packages/geoview-core/src/core/components/layers/types.ts @@ -30,15 +30,12 @@ export interface TypeLegendLayer { layerPath: string; layerAttribution?: string[]; metadataAccessPath?: string; - order: number; // useful for ordering layers layerName: string; type?: TypeGeoviewLayerType; styleConfig?: TypeStyleConfig | null; layerStatus?: TypeLayerStatus; layerPhase?: string; querySent?: boolean; - - isVisible: TypeVisibilityFlags; // is layer is visible canToggle?: boolean; // can sublayer visibility be toggled icons?: TypeLegendLayerIcons; @@ -49,7 +46,5 @@ export interface TypeLegendLayer { opacity?: number; opacityFromParent?: number; zoom?: number; - - isRemovable?: boolean; canSetOpacity?: boolean; } diff --git a/packages/geoview-core/src/core/components/legend/legend-layer.tsx b/packages/geoview-core/src/core/components/legend/legend-layer.tsx index 22d370859c1..5c8d0240d6c 100644 --- a/packages/geoview-core/src/core/components/legend/legend-layer.tsx +++ b/packages/geoview-core/src/core/components/legend/legend-layer.tsx @@ -15,6 +15,7 @@ import { KeyboardArrowUpIcon, } from '@/ui'; import { TypeLegendLayer } from '@/core/components/layers/types'; +import { useMapStoreActions } from '@/core/stores/'; import { getSxClasses } from './legend-styles'; import { LayerIcon } from '../layers/layer-icon'; import { logger } from '@/core/utils/logger'; @@ -34,9 +35,12 @@ export function LegendLayer(props: LegendLayerProps): JSX.Element { const sxClasses = getSxClasses(theme); const [isGroupOpen, setGroupOpen] = useState(true); + const { getVisibilityFromOrderedLayerInfo } = useMapStoreActions(); const getLayerChildren = () => { - return layer.children?.filter((c) => c.isVisible !== 'no' && ['processed', 'loaded'].includes(c.layerStatus ?? '')); + return layer.children?.filter( + (c) => getVisibilityFromOrderedLayerInfo(c.layerPath) !== 'no' && ['processed', 'loaded'].includes(c.layerStatus ?? '') + ); }; /** @@ -68,7 +72,7 @@ export function LegendLayer(props: LegendLayerProps): JSX.Element { return ( {layer.children - .filter((d) => d.isVisible !== 'no' && !['error', 'processing'].includes(d.layerStatus ?? '')) + .filter((d) => getVisibilityFromOrderedLayerInfo(d.layerPath) !== 'no' && !['error', 'processing'].includes(d.layerStatus ?? '')) .map((item) => ( ))} diff --git a/packages/geoview-core/src/core/components/legend/legend.tsx b/packages/geoview-core/src/core/components/legend/legend.tsx index 824778265c8..9e7897849da 100644 --- a/packages/geoview-core/src/core/components/legend/legend.tsx +++ b/packages/geoview-core/src/core/components/legend/legend.tsx @@ -2,7 +2,7 @@ import { useTheme } from '@mui/material'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Box, Paper, Typography } from '@/ui'; -import { useMapVisibleLayers, useLayerStoreActions } from '@/core/stores/'; +import { useLayerLegendLayers, useMapOrderedLayerInfo, useLayerStoreActions } from '@/core/stores/'; import { logger } from '@/core/utils/logger'; import { getSxClasses } from './legend-styles'; @@ -28,7 +28,8 @@ export function Legend({ fullWidth }: LegendType): JSX.Element { const [formattedLegendLayerList, setFormattedLegendLayersList] = useState([]); // store state - const visibleLayers = useMapVisibleLayers(); + const orderedLayerInfo = useMapOrderedLayerInfo(); + const layersList = useLayerLegendLayers(); const { getLayer } = useLayerStoreActions(); // Custom hook for calculating the height of footer panel @@ -72,16 +73,24 @@ export function Legend({ fullWidth }: LegendType): JSX.Element { useEffect(() => { // Log - logger.logTraceUseEffect('LEGEND - visiblelayers', visibleLayers.length, visibleLayers); + logger.logTraceUseEffect('LEGEND - orderedLayerInfo', orderedLayerInfo.length, orderedLayerInfo); + + const visibleLayers = orderedLayerInfo + .map((layerInfo) => { + if (layerInfo.visible !== 'no') return layerInfo.layerPath; + return undefined; + }) + .filter((layerPath) => layerPath !== undefined); // Loop on the visible layers to retrieve the valid TypeLegendLayer objects const parentPaths: string[] = []; + const layers = visibleLayers .map((layerPath) => { - const pathStart = layerPath.split('/')[0]; + const pathStart = layerPath!.split('/')[0]; if (!parentPaths.includes(pathStart)) { parentPaths.push(pathStart); - return getLayer(layerPath); + return getLayer(layerPath!); } return undefined; }) @@ -91,7 +100,7 @@ export function Legend({ fullWidth }: LegendType): JSX.Element { updateLegendLayerListByWindowSize(layers); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [getLayer, visibleLayers]); + }, [orderedLayerInfo, layersList]); useEffect(() => { // Log diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts index 3ae53a368d7..1569edc2c89 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts @@ -20,12 +20,11 @@ import { MapEventProcessor } from '@/api/event-processors/event-processor-childr export interface ILayerState { highlightedLayer: string; - selectedItem?: TypeLegendLayer; - selectedIsVisible: boolean; selectedLayer: TypeLegendLayer; selectedLayerPath: string | undefined | null; legendLayers: TypeLegendLayer[]; displayState: TypeLayersViewDisplayState; + actions: { setLegendLayers: (legendLayers: TypeLegendLayer[]) => void; getLayer: (layerPath: string) => TypeLegendLayer | undefined; @@ -33,9 +32,7 @@ export interface ILayerState { setDisplayState: (newDisplayState: TypeLayersViewDisplayState) => void; setHighlightLayer: (layerPath: string) => void; setLayerOpacity: (layerPath: string, opacity: number) => void; - reorderLayer: (startIndex: number, endIndex: number, layerPath: string) => void; setSelectedLayerPath: (layerPath: string) => void; - toggleLayerVisibility: (layerPath: string) => void; toggleItemVisibility: (layerPath: string, geometryType: TypeStyleGeometry, itemName: string) => void; setAllItemsVisibility: (layerPath: string, visibility: 'yes' | 'no') => void; deleteLayer: (layerPath: string) => void; @@ -46,7 +43,6 @@ export interface ILayerState { export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILayerState { const init = { highlightedLayer: '', - selectedIsVisible: false, legendLayers: [] as TypeLegendLayer[], selectedLayerPath: null, displayState: 'view', @@ -133,50 +129,40 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay }, }); }, - toggleLayerVisibility: (layerPath: string) => { - const curLayers = get().layerState.legendLayers; - const layer = findLayerByPath(curLayers, layerPath); - setVisibilityInLayerAndItems(layer as TypeLegendLayer, layer?.isVisible === 'no' ? 'yes' : 'no'); - // TODO: keep reference to geoview map instance in the store or keep accessing with api - discussion - //! may not work with group items ... see if Yves work will make this simplier - api.maps[get().mapId].layer.geoviewLayer(layerPath).setVisible(layer?.isVisible !== 'no', layerPath); - - // now update store - set({ - layerState: { - ...get().layerState, - legendLayers: [...curLayers], - }, - }); - }, toggleItemVisibility: (layerPath: string, geometryType: TypeStyleGeometry, itemName: string) => { const curLayers = get().layerState.legendLayers; const registeredLayer = api.maps[get().mapId].layer.registeredLayers[layerPath] as TypeVectorLayerEntryConfig; const layer = findLayerByPath(curLayers, layerPath); if (layer) { - _.each(layer.items, (item, index) => { + _.each(layer.items, (item) => { if (item.geometryType === geometryType && item.name === itemName && item.isVisible !== 'always') { item.isVisible = item.isVisible === 'no' ? 'yes' : 'no'; // eslint-disable-line no-param-reassign - if (item.isVisible === 'yes' && layer.isVisible === 'no') { - layer.isVisible = 'yes'; + if (item.isVisible === 'yes' && MapEventProcessor.getMapVisibilityFromOrderedLayerInfo(get().mapId, layerPath) === 'no') { + MapEventProcessor.setOrToggleMapVisibilty(get().mapId, layerPath, 'yes'); } // assign value to registered layer. This is use by applyFilter function to set visibility // TODO: check if we need to refactor to centralize attribute setting.... // TODO: know issue when we toggle a default visibility item https://github.com/Canadian-Geospatial-Platform/geoview/issues/1564 if (registeredLayer.style![geometryType]?.styleType === 'classBreaks') { - (registeredLayer.style![geometryType]! as TypeClassBreakStyleConfig).classBreakStyleInfo[index].visible = item.isVisible; + const geometryStyleConfig = registeredLayer.style![geometryType]! as TypeClassBreakStyleConfig; + const classBreakStyleInfo = geometryStyleConfig.classBreakStyleInfo.find((styleInfo) => styleInfo.label === itemName); + if (classBreakStyleInfo) classBreakStyleInfo.visible = item.isVisible; + else geometryStyleConfig.defaultVisible = item.isVisible; } else if (registeredLayer.style![geometryType]?.styleType === 'uniqueValue') { - (registeredLayer.style![geometryType]! as TypeUniqueValueStyleConfig).uniqueValueStyleInfo[index].visible = item.isVisible; + const geometryStyleConfig = registeredLayer.style![geometryType]! as TypeUniqueValueStyleConfig; + const uniqueStyleInfo = geometryStyleConfig.uniqueValueStyleInfo.find((styleInfo) => styleInfo.label === itemName); + if (uniqueStyleInfo) uniqueStyleInfo.visible = item.isVisible; + else geometryStyleConfig.defaultVisible = item.isVisible; } } }); // 'always' is neither 'yes', nor 'no'. const allItemsUnchecked = _.every(layer.items, (i) => ['no', 'always'].includes(i.isVisible!)); - if (allItemsUnchecked && layer.isVisible !== 'always') { - layer.isVisible = 'no'; + if (allItemsUnchecked) { + MapEventProcessor.setOrToggleMapVisibilty(get().mapId, layerPath, 'no'); } // apply filter to layer @@ -190,30 +176,40 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay }); }, setAllItemsVisibility: (layerPath: string, visibility: 'yes' | 'no') => { + MapEventProcessor.setOrToggleMapVisibilty(get().mapId, layerPath, visibility); const curLayers = get().layerState.legendLayers; const registeredLayer = api.maps[get().mapId].layer.registeredLayers[layerPath] as TypeVectorLayerEntryConfig; const layer = findLayerByPath(curLayers, layerPath); if (layer) { - _.each(layer.items, (item, index) => { - if (item.isVisible !== 'always') { - item.isVisible = visibility; // eslint-disable-line no-param-reassign - - // assign value to registered layer. This is use by applyFilter function to set visibility - // TODO: check if we need to refactor to centralize attribute setting.... - if (registeredLayer.style && registeredLayer.style![item.geometryType]?.styleType === 'classBreaks') { - (registeredLayer.style![item.geometryType]! as TypeClassBreakStyleConfig).classBreakStyleInfo[index].visible = - item.isVisible; - } else if (registeredLayer.style![item.geometryType]?.styleType === 'uniqueValue') { - (registeredLayer.style![item.geometryType]! as TypeUniqueValueStyleConfig).uniqueValueStyleInfo[index].visible = - item.isVisible; - } - } + _.each(layer.items, (item) => { + // eslint-disable-next-line no-param-reassign + if (item.isVisible !== 'always') item.isVisible = visibility; }); - // TODO: this visibility flag for the store should we use to show/hide icon on the layer item list (if always in child, no toggle visibility) - // This should be set at init of layer - if (layer.isVisible !== 'always') { - layer.isVisible = visibility; + // assign value to registered layer. This is use by applyFilter function to set visibility + // TODO: check if we need to refactor to centralize attribute setting.... + if (registeredLayer.style) { + ['Point', 'LineString', 'Polygon'].forEach((geometry) => { + if (registeredLayer.style![geometry as TypeStyleGeometry]) { + if (registeredLayer.style![geometry as TypeStyleGeometry]?.styleType === 'classBreaks') { + const geometryStyleConfig = registeredLayer.style![geometry as TypeStyleGeometry]! as TypeClassBreakStyleConfig; + if (geometryStyleConfig.defaultVisible && geometryStyleConfig.defaultVisible !== 'always') + geometryStyleConfig.defaultVisible = visibility; + geometryStyleConfig.classBreakStyleInfo.forEach((styleInfo) => { + // eslint-disable-next-line no-param-reassign + if (styleInfo.visible !== 'always') styleInfo.visible = visibility; + }); + } else if (registeredLayer.style![geometry as TypeStyleGeometry]?.styleType === 'uniqueValue') { + const geometryStyleConfig = registeredLayer.style![geometry as TypeStyleGeometry]! as TypeUniqueValueStyleConfig; + if (geometryStyleConfig.defaultVisible && geometryStyleConfig.defaultVisible !== 'always') + geometryStyleConfig.defaultVisible = visibility; + geometryStyleConfig.uniqueValueStyleInfo.forEach((styleInfo) => { + // eslint-disable-next-line no-param-reassign + if (styleInfo.visible !== 'always') styleInfo.visible = visibility; + }); + } + } + }); } } @@ -228,7 +224,7 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay // ! try to make reusable store actions.... // ! we can have always item.... we cannot set visibility so if present we will need to trap. Need more use case // ! create a function setItemVisibility called with layer path and this function set the registered layer (from store values) then apply the filter. - (api.maps[get().mapId].layer.geoviewLayer(layerPath) as AbstractGeoViewVector).applyViewFilter(layerPath); + (api.maps[get().mapId].layer.geoviewLayer(layerPath) as AbstractGeoViewVector).applyViewFilter(''); }, deleteLayer: (layerPath: string) => { const curLayers = get().layerState.legendLayers; @@ -249,16 +245,6 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay const { bounds } = layer as TypeLegendLayer; if (bounds) MapEventProcessor.zoomToExtent(get().mapId, bounds, options); }, - reorderLayer: (startIndex: number, endIndex: number, layerPath: string) => { - const curLayers = get().layerState.legendLayers; - const reorderedLayers = reorderSingleLayer(curLayers, startIndex, endIndex, layerPath); - set({ - layerState: { - ...get().layerState, - legendLayers: [...reorderedLayers], - }, - }); - }, }, } as ILayerState; @@ -267,24 +253,6 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay // private functions -// function set visibility in layer and its items -function setVisibilityInLayerAndItems(layer: TypeLegendLayer, visibility: 'yes' | 'no') { - if (layer.isVisible === 'always') { - return; - } - _.set(layer, 'isVisible', visibility); - _.each(layer.items, (item) => { - if (item.isVisible !== 'always') { - _.set(item, 'isVisible', visibility); - } - }); - if (layer.children && layer.children.length > 0) { - _.each(layer.children, (child) => { - setVisibilityInLayerAndItems(child, visibility); - }); - } -} - function setOpacityInLayerAndChildren(layer: TypeLegendLayer, opacity: number, mapId: string, isChild = false) { _.set(layer, 'opacity', opacity); api.maps[mapId].layer.geoviewLayer(layer.layerPath).setOpacity(opacity, layer.layerPath); @@ -327,49 +295,14 @@ function deleteSingleLayer(layers: TypeLegendLayer[], layerPath: string) { } } -function reorderSingleLayer(collection: TypeLegendLayer[], startIndex: number, endIndex: number, layerPath: string): TypeLegendLayer[] { - let layerFound = false; - - function findLayerAndSortIt(startingCollection: TypeLegendLayer[]) { - if (layerFound) { - return; - } - layerFound = startingCollection.find((lyr) => lyr.layerPath === layerPath) !== undefined; - - if (layerFound) { - const [removed] = startingCollection.splice(startIndex, 1); - startingCollection.splice(endIndex, 0, removed); - - /* eslint-disable no-param-reassign */ - for (let i = 0; i < startingCollection.length; i++) { - startingCollection[i].order = i; - } - - return; - } - - // if not found at this level, lets find it in children - for (let i = 0; i < startingCollection.length; i++) { - if (startingCollection[i].children.length > 0) { - findLayerAndSortIt(startingCollection[i].children); - } - } - } - - findLayerAndSortIt(collection); - - return collection; -} - // ********************************************************** // Layer state selectors // ********************************************************** -export const useLayerBounds = () => useStore(useGeoViewStore(), (state) => state.layerState.legendLayers); export const useLayerHighlightedLayer = () => useStore(useGeoViewStore(), (state) => state.layerState.highlightedLayer); -export const useLayersList = () => useStore(useGeoViewStore(), (state) => state.layerState.legendLayers); +export const useLayerLegendLayers = () => useStore(useGeoViewStore(), (state) => state.layerState.legendLayers); export const useLayerSelectedLayer = () => useStore(useGeoViewStore(), (state) => state.layerState.selectedLayer); -export const useSelectedLayerPath = () => useStore(useGeoViewStore(), (state) => state.layerState.selectedLayerPath); -export const useLayersDisplayState = () => useStore(useGeoViewStore(), (state) => state.layerState.displayState); +export const useLayerSelectedLayerPath = () => useStore(useGeoViewStore(), (state) => state.layerState.selectedLayerPath); +export const useLayerDisplayState = () => useStore(useGeoViewStore(), (state) => state.layerState.displayState); export const useLayerStoreActions = () => useStore(useGeoViewStore(), (state) => state.layerState.actions); diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts index a013937b140..0ec051ce221 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts @@ -15,7 +15,7 @@ import { TypeSetStore, TypeGetStore } from '@/core/stores/geoview-store'; import { TypeBasemapOptions, TypeMapFeaturesConfig, TypeValidMapProjectionCodes } from '@/core/types/global-types'; import { TypeFeatureInfoEntry, TypeGeometry, TypeMapMouseInfo } from '@/api/events/payloads'; -import { TypeInteraction } from '@/geo/map/map-schema-types'; +import { TypeInteraction, TypeVisibilityFlags } from '@/geo/map/map-schema-types'; import { TypeClickMarker, api } from '@/app'; import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor'; @@ -31,6 +31,14 @@ export interface TypeNorthArrow { isNorthVisible: boolean; } +export interface TypeOrderedLayerInfo { + layerPath: string; + visible: TypeVisibilityFlags; + removable: boolean; + queryable?: boolean; + hoverable?: boolean; +} + export interface IMapState { attribution: string[]; basemapOptions: TypeBasemapOptions; @@ -41,12 +49,12 @@ export interface IMapState { fixNorth: boolean; highlightedFeatures: Array; interaction: TypeInteraction; - layerOrder: string[]; mapElement?: OLMap; mapExtent: Extent | undefined; mapLoaded: boolean; northArrow: boolean; northArrowElement: TypeNorthArrow; + orderedLayerInfo: Array; overlayClickMarker?: Overlay; overlayNorthMarker?: Overlay; overviewMap: boolean; @@ -56,7 +64,6 @@ export interface IMapState { scale: TypeScaleInfo; selectedFeatures: Array; size: [number, number]; - visibleLayers: string[]; zoom: number; setDefaultConfigValues: (config: TypeMapFeaturesConfig) => void; @@ -75,25 +82,31 @@ export interface IMapState { addSelectedFeature: (feature: TypeFeatureInfoEntry) => void; createBaseMapFromOptions: () => void; createEmptyBasemap: () => TileLayer; + getIndexFromOrderedLayerInfo: (layerPath: string) => number; getPixelFromCoordinate: (coord: Coordinate) => [number, number]; + getRemovableFromOrderedLayerInfo: (layerPath: string) => boolean; + getVisibilityFromOrderedLayerInfo: (layerPath: string) => TypeVisibilityFlags; hideClickMarker: () => void; highlightBBox: (extent: Extent, isLayerHighlight?: boolean) => void; removeHighlightedFeature: (feature: TypeFeatureInfoEntry | 'all') => void; removeSelectedFeature: (feature: TypeFeatureInfoEntry | 'all') => void; + reorderLayer: (layerPath: string, move: number) => void; setAttribution: (attribution: string[]) => void; setClickCoordinates: () => void; setFixNorth: (ifFix: boolean) => void; + setHoverable: (layerPath: string, hoverable: boolean) => void; setInteraction: (interaction: TypeInteraction) => void; - setLayerOrder: (newOrder: string[]) => void; setMapElement: (mapElem: OLMap) => void; setMapKeyboardPanInteractions: (panDelta: number) => void; + setOrderedLayerInfo: (newOrderedLayerInfo: Array) => void; + setOrToggleLayerVisibility: (layerPath: string, newValue?: TypeVisibilityFlags) => void; setOverlayClickMarker: (overlay: Overlay) => void; setOverlayClickMarkerRef: (htmlRef: HTMLElement) => void; setOverlayNorthMarker: (overlay: Overlay) => void; setOverlayNorthMarkerRef: (htmlRef: HTMLElement) => void; setProjection: (projectionCode: TypeValidMapProjectionCodes, view: View) => void; + setQueryable: (layerPath: string, queryable: boolean) => void; setRotation: (degree: number) => void; - setVisibleLayers: (newOrder: string[]) => void; setZoom: (zoom: number, duration?: number) => void; showClickMarker: (marker: TypeClickMarker) => void; transformPoints: (coords: Coordinate[], outputProjection: number) => Coordinate[]; @@ -124,11 +137,11 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt fixNorth: false, highlightedFeatures: [], interaction: 'static', - layerOrder: [], mapExtent: undefined, mapLoaded: false, northArrow: false, northArrowElement: { degreeRotation: '180.0', isNorthVisible: true } as TypeNorthArrow, + orderedLayerInfo: [], overviewMap: false, overviewMapHideZoom: 0, pointerPosition: undefined, @@ -136,7 +149,6 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt scale: { lineWidth: '', labelGraphic: '', labelNumeric: '' } as TypeScaleInfo, selectedFeatures: [], size: [0, 0] as [number, number], - visibleLayers: [], zoom: 0, // initialize default stores section from config information when store receive configuration file @@ -320,6 +332,21 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt createEmptyBasemap: (): TileLayer => { return MapEventProcessor.createEmptyBasemap(get().mapId); }, + getIndexFromOrderedLayerInfo: (layerPath: string): number => { + const info = get().mapState.orderedLayerInfo; + for (let i = 0; i < info.length; i++) if (info[i].layerPath === layerPath) return i; + return -1; + }, + getRemovableFromOrderedLayerInfo: (layerPath: string): boolean => { + const info = get().mapState.orderedLayerInfo; + const pathInfo = info.find((item) => item.layerPath === layerPath); + return pathInfo!.removable; + }, + getVisibilityFromOrderedLayerInfo: (layerPath: string): string => { + const info = get().mapState.orderedLayerInfo; + const pathInfo = info.find((item) => item.layerPath === layerPath); + return pathInfo?.visible || 'yes'; + }, getPixelFromCoordinate: (coord: Coordinate): [number, number] => { return get().mapState.mapElement!.getPixelFromCoordinate(coord) as unknown as [number, number]; }, @@ -363,6 +390,26 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt }); } }, + reorderLayer: (layerPath: string, move: number) => { + const direction = move < 0 ? -1 : 1; + let absoluteMoves = Math.abs(move); + const orderedLayers = [...get().mapState.orderedLayerInfo]; + let startingIndex = -1; + for (let i = 0; i < orderedLayers.length; i++) if (orderedLayers[i].layerPath === layerPath) startingIndex = i; + const layerInfo = orderedLayers[startingIndex]; + const movedLayers = orderedLayers.filter((layer) => layer.layerPath.startsWith(layerPath)); + orderedLayers.splice(startingIndex, movedLayers.length); + let nextIndex = startingIndex; + const pathLength = layerInfo.layerPath.split('/').length; + while (absoluteMoves > 0) { + nextIndex += direction; + if (nextIndex === orderedLayers.length || nextIndex === 0) { + absoluteMoves = 0; + } else if (orderedLayers[nextIndex].layerPath.split('/').length === pathLength) absoluteMoves--; + } + orderedLayers.splice(nextIndex, 0, ...movedLayers); + get().mapState.actions.setOrderedLayerInfo(orderedLayers); + }, setAttribution: (attribution: string[]) => { set({ mapState: { @@ -387,6 +434,19 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt }, }); }, + setHoverable: (layerPath: string, hoverable: boolean) => { + const curLayerInfo = get().mapState.orderedLayerInfo; + const layerInfo = curLayerInfo.find((info) => info.layerPath === layerPath); + if (layerInfo) { + layerInfo.hoverable = hoverable; + set({ + mapState: { + ...get().mapState, + orderedLayerInfo: [...curLayerInfo], + }, + }); + } + }, setInteraction: (interaction: TypeInteraction) => { set({ mapState: { @@ -400,15 +460,6 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt .mapState.mapElement!.getInteractions() .forEach((x) => x.setActive(interaction === 'dynamic')); }, - setLayerOrder: (newOrder: string[]) => { - set({ - mapState: { - ...get().mapState, - layerOrder: newOrder, - }, - }); - MapEventProcessor.setLayerZIndices(get().mapId); - }, setMapElement: (mapElem: OLMap) => { set({ mapState: { @@ -431,6 +482,15 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt }, }); }, + setOrderedLayerInfo: (newOrderedLayerInfo: Array) => { + set({ + mapState: { + ...get().mapState, + orderedLayerInfo: newOrderedLayerInfo, + }, + }); + MapEventProcessor.setLayerZIndices(get().mapId); + }, setOverlayClickMarkerRef: (htmlRef: HTMLElement) => { const overlay = get().mapState.overlayClickMarker; if (overlay !== undefined) overlay.setElement(htmlRef); @@ -461,19 +521,25 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt // reload the basemap from new projection MapEventProcessor.resetBasemap(get().mapId); }, + setQueryable: (layerPath: string, queryable: boolean) => { + const curLayerInfo = get().mapState.orderedLayerInfo; + const layerInfo = curLayerInfo.find((info) => info.layerPath === layerPath); + if (layerInfo) { + layerInfo.queryable = queryable; + if (queryable) layerInfo.hoverable = queryable; + set({ + mapState: { + ...get().mapState, + orderedLayerInfo: [...curLayerInfo], + }, + }); + } + }, setRotation: (degree: number) => { // set ol map rotation // State is set by the map state store event 'onMapRotation' get().mapState.mapElement!.getView().animate({ rotation: degree }); }, - setVisibleLayers: (newOrder: string[]) => { - set({ - mapState: { - ...get().mapState, - visibleLayers: newOrder, - }, - }); - }, setZoom: (zoom: number, duration?: number) => { // set ol map zoom // State is set by the map state store event 'onMapZoomEnd' @@ -489,6 +555,21 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt mapState: { ...get().mapState, clickMarker: { lnglat: projectedCoords[0] } }, }); }, + setOrToggleLayerVisibility: (layerPath: string, newValue?: TypeVisibilityFlags): void => { + const curOrderedLayerInfo = get().mapState.orderedLayerInfo; + const layerInfo = curOrderedLayerInfo.find((info) => info.layerPath === layerPath); + if (layerInfo && layerInfo.visible !== 'always') { + if (newValue) layerInfo!.visible = newValue; + else layerInfo!.visible = layerInfo?.visible === 'yes' ? 'no' : 'yes'; + api.maps[get().mapId].layer.geoviewLayer(layerPath).setVisible(layerInfo.visible !== 'no', layerPath); + set({ + mapState: { + ...get().mapState, + orderedLayerInfo: [...curOrderedLayerInfo], + }, + }); + } + }, transformPoints: (coords: Coordinate[], outputProjection: number): Coordinate[] => { return api.projection.transformPoints(coords, `EPSG:${get().mapState.currentProjection}`, `EPSG:${outputProjection}`); }, @@ -521,11 +602,11 @@ export const useMapClickMarker = () => useStore(useGeoViewStore(), (state) => st export const useMapElement = () => useStore(useGeoViewStore(), (state) => state.mapState.mapElement); export const useMapExtent = () => useStore(useGeoViewStore(), (state) => state.mapState.mapExtent); export const useMapFixNorth = () => useStore(useGeoViewStore(), (state) => state.mapState.fixNorth); -export const useMapLayers = () => useStore(useGeoViewStore(), (state) => state.mapState.layerOrder); export const useMapInteraction = () => useStore(useGeoViewStore(), (state) => state.mapState.interaction); export const useMapLoaded = () => useStore(useGeoViewStore(), (state) => state.mapState.mapLoaded); export const useMapNorthArrow = () => useStore(useGeoViewStore(), (state) => state.mapState.northArrow); export const useMapNorthArrowElement = () => useStore(useGeoViewStore(), (state) => state.mapState.northArrowElement); +export const useMapOrderedLayerInfo = () => useStore(useGeoViewStore(), (state) => state.mapState.orderedLayerInfo); export const useMapOverviewMap = () => useStore(useGeoViewStore(), (state) => state.mapState.overviewMap); export const useMapOverviewMapHideZoom = () => useStore(useGeoViewStore(), (state) => state.mapState.overviewMapHideZoom); export const useMapPointerPosition = () => useStore(useGeoViewStore(), (state) => state.mapState.pointerPosition); @@ -534,7 +615,6 @@ export const useMapRotation = () => useStore(useGeoViewStore(), (state) => state export const useMapSelectedFeatures = () => useStore(useGeoViewStore(), (state) => state.mapState.selectedFeatures); export const useMapScale = () => useStore(useGeoViewStore(), (state) => state.mapState.scale); export const useMapSize = () => useStore(useGeoViewStore(), (state) => state.mapState.size); -export const useMapVisibleLayers = () => useStore(useGeoViewStore(), (state) => state.mapState.visibleLayers); export const useMapZoom = () => useStore(useGeoViewStore(), (state) => state.mapState.zoom); export const useMapStoreActions = () => useStore(useGeoViewStore(), (state) => state.mapState.actions); diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts b/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts index 983c8fd8cbc..c6344a66042 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts @@ -245,6 +245,7 @@ export function commonProcessFeatureInfoConfig( layerConfig: TypeEsriFeatureLayerEntryConfig | TypeEsriDynamicLayerEntryConfig | TypeEsriImageLayerEntryConfig ) { if (!layerConfig.source.featureInfo) layerConfig.source.featureInfo = { queryable: capabilities.includes('Query') }; + MapEventProcessor.setMapLayerQueryable(this.mapId, layerConfig.layerPath, layerConfig.source.featureInfo.queryable); // dynamic group layer doesn't have fields definition if (!layerConfig.isMetadataLayerGroup) { // Process undefined outfields or aliasFields ('' = false and !'' = true). Also, if en is undefined, then fr is also undefined. diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts index f2d5299845f..da769d3ccb5 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts @@ -581,6 +581,7 @@ export class WMS extends AbstractGeoViewRaster { if (layerCapabilities) { if (layerCapabilities.Attribution) this.attributions.push(layerCapabilities.Attribution.Title as string); if (!layerConfig.source.featureInfo) layerConfig.source.featureInfo = { queryable: !!layerCapabilities.queryable }; + MapEventProcessor.setMapLayerQueryable(this.mapId, layerConfig.layerPath, layerConfig.source.featureInfo.queryable); // ! TODO: The solution implemented in the following lines is not right. scale and zoom are not the same things. // if (layerConfig.initialSettings?.minZoom === undefined && layerCapabilities.MinScaleDenominator !== undefined) // layerConfig.initialSettings.minZoom = layerCapabilities.MinScaleDenominator as number; diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts index db832f28ed0..5c770f46891 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts @@ -257,6 +257,7 @@ export class GeoPackage extends AbstractGeoViewVector { if (layers) { layerGroup!.getLayers().push(layers); this.setLayerStatus('processed', layerPath); + MapEventProcessor.replaceOrderedLayerInfo(this.mapId, layerConfig); } else { this.layerLoadError.push({ layer: listOfLayerEntryConfig[0].layerPath, @@ -274,6 +275,7 @@ export class GeoPackage extends AbstractGeoViewVector { const layerPath0 = listOfLayerEntryConfig[0].layerPath; if (layer) { this.setLayerStatus('processed', layerPath0); + MapEventProcessor.replaceOrderedLayerInfo(this.mapId, listOfLayerEntryConfig[0]); resolve(layer); } else { this.layerLoadError.push({ diff --git a/packages/geoview-core/src/geo/layer/layer.ts b/packages/geoview-core/src/geo/layer/layer.ts index 3b1a6ec597c..0a614ae6880 100644 --- a/packages/geoview-core/src/geo/layer/layer.ts +++ b/packages/geoview-core/src/geo/layer/layer.ts @@ -4,7 +4,7 @@ import { GeoCore, layerConfigIsGeoCore } from '@/geo/layer/other/geocore'; import { Geometry } from '@/geo/layer/geometry/geometry'; import { FeatureHighlight } from '@/geo/utils/feature-highlight'; -import { api } from '@/app'; +import { TypeOrderedLayerInfo, api } from '@/app'; import { EVENT_NAMES } from '@/api/events/event-types'; import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor'; @@ -62,7 +62,7 @@ export class Layer { geometry: Geometry | undefined; // order to load layers - initialLayerOrder: string[] = []; + initialLayerOrder: Array = []; /** used to reference the map id */ private mapId: string; @@ -197,38 +197,70 @@ export class Layer { } /** - * Loads layers that was passed in with the map config - * - * @param {TypeGeoviewLayerConfig[]} geoviewLayerConfigs an optional array containing layers passed within the map config + * Generate an array of layer info for the orderedLayerList. + * @param {TypeGeoviewLayerConfig} geoviewLayerConfig The config to get the info from. + * @returns {TypeOrderedLayerInfo[]} The array of ordered layer info. */ - loadListOfGeoviewLayer(geoviewLayerConfigs?: TypeGeoviewLayerConfig[]) { - const validGeoviewLayerConfigs = this.deleteDuplicatGeoviewLayerConfig(geoviewLayerConfigs); + generateArrayOfLayerOrderInfo(geoviewLayerConfig: TypeGeoviewLayerConfig | TypeLayerEntryConfig): TypeOrderedLayerInfo[] { + // TODO Add placeholder for geocore and the replacement when the layer is created in geocore.ts + if ((geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerType === 'geoCore') return []; + const newOrderedLayerInfos = []; const addSubLayerPathToLayerOrder = (layerEntryConfig: TypeLayerEntryConfig, layerPath: string): void => { - const subLayerPath = `${layerPath}/${layerEntryConfig.layerId}`; - this.initialLayerOrder.push(subLayerPath); + const subLayerPath = layerPath.endsWith(layerEntryConfig.layerId) ? layerPath : `${layerPath}/${layerEntryConfig.layerId}`; + const layerInfo: TypeOrderedLayerInfo = { + layerPath: subLayerPath, + visible: layerEntryConfig.initialSettings?.visible || 'yes', + removable: layerEntryConfig.initialSettings?.removable !== undefined ? layerEntryConfig.initialSettings?.removable : true, + queryable: layerEntryConfig.source?.featureInfo?.queryable !== undefined ? layerEntryConfig.source?.featureInfo?.queryable : true, + hoverable: layerEntryConfig.initialSettings?.hoverable !== undefined ? layerEntryConfig.initialSettings?.hoverable : true, + }; + newOrderedLayerInfos.push(layerInfo); if (layerEntryConfig.listOfLayerEntryConfig?.length) { layerEntryConfig.listOfLayerEntryConfig?.forEach((subLayerEntryConfig) => { addSubLayerPathToLayerOrder(subLayerEntryConfig, subLayerPath); }); } }; - - // set order for layers to appear on the map according to config - validGeoviewLayerConfigs.forEach((geoviewLayerConfig) => { - let layerPath = ''; - if (geoviewLayerConfig.listOfLayerEntryConfig.length > 1) { - layerPath = `${geoviewLayerConfig.geoviewLayerId}/${geoviewLayerConfig.geoviewLayerId}`; - this.initialLayerOrder.push(layerPath); - geoviewLayerConfig.listOfLayerEntryConfig.forEach((layerEntryConfig) => { + if ((geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId) { + if ((geoviewLayerConfig as TypeGeoviewLayerConfig).listOfLayerEntryConfig.length > 1) { + const layerPath = `${(geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId}/${ + (geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId + }`; + const layerInfo: TypeOrderedLayerInfo = { + layerPath, + visible: geoviewLayerConfig.initialSettings?.visible || 'yes', + removable: geoviewLayerConfig.initialSettings?.removable !== undefined ? geoviewLayerConfig.initialSettings?.removable : true, + }; + newOrderedLayerInfos.push(layerInfo); + (geoviewLayerConfig as TypeGeoviewLayerConfig).listOfLayerEntryConfig.forEach((layerEntryConfig) => { addSubLayerPathToLayerOrder(layerEntryConfig, layerPath); }); } else { - layerPath = `${geoviewLayerConfig.geoviewLayerId}/${geoviewLayerConfig.listOfLayerEntryConfig[0].layerId}`; - this.initialLayerOrder.push(layerPath); + const layerEntryConfig = (geoviewLayerConfig as TypeGeoviewLayerConfig).listOfLayerEntryConfig[0]; + addSubLayerPathToLayerOrder(layerEntryConfig, layerEntryConfig.layerPath); } + } else addSubLayerPathToLayerOrder(geoviewLayerConfig as TypeLayerEntryConfig, (geoviewLayerConfig as TypeLayerEntryConfig).layerPath); + + return newOrderedLayerInfos; + } + + /** + * Load layers that was passed in with the map config + * + * @param {TypeGeoviewLayerConfig[]} geoviewLayerConfigs an optional array containing layers passed within the map config + */ + loadListOfGeoviewLayer(geoviewLayerConfigs?: TypeGeoviewLayerConfig[]) { + const validGeoviewLayerConfigs = this.deleteDuplicatGeoviewLayerConfig(geoviewLayerConfigs); + + // set order for layers to appear on the map according to config + const orderedLayerInfos: TypeOrderedLayerInfo[] = []; + validGeoviewLayerConfigs.forEach((geoviewLayerConfig) => { + const layerInfos = this.generateArrayOfLayerOrderInfo(geoviewLayerConfig); + orderedLayerInfos.push(...layerInfos); api.event.emit(layerConfigPayload(EVENT_NAMES.LAYER.EVENT_ADD_LAYER, this.mapId, geoviewLayerConfig)); }); + MapEventProcessor.setMapOrderedLayerInfo(this.mapId, orderedLayerInfos); } /** diff --git a/packages/geoview-core/src/geo/map/map-schema-types.ts b/packages/geoview-core/src/geo/map/map-schema-types.ts index 6b59b3aee53..5c9c44bb9f6 100644 --- a/packages/geoview-core/src/geo/map/map-schema-types.ts +++ b/packages/geoview-core/src/geo/map/map-schema-types.ts @@ -69,6 +69,12 @@ export type TypeLayerInitialSettings = { maxZoom?: number; /** A CSS class name to set to the layer element. */ className?: string; + /** Is the layer removable. */ + removable?: true; + /** Is the layer hoverable. */ + hoverable?: true; + /** Is the layer queryable. */ + queryable?: true; }; /** ****************************************************************************************************************************** diff --git a/packages/geoview-core/src/geo/utils/layer-set.ts b/packages/geoview-core/src/geo/utils/layer-set.ts index 011f708b970..4e2aa2bbdd4 100644 --- a/packages/geoview-core/src/geo/utils/layer-set.ts +++ b/packages/geoview-core/src/geo/utils/layer-set.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor'; import { EVENT_NAMES } from '@/api/events/event-types'; import { LayerSetPayload, @@ -137,6 +138,7 @@ export class LayerSet { ); } else if (action === 'remove' && layerPath in this.resultsSet) { delete this.resultsSet[layerPath]; + MapEventProcessor.removeOrderedLayerInfo(this.mapId, layerPath); api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultsSet, layerPath)); } } diff --git a/packages/geoview-geochart/src/geochart-panel.tsx b/packages/geoview-geochart/src/geochart-panel.tsx index 258c00eb4fc..16562c8163e 100644 --- a/packages/geoview-geochart/src/geochart-panel.tsx +++ b/packages/geoview-geochart/src/geochart-panel.tsx @@ -1,12 +1,12 @@ import { useTheme } from '@mui/material/styles'; -import { TypeWindow, getLocalizedMessage } from 'geoview-core'; +import { TypeOrderedLayerInfo, TypeWindow, getLocalizedMessage } from 'geoview-core'; import { ChartType, SchemaValidator } from 'geochart'; import { LayerListEntry, Layout } from 'geoview-core/src/core/components/common'; import { TypeLayerData, TypeArrayOfLayerData } from 'geoview-core/src/api/events/payloads/get-feature-info-payload'; import { Typography } from 'geoview-core/src/ui/typography/typography'; import { Paper } from 'geoview-core/src/ui'; import { - useMapVisibleLayers, + useMapOrderedLayerInfo, useGeochartConfigs, useGeochartStoreActions, useGeochartStoreLayerDataArrayBatch, @@ -42,7 +42,7 @@ export function GeoChartPanel(props: GeoChartPanelProps): JSX.Element { // Get states and actions from store const configObj = useGeochartConfigs(); - const visibleLayers = useMapVisibleLayers() as string[]; + const orderedLayerInfo = useMapOrderedLayerInfo() as TypeOrderedLayerInfo[]; const storeArrayOfLayerData = useGeochartStoreLayerDataArrayBatch() as TypeArrayOfLayerData; const selectedLayerPath = useGeochartStoreSelectedLayerPath() as string; const { setSelectedLayerPath, setLayerDataArrayBatchLayerPathBypass } = useGeochartStoreActions(); @@ -102,6 +102,13 @@ export function GeoChartPanel(props: GeoChartPanelProps): JSX.Element { // Log logger.logTraceUseMemo('GEOCHART-PANEL - memoLayersList', storeArrayOfLayerData); + const visibleLayers = orderedLayerInfo + .map((layerInfo) => { + if (layerInfo.visible !== 'no') return layerInfo.layerPath; + return undefined; + }) + .filter((layerPath) => layerPath !== undefined); + // Set the layers list return visibleLayers .map((layerPath) => storeArrayOfLayerData.find((layerData) => layerData.layerPath === layerPath)) @@ -118,7 +125,7 @@ export function GeoChartPanel(props: GeoChartPanelProps): JSX.Element { tooltip: `${layer!.layerName}, ${getNumFeaturesLabel(layer!)}`, } as LayerListEntry) ); - }, [visibleLayers, storeArrayOfLayerData, configObj, getNumFeaturesLabel]); + }, [orderedLayerInfo, storeArrayOfLayerData, configObj, getNumFeaturesLabel]); /** * Memoizes the selected layer for the LayerList component. diff --git a/packages/geoview-time-slider/src/time-slider-panel.tsx b/packages/geoview-time-slider/src/time-slider-panel.tsx index f3d6c790c60..8ef23c711f8 100644 --- a/packages/geoview-time-slider/src/time-slider-panel.tsx +++ b/packages/geoview-time-slider/src/time-slider-panel.tsx @@ -1,7 +1,7 @@ import { useTheme } from '@mui/material/styles'; -import { TypeWindow, getLocalizedMessage } from 'geoview-core'; +import { TypeOrderedLayerInfo, TypeWindow, getLocalizedMessage } from 'geoview-core'; import { LayerListEntry, Layout } from 'geoview-core/src/core/components/common'; -import { useMapVisibleLayers, useTimeSliderLayers } from 'geoview-core/src/core/stores'; +import { useMapOrderedLayerInfo, useTimeSliderLayers } from 'geoview-core/src/core/stores'; import { Paper, Typography } from 'geoview-core/src/ui'; import { logger } from 'geoview-core/src/core/utils/logger'; @@ -33,7 +33,7 @@ export function TimeSliderPanel(props: TypeTimeSliderProps): JSX.Element { const [selectedLayerPath, setSelectedLayerPath] = useState(); // get values from store - const visibleLayers = useMapVisibleLayers() as string[]; + const orderedLayerInfo = useMapOrderedLayerInfo() as TypeOrderedLayerInfo[]; const timeSliderLayers = useTimeSliderLayers(); /** @@ -53,10 +53,17 @@ export function TimeSliderPanel(props: TypeTimeSliderProps): JSX.Element { // Log logger.logTraceUseMemo('TIME-SLIDER-PANEL - memoLayersList', timeSliderLayers); + const visibleLayers = orderedLayerInfo + .map((layerInfo) => { + if (layerInfo.visible !== 'no') return layerInfo.layerPath; + return undefined; + }) + .filter((layerPath) => layerPath !== undefined); + // Return the layers return visibleLayers .map((layerPath) => { - return { layerPath, timeSliderLayerInfo: timeSliderLayers[layerPath] }; + return { layerPath, timeSliderLayerInfo: timeSliderLayers[layerPath!] }; }) .filter((layer) => layer && layer.timeSliderLayerInfo) .map((layer) => { @@ -68,7 +75,7 @@ export function TimeSliderPanel(props: TypeTimeSliderProps): JSX.Element { queryStatus: 'processed', } as LayerListEntry; }); - }, [visibleLayers, timeSliderLayers]); + }, [orderedLayerInfo, timeSliderLayers]); useEffect(() => { // Log