Improve System Health pane (#24188)

* build out system health pane

* tweaks

* fixes

* fix notice link so it opens the correct camera

* tweak language
This commit is contained in:
Josh Hawkins
2026-09-12 07:30:04 -06:00
committed by Nicolas Mowen
parent 6d33b31bc6
commit 70ce193e09
57 changed files with 3965 additions and 464 deletions
+136 -54
View File
@@ -7,82 +7,164 @@ import {
LuSlidersHorizontal,
LuX,
} from "react-icons/lu";
import { TooltipPortal } from "@radix-ui/react-tooltip";
import { Button } from "@/components/ui/button";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { CameraNameLabel } from "@/components/camera/FriendlyNameLabel";
import ActivityIndicator from "@/components/indicators/activity-indicator";
import { useDocDomain } from "@/hooks/use-doc-domain";
import type { HealthProblem } from "@/types/health";
type HealthProblemRowProps = {
problem: HealthProblem;
};
const ICON_BUTTON_CLASS =
"size-6 shrink-0 text-muted-foreground hover:text-primary";
function RowAction({
label,
children,
}: {
label: string;
children: React.ReactNode;
}) {
return (
<Tooltip>
<TooltipTrigger asChild>{children}</TooltipTrigger>
<TooltipPortal>
<TooltipContent>{label}</TooltipContent>
</TooltipPortal>
</Tooltip>
);
}
export default function HealthProblemRow({ problem }: HealthProblemRowProps) {
const { t } = useTranslation(["views/system"]);
const { t } = useTranslation(["views/system", "common"]);
const { getLocaleDocUrl } = useDocDomain();
const hasDetails = problem.scope || problem.meta;
const hasActions =
problem.link ||
problem.docLink ||
problem.externalLink ||
problem.onDismiss;
return (
<div
className="flex items-start gap-2 border-b border-border px-1 py-2 text-sm last:border-b-0"
className="flex items-center gap-2 border-b border-border px-1 py-2 text-sm last:border-b-0"
data-testid={`health-problem-${problem.id}`}
data-severity={problem.severity}
>
<div className="mt-0.5 flex shrink-0">
{problem.severity === "error" && <LuX className="size-4 text-danger" />}
{problem.severity === "warning" && (
<FaTriangleExclamation className="size-4 text-yellow-500" />
)}
{problem.severity === "info" && (
<LuInfo className="size-4 text-selected" />
<div className="flex shrink-0 self-start pt-0.5">
{problem.pending ? (
<ActivityIndicator className="" size={16} />
) : (
<>
{problem.severity === "error" && (
<LuX className="size-4 text-danger" />
)}
{problem.severity === "warning" && (
<FaTriangleExclamation className="size-4 text-yellow-500" />
)}
{problem.severity === "info" && (
<LuInfo className="size-4 text-selected" />
)}
</>
)}
</div>
{problem.scope && (
<span className="rounded-md bg-secondary px-1.5 py-0.5 text-xs text-secondary-foreground smart-capitalize">
{problem.scopeIsCamera ? (
<CameraNameLabel camera={problem.scope} />
) : (
problem.scope
)}
</span>
)}
<div className="min-w-0 flex-1">
<div>{problem.text}</div>
{problem.meta && (
<div className="mt-0.5 text-xs text-muted-foreground">
{problem.meta}
{hasDetails && (
<div className="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
{problem.scope && (
<span className="rounded bg-secondary px-1.5 py-0.5 text-xs text-primary-variant">
{problem.scopeIsCamera ? (
<CameraNameLabel camera={problem.scope} />
) : (
problem.scope
)}
</span>
)}
{problem.meta && <span>{problem.meta}</span>}
</div>
)}
</div>
<div className="flex shrink-0 items-center gap-2 text-muted-foreground">
{problem.onDismiss && (
<Button
variant="ghost"
size="sm"
className="h-6 px-2"
onClick={problem.onDismiss}
aria-label={t("health.notices.dismiss")}
>
{t("health.notices.dismiss")}
</Button>
)}
{problem.link && (
<Link
to={problem.link}
aria-label={t("health.notices.openSettings")}
className="hover:text-primary"
>
<LuSlidersHorizontal className="size-4" />
</Link>
)}
{problem.externalLink && (
<a
href={problem.externalLink}
target="_blank"
rel="noreferrer"
aria-label={t("health.notices.openLink")}
className="hover:text-primary"
>
<LuExternalLink className="size-4" />
</a>
)}
</div>
{hasActions && (
<div className="ml-auto flex shrink-0 items-center gap-1">
{problem.link && (
<RowAction label={t("health.notices.openSettings")}>
<Button
asChild
variant="ghost"
size="icon"
className={ICON_BUTTON_CLASS}
>
<Link
to={problem.link}
aria-label={t("health.notices.openSettings")}
>
<LuSlidersHorizontal className="size-3.5" />
</Link>
</Button>
</RowAction>
)}
{problem.docLink && (
<RowAction label={t("readTheDocumentation", { ns: "common" })}>
<Button
asChild
variant="ghost"
size="icon"
className={ICON_BUTTON_CLASS}
>
<a
href={getLocaleDocUrl(problem.docLink)}
target="_blank"
rel="noreferrer"
aria-label={t("readTheDocumentation", { ns: "common" })}
>
<LuExternalLink className="size-3.5" />
</a>
</Button>
</RowAction>
)}
{problem.externalLink && (
<RowAction label={t("health.notices.openLink")}>
<Button
asChild
variant="ghost"
size="icon"
className={ICON_BUTTON_CLASS}
>
<a
href={problem.externalLink}
target="_blank"
rel="noreferrer"
aria-label={t("health.notices.openLink")}
>
<LuExternalLink className="size-3.5" />
</a>
</Button>
</RowAction>
)}
{problem.onDismiss && (
<RowAction label={t("health.notices.dismiss")}>
<Button
variant="ghost"
size="icon"
className={ICON_BUTTON_CLASS}
aria-label={t("health.notices.dismiss")}
onClick={problem.onDismiss}
>
<LuX className="size-3.5" />
</Button>
</RowAction>
)}
</div>
)}
</div>
);
}