diff --git a/README.md b/README.md index e51b81c..946d684 100644 --- a/README.md +++ b/README.md @@ -140,8 +140,17 @@ Der aktive Bereich steht in der Adresse (`/settings#texte`), Links und Neuladen landen also wieder dort. Der Status-Bereich ist der Einstieg: Kennzahlen plus **„Noch einzurichten"** — -alle eingeschalteten Module, denen noch ein Kanal oder eine Rolle fehlt, mit -Sprung direkt zur richtigen Stelle. +alle eingeschalteten Module, denen noch ein Kanal oder eine Rolle fehlt. Daneben +steht **„Kanal anlegen"** bzw. **„Rolle anlegen"**: der Bot legt sie in Discord +an, setzt bei privaten Kanälen die Rechte (nur Team sieht sie) und trägt die +Einstellung gleich ein. Gibt es Kanal oder Rolle schon, werden sie verknüpft +statt doppelt angelegt. + +Dafür braucht der Bot *Kanäle verwalten* bzw. *Rollen verwalten* — fehlt das +Recht, sagt das Panel genau das. Die Vorlagen (Name, Thema, privat/öffentlich) +stehen bei den Modulen in [`src/modules.js`](src/modules.js). Gelöscht oder +umbenannt wird bewusst nichts: ein Fehlklick beim Anlegen kostet einen +überflüssigen Kanal, einer beim Löschen dessen Verlauf. Team-Mitglieder sehen nur die Bereiche ihrer Rechte. Alles zur Laufzeit änderbar — gespeichert in SQLite, Env-Variablen sind nur Fallback, kein Redeploy nötig: diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index 18010c4..efa4545 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -304,6 +304,7 @@ export default function Settings({ me }) { const [modules, setModules] = useState([]); const [moduleGroups, setModuleGroups] = useState([]); const [modFilter, setModFilter] = useState('alle'); + const [creating, setCreating] = useState(null); // Einstellung, die gerade angelegt wird // Text-Vorlagen (was der Bot nach außen schreibt) const [templates, setTemplates] = useState([]); const [templateGroups, setTemplateGroups] = useState([]); @@ -501,6 +502,26 @@ export default function Settings({ me }) { } } + /** Fehlenden Kanal / fehlende Rolle vom Bot anlegen lassen */ + async function createMissing(entry) { + setCreating(entry.setting); + try { + const res = await apiPost('/api/setup/create', { setting: entry.setting }); + setModules(res.modules); + // Die neue Auswahl steht sofort im Formular — und zählt nicht als + // ungespeicherte Änderung, weil der Vergleichsstand mitwandert. + setForm(res.settings); + setData((d) => (d ? { ...d, settings: res.settings } : d)); + flash(res.wiederverwendet + ? `✓ Vorhandenen ${res.art === 'rolle' ? 'Rolle' : 'Kanal'} „${res.name}" verknüpft` + : `✓ ${res.art === 'rolle' ? 'Rolle' : 'Kanal'} „${res.name}" angelegt`); + } catch (error) { + flash(`✗ ${error.body?.error ?? 'Anlegen fehlgeschlagen'}`); + } finally { + setCreating(null); + } + } + /** Alle geänderten Stellwerte auf einmal speichern */ async function saveTuning() { const changed = Object.fromEntries( @@ -1023,8 +1044,22 @@ export default function Settings({ me }) {
{m.name} - {m.missing.join(', ')} + {m.missing.map((x) => x.label).join(', ')} + {/* Was der Bot selbst anlegen kann, bekommt einen Knopf dafür */} + {m.missing.filter((x) => x.create).map((x) => ( + + ))} {m.tab && (