diff --git a/frontend/src/components/ModulePage.jsx b/frontend/src/components/ModulePage.jsx index 8ee0e55..511ff49 100644 --- a/frontend/src/components/ModulePage.jsx +++ b/frontend/src/components/ModulePage.jsx @@ -80,6 +80,13 @@ export default function ModulePage(props) { if (fehler) return

Diese Funktion konnte nicht geladen werden.

; if (!detail) return

Lade …

; + // Listen notfalls auffüllen. Eine halbe Antwort — abgeschnitten, veraltet, + // von einem Proxy verstümmelt — hat sonst die ganze Config weiß gemacht: + // `werte.some(...)` wirft, und React reisst den Baum mit. + const felder = detail.felder ?? []; + const texte = detail.texte ?? []; + const werte = detail.werte ?? []; + const missing = detail.missing ?? []; const Icon = moduleIcon(detail.id); @@ -97,7 +104,7 @@ export default function ModulePage(props) { async function werteSpeichern() { const geaendert = Object.fromEntries( Object.entries(werteEntwurf).filter(([wid, v]) => { - const jetzt = detail.werte.find((w) => w.id === wid); + const jetzt = werte.find((w) => w.id === wid); return jetzt && String(v) !== String(jetzt.value); }) ); @@ -125,7 +132,7 @@ export default function ModulePage(props) { } } - const werteOffen = detail.werte.some( + const werteOffen = werte.some( (w) => werteEntwurf[w.id] !== undefined && String(werteEntwurf[w.id]) !== String(w.value) ); @@ -159,22 +166,22 @@ export default function ModulePage(props) { - {detail.enabled && detail.missing.length > 0 && ( + {detail.enabled && missing.length > 0 && (

- Fehlt noch: {detail.missing.map((m) => m.label).join(', ')} + Fehlt noch: {missing.map((m) => m.label).join(', ')}

)} - {detail.enabled && detail.missing.length === 0 && ( + {detail.enabled && missing.length === 0 && (

Einsatzbereit

)} {/* Kanäle, Rollen und alles Weitere */} - {detail.felder.length > 0 && ( + {felder.length > 0 && (

Einstellungen

- {detail.felder.filter((f) => f.art !== 'farbe').map((f) => ( + {felder.filter((f) => f.art !== 'farbe').map((f) => (
{f.art !== 'schalter' && (
))} - {detail.felder.some((f) => f.art === 'farbe') && ( + {felder.some((f) => f.art === 'farbe') && (
- {detail.felder.filter((f) => f.art === 'farbe').map((f) => ( + {felder.filter((f) => f.art === 'farbe').map((f) => ( 0 && ( + {texte.length > 0 && (

Texte

- {detail.texte.map((t) => { + {texte.map((t) => { const entwurf = textEntwurf[t.id]; const wert = entwurf ?? t.text; const geaendert = entwurf != null && entwurf !== t.text; @@ -294,11 +301,11 @@ export default function ModulePage(props) { )} {/* Werte dieser Funktion */} - {detail.werte.length > 0 && ( + {werte.length > 0 && (

Werte

- {detail.werte.map((w) => { + {werte.map((w) => { const wert = werteEntwurf[w.id] ?? w.value; const geaendert = werteEntwurf[w.id] !== undefined && String(werteEntwurf[w.id]) !== String(w.value); return ( diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index 3d1e63d..8da47a7 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -4103,7 +4103,12 @@ export default function Settings({ me }) { {TAB_SECTIONS.map((section) => { const items = foundTabs.filter((t) => t.section === section.id); - if (items.length === 0) return null; + // Module mit `nav` bekommen hier einen festen Platz — + // sonst sind sie nur übers Raster erreichbar oder + // solange man sie angeheftet lässt. + const eigene = modules.filter((m) => m.nav && m.group === section.id + && (!query || m.name.toLowerCase().includes(query.toLowerCase()))); + if (items.length === 0 && eigene.length === 0) return null; return (
{section.label} @@ -4117,6 +4122,19 @@ export default function Settings({ me }) { {t.label} ))} + {eigene.map((m) => { + const Icon = moduleIcon(m.id); + return ( + + ); + })}
); })} diff --git a/src/modules.js b/src/modules.js index 5a4e22e..9fe27e0 100644 --- a/src/modules.js +++ b/src/modules.js @@ -247,7 +247,7 @@ export const MODULES = [ tool: { tab: 'server', label: 'Game-Server verwalten' }, }, { - id: 'ls_farm', group: 'gaming', name: 'LS — Höfe & Preise', + id: 'ls_farm', group: 'gaming', name: 'LS — Höfe & Preise', nav: true, desc: 'Landwirtschafts-Simulator: Besitzkarte mit Höfen, Fahrzeugen und Spielern, ' + 'dazu die Preiskurven übers Jahr. Braucht einen LS-Server mit Zugangs-Code unter „Game-Server".', tab: 'server', setting: 'ls_farm_enabled', @@ -481,6 +481,11 @@ export function moduleStates() { desc: mod.desc, group: mod.group, tab: mod.tab ?? null, + // Bekommt einen festen Platz in der Seitenleiste, unter der eigenen + // Gruppe. Für Module gedacht, die eine ganze Seite füllen — sonst + // erreicht man sie nur über das Raster oder als angeheftete Funktion, + // und dann steht ausgerechnet das grösste Modul nirgends. + nav: mod.nav === true, enabled: moduleEnabled(mod.id), missing: moduleMissing(mod), }));