diff --git a/central_frontend/src/dialogs/DeployOTAUpdateDialogProvider.tsx b/central_frontend/src/dialogs/DeployOTAUpdateDialogProvider.tsx new file mode 100644 index 0000000..0756ca0 --- /dev/null +++ b/central_frontend/src/dialogs/DeployOTAUpdateDialogProvider.tsx @@ -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(); + + 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([]); + + const startDeployment = () => {}; + return ( + + + Deploy update {p.update.version} for platform{" "} + {p.update.platform} + + ( + + + You can choose to deploy update to all device or to target only a + part of devices: + + + + Gender + setAllDevices(v.target.value == "true")} + > + } + label="Deploy the update to all the devices of the platform" + /> + } + label="Deploy the update to a limited range of devices" + /> + + + {!allDevices && ( + + There are no devices to which the update can be deployed. + + )} + {!allDevices && ( + + {devicesList?.map((d) => ( + { + if (v) { + selectedDevices.push(d.id); + setSelectedDevices([...selectedDevices]); + } else + setSelectedDevices( + selectedDevices.filter((e) => e != d.id) + ); + }} + /> + } + label={d.name} + /> + ))} + + )} + + )} + /> + + + + + + ); +} diff --git a/central_frontend/src/routes/OTARoute.tsx b/central_frontend/src/routes/OTARoute.tsx index 4a11813..8d366ba 100644 --- a/central_frontend/src/routes/OTARoute.tsx +++ b/central_frontend/src/routes/OTARoute.tsx @@ -1,3 +1,5 @@ +import { mdiFolderUploadOutline } from "@mdi/js"; +import Icon from "@mdi/react"; import DeleteIcon from "@mui/icons-material/Delete"; import DownloadIcon from "@mui/icons-material/Download"; import FileUploadIcon from "@mui/icons-material/FileUpload"; @@ -16,6 +18,7 @@ import { import { filesize } from "filesize"; import React from "react"; import { OTAAPI, OTAUpdate } from "../api/OTAApi"; +import { DeployOTAUpdateDialogProvider } from "../dialogs/DeployOTAUpdateDialogProvider"; import { UploadUpdateDialog } from "../dialogs/UploadUpdateDialog"; import { useAlert } from "../hooks/context_providers/AlertDialogProvider"; import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider"; @@ -110,6 +113,10 @@ function _OTAList(p: { const loadingMessage = useLoadingMessage(); const snackbar = useSnackbar(); + const [deployUpdate, setDeployUpdate] = React.useState< + OTAUpdate | undefined + >(); + const deleteUpdate = async (update: OTAUpdate) => { if ( !(await confirm( @@ -135,40 +142,53 @@ function _OTAList(p: { }; return ( - - - - - Platform - Version - File size - - - - - {p.list.map((row, num) => ( - - {row.platform} - {row.version} - {filesize(row.file_size)} - - - - - - - - - - deleteUpdate(row)}> - - - - + <> + {deployUpdate && ( + setDeployUpdate(undefined)} + /> + )} + +
+ + + Platform + Version + File size + - ))} - -
-
+ + + {p.list.map((row, num) => ( + + {row.platform} + {row.version} + {filesize(row.file_size)} + + + setDeployUpdate(row)}> + + + + + + + + + + + + deleteUpdate(row)}> + + + + + + ))} + + + + ); }