diff --git a/src/components/trays/model-selection/catalogItems.js b/src/components/trays/model-selection/catalogItems.js index 1f281a5f..a668f557 100644 --- a/src/components/trays/model-selection/catalogItems.js +++ b/src/components/trays/model-selection/catalogItems.js @@ -135,6 +135,14 @@ export default function CatalogItems(data) { ); } + else if(data.data['catalog'] === undefined || data.data['catalog'] === null) { + return ( +
+ Error: { 'No catalog data retrieved.' } +
+ ); + } + // return all the data cards else { // save the name of the element for tropical storms and advisory numbers diff --git a/src/components/trays/model-selection/synopticTab.js b/src/components/trays/model-selection/synopticTab.js index fea8455d..f5dbc481 100644 --- a/src/components/trays/model-selection/synopticTab.js +++ b/src/components/trays/model-selection/synopticTab.js @@ -1,4 +1,4 @@ -import React, { Fragment, useState, useEffect } from 'react'; +import React, { Fragment, useState, useEffect, useMemo } from 'react'; import { Button, Divider, Select, Stack } from '@mui/joy'; import { DatePicker } from '@mui/x-date-pickers'; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; @@ -8,6 +8,7 @@ import axios from 'axios'; import DropDownOptions from "@model-selection/DropDownOptions"; import CatalogItems from "@model-selection/catalogItems"; import { getNamespacedEnvParam, getBrandingHandler } from "@utils/map-utils"; +import dayjs from 'dayjs'; /** * Form to filter/select synoptic runs @@ -18,14 +19,14 @@ import { getNamespacedEnvParam, getBrandingHandler } from "@utils/map-utils"; export const SynopticTabForm = () => { // declare all state variables for the synoptic tab dropdown data - const [synopticDate, setSynopticDate] = useState(null); + const [synopticDate, setSynopticDate] = useState(dayjs(new Date())); const [synopticCycle, setSynopticCycle] = useState(null); const [synopticGrid, setSynopticGrid] = useState(null); const [synopticInstance, setSynopticInstance] = useState(null); // init the data urls const rootUrl = `${ getNamespacedEnvParam('REACT_APP_UI_DATA_URL') }`; - const basePulldownUrl = `get_pulldown_data?met_class=synoptic&use_v3_sp=true${ getBrandingHandler() }`; + const basePulldownUrl = `get_pulldown_data?met_class=synoptic${ getBrandingHandler() }`; const baseDataUrl = `get_ui_data_secure?limit=14&met_class=synoptic&use_v3_sp=true${ getBrandingHandler() }`; const [finalDataUrl, setFinalDataUrl] = useState(rootUrl + basePulldownUrl); @@ -33,6 +34,24 @@ export const SynopticTabForm = () => { const [dropDownData, setDropDownData] = useState(null); const [catalogData, setCatalogData] = useState(null); + // state for the date validation error + const [error, setError] = useState(null); + + const setChangedSynopticDate = (newValue) => { + // if there was a valid date + if (!isNaN(newValue) && newValue !== null) { + //console.log('setChangedSynopticDate Good date: ' + newValue.$d + ', error: ' + error + ', newValue: ' + newValue); + // save the date + setSynopticDate(newValue.$d); + } + // else handle a bad date + else { + //console.log('setChangedSynopticDate Bad date: ' + newValue); + // clear the date + setSynopticDate(null); + } + }; + /** * method to initiate a model search with the filter selections on the synoptic form * @@ -42,6 +61,8 @@ export const SynopticTabForm = () => { // avoid doing the usual form submit operations event.preventDefault(); + //console.log('formSynopticSubmit error: ' + error); + // build the query string from the submitted form data let queryString = ((synopticDate) ? '&run_date=' + synopticDate.toISOString() : '') + @@ -79,27 +100,45 @@ export const SynopticTabForm = () => { }; // make the call to get the data - const {data} = await axios.get(finalDataUrl, requestOptions); + const ret_val = await axios + // make the call to get the data + .get(finalDataUrl, requestOptions) + // use the data returned + .then (( response ) => { + // return the data + return response.data; + }) + .catch (( error ) => { + // make sure we do not render anything + return error.response.status; + }); - // check the request type - if (finalDataUrl.indexOf('get_pulldown_data') !== -1) { - // save the dropdown data - setDropDownData(data); - } - else { - // save the catalog data - setCatalogData(data); + // if (finalDataUrl.indexOf('get_pulldown_data') !== -1) + // console.log('finalDataUrl: ' + finalDataUrl); + + // if there was an error from the web service + if (ret_val !== 500) { + // check the request type to save it to the correct place + if (finalDataUrl.indexOf('get_pulldown_data') !== -1) { + // save the dropdown data + setDropDownData(ret_val); + } + else { + // save the catalog data + setCatalogData(ret_val); + } } + else + // reset the form data + resetForm(); // return something return true; - }, - - refetchOnWindowFocus: false + }, refetchOnWindowFocus: false }); /** - * this will build the data url and will cause a DB hit + * this will build the data url and will cause a web service/DB hit */ useEffect(() => { // build the new data url @@ -159,53 +198,97 @@ export const SynopticTabForm = () => { * @returns {boolean} */ const disableDate = (date) => { - // return false if the date is not found in the list of available dates - return !dropDownData['run_dates'].includes(date.toISOString().split("T")[0]); + if (dropDownData) { + // return false if the date is not found in the list of available dates + return !dropDownData['run_dates'].includes(date.toISOString().split("T")[0]); + } }; + /** + * handles date picker error text + * + * @type {string} + */ + const errorMessage = useMemo(() => { + //console.log('errorMessage error: ' + error); + + switch (error) { + case 'maxDate': { + return 'Please select a date that is not in the future'; + } + + case 'minDate': { + return 'Please select a date after 01/01/2020'; + } + + case 'invalidDate': { + return 'This date is not yet valid'; + } + + case 'shouldDisableDate': { + return 'There is no data available on this date'; + } + + default: { + return ''; + } + } + + }, [error]); + /** * return the rendered component */ return ( -
- - + + + setError(newError) } + disableFuture name="synoptic-date" - shouldDisableDate={disableDate} - slotProps={{textField: {size: 'small'}, field: {clearable: true}}} + shouldDisableDate={ disableDate } + minDate={ dayjs('2023-06-01') } + slotProps={{ + textField: { size: 'small', helperText: errorMessage}, + field: { clearable: true }, + actionBar: { actions: ['clear'] }, + }} + onChange={(newValue) => { - setSynopticDate(newValue.$d); + setChangedSynopticDate(newValue); }}/> + - { setSynopticCycle(newValue); }}> - + - { setSynopticGrid(newValue); }}> - + - { setSynopticInstance(newValue); }}> - + - - + + - {} + { }