Skip to content

Commit

Permalink
Merge pull request #325 from RENCI/issue-73-UTC-on-off
Browse files Browse the repository at this point in the history
UTC/locale date format selection
  • Loading branch information
lstillwe authored Nov 12, 2024
2 parents 5dd4801 + 295c077 commit 8cd9b65
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 130 deletions.
7 changes: 5 additions & 2 deletions src/components/compare-panel/compare-panel.js
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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];

Expand All @@ -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
Expand Down
17 changes: 12 additions & 5 deletions src/components/control-panel/control-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: <MaxElevationIcon />,
Expand All @@ -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];
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -357,10 +364,10 @@ export const ControlPanel = () => {
{metClass === 'tropical'? `Storm Name: ${stormName}` : ''}
</Typography>
<Typography level="body-md" alignSelf="center">
Model run date: {runDate}
Model run date: { runDate }
</Typography>
<Typography level="body-sm" alignSelf="center">
Instance: {instanceName}
Instance: { instanceName }
</Typography>
<Typography level="body-sm" alignSelf="center">
Meteorology: { eventType }
Expand Down
52 changes: 33 additions & 19 deletions src/components/dialog/observation-chart.js
Original file line number Diff line number Diff line change
@@ -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");
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 '';
Expand All @@ -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
Expand Down Expand Up @@ -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"]) {
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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 (
Expand All @@ -338,8 +352,8 @@ function CreateObsChart(c) {
<LineChart margin={{top: 5, right: 10, left: -25, bottom: 5}} data={data} isHide={c.chartProps.isHideLine}>
<CartesianGrid strokeDasharray="1 1"/>

<XAxis interval={get_xtick_interval(data)} angle={-90} height={55} unit={'Z'} tickMargin={27}
tick={{stroke: 'tan', strokeWidth: .5}} dataKey="time" tickFormatter={(value) => formatX_axis(value)}/>
<XAxis interval={get_xtick_interval(data)} angle={-90} height={55} tickMargin={27}
tick={{stroke: 'tan', strokeWidth: .5}} dataKey="time" tickFormatter={(value) => formatX_axis(value, useUTC.enabled)}/>

<ReferenceLine y={0} stroke="Black" strokeDasharray="3 3"/>

Expand Down Expand Up @@ -367,4 +381,4 @@ function CreateObsChart(c) {
}
</Fragment>
);
}
};
19 changes: 10 additions & 9 deletions src/components/map/hurricane-track.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';


Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/components/map/storm-layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion src/components/trays/compare-layers/CompareLayersTray.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const CompareLayersTray = () => {

const {
mapStyle,
useUTC
} = useSettings();

// used to collapse other open accordions
Expand Down Expand Up @@ -339,7 +340,7 @@ export const CompareLayersTray = () => {
onChange={ (event, expanded) => { setAccordionIndex(expanded ? idx : null); }}
>
<AccordionSummary>
<Typography level="body-xs">{ getHeaderSummary(layer['properties']) }</Typography>
<Typography level="body-xs">{ getHeaderSummary(layer['properties'], useUTC.enabled)}</Typography>
</AccordionSummary>

<AccordionDetails>
Expand Down
Loading

0 comments on commit 8cd9b65

Please sign in to comment.