Can delete a device relay from UI
This commit is contained in:
parent
f35aac04f6
commit
b0023a5167
@ -39,4 +39,14 @@ export class RelayApi {
|
|||||||
jsonData: relay,
|
jsonData: relay,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a relay configuration
|
||||||
|
*/
|
||||||
|
static async Delete(relay: DeviceRelay): Promise<void> {
|
||||||
|
await APIClient.exec({
|
||||||
|
method: "DELETE",
|
||||||
|
uri: `/relay/${relay.id}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
Grid,
|
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import Grid from "@mui/material/Grid2";
|
||||||
import { TimePicker } from "@mui/x-date-pickers";
|
import { TimePicker } from "@mui/x-date-pickers";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Device, DeviceRelay } from "../api/DeviceApi";
|
import { Device, DeviceRelay } from "../api/DeviceApi";
|
||||||
@ -81,7 +81,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogFormTitle>General info</DialogFormTitle>
|
<DialogFormTitle>General info</DialogFormTitle>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
editable
|
editable
|
||||||
label="Relay name"
|
label="Relay name"
|
||||||
@ -97,7 +97,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
size={ServerApi.Config.constraints.dev_name_len}
|
size={ServerApi.Config.constraints.dev_name_len}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<CheckboxInput
|
<CheckboxInput
|
||||||
editable
|
editable
|
||||||
label="Enable relay"
|
label="Enable relay"
|
||||||
@ -112,7 +112,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
editable
|
editable
|
||||||
label="Priority"
|
label="Priority"
|
||||||
@ -130,7 +130,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
helperText="Relay priority when selecting relays to turn on. 0 = lowest priority"
|
helperText="Relay priority when selecting relays to turn on. 0 = lowest priority"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
editable
|
editable
|
||||||
label="Consumption"
|
label="Consumption"
|
||||||
@ -148,7 +148,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
helperText="Estimated consumption of device powered by relay"
|
helperText="Estimated consumption of device powered by relay"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
editable
|
editable
|
||||||
label="Minimal uptime"
|
label="Minimal uptime"
|
||||||
@ -166,7 +166,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
helperText="Minimal time this relay shall be left on before it can be turned off (in seconds)"
|
helperText="Minimal time this relay shall be left on before it can be turned off (in seconds)"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
editable
|
editable
|
||||||
label="Minimal downtime"
|
label="Minimal downtime"
|
||||||
@ -188,7 +188,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
|
|
||||||
<DialogFormTitle>Daily runtime</DialogFormTitle>
|
<DialogFormTitle>Daily runtime</DialogFormTitle>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<CheckboxInput
|
<CheckboxInput
|
||||||
editable
|
editable
|
||||||
label="Enable minimal runtime"
|
label="Enable minimal runtime"
|
||||||
@ -208,7 +208,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
|
|
||||||
{!!relay.daily_runtime && (
|
{!!relay.daily_runtime && (
|
||||||
<>
|
<>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
editable
|
editable
|
||||||
label="Minimal daily runtime"
|
label="Minimal daily runtime"
|
||||||
@ -231,7 +231,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
helperText="Minimum time, in seconds, that this relay should run each day"
|
helperText="Minimum time, in seconds, that this relay should run each day"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<TimePicker
|
<TimePicker
|
||||||
label="Reset time"
|
label="Reset time"
|
||||||
value={timeOfDay(relay.daily_runtime!.reset_time)}
|
value={timeOfDay(relay.daily_runtime!.reset_time)}
|
||||||
@ -248,7 +248,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<MultipleSelectInput
|
<MultipleSelectInput
|
||||||
label="Catchup hours"
|
label="Catchup hours"
|
||||||
helperText="The hours during which the relay should be turned on to reach expected runtime"
|
helperText="The hours during which the relay should be turned on to reach expected runtime"
|
||||||
@ -278,7 +278,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
|
|
||||||
<DialogFormTitle>Constraints</DialogFormTitle>
|
<DialogFormTitle>Constraints</DialogFormTitle>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<SelectMultipleRelaysInput
|
<SelectMultipleRelaysInput
|
||||||
label="Required relays"
|
label="Required relays"
|
||||||
exclude={[relay.id]}
|
exclude={[relay.id]}
|
||||||
@ -294,7 +294,7 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
helperText="Relays that must be already up for this relay to be started"
|
helperText="Relays that must be already up for this relay to be started"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid size={{ xs: 6 }}>
|
||||||
<SelectMultipleRelaysInput
|
<SelectMultipleRelaysInput
|
||||||
label="Conflicting relays"
|
label="Conflicting relays"
|
||||||
exclude={[relay.id]}
|
exclude={[relay.id]}
|
||||||
|
@ -1,14 +1,32 @@
|
|||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import { IconButton, Tooltip } from "@mui/material";
|
import DeleteIcon from "@mui/icons-material/Delete";
|
||||||
|
import EditIcon from "@mui/icons-material/Edit";
|
||||||
|
import {
|
||||||
|
IconButton,
|
||||||
|
ListItem,
|
||||||
|
ListItemText,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
|
} from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Device, DeviceRelay } from "../../api/DeviceApi";
|
import { Device, DeviceRelay } from "../../api/DeviceApi";
|
||||||
import { DeviceRouteCard } from "./DeviceRouteCard";
|
|
||||||
import { EditDeviceRelaysDialog } from "../../dialogs/EditDeviceRelaysDialog";
|
import { EditDeviceRelaysDialog } from "../../dialogs/EditDeviceRelaysDialog";
|
||||||
|
import { DeviceRouteCard } from "./DeviceRouteCard";
|
||||||
|
import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider";
|
||||||
|
import { useLoadingMessage } from "../../hooks/context_providers/LoadingMessageProvider";
|
||||||
|
import { RelayApi } from "../../api/RelayApi";
|
||||||
|
import { useSnackbar } from "../../hooks/context_providers/SnackbarProvider";
|
||||||
|
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
|
||||||
|
|
||||||
export function DeviceRelays(p: {
|
export function DeviceRelays(p: {
|
||||||
device: Device;
|
device: Device;
|
||||||
onReload: () => void;
|
onReload: () => void;
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
|
const confirm = useConfirm();
|
||||||
|
const loadingMessage = useLoadingMessage();
|
||||||
|
const snackbar = useSnackbar();
|
||||||
|
const alert = useAlert();
|
||||||
|
|
||||||
const [dialogOpen, setDialogOpen] = React.useState(false);
|
const [dialogOpen, setDialogOpen] = React.useState(false);
|
||||||
const [currRelay, setCurrRelay] = React.useState<DeviceRelay | undefined>();
|
const [currRelay, setCurrRelay] = React.useState<DeviceRelay | undefined>();
|
||||||
|
|
||||||
@ -17,6 +35,25 @@ export function DeviceRelays(p: {
|
|||||||
setCurrRelay(undefined);
|
setCurrRelay(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const deleteRelay = async (r: DeviceRelay) => {
|
||||||
|
if (
|
||||||
|
!(await confirm("Do you really want to delete this relay configuration?"))
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await RelayApi.Delete(r);
|
||||||
|
|
||||||
|
p.onReload();
|
||||||
|
snackbar("The relay configuration was successfully deleted!");
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to delete relay!", e);
|
||||||
|
alert(`Failed to delete device relay configuration! ${e}`);
|
||||||
|
} finally {
|
||||||
|
loadingMessage.hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{dialogOpen && (
|
{dialogOpen && (
|
||||||
@ -43,7 +80,39 @@ export function DeviceRelays(p: {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
TODO : relays list ({p.device.relays.length}) relays now)
|
{p.device.relays.length === 0 ? (
|
||||||
|
<Typography style={{ textAlign: "center" }}>
|
||||||
|
No relay configured yet.
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{p.device.relays.map((r, i) => (
|
||||||
|
<ListItem
|
||||||
|
alignItems="flex-start"
|
||||||
|
key={r.id}
|
||||||
|
secondaryAction={
|
||||||
|
<>
|
||||||
|
<Tooltip title="Edit the relay configuration">
|
||||||
|
<IconButton>
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
{i === p.device.relays.length - 1 && (
|
||||||
|
<Tooltip title="Delete the relay configuration">
|
||||||
|
<IconButton onClick={() => deleteRelay(r)}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemText primary={r.name} secondary={"TODO: status"} />
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
</DeviceRouteCard>
|
</DeviceRouteCard>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import DeleteIcon from "@mui/icons-material/Delete";
|
import DeleteIcon from "@mui/icons-material/Delete";
|
||||||
import { Grid, IconButton, Tooltip } from "@mui/material";
|
import { IconButton, Tooltip } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { Device, DeviceApi } from "../../api/DeviceApi";
|
import { Device, DeviceApi } from "../../api/DeviceApi";
|
||||||
@ -11,6 +11,7 @@ import { AsyncWidget } from "../../widgets/AsyncWidget";
|
|||||||
import { SolarEnergyRouteContainer } from "../../widgets/SolarEnergyRouteContainer";
|
import { SolarEnergyRouteContainer } from "../../widgets/SolarEnergyRouteContainer";
|
||||||
import { GeneralDeviceInfo } from "./GeneralDeviceInfo";
|
import { GeneralDeviceInfo } from "./GeneralDeviceInfo";
|
||||||
import { DeviceRelays } from "./DeviceRelays";
|
import { DeviceRelays } from "./DeviceRelays";
|
||||||
|
import Grid from "@mui/material/Grid2";
|
||||||
|
|
||||||
export function DeviceRoute(): React.ReactElement {
|
export function DeviceRoute(): React.ReactElement {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
@ -81,10 +82,10 @@ function DeviceRouteInner(p: {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid size={{ xs: 12, md: 6 }}>
|
||||||
<GeneralDeviceInfo {...p} />
|
<GeneralDeviceInfo {...p} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid size={{ xs: 12, md: 6 }}>
|
||||||
<DeviceRelays {...p} />
|
<DeviceRelays {...p} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -4,7 +4,6 @@ import Avatar from "@mui/material/Avatar";
|
|||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import CssBaseline from "@mui/material/CssBaseline";
|
import CssBaseline from "@mui/material/CssBaseline";
|
||||||
import Grid from "@mui/material/Grid";
|
|
||||||
import Link from "@mui/material/Link";
|
import Link from "@mui/material/Link";
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
@ -12,6 +11,7 @@ import Typography from "@mui/material/Typography";
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useLoadingMessage } from "../hooks/context_providers/LoadingMessageProvider";
|
import { useLoadingMessage } from "../hooks/context_providers/LoadingMessageProvider";
|
||||||
import { AuthApi } from "../api/AuthApi";
|
import { AuthApi } from "../api/AuthApi";
|
||||||
|
import Grid from "@mui/material/Grid2";
|
||||||
|
|
||||||
function Copyright(props: any) {
|
function Copyright(props: any) {
|
||||||
return (
|
return (
|
||||||
@ -60,10 +60,7 @@ export function LoginRoute() {
|
|||||||
<Grid container component="main" sx={{ height: "100vh" }}>
|
<Grid container component="main" sx={{ height: "100vh" }}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Grid
|
<Grid
|
||||||
item
|
size={{ sm: 4, md: 7, xs: false }}
|
||||||
xs={false}
|
|
||||||
sm={4}
|
|
||||||
md={7}
|
|
||||||
sx={{
|
sx={{
|
||||||
backgroundImage: 'url("/sun.jpg")',
|
backgroundImage: 'url("/sun.jpg")',
|
||||||
backgroundColor: (t) =>
|
backgroundColor: (t) =>
|
||||||
@ -74,7 +71,12 @@ export function LoginRoute() {
|
|||||||
backgroundPosition: "left",
|
backgroundPosition: "left",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
|
<Grid
|
||||||
|
size={{ xs: 12, sm: 8, md: 5 }}
|
||||||
|
component={Paper}
|
||||||
|
elevation={6}
|
||||||
|
square
|
||||||
|
>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
my: 8,
|
my: 8,
|
||||||
|
Loading…
Reference in New Issue
Block a user