feat(admin): Web-Suche pro Nutzer ein-/ausschaltbar

web_search_enabled in AdminUserPrefsUpdate (war nicht im Schema -> wurde wie
frueher voice_gender still verworfen) + in der /admin/users-Antwort (Checkbox-
Initialzustand, Default = globaler Wert) + Checkbox im Admin-Nutzer-Bereich
(speichert sofort). resolve_route respektierte das Pref schon -> wirkt jetzt
durchgaengig (AUS = plain Provider, AN = ToolCallingLLM).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-30 09:12:55 +02:00
commit 5609741039
3 changed files with 25 additions and 0 deletions

View file

@ -237,6 +237,7 @@ async def list_users():
"emergency_contacts", "emergency_phones", "emergency_cooldown_minutes",
)},
"location_consent": bool((u.prefs or {}).get("location_consent", False)),
"web_search_enabled": bool((u.prefs or {}).get("web_search_enabled", runtime_settings.web_search_enabled)),
"is_admin": is_admin_user(u),
}
for u in get_store().list_users()

View file

@ -164,6 +164,7 @@ class AdminUserPrefsUpdate(BaseModel):
Format geprüft (serverseitige Härtung zusätzlich zur Frontend-Validierung).
"""
allowed_languages: str | None = None
web_search_enabled: bool | None = None # Web-Suche (Weg 2) pro Nutzer an/aus
# Notfall-Profil (in user.prefs gespeichert, fließt in die Notruf-Meldungen ein)
full_name: str | None = None
street: str | None = None

View file

@ -1220,6 +1220,14 @@ function buildUserCard(u) {
<div class="lang-allow flex flex-wrap gap-1"></div>
</div>
<!-- Web-Suche (Weg 2) -->
<div class="mt-3 pt-3 border-t border-slate-100 dark:border-slate-700">
<label class="text-xs text-slate-600 dark:text-slate-300 flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="ws-enabled" /> Web-Suche für aktuelle Fragen erlauben
<span class="ws-status text-slate-400"></span>
</label>
</div>
<!-- Notfall-Profil -->
<div class="mt-3 pt-3 border-t border-slate-100 dark:border-slate-700">
<button class="btn-prof text-xs text-slate-500 hover:text-slate-700 dark:hover:text-slate-300 flex items-center gap-1 transition-colors">
@ -1308,6 +1316,21 @@ function buildUserCard(u) {
});
const consentEl = card.querySelector(".prof-consent");
if (consentEl) consentEl.checked = !!u.location_consent;
// Web-Suche pro Nutzer: sofort speichern bei Änderung
const wsEl = card.querySelector(".ws-enabled");
const wsStatus = card.querySelector(".ws-status");
if (wsEl) {
wsEl.checked = !!u.web_search_enabled;
wsEl.addEventListener("change", async () => {
if (wsStatus) wsStatus.textContent = "speichere …";
const res = await adminFetch(`/api/admin/users/${uid}/prefs`, "PUT", { web_search_enabled: wsEl.checked });
if (wsStatus) {
wsStatus.textContent = res ? "✓" : "Fehler";
setTimeout(() => { wsStatus.textContent = ""; }, 2000);
}
});
}
const profBtn = card.querySelector(".btn-prof");
const profSection = card.querySelector(".prof-section");
const profArrow = card.querySelector(".prof-arrow");