Skip to content

Commit

Permalink
Merge pull request #76 from RENCI/model-selection-data
Browse files Browse the repository at this point in the history
Model selection data
  • Loading branch information
lstillwe authored Jun 6, 2024
2 parents b5d55f7 + 18ea09f commit 69fc26e
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 76 deletions.
2 changes: 1 addition & 1 deletion src/components/dialog/base-floating-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default function BaseFloatingDialog({ title, dialogObject, dataKey, dataL

<DialogContent sx={{backgroundColor: 'white', fontSize: 14, m: 0, width: 590, height: 350 }}>{ dialogObject }</DialogContent>

<DialogActions sx={{backgroundColor: 'lightgray', height: 35, m: 0, p: 1}}><Button style={{fontSize: 14}} autoFocus onClick={handleClose}> Close </Button></DialogActions>
<DialogActions sx={{backgroundColor: 'lightgray', height: 35, m: 0, p: 1}}><Button style={{fontSize: 14}} autoFocus onClick={ handleClose }> Close </Button></DialogActions>
</Dialog>
</Fragment>
);
Expand Down
6 changes: 3 additions & 3 deletions src/components/dialog/observation-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export const ObservationDialog = (obs_data) => {

// create a data object for the base dialog to use to render
const floaterArgs = {
title: obs_data.obs.location_name,
dialogObject: {...graphObj(obs_data.obs.csvurl)},
dataKey: obs_data.obs.station_name,
title: obs_data.obs['location_name'],
dialogObject: {...graphObj(obs_data.obs['csvurl'])},
dataKey: obs_data.obs['station_name'],
dataList: selectedObservations,
setDataList: setSelectedObservations,
map: map
Expand Down
61 changes: 39 additions & 22 deletions src/components/model-selection/catalogItems.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React, {Fragment, useState} from "react";
import PropTypes from 'prop-types';
import {AccordionGroup, Accordion, AccordionSummary, AccordionDetails, Stack} from '@mui/joy';
import {AccordionGroup, Accordion, AccordionSummary, AccordionDetails, Stack, Checkbox} from '@mui/joy';

// set component prop types
CatalogItems.propTypes = { data: PropTypes.any};

/**
* returns a list of drop down options for that data/type.
Expand All @@ -10,23 +13,24 @@ import {AccordionGroup, Accordion, AccordionSummary, AccordionDetails, Stack} fr
* @constructor
*/
export default function CatalogItems(data) {
// set component prop types
CatalogItems.propTypes = { data: PropTypes.any };

// create some state for what catalog accordian is expanded/not expanded
const [accordianIndex, setAccordianIndex] = useState(-1);
const [accordianDateIndex, setAccordianDateIndex] = useState(-1);

// variables for the met-class type data
let numberName = '';
let numberElement = '';

// do not render if there is no data
if (data.data != null) {
// if there is a warning getting the result
// if there was a warning getting the result
if (data.data['Warning'] !== undefined) {
return (
<div>
Warning: {data.data['Warning']}
</div>
);
}
// if there is an error getting the result
// if there was an error getting the result
else if(data.data['Error'] !== undefined) {
return (
<div>
Expand All @@ -36,34 +40,47 @@ export default function CatalogItems(data) {
}
// return all the data cards
else {
// save the name of the element for advisory or cycle numbers
if (data.isTropical) {
numberName = ' Advisory: ';
numberElement = 'advisory_number';
}
else if (!data.isTropical) {
numberName = ' Cycle: ';
numberElement = 'cycle';
}

// render the results of the data query
return (
<Fragment>
<AccordionGroup sx={{maxWidth: 410, size: "sm", variant: "soft"}}>
<AccordionGroup sx={{maxWidth: 415, size: "sm", variant: "soft"}}>
{
data
.data['catalog']
.filter(catalogs => catalogs !== "")
.map((catalog, itemIndex) =>
data.data['catalog']
.filter(catalogs => catalogs !== "")
.map(
(catalog, itemIndex) =>
(
<Stack key={ itemIndex } spacing={1}>
<Stack key={ itemIndex } spacing={ 1 }>
<Accordion
key={ itemIndex }
sx={{ p: 0 }}
expanded={accordianIndex === itemIndex}
expanded={accordianDateIndex === itemIndex}
onChange={(event, expanded) => {
setAccordianIndex(expanded ? itemIndex : null);
setAccordianDateIndex(expanded ? itemIndex : null);
}}>

<AccordionSummary>
Model date: {catalog['id']}
{catalog['id']}
</AccordionSummary>

<AccordionDetails>
{catalog['members'].map((member, memberIndex) => (
<Stack key={ memberIndex }>
{member['id'] }
</Stack>
))}
{ catalog['members']
.filter((val, idx, self) => (
idx === self.findIndex((t)=> (
t['group'] === val['group']))))
.map((member, memberIndex) => (
<Checkbox sx={{ m: .5 }} key={ memberIndex } label={ numberName + member['properties'][numberElement] + ' (' + member['properties']['grid_type'] + ')' }/>
))
}
</AccordionDetails>
</Accordion>
</Stack>
Expand Down
64 changes: 40 additions & 24 deletions src/components/model-selection/synopticTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ import axios from 'axios';
import DropDownOptions from "@model-selection/DropDownOptions";
import CatalogItems from "@model-selection/catalogItems";

/**
* Form to filter/selt synoptic runs
*
* @returns {JSX.Element}
* @constructor
*/
export const SynopticTabForm = () => {
// declare all state variables for the synoptic tab dropdown data
const [synopticDate, setSynopticDate] = useState('');
const [synopticCycle, setSynopticCycle] = useState('');
const [synopticGrid, setSynopticGrid] = useState('');
const [synopticInstance, setSynopticInstance] = useState('');
const [synopticDate, setSynopticDate] = useState(null);
const [synopticCycle, setSynopticCycle] = useState(null);
const [synopticGrid, setSynopticGrid] = useState(null);
const [synopticInstance, setSynopticInstance] = useState(null);

// init the data urls
const rootUrl = `${process.env.REACT_APP_UI_DATA_URL}`;
Expand All @@ -31,19 +37,15 @@ export const SynopticTabForm = () => {
* @param event
*/
const formSynopticSubmit = (event) => {
// dont do the usual form submit operations
// avoid doing the usual form submit operations
event.preventDefault();

// gather all the form data
const formData = new FormData(event.target);
const formJson = Object.fromEntries(formData.entries());

// build the query string from the submitted form data
const queryString =
((formJson['synoptic-date'] !== "") ? '&run_date=' + formJson['synoptic-date'] : '') +
((formJson['synoptic-cycle'] !== "") ? '&cycle=' + formJson['synoptic-cycle'] : '') +
((formJson['synoptic-grid'] !== "") ? '&grid_type=' + formJson['synoptic-grid'] : '') +
((formJson['synoptic-instance'] !== "") ? '&instance=' + formJson['synoptic-instance'] : '');
((synopticDate) ? '&run_date=' + synopticDate.toISOString() : '') +
((synopticCycle) ? '&cycle=' + synopticCycle : '') +
((synopticGrid) ? '&grid_type=' + synopticGrid : '') +
((synopticInstance) ? '&instance=' + synopticInstance : '');

// set the url to go after ui data
setFinalDataUrl(rootUrl + baseDataUrl + queryString);
Expand Down Expand Up @@ -90,14 +92,28 @@ export const SynopticTabForm = () => {
*/
useEffect(() => {
// build the new data url
buildDataUrl();
buildDropDownDataUrl();
});

/**
* resets the form
*/
function resetForm() {
// reset the form controls
setSynopticDate(null);
setSynopticCycle(null);
setSynopticGrid(null);
setSynopticInstance(null);

// and clear out any data retrieved
setCatalogData(null);
}

/**
* method to build the query sting to get data
*
*/
function buildDataUrl() {
function buildDropDownDataUrl() {
// init the query string
let query_string = '';

Expand All @@ -113,7 +129,7 @@ export const SynopticTabForm = () => {
// set the query string
if (synopticInstance !== '' && synopticInstance != null) { query_string += '&instance_name=' + synopticInstance; }

// set the pulldown data url. this will trigger a data gathering
// set the pulldown data url. this will trigger data gathering
setFinalDataUrl(rootUrl + basePulldownUrl + query_string);
}

Expand All @@ -125,7 +141,7 @@ export const SynopticTabForm = () => {
*/
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]);
return !dropDownData['run_dates'].includes(date.toISOString().split("T")[0]);
};

/**
Expand All @@ -139,34 +155,34 @@ export const SynopticTabForm = () => {
<DatePicker
name="synoptic-date"
shouldDisableDate={ disableDate }
slotProps={{textField: {size: 'small'}, field: { clearable: true }}}
onChange={ (newValue) => { setSynopticDate(newValue); }}/>
slotProps={{ textField: {size: 'small'}, field: { clearable: true } }}
onChange={ (newValue) => { setSynopticDate(newValue.$d); }}/>
</LocalizationProvider>

<Select name="synoptic-cycle" placeholder="Please select a cycle" onChange={(e, newValue) => {
<Select name="synoptic-cycle" value={ synopticCycle } placeholder="Please select a cycle" onChange={(e, newValue) => {
setSynopticCycle(newValue); }}>
<DropDownOptions data={dropDownData} type={'cycles'} />
</Select>

<Select name="synoptic-grid" placeholder="Please select a grid" onChange={(e, newValue) => {
<Select name="synoptic-grid" value={ synopticGrid } placeholder="Please select a grid" onChange={(e, newValue) => {
setSynopticGrid(newValue); }}>
<DropDownOptions data={dropDownData} type={'grid_types'} />
</Select>

<Select name="synoptic-instance" placeholder="Please select an instance" onChange={(e, newValue) => {
<Select name="synoptic-instance" value={ synopticInstance } placeholder="Please select an instance" onChange={(e, newValue) => {
setSynopticInstance(newValue); }}>
<DropDownOptions data={dropDownData} type={'instance_names'} />
</Select>

<Button type="submit">Submit</Button>
<Button type="reset">Reset</Button>
<Button type="reset" onClick={ resetForm }>Reset</Button>
</Stack>

<Divider sx={{m: 2}}/>

<Stack sx={{maxHeight: "400px", overflow: "auto"}}>
{
<CatalogItems data={ catalogData } />
<CatalogItems data={ catalogData } isTropical = { false } />
}
</Stack>
</form>
Expand Down
55 changes: 30 additions & 25 deletions src/components/model-selection/tropicalTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ import axios from 'axios';
import DropDownOptions from "@model-selection/DropDownOptions";
import CatalogItems from "@model-selection/catalogItems";

/**
* Form to filter/selt tropical runs
*
* @returns {JSX.Element}
* @constructor
*/
export const TropicalTabForm = () => {
// declare state variables for all tropical tab controls
const [tropicalStorm, setTropicalStorm] = useState('');
const [tropicalAdvisory, setTropicalAdvisory] = useState('');
const [tropicalGrid, setTropicalGrid] = useState('');
const [tropicalInstance, setTropicalInstance] = useState('');
const [tropicalStorm, setTropicalStorm] = useState(null);
const [tropicalAdvisory, setTropicalAdvisory] = useState(null);
const [tropicalGrid, setTropicalGrid] = useState(null);
const [tropicalInstance, setTropicalInstance] = useState(null);


// init the data urls
Expand All @@ -29,19 +35,15 @@ export const TropicalTabForm = () => {
* @param event
*/
const formTropicalHandler = (event) => {
// dont do the usual submit operations
// avoid doing the usual submit operations
event.preventDefault();

// gather all the form data
const formData = new FormData(event.target);
const formJson = Object.fromEntries(formData.entries());

// build the query string from the submitted form data
const queryString =
((formJson['tropical-storm-name'] !== "") ? '&storm_name=' + formJson['tropical-storm-name'] : '') +
((formJson['tropical-advisory'] !== "") ? '&advisory_number=' + formJson['tropical-advisory'] : '') +
((formJson['tropical-grid'] !== "") ? '&grid_type=' + formJson['tropical-grid'] : '') +
((formJson['tropical-instance'] !== "") ? '&instance=' + formJson['tropical-instance'] : '');
((tropicalStorm) ? '&storm_name=' + tropicalStorm : '') +
((tropicalAdvisory) ? '&advisory_number=' + tropicalAdvisory : '') +
((tropicalGrid) ? '&grid_type=' + tropicalGrid : '') +
((tropicalInstance) ? '&instance=' + tropicalInstance : '');

// set the url to go after ui data
setFinalDataUrl(rootUrl + baseDataUrl + queryString);
Expand Down Expand Up @@ -95,14 +97,17 @@ export const TropicalTabForm = () => {
* resets the form
*/
function resetForm() {
setTropicalStorm('');
setTropicalAdvisory('');
setTropicalGrid('');
setTropicalInstance('');

buildDropDownDataUrl();
// reset the form controls
setTropicalStorm(null);
setTropicalAdvisory(null);
setTropicalGrid(null);
setTropicalInstance(null);

// and clear out any data retrieved
setCatalogData(null);
}

// buildDropDownDataUrl();
/**
* method to build the query sting to get data
*
Expand All @@ -123,7 +128,7 @@ export const TropicalTabForm = () => {
// set the instance query string
if (tropicalInstance !== '' && tropicalInstance !== null) {query_string += '&instance_name=' + tropicalInstance; }

// set the pulldown data url. this will trigger a data gathering
// set the pulldown data url. this will trigger a data pull
setFinalDataUrl(rootUrl + basePulldownUrl + query_string);
}

Expand All @@ -134,19 +139,19 @@ export const TropicalTabForm = () => {
<Fragment>
<form name={"Tropical"} onSubmit={formTropicalHandler}>
<Stack spacing={1}>
<Select name="tropical-storm-name" defaultValue="" placeholder="Please select a tropical storm" onChange={(e, newValue) => {
<Select name="tropical-storm-name" value={ tropicalStorm } placeholder="Please select a tropical storm" onChange={(e, newValue) => {
setTropicalStorm(newValue); }}>
<DropDownOptions data={dropDownData} type={'storm_names'} />
</Select>
<Select name="tropical-advisory" placeholder="Please select an advisory" onChange={(e, newValue) => {
<Select name="tropical-advisory" value={ tropicalAdvisory } placeholder="Please select an advisory" onChange={(e, newValue) => {
setTropicalAdvisory(newValue); }}>
<DropDownOptions data={ dropDownData } type={ 'advisory_numbers' } />
</Select>
<Select name="tropical-grid" placeholder="Please select a grid" onChange={(e, newValue) => {
<Select name="tropical-grid" value={ tropicalGrid } placeholder="Please select a grid" onChange={(e, newValue) => {
setTropicalGrid(newValue); }}>
<DropDownOptions data={ dropDownData } type={ 'grid_types' } />
</Select>
<Select name="tropical-instance" placeholder="Please select an instance" onChange={(e, newValue) => {
<Select name="tropical-instance" value={ tropicalInstance } placeholder="Please select an instance" onChange={(e, newValue) => {
setTropicalInstance(newValue); }}>
<DropDownOptions data={ dropDownData } type={ 'instance_names' } />
</Select>
Expand All @@ -159,7 +164,7 @@ export const TropicalTabForm = () => {

<Stack sx={{maxHeight: "400px", overflow: "auto"}}>
{
<CatalogItems data={ catalogData } />
<CatalogItems data={ catalogData } isTropical={ true } />
}
</Stack>
</form>
Expand Down
2 changes: 1 addition & 1 deletion src/components/trays/hurricanes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ import { Storm as HurricaneIcon } from '@mui/icons-material';

export const icon = <HurricaneIcon />;
export const title = 'Hurricanes';
export const trayContents = () => <div>hurricanes tray</div>;
export const trayContents = () => <div style={{padding: "10px"}}>Coming soon!</div>;

0 comments on commit 69fc26e

Please sign in to comment.