Skip to content

Commit

Permalink
site->run refactor + api restructuring
Browse files Browse the repository at this point in the history
  • Loading branch information
TShapinsky committed Dec 11, 2023
1 parent a5391c0 commit 8e41cc7
Show file tree
Hide file tree
Showing 9 changed files with 746 additions and 851 deletions.
6 changes: 3 additions & 3 deletions alfalfa_web/components/Sites/ErrorDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ import React from "react";
import { Close } from "@mui/icons-material";
import { Dialog, DialogContent, DialogTitle, Grid, IconButton } from "@mui/material";

export const ErrorDialog = ({ onClose, site }) => {
export const ErrorDialog = ({ onClose, run }) => {
return (
<div>
<Dialog fullWidth={true} maxWidth="lg" open={true} onClose={onClose}>
<DialogTitle>
<Grid container justifyContent="space-between" alignItems="center">
<span>{`${site.name} Error Log`}</span>
<span>{`${run.name} Error Log`}</span>
<IconButton onClick={onClose}>
<Close />
</IconButton>
</Grid>
</DialogTitle>
<DialogContent>
<pre style={{ whiteSpace: "pre-wrap" }}>{site.errorLog}</pre>
<pre style={{ whiteSpace: "pre-wrap" }}>{run.errorLog}</pre>
</DialogContent>
</Dialog>
</div>
Expand Down
20 changes: 15 additions & 5 deletions alfalfa_web/components/Sites/PointDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,23 @@ import {
} from "@mui/material";
import ky from "ky";

export const PointDialog = ({ onClose, site }) => {
export const PointDialog = ({ onClose, run }) => {
const [expanded, setExpanded] = useState(false);
const [points, setPoints] = useState();

useEffect(async () => {
const { data: points } = await ky(`/api/v2/sites/${site.id}/points`).json();
setPoints(points);
const { payload: points } = await ky(`/api/v2/runs/${run.id}/points`).json();
await ky(`/api/v2/runs/${run.id}/points/values`)
.json()
.then(({ payload: values }) => {
for (const i in points) {
const point = points[i];
if (point.id in values) {
point.value = values[point.id];
}
}
setPoints(points);
});
}, []);

const handleChange = (pointId) => (event, expanded) => {
Expand All @@ -48,7 +58,7 @@ export const PointDialog = ({ onClose, site }) => {
return (
<div style={{ paddingTop: "2px" }}>
{!points.length ? (
<Typography align="center">— No points associated with site</Typography>
<Typography align="center">— No points associated with run</Typography>
) : (
points.sort(sortPoints).map((point, i) => {
return (
Expand Down Expand Up @@ -90,7 +100,7 @@ export const PointDialog = ({ onClose, site }) => {
<Dialog fullWidth={true} maxWidth="lg" open={true} onClose={onClose}>
<DialogTitle>
<Grid container justifyContent="space-between" alignItems="center">
<span>{`${site.name} Points`}</span>
<span>{`${run.name} Points`}</span>
<IconButton onClick={onClose}>
<Close />
</IconButton>
Expand Down
100 changes: 48 additions & 52 deletions alfalfa_web/components/Sites/Sites.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,72 +9,72 @@ import { StartDialog } from "./StartDialog";
export const Sites = () => {
const [loading, setLoading] = useState(true);
const [selected, setSelected] = useState([]);
const [sites, setSites] = useState([]);
const [runs, setRuns] = useState([]);
const [showErrorDialog, setShowErrorDialog] = useState(null);
const [showPointDialog, setShowPointDialog] = useState(null);
const [showStartDialog, setShowStartDialog] = useState(null);

const validStates = {
start: ["ready"],
stop: ["preprocessing", "starting", "started", "running", "stopping"],
remove: ["ready", "complete", "error"],
download: ["ready", "complete", "error"]
start: ["READY"],
stop: ["PREPROCESSING", "STARTING", "STARTED", "RUNNING", "STOPPING"],
remove: ["READY", "COMPLETE", "ERROR"],
download: ["READY", "COMPLETE", "ERROR"]
};

const fetchSites = async () => {
const { data: sites } = await ky("/api/v2/runs").json();
setSites(sites);
const fetchRuns = async () => {
const { payload: runs } = await ky("/api/v2/runs").json();
setRuns(runs);
setLoading(false);
};

useEffect(() => {
fetchSites();
const id = setInterval(fetchSites, 1000);
fetchRuns();
const id = setInterval(fetchRuns, 1000);

return () => clearInterval(id);
}, []);

const isSelected = (siteRef) => selected.includes(siteRef);
const isSelected = (runId) => selected.includes(runId);

const selectedSites = () => sites.filter(({ id }) => selected.includes(id));
const selectedRuns = () => runs.filter(({ id }) => selected.includes(id));

const handleRowClick = (event, siteRef) => {
const newSelected = selected.includes(siteRef) ? selected.filter((id) => id !== siteRef) : [...selected, siteRef];
const handleRowClick = (event, runId) => {
const newSelected = selected.includes(runId) ? selected.filter((id) => id !== runId) : [...selected, runId];
setSelected(newSelected);
};

const isStartButtonDisabled = () => {
return !selectedSites().some(({ status }) => validStates.start.includes(status));
return !selectedRuns().some(({ status }) => validStates.start.includes(status));
};

const isStopButtonDisabled = () => {
return !selectedSites().some(({ status }) => validStates.stop.includes(status));
return !selectedRuns().some(({ status }) => validStates.stop.includes(status));
};

const isRemoveButtonDisabled = () => {
return !selectedSites().some(({ status }) => validStates.remove.includes(status));
return !selectedRuns().some(({ status }) => validStates.remove.includes(status));
};

const isDownloadButtonDisabled = () => {
return !selectedSites().some(({ status }) => validStates.download.includes(status));
return !selectedRuns().some(({ status }) => validStates.download.includes(status));
};

const handleOpenErrorDialog = (event, site) => {
const handleOpenErrorDialog = (event, run) => {
event.stopPropagation();
setShowErrorDialog(site);
setShowErrorDialog(run);
};

const handleOpenPointDialog = (event, site) => {
const handleOpenPointDialog = (event, run) => {
event.stopPropagation();
setShowPointDialog(site);
setShowPointDialog(run);
};

const handleStartSimulation = (startDatetime, endDatetime, timescale, realtime, externalClock) => {
selectedSites()
selectedRuns()
.filter(({ status }) => validStates.start.includes(status))
.map(async ({ id }) => {
await ky
.post(`/api/v2/sites/${id}/start`, {
.post(`/api/v2/runs/${id}/start`, {
json: {
startDatetime,
endDatetime,
Expand All @@ -88,23 +88,23 @@ export const Sites = () => {
};

const handleStopSimulation = () => {
selectedSites()
selectedRuns()
.filter(({ status }) => validStates.stop.includes(status))
.map(async ({ id }) => {
await ky.post(`/api/v2/sites/${id}/stop`).json();
await ky.post(`/api/v2/runs/${id}/stop`).json();
});
};

const handleRemoveSite = () => {
selectedSites()
const handleRemoveRun = () => {
selectedRuns()
.filter(({ status }) => validStates.remove.includes(status))
.map(async ({ id }) => {
await ky.delete(`/api/v2/sites/${id}`).json();
await ky.delete(`/api/v2/runs/${id}`).json();
});
};

const handleDownloadSite = async () => {
const ids = selectedSites()
const handleDownloadRun = async () => {
const ids = selectedRuns()
.filter(({ status }) => validStates.download.includes(status))
.map(({ id }) => id);

Expand All @@ -118,8 +118,8 @@ export const Sites = () => {

return (
<Grid container direction="column">
{showErrorDialog && <ErrorDialog site={showErrorDialog} onClose={() => setShowErrorDialog(null)} />}
{showPointDialog && <PointDialog site={showPointDialog} onClose={() => setShowPointDialog(null)} />}
{showErrorDialog && <ErrorDialog run={showErrorDialog} onClose={() => setShowErrorDialog(null)} />}
{showPointDialog && <PointDialog run={showPointDialog} onClose={() => setShowPointDialog(null)} />}
{showStartDialog && (
<StartDialog onStartSimulation={handleStartSimulation} onClose={() => setShowStartDialog(null)} />
)}
Expand All @@ -136,33 +136,33 @@ export const Sites = () => {
</TableRow>
</TableHead>
<TableBody>
{sites.map((site) => {
{runs.map((run) => {
return (
<TableRow
key={site.id}
key={run.id}
selected={false}
style={{ cursor: "default" }}
onClick={(event) => handleRowClick(event, site.id)}>
onClick={(event) => handleRowClick(event, run.id)}>
<TableCell padding="checkbox">
<Checkbox checked={isSelected(site.id)} />
<Checkbox checked={isSelected(run.id)} />
</TableCell>
<TableCell padding="none">{site.name}</TableCell>
<TableCell>{site.id}</TableCell>
<TableCell padding="none">{run.name}</TableCell>
<TableCell>{run.id}</TableCell>
<TableCell>
{site.status === "error" && site.errorLog ? (
{run.status === "error" && run.errorLog ? (
<Button
variant="text"
style={{ marginLeft: -9 }}
onClick={(event) => handleOpenErrorDialog(event, site)}>
{site.status.toUpperCase()}
onClick={(event) => handleOpenErrorDialog(event, run)}>
{run.status.toUpperCase()}
</Button>
) : (
site.status.toUpperCase()
run.status.toUpperCase()
)}
</TableCell>
<TableCell>{site.datetime}</TableCell>
<TableCell>{run.datetime}</TableCell>
<TableCell>
<IconButton onClick={(event) => handleOpenPointDialog(event, site)}>
<IconButton onClick={(event) => handleOpenPointDialog(event, run)}>
<MoreVert />
</IconButton>
</TableCell>
Expand All @@ -189,17 +189,13 @@ export const Sites = () => {
</Button>
</Grid>
<Grid item>
<Button variant="contained" disabled={isRemoveButtonDisabled()} onClick={handleRemoveSite} sx={{ m: 1 }}>
<Button variant="contained" disabled={isRemoveButtonDisabled()} onClick={handleRemoveRun} sx={{ m: 1 }}>
Remove Test Case
</Button>
</Grid>
<Grid item>
<Button
variant="contained"
disabled={isDownloadButtonDisabled()}
onClick={handleDownloadSite}
sx={{ m: 1 }}>
Download Site
<Button variant="contained" disabled={isDownloadButtonDisabled()} onClick={handleDownloadRun} sx={{ m: 1 }}>
Download Run
</Button>
</Grid>
</Grid>
Expand Down
Loading

0 comments on commit 8e41cc7

Please sign in to comment.