From 6bcb4413cad53ec40098c155269db8b53f578c8f Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Thu, 1 Aug 2024 09:11:25 -0400 Subject: [PATCH 1/7] minor updates to the deploy values, adding DB config values --- src/components/trays/layers/list.js | 209 ++++++++++++++-------------- 1 file changed, 107 insertions(+), 102 deletions(-) diff --git a/src/components/trays/layers/list.js b/src/components/trays/layers/list.js index d5757be8..be113014 100644 --- a/src/components/trays/layers/list.js +++ b/src/components/trays/layers/list.js @@ -1,11 +1,12 @@ import React from 'react'; import { - AccordionGroup, Box, - Divider, Accordion, AccordionSummary, AccordionDetails + AccordionGroup, Box, + Divider, Accordion, AccordionSummary, AccordionDetails } from '@mui/joy'; -import { useLayers } from '@context'; -import { LayerCard } from './layer-card'; -import { DeleteModelRunButton } from "@components/trays/layers/delete-layer-button"; +import {useLayers} from '@context'; +import {LayerCard} from './layer-card'; +import {DeleteModelRunButton} from "@components/trays/layers/delete-layer-button"; +import Draggable from 'react-draggable'; /** * gets the header data property name index @@ -16,40 +17,40 @@ import { DeleteModelRunButton } from "@components/trays/layers/delete-layer-butt * @returns {string} */ const getPropertyName = (layerProps, type) => { - // init the return - let ret_val = undefined; - - // capture the name of the element for tropical storms and advisory numbers - if (layerProps['met_class'] === 'tropical') { - switch (type) { - case 'stormOrModelEle': - ret_val = layerProps['storm_name']; - break; - case 'numberName': - ret_val = ' Adv: '; - break; - case 'numberEle': - ret_val = layerProps['advisory_number']; - break; + // init the return + let ret_val = undefined; + + // capture the name of the element for tropical storms and advisory numbers + if (layerProps['met_class'] === 'tropical') { + switch (type) { + case 'stormOrModelEle': + ret_val = layerProps['storm_name']; + break; + case 'numberName': + ret_val = ' Adv: '; + break; + case 'numberEle': + ret_val = layerProps['advisory_number']; + break; + } } - } - // capture the name of the synoptic ADCIRC models and cycle numbers - else { - switch (type) { - case 'stormOrModelEle': - ret_val = layerProps['model']; - break; - case 'numberName': - ret_val = ' Cycle: '; - break; - case 'numberEle': - ret_val = layerProps['cycle']; - break; + // capture the name of the synoptic ADCIRC models and cycle numbers + else { + switch (type) { + case 'stormOrModelEle': + ret_val = layerProps['model']; + break; + case 'numberName': + ret_val = ' Cycle: '; + break; + case 'numberEle': + ret_val = layerProps['cycle']; + break; + } } - } - // return to the caller - return ret_val; + // return to the caller + return ret_val; }; @@ -61,13 +62,13 @@ const getPropertyName = (layerProps, type) => { * @returns {string} */ const getHeaderSummary = (layerProps) => { - // get the full accordian summary text - return layerProps['run_date'] + ': ' + - ((getPropertyName(layerProps, 'stormOrModelEle') === undefined) ? 'Data error' : getPropertyName(layerProps, 'stormOrModelEle').toUpperCase()) + - ', ' + getPropertyName(layerProps, 'numberName') + getPropertyName(layerProps, 'numberEle') + - ', Type: ' + layerProps['event_type'] + - ', Grid: ' + layerProps['grid_type'] + - ((layerProps['meteorological_model'] === 'None') ? '' : ', ' + layerProps['meteorological_model']); + // get the full accordian summary text + return layerProps['run_date'] + ': ' + + ((getPropertyName(layerProps, 'stormOrModelEle') === undefined) ? 'Data error' : getPropertyName(layerProps, 'stormOrModelEle').toUpperCase()) + + ', ' + getPropertyName(layerProps, 'numberName') + getPropertyName(layerProps, 'numberEle') + + ', Type: ' + layerProps['event_type'] + + ', Grid: ' + layerProps['grid_type'] + + ((layerProps['meteorological_model'] === 'None') ? '' : ', ' + layerProps['meteorological_model']); }; /** @@ -84,11 +85,11 @@ const renderLayerCards = (layers, group) => { // filter/map the layers to create/return the layer card list layers // capture the layers for this group - .filter(layer => ( layer['group'] === group) ) + .filter(layer => (layer['group'] === group)) // at this point we have the distinct runs .map((layer, idx) => { - layerCards.push( ); - }); + layerCards.push( ); + }); // return to the caller return layerCards; @@ -101,23 +102,23 @@ const renderLayerCards = (layers, group) => { * @returns {*[]} */ const getGroupList = (layers) => { - // init the group list - const groupList = []; - - // loop through the layers and get the unique groups - layers - // filter by the group name - .filter((groups, idx, self) => - ( idx === self.findIndex((t)=> ( t['group'] === groups['group']) ))) - // .sort((a, b) => - // a['run_date'] < b['run_date'] ? 1 : -1) - // at this point we have the distinct runs - .map((layer) => { - groupList.push(layer); - }); - - // return the list of groups - return groupList; + // init the group list + const groupList = []; + + // loop through the layers and get the unique groups + layers + // filter by the group name + .filter((groups, idx, self) => + (idx === self.findIndex((t) => (t['group'] === groups['group'])))) + // .sort((a, b) => + // a['run_date'] < b['run_date'] ? 1 : -1) + // at this point we have the distinct runs + .map((layer) => { + groupList.push(layer); + }); + + // return the list of groups + return groupList; }; /** @@ -127,44 +128,48 @@ const getGroupList = (layers) => { * @constructor */ export const LayersList = () => { - // get a handle to the layer state - const { defaultModelLayers } = useLayers(); - - // get the default layers - const layers = [...defaultModelLayers]; - - // get the unique groups in the selected run groups - const groupList = getGroupList(layers); - - // loop through the layers and put them away - return ( - - { - // loop through the layer groups and put them away - groupList - // filter by the group name - .filter((groups, idx, self) => - ( idx === self.findIndex((t)=> ( t['group'] === groups['group']) ))) - // at this point we have the distinct runs - .map((groups, idx) => { - return ( - - - - - { getHeaderSummary(groups['properties']) } - - - - - { renderLayerCards( layers, groups['group'] ) } - - - ); - }) - } - - - ); + // get a handle to the layer state + const {defaultModelLayers} = useLayers(); + + // get the default layers + const layers = [...defaultModelLayers]; + + // get the unique groups in the selected run groups + const groupList = getGroupList(layers); + + const nodeRef = React.useRef(null); + + // loop through the layers and put them away + return ( + + + { + // loop through the layer groups and put them away + groupList + // filter by the group name + .filter((groups, idx, self) => + (idx === self.findIndex((t) => (t['group'] === groups['group'])))) + // at this point we have the distinct runs + .map((groups, idx) => { + return ( + + + + + {getHeaderSummary(groups['properties'])} + + + + + {renderLayerCards(layers, groups['group'])} + + + ); + }) + } + + + + ); }; From 5b6d839befe56d1a278be152e5b360aa38cadf58 Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:29:17 -0400 Subject: [PATCH 2/7] the x/y overflow param usage has a negative impact on the drag and drop component. --- src/components/sidebar/tray.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/sidebar/tray.js b/src/components/sidebar/tray.js index d9fff7e6..cae04cc7 100644 --- a/src/components/sidebar/tray.js +++ b/src/components/sidebar/tray.js @@ -19,8 +19,8 @@ export const Tray = ({ active, Contents, title, closeHandler }) => { width: TRAY_WIDTH, zIndex: 410, filter: 'drop-shadow(0 0 8px rgba(0, 0, 0, 0.2))', - overflowX: 'hidden', - overflowY: 'auto', + overflow: 'hidden', + // overflowY: 'auto', display: 'flex', flexDirection: 'column', ".tray-header": { From 0b0e0d733f2400485da6f98c3878546aa56befa2 Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:29:38 -0400 Subject: [PATCH 3/7] adding react-beautiful-dnd --- package-lock.json | 112 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 113 insertions(+) diff --git a/package-lock.json b/package-lock.json index 9f11f2c3..0082929d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "mapbox-gl": "^3.1.2", "prop-types": "^15.8.1", "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-leaflet": "^4.2.1", @@ -5420,6 +5421,16 @@ "@types/node": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "license": "MIT", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -5540,6 +5551,18 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-redux": { + "version": "7.1.33", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz", + "integrity": "sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==", + "license": "MIT", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.10", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", @@ -8052,6 +8075,15 @@ "postcss": "^8.4" } }, + "node_modules/css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "license": "MIT", + "dependencies": { + "tiny-invariant": "^1.0.6" + } + }, "node_modules/css-has-pseudo": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-6.0.3.tgz", @@ -14251,6 +14283,12 @@ "url": "https://github.com/sponsors/streamich" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -16235,6 +16273,12 @@ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" }, + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==", + "license": "MIT" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -16338,6 +16382,25 @@ "node": ">=0.10.0" } }, + "node_modules/react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.5 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -16437,6 +16500,37 @@ } } }, + "node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -16604,6 +16698,15 @@ "node": ">= 10.13.0" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -18540,6 +18643,15 @@ "punycode": "^2.1.0" } }, + "node_modules/use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/user-home": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", diff --git a/package.json b/package.json index 0c7f8890..02ff2f42 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "mapbox-gl": "^3.1.2", "prop-types": "^15.8.1", "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-leaflet": "^4.2.1", From 90b8383fab23a2bd48a24afba3e07a2d50a69f0c Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:30:41 -0400 Subject: [PATCH 4/7] implementing drag/drop of the model runs, tidying up code layout. --- src/components/trays/layers/list.js | 111 +++++++++++++++++----------- 1 file changed, 68 insertions(+), 43 deletions(-) diff --git a/src/components/trays/layers/list.js b/src/components/trays/layers/list.js index be113014..ca1aa662 100644 --- a/src/components/trays/layers/list.js +++ b/src/components/trays/layers/list.js @@ -1,12 +1,10 @@ import React from 'react'; -import { - AccordionGroup, Box, - Divider, Accordion, AccordionSummary, AccordionDetails -} from '@mui/joy'; -import {useLayers} from '@context'; -import {LayerCard} from './layer-card'; -import {DeleteModelRunButton} from "@components/trays/layers/delete-layer-button"; -import Draggable from 'react-draggable'; +import { AccordionGroup, Box, Divider, Accordion, AccordionSummary, AccordionDetails, Stack } from '@mui/joy'; +import { useLayers } from '@context'; +import { LayerCard } from './layer-card'; +import { DeleteModelRunButton } from "@components/trays/layers/delete-layer-button"; +import { DragHandleRounded as Handle } from '@mui/icons-material'; +import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; /** * gets the header data property name index @@ -16,13 +14,14 @@ import Draggable from 'react-draggable'; * @param type * @returns {string} */ -const getPropertyName = (layerProps, type) => { +const getPropertyName = (layerProps, element_name) => { // init the return let ret_val = undefined; // capture the name of the element for tropical storms and advisory numbers if (layerProps['met_class'] === 'tropical') { - switch (type) { + // by the element name + switch (element_name) { case 'stormOrModelEle': ret_val = layerProps['storm_name']; break; @@ -36,7 +35,7 @@ const getPropertyName = (layerProps, type) => { } // capture the name of the synoptic ADCIRC models and cycle numbers else { - switch (type) { + switch (element_name) { case 'stormOrModelEle': ret_val = layerProps['model']; break; @@ -110,8 +109,6 @@ const getGroupList = (layers) => { // filter by the group name .filter((groups, idx, self) => (idx === self.findIndex((t) => (t['group'] === groups['group'])))) - // .sort((a, b) => - // a['run_date'] < b['run_date'] ? 1 : -1) // at this point we have the distinct runs .map((layer) => { groupList.push(layer); @@ -137,39 +134,67 @@ export const LayersList = () => { // get the unique groups in the selected run groups const groupList = getGroupList(layers); - const nodeRef = React.useRef(null); + // handle the drag event + const onDragEnd = (result) => { + // dropped outside the list + if (!result.destination) { + return; + } + + // reorder the layer list + reorder( + layers, + result.source.index, + result.destination.index + ); + }; + + // a little function to help us with reordering the result + const reorder = (list, startIndex, endIndex) => { + const result = Array.from(list); + const [removed] = result.splice(startIndex, 1); + result.splice(endIndex, 0, removed); + + return result; + }; // loop through the layers and put them away return ( - - - { - // loop through the layer groups and put them away - groupList - // filter by the group name - .filter((groups, idx, self) => - (idx === self.findIndex((t) => (t['group'] === groups['group'])))) - // at this point we have the distinct runs - .map((groups, idx) => { - return ( - - - - - {getHeaderSummary(groups['properties'])} - - - - - {renderLayerCards(layers, groups['group'])} - - - ); - }) - } - - - + + + { (provided) => ( + + { + // loop through the layer groups and put them away + groupList + // filter by the group name + .filter((group, idx, self) => + (idx === self.findIndex((t) => (t['group'] === group['group'])))) + // at this point we have the distinct runs + .map((group, idx) => ( + + {(provided) => ( + + + + + + { getHeaderSummary(group['properties']) } + + + + + + + { renderLayerCards(layers, group['group'] )} + + + )} + )) + } { provided.placeholder } + )} + + ); }; From ef10c653871eea1606c78d44c38e72839f48a3ec Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:40:12 -0400 Subject: [PATCH 5/7] adjusting opacity --- src/components/trays/layers/delete-layer-button.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/trays/layers/delete-layer-button.js b/src/components/trays/layers/delete-layer-button.js index bca856fc..30b314f8 100644 --- a/src/components/trays/layers/delete-layer-button.js +++ b/src/components/trays/layers/delete-layer-button.js @@ -43,7 +43,7 @@ export const DeleteModelRunButton = ({ groupId }) => { sx={{ alignContent: 'right', m: 1, - 'filter': 'opacity(0.3)', + 'filter': 'opacity(0.5)', transition: 'filter 250ms', '&:hover': { 'filter': 'opacity(1.0)', From 88272f36ecae49f4e365abeaab7e23d26eacb17c Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Fri, 2 Aug 2024 09:11:08 -0400 Subject: [PATCH 6/7] adding comments --- src/components/trays/model-selection/catalogItems.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/trays/model-selection/catalogItems.js b/src/components/trays/model-selection/catalogItems.js index 5160d59f..1f281a5f 100644 --- a/src/components/trays/model-selection/catalogItems.js +++ b/src/components/trays/model-selection/catalogItems.js @@ -114,6 +114,9 @@ export default function CatalogItems(data) { return ({ visible: false, opacity: 1.0 }); }; + /** + * render the selected model runs + */ // do not render if there is no data if (data.data != null) { // if there was a warning getting the result @@ -170,7 +173,7 @@ export default function CatalogItems(data) { { // loop through the data members and put them away catalog['members'] - // filter by the group name + // filter by the group name, get the top 1 .filter((val, idx, self) => ( idx === self.findIndex((t)=> ( t['group'] === val['group']) ))) .sort((a, b) => a['properties'][numberEle] < b['properties'][numberEle] ? 1 : -1) From 5b727e092c0638825768997ea41d103bbfe7a60c Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Fri, 2 Aug 2024 09:20:21 -0400 Subject: [PATCH 7/7] finishing up full drag/drop functionality --- src/components/trays/layers/list.js | 137 ++++++++++++++++++++++------ 1 file changed, 110 insertions(+), 27 deletions(-) diff --git a/src/components/trays/layers/list.js b/src/components/trays/layers/list.js index ca1aa662..d73d8698 100644 --- a/src/components/trays/layers/list.js +++ b/src/components/trays/layers/list.js @@ -52,7 +52,6 @@ const getPropertyName = (layerProps, element_name) => { return ret_val; }; - /** * gets the summary header text for the layer groups. * This takes into account the two types of runs (tropical, synoptic) @@ -107,8 +106,8 @@ const getGroupList = (layers) => { // loop through the layers and get the unique groups layers // filter by the group name - .filter((groups, idx, self) => - (idx === self.findIndex((t) => (t['group'] === groups['group'])))) + .filter((group, idx, self) => + (idx === self.findIndex((t) => (t['group'] === group['group'])))) // at this point we have the distinct runs .map((layer) => { groupList.push(layer); @@ -118,6 +117,49 @@ const getGroupList = (layers) => { return groupList; }; +/** + * reorder the list of groups + * + * @param grpList + * @param startIndex + * @param endIndex + * @returns {unknown[]} + */ +const reOrderGroups = (grpList, startIndex, endIndex) => { + // copy the list + const ret_val = Array.from(grpList); + + // get the item that is moving + const [removed] = ret_val.splice(startIndex, 1); + + // put it in the new position + ret_val.splice(endIndex, 0, removed); + + // return the result + return ret_val; +}; + +/** + * adds or updates the visibility of the layer on the map surface. + * + * presumably this will have to take the met class into consideration. + * + * @param layer + * @param group + * @returns {{ visible: boolean, opacity: 1.0 }} + */ +const newLayerDefaultState = (layer, group) => { + // if this is an obs layer and is the one just added + if (layer.group === group && + (layer.properties['product_type'] === 'obs' || layer.properties['product_type'] === 'maxele63')) + // make this layer visible + return ({ visible: true, opacity: 1.0 }); + // remove layer visibility + else + // make this layer invisible + return ({ visible: false, opacity: 1.0 }); +}; + /** * render the layers for the selected run groups * @@ -126,39 +168,80 @@ const getGroupList = (layers) => { */ export const LayersList = () => { // get a handle to the layer state - const {defaultModelLayers} = useLayers(); + const {defaultModelLayers, setDefaultModelLayers} = useLayers(); // get the default layers const layers = [...defaultModelLayers]; - // get the unique groups in the selected run groups + // get the unique groups in the selected model runs const groupList = getGroupList(layers); - // handle the drag event + /** + * handle the drag event + * + * @param result + */ const onDragEnd = (result) => { - // dropped outside the list + // handle case that there is no destination (could have been dragged out of the drop area) if (!result.destination) { return; } - // reorder the layer list - reorder( - layers, - result.source.index, - result.destination.index - ); + // create an array of group ids + let grpList = []; + + // get the current layer groups + getGroupList(layers).map((item) => (grpList.push(item['group']))); + + // swap the elements + grpList = reOrderGroups(grpList, result.source.index, result.destination.index); + + // reorder the layers and put them back in state + reOrderLayers(grpList); }; - // a little function to help us with reordering the result - const reorder = (list, startIndex, endIndex) => { - const result = Array.from(list); - const [removed] = result.splice(startIndex, 1); - result.splice(endIndex, 0, removed); + /** + * order the layers in state based on the new group list order + * + * @param grpList + * @returns {*[]} + */ + const reOrderLayers = (grpList) => { + // init the return + const newLayerList = []; + + // reorder the layers into a new array + grpList + // soin through the groups + .map((group) => ( + // spin through the layers + defaultModelLayers + // get the layers for this group + .filter((layer) => + (layer['group'] === group)) + // add the group layers into a new list + .map((layer) => + (newLayerList.push(layer))))); + + // reset the visible layer states for all model runs in the layer tray. + [...newLayerList].forEach((layer) => { + // perform the visible state logic + layer.state = newLayerDefaultState(layer, layer.group); + }); + + // now update the visible layer state for the top most model run + [...newLayerList].forEach((layer) => { + // perform the visible state logic + layer.state = newLayerDefaultState(layer, newLayerList[0].group); + }); - return result; + // update the layer list in state + setDefaultModelLayers(newLayerList); }; - // loop through the layers and put them away + /** + * render the layers on the tray + */ return ( @@ -168,25 +251,25 @@ export const LayersList = () => { // loop through the layer groups and put them away groupList // filter by the group name - .filter((group, idx, self) => - (idx === self.findIndex((t) => (t['group'] === group['group'])))) + .filter((groups, idx, self) => + (idx === self.findIndex((t) => (t['group'] === groups['group'])))) // at this point we have the distinct runs - .map((group, idx) => ( - + .map((layer, idx) => ( + {(provided) => ( - { getHeaderSummary(group['properties']) } + { getHeaderSummary(layer['properties']) } - + - { renderLayerCards(layers, group['group'] )} + { renderLayerCards(layers, layer['group'] )} )}