Modul-Seiten: alles zu einer Funktion an einem Ort
Bisher war eine Funktion über vier Bereiche verteilt: Schalter unter Module, Kanal unter Support, Texte unter Texte, Werte unter Werte. Wer die Begrüßung ändern wollte, brauchte drei Bereiche. Jetzt öffnet ein Klick auf die Karte die Seite dieser Funktion — mit Schalter, ihren Kanälen und Feldern, ihren Texten, ihren Werten und dem Weg zum passenden Werkzeug. Für „Willkommen" also Kanal, Karte, Farben, Vorschau und beide Texte untereinander. Bewusst keine 35 Einträge in der Seitenleiste: das Modul-Raster ist die Navigation, wie bei MEE6. Die Seitenleiste bleibt so lang wie vorher. Die Seite wird aus den Registern gebaut, nicht von Hand: modules.js kennt die Felder (neu: `fields` für alles jenseits der Pflichtkanäle, `tool` für den Verweis auf einen Editor), templates.js hatte die Zuordnung schon, tuning.js hat sie bekommen. Eine neue Funktion bekommt ihre Seite dadurch geschenkt — es gibt keinen Ort, an dem man sie vergessen könnte. Was ein eigenes Werkzeug hat — Rollen-Menüs, Bewerbungen, Composer, Server-Monitor —, bleibt in seinem Bereich; die Modul-Seite verlinkt nur dorthin. Dort ist mehr Platz, und die Editoren lassen sich nicht sinnvoll aus Registern erzeugen. Texte und Werte bleiben zusätzlich als flache Übersicht: wer alle Texte am Stück durchgehen will, soll dafür nicht 27 Seiten öffnen müssen. Beim Umbau ist mir ein Skript in die Quelldatei gelaufen — der Schreibvorgang scheiterte an einem Emoji und hinterließ modules.js leer. Wiederhergestellt aus dem letzten Commit; die Skripte schreiben jetzt erst in eine Zwischendatei und benennen danach um. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
IconSearch, IconSystem as IconTune,
|
||||
} from '../icons.jsx';
|
||||
import { moduleIcon } from '../module-icons.jsx';
|
||||
import ModulePage from '../components/ModulePage.jsx';
|
||||
import { findSettings, SETTING_INDEX } from '../setting-index.js';
|
||||
import { Markdown } from '../markdown.jsx';
|
||||
|
||||
@@ -245,10 +246,11 @@ function fmtBytes(b) {
|
||||
export default function Settings({ me }) {
|
||||
// Tab steht in der Adresse (#texte), damit Neuladen und Links den Bereich behalten
|
||||
const [tab, setTabState] = useState(
|
||||
() => TABS.find((t) => t.id === window.location.hash.slice(1))?.id ?? 'status'
|
||||
() => TABS.find((t) => t.id === window.location.hash.slice(1).split('/')[0])?.id ?? 'status'
|
||||
);
|
||||
const setTab = (id) => {
|
||||
setTabState(id);
|
||||
setOpenModuleState(null);
|
||||
window.history.replaceState(null, '', `#${id}`);
|
||||
};
|
||||
const [tabSearch, setTabSearch] = useState('');
|
||||
@@ -304,6 +306,14 @@ export default function Settings({ me }) {
|
||||
const [modules, setModules] = useState([]);
|
||||
const [moduleGroups, setModuleGroups] = useState([]);
|
||||
const [modFilter, setModFilter] = useState('alle');
|
||||
// Offene Modul-Seite steht mit in der Adresse: #module/welcome
|
||||
const [openModule, setOpenModuleState] = useState(
|
||||
() => window.location.hash.split('/')[1] ?? null
|
||||
);
|
||||
const setOpenModule = (id) => {
|
||||
setOpenModuleState(id);
|
||||
window.history.replaceState(null, '', id ? `#module/${id}` : '#module');
|
||||
};
|
||||
const [creating, setCreating] = useState(null); // Einstellung, die gerade angelegt wird
|
||||
// Grundgerüst-Assistent
|
||||
const [plan, setPlan] = useState(null); // Vorschau, null = zu
|
||||
@@ -459,7 +469,7 @@ export default function Settings({ me }) {
|
||||
// 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;
|
||||
const id = TABS.find((t) => t.id === window.location.hash.slice(1).split('/')[0])?.id;
|
||||
if (id) setTabState(id);
|
||||
};
|
||||
window.addEventListener('hashchange', onHash);
|
||||
@@ -2355,7 +2365,21 @@ export default function Settings({ me }) {
|
||||
];
|
||||
const groupLabel = (id) => moduleGroups.find((g) => g.id === id)?.label ?? '';
|
||||
|
||||
const tabModule = (
|
||||
const tabModule = openModule ? (
|
||||
<ModulePage
|
||||
id={openModule}
|
||||
onBack={() => setOpenModule(null)}
|
||||
onToggle={toggleModule}
|
||||
form={form}
|
||||
setForm={setForm}
|
||||
PickSelect={PickSelect}
|
||||
channelItems={channelItems}
|
||||
roleItems={roleItems}
|
||||
welcomePreviewUrl={welcomePreviewUrl}
|
||||
flash={flash}
|
||||
goTab={setTab}
|
||||
/>
|
||||
) : (
|
||||
<div className="settings-section">
|
||||
<h2 className="settings-title">// Module</h2>
|
||||
<p className="section-intro">
|
||||
@@ -2387,11 +2411,17 @@ export default function Settings({ me }) {
|
||||
return (
|
||||
<div className={`card mod-card${m.enabled ? ' on' : ''}`} key={m.id}>
|
||||
<div className="mod-head">
|
||||
<span className="mod-icon"><Icon size={20} /></span>
|
||||
<span className="mod-titles">
|
||||
<span className="mod-name">{m.name}</span>
|
||||
<span className="mod-group">{groupLabel(m.group)}</span>
|
||||
</span>
|
||||
<button
|
||||
className="mod-open"
|
||||
title={`${m.name} einrichten`}
|
||||
onClick={() => setOpenModule(m.id)}
|
||||
>
|
||||
<span className="mod-icon"><Icon size={20} /></span>
|
||||
<span className="mod-titles">
|
||||
<span className="mod-name">{m.name}</span>
|
||||
<span className="mod-group">{groupLabel(m.group)}</span>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`mod-switch${m.enabled ? ' on' : ''}`}
|
||||
title={m.enabled ? 'Ausschalten' : 'Einschalten'}
|
||||
@@ -2411,16 +2441,9 @@ export default function Settings({ me }) {
|
||||
<span className="mod-ready with-icon"><IconCheck size={13} /> Einsatzbereit</span>
|
||||
)}
|
||||
{!m.enabled && <span className="mod-off">Ausgeschaltet</span>}
|
||||
{m.tab && (
|
||||
<button
|
||||
className="mod-link"
|
||||
onClick={() => (m.missing.length > 0
|
||||
? jumpToMissing(m.missing[0], m.tab)
|
||||
: setTab(m.tab))}
|
||||
>
|
||||
Einstellungen →
|
||||
</button>
|
||||
)}
|
||||
<button className="mod-link" onClick={() => setOpenModule(m.id)}>
|
||||
Einrichten →
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -2434,7 +2457,8 @@ export default function Settings({ me }) {
|
||||
<div className="settings-section">
|
||||
<h2 className="settings-title">// Texte</h2>
|
||||
<p className="section-intro">
|
||||
Alles, was der Bot nach außen schreibt. Zeile anklicken zum Bearbeiten —
|
||||
Alle Texte am Stück — wer nur die einer Funktion sucht, findet sie
|
||||
auch auf deren Modul-Seite. 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.
|
||||
@@ -2541,7 +2565,8 @@ export default function Settings({ me }) {
|
||||
<div className="settings-section">
|
||||
<h2 className="settings-title">// Werte</h2>
|
||||
<p className="section-intro">
|
||||
Zahlen, die das Verhalten steuern — wie viel XP eine Nachricht bringt,
|
||||
Alle Werte am Stück; jeder steht zusätzlich auf der Seite seiner
|
||||
Funktion. Zahlen, die das Verhalten steuern — wie viel XP eine Nachricht bringt,
|
||||
wie oft geprüft wird, wann gepostet wird. Geänderte Intervalle greifen ab
|
||||
dem nächsten Durchlauf, ohne Neustart. Neben jedem Feld steht der erlaubte
|
||||
Bereich; angepasste Werte lassen sich einzeln zurücksetzen.
|
||||
|
||||
Reference in New Issue
Block a user