This commit is contained in:
Josh Hawkins 2026-04-07 09:41:56 -05:00
parent acf4b4093b
commit 8e5483f0c0
3 changed files with 81 additions and 9 deletions

View File

@ -62,7 +62,10 @@
"zones": "Zones", "zones": "Zones",
"ratio": "Ratio", "ratio": "Ratio",
"area": "Area", "area": "Area",
"score": "Score" "score": "Score",
"computedScore": "Computed Score",
"topScore": "Top Score",
"toggleAdvancedScores": "Toggle advanced scores"
} }
}, },
"annotationSettings": { "annotationSettings": {

View File

@ -9,7 +9,12 @@ import { FrigateConfig } from "@/types/frigateConfig";
import { formatUnixTimestampToDateTime } from "@/utils/dateUtil"; import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
import { use24HourTime } from "@/hooks/use-date-utils"; import { use24HourTime } from "@/hooks/use-date-utils";
import { getIconForLabel } from "@/utils/iconUtil"; import { getIconForLabel } from "@/utils/iconUtil";
import { LuCircle, LuFolderX } from "react-icons/lu"; import {
LuChevronDown,
LuChevronRight,
LuCircle,
LuFolderX,
} from "react-icons/lu";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import HlsVideoPlayer from "@/components/player/HlsVideoPlayer"; import HlsVideoPlayer from "@/components/player/HlsVideoPlayer";
import { baseUrl } from "@/api/baseUrl"; import { baseUrl } from "@/api/baseUrl";
@ -899,6 +904,7 @@ function LifecycleIconRow({
const { t } = useTranslation(["views/explore", "components/player"]); const { t } = useTranslation(["views/explore", "components/player"]);
const { data: config } = useSWR<FrigateConfig>("config"); const { data: config } = useSWR<FrigateConfig>("config");
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [showAdvancedScores, setShowAdvancedScores] = useState(false);
const navigate = useNavigate(); const navigate = useNavigate();
const isAdmin = useIsAdmin(); const isAdmin = useIsAdmin();
@ -993,12 +999,31 @@ function LifecycleIconRow({
[item.data.box], [item.data.box],
); );
const score = useMemo(() => { const currentScore = useMemo(
if (item.data.score !== undefined) { () =>
return (item.data.score * 100).toFixed(0) + "%"; item.data.score !== undefined
} ? (item.data.score * 100).toFixed(0) + "%"
return "N/A"; : null,
}, [item.data.score]); [item.data.score],
);
const computedScore = useMemo(
() =>
item.data.computed_score !== undefined &&
item.data.computed_score !== null &&
item.data.computed_score > 0
? (item.data.computed_score * 100).toFixed(0) + "%"
: null,
[item.data.computed_score],
);
const topScore = useMemo(
() =>
item.data.top_score !== undefined &&
item.data.top_score !== null &&
item.data.top_score > 0
? (item.data.top_score * 100).toFixed(0) + "%"
: null,
[item.data.top_score],
);
return ( return (
<div <div
@ -1034,8 +1059,50 @@ function LifecycleIconRow({
<span className="text-primary-variant"> <span className="text-primary-variant">
{t("trackingDetails.lifecycleItemDesc.header.score")} {t("trackingDetails.lifecycleItemDesc.header.score")}
</span> </span>
<span className="font-medium text-primary">{score}</span> <span className="font-medium text-primary">
{currentScore ?? "N/A"}
</span>
{(computedScore || topScore) && (
<button
type="button"
onClick={(e) => {
e.stopPropagation();
setShowAdvancedScores((v) => !v);
}}
className="ml-1 inline-flex items-center text-primary-variant hover:text-primary"
aria-expanded={showAdvancedScores}
aria-label={t(
"trackingDetails.lifecycleItemDesc.header.toggleAdvancedScores",
)}
>
{showAdvancedScores ? (
<LuChevronDown className="size-3.5" />
) : (
<LuChevronRight className="size-3.5" />
)}
</button>
)}
</div> </div>
{showAdvancedScores && computedScore && (
<div className="flex items-center gap-1.5">
<span className="text-primary-variant">
{t(
"trackingDetails.lifecycleItemDesc.header.computedScore",
)}
</span>
<span className="font-medium text-primary">
{computedScore}
</span>
</div>
)}
{showAdvancedScores && topScore && (
<div className="flex items-center gap-1.5">
<span className="text-primary-variant">
{t("trackingDetails.lifecycleItemDesc.header.topScore")}
</span>
<span className="font-medium text-primary">{topScore}</span>
</div>
)}
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<span className="text-primary-variant"> <span className="text-primary-variant">
{t("trackingDetails.lifecycleItemDesc.header.ratio")} {t("trackingDetails.lifecycleItemDesc.header.ratio")}

View File

@ -17,6 +17,8 @@ export type TrackingDetailsSequence = {
camera: string; camera: string;
label: string; label: string;
score: number; score: number;
computed_score?: number;
top_score?: number;
sub_label: string; sub_label: string;
box?: [number, number, number, number]; box?: [number, number, number, number];
region: [number, number, number, number]; region: [number, number, number, number];