Skip to content

Commit

Permalink
chore: normalize error retry banners
Browse files Browse the repository at this point in the history
  • Loading branch information
mdvanes committed Apr 15, 2024
1 parent c01ce11 commit ded8cb0
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 76 deletions.
17 changes: 8 additions & 9 deletions apps/client/src/Components/Molecules/DockerList/DockerList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Alert, Box, Grid } from "@mui/material";
import { Box, Grid } from "@mui/material";
import { Stack } from "@mui/system";
import { FC, useEffect, useState } from "react";
import {
Expand All @@ -8,6 +8,7 @@ import {
import { getErrorMessage } from "../../../Utils/getErrorMessage";
import CardExpandBar from "../CardExpandBar/CardExpandBar";
import DockerInfo from "../DockerInfo/DockerInfo";
import ErrorRetry from "../ErrorRetry/ErrorRetry";
import LoadingDot from "../LoadingDot/LoadingDot";
import ContainerDot from "./ContainerDot";

Expand All @@ -22,14 +23,12 @@ interface DockerListProps {
const DockerList: FC<DockerListProps> = ({ onError }) => {
const [isOpen, setIsOpen] = useState(false);
const [isSkippingBecauseError, setIsSkippingBecauseError] = useState(false);
const { data, isLoading, isFetching, error } = useGetDockerListQuery(
undefined,
{
const { data, isLoading, isFetching, error, refetch } =
useGetDockerListQuery(undefined, {
pollingInterval: isSkippingBecauseError
? undefined
: UPDATE_INTERVAL_MS,
}
);
});

useEffect(() => {
if (error) {
Expand All @@ -40,9 +39,9 @@ const DockerList: FC<DockerListProps> = ({ onError }) => {

if (error) {
return (
<Box mx={-2}>
<Alert severity="error">{getErrorMessage(error)}</Alert>
</Box>
<ErrorRetry retry={() => refetch()}>
DockerList could not load
</ErrorRetry>
);
}

Expand Down
28 changes: 15 additions & 13 deletions apps/client/src/Components/Molecules/DownloadList/DownloadList.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { List, Paper } from "@mui/material";
import { FC, useEffect, useState } from "react";
import { Alert, List, Paper } from "@mui/material";
import { useAppDispatch } from "../../../store";
import DownloadListItem from "./DownloadListItem";
import { logError } from "../LogCard/logSlice";
import { useGetDownloadListQuery } from "../../../Services/downloadListApi";
import { getErrorMessage } from "../../../Utils/getErrorMessage";
import { useAppDispatch } from "../../../store";
import CardExpandBar from "../CardExpandBar/CardExpandBar";
import ErrorRetry from "../ErrorRetry/ErrorRetry";
import LoadingDot from "../LoadingDot/LoadingDot";
import { logError } from "../LogCard/logSlice";
import DownloadListItem from "./DownloadListItem";

const UPDATE_INTERVAL_MS = 30000;

Expand All @@ -14,20 +16,20 @@ const DownloadList: FC = () => {
const [isSkippingBecauseError, setIsSkippingBecauseError] = useState(false);
const dispatch = useAppDispatch();

const { data, error, isLoading, isFetching } = useGetDownloadListQuery(
undefined,
{
const { data, error, isLoading, isFetching, refetch } =
useGetDownloadListQuery(undefined, {
pollingInterval: isSkippingBecauseError
? undefined
: UPDATE_INTERVAL_MS,
}
);
});
const [listItems, setListItems] = useState<JSX.Element[]>([]);

useEffect(() => {
if (error) {
setIsSkippingBecauseError(true);
dispatch(logError("GetDownloadList failed"));
dispatch(
logError(`GetDownloadList failed: ${getErrorMessage(error)}`)
);
}
}, [dispatch, error]);

Expand All @@ -50,9 +52,9 @@ const DownloadList: FC = () => {
<List component={Paper}>
<LoadingDot isLoading={isLoading || isFetching} />
{error && (
<Alert severity="error">
There is an error, data may be stale
</Alert>
<ErrorRetry marginate retry={() => refetch()}>
DL could not load
</ErrorRetry>
)}
{listItems}
<CardExpandBar
Expand Down
52 changes: 52 additions & 0 deletions apps/client/src/Components/Molecules/ErrorRetry/ErrorRetry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import RestartAltIcon from "@mui/icons-material/RestartAlt";
import { Alert, Box, IconButton, Tooltip } from "@mui/material";
import { FC, PropsWithChildren } from "react";

interface Props extends PropsWithChildren {
marginate?: boolean;
retry: () => void;
}

export const ErrorRetry: FC<Props> = ({
marginate = false,
children,
retry,
}) => {
return (
<Box
mx={marginate ? undefined : -2}
component={Alert}
severity="error"
square
sx={{
".MuiAlert-message": {
width: "100%",
},
}}
>
<Box
display="flex"
flex={1}
flexDirection="row"
justifyContent="space-between"
>
<div>{children}</div>
<Tooltip title="Retry">
<IconButton
size="small"
onClick={retry}
sx={{
".MuiSvgIcon-root": {
marginTop: "-0.5rem",
},
}}
>
<RestartAltIcon />
</IconButton>
</Tooltip>
</Box>
</Box>
);
};

export default ErrorRetry;
118 changes: 64 additions & 54 deletions apps/client/src/Components/Molecules/HomeSec/HomeSec.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { FC } from "react";
import { useGetHomesecStatusQuery } from "../../../Services/homesecApi";
import { HomesecStatusResponse, TypeF } from "@homeremote/types";
import {
Icon,
List,
ListItem,
ListItemAvatar,
ListItemButton,
ListItemText,
Paper,
Icon,
Tooltip,
} from "@mui/material";
import { HomesecStatusResponse, TypeF } from "@homeremote/types";
import { FC } from "react";
import { useGetHomesecStatusQuery } from "../../../Services/homesecApi";
import ErrorRetry from "../ErrorRetry/ErrorRetry";
import LoadingDot from "../LoadingDot/LoadingDot";
import SimpleHomeSecListItem from "./SimpleHomeSecListItem";

Expand All @@ -31,63 +33,71 @@ export const HomeSec: FC = () => {
const { data, isLoading, isFetching, isError, refetch } =
useGetHomesecStatusQuery(undefined);

const hasNoDevices =
!isError &&
!isLoading &&
!isFetching &&
(!data?.devices || data?.devices.length === 0);

return (
<List
component={Paper}
style={{
borderWidth: 1,
borderStyle: "solid",
borderColor: statusClass[data?.status ?? "Error"],
}}
>
<LoadingDot isLoading={isLoading || isFetching} />
{isError ? (
<SimpleHomeSecListItem
title="Error retrieving devices"
onClick={() => refetch()}
/>
) : (
""
)}
{!data?.devices || data?.devices.length === 0 ? (
<SimpleHomeSecListItem
title="No devices found"
onClick={() => refetch()}
/>
) : (
""
)}
{data?.devices?.map((sensor) => (
<ListItem key={sensor.id} disableGutters disablePadding dense>
<ListItemButton>
<ListItemAvatar>
<Icon>{typeIcon[sensor.type_f]}</Icon>
</ListItemAvatar>
<ListItemText
primary={
<div
style={{
display: "flex",
justifyContent: "space-between",
}}
>
<div>{sensor.name}</div>
<Tooltip title={`HomeSec status: ${data?.status ?? "Error"}`}>
<List
component={Paper}
style={{
borderWidth: 1,
borderStyle: "solid",
borderColor: statusClass[data?.status ?? "Error"],
}}
>
<LoadingDot isLoading={isLoading || isFetching} />
{isError && (
<ErrorRetry marginate retry={() => refetch()}>
HomeSec could not load
</ErrorRetry>
)}
{hasNoDevices && (
<SimpleHomeSecListItem
title="No HomeSec devices found"
onClick={() => refetch()}
/>
)}
{data?.devices?.map((sensor) => (
<ListItem
key={sensor.id}
disableGutters
disablePadding
dense
>
<ListItemButton>
<ListItemAvatar>
<Icon>{typeIcon[sensor.type_f]}</Icon>
</ListItemAvatar>
<ListItemText
primary={
<div
style={{
display: "flex",
gap: "16px",
justifyContent: "space-between",
}}
>
<div>{sensor.status}</div>
<div>{sensor.rssi}</div>
<div>{sensor.name}</div>
<div
style={{
display: "flex",
gap: "16px",
}}
>
<div>{sensor.status}</div>
<div>{sensor.rssi}</div>
</div>
</div>
</div>
}
/>
</ListItemButton>
</ListItem>
))}
</List>
}
/>
</ListItemButton>
</ListItem>
))}
</List>
</Tooltip>
);
};

Expand Down

0 comments on commit ded8cb0

Please sign in to comment.