* tweak language

* show validation errors in json response

* fix export hwaccel args field in UI

* increase annotation offset consts

* fix save button race conditions, add reset spinner, and fix enrichments profile leak

- Disable both Save and SaveAll buttons while either operation is in progress so users cannot trigger concurrent saves
- Show activity indicator on Reset to Default/Global button during the API call
- Enrichments panes (semantic search, genai, face recognition) now always show base config fields regardless of profile selection in the header dropdown

* fix genai additional_concerns validation error with textarea array widget

The additional_concerns field is list[str] in the backend but was using the textarea widget which produces a string value, causing validation errors.
Created a TextareaArrayWidget that converts between array (one item per line) and textarea display, and switched additional_concerns to use it

* populate and sort global audio filters for all audio labels

* add column labels in profiles view

* enforce a minimum value of 2 for min_initialized

* reuse widget and refactor for multiline

* fix

* change record copy preset to transcode audio to aac
This commit is contained in:
Josh Hawkins
2026-03-26 13:47:24 -05:00
committed by GitHub
parent 909b40ba96
commit 4772e6a2ab
17 changed files with 264 additions and 69 deletions
+21 -4
View File
@@ -724,6 +724,7 @@ export default function Settings() {
// Save All state
const [isSavingAll, setIsSavingAll] = useState(false);
const [isAnySectionSaving, setIsAnySectionSaving] = useState(false);
const [restartDialogOpen, setRestartDialogOpen] = useState(false);
const { send: sendRestart } = useRestart();
const { data: fullSchema } = useSWR<RJSFSchema>("config/schema.json");
@@ -1299,6 +1300,10 @@ export default function Settings() {
[],
);
const handleSectionSavingChange = useCallback((saving: boolean) => {
setIsAnySectionSaving(saving);
}, []);
// The active profile being edited for the selected camera
const activeEditingProfile = selectedCamera
? (editingProfile[selectedCamera] ?? null)
@@ -1508,7 +1513,7 @@ export default function Settings() {
onClick={handleUndoAll}
variant="outline"
size="sm"
disabled={isSavingAll}
disabled={isSavingAll || isAnySectionSaving}
className="flex w-full items-center justify-center gap-2"
>
{t("button.undoAll", {
@@ -1520,7 +1525,11 @@ export default function Settings() {
onClick={handleSaveAll}
variant="select"
size="sm"
disabled={isSavingAll || hasPendingValidationErrors}
disabled={
isSavingAll ||
isAnySectionSaving ||
hasPendingValidationErrors
}
className="flex w-full items-center justify-center gap-2"
>
{isSavingAll ? (
@@ -1606,6 +1615,8 @@ export default function Settings() {
}
profilesUIEnabled={profilesUIEnabled}
setProfilesUIEnabled={setProfilesUIEnabled}
isSavingAll={isSavingAll}
onSectionSavingChange={handleSectionSavingChange}
/>
);
})()}
@@ -1674,7 +1685,7 @@ export default function Settings() {
onClick={handleUndoAll}
variant="outline"
size="sm"
disabled={isSavingAll}
disabled={isSavingAll || isAnySectionSaving}
className="flex items-center justify-center gap-2"
>
{t("button.undoAll", {
@@ -1686,7 +1697,11 @@ export default function Settings() {
variant="select"
size="sm"
onClick={handleSaveAll}
disabled={isSavingAll || hasPendingValidationErrors}
disabled={
isSavingAll ||
isAnySectionSaving ||
hasPendingValidationErrors
}
className="flex items-center justify-center gap-2"
>
{isSavingAll ? (
@@ -1843,6 +1858,8 @@ export default function Settings() {
onDeleteProfileSection={handleDeleteProfileForCurrentSection}
profilesUIEnabled={profilesUIEnabled}
setProfilesUIEnabled={setProfilesUIEnabled}
isSavingAll={isSavingAll}
onSectionSavingChange={handleSectionSavingChange}
/>
);
})()}