Kalender: was auf den Brettern steht und einen Termin hat
Filipe, zu einer Clip-Karte: "ich will dass die auch in einer kalender
drin sind, aber ich will dass es richtig geil ist und perfektionier das
bitte."
Gemessen vor dem Bau: /workspace/api/termine lieferte `termine` und
`fristen`. Die Zettel von den achtzehn Brettern kamen nirgends vor --
obwohl `eintraege` seit langem VIER Zeitfelder hat: datum, uhrzeit,
geplant, event_ende.
WELCHE HINEINGEHOEREN, IST DIE GANZE FRAGE -- und sie laesst sich
messen statt raten. `datum` ist ein Pflichtfeld und faellt auf HEUTE
zurueck, wenn niemand eins waehlt. Alle Eintraege hineinzukippen hiesse
also: jeder je getippte Zettel steht an dem Tag, an dem ihn jemand
getippt hat. Nach einem Monat waere der Kalender ein Protokoll und kein
Plan -- und ein Kalender, in dem alles steht, sagt nichts mehr.
GEZEIGT WIRD NUR, WOFUER JEMAND EINE ZEIT BESTIMMT HAT:
geplant eine Zusage ("Wird gemacht -- am 24.09.")
event_ende ein Zeitraum
uhrzeit niemand tippt aus Versehen 20:00
datum > heute der Rueckfall ist IMMER heute oder frueher
Erledigtes bleibt draussen. Der vierte Fall ist der wichtigste und der
unauffaelligste: kein neues Feld, keine Umgewoehnung.
RECHTE: dieselbe Funktion wie die Bretter selbst (`sichtbarEintrag`),
nicht eine zweite Meinung. Im Kalender steht nur eine kleine Pille mit
einem Titel -- dass darin ein vertrauliches Vorhaben steckt, faellt
niemandem auf, der nicht danach sucht. Genau so kam am 03.09. eine
Managerin an fremde Aufgabenfristen.
DREI FEHLER AM BILDSCHIRMFOTO GEFUNDEN, nicht an einer Zahl:
1. Der Brettname stand VOR dem Titel -- aus "Clip am Wochenende"
wurde "Cli...". Das Etikett verdraengte, was es einordnen sollte.
Jetzt zweite Zeile: Hoehe ist im Monatsraster der billigere Platz.
2. Am Handy (45px Zellbreite) wurde daraus ein "Co..." -- Hoehe ohne
Information. Jetzt eine CONTAINER-Abfrage: entschieden wird nach
der Breite der ZELLE, nicht des Fensters. Eine Fensterschwelle
waere wieder die Rechnung von gestern (September, Kopfleiste,
zweimal).
3. .64rem = 10,24px -- unter der Hausgrenze 11,5px, gefunden von
pruef-css-klassen. Gedaempft wird jetzt ueber Farbe und Gewicht,
nicht ueber Groesse.
EIN ECHTER FEHLER VERHINDERT: In der Listenansicht waeren die Zettel im
Termin-Zweig gelandet -- mit Wecker, "erledigt" und "loeschen". Der
Knopf haette PATCH /api/termine/b12 geschickt: eine Nummer, die es dort
nicht gibt, an eine Schnittstelle, die davon nichts weiss. Still, ohne
Wirkung, ohne Meldung.
DER WEG FUEHRT AUF DEN ZETTEL, nicht nur auf das Brett -- ueber
`?zeigen=` (kopf.js), den Weg, den das Haus dafuer schon hat. Zwischen
zwanzig Eintraegen waere der gesuchte sonst von Hand zu suchen.
pruef-kalender: +25 Pruefungen. Sieben Gegenproben, jede zielgenau:
Schnitt weg -> 6 rot Erledigtes rein -> 6 rot
Rechteregel ausgehebelt-> 1 rot COALESCE weg -> 1 rot
Termin-Knoepfe an -> 2 rot Container-Regel weg -> 1 rot
Sprung-Zweig weg -> 3 rot
UND SIEBEN FESTE ZAHLEN ABGELEITET. Die alten Pruefungen zaehlten
"alle fünf Einträge", "vier Arten", "vier Filter" -- mit den neuen
Testdaten wurden daraus zehn, und sieben Pruefungen je Bildschirmgroesse
wurden rot, ohne dass am Kalender etwas kaputt war. Mit `git stash`
nachgemessen (ohne meine Aenderung: 0 Fehler), also nicht angepasst,
sondern gerechnet: jede Zahl kommt jetzt aus den Testdaten darueber.
Zwei eigene Pruefungsfehler dabei behoben: ein falscher Umschalter-
Selektor liess `every()` auf einem leeren Feld laufen (gruen ohne
Daten), und die Sichtbarkeit der zweiten Zeile wurde ueber
`textContent` gemessen -- das liefert auch, was `display: none`
ausblendet.
Gruen: kalender, sprung, namen, css-klassen, struktur.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -20,6 +20,16 @@ import {
|
||||
import {
|
||||
nachfuellenAlle, serienPruefen, serieAnlegen, zuordnungErzwingen,
|
||||
} from "./workspace-serien.js";
|
||||
/* DIE SICHTBARKEIT DER BRETTEINTRAEGE KOMMT AUS IHREM EIGENEN HAUS.
|
||||
|
||||
`sichtbarEintrag` ist dieselbe Funktion, durch die auch das Lesen
|
||||
eines Bretts, das Aendern und das Loeschen gehen. Eine hier
|
||||
nachgebaute Fassung waere eine zweite Meinung darueber, wer was
|
||||
sehen darf -- und die zweite ist erfahrungsgemaess die, die mehr
|
||||
durchlaesst. Genau so kam am 03.09. eine Managerin an fremde
|
||||
Aufgabenfristen: nicht durch ein Loch, sondern durch eine zweite
|
||||
Regel, die "istLeitung" fragte statt der richtigen. */
|
||||
import { sichtbarEintrag, BEREICHE } from "./workspace-bereiche.js";
|
||||
|
||||
export const kalenderRouter = express.Router();
|
||||
|
||||
@@ -398,7 +408,84 @@ kalenderRouter.get("/workspace/api/termine", (req, res) => {
|
||||
for (const t of termine) t.checkliste_aufgaben = gezaehlt.get(t.id) || 0;
|
||||
}
|
||||
}
|
||||
res.json({ termine, fristen, von, bis, checkliste_moeglich: moeglich });
|
||||
/* =================================================================
|
||||
WAS AUF DEN BRETTERN STEHT UND EINEN TERMIN HAT (17.09.2026)
|
||||
|
||||
Filipe, zu einem Bildschirmfoto einer Clip-Karte: „ich will dass
|
||||
die auch in einer kalender drin sind."
|
||||
|
||||
WELCHE? Das ist die ganze Frage, und sie laesst sich messen
|
||||
statt raten. `eintraege.datum` ist ein PFLICHTFELD und faellt
|
||||
auf „heute" zurueck, wenn niemand eins waehlt (workspace-
|
||||
bereiche.js, pruefe()). Alle Eintraege in den Kalender zu kippen
|
||||
hiesse deshalb: jeder je angelegte Zettel steht an dem Tag, an
|
||||
dem ihn jemand getippt hat. Nach einem Monat waere der Kalender
|
||||
ein Protokoll und kein Plan -- und ein Kalender, in dem alles
|
||||
steht, sagt nichts mehr.
|
||||
|
||||
GEZEIGT WIRD DESHALB NUR, WOFUER JEMAND EINE ZEIT BESTIMMT HAT.
|
||||
Vier Faelle, jeder einzeln begruendbar:
|
||||
|
||||
geplant Eine Zusage. „Wird gemacht -- am 24.09." Das ist
|
||||
ein Termin, den jemand jemandem gegeben hat.
|
||||
event_ende Ein Zeitraum. Wer ein Ende eintraegt, meint eine
|
||||
Veranstaltung, keine Notiz.
|
||||
uhrzeit Wer eine Uhrzeit tippt, meint einen Zeitpunkt.
|
||||
Niemand traegt aus Versehen 20:00 ein.
|
||||
datum > heute Der Rueckfall ist IMMER heute oder frueher. Ein
|
||||
Datum in der Zukunft kann nur Absicht sein.
|
||||
|
||||
Der vierte Fall ist der wichtigste und der unauffaelligste: Er
|
||||
braucht kein neues Feld und keine Umgewoehnung. Wer einem
|
||||
Eintrag ein kuenftiges Datum gibt, hat ihn geplant -- und sieht
|
||||
ihn ab sofort im Kalender.
|
||||
|
||||
ERLEDIGTES BLEIBT DRAUSSEN. Ein Kalender zeigt, was ansteht.
|
||||
Was schon gemacht ist, gehoert auf sein Brett, nicht in die
|
||||
Planung der naechsten Woche. */
|
||||
const eintragRegel = sichtbarEintrag(req.person, "e");
|
||||
const brettsachen = eintragRegel ? db().prepare(`
|
||||
SELECT e.id, e.bereich, e.art, e.titel, e.text, e.status,
|
||||
e.dringlichkeit, e.datum, e.uhrzeit, e.geplant, e.event_ende,
|
||||
pe.name AS von_name,
|
||||
/* WELCHER TAG ZAEHLT -- abgeleitet, nicht im Browser
|
||||
nachgerechnet. Eine Zusage schlaegt das Erfassungsdatum:
|
||||
Wer sagt "am 24.", meint den 24., auch wenn der Zettel
|
||||
am 3. entstanden ist. */
|
||||
COALESCE(e.geplant, e.datum) AS wann,
|
||||
CASE
|
||||
WHEN e.geplant IS NOT NULL THEN 'zugesagt'
|
||||
WHEN e.event_ende IS NOT NULL THEN 'zeitraum'
|
||||
WHEN e.uhrzeit IS NOT NULL THEN 'uhrzeit'
|
||||
ELSE 'termin'
|
||||
END AS grund
|
||||
FROM eintraege e
|
||||
LEFT JOIN personen pe ON pe.id = e.erstellt_von
|
||||
WHERE ${eintragRegel.wo}
|
||||
AND e.status NOT IN ('erledigt', 'abgelehnt')
|
||||
AND (
|
||||
e.geplant IS NOT NULL
|
||||
OR e.event_ende IS NOT NULL
|
||||
OR e.uhrzeit IS NOT NULL
|
||||
OR e.datum > ?
|
||||
)
|
||||
AND COALESCE(e.geplant, e.datum) >= ?
|
||||
AND COALESCE(e.geplant, e.datum) <= ?
|
||||
ORDER BY wann, e.uhrzeit, e.id`)
|
||||
.all(...eintragRegel.werte, heuteLokal(), von, bis) : [];
|
||||
|
||||
/* DER NAME DES BRETTS KOMMT MIT -- und zwar aus dem Katalog, nicht
|
||||
als abgeschriebene Liste im Browser. Ein Brett, das morgen
|
||||
dazukommt, steht damit von selbst richtig da; eine zweite Liste
|
||||
waere die, die beim naechsten Mal vergessen wird. */
|
||||
for (const b of brettsachen) {
|
||||
b.brett_name = BEREICHE[b.bereich]?.name || b.bereich;
|
||||
/* Nur die ersten Zeilen -- im Kalender steht eine Pille, kein
|
||||
Aufsatz. Der ganze Text steht auf dem Brett. */
|
||||
b.text = b.text ? String(b.text).slice(0, 180) : null;
|
||||
}
|
||||
|
||||
res.json({ termine, fristen, brettsachen, von, bis, checkliste_moeglich: moeglich });
|
||||
} catch (fehler) {
|
||||
console.error("[workspace] Termine lesen:", fehler?.message);
|
||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||
|
||||
Reference in New Issue
Block a user