Miscellaneous fixes (#23000)
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions

* ensure classification wizard dialog is scrollable on mobile too

* add chat and features group to mobile menu

Co-authored-by: Copilot <copilot@github.com>

* Set min length for summary too

* Don't use orange for review item

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
This commit is contained in:
Josh Hawkins 2026-04-25 10:12:20 -05:00 committed by GitHub
parent 819e8de172
commit 1a1994ca17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 54 additions and 32 deletions

View File

@ -8,8 +8,6 @@ class ReviewMetadata(BaseModel):
description="A short title characterizing what took place and where, under 10 words." description="A short title characterizing what took place and where, under 10 words."
) )
scene: str = Field( scene: str = Field(
min_length=120,
max_length=600,
description="A chronological narrative of what happens from start to finish.", description="A chronological narrative of what happens from start to finish.",
) )
shortSummary: str = Field( shortSummary: str = Field(

View File

@ -151,6 +151,18 @@ Each line represents a detection state, not necessarily unique individuals. The
if "other_concerns" in schema.get("required", []): if "other_concerns" in schema.get("required", []):
schema["required"].remove("other_concerns") schema["required"].remove("other_concerns")
# Length hints injected into the schema as suggestions to the model
# (enforced by grammar-based providers like llama.cpp) but kept off the
# Pydantic model so a non-compliant response does not fail validation.
length_hints = {
"scene": {"minLength": 120, "maxLength": 600},
"shortSummary": {"minLength": 70, "maxLength": 100},
}
for field, hints in length_hints.items():
prop = schema.get("properties", {}).get(field)
if prop is not None:
prop.update(hints)
# OpenAI strict mode requires additionalProperties: false on all objects # OpenAI strict mode requires additionalProperties: false on all objects
schema["additionalProperties"] = False schema["additionalProperties"] = False

View File

@ -257,6 +257,7 @@
"export": "Export", "export": "Export",
"actions": "Actions", "actions": "Actions",
"uiPlayground": "UI Playground", "uiPlayground": "UI Playground",
"features": "Features",
"faceLibrary": "Face Library", "faceLibrary": "Face Library",
"classification": "Classification", "classification": "Classification",
"chat": "Chat", "chat": "Chat",

View File

@ -161,13 +161,13 @@ export function AnimatedEventCard({
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button <Button
className={cn( className={cn(
"absolute left-2 top-1 z-40 transition-opacity", "absolute left-2 top-1 z-40 bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500 transition-opacity",
threatLevel === ThreatLevel.SECURITY_CONCERN && threatLevel === ThreatLevel.SECURITY_CONCERN &&
"pointer-events-auto bg-severity_alert opacity-100 hover:bg-severity_alert", "pointer-events-auto opacity-100",
threatLevel === ThreatLevel.NEEDS_REVIEW && threatLevel === ThreatLevel.NEEDS_REVIEW &&
"pointer-events-auto bg-severity_detection opacity-100 hover:bg-severity_detection", "pointer-events-auto opacity-100",
threatLevel === ThreatLevel.NORMAL && threatLevel === ThreatLevel.NORMAL &&
"pointer-events-none bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100", "pointer-events-none opacity-0 group-hover:pointer-events-auto group-hover:opacity-100",
)} )}
size="xs" size="xs"
aria-label={t("markAsReviewed")} aria-label={t("markAsReviewed")}

View File

@ -14,7 +14,6 @@ import Step3ChooseExamples, {
Step3FormData, Step3FormData,
} from "./wizard/Step3ChooseExamples"; } from "./wizard/Step3ChooseExamples";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { isDesktop } from "react-device-detect";
import axios from "axios"; import axios from "axios";
const OBJECT_STEPS = [ const OBJECT_STEPS = [
@ -153,13 +152,9 @@ export default function ClassificationModelWizardDialog({
> >
<DialogContent <DialogContent
className={cn( className={cn(
"", "scrollbar-container max-h-[90%] overflow-y-auto",
isDesktop && wizardState.currentStep == 0 && "xl:max-h-[80%]",
wizardState.currentStep == 0 && wizardState.currentStep > 0 && "md:max-w-[70%] xl:max-h-[80%]",
"max-h-[90%] overflow-y-auto xl:max-h-[80%]",
isDesktop &&
wizardState.currentStep > 0 &&
"max-h-[90%] max-w-[70%] overflow-y-auto xl:max-h-[80%]",
)} )}
onInteractOutside={(e) => { onInteractOutside={(e) => {
e.preventDefault(); e.preventDefault();

View File

@ -6,6 +6,7 @@ import {
LuLifeBuoy, LuLifeBuoy,
LuList, LuList,
LuLogOut, LuLogOut,
LuMessageSquare,
LuMoon, LuMoon,
LuSquarePen, LuSquarePen,
LuScanFace, LuScanFace,
@ -482,21 +483,25 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
</Link> </Link>
</> </>
)} )}
{isAdmin && isMobile && config?.face_recognition.enabled && ( </DropdownMenuGroup>
<> {isMobile && isAdmin && (
<Link to="/faces"> <>
<MenuItem <DropdownMenuLabel className="mt-1">
className="flex w-full items-center p-2 text-sm" {t("menu.features")}
aria-label={t("menu.faceLibrary")} </DropdownMenuLabel>
> <DropdownMenuSeparator />
<LuScanFace className="mr-2 size-4" /> <DropdownMenuGroup className="flex flex-col">
<span>{t("menu.faceLibrary")}</span> {config?.face_recognition.enabled && (
</MenuItem> <Link to="/faces">
</Link> <MenuItem
</> className="flex w-full items-center p-2 text-sm"
)} aria-label={t("menu.faceLibrary")}
{isAdmin && isMobile && ( >
<> <LuScanFace className="mr-2 size-4" />
<span>{t("menu.faceLibrary")}</span>
</MenuItem>
</Link>
)}
<Link to="/classification"> <Link to="/classification">
<MenuItem <MenuItem
className="flex w-full items-center p-2 text-sm" className="flex w-full items-center p-2 text-sm"
@ -506,9 +511,20 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
<span>{t("menu.classification")}</span> <span>{t("menu.classification")}</span>
</MenuItem> </MenuItem>
</Link> </Link>
</> {config?.genai?.model !== "none" && (
)} <Link to="/chat">
</DropdownMenuGroup> <MenuItem
className="flex w-full items-center p-2 text-sm"
aria-label={t("menu.chat")}
>
<LuMessageSquare className="mr-2 size-4" />
<span>{t("menu.chat")}</span>
</MenuItem>
</Link>
)}
</DropdownMenuGroup>
</>
)}
<DropdownMenuLabel className={isDesktop ? "mt-3" : "mt-1"}> <DropdownMenuLabel className={isDesktop ? "mt-3" : "mt-1"}>
{t("menu.appearance")} {t("menu.appearance")}
</DropdownMenuLabel> </DropdownMenuLabel>