From e7249118dac9efac7b0b32d61eb123c09d650d34 Mon Sep 17 00:00:00 2001 From: DrMelone <27028174+Classic298@users.noreply.github.com> Date: Mon, 13 Apr 2026 00:32:35 +0200 Subject: [PATCH] fix: apply admin defaults for brand-new users, normalize chatDirection, wire entry points MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - +layout.svelte always merges adminDefaults with whatever user UI is available (server-returned settings.ui, or localStorage, or {}). The previous branch skipped defaults entirely when getUserSettings() returned null, which is exactly the new-user case the feature targets — admin defaults never reached users who hadn't customized anything. - InterfaceDefaultsForm.validate_chat_direction now accepts any casing and normalizes to the shape the frontend store expects ('auto' lowercase, 'LTR' / 'RTL' uppercase). The interface-settings toggle cycles uppercase values, so admin saves with LTR/RTL were rejected with 422 by the old lowercase-only validator. - admin Settings/Interface.svelte adds the missing entry points: a "Configure Defaults" button that toggles showInterfaceDefaultsModal and a destructive "Reset All Users Interface Settings" button that toggles showResetConfirmDialog. The flags and bound components were already in place; nothing was flipping them. - getInterfaceDefaults / setInterfaceDefaults / resetAllUsersInterfaceSettings fall back through err.detail / err.message / stringification so network-level failures (fetch TypeError, non-JSON body) surface as thrown errors instead of resolving to null and letting callers treat failed requests as silent successes. --- backend/open_webui/routers/configs.py | 16 +++++++-- src/lib/apis/configs/index.ts | 9 +++-- src/lib/apis/users/index.ts | 6 +++- .../admin/Settings/Interface.svelte | 36 +++++++++++++++++++ src/routes/+layout.svelte | 17 ++++----- 5 files changed, 70 insertions(+), 14 deletions(-) diff --git a/backend/open_webui/routers/configs.py b/backend/open_webui/routers/configs.py index c286152abd..fd2ad14602 100644 --- a/backend/open_webui/routers/configs.py +++ b/backend/open_webui/routers/configs.py @@ -676,9 +676,19 @@ class InterfaceDefaultsForm(BaseModel): @field_validator("chatDirection") @classmethod def validate_chat_direction(cls, value): - if value is not None and value not in ("auto", "ltr", "rtl"): - raise ValueError("chatDirection must be 'auto', 'ltr', or 'rtl'") - return value + # The user-side store is typed 'LTR' | 'RTL' | 'auto' and the + # Interface settings toggle cycles uppercase values, so accept any + # casing and normalize to the shape the frontend expects. Rejecting + # the uppercase values outright (as the validator did before) made + # the modal fail with a 422 on every LTR/RTL save. + if value is None: + return value + normalized = value.lower() + if normalized == "auto": + return "auto" + if normalized in ("ltr", "rtl"): + return normalized.upper() + raise ValueError("chatDirection must be 'auto', 'LTR', or 'RTL'") @field_validator("textScale") @classmethod diff --git a/src/lib/apis/configs/index.ts b/src/lib/apis/configs/index.ts index 7cbdad0431..df16b033d2 100644 --- a/src/lib/apis/configs/index.ts +++ b/src/lib/apis/configs/index.ts @@ -664,7 +664,12 @@ export const getInterfaceDefaults = async (token: string) => { }) .catch((err) => { console.error(err); - error = err.detail; + // Fall back through detail / message / stringification so a + // network TypeError or non-JSON response still produces a truthy + // error — otherwise the function silently returned null and the + // caller couldn't tell a failed fetch from an empty-defaults + // response. + error = err?.detail ?? err?.message ?? (typeof err === 'string' ? err : 'Request failed'); return null; }); @@ -692,7 +697,7 @@ export const setInterfaceDefaults = async (token: string, defaults: object) => { }) .catch((err) => { console.error(err); - error = err.detail; + error = err?.detail ?? err?.message ?? (typeof err === 'string' ? err : 'Request failed'); return null; }); diff --git a/src/lib/apis/users/index.ts b/src/lib/apis/users/index.ts index b599f0b7fc..23e8eca5df 100644 --- a/src/lib/apis/users/index.ts +++ b/src/lib/apis/users/index.ts @@ -567,7 +567,11 @@ export const resetAllUsersInterfaceSettings = async (token: string) => { }) .catch((err) => { console.error(err); - error = err.detail; + // Fall back through detail / message / stringification so a + // network TypeError or non-JSON response still produces a truthy + // error — otherwise the function silently returned null and the + // caller could mistake a failed reset for a silent success. + error = err?.detail ?? err?.message ?? (typeof err === 'string' ? err : 'Request failed'); return null; }); diff --git a/src/lib/components/admin/Settings/Interface.svelte b/src/lib/components/admin/Settings/Interface.svelte index 204415910c..8bec5c8606 100644 --- a/src/lib/components/admin/Settings/Interface.svelte +++ b/src/lib/components/admin/Settings/Interface.svelte @@ -114,6 +114,42 @@ }} >