diff --git a/src/app.js b/src/app.js
index d1ea00fd..9414e789 100644
--- a/src/app.js
+++ b/src/app.js
@@ -6,7 +6,7 @@ import { useLayers } from '@context';
import { Sidebar } from '@components/sidebar';
import { ControlPanel } from '@components/control-panel';
import { ComparePanel } from '@components/compare-panel';
-import { MapLegend } from '@components/legend';
+import { MapLegend, AdditionalMapLegend } from '@components/legend';
import { AlertUser } from '@components/alert-user';
import { Config } from '@components/config';
import { Acknowledgements } from "@components/acknowledgements";
@@ -43,6 +43,7 @@ const Content = () => {
{ (defaultInstanceName != null) && }
+
);
diff --git a/src/components/legend/additional-legend.js b/src/components/legend/additional-legend.js
new file mode 100644
index 00000000..fce01f40
--- /dev/null
+++ b/src/components/legend/additional-legend.js
@@ -0,0 +1,106 @@
+import React, { useRef, Fragment } from 'react';
+import { Card, Box, Stack, Avatar, Typography } from '@mui/joy';
+import { useLayers } from '@context';
+import Draggable from "react-draggable";
+
+/**
+ * renders the legend for selected additional layers
+ *
+ * @constructor
+ */
+export const AdditionalMapLegend = () => {
+ // install the selected observation list from the layer context
+ const { externalLayers, topMostExtLegendIndex, setTopMostExtLegendIndex } = useLayers();
+
+ // create a reference to avoid the findDOMNode deprecation issue
+ const nodeRef = useRef(null);
+
+ /**
+ * handles a click on the legend to make it have focus
+ */
+ const handleClick = (index) => {
+ // set the new topmost dialog in the stack
+ setTopMostExtLegendIndex(index);
+ };
+
+ // render the legends
+ return (
+
+ {
+ // loop through the external layers and create checkbox selections grouped by the source
+ externalLayers
+ // group by the source name
+ .filter((val, idx, self) => (
+ idx === self.findIndex((t)=> ( t['source'] === val['source']) ))
+ )
+ // output sources
+ .map((layer) => (
+ // display legends for all selected external layers
+ externalLayers
+ // group by the source name
+ .filter(item => item.source === layer.source)
+ // only render visible layers that have a URL to a legend
+ .filter(item => (item.state.visible && item.params['legendURL']))
+ // run through all the layers in each group
+ .map((sublayer, itemIndex) => (
+
+
+ handleClick(sublayer['row_num']) }
+ sx={{
+ position: 'absolute',
+ top: 10 + ( 15 * itemIndex ),
+ right: 75 + ( 25 * itemIndex ),
+ transition: 'filter 250ms',
+ padding: '5px',
+ border: 1,
+ borderRadius: 'sm',
+ filter: 'opacity(0.9)', '&:hover': { filter: 'opacity(1.0)' },
+ width: '60px',
+ zIndex: (sublayer['row_num'] === topMostExtLegendIndex) ? 1000 : 999 }}>
+
+
+
+
+
+
+ { sublayer.source.split(' ').map(word => word.charAt(0)) } { sublayer.row_num }
+
+
+
+
+
+
+
+ ))
+ ))
+ }
+
+ );
+};
diff --git a/src/components/legend/index.js b/src/components/legend/index.js
index 74075732..f1883c2a 100644
--- a/src/components/legend/index.js
+++ b/src/components/legend/index.js
@@ -1 +1,2 @@
-export * from './legend';
\ No newline at end of file
+export * from './legend';
+export * from './additional-legend';
\ No newline at end of file
diff --git a/src/components/legend/legend.js b/src/components/legend/legend.js
index 73b49bef..fd21be21 100644
--- a/src/components/legend/legend.js
+++ b/src/components/legend/legend.js
@@ -136,6 +136,7 @@ export const MapLegend = () => {
'&:hover': { filter: 'opacity(1.0)' },
padding: '10px',
zIndex: 999,
+ border: 1,
borderRadius: 'sm',
visibility: legendVisibilty,
diff --git a/src/components/map/external-layers.js b/src/components/map/external-layers.js
index 7efa444c..09326eb3 100644
--- a/src/components/map/external-layers.js
+++ b/src/components/map/external-layers.js
@@ -16,15 +16,7 @@ export const ExternalLayers = () => {
externalLayers
} = useLayers();
- //const sst_url = "https://coastwatch.noaa.gov/erddap/wms/noaacwBLENDEDsstDNDaily/request";
- //const sst_layer = "noaacwBLENDEDsstDNDaily:analysed_sst";
-
- //const sst_url = "https://coastwatch.noaa.gov/erddap/wms/noaacwecnAVHRRmultisatsstEastCoastMonthly/request";
- //const sst_layer = "noaacwecnAVHRRmultisatsstEastCoastMonthly:sst";
-
- //const sst_url = "https://coastwatch.noaa.gov/erddap/wms/noaacwecnAVHRRmultisatsstEastCoast3Day/request";
- //const sst_layer = "noaacwecnAVHRRmultisatsstEastCoast3Day:sst";
-
+ // if there are external layers to render
if (externalLayers != null) {
return (
@@ -34,10 +26,10 @@ export const ExternalLayers = () => {
.map(
(layer) => (
)
)
diff --git a/src/components/trays/additional-layers/externalLayerItems.js b/src/components/trays/additional-layers/externalLayerItems.js
index 3732185d..c1497005 100644
--- a/src/components/trays/additional-layers/externalLayerItems.js
+++ b/src/components/trays/additional-layers/externalLayerItems.js
@@ -5,7 +5,7 @@ import {
import { KeyboardArrowDown as ExpandIcon } from '@mui/icons-material';
import { useLayers } from "@context/map-context";
import PropTypes from 'prop-types';
-import {ActionButton} from "@components/buttons";
+import { ActionButton } from "@components/buttons";
// set component prop types
ExternalLayerItems.propTypes = {
@@ -215,7 +215,7 @@ export default function ExternalLayerItems(data) {
expanded={ getAccordionState(layer['source']) }
onChange={ () => toggleAccordionView(layer['source']) }>
-
+
{ layer['source'] }
@@ -243,7 +243,7 @@ export default function ExternalLayerItems(data) {
{ layer['name'] } }
+ label={ { layer['row_num'] }: { layer['name'] } }
onChange={ () => toggleLayerVisibility(layer['name']) }
/>
diff --git a/src/components/trays/remove/index.js b/src/components/trays/remove/index.js
index 9542fbc2..5be34922 100644
--- a/src/components/trays/remove/index.js
+++ b/src/components/trays/remove/index.js
@@ -7,6 +7,7 @@ import { RemoveAllObservations } from "./remove-observations";
import { RemoveModels } from "./remove-models";
import { ResetStyles } from "./reset-styles";
import { ResetCompare } from "./reset-compare";
+import { RemoveAdditionalLayers } from "./remove-addl-layers";
// get an icon for the tray
export const icon = ;
@@ -25,5 +26,6 @@ export const trayContents = () => (
+
);
diff --git a/src/components/trays/remove/remove-addl-layers.js b/src/components/trays/remove/remove-addl-layers.js
new file mode 100644
index 00000000..47eca499
--- /dev/null
+++ b/src/components/trays/remove/remove-addl-layers.js
@@ -0,0 +1,21 @@
+import React, { Fragment } from 'react';
+import { Button } from '@mui/joy';
+import { useLayers } from "@context";
+
+/**
+ * component that handles the removal of Additional layers.
+ *
+ * @returns React.ReactElement
+ * @constructor
+ */
+export const RemoveAdditionalLayers = () => {
+ // get the method to remove the observation items in state
+ const { removeAdditionalLayers } = useLayers();
+
+ // render the button
+ return (
+
+
+
+ );
+};
diff --git a/src/context/map-context.js b/src/context/map-context.js
index a9dc4505..ca7a54fd 100644
--- a/src/context/map-context.js
+++ b/src/context/map-context.js
@@ -68,6 +68,9 @@ export const LayersProvider = ({ children }) => {
// state to keep track of the obs dialog that has focus
const [topMostDialogIndex, setTopMostDialogIndex] = useState(0);
+ // state to keep track of the obs dialog that has focus
+ const [topMostExtLegendIndex, setTopMostExtLegendIndex] = useState(0);
+
/**
* this section is for the side-by-side compare mode items
* @type {string}
@@ -127,6 +130,26 @@ export const LayersProvider = ({ children }) => {
}
};
+ /**
+ * hides the selected additional layers
+ *
+ */
+ const removeAdditionalLayers = () => {
+ // get a copy of the external layers
+ const newLayers = [...externalLayers];
+
+ // loop through the layers
+ newLayers.map(layer => {
+ // if this later is set to visible
+ if (layer.state.visible) {
+ layer.state.visible = false;
+ }
+ });
+
+ // save the altered list
+ setExternalLayers([...newLayers]);
+ };
+
/**
* clears any captured compare selection data and layers
*
@@ -452,10 +475,13 @@ export const LayersProvider = ({ children }) => {
selectedRightLayer, setSelectedRightLayer,
sideBySideLayers, setSideBySideLayers,
resetCompare, removeSideBySideLayers,
-
+ removeAdditionalLayers,
// tracks the dialog that has focus
- topMostDialogIndex, setTopMostDialogIndex
+ topMostDialogIndex, setTopMostDialogIndex,
+
+ // tracks the topmost additional layer legend index
+ topMostExtLegendIndex, setTopMostExtLegendIndex
}}
>
{children}