mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-27 22:29:02 +03:00
fix array field template
This commit is contained in:
@@ -17,6 +17,7 @@ export const ReviewSection = createConfigSection({
|
||||
"detections.labels",
|
||||
"detections.enabled_in_config",
|
||||
"detections.required_zones",
|
||||
"genai.enabled_in_config",
|
||||
],
|
||||
advancedFields: [],
|
||||
},
|
||||
|
||||
@@ -22,6 +22,7 @@ import { SwitchesWidget } from "./widgets/SwitchesWidget";
|
||||
import { ObjectLabelSwitchesWidget } from "./widgets/ObjectLabelSwitchesWidget";
|
||||
import { AudioLabelSwitchesWidget } from "./widgets/AudioLabelSwitchesWidget";
|
||||
import { ZoneSwitchesWidget } from "./widgets/ZoneSwitchesWidget";
|
||||
import { ArrayAsTextWidget } from "./widgets/ArrayAsTextWidget";
|
||||
|
||||
import { FieldTemplate } from "./templates/FieldTemplate";
|
||||
import { ObjectFieldTemplate } from "./templates/ObjectFieldTemplate";
|
||||
@@ -48,6 +49,7 @@ export const frigateTheme: FrigateTheme = {
|
||||
PasswordWidget: PasswordWidget,
|
||||
SelectWidget: SelectWidget,
|
||||
CheckboxWidget: SwitchWidget,
|
||||
ArrayAsTextWidget: ArrayAsTextWidget,
|
||||
// Custom widgets
|
||||
switch: SwitchWidget,
|
||||
password: PasswordWidget,
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
// Array Field Template - renders array fields with add/remove controls
|
||||
import type { ArrayFieldTemplateProps } from "@rjsf/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { LuPlus, LuTrash2, LuGripVertical } from "react-icons/lu";
|
||||
import { LuPlus } from "react-icons/lu";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface ArrayItem {
|
||||
key: string;
|
||||
index: number;
|
||||
children: React.ReactNode;
|
||||
hasRemove: boolean;
|
||||
onDropIndexClick: (index: number) => () => void;
|
||||
}
|
||||
|
||||
export function ArrayFieldTemplate(props: ArrayFieldTemplateProps) {
|
||||
const { items, canAdd, onAddClick, disabled, readonly, schema } = props;
|
||||
|
||||
@@ -36,52 +27,20 @@ export function ArrayFieldTemplate(props: ArrayFieldTemplateProps) {
|
||||
</p>
|
||||
)}
|
||||
|
||||
{(items as unknown as ArrayItem[]).map((element: ArrayItem) => (
|
||||
<div
|
||||
key={element.key}
|
||||
className={cn("flex items-start gap-2", !isSimpleType && "flex-col")}
|
||||
>
|
||||
{isSimpleType ? (
|
||||
<div className="flex flex-1 items-center gap-2">
|
||||
<LuGripVertical className="h-4 w-4 cursor-move text-muted-foreground" />
|
||||
<div className="flex-1">{element.children}</div>
|
||||
{element.hasRemove && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={element.onDropIndexClick(element.index)}
|
||||
disabled={disabled || readonly}
|
||||
className="h-8 w-8 text-destructive hover:text-destructive"
|
||||
>
|
||||
<LuTrash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Card className="w-full">
|
||||
<CardContent className="pt-4">
|
||||
<div className="flex items-start gap-2">
|
||||
<LuGripVertical className="mt-2 h-4 w-4 cursor-move text-muted-foreground" />
|
||||
<div className="flex-1">{element.children}</div>
|
||||
{element.hasRemove && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={element.onDropIndexClick(element.index)}
|
||||
disabled={disabled || readonly}
|
||||
className="h-8 w-8 text-destructive hover:text-destructive"
|
||||
>
|
||||
<LuTrash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{items.map((element, index) => {
|
||||
// RJSF items are pre-rendered React elements, render them directly
|
||||
return (
|
||||
<div
|
||||
key={element.key || index}
|
||||
className={cn(
|
||||
"flex items-start gap-2",
|
||||
!isSimpleType && "flex-col",
|
||||
)}
|
||||
>
|
||||
{element}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{canAdd && (
|
||||
<Button
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Widget that displays an array as a concatenated text string
|
||||
import type { WidgetProps } from "@rjsf/utils";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { useCallback } from "react";
|
||||
|
||||
export function ArrayAsTextWidget(props: WidgetProps) {
|
||||
const { value, onChange, disabled, readonly, placeholder } = props;
|
||||
|
||||
// Convert array to space-separated string
|
||||
const textValue =
|
||||
Array.isArray(value) && value.length > 0 ? value.join(" ") : "";
|
||||
|
||||
const handleChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const newText = event.target.value;
|
||||
// Convert space-separated string back to array
|
||||
const newArray = newText.trim() ? newText.trim().split(/\s+/) : [];
|
||||
onChange(newArray);
|
||||
},
|
||||
[onChange],
|
||||
);
|
||||
|
||||
return (
|
||||
<Input
|
||||
value={textValue}
|
||||
onChange={handleChange}
|
||||
disabled={disabled}
|
||||
readOnly={readonly}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user