diff --git a/web/public/locales/en/components/player.json b/web/public/locales/en/components/player.json index 3b50ff5ed..6ceef7e0c 100644 --- a/web/public/locales/en/components/player.json +++ b/web/public/locales/en/components/player.json @@ -4,7 +4,8 @@ "noPreviewFoundFor": "No Preview Found for {{cameraName}}", "submitFrigatePlus": { "title": "Submit this frame to Frigate+?", - "submit": "Submit" + "submit": "Submit", + "previewError": "Could not load snapshot preview. The recording may not be available at this time." }, "livePlayerRequiredIOSVersion": "iOS 17.1 or greater is required for this live stream type.", "streamOffline": { diff --git a/web/src/components/config-form/section-configs/ffmpeg.ts b/web/src/components/config-form/section-configs/ffmpeg.ts index d0d426a6a..97326c33f 100644 --- a/web/src/components/config-form/section-configs/ffmpeg.ts +++ b/web/src/components/config-form/section-configs/ffmpeg.ts @@ -31,6 +31,8 @@ const ffmpeg: SectionConfigOverrides = { "inputs.output_args": "/configuration/ffmpeg_presets#output-args-presets", "output_args.record": "/configuration/ffmpeg_presets#output-args-presets", "inputs.roles": "/configuration/cameras/#setting-up-camera-inputs", + apple_compatibility: + "/configuration/camera_specific#h265-cameras-via-safari", }, restartRequired: [], fieldOrder: [ diff --git a/web/src/components/config-form/section-configs/lpr.ts b/web/src/components/config-form/section-configs/lpr.ts index 0567c6cf4..c56966142 100644 --- a/web/src/components/config-form/section-configs/lpr.ts +++ b/web/src/components/config-form/section-configs/lpr.ts @@ -27,10 +27,12 @@ const lpr: SectionConfigOverrides = { ], fieldDocs: { enhancement: "/configuration/license_plate_recognition#enhancement", + debug_save_plates: + "/configuration/license_plate_recognition/#how-do-i-debug-lpr-issues", }, restartRequired: [], fieldOrder: ["enabled", "min_area", "enhancement", "expire_time"], - hiddenFields: [], + hiddenFields: ["expire_time"], advancedFields: ["expire_time", "enhancement"], overrideFields: ["enabled", "min_area", "enhancement"], }, diff --git a/web/src/components/config-form/section-configs/onvif.ts b/web/src/components/config-form/section-configs/onvif.ts index c08cd7a58..acfb68f16 100644 --- a/web/src/components/config-form/section-configs/onvif.ts +++ b/web/src/components/config-form/section-configs/onvif.ts @@ -3,6 +3,11 @@ import type { SectionConfigOverrides } from "./types"; const onvif: SectionConfigOverrides = { base: { sectionDocs: "/configuration/cameras#setting-up-camera-ptz-controls", + fieldDocs: { + autotracking: "/configuration/autotracking", + "autotracking.calibrate_on_startup": + "/configuration/autotracking#calibration", + }, fieldOrder: [ "host", "port", diff --git a/web/src/components/config-form/section-configs/review.ts b/web/src/components/config-form/section-configs/review.ts index ce0d7b911..1069d82bf 100644 --- a/web/src/components/config-form/section-configs/review.ts +++ b/web/src/components/config-form/section-configs/review.ts @@ -45,6 +45,10 @@ const review: SectionConfigOverrides = { fieldDocs: { "alerts.labels": "/configuration/review/#alerts-and-detections", "detections.labels": "/configuration/review/#alerts-and-detections", + genai: "/configuration/genai/genai_review", + "genai.image_source": "/configuration/genai/genai_review#image-source", + "genai.additional_concerns": + "/configuration/genai/genai_review#additional-concerns", }, restartRequired: [], fieldOrder: ["alerts", "detections", "genai", "genai.enabled"], diff --git a/web/src/components/config-form/theme/templates/ObjectFieldTemplate.tsx b/web/src/components/config-form/theme/templates/ObjectFieldTemplate.tsx index 65c5c5541..4b588d62b 100644 --- a/web/src/components/config-form/theme/templates/ObjectFieldTemplate.tsx +++ b/web/src/components/config-form/theme/templates/ObjectFieldTemplate.tsx @@ -9,11 +9,13 @@ import { import { Children, useState, useEffect, useRef } from "react"; import type { ReactNode } from "react"; import RestartRequiredIndicator from "@/components/indicators/RestartRequiredIndicator"; -import { LuChevronDown, LuChevronRight } from "react-icons/lu"; +import { LuChevronDown, LuChevronRight, LuExternalLink } from "react-icons/lu"; import { useTranslation } from "react-i18next"; +import { Link } from "react-router-dom"; import { cn } from "@/lib/utils"; import { getTranslatedLabel } from "@/utils/i18n"; import { requiresRestartForFieldPath } from "@/utils/configUtil"; +import { useDocDomain } from "@/hooks/use-doc-domain"; import { ConfigFormContext } from "@/types/configForm"; import { buildTranslationPath, @@ -178,6 +180,7 @@ export function ObjectFieldTemplate(props: ObjectFieldTemplateProps) { "views/settings", "common", ]); + const { getLocaleDocUrl } = useDocDomain(); const objectRequiresRestart = requiresRestartForFieldPath( fieldPath, restartRequired, @@ -300,6 +303,17 @@ export function ObjectFieldTemplate(props: ObjectFieldTemplateProps) { schemaDescription; inferredDescription = inferredDescription ?? fallbackDescription; + const pathStringSegments = + path?.filter((segment): segment is string => typeof segment === "string") ?? + []; + const fieldDocsKey = translationPath || pathStringSegments.join("."); + const fieldDocsPath = fieldDocsKey + ? formContext?.fieldDocs?.[fieldDocsKey] + : undefined; + const fieldDocsUrl = fieldDocsPath + ? getLocaleDocUrl(fieldDocsPath) + : undefined; + const renderGroupedFields = (items: (typeof properties)[number][]) => { if (!items.length) { return null; @@ -466,6 +480,20 @@ export function ObjectFieldTemplate(props: ObjectFieldTemplateProps) { {inferredDescription}

)} + {fieldDocsUrl && ( +
+ e.stopPropagation()} + > + {t("readTheDocumentation", { ns: "common" })} + + +
+ )} {isOpen ? ( diff --git a/web/src/components/overlay/DebugReplayDialog.tsx b/web/src/components/overlay/DebugReplayDialog.tsx index 9c3efb4f5..2a9e09d08 100644 --- a/web/src/components/overlay/DebugReplayDialog.tsx +++ b/web/src/components/overlay/DebugReplayDialog.tsx @@ -113,18 +113,19 @@ export function DebugReplayContent({ {isDesktop && } -
{t("button.cancel", { ns: "common" })} -
+ {activeTab === "export" ? ( + )}