mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 13:34:13 +03:00
Camera wizard tweaks (#20643)
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
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
* dialog size tweaks * move icon and make links in popvers clickable * colors and clickable links
This commit is contained in:
parent
f5a57edcc9
commit
e2da8aa04c
@ -20,6 +20,8 @@ import type {
|
|||||||
ConfigSetBody,
|
ConfigSetBody,
|
||||||
} from "@/types/cameraWizard";
|
} from "@/types/cameraWizard";
|
||||||
import { processCameraName } from "@/utils/cameraUtil";
|
import { processCameraName } from "@/utils/cameraUtil";
|
||||||
|
import { isDesktop } from "react-device-detect";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
type WizardState = {
|
type WizardState = {
|
||||||
wizardData: Partial<WizardFormData>;
|
wizardData: Partial<WizardFormData>;
|
||||||
@ -335,7 +337,15 @@ export default function CameraWizardDialog({
|
|||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={handleClose}>
|
<Dialog open={open} onOpenChange={handleClose}>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
className="max-h-[90dvh] max-w-4xl overflow-y-auto"
|
className={cn(
|
||||||
|
"max-h-[90dvh] max-w-xl overflow-y-auto",
|
||||||
|
isDesktop &&
|
||||||
|
currentStep == 0 &&
|
||||||
|
state.wizardData?.streams?.[0]?.testResult?.snapshot &&
|
||||||
|
"max-w-4xl",
|
||||||
|
isDesktop && currentStep == 1 && "max-w-2xl",
|
||||||
|
isDesktop && currentStep > 1 && "max-w-4xl",
|
||||||
|
)}
|
||||||
onInteractOutside={(e) => {
|
onInteractOutside={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import {
|
|||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
FormDescription,
|
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import {
|
import {
|
||||||
@ -298,6 +297,7 @@ export default function Step1NameCamera({
|
|||||||
};
|
};
|
||||||
|
|
||||||
setTestResult(testResult);
|
setTestResult(testResult);
|
||||||
|
onUpdate({ streams: [{ id: "", url: "", roles: [], testResult }] });
|
||||||
toast.success(t("cameraWizard.step1.testSuccess"));
|
toast.success(t("cameraWizard.step1.testSuccess"));
|
||||||
} else {
|
} else {
|
||||||
const error =
|
const error =
|
||||||
@ -337,7 +337,7 @@ export default function Step1NameCamera({
|
|||||||
setIsTesting(false);
|
setIsTesting(false);
|
||||||
setTestStatus("");
|
setTestStatus("");
|
||||||
}
|
}
|
||||||
}, [form, generateStreamUrl, t]);
|
}, [form, generateStreamUrl, t, onUpdate]);
|
||||||
|
|
||||||
const onSubmit = (data: z.infer<typeof step1FormData>) => {
|
const onSubmit = (data: z.infer<typeof step1FormData>) => {
|
||||||
onUpdate(data);
|
onUpdate(data);
|
||||||
@ -380,7 +380,9 @@ export default function Step1NameCamera({
|
|||||||
name="cameraName"
|
name="cameraName"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("cameraWizard.step1.cameraName")}</FormLabel>
|
<FormLabel className="text-primary-variant">
|
||||||
|
{t("cameraWizard.step1.cameraName")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className="h-8"
|
className="h-8"
|
||||||
@ -400,7 +402,43 @@ export default function Step1NameCamera({
|
|||||||
name="brandTemplate"
|
name="brandTemplate"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("cameraWizard.step1.cameraBrand")}</FormLabel>
|
<div className="flex items-center gap-1 pb-1">
|
||||||
|
<FormLabel className="text-primary-variant">
|
||||||
|
{t("cameraWizard.step1.cameraBrand")}
|
||||||
|
</FormLabel>
|
||||||
|
{field.value &&
|
||||||
|
(() => {
|
||||||
|
const selectedBrand = CAMERA_BRANDS.find(
|
||||||
|
(brand) => brand.value === field.value,
|
||||||
|
);
|
||||||
|
return selectedBrand &&
|
||||||
|
selectedBrand.value != "other" ? (
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="h-4 w-4 p-0"
|
||||||
|
>
|
||||||
|
<LuInfo className="size-3" />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="pointer-events-auto w-80 text-primary-variant">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h4 className="font-medium">
|
||||||
|
{selectedBrand.label}
|
||||||
|
</h4>
|
||||||
|
<p className="break-all text-sm text-muted-foreground">
|
||||||
|
{t("cameraWizard.step1.brandUrlFormat", {
|
||||||
|
exampleUrl: selectedBrand.exampleUrl,
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
) : null;
|
||||||
|
})()}
|
||||||
|
</div>
|
||||||
<Select
|
<Select
|
||||||
onValueChange={field.onChange}
|
onValueChange={field.onChange}
|
||||||
defaultValue={field.value}
|
defaultValue={field.value}
|
||||||
@ -421,37 +459,6 @@ export default function Step1NameCamera({
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
{field.value &&
|
|
||||||
(() => {
|
|
||||||
const selectedBrand = CAMERA_BRANDS.find(
|
|
||||||
(brand) => brand.value === field.value,
|
|
||||||
);
|
|
||||||
return selectedBrand &&
|
|
||||||
selectedBrand.value != "other" ? (
|
|
||||||
<FormDescription className="mt-1 pt-0.5 text-xs text-muted-foreground">
|
|
||||||
<Popover>
|
|
||||||
<PopoverTrigger>
|
|
||||||
<div className="flex flex-row items-center gap-0.5 text-xs text-muted-foreground hover:text-primary">
|
|
||||||
<LuInfo className="mr-1 size-3" />
|
|
||||||
{t("cameraWizard.step1.brandInformation")}
|
|
||||||
</div>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent className="w-80">
|
|
||||||
<div className="space-y-2">
|
|
||||||
<h4 className="font-medium">
|
|
||||||
{selectedBrand.label}
|
|
||||||
</h4>
|
|
||||||
<p className="break-all text-sm text-muted-foreground">
|
|
||||||
{t("cameraWizard.step1.brandUrlFormat", {
|
|
||||||
exampleUrl: selectedBrand.exampleUrl,
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
</FormDescription>
|
|
||||||
) : null;
|
|
||||||
})()}
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -463,7 +470,9 @@ export default function Step1NameCamera({
|
|||||||
name="host"
|
name="host"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("cameraWizard.step1.host")}</FormLabel>
|
<FormLabel className="text-primary-variant">
|
||||||
|
{t("cameraWizard.step1.host")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className="h-8"
|
className="h-8"
|
||||||
@ -481,7 +490,7 @@ export default function Step1NameCamera({
|
|||||||
name="username"
|
name="username"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel className="text-primary-variant">
|
||||||
{t("cameraWizard.step1.username")}
|
{t("cameraWizard.step1.username")}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
@ -503,7 +512,7 @@ export default function Step1NameCamera({
|
|||||||
name="password"
|
name="password"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel className="text-primary-variant">
|
||||||
{t("cameraWizard.step1.password")}
|
{t("cameraWizard.step1.password")}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
@ -544,7 +553,9 @@ export default function Step1NameCamera({
|
|||||||
name="customUrl"
|
name="customUrl"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("cameraWizard.step1.customUrl")}</FormLabel>
|
<FormLabel className="text-primary-variant">
|
||||||
|
{t("cameraWizard.step1.customUrl")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className="h-8"
|
className="h-8"
|
||||||
|
|||||||
@ -277,7 +277,7 @@ export default function Step2StreamConfig({
|
|||||||
|
|
||||||
<div className="grid grid-cols-1 gap-4">
|
<div className="grid grid-cols-1 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-sm font-medium">
|
<label className="text-sm font-medium text-primary-variant">
|
||||||
{t("cameraWizard.step2.url")}
|
{t("cameraWizard.step2.url")}
|
||||||
</label>
|
</label>
|
||||||
<div className="flex flex-row items-center gap-2">
|
<div className="flex flex-row items-center gap-2">
|
||||||
@ -325,7 +325,7 @@ export default function Step2StreamConfig({
|
|||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<Label className="text-sm font-medium">
|
<Label className="text-sm font-medium text-primary-variant">
|
||||||
{t("cameraWizard.step2.roles")}
|
{t("cameraWizard.step2.roles")}
|
||||||
</Label>
|
</Label>
|
||||||
<Popover>
|
<Popover>
|
||||||
@ -334,7 +334,7 @@ export default function Step2StreamConfig({
|
|||||||
<LuInfo className="size-3" />
|
<LuInfo className="size-3" />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-80 text-xs">
|
<PopoverContent className="pointer-events-auto w-80 text-xs">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="font-medium">
|
<div className="font-medium">
|
||||||
{t("cameraWizard.step2.rolesPopover.title")}
|
{t("cameraWizard.step2.rolesPopover.title")}
|
||||||
@ -395,7 +395,7 @@ export default function Step2StreamConfig({
|
|||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<Label className="text-sm font-medium">
|
<Label className="text-sm font-medium text-primary-variant">
|
||||||
{t("cameraWizard.step2.featuresTitle")}
|
{t("cameraWizard.step2.featuresTitle")}
|
||||||
</Label>
|
</Label>
|
||||||
<Popover>
|
<Popover>
|
||||||
@ -404,7 +404,7 @@ export default function Step2StreamConfig({
|
|||||||
<LuInfo className="size-3" />
|
<LuInfo className="size-3" />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-80 text-xs">
|
<PopoverContent className="pointer-events-auto w-80 text-xs">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="font-medium">
|
<div className="font-medium">
|
||||||
{t("cameraWizard.step2.featuresPopover.title")}
|
{t("cameraWizard.step2.featuresPopover.title")}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user