Skip to content

Commit

Permalink
Merge pull request #22 from RENCI/feature/dialog
Browse files Browse the repository at this point in the history
Feature - Base and observation dialogs
  • Loading branch information
lstillwe authored May 3, 2024
2 parents 8e200ab + 1ea6864 commit 9385b20
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 11 deletions.
29 changes: 26 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,19 @@
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@fontsource/inter": "^5.0.16",
"@mui/icons-material": "^5.15.11",
"@mui/joy": "^5.0.0-beta.32",
"@mui/material": "^5.15.11",
"@mui/icons-material": "^5.15.15",
"@mui/joy": "^5.0.0-beta.36",
"@mui/material": "^5.15.15",
"axios": "^1.6.7",
"core-js": "^3.36.0",
"d3": "^7.8.5",
"dotenv": "^16.4.5",
"leaflet": "^1.9.4",
"mapbox-gl": "^3.1.2",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-draggable": "^4.4.6",
"react-leaflet": "^4.2.1",
"react-map-gl": "^7.1.7",
"react-query": "^3.39.3",
Expand Down
24 changes: 19 additions & 5 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import React, { Fragment } from 'react';
import { Map } from '@components/map';
import ObservationDialog from "@components/map/observation-dialog";
import { useLayers } from '@context';
import { Sidebar } from '@components/sidebar';

export const App = () => {
return (
// install the selected observation list from the layer context
const {
selectedObservations
} = useLayers();

return (
<Fragment>
<Map/>
<Sidebar />
</Fragment>
);
{
// for each observation selected
selectedObservations.map (function (obs) {
// render the observation
return <ObservationDialog key={obs.station_name} obs={obs} />;
})
}
<Map />
<Sidebar />
</Fragment>
);
};
4 changes: 4 additions & 0 deletions src/components/map/default-layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const DefaultLayers = () => {
const {
defaultModelLayers,
setDefaultModelLayers,
setSelectedObservations
} = useLayers();

// Create the authorization header
Expand Down Expand Up @@ -81,6 +82,9 @@ export const DefaultLayers = () => {
// from the feature.properties.csv_url and create a fancy plot
console.log("Observation Station '" + feature.properties.location_name + "' clicked");
markClicked(map, e);

// populate selectedObservations list with the newly selected observation point
setSelectedObservations(previous => [...previous, feature.properties]);
});
}
};
Expand Down
33 changes: 33 additions & 0 deletions src/components/map/observation-dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, {Fragment} from 'react';
import PropTypes from 'prop-types';
import BaseFloatingDialog from "@utils/base-floating-dialog";

// define the properties of this component
ObservationDialog.propTypes = {
obs_data: PropTypes.object
};

export default function ObservationDialog(obs_data) {
// TODO: the url is put in here but it will eventually
// return a graph using data from this url
const graphObj = (url) => {
return (
<Fragment>
<div>
{url}
</div>
</Fragment>
);
};

// create an object for the base dialog
const floaterArgs = {title: obs_data.obs.station_name, description: obs_data.obs.location_name, openDialogImmediately:true, "dialogObject": {...graphObj(obs_data.obs.csvurl)}};

// render the dialog.
// the key here will be used to remove the dialog from the selected observation list when the dialog is closed
return (
<Fragment>
<BaseFloatingDialog {...floaterArgs} />
</Fragment>
);
};
6 changes: 6 additions & 0 deletions src/context/map-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export const useLayers = () => useContext(LayersContext);
export const LayersProvider = ({ children }) => {
const [defaultModelLayers, setDefaultModelLayers] = useState([]);
const [filteredModelLayers, setFilteredModelLayers] = useState([]);

// this object contains data for graph rendering
const [selectedObservations, setSelectedObservations] = useState([]);

const [map, setMap] = useState(null);

const toggleLayerVisibility = id => {
Expand Down Expand Up @@ -35,6 +39,8 @@ export const LayersProvider = ({ children }) => {
filteredModelLayers,
setFilteredModelLayers,
toggleLayerVisibility,
selectedObservations,
setSelectedObservations
}}
>
{children}
Expand Down
104 changes: 104 additions & 0 deletions src/utils/base-floating-dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React, {Fragment} from 'react';
import Draggable from 'react-draggable';
import PropTypes from 'prop-types';

import Button from '@mui/material/Button';
import CssBaseline from '@mui/material/CssBaseline';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogActions';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import Paper from '@mui/material/Paper';
import Slide from '@mui/material/Slide';

import { useLayers } from '@context';

// define the properties of this component
BaseFloatingDialog.propTypes = {
title: PropTypes.string,
description: PropTypes.string,
openDialogImmediately: PropTypes.bool,
dialogObject: PropTypes.any
};

/**
* This is a component that displays a floating dialog with the content passed
*
* @param title: string
* @param description: string
* @param openDialogImmediately: boolean
* @param dialogObject: {JSX.Element}
* @returns {JSX.Element}
*/
export default function BaseFloatingDialog({ title, description, openDialogImmediately, dialogObject} ) {
// define the dialog open/close session state
const [open, setOpen] = React.useState(openDialogImmediately);

const {
selectedObservations,
setSelectedObservations
} = useLayers();

/**
* the close dialog handler
*/
const handleClose = () => {
// close the dialog
setOpen(false);

// remove this item from the selected observations list
setSelectedObservations(selectedObservations.filter(item => item.station_name !== title));
};

/**
* configure and render the floating dialog
*/
return (
<Fragment>
<CssBaseline />
<Dialog
aria-labelledby="draggable-dialog-title"
open={open}
onClose={handleClose}
PaperComponent={PaperComponent}
TransitionComponent={Transition}
disableEnforceFocus
style={{ pointerEvents: 'none'}}
PaperProps={{ style: { pointerEvents: 'auto'} }}
sx={{ '.MuiBackdrop-root': { backgroundColor: 'transparent' }}}
>
<DialogTitle sx={{cursor: 'move', backgroundColor: 'lightgray', textAlign: 'center'}} id="draggable-dialog-title"> { "Station: " + title } </DialogTitle>

<DialogContent sx={{backgroundColor: 'lightblue'}}><DialogContentText> { "Location: " + description } </DialogContentText></DialogContent>

<DialogContent sx={{backgroundColor: 'lightgreen'}}>{ dialogObject }</DialogContent>

<DialogActions sx={{backgroundColor: 'lightgray'}}><Button autoFocus onClick={handleClose}> Close </Button></DialogActions>
</Dialog>
</Fragment>
);
};

/**
* This creates a 3D dialog.
*
* @param props
* @returns {JSX.Element}
* @constructor
*/
function PaperComponent(props) {
return (
<Draggable handle="#draggable-dialog-title" cancel={'[class*="MuiDialogContent-root"]'}>
<Paper {...props} />
</Draggable>
);
}

/**
* This creates an animated transition for the dialog that pops up
* @type {React.ForwardRefExoticComponent<React.PropsWithoutRef<{}> & React.RefAttributes<any>>}
*/
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
});

0 comments on commit 9385b20

Please sign in to comment.