Files
ota-admin-portal/src/components/Manifest/Deploy/index.jsx
2022-11-17 11:45:37 -08:00

214 lines
6.4 KiB
JavaScript

import { Button, FormControlLabel, Grid, Switch, Typography } from "@material-ui/core";
import clsx from "clsx";
import React, { useEffect, useState } from "react";
import { Redirect, useParams } from "react-router";
import { logger } from "../../../services/monitoring";
import { LocalDateTimeString } from "../../../utils/dates";
import { Permissions } from "../../../utils/roles";
import { CarUpdatesProvider, useCarUpdatesContext } from "../../Contexts/CarUpdatesContext";
import { FleetProvider } from "../../Contexts/FleetContext";
import { ManifestsProvider, useManifestsContext } from "../../Contexts/ManifestsContext";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import { VehicleProvider } from "../../Contexts/VehicleContext";
import CarSelectionTable from "../../Controls/CarSelectionTable";
import FleetSelectionTable from "../../Controls/FleetSelectionTable";
import { RoleWrap } from "../../Controls/RoleWrap";
import SearchField from "../../Controls/SearchField";
import useStyles from "../../useStyles";
const CAR_UPDATE = false;
const FLEET_UPDATE = true;
const MainForm = () => {
const [updateType, setUpdateType] = useState(CAR_UPDATE);
const {manifest_id} = useParams();
const {getManifests, manifests, busy} = useManifestsContext();
const {deployCarUpdates, deployFleetUpdates} = useCarUpdatesContext();
const {
groups,
providers,
token: {
idToken: {jwtToken: token},
},
} = useUserContext();
const {setMessage, setTitle, setSitePath} = useStatusContext();
const [manifestName, setManifestName] = useState("");
const [version, setVersion] = useState("");
const [createDate, setCreateDate] = useState("");
const [selected, setSelected] = useState([]);
const [search, setSearch] = useState("");
const [redirect, setRedirect] = useState("");
const classes = useStyles();
const handleChange = (_) => {
setSelected([]);
setUpdateType(updateType === CAR_UPDATE ? FLEET_UPDATE : CAR_UPDATE);
}
const handleSearch = (query) => {
setSelected([]);
setSearch(query);
};
const handleSelectAll = (cars) => {
setSelected(cars);
};
const handleSelect = (event, key) => {
try {
let newSelected;
if (event.target.checked) {
newSelected = [...selected];
newSelected.push(key);
} else {
newSelected = selected.filter((vinOrName) => vinOrName !== key);
}
setSelected(newSelected);
} catch (e) {
logger.warn(e.stack);
}
};
const onSubmit = async (event) => {
try {
event.preventDefault();
const data = {
manifest_id: parseInt(manifest_id),
}
if (updateType === CAR_UPDATE) {
data.vins = selected;
await deployCarUpdates(data, token);
} else {
data.fleet_names = selected;
await deployFleetUpdates(data, token);
}
setMessage(
`Deployed ${manifestName} ${version} to ${selected.length} cars`
);
setRedirect(`/package-status/${manifest_id}`);
} catch (e) {
setMessage(e.message);
logger.warn(e.stack);
}
};
const getData = async () => {
try {
getManifests({id: parseInt(manifest_id)}, token);
} catch (e) {
setMessage(e.message);
logger.warn(e.stack);
}
};
useEffect(() => {
getData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [token]);
useEffect(() => {
const title = `Deploy ${manifestName} ${version}`;
setTitle(title);
setSitePath([
{
label: "Deployments",
link: "/packages",
},
{
label: title,
},
]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [manifestName, version]);
useEffect(() => {
if (!manifests || manifests.length === 0) return;
const data = manifests[0];
setManifestName(data.name);
setVersion(data.version);
setCreateDate(LocalDateTimeString(data.created));
}, [manifests]);
if (redirect.length > 0) {
return <Redirect to={redirect}/>;
}
return (
<div className={classes.paper}>
<form className={classes.form} noValidate action="{onSubmit}">
<Typography variant="body2">Created {createDate}.</Typography>
<Grid container className={classes.root} spacing={2}>
<Grid item md={2}>
<div
className={classes.labelInline}
>{`${selected.length} Selected`}</div>
</Grid>
<Grid item md={2} className={classes.textCenterAlign}>
<RoleWrap
groups={groups}
providers={providers}
rolesPerProvider={Permissions.FiskerRead}
>
<FormControlLabel control={<Switch
checked={updateType === CAR_UPDATE}
onChange={handleChange}
inputProps={{'aria-label': 'controlled'}}
/>} label="Car(default) or Fleet"/>
</RoleWrap>
</Grid>
<Grid item md={4} className={classes.textCenterAlign}>
<SearchField classes={classes} onSearch={handleSearch}/>
</Grid>
<Grid item md={4} className={classes.textRightAlign}>
<Button
type="submit"
disabled={busy || selected.length === 0}
variant="contained"
color="primary"
className={clsx(classes.formControl, classes.textField)}
onClick={onSubmit}
>
{busy ? "Deploying..." : "Deploy"}
</Button>
</Grid>
</Grid>
{updateType === CAR_UPDATE ?
<VehicleProvider>
<CarSelectionTable
classes={classes}
token={token}
multiSelect={true}
search={{search}}
selected={selected}
onSelect={handleSelect}
onSelectAll={handleSelectAll}
/></VehicleProvider> :
<FleetProvider>
<FleetSelectionTable
classes={classes}
token={token}
multiSelect={true}
search={{search}}
selected={selected}
onSelect={handleSelect}
onSelectAll={handleSelectAll}/>
</FleetProvider>
}
</form>
</div>
);
};
const ManifestDeployForm = () => (
<ManifestsProvider>
<CarUpdatesProvider>
<MainForm/>
</CarUpdatesProvider>
</ManifestsProvider>
);
export default ManifestDeployForm;