diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index db2563c..cf3c9dc 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -67,6 +67,10 @@ const TABS = [ find: 'mitarbeiter rechte bereiche protokoll audit zugriff' }, ]; +// Tabs, die nur aus Formular-Blöcken bestehen — die dürfen zweispaltig laufen. +// Alles mit Editor, Vorschau oder Liste bleibt einspaltig. +const DENSE_TABS = new Set(['feeds', 'community', 'support', 'system']); + // Welcher Team-Scope schaltet welchen Tab frei (null = nur Owner) const TAB_SCOPES = { status: 'any', @@ -222,6 +226,7 @@ export default function Settings({ me }) { const [templates, setTemplates] = useState([]); const [templateGroups, setTemplateGroups] = useState([]); const [tplDraft, setTplDraft] = useState({}); // id → bearbeiteter Text + const [openTpl, setOpenTpl] = useState(null); // aufgeklappte Vorlage // Eigene Seiten (Regeln, Über uns, …) const emptyPage = { slug: '', title: '', content: '', published: false, in_menu: true, sort: 0, isNew: true }; const [pages, setPages] = useState([]); @@ -300,6 +305,16 @@ export default function Settings({ me }) { if (data?.status?.botDescription != null) setBotDesc(data.status.botDescription); }, [data]); + // Zurück-Taste und von Hand geänderte Adressen sollen den Bereich mitwechseln + useEffect(() => { + const onHash = () => { + const id = TABS.find((t) => t.id === window.location.hash.slice(1))?.id; + if (id) setTabState(id); + }; + window.addEventListener('hashchange', onHash); + return () => window.removeEventListener('hashchange', onHash); + }, []); + // Falls der aktive Tab nicht (mehr) erlaubt ist → auf den ersten erlaubten wechseln useEffect(() => { if (!canTab(tab) && visibleTabs.length > 0) setTab(visibleTabs[0].id); @@ -1890,10 +1905,10 @@ export default function Settings({ me }) {
- Alles, was der Bot nach außen schreibt — Begrüßungen, Bestätigungen, - Direktnachrichten. Die Bausteine in geschweiften Klammern setzt der Bot - beim Senden ein; klick einen an, um ihn an der Cursor-Position einzufügen. - Ein leeres Feld bedeutet: wieder der Standardtext. + Alles, was der Bot nach außen schreibt. Zeile anklicken zum Bearbeiten — + die Bausteine in geschweiften Klammern setzt der Bot beim Senden ein, + ein Klick darauf fügt sie an der Cursor-Position ein. Ein leeres Feld + bedeutet: wieder der Standardtext.
{templateGroups.map((group) => { @@ -1910,56 +1925,75 @@ export default function Settings({ me }) { const value = draft ?? t.text; const dirty = draft != null && draft !== t.text; const off = t.module && modules.some((m) => m.id === t.module && !m.enabled); + const open = openTpl === t.id; return ( -