re-add override and modified indicators

This commit is contained in:
Josh Hawkins
2026-02-27 09:40:21 -06:00
parent f8eee8ed0b
commit 95a0530ce6
3 changed files with 214 additions and 23 deletions
+38 -1
View File
@@ -1,13 +1,25 @@
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import Heading from "@/components/ui/heading";
import type { SectionConfig } from "@/components/config-form/sections";
import { ConfigSectionTemplate } from "@/components/config-form/sections";
import type { PolygonType } from "@/types/canvas";
import { Badge } from "@/components/ui/badge";
export type SettingsPageProps = {
selectedCamera?: string;
setUnsavedChanges?: React.Dispatch<React.SetStateAction<boolean>>;
selectedZoneMask?: PolygonType[];
onSectionStatusChange?: (
sectionKey: string,
level: "global" | "camera",
status: SectionStatus,
) => void;
};
export type SectionStatus = {
hasChanges: boolean;
isOverridden: boolean;
};
export type SingleSectionPageOptions = {
@@ -29,6 +41,7 @@ export function SingleSectionPage({
showOverrideIndicator = true,
selectedCamera,
setUnsavedChanges,
onSectionStatusChange,
}: SingleSectionPageProps) {
const sectionNamespace =
level === "camera" ? "config/cameras" : "config/global";
@@ -37,6 +50,14 @@ export function SingleSectionPage({
"views/settings",
"common",
]);
const [sectionStatus, setSectionStatus] = useState<SectionStatus>({
hasChanges: false,
isOverridden: false,
});
useEffect(() => {
onSectionStatusChange?.(sectionKey, level, sectionStatus);
}, [onSectionStatusChange, sectionKey, level, sectionStatus]);
if (level === "camera" && !selectedCamera) {
return (
@@ -48,10 +69,11 @@ export function SingleSectionPage({
return (
<div className="flex size-full flex-col pr-2">
<div className="mb-4">
<div className="space-y-4">
<Heading as="h3">
{t(`${sectionKey}.label`, { ns: sectionNamespace })}
</Heading>
{i18n.exists(`${sectionKey}.description`, {
ns: sectionNamespace,
}) && (
@@ -59,6 +81,20 @@ export function SingleSectionPage({
{t(`${sectionKey}.description`, { ns: sectionNamespace })}
</p>
)}
<div className="flex flex-wrap items-center gap-2">
{level === "camera" &&
showOverrideIndicator &&
sectionStatus.isOverridden && (
<Badge variant="secondary" className="text-xs">
{t("overridden", { ns: "common", defaultValue: "Overridden" })}
</Badge>
)}
{sectionStatus.hasChanges && (
<Badge variant="outline" className="text-xs">
{t("modified", { ns: "common", defaultValue: "Modified" })}
</Badge>
)}
</div>
</div>
<ConfigSectionTemplate
sectionKey={sectionKey}
@@ -69,6 +105,7 @@ export function SingleSectionPage({
showTitle={false}
sectionConfig={sectionConfig}
requiresRestart={requiresRestart}
onStatusChange={setSectionStatus}
/>
</div>
);