mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-23 08:38:22 +03:00
add optional field widget
adds a switch to enable nullable fields like skip_motion_threshold
This commit is contained in:
parent
ef07563d0a
commit
ddba2dd6e7
@ -26,6 +26,7 @@ import { FfmpegArgsWidget } from "./widgets/FfmpegArgsWidget";
|
|||||||
import { InputRolesWidget } from "./widgets/InputRolesWidget";
|
import { InputRolesWidget } from "./widgets/InputRolesWidget";
|
||||||
import { TimezoneSelectWidget } from "./widgets/TimezoneSelectWidget";
|
import { TimezoneSelectWidget } from "./widgets/TimezoneSelectWidget";
|
||||||
import { CameraPathWidget } from "./widgets/CameraPathWidget";
|
import { CameraPathWidget } from "./widgets/CameraPathWidget";
|
||||||
|
import { OptionalFieldWidget } from "./widgets/OptionalFieldWidget";
|
||||||
|
|
||||||
import { FieldTemplate } from "./templates/FieldTemplate";
|
import { FieldTemplate } from "./templates/FieldTemplate";
|
||||||
import { ObjectFieldTemplate } from "./templates/ObjectFieldTemplate";
|
import { ObjectFieldTemplate } from "./templates/ObjectFieldTemplate";
|
||||||
@ -73,6 +74,7 @@ export const frigateTheme: FrigateTheme = {
|
|||||||
audioLabels: AudioLabelSwitchesWidget,
|
audioLabels: AudioLabelSwitchesWidget,
|
||||||
zoneNames: ZoneSwitchesWidget,
|
zoneNames: ZoneSwitchesWidget,
|
||||||
timezoneSelect: TimezoneSelectWidget,
|
timezoneSelect: TimezoneSelectWidget,
|
||||||
|
optionalField: OptionalFieldWidget,
|
||||||
},
|
},
|
||||||
templates: {
|
templates: {
|
||||||
FieldTemplate: FieldTemplate as React.ComponentType<FieldTemplateProps>,
|
FieldTemplate: FieldTemplate as React.ComponentType<FieldTemplateProps>,
|
||||||
|
|||||||
@ -0,0 +1,64 @@
|
|||||||
|
// Optional Field Widget - wraps any inner widget with an enable/disable switch
|
||||||
|
// Used for nullable fields where None means "disabled" (not the same as 0)
|
||||||
|
|
||||||
|
import type { WidgetProps } from "@rjsf/utils";
|
||||||
|
import { getWidget } from "@rjsf/utils";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { getNonNullSchema } from "../fields/nullableUtils";
|
||||||
|
|
||||||
|
export function OptionalFieldWidget(props: WidgetProps) {
|
||||||
|
const { id, value, disabled, readonly, onChange, schema, options, registry } =
|
||||||
|
props;
|
||||||
|
|
||||||
|
const innerWidgetName = (options.innerWidget as string) || undefined;
|
||||||
|
const isEnabled = value !== undefined && value !== null;
|
||||||
|
|
||||||
|
// Extract the non-null branch from anyOf [Type, null]
|
||||||
|
const innerSchema = getNonNullSchema(schema) ?? schema;
|
||||||
|
|
||||||
|
const InnerWidget = getWidget(innerSchema, innerWidgetName, registry.widgets);
|
||||||
|
|
||||||
|
const getDefaultValue = () => {
|
||||||
|
if (innerSchema.default !== undefined && innerSchema.default !== null) {
|
||||||
|
return innerSchema.default;
|
||||||
|
}
|
||||||
|
if (innerSchema.minimum !== undefined) {
|
||||||
|
return innerSchema.minimum;
|
||||||
|
}
|
||||||
|
if (innerSchema.type === "integer" || innerSchema.type === "number") {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (innerSchema.type === "string") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleToggle = (checked: boolean) => {
|
||||||
|
onChange(checked ? getDefaultValue() : undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const innerProps: WidgetProps = {
|
||||||
|
...props,
|
||||||
|
schema: innerSchema,
|
||||||
|
disabled: disabled || readonly || !isEnabled,
|
||||||
|
value: isEnabled ? value : getDefaultValue(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<Switch
|
||||||
|
id={`${id}-toggle`}
|
||||||
|
checked={isEnabled}
|
||||||
|
disabled={disabled || readonly}
|
||||||
|
onCheckedChange={handleToggle}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={cn("flex-1", !isEnabled && "pointer-events-none opacity-40")}
|
||||||
|
>
|
||||||
|
<InnerWidget {...innerProps} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user