„Einrichten" zeigt jetzt, was fehlt — und Env-Werte gelten als gesetzt
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

Zwei Fehler, die zusammen für Ratlosigkeit gesorgt haben.

In der Liste stand „Fehlermeldungen — Gitea-Token", obwohl das Token über
GITEA_API_TOKEN längst gesetzt war und /bug lief. Grund: die
Voraussetzungs-Prüfung las die Einstellung roh statt den wirksamen Wert,
sah also nur in die Datenbank und nicht in die Umgebung. Betraf außerdem
Devlog-Kanal, Commit-Kanal und Guild-ID. runtime-settings hat dafür jetzt
effectiveSetting(), das beides zusammenführt.

Und wer dann auf „Einrichten" drückte, landete im System-Bereich — dort
gibt es gar kein Token-Feld, das steht bei Brand. Das Modul zeigte auf den
falschen Bereich.

Jetzt springt „Einrichten" auf das konkrete Feld und hebt es kurz hervor,
statt nur den Bereich zu wechseln. Der Bereich kommt dabei aus dem
Einstellungs-Register, das ohnehin weiß, wo jedes Feld liegt — damit kann
die Zuordnung am Modul nicht mehr auseinanderlaufen. Dieselbe Logik hängt
an „Einstellungen →" auf den Modul-Karten.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 21:43:34 +02:00
co-authored by Claude Fable 5
parent 01fadadcd8
commit bea35234c6
4 changed files with 56 additions and 10 deletions
+25 -8
View File
@@ -9,7 +9,7 @@ import {
IconSearch, IconSystem as IconTune, IconSearch, IconSystem as IconTune,
} from '../icons.jsx'; } from '../icons.jsx';
import { moduleIcon } from '../module-icons.jsx'; import { moduleIcon } from '../module-icons.jsx';
import { findSettings } from '../setting-index.js'; import { findSettings, SETTING_INDEX } from '../setting-index.js';
import { Markdown } from '../markdown.jsx'; import { Markdown } from '../markdown.jsx';
const API_SCOPES = [ const API_SCOPES = [
@@ -348,6 +348,16 @@ export default function Settings({ me }) {
// … und zusätzlich auf einzelne Einstellungen, mit Sprung aufs Feld // … und zusätzlich auf einzelne Einstellungen, mit Sprung aufs Feld
const foundSettings = query ? findSettings(query, canTab) : []; const foundSettings = query ? findSettings(query, canTab) : [];
/**
* Zum Feld einer Einstellung springen — der Bereich kommt aus dem Register,
* damit „Einrichten" nicht im falschen Tab landet (das Gitea-Token steht
* z. B. bei Brand, nicht bei System).
*/
function jumpToMissing(fehlt, fallbackTab) {
const bekannt = SETTING_INDEX.find((s) => s.id === fehlt.setting);
jumpToSetting(bekannt ?? { id: fehlt.setting, tab: fallbackTab });
}
/** Bereich wechseln, zum Feld scrollen und es kurz hervorheben */ /** Bereich wechseln, zum Feld scrollen und es kurz hervorheben */
function jumpToSetting(entry) { function jumpToSetting(entry) {
setTab(entry.tab); setTab(entry.tab);
@@ -1155,11 +1165,13 @@ export default function Settings({ me }) {
: `${x.create.rolle ? 'Rolle' : 'Kanal'} anlegen`} : `${x.create.rolle ? 'Rolle' : 'Kanal'} anlegen`}
</button> </button>
))} ))}
{m.tab && ( <button
<button className="btn-mini" onClick={() => setTab(m.tab)}> className="btn-mini"
Einrichten title={`Zum Feld „${m.missing[0].label}" springen`}
</button> onClick={() => jumpToMissing(m.missing[0], m.tab)}
)} >
Einrichten
</button>
</div> </div>
))} ))}
</div> </div>
@@ -1244,7 +1256,7 @@ export default function Settings({ me }) {
<label>Guild-ID <span className="field-hint">für sofortige Slash-Commands; greift beim nächsten Neustart</span></label> <label>Guild-ID <span className="field-hint">für sofortige Slash-Commands; greift beim nächsten Neustart</span></label>
<input type="text" placeholder="Server-ID" value={form.discord_guild_id} onChange={(e) => setForm({ ...form, discord_guild_id: e.target.value })} /> <input type="text" placeholder="Server-ID" value={form.discord_guild_id} onChange={(e) => setForm({ ...form, discord_guild_id: e.target.value })} />
</div> </div>
<div className="field"> <div className="field" data-setting="gitea_api_token">
<label>Gitea-API-Token <span className="field-hint">{form.gitea_api_token_set ? '✓ gesetzt — neuen Wert eingeben zum Ersetzen' : 'für /bug; wird nie wieder angezeigt'}</span></label> <label>Gitea-API-Token <span className="field-hint">{form.gitea_api_token_set ? '✓ gesetzt — neuen Wert eingeben zum Ersetzen' : 'für /bug; wird nie wieder angezeigt'}</span></label>
<input type="password" placeholder="Token (write-only)" value={giteaToken} onChange={(e) => setGiteaToken(e.target.value)} /> <input type="password" placeholder="Token (write-only)" value={giteaToken} onChange={(e) => setGiteaToken(e.target.value)} />
</div> </div>
@@ -2400,7 +2412,12 @@ export default function Settings({ me }) {
)} )}
{!m.enabled && <span className="mod-off">Ausgeschaltet</span>} {!m.enabled && <span className="mod-off">Ausgeschaltet</span>}
{m.tab && ( {m.tab && (
<button className="mod-link" onClick={() => setTab(m.tab)}> <button
className="mod-link"
onClick={() => (m.missing.length > 0
? jumpToMissing(m.missing[0], m.tab)
: setTab(m.tab))}
>
Einstellungen Einstellungen
</button> </button>
)} )}
+1
View File
@@ -83,6 +83,7 @@ export const SETTING_INDEX = [
{ id: 'cookie_domain', tab: 'system', label: 'Cookie-Domain', find: 'login beide domains' }, { id: 'cookie_domain', tab: 'system', label: 'Cookie-Domain', find: 'login beide domains' },
{ id: 'gitea_url', tab: 'system', label: 'Gitea-Adresse', find: 'git server url' }, { id: 'gitea_url', tab: 'system', label: 'Gitea-Adresse', find: 'git server url' },
{ id: 'discord_guild_id', tab: 'brand', label: 'Server-ID', find: 'guild id discord' }, { id: 'discord_guild_id', tab: 'brand', label: 'Server-ID', find: 'guild id discord' },
{ id: 'gitea_api_token', tab: 'brand', label: 'Gitea-API-Token', find: 'token bug issue schluessel' },
{ id: 'legal_name', tab: 'system', label: 'Impressum: Name', find: 'betreiber rechtstext' }, { id: 'legal_name', tab: 'system', label: 'Impressum: Name', find: 'betreiber rechtstext' },
{ id: 'legal_address', tab: 'system', label: 'Impressum: Anschrift', find: 'adresse rechtstext' }, { id: 'legal_address', tab: 'system', label: 'Impressum: Anschrift', find: 'adresse rechtstext' },
{ id: 'legal_email', tab: 'system', label: 'Impressum: E-Mail', find: 'kontakt rechtstext' }, { id: 'legal_email', tab: 'system', label: 'Impressum: E-Mail', find: 'kontakt rechtstext' },
+7 -2
View File
@@ -9,6 +9,7 @@
// arbeiten kann. Fehlt etwas, zeigt das Panel „noch nicht einsatzbereit" // arbeiten kann. Fehlt etwas, zeigt das Panel „noch nicht einsatzbereit"
// statt das Modul stillschweigend nichts tun zu lassen. // statt das Modul stillschweigend nichts tun zu lassen.
import { getSetting, setSetting } from './db.js'; import { getSetting, setSetting } from './db.js';
import { effectiveSetting } from './runtime-settings.js';
export const MODULE_GROUPS = [ export const MODULE_GROUPS = [
{ id: 'inhalte', label: 'Inhalte & Feeds' }, { id: 'inhalte', label: 'Inhalte & Feeds' },
@@ -162,7 +163,9 @@ export const MODULES = [
{ {
id: 'bug_reports', group: 'moderation', name: 'Fehlermeldungen', id: 'bug_reports', group: 'moderation', name: 'Fehlermeldungen',
desc: 'Meldungen werden zu Issues im Repository, mit Rückmeldung beim Schließen.', desc: 'Meldungen werden zu Issues im Repository, mit Rückmeldung beim Schließen.',
tab: 'system', default: true, // Der Token steht im Brand-Bereich („Aus der Env verlagert"), nicht im
// System-Bereich — sonst landet „Einrichten" an der falschen Stelle.
tab: 'brand', default: true,
requires: [{ setting: 'gitea_api_token', label: 'Gitea-Token' }], requires: [{ setting: 'gitea_api_token', label: 'Gitea-Token' }],
}, },
@@ -251,7 +254,9 @@ export function setModuleEnabled(id, on) {
*/ */
export function moduleMissing(mod) { export function moduleMissing(mod) {
return (mod.requires ?? []) return (mod.requires ?? [])
.filter((r) => !String(getSetting(r.setting) ?? '').trim()) // Effektiver Wert, nicht nur die Einstellung: was über die Umgebung
// gesetzt ist, fehlt nicht.
.filter((r) => !effectiveSetting(r.setting))
.map((r) => ({ setting: r.setting, label: r.label, create: r.create ?? null })); .map((r) => ({ setting: r.setting, label: r.label, create: r.create ?? null }));
} }
+23
View File
@@ -229,6 +229,29 @@ export function welcomeChannelId() {
return getSetting('welcome_channel_id') || null; return getSetting('welcome_channel_id') || null;
} }
/**
* Wert einer Einstellung so, wie er tatsächlich wirkt — also inklusive der
* Env-Fallbacks aus config.js.
*
* Ohne das meldet die Config Sachen als „fehlt", die über die Umgebung längst
* gesetzt sind: Wer sein Gitea-Token per GITEA_API_TOKEN übergibt, sieht in
* der Liste „Fehlermeldungen — Gitea-Token", obwohl /bug einwandfrei läuft.
*
* @param {string} key
* @returns {string}
*/
export function effectiveSetting(key) {
const gesetzt = String(getSetting(key) ?? '').trim();
if (gesetzt) return gesetzt;
const ausDerEnv = {
devlog_channel_id: config.devlogChannelId,
commit_channel_id: config.commitChannelId,
gitea_api_token: config.giteaApiToken,
discord_guild_id: config.discordGuildId,
}[key];
return String(ausDerEnv ?? '').trim();
}
/** /**
* Aussehen der Willkommens-Karte. Die Standardwerte sind der Marken-Look; * Aussehen der Willkommens-Karte. Die Standardwerte sind der Marken-Look;
* die Marken-Farben ziehen automatisch nach, solange nichts eigenes gesetzt ist. * die Marken-Farben ziehen automatisch nach, solange nichts eigenes gesetzt ist.