mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-10 10:33:11 +03:00
disable save all when any section is invalid
This commit is contained in:
parent
3b5f84c601
commit
49f4bc48b6
@ -121,6 +121,7 @@ export interface BaseSectionProps {
|
||||
onStatusChange?: (status: {
|
||||
hasChanges: boolean;
|
||||
isOverridden: boolean;
|
||||
hasValidationErrors: boolean;
|
||||
}) => void;
|
||||
/** Pending form data keyed by "sectionKey" or "cameraName::sectionKey" */
|
||||
pendingDataBySection?: Record<string, unknown>;
|
||||
@ -371,8 +372,8 @@ export function ConfigSection({
|
||||
}, [formData, pendingData, extraHasChanges]);
|
||||
|
||||
useEffect(() => {
|
||||
onStatusChange?.({ hasChanges, isOverridden });
|
||||
}, [hasChanges, isOverridden, onStatusChange]);
|
||||
onStatusChange?.({ hasChanges, isOverridden, hasValidationErrors });
|
||||
}, [hasChanges, isOverridden, hasValidationErrors, onStatusChange]);
|
||||
|
||||
// Handle form data change
|
||||
const handleChange = useCallback(
|
||||
|
||||
@ -668,6 +668,13 @@ export default function Settings() {
|
||||
const { data: fullSchema } = useSWR<RJSFSchema>("config/schema.json");
|
||||
|
||||
const hasPendingChanges = Object.keys(pendingDataBySection).length > 0;
|
||||
const hasPendingValidationErrors = useMemo(
|
||||
() =>
|
||||
Object.values(sectionStatusByKey).some(
|
||||
(status) => !!status && status.hasChanges && status.hasValidationErrors,
|
||||
),
|
||||
[sectionStatusByKey],
|
||||
);
|
||||
const pendingChangesPreview = useMemo<SaveAllPreviewItem[]>(() => {
|
||||
if (!config || !fullSchema) return [];
|
||||
|
||||
@ -734,7 +741,13 @@ export default function Settings() {
|
||||
);
|
||||
|
||||
const handleSaveAll = useCallback(async () => {
|
||||
if (!config || !fullSchema || !hasPendingChanges) return;
|
||||
if (
|
||||
!config ||
|
||||
!fullSchema ||
|
||||
!hasPendingChanges ||
|
||||
hasPendingValidationErrors
|
||||
)
|
||||
return;
|
||||
|
||||
setIsSavingAll(true);
|
||||
let successCount = 0;
|
||||
@ -812,6 +825,7 @@ export default function Settings() {
|
||||
updated[menuKey] = {
|
||||
...updated[menuKey],
|
||||
hasChanges: false,
|
||||
hasValidationErrors: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -865,6 +879,7 @@ export default function Settings() {
|
||||
config,
|
||||
fullSchema,
|
||||
hasPendingChanges,
|
||||
hasPendingValidationErrors,
|
||||
pendingDataBySection,
|
||||
pendingKeyToMenuKey,
|
||||
t,
|
||||
@ -885,6 +900,7 @@ export default function Settings() {
|
||||
updated[menuKey] = {
|
||||
...updated[menuKey],
|
||||
hasChanges: false,
|
||||
hasValidationErrors: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1011,7 +1027,9 @@ export default function Settings() {
|
||||
useEffect(() => {
|
||||
if (!selectedCamera || !cameraOverrides) return;
|
||||
|
||||
const overrideMap: Partial<Record<SettingsType, SectionStatus>> = {};
|
||||
const overrideMap: Partial<
|
||||
Record<SettingsType, Pick<SectionStatus, "hasChanges" | "isOverridden">>
|
||||
> = {};
|
||||
|
||||
// Set override status for all camera sections using the shared mapping
|
||||
Object.entries(CAMERA_SECTION_MAPPING).forEach(
|
||||
@ -1031,7 +1049,12 @@ export default function Settings() {
|
||||
// Merge and update both hasChanges and isOverridden for camera sections
|
||||
const merged = { ...prev };
|
||||
Object.entries(overrideMap).forEach(([key, status]) => {
|
||||
merged[key as SettingsType] = status;
|
||||
const existingStatus = merged[key as SettingsType];
|
||||
merged[key as SettingsType] = {
|
||||
hasChanges: status.hasChanges,
|
||||
isOverridden: status.isOverridden,
|
||||
hasValidationErrors: existingStatus?.hasValidationErrors ?? false,
|
||||
};
|
||||
});
|
||||
return merged;
|
||||
});
|
||||
@ -1164,7 +1187,7 @@ export default function Settings() {
|
||||
onClick={handleSaveAll}
|
||||
variant="select"
|
||||
size="sm"
|
||||
disabled={isSavingAll}
|
||||
disabled={isSavingAll || hasPendingValidationErrors}
|
||||
className="flex w-full items-center justify-center gap-2"
|
||||
>
|
||||
{isSavingAll ? (
|
||||
@ -1306,7 +1329,7 @@ export default function Settings() {
|
||||
variant="select"
|
||||
size="sm"
|
||||
onClick={handleSaveAll}
|
||||
disabled={isSavingAll}
|
||||
disabled={isSavingAll || hasPendingValidationErrors}
|
||||
className="flex items-center justify-center gap-2"
|
||||
>
|
||||
{isSavingAll ? (
|
||||
|
||||
@ -31,6 +31,7 @@ export type SettingsPageProps = {
|
||||
export type SectionStatus = {
|
||||
hasChanges: boolean;
|
||||
isOverridden: boolean;
|
||||
hasValidationErrors: boolean;
|
||||
};
|
||||
|
||||
export type SingleSectionPageOptions = {
|
||||
@ -67,6 +68,7 @@ export function SingleSectionPage({
|
||||
const [sectionStatus, setSectionStatus] = useState<SectionStatus>({
|
||||
hasChanges: false,
|
||||
isOverridden: false,
|
||||
hasValidationErrors: false,
|
||||
});
|
||||
const resolvedSectionConfig = useMemo(
|
||||
() => sectionConfig ?? getSectionConfig(sectionKey, level),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user