Modul-Tab im Plugin-Raster: Filter-Reiter und Symbole
Vorbild war das MEE6-Dashboard: Kategorie-Reiter über einem Raster aus Karten, jede mit einem eigenen Symbol. Inhaltlich war unser Modul-Tab schon dort — es fehlten genau diese zwei Dinge. Die Gruppen standen als Überschriften untereinander, was bei 35 Karten eine lange Rolle ergab. Jetzt filtern Reiter mit Anzahl: Alle, die vier Gruppen, dazu „Noch einzurichten" und „Ausgeschaltet". Die beiden letzten sind bewusst dabei — mit genau diesen Fragen kommt man am häufigsten her. Die Gruppe steht klein unter dem Namen, damit sie im gefilterten Raster nicht verlorengeht. Jede Karte hat eine Symbol-Kachel, die bei laufendem Modul in der Markenfarbe leuchtet und sonst grau bleibt — man erkennt eine Funktion damit am Bild statt am Lesen. Die Zuordnung lag schon in der Funktionsseite; sie liegt jetzt in module-icons.jsx, damit beide Seiten dieselbe benutzen. Farbige Kachelbilder wie bei MEE6 gibt es bewusst nicht: die Strichsymbole passen zum Rest der Oberfläche, bunte Kacheln wären ein Fremdkörper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
IconHome as IconLayers, IconWarning, IconCheck, IconMessage, IconRefresh,
|
||||
IconSearch, IconSystem as IconTune,
|
||||
} from '../icons.jsx';
|
||||
import { moduleIcon } from '../module-icons.jsx';
|
||||
import { Markdown } from '../markdown.jsx';
|
||||
|
||||
const API_SCOPES = [
|
||||
@@ -225,6 +226,7 @@ export default function Settings({ me }) {
|
||||
// Module (An/Aus für alle Funktionen)
|
||||
const [modules, setModules] = useState([]);
|
||||
const [moduleGroups, setModuleGroups] = useState([]);
|
||||
const [modFilter, setModFilter] = useState('alle');
|
||||
// Text-Vorlagen (was der Bot nach außen schreibt)
|
||||
const [templates, setTemplates] = useState([]);
|
||||
const [templateGroups, setTemplateGroups] = useState([]);
|
||||
@@ -1997,6 +1999,25 @@ export default function Settings({ me }) {
|
||||
</>
|
||||
);
|
||||
|
||||
// Filter über dem Modul-Raster — bei 35 Karten ist eine lange Liste
|
||||
// untereinander mühsam. „Noch einzurichten" ist bewusst dabei: das ist die
|
||||
// Frage, mit der man am häufigsten herkommt.
|
||||
const shownModules = modules.filter((m) => {
|
||||
if (modFilter === 'alle') return true;
|
||||
if (modFilter === 'todo') return m.enabled && m.missing.length > 0;
|
||||
if (modFilter === 'aus') return !m.enabled;
|
||||
return m.group === modFilter;
|
||||
});
|
||||
const modFilters = [
|
||||
{ id: 'alle', label: 'Alle', n: modules.length },
|
||||
...moduleGroups.map((g) => ({
|
||||
id: g.id, label: g.label, n: modules.filter((m) => m.group === g.id).length,
|
||||
})),
|
||||
{ id: 'todo', label: 'Noch einzurichten', n: modules.filter((m) => m.enabled && m.missing.length > 0).length },
|
||||
{ id: 'aus', label: 'Ausgeschaltet', n: modules.filter((m) => !m.enabled).length },
|
||||
];
|
||||
const groupLabel = (id) => moduleGroups.find((g) => g.id === id)?.label ?? '';
|
||||
|
||||
const tabModule = (
|
||||
<div className="settings-section">
|
||||
<h2 className="settings-title">// Module</h2>
|
||||
@@ -2007,47 +2028,63 @@ export default function Settings({ me }) {
|
||||
der Karte.
|
||||
</p>
|
||||
|
||||
{moduleGroups.map((group) => {
|
||||
const mods = modules.filter((m) => m.group === group.id);
|
||||
if (mods.length === 0) return null;
|
||||
return (
|
||||
<div key={group.id} style={{ marginBottom: '1.8rem' }}>
|
||||
<h3 className="settings-title" style={{ fontSize: '.66rem', marginBottom: '.8rem' }}>
|
||||
{group.label}
|
||||
</h3>
|
||||
<div className="mod-grid">
|
||||
{mods.map((m) => (
|
||||
<div className={`card mod-card${m.enabled ? ' on' : ''}`} key={m.id}>
|
||||
<div className="mod-head">
|
||||
<div className="mod-filters">
|
||||
{modFilters.map((f) => (
|
||||
<button
|
||||
key={f.id}
|
||||
className={`mod-filter${modFilter === f.id ? ' active' : ''}`}
|
||||
disabled={f.n === 0 && modFilter !== f.id}
|
||||
onClick={() => setModFilter(f.id)}
|
||||
>
|
||||
{f.label} <span className="mod-filter-n">{f.n}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{shownModules.length === 0 ? (
|
||||
<p className="notice">Hier ist gerade nichts.</p>
|
||||
) : (
|
||||
<div className="mod-grid">
|
||||
{shownModules.map((m) => {
|
||||
const Icon = moduleIcon(m.id);
|
||||
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>
|
||||
<button
|
||||
className={`mod-switch${m.enabled ? ' on' : ''}`}
|
||||
title={m.enabled ? 'Ausschalten' : 'Einschalten'}
|
||||
onClick={() => toggleModule(m.id, !m.enabled)}
|
||||
>
|
||||
<span className="mod-knob" />
|
||||
</button>
|
||||
</div>
|
||||
<p className="mod-desc">{m.desc}</p>
|
||||
<span className="mod-group">{groupLabel(m.group)}</span>
|
||||
</span>
|
||||
<button
|
||||
className={`mod-switch${m.enabled ? ' on' : ''}`}
|
||||
title={m.enabled ? 'Ausschalten' : 'Einschalten'}
|
||||
onClick={() => toggleModule(m.id, !m.enabled)}
|
||||
>
|
||||
<span className="mod-knob" />
|
||||
</button>
|
||||
</div>
|
||||
<p className="mod-desc">{m.desc}</p>
|
||||
<div className="mod-foot">
|
||||
{m.enabled && m.missing.length > 0 && (
|
||||
<p className="mod-missing with-icon">
|
||||
<IconWarning size={13} /> Fehlt noch: {m.missing.join(', ')}
|
||||
</p>
|
||||
<span className="mod-missing with-icon">
|
||||
<IconWarning size={13} /> Fehlt: {m.missing.join(', ')}
|
||||
</span>
|
||||
)}
|
||||
{m.enabled && m.missing.length === 0 && (
|
||||
<p className="mod-ready with-icon"><IconCheck size={13} /> Einsatzbereit</p>
|
||||
<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={() => setTab(m.tab)}>
|
||||
Einstellungen →
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user