Create the dialog to select the deployment target

This commit is contained in:
Pierre HUBERT 2024-10-09 18:32:29 +02:00
parent e4da44b5ce
commit 386f0439e4
2 changed files with 171 additions and 34 deletions

View File

@ -0,0 +1,117 @@
import {
Button,
Checkbox,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
FormControl,
FormControlLabel,
FormGroup,
FormLabel,
Radio,
RadioGroup,
Typography,
} from "@mui/material";
import React from "react";
import { Device, DeviceApi } from "../api/DeviceApi";
import { OTAUpdate } from "../api/OTAApi";
import { AsyncWidget } from "../widgets/AsyncWidget";
export function DeployOTAUpdateDialogProvider(p: {
update: OTAUpdate;
onClose: () => void;
}): React.ReactElement {
const [devicesList, setDevicesList] = React.useState<Device[] | undefined>();
const loadDevicesList = async () => {
let list = await DeviceApi.ValidatedList();
list = list.filter((e) => e.info.reference == p.update.platform);
setDevicesList(list);
};
const [allDevices, setAllDevices] = React.useState(false);
const [selectedDevices, setSelectedDevices] = React.useState<string[]>([]);
const startDeployment = () => {};
return (
<Dialog open={true} onClose={p.onClose}>
<DialogTitle>
Deploy update <i>{p.update.version}</i> for platform{" "}
<i>{p.update.platform}</i>
</DialogTitle>
<AsyncWidget
loadKey={1}
load={loadDevicesList}
errMsg="Failed to load the list of devices!"
build={() => (
<DialogContent>
<DialogContentText>
You can choose to deploy update to all device or to target only a
part of devices:
</DialogContentText>
<FormControl>
<FormLabel>Gender</FormLabel>
<RadioGroup
name="radio-buttons-group"
value={allDevices}
onChange={(v) => setAllDevices(v.target.value == "true")}
>
<FormControlLabel
value={true}
control={<Radio />}
label="Deploy the update to all the devices of the platform"
/>
<FormControlLabel
value={false}
control={<Radio />}
label="Deploy the update to a limited range of devices"
/>
</RadioGroup>
</FormControl>
{!allDevices && (
<Typography>
There are no devices to which the update can be deployed.
</Typography>
)}
{!allDevices && (
<FormGroup>
{devicesList?.map((d) => (
<FormControlLabel
control={
<Checkbox
checked={selectedDevices.includes(d.id)}
onChange={(_e, v) => {
if (v) {
selectedDevices.push(d.id);
setSelectedDevices([...selectedDevices]);
} else
setSelectedDevices(
selectedDevices.filter((e) => e != d.id)
);
}}
/>
}
label={d.name}
/>
))}
</FormGroup>
)}
</DialogContent>
)}
/>
<DialogActions>
<Button onClick={p.onClose}>Cancel</Button>
<Button
onClick={startDeployment}
autoFocus
disabled={!allDevices && selectedDevices.length == 0}
>
Start deployment
</Button>
</DialogActions>
</Dialog>
);
}

View File

@ -1,3 +1,5 @@
import { mdiFolderUploadOutline } from "@mdi/js";
import Icon from "@mdi/react";
import DeleteIcon from "@mui/icons-material/Delete"; import DeleteIcon from "@mui/icons-material/Delete";
import DownloadIcon from "@mui/icons-material/Download"; import DownloadIcon from "@mui/icons-material/Download";
import FileUploadIcon from "@mui/icons-material/FileUpload"; import FileUploadIcon from "@mui/icons-material/FileUpload";
@ -16,6 +18,7 @@ import {
import { filesize } from "filesize"; import { filesize } from "filesize";
import React from "react"; import React from "react";
import { OTAAPI, OTAUpdate } from "../api/OTAApi"; import { OTAAPI, OTAUpdate } from "../api/OTAApi";
import { DeployOTAUpdateDialogProvider } from "../dialogs/DeployOTAUpdateDialogProvider";
import { UploadUpdateDialog } from "../dialogs/UploadUpdateDialog"; import { UploadUpdateDialog } from "../dialogs/UploadUpdateDialog";
import { useAlert } from "../hooks/context_providers/AlertDialogProvider"; import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider"; import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
@ -110,6 +113,10 @@ function _OTAList(p: {
const loadingMessage = useLoadingMessage(); const loadingMessage = useLoadingMessage();
const snackbar = useSnackbar(); const snackbar = useSnackbar();
const [deployUpdate, setDeployUpdate] = React.useState<
OTAUpdate | undefined
>();
const deleteUpdate = async (update: OTAUpdate) => { const deleteUpdate = async (update: OTAUpdate) => {
if ( if (
!(await confirm( !(await confirm(
@ -135,40 +142,53 @@ function _OTAList(p: {
}; };
return ( return (
<TableContainer component={Paper}> <>
<Table sx={{ minWidth: 650 }} aria-label="simple table"> {deployUpdate && (
<TableHead> <DeployOTAUpdateDialogProvider
<TableRow> update={deployUpdate!}
<TableCell align="center">Platform</TableCell> onClose={() => setDeployUpdate(undefined)}
<TableCell align="center">Version</TableCell> />
<TableCell align="center">File size</TableCell> )}
<TableCell align="center"></TableCell> <TableContainer component={Paper}>
</TableRow> <Table sx={{ minWidth: 650 }} aria-label="simple table">
</TableHead> <TableHead>
<TableBody> <TableRow>
{p.list.map((row, num) => ( <TableCell align="center">Platform</TableCell>
<TableRow hover key={num}> <TableCell align="center">Version</TableCell>
<TableCell align="center">{row.platform}</TableCell> <TableCell align="center">File size</TableCell>
<TableCell align="center">{row.version}</TableCell> <TableCell align="center"></TableCell>
<TableCell align="center">{filesize(row.file_size)}</TableCell>
<TableCell align="center">
<Tooltip title="Download a copy of the firmware">
<RouterLink to={OTAAPI.DownloadOTAUpdateURL(row)}>
<IconButton>
<DownloadIcon />
</IconButton>
</RouterLink>
</Tooltip>
<Tooltip title="Delete firmware update">
<IconButton onClick={() => deleteUpdate(row)}>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow> </TableRow>
))} </TableHead>
</TableBody> <TableBody>
</Table> {p.list.map((row, num) => (
</TableContainer> <TableRow hover key={num}>
<TableCell align="center">{row.platform}</TableCell>
<TableCell align="center">{row.version}</TableCell>
<TableCell align="center">{filesize(row.file_size)}</TableCell>
<TableCell align="center">
<Tooltip title="Deploy the update to devices">
<IconButton onClick={() => setDeployUpdate(row)}>
<Icon path={mdiFolderUploadOutline} size={1} />
</IconButton>
</Tooltip>
<Tooltip title="Download a copy of the firmware">
<RouterLink to={OTAAPI.DownloadOTAUpdateURL(row)}>
<IconButton>
<DownloadIcon />
</IconButton>
</RouterLink>
</Tooltip>
<Tooltip title="Delete firmware update">
<IconButton onClick={() => deleteUpdate(row)}>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
); );
} }