diff --git a/src/components/compare-panel/compare-panel.js b/src/components/compare-panel/compare-panel.js
index 4f25a922..ee001fb7 100644
--- a/src/components/compare-panel/compare-panel.js
+++ b/src/components/compare-panel/compare-panel.js
@@ -1,6 +1,6 @@
import React, { useRef } from 'react';
import { Stack, Typography, Button, Card, Tooltip } from '@mui/joy';
-import { useLayers } from '@context';
+import {useLayers, useSettings} from '@context';
import { SwapHorizontalCircleSharp as SwapLayersIcon,
CloseSharp as ResetIcon } from '@mui/icons-material';
import { getHeaderSummary } from "@utils/map-utils";
@@ -27,6 +27,9 @@ export const ComparePanel = () => {
resetCompare
} = useLayers();
+ // use the use UTC value from the settings state
+ const { useUTC } = useSettings();
+
// get the default model run layers
const layers = [...defaultModelLayers];
@@ -46,7 +49,7 @@ export const ComparePanel = () => {
// if the layers were captured
if (layerProps !== undefined && layerProps.length !== 0) {
// get the full header summary text
- return getHeaderSummary(layerProps[0]['properties']);
+ return getHeaderSummary(layerProps[0]['properties'], useUTC.enabled);
}
else {
// return the default text
diff --git a/src/components/control-panel/control-panel.js b/src/components/control-panel/control-panel.js
index 3877513d..6841ea30 100644
--- a/src/components/control-panel/control-panel.js
+++ b/src/components/control-panel/control-panel.js
@@ -23,9 +23,10 @@ import {
Water as MaxElevationIcon,
Waves as HIResMaxElevationIcon,
} from '@mui/icons-material';
-import { getBrandingHandler, getNamespacedEnvParam } from "@utils/map-utils";
+import { getBrandingHandler, getNamespacedEnvParam, getPreferredTimeZone} from "@utils/map-utils";
import { getDefaultInstanceName } from "@components/config";
import { Branding } from './branding';
+import {useSettings} from "@context";
const layerIcons = {
maxele63: ,
@@ -43,7 +44,13 @@ export const ControlPanel = () => {
setDefaultModelLayers,
getAllLayersInvisible,
toggleLayerVisibility,
- toggleHurricaneLayerVisibility } = useLayers();
+ toggleHurricaneLayerVisibility,
+ } = useLayers();
+
+ /**
+ * use the use UTC value from the settings state
+ */
+ const { useUTC } = useSettings();
const data_url = `${ getNamespacedEnvParam('REACT_APP_UI_DATA_URL') }` + `get_ui_data_secure?limit=1&use_v3_sp=true${ getBrandingHandler() + getDefaultInstanceName() }`;
const layers = [...defaultModelLayers];
@@ -78,7 +85,7 @@ export const ControlPanel = () => {
if (topLayers[0]) {
runCycle = topLayers[0].properties.cycle;
runAdvisory = topLayers[0].properties.advisory_number;
- runDate = topLayers[0].properties.run_date;
+ runDate = getPreferredTimeZone(topLayers[0].properties, useUTC.enabled);
instanceName = topLayers[0].properties.instance_name;
metClass = topLayers[0].properties.met_class;
eventType = topLayers[0].properties.event_type;
@@ -357,10 +364,10 @@ export const ControlPanel = () => {
{metClass === 'tropical'? `Storm Name: ${stormName}` : ''}
- Model run date: {runDate}
+ Model run date: { runDate }
- Instance: {instanceName}
+ Instance: { instanceName }
Meteorology: { eventType }
diff --git a/src/components/dialog/observation-chart.js b/src/components/dialog/observation-chart.js
index d7b8c931..0709fd4c 100644
--- a/src/components/dialog/observation-chart.js
+++ b/src/components/dialog/observation-chart.js
@@ -1,12 +1,12 @@
import React, {Fragment} from 'react';
-import {useQuery} from '@tanstack/react-query';
-import {Typography} from '@mui/material';
+import { useQuery } from '@tanstack/react-query';
+import { Typography } from '@mui/material';
import axios from 'axios';
import axiosRetry from 'axios-retry';
-import {LineChart, Line, XAxis, YAxis, CartesianGrid, ResponsiveContainer, Tooltip, ReferenceLine} from 'recharts';
+import { LineChart, Line, XAxis, YAxis, CartesianGrid, ResponsiveContainer, Tooltip, ReferenceLine } from 'recharts';
import {getNamespacedEnvParam} from "@utils/map-utils";
import dayjs from 'dayjs';
-
+import { useSettings } from '@context';
// install day.js for UTC visual formatting
const utc = require("dayjs/plugin/utc");
@@ -43,7 +43,7 @@ console.error = (...args) => {
* @param url
* @returns { json }
*/
-function getObsChartData(url, setLineButtonView) {
+function getObsChartData(url, setLineButtonView, useUTC) {
// configure the retry count to be zero
axiosRetry(axios, {
retries: 0
@@ -80,7 +80,7 @@ function getObsChartData(url, setLineButtonView) {
// if there was not an error
if (ret_val !== 500) {
// return the csv data in JSON format
- return csvToJSON(ret_val, setLineButtonView);
+ return csvToJSON(ret_val, setLineButtonView, useUTC);
} else
// just return nothing and nothing will be rendered
return '';
@@ -94,7 +94,7 @@ function getObsChartData(url, setLineButtonView) {
* @param csvData
* @returns { json [] }
*/
-function csvToJSON(csvData, setLineButtonView) {
+const csvToJSON = (csvData, setLineButtonView, useUTC) => {
// ensure that there is csv data to convert
if (csvData !== "") {
// split on carriage returns. also removing all the windows \r characters if they exist
@@ -128,8 +128,15 @@ function csvToJSON(csvData, setLineButtonView) {
ret_val.map(function (e) {
// only convert records with a valid time
if (e.time !== "") {
- // take off the time zone
- e.time = e.time.substring(0, e.time.split(':', 2).join(':').length) + 'Z';
+ // put the date/time in the chosen format
+ if (useUTC) {
+ // reformat the text given into UTC format
+ e.time = e.time.substring(0, e.time.split(':', 2).join(':').length) + 'Z';
+ }
+ else {
+ // reformat the date/time to the local timezone
+ e.time = new Date(e.time).toLocaleString();
+ }
// data that is missing a value will not result in plotting
if (e["Observations"]) {
@@ -193,7 +200,7 @@ function csvToJSON(csvData, setLineButtonView) {
// return the json data representation
return ret_val;
}
-}
+};
/**
* reformats the data label shown on the x-axis
@@ -207,19 +214,23 @@ function formatY_axis(value) {
}
/**
- * reformats the data label shown on the x-axis
+ * reformats the data label shown on the x-axis. this uses the chosen timezone.
*
* @param value
* @returns {string}
*/
-function formatX_axis(value) {
+function formatX_axis(value, useUTC) {
// init the return value
let ret_val = "";
// empty data will be ignored
if (value !== "")
- // do the reformatting
- ret_val = dayjs.utc(value).format('MM/DD-HH').split('+')[0];
+ // put this in the proper format
+ if(useUTC)
+ ret_val = dayjs.utc(value).format('MM/DD-HH').split('+')[0] + 'Z';
+ // else use reformat using the local time zone
+ else
+ ret_val = dayjs(value).format('MM/DD-HH').split('+')[0];
// return the formatted value
return ret_val;
@@ -321,9 +332,12 @@ function get_xtick_interval(data) {
* @returns React.ReactElement
* @constructor
*/
-function CreateObsChart(c) {
+const CreateObsChart = (c) => {
+ // get the timezone preference
+ const { useUTC } = useSettings();
+
// call to get the data. expect back some information too
- const {status, data} = getObsChartData(c.chartProps.url, c.chartProps.setLineButtonView);
+ const {status, data} = getObsChartData(c.chartProps.url, c.chartProps.setLineButtonView, useUTC.enabled);
// render the chart
return (
@@ -338,8 +352,8 @@ function CreateObsChart(c) {
- formatX_axis(value)}/>
+ formatX_axis(value, useUTC.enabled)}/>
@@ -367,4 +381,4 @@ function CreateObsChart(c) {
}
);
-}
+};
diff --git a/src/components/map/hurricane-track.js b/src/components/map/hurricane-track.js
index 33bf6f49..bd9ab4bf 100644
--- a/src/components/map/hurricane-track.js
+++ b/src/components/map/hurricane-track.js
@@ -2,13 +2,9 @@ import React, { useState, useEffect, Fragment } from 'react';
import PropTypes from 'prop-types';
import { GeoJSON } from 'react-leaflet';
import { Marker } from 'leaflet';
-import {
- getTrackData,
- getTrackGeojson
-} from "@utils/hurricane/track";
-import { useLayers } from '@context';
+import { getTrackData, getTrackGeojson } from "@utils/hurricane/track";
+import { useLayers, useSettings} from '@context';
import { getNamespacedEnvParam } from "@utils";
-import { useSettings } from '@context';
import { mphToMps, mphToKnots } from '@utils/map-utils';
@@ -17,6 +13,10 @@ export const HurricaneTrackGeoJson = ({index}) => {
const {
hurricaneTrackLayers,
} = useLayers();
+
+ // get the time zone from settings state
+ const { useUTC } = useSettings();
+
const [hurricaneData, setHurricaneData] = useState();
const {
@@ -91,6 +91,8 @@ export const HurricaneTrackGeoJson = ({index}) => {
const onEachHurrFeature = (feature, layer) => {
if (feature.properties && feature.properties.time_utc) {
+ // get the date/time by current preference
+ const preferredTimeZone = useUTC.enabled ? feature.properties.time_utc + 'Z' : new Date(feature.properties.time_utc + 'Z').toLocaleString();
// set wind speed to default units setting values
let windSpeed = mphToMps(feature.properties.max_wind_speed_mph);
@@ -103,9 +105,8 @@ export const HurricaneTrackGeoJson = ({index}) => {
unitStr = speedType.current;
}
- const popupContent = feature.properties.storm_name + ": " +
- feature.properties.time_utc + ", " +
- windSpeed.toFixed(1) + unitStr;
+ // build the popup content
+ const popupContent = feature.properties.storm_name + ": " + preferredTimeZone + ", " + windSpeed.toFixed(1) + unitStr;
layer.on("mouseover", function (e) {
this.bindPopup(popupContent).openPopup(e.latlng);
diff --git a/src/components/map/storm-layers.js b/src/components/map/storm-layers.js
index 9c27d263..2cb6dfdc 100644
--- a/src/components/map/storm-layers.js
+++ b/src/components/map/storm-layers.js
@@ -95,6 +95,7 @@ export const StormLayers = () => {
stormName: stormName,
stormNumber: stormNumber,
runDate: topLayer.properties.run_date,
+ insertion_date: topLayer.properties['insertion_date'],
year: year,
advisory: advisory,
instanceName: topLayer.properties.instance_name,
diff --git a/src/components/trays/compare-layers/CompareLayersTray.js b/src/components/trays/compare-layers/CompareLayersTray.js
index f6da5d9b..55d9f851 100644
--- a/src/components/trays/compare-layers/CompareLayersTray.js
+++ b/src/components/trays/compare-layers/CompareLayersTray.js
@@ -61,6 +61,7 @@ export const CompareLayersTray = () => {
const {
mapStyle,
+ useUTC
} = useSettings();
// used to collapse other open accordions
@@ -339,7 +340,7 @@ export const CompareLayersTray = () => {
onChange={ (event, expanded) => { setAccordionIndex(expanded ? idx : null); }}
>
- { getHeaderSummary(layer['properties']) }
+ { getHeaderSummary(layer['properties'], useUTC.enabled)}
diff --git a/src/components/trays/help-about/helpAboutTray.js b/src/components/trays/help-about/helpAboutTray.js
index bf2d4a76..bee48563 100644
--- a/src/components/trays/help-about/helpAboutTray.js
+++ b/src/components/trays/help-about/helpAboutTray.js
@@ -14,7 +14,7 @@ import {
Share as ShareViewIcon,
HelpCenter as HelpAboutIcon,
- // map model layer types
+ // map ADCIRC model layer types
Tsunami as WaveHeightIcon,
QueryStats as ObservationIcon,
Air as WindVelocityIcon,
@@ -94,7 +94,7 @@ export const HelpAboutTray = () => {
Funding:
- DHS Coastal Resilience Center
+ DHS Coastal Resilience Center.
National Ocean Partnership Program (NOPP)
RENCI
@@ -102,10 +102,10 @@ export const HelpAboutTray = () => {
Collaborators:
- RENCI/UNC, NCSU, UGA
- DHS CRC
- The Water Institute for the Gulf
- NC Dept of Transportation
+ RENCI/UNC, NC State University and the University opf Georgia.
+ DHS CRC.
+ The Water Institute for the Gul.
+ NC Dept of Transportation.
@@ -173,9 +173,9 @@ export const HelpAboutTray = () => {
}}>
APSViz User Interface
- The APSViz User interface renders the products of the APSViz
+ The APSViz User interface renders the ADCIRC model layers of the APSViz
workflows for the user. It provides the user with tools to select, interrogate and display various
- ADCIRC products.
+ ADCIRC model layers.
@@ -199,40 +199,38 @@ export const HelpAboutTray = () => {
- Search for and select tropical or synoptic model runs.
+ Search for and select tropical or synoptic ADCIRC model runs.
Display tropical hurricane tracks and cones of uncertainty.
- Cycle through tropical advisories or synoptic model runs.
- Display (or hide) various model layer products such as wind speed, wave height, water levels,
+ Cycle through tropical advisories or synoptic ADCIRC model runs.
+ Display (or hide) various ADCIRC model layers such as wind speed, wave height, water levels,
etc.
Select observation points to display current and forecast timeseries data at that location.
Select anywhere on a map layer to display current and forecast timeseries geo-point data at that
location.
Compare ADCIRC model layer types.
View and adjust ADCIRC Layer colormap properties.
+ Select between UTC or current local date and time formats.
- {
- setIndex(expanded ? 3 : null);
- }}>
+ { setIndex(expanded ? 3 : null); }}>
What do all the icons mean?
Each icon represents a functionality of the application available to
- the
- user.
+ the user.
Collapsable sidebar items:
Selected models and
layers list
- Compare model
- run product layers
+ Compare ADCIRC model
+ layers
Hurricane track list
- Model run
+ ADCIRC model run
filtering and selection
Remove various map
items
@@ -278,18 +276,18 @@ export const HelpAboutTray = () => {
Toggle light or dark
mode.
Select a different base map.
- Reorder a model run up or down in the
+ Reorder a ADCIRC model run up or down in the
list.
Turn on/off a
- layer
+ layer.
Remove a model run or layer.
- Swap model run
+ sx={{color: 'darkred', 'filter': 'opacity(0.5)'}}/>Remove a ADCIRC model run or layer.
+ Swap ADCIRC model run
layer compare panes.
or Expand
or collapse an item.
or Reorder
- a model layer.
+ the ADCIRC model layers.
or Increment tropical advisories or synoptic
cycles.
@@ -325,7 +323,7 @@ export const HelpAboutTray = () => {
Edge
- Right click the browser surface.
+ Right click on the browser surface.
Select `Screenshot` from the context menu that appears.
At the top of the browser you can select to capture a portion of the browser or the entire
browser surface.
@@ -335,9 +333,7 @@ export const HelpAboutTray = () => {
- {
- setScreenCapIndex(expanded ? 6 : null);
- }}>
+ { setScreenCapIndex(expanded ? 6 : null); }}>
Firefox
@@ -351,9 +347,7 @@ export const HelpAboutTray = () => {
- {
- setScreenCapIndex(expanded ? 7 : null);
- }}>
+ { setScreenCapIndex(expanded ? 7 : null); }}>
Safari
@@ -384,12 +378,11 @@ export const HelpAboutTray = () => {
selection sidebar button.
- Click on the ADCIRC Model selection icon.
- Select either tropical or synoptic model runs.
+ Click on the ADCIRC Model selection icon button on the sidebar.
+ Select either the tropical or synoptic ADCIRC model run tab.
Select one or more appropriate data filter parameters.
- Click on the Submit button to retrieve model runs.
- Select on the model runs returned from the query to place them on the map
- surface.
+ Click on the Submit button to retrieve ADCIRC model runs.
+ Select on the ADCIRC model runs returned from the query to place them on the map surface.
When finished, retract the tray or click the Reset button to start a new search.
@@ -399,19 +392,19 @@ export const HelpAboutTray = () => {
setIndex(expanded ? 9 : null);
}}>
- How do I include, remove or reorder Layers on the map?
+ How do I include, remove or reorder ADCIRC model layers on the map?
- The Model layers
+ The ADCIRC Model layers
sidebar button.
- Click on the Model Layers icon button.
- Expand a model run.
+ Click on the ADCIRC model Layers icon button on the sidebar.
+ Expand a ADCIRC model run.
You can show/hide (slider), remove or reorder
- (up/down arrows) for individual model run layers from the list shown.
+ (up/down arrows) for individual ADCIRC model run layers from the list shown.
@@ -444,16 +437,15 @@ export const HelpAboutTray = () => {
Settings sidebar button.
- Is for selecting light or dark mode.
+ Is for selecting light or
+ dark mode.
Is for selecting a different base
map.
- {
- setIndex(expanded ? 12 : null);
- }}>
+ { setIndex(expanded ? 12 : null); }}>
How do I change the base map?
@@ -463,16 +455,14 @@ export const HelpAboutTray = () => {
Settings sidebar button.
- Click on the Application Settings icon
- Click on the base map icon
+ Click on the Application Settings icon button on the sidebar.
+ Click on the base map icon.
Select your preferred base map.
- {
- setIndex(expanded ? 13 : null);
- }}>
+ { setIndex(expanded ? 13 : null); }}>
How do I view observation data?
@@ -513,14 +503,16 @@ export const HelpAboutTray = () => {
src={targetIcon}>The selected location icon.
+
+ The user may select one or more points on the active Maximum Water Level or Maximum Surface Wave Height surface
+ features to plot available ADCIRC nowcast and forecast model values. The nowcast looks back 6 hours and forcast
+ data can go up to 5 days into the future.
+
- The user may select one or more points on the active Maximum Water Level or Maximum
- Surface Wave Height surface features to plot available nowcast and forecast model values.
- The nowcast looks back 6 hours. For each target point, a plot will be presented and the associated lat/lon
- values will be included in the plot titles. If no data are available, the plot chart will report a warning
- indicating a problem with collecting data. Data may be unavailable for multiple reasons including model runs that
- did not compute the quantity of interest or selecting a lat/lon target that are outside the model grid,
- such as inland.
+ For each target point, a plot will be presented and the associated lat/lon values will be included in the plot
+ titles. If no data are available, the plot chart will report a warning indicating a problem with collecting data.
+ Data may be unavailable for multiple reasons including ADCIRC model runs that did not compute the quantity of interest
+ or selecting a lat/lon target that are outside the ADCIRC model grid, such as inland.
@@ -529,7 +521,8 @@ export const HelpAboutTray = () => {
- Please note that this feature is not available when in Compare Layers mode.
+ Please note that this feature is only available for water level layers. It is also not available when in Compare
+ Layers mode.
@@ -538,7 +531,7 @@ export const HelpAboutTray = () => {
setIndex(expanded ? 15 : null);
}}>
- How do I compare model run layers?
+ How do I compare ADCIRC model run layers?
@@ -547,13 +540,14 @@ export const HelpAboutTray = () => {
- Select a Model run and layer for the left pane.
- Select a Model run and layer for the right pane.
+ Click on the Compare Layers icon button on the sidebar.
+ Select a ADCIRC model run and layer for the left pane.
+ Select a ADCIRC model run and layer for the right pane.
Select the Reset button to clear your selections.
Select the Swap button to reposition your selections.
- Note: Adding, removing or altering model runs or layers will automatically
+ Note: Adding, removing or altering ADCIRC model runs or layers will automatically
restore the default view.
@@ -564,8 +558,8 @@ export const HelpAboutTray = () => {
setIndex(expanded ? 16 : null);
}}>
- How do I view or adjust ADCIRC layer colormap
- ranges?
+ How do I view or adjust a ADCIRC model layer colormap
+ range?
@@ -575,20 +569,20 @@ export const HelpAboutTray = () => {
- Users have the ability to change the colormap ranges for ADCIRC layer product types within the "Edit
+ Users have the ability to change the colormap ranges for ADCIRC layer types within the "Edit
ADCIRC Layer Colormaps" section in the Application Settings sidebar.
- The colormap ranges for each layer product are found on the "Basic tab". These settings allow a
- user to specify the minimum and maximum values attributed to the colormap range for that layer product.
+ The colormap ranges for each layer are found on the "Basic tab". These settings allow a
+ user to specify the minimum and maximum values attributed to the colormap range for that ADCIRC model layer.
+ Click on the Application Settings icon button on the sidebar.
Select the Edit ADCIRC Layer Colormaps "Basic" tab.
- Find the layer product range you would like to adjust.
- Use the slider buttons to specify the minimum and maximum color ranges for a layer
- product.
+ Find the ADCIRC model layer range you would like to adjust.
+ Use the slider buttons to specify the minimum and maximum color ranges for a ADCIRC model layer.
@@ -608,19 +602,19 @@ export const HelpAboutTray = () => {
- Users have the ability to view or alter colormap styles for ADCIRC layer product types within the "Edit
+ Users have the ability to view or alter colormap styles for ADCIRC model layer types within the "Edit
ADCIRC Layer Colormaps" section of the Application Settings sidebar.
- The colormap styles for each layer product are found on the "Advanced" tab. These setting allows a user
- to specify the
- values attributed to the colormap for that layer product.
+ The colormap styles for each model layer are found on the "Advanced" tab. These setting allows a user
+ to specify the values attributed to the colormap for that ADCIRC model layer.
+ Click on the Application Settings icon button on the sidebar.
Select the Edit ADCIRC Layer Colormaps "Advanced" tab.
- Choose the layer product type you would like to modify.
+ Choose the ADCIRC model layer type you would like to modify.
Optionally select the colormap style type. "Ramp" is a continuous color gradient,
while "Interval" represent color steps.
Optionally select the colormap number of classes. This value divides the colormap steps
@@ -632,6 +626,37 @@ export const HelpAboutTray = () => {
+ {
+ setIndex(expanded ? 18 : null);
+ }}>
+
+ How do I change the date and time format to reflect my
+ current locale?
+
+
+
+
+ The Application
+ Settings sidebar button.
+
+
+
+ Users have the ability to change the way dates and times are displayed in the Application Settings sidebar.
+
+
+
+ Users can select if they want to see dates and times in UTC format (the default) or by the locale defined within
+ the browser or as defined in the computer's operating system.
+
+
+
+ Click on the Application Settings icon button on the sidebar.
+ Locate the "Select date/time format" section.
+ Use the slider button to switch between UTC or your current time zone.
+
+
+
+
diff --git a/src/components/trays/hurricane/hurricane-card.js b/src/components/trays/hurricane/hurricane-card.js
index 924c8d38..de62e8cf 100644
--- a/src/components/trays/hurricane/hurricane-card.js
+++ b/src/components/trays/hurricane/hurricane-card.js
@@ -9,13 +9,20 @@ import {
import {
Schedule as ClockIcon,
} from '@mui/icons-material';
-import { useLayers } from '@context';
+import { useLayers, useSettings } from '@context';
import { useToggleState } from '@hooks';
+import { getPreferredTimeZone } from "@utils/map-utils";
export const HurricaneCard = ( layer ) => {
const {
- toggleHurricaneLayerVisibility,
+ toggleHurricaneLayerVisibility
} = useLayers();
+
+ /**
+ * use the use UTC value from the settings state
+ */
+ const { useUTC } = useSettings();
+
const expanded = useToggleState(false);
const hlayer = layer.layer;
const isVisible = hlayer.state.visible;
@@ -73,7 +80,7 @@ export const HurricaneCard = ( layer ) => {
sx={{ flex: 1, pl: '50px' }}
>
- { new Date(hlayer.runDate).toUTCString() }
+ { getPreferredTimeZone(hlayer, useUTC.enabled, true)}
Advisory { hlayer.advisory }
diff --git a/src/components/trays/layers/layer-card.js b/src/components/trays/layers/layer-card.js
index 6c944b5f..58d6f1a8 100644
--- a/src/components/trays/layers/layer-card.js
+++ b/src/components/trays/layers/layer-card.js
@@ -12,17 +12,24 @@ import {
KeyboardArrowDown as ExpandIcon,
Schedule as ClockIcon,
} from '@mui/icons-material';
-import { useLayers } from '@context';
+import { useLayers, useSettings } from '@context';
import { useToggleState } from '@hooks';
import { LayerActions } from './layer-card-actions';
import { ActionButton } from '@components/buttons';
import { DeleteLayerButton } from './delete-layer-button';
+import { getPreferredTimeZone } from "@utils/map-utils";
export const LayerCard = ({ layer }) => {
const {
getLayerIcon,
- toggleLayerVisibility2,
+ toggleLayerVisibility2
} = useLayers();
+
+ /**
+ * use the use UTC value from the settings state
+ */
+ const { useUTC } = useSettings();
+
const expanded = useToggleState(false);
const isVisible = layer.state.visible;
@@ -82,7 +89,7 @@ export const LayerCard = ({ layer }) => {
sx={{ flex: 1, pl: '50px' }}
>
- { layer.properties.run_date }
+ { getPreferredTimeZone(layer.properties, useUTC.enabled) }
Cycle { layer.properties.cycle }
diff --git a/src/components/trays/layers/list.js b/src/components/trays/layers/list.js
index b8437f5e..9a654551 100644
--- a/src/components/trays/layers/list.js
+++ b/src/components/trays/layers/list.js
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { Accordion, AccordionDetails, AccordionGroup, Box, Divider, IconButton, Stack } from '@mui/joy';
import { ActionButton } from '@components/buttons';
import { KeyboardArrowDown as ExpandIcon } from '@mui/icons-material';
-import { useLayers } from '@context';
+import { useLayers, useSettings } from '@context';
import { LayerCard } from './layer-card';
import { DeleteModelRunButton } from "@components/trays/layers/delete-layer-button";
import { Typography } from '@mui/joy';
@@ -113,6 +113,9 @@ export const LayersList = () => {
// get a handle to the layer state
const { removeObservations, defaultModelLayers, setDefaultModelLayers, hurricaneTrackLayers, setHurricaneTrackLayers } = useLayers();
+ // use the use UTC value from the settings state
+ const { useUTC } = useSettings();
+
// get the default layers
const layers = [...defaultModelLayers];
@@ -307,7 +310,7 @@ export const LayersList = () => {
- { getHeaderSummary(layer['properties']) }
+ { getHeaderSummary(layer['properties'], useUTC.enabled) }
diff --git a/src/components/trays/model-selection/catalogItems.js b/src/components/trays/model-selection/catalogItems.js
index 602a6393..e2d6b9c6 100644
--- a/src/components/trays/model-selection/catalogItems.js
+++ b/src/components/trays/model-selection/catalogItems.js
@@ -3,6 +3,7 @@ import { AccordionGroup, Accordion, AccordionSummary, AccordionDetails, Stack, C
import PropTypes from 'prop-types';
import { getHeaderSummary } from "@utils/map-utils";
import { useLayers } from "@context/map-context";
+import {useSettings} from "@context";
// set component prop types
CatalogItems.propTypes = { data: PropTypes.any };
@@ -19,9 +20,12 @@ export default function CatalogItems(data) {
const {
removeObservations,
defaultModelLayers,
- setDefaultModelLayers,
+ setDefaultModelLayers
} = useLayers();
+ // use the use UTC value from the settings state
+ const { useUTC } = useSettings();
+
// create some state for what catalog accordian is expanded/not expanded
const [accordianDateIndex, setAccordianDateIndex] = useState(-1);
@@ -170,7 +174,7 @@ export default function CatalogItems(data) {
expanded={accordianDateIndex === itemIndex}
onChange={(event, expanded) => { setAccordianDateIndex(expanded ? itemIndex : null); }}>
- { catalog['id'] }
+ { catalog['id'] } {useUTC.enabled ? '' : '(UTC)' }
{
// loop through the data members and put them away
@@ -188,7 +192,7 @@ export default function CatalogItems(data) {
sx={{ m: .5 }}
key={ mbrIdx }
checked={ getCheckedState(mbr.group) }
- label={ { getHeaderSummary(mbr['properties']) } }
+ label={ { getHeaderSummary(mbr['properties'], useUTC.enabled)} }
onChange={ (event) => handleCBClick( catalog['members'], mbr['group'],
event.target.checked) }
/>
diff --git a/src/components/trays/settings/colormaps/style-edit.js b/src/components/trays/settings/colormaps/style-edit.js
index 62c30d2b..4c7b5888 100644
--- a/src/components/trays/settings/colormaps/style-edit.js
+++ b/src/components/trays/settings/colormaps/style-edit.js
@@ -165,7 +165,7 @@ export const StyleEditor = () => {
// for imperial based values, because the value is always represented
// in it metric form.
const lastQuantity = getFloatNumberFromLabel(colormap.colorMapEntries[lastIndex].label, 1);
- console.log(lastQuantity);
+
if (styleName === MAXWVEL) {
if (unitsType.current === "imperial") {
labelUnit = ((speedType.current === "knots")? " kn" : " mph");
diff --git a/src/components/trays/settings/date-time-format.js b/src/components/trays/settings/date-time-format.js
new file mode 100644
index 00000000..a699d908
--- /dev/null
+++ b/src/components/trays/settings/date-time-format.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { Typography, Switch, Stack } from '@mui/joy';
+import { useSettings } from '@context';
+
+/**
+ *
+ * @returns React.ReactElement
+ * @constructor
+ */
+export const DateTimeFormat = () => {
+ // get the timezone preference
+ const { useUTC } = useSettings();
+
+ // sets the state when the switch is changed
+ const onChange = () => {
+ // set the new state (toggle)
+ useUTC.toggle();
+ };
+
+ // return the control
+ return (
+
+ Select date/time format
+ }
+ >Use your locale
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/trays/settings/index.js b/src/components/trays/settings/index.js
index 21521179..f74b1953 100644
--- a/src/components/trays/settings/index.js
+++ b/src/components/trays/settings/index.js
@@ -5,6 +5,7 @@ import { Tune as SettingsIcon } from '@mui/icons-material';
import { DarkModeToggle } from './dark-mode';
import { BaseMaps } from './basemap';
import { DataRangeEdit } from './colormaps';
+import { DateTimeFormat } from './date-time-format';
import { Units } from './units';
export const icon = ;
@@ -15,14 +16,16 @@ export const trayContents = () => (
Set/Unset Dark Mode
-
+
Select a Basemap
-
+
+
+
Units of measurement
-
- Edit ADCIRC Layer Colormaps
+
+ Edit ADCIRC Layer Colormaps
diff --git a/src/context/settings.js b/src/context/settings.js
index ce6a9fea..3bd9da3f 100644
--- a/src/context/settings.js
+++ b/src/context/settings.js
@@ -10,6 +10,7 @@ import { useColorScheme } from '@mui/joy/styles';
import {
useLocalStorage,
useToggleState,
+ useToggleLocalStorage
} from '@hooks';
import { maxeleStyle, maxwvelStyle, swanStyle } from '@utils';
@@ -37,8 +38,12 @@ export const SettingsProvider = ({ children }) => {
const [storedMaxwvelOpacity, setStoredMaxwvelOpacity] = useLocalStorage('maxwvel_opacity',1.0);
const [storedSwanOpacity, setStoredSwanOpacity] = useLocalStorage('swan_opacity',1.0);
+ // setting for the users UTC vs. Local time zone display
+ const useUTC = useToggleLocalStorage('useUTC', true);
+
// save the units type specified by user - imperial or metric (default)
const [storedUnitsType, setStoredUnitsType] = useLocalStorage('unitsType','metric');
+
// if units type is imperial, need to save wind speed unit - mph or knots
// default for metric is meters/second (mps)
const [storedSpeedType, setStoredSpeedType] = useLocalStorage('speedType','mps');
@@ -48,6 +53,9 @@ export const SettingsProvider = ({ children }) => {
{
return ret_val;
};
+/**
+ * gets the run date formatted based on current user UTC/locale selection
+ *
+ * @param layerProps
+ * @param useUTC
+ * @param longFormat
+ * @returns {string|string}
+ */
+export const getPreferredTimeZone = (layerProps, useUTC, longFormat=false) => {
+ // if the usage needs the full date format
+ if (longFormat) {
+ return useUTC ? new Date(layerProps['runDate']).toUTCString() : new Date(layerProps['insertion_date']).toLocaleString();
+ }
+ // send back the short date format
+ else {
+ // get the date/time by current preference
+ return useUTC ? layerProps['run_date'] : new Date(layerProps['insertion_date']).toLocaleDateString();
+ }
+};
+
/**
* gets the summary header text for the layer groups.
* This takes into account the two types of runs (tropical, synoptic)
@@ -107,9 +127,9 @@ export const getPropertyName = (layerProps, element_name) => {
* @param layerProps
* @returns {string}
*/
-export const getHeaderSummary = (layerProps) => {
+export const getHeaderSummary = (layerProps, useUTC) => {
// get the full accordian summary text
- return layerProps['run_date'] + ': ' +
+ return getPreferredTimeZone(layerProps, useUTC) + ': ' +
((getPropertyName(layerProps, 'stormOrModelEle') === undefined) ? 'Data error' : getPropertyName(layerProps, 'stormOrModelEle').toUpperCase()) +
', ' + getPropertyName(layerProps, 'numberName') + getPropertyName(layerProps, 'numberEle') +
', Type: ' + layerProps['event_type'] +
@@ -186,7 +206,6 @@ export const markClicked = (map, event, id) => {
marker.addTo(map);
};
-
export const markUnclicked = (map, id) => {
map.eachLayer((layer) => {
if (layer.options && layer.options.pane === "markerPane") {