chore: Demo-Daten, Bildaufnahme und Platz in der Kopfleiste

Die Demo-Instanz redet mit niemandem mehr: Solange DEMO_MODUS gilt,
starten die Jobs fuer Zammad, Telegram und den Spiegel gar nicht erst.
Sie ist mit erfundenen Daten gefuellt und steht nur fuer Bilder — ein
Aufruf nach draussen waere bestenfalls sinnlos.

Die Kopfleiste ist breiter als die Inhaltsspalte. Mit dem elften Eintrag
passte sie dort nicht mehr, und "Einstellungen" verschwand
stillschweigend am rechten Rand. Aufgefallen ist das erst im
aufgenommenen Bild.

Der Kartentext beschrieb noch den Weg von vor dem Kopplungscode.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-12 04:51:37 +02:00
co-authored by Claude Opus 5
parent f5eadefdbb
commit 3c7cdbbbf3
6 changed files with 71 additions and 8 deletions
+5
View File
@@ -68,5 +68,10 @@ services:
# moeglich, hinaus geht trotzdem nichts. # moeglich, hinaus geht trotzdem nichts.
SMTP_HOST: smtp.planer.invalid SMTP_HOST: smtp.planer.invalid
SMTP_ABSENDER: Planer <planer@planer.invalid> SMTP_ABSENDER: Planer <planer@planer.invalid>
# Erfundene Werte, damit die Seite "Integrationen" den eingerichteten
# Fall zeigt. Nach draussen geht davon nichts: Die Jobs schweigen,
# solange DEMO_MODUS true ist.
TELEGRAM_TOKEN: 000000:demo-token-ohne-funktion
SPIEGEL_GEHEIMNIS: demo-geheimnis-ohne-funktion
ports: ports:
- '${SCREENSHOT_APP_PORT:-3200}:3000' - '${SCREENSHOT_APP_PORT:-3200}:3000'
+47
View File
@@ -429,6 +429,7 @@ async function main(): Promise<void> {
anlaesse: 'tagesueberblick,faelligkeit,zeitblock', anlaesse: 'tagesueberblick,faelligkeit,zeitblock',
perPush: true, perPush: true,
perMail: true, perMail: true,
perTelegram: true,
ueberblickUm: 7 * 60, ueberblickUm: 7 * 60,
ruheVon: 20 * 60, ruheVon: 20 * 60,
ruheBis: 7 * 60, ruheBis: 7 * 60,
@@ -442,6 +443,52 @@ async function main(): Promise<void> {
// nicht lesen kann. Ein erfundener Eintrag verschwände beim ersten Lauf // nicht lesen kann. Ein erfundener Eintrag verschwände beim ersten Lauf
// wieder — die Bilder zeigen deshalb den Zustand vor der ersten Anmeldung. // wieder — die Bilder zeigen deshalb den Zustand vor der ersten Anmeldung.
// --- Integrationen --------------------------------------------------------
await db.integrationszustand.deleteMany({})
await db.integrationszustand.create({
data: {
quelle: 'TELEGRAM',
merker: '4711',
letzterLauf: new Date(Date.UTC(2026, 2, 17, 8, 18)),
letzterErfolg: new Date(Date.UTC(2026, 2, 17, 8, 18)),
},
})
await db.integrationszustand.create({
data: {
quelle: 'SPIEGEL',
letzterLauf: new Date(Date.UTC(2026, 2, 17, 8, 15)),
letzterErfolg: new Date(Date.UTC(2026, 2, 17, 8, 15)),
},
})
await db.telegramChat.deleteMany({})
await db.telegramChat.create({
data: {
// Erfunden. Der Bot ist ohnehin abgeschaltet, solange DEMO_MODUS gilt.
chatId: BigInt(147258369),
benutzerId: benutzer.id,
bezeichnung: 'Martina',
erstelltAm: new Date(Date.UTC(2026, 1, 3, 8, 25)),
zuletztBenutzt: new Date(Date.UTC(2026, 2, 17, 6, 40)),
},
})
// Dienstliche Belegung, wie sie aus der Firma hereinkaeme: ohne Titel.
await db.spiegelbelegung.deleteMany({})
for (const [tag, stunde, dauer] of [
[17, 9, 2],
[18, 13, 3],
[19, 8, 1],
] as const) {
await db.spiegelbelegung.create({
data: {
quelleRef: `demo-spiegel-${tag}-${stunde}`,
beginn: new Date(Date.UTC(2026, 2, tag, stunde - 1, 0)),
ende: new Date(Date.UTC(2026, 2, tag, stunde - 1 + dauer, 0)),
},
})
}
console.log(`Demo-Daten stehen bereit. Anmeldung: ${DEMO_EMAIL}`) console.log(`Demo-Daten stehen bereit. Anmeldung: ${DEMO_EMAIL}`)
} }
+1
View File
@@ -43,6 +43,7 @@ const AUFNAHMEN: Aufnahme[] = [
{ name: 'ideen', pfad: '/ideen' }, { name: 'ideen', pfad: '/ideen' },
{ name: 'bereiche', pfad: '/bereiche' }, { name: 'bereiche', pfad: '/bereiche' },
{ name: 'kalenderkonten', pfad: '/kalenderkonten' }, { name: 'kalenderkonten', pfad: '/kalenderkonten' },
{ name: 'integrationen', pfad: '/integrationen' },
{ name: 'einstellungen', pfad: '/einstellungen' }, { name: 'einstellungen', pfad: '/einstellungen' },
{ {
name: 'benachrichtigungen', name: 'benachrichtigungen',
+3 -4
View File
@@ -166,10 +166,9 @@ export default async function IntegrationenSeite() {
<CardTitel className="text-base">Telegram-Chats</CardTitel> <CardTitel className="text-base">Telegram-Chats</CardTitel>
<CardBeschreibung> <CardBeschreibung>
Nur wer hier steht, darf mit dem Bot reden — und nur diese Chats bekommen Nur wer hier steht, darf mit dem Bot reden — und nur diese Chats bekommen
Meldungen. Alles andere wird verworfen, ohne zu antworten. Die Kennung Meldungen. Alles andere wird verworfen, ohne zu antworten. Zum Verbinden
deines Chats verrät dir der Bot, wenn du ihm{' '} holst du dir hier einen Code und schickst ihn dem Bot; er gilt zehn Minuten
<code className="text-xs">/start</code> schickst und danach hier nachsiehst; und genau einmal.
steht sie noch nicht drin, findest du sie im Protokoll.
</CardBeschreibung> </CardBeschreibung>
</CardKopf> </CardKopf>
<CardInhalt> <CardInhalt>
+7 -1
View File
@@ -50,7 +50,13 @@ export function Kopfleiste({
Navigation waagerecht, statt umzubrechen und den Namen der Anwendung in Navigation waagerecht, statt umzubrechen und den Namen der Anwendung in
die zweite Zeile zu drängen. die zweite Zeile zu drängen.
*/} */}
<div className="mx-auto flex w-full max-w-5xl items-center gap-3 px-4 py-3 sm:gap-6"> {/*
Breiter als die Inhaltsspalte (max-w-5xl): Mit dem elften Eintrag
passte die Leiste dort nicht mehr, und "Einstellungen" verschwand
stillschweigend am rechten Rand. Eine Leiste, die Punkte verschluckt,
ist schlimmer als eine, die nicht buendig mit dem Text steht.
*/}
<div className="mx-auto flex w-full max-w-7xl items-center gap-3 px-4 py-3 sm:gap-5">
<Link href="/" className="shrink-0 text-base font-semibold tracking-tight"> <Link href="/" className="shrink-0 text-base font-semibold tracking-tight">
Planer Planer
</Link> </Link>
+8 -3
View File
@@ -111,7 +111,12 @@ export function jobsStarten(): void {
const einst = umgebung() const einst = umgebung()
if (einst.zammadAktiv) { // Die Demo-Instanz redet mit niemandem. Sie ist mit erfundenen Daten
// gefuellt und steht nur fuer Bilder – ein Aufruf nach draussen waere
// bestenfalls sinnlos und schlimmstenfalls peinlich.
const nachDraussen = !einst.DEMO_MODUS
if (einst.zammadAktiv && nachDraussen) {
cron.schedule(ZAMMAD_PLAN, () => { cron.schedule(ZAMMAD_PLAN, () => {
void zammadAbgleichen(DIENST) void zammadAbgleichen(DIENST)
.then((bericht) => { .then((bericht) => {
@@ -127,7 +132,7 @@ export function jobsStarten(): void {
}) })
} }
if (einst.telegramAktiv) { if (einst.telegramAktiv && nachDraussen) {
cron.schedule(TELEGRAM_PLAN, () => { cron.schedule(TELEGRAM_PLAN, () => {
void telegramAbholen(DIENST) void telegramAbholen(DIENST)
.then((bericht) => { .then((bericht) => {
@@ -142,7 +147,7 @@ export function jobsStarten(): void {
}) })
} }
if (einst.spiegelSendenAktiv) { if (einst.spiegelSendenAktiv && nachDraussen) {
cron.schedule(SPIEGEL_PLAN, () => { cron.schedule(SPIEGEL_PLAN, () => {
void spiegelSenden().catch((fehler: unknown) => { void spiegelSenden().catch((fehler: unknown) => {
console.error('Spiegel-Versand abgebrochen:', fehler) console.error('Spiegel-Versand abgebrochen:', fehler)