Gegliedert nach Alter: sieben Stufen, klappbar
Filipe: "ich will da unterkategorien die man auf und zu klappen kann,
so wie heute gestern, diese woche, diesen monate, über ein monat,
über 6 monate, über ein jahr."
DAS IST DIE BESSERE ANTWORT AUF DIE LANGEN LISTEN als die Zahl von
gestern. Zwoelf ist willkuerlich; eine Gliederung nach Alter
beantwortet die Frage, die man an so eine Liste wirklich stellt --
was ist neu?
DIE ERSTEN VIER STUFEN SIND KALENDERBEZOGEN, die letzten drei
altersbezogen:
Heute, Gestern der Kalendertag
Diese Woche seit MONTAG -- am Dienstag ist der Freitag
davor nicht "diese Woche"
Dieser Monat seit dem Ersten
Ueber einen Monat der Abstand, weil "Mai" niemandem sagt,
Ueber sechs Monate wie lange das her ist
Ueber ein Jahr
Das klingt uneinheitlich und ist genau richtig.
DIE NEUESTE GRUPPE STEHT OFFEN, die aelteren zu. Wer die Seite
aufmacht, will sehen was neu ist -- und alles Aeltere ist sichtbar
VORHANDEN, ohne den Weg zu verstellen. Die eigene Wahl gewinnt und
wird gemerkt, je Gruppe und je Spalte.
EINE LEERE STUFE ERSCHEINT NICHT. Sieben leere Ueberschriften waeren
schlimmer als eine lange Liste. Und gegliedert wird erst UEBER zwoelf
Eintraegen -- darunter waeren es sieben Ueberschriften fuer fuenf
Karten.
Die Zwoelfergrenze von gestern bleibt, gilt aber jetzt JE GRUPPE: Auch
"Ueber ein Jahr" kann dreihundert Eintraege haben, und dann hilft die
Gliederung allein nicht.
GERECHNET WIRD IN ORTSZEIT (window.heuteLokal), nicht in UTC. Ein
Eintrag von gestern 23:40 waere in UTC schon heute und stuende unter
"Heute", waehrend das Datum daneben gestern sagt.
ZWEI DINGE NACHGESEHEN STATT GERATEN:
abschnittKlappbar nimmt als vierten Wert ein BOOLEAN (zuVorgabe),
kein Objekt. Ich hatte "{ offen: ... }" angenommen; beim Nachsehen
in kopf.js stand etwas anderes da.
Jede Gruppe braucht einen eigenen Merker. Ohne ihn teilten sich
"Heute bei DogFather" und "Heute bei HasiDog" denselben Zustand,
und wer die eine zuklappt, klappt die andere mit.
Gemessen mit Eintraegen ueber alle sieben Stufen: 10 Messungen,
0 Befunde -- Reihenfolge, Zahlen, offen/zu, Klapp-Pfeil, kein
seitlicher Ueberstand, und ein Tipp macht eine zugeklappte Gruppe
wirklich auf. pruef-highlights 31, pruef-galerie und
pruef-css-klassen in Ordnung.
NOCH OFFEN -- screen1: "Screenshots oder Kurzschnitte reinposten"
braucht eine Route, die eine Datei an einen EINTRAG haengt. Die gibt
es heute nicht: workspace-video.js legt Coverbilder beim Einlesen
eines TikTok-Links an, workspace-dateien.js laedt hoch, aber ohne
eintrag_id. Das ist ein eigener Brocken und kein Nebenbei.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -2079,7 +2079,134 @@
|
||||
(e.datum DESC, e.id DESC). "Die ersten zwoelf" sind also die
|
||||
neuesten zwoelf, nicht die erstbesten. */
|
||||
const AUF_EINMAL = 12;
|
||||
function kartenLegen(kasten, fach) {
|
||||
|
||||
/* ==== NACH ALTER GEGLIEDERT (24.09.2026) ======================
|
||||
|
||||
Filipe: "ich will da unterkategorien die man auf und zu
|
||||
klappen kann, so wie heute gestern, diese woche, diesen
|
||||
monate, über ein monat, über 6 monate, über ein jahr."
|
||||
|
||||
Das ist die bessere Antwort auf die langen Listen als die
|
||||
Zahl von gestern. Zwoelf ist willkuerlich; eine Gliederung
|
||||
nach Alter beantwortet die Frage, die man an so eine Liste
|
||||
wirklich stellt -- "was ist neu?". Und was alt ist, steht
|
||||
zugeklappt da: sichtbar, dass es existiert, ohne den Weg zu
|
||||
verstellen.
|
||||
|
||||
DIE ERSTEN VIER STUFEN SIND KALENDERBEZOGEN, die letzten drei
|
||||
altersbezogen. Das klingt uneinheitlich und ist genau richtig:
|
||||
"Diese Woche" heisst seit Montag, nicht "in den letzten
|
||||
sieben Tagen" -- am Dienstag ist der Freitag davor nicht
|
||||
"diese Woche". Fuer alles aeltere zaehlt dagegen der Abstand,
|
||||
weil "Mai" niemandem sagt, wie lange das her ist.
|
||||
|
||||
EINE STUFE OHNE EINTRAEGE ERSCHEINT NICHT. Sieben leere
|
||||
Ueberschriften waeren schlimmer als eine lange Liste. */
|
||||
const ZEITSTUFEN = [
|
||||
{ schluessel: 'heute', name: 'Heute' },
|
||||
{ schluessel: 'gestern', name: 'Gestern' },
|
||||
{ schluessel: 'woche', name: 'Diese Woche' },
|
||||
{ schluessel: 'monat', name: 'Dieser Monat' },
|
||||
{ schluessel: 'aelter', name: 'Über einen Monat' },
|
||||
{ schluessel: 'halb', name: 'Über sechs Monate' },
|
||||
{ schluessel: 'jahr', name: 'Über ein Jahr' },
|
||||
];
|
||||
|
||||
/** In welche Stufe faellt dieser Eintrag?
|
||||
*
|
||||
* GERECHNET WIRD IN ORTSZEIT, nicht in UTC. Ein Eintrag von
|
||||
* gestern 23:40 waere in UTC schon heute -- und stuende dann
|
||||
* unter "Heute", waehrend das Datum daneben gestern sagt.
|
||||
* window.heuteLokal() ist die Stelle im Haus, die das richtig
|
||||
* macht. */
|
||||
function stufeVon(e) {
|
||||
const roh = String(e?.datum || '').slice(0, 10);
|
||||
if (!roh) return 'jahr';
|
||||
const heute = window.heuteLokal
|
||||
? window.heuteLokal() : new Date().toISOString().slice(0, 10);
|
||||
if (roh === heute) return 'heute';
|
||||
|
||||
const tag = new Date(heute + 'T00:00:00');
|
||||
const dann = new Date(roh + 'T00:00:00');
|
||||
if (Number.isNaN(dann.getTime())) return 'jahr';
|
||||
|
||||
const gestern = new Date(tag); gestern.setDate(tag.getDate() - 1);
|
||||
if (dann.getTime() === gestern.getTime()) return 'gestern';
|
||||
|
||||
/* Montag als Wochenanfang -- getDay() liefert Sonntag = 0, und
|
||||
in Deutschland steht der am Ende. Dieselbe Rechnung wie in
|
||||
zeitAb() weiter oben. */
|
||||
const montag = new Date(tag);
|
||||
montag.setDate(tag.getDate() - ((tag.getDay() + 6) % 7));
|
||||
if (dann >= montag) return 'woche';
|
||||
|
||||
const ersterDesMonats = new Date(tag.getFullYear(), tag.getMonth(), 1);
|
||||
if (dann >= ersterDesMonats) return 'monat';
|
||||
|
||||
const halbesJahr = new Date(tag); halbesJahr.setMonth(tag.getMonth() - 6);
|
||||
const einJahr = new Date(tag); einJahr.setFullYear(tag.getFullYear() - 1);
|
||||
if (dann < einJahr) return 'jahr';
|
||||
if (dann < halbesJahr) return 'halb';
|
||||
return 'aelter';
|
||||
}
|
||||
|
||||
/** Die Karten eines Fachs in einen Kasten legen -- gegliedert
|
||||
* nach Alter, jede Gruppe auf- und zuklappbar.
|
||||
*
|
||||
* "merker" unterscheidet die Gruppen zweier Spalten: Ohne ihn
|
||||
* teilten sich "Heute bei DogFather" und "Heute bei HasiDog"
|
||||
* denselben Zustand, und wer die eine zuklappt, klappt die
|
||||
* andere mit. */
|
||||
function kartenLegen(kasten, fach, merker) {
|
||||
/* Bei wenigen Eintraegen waere eine Gliederung Aufwand ohne
|
||||
Nutzen: sieben Ueberschriften fuer fuenf Karten. Erst wenn
|
||||
es sich lohnt, wird gegliedert. */
|
||||
if (fach.length <= AUF_EINMAL) { stapelLegen(kasten, fach); return; }
|
||||
|
||||
const faecher = new Map(ZEITSTUFEN.map((s) => [s.schluessel, []]));
|
||||
for (const e of fach) {
|
||||
const s = stufeVon(e);
|
||||
(faecher.get(s) || faecher.get('jahr')).push(e);
|
||||
}
|
||||
|
||||
let erste = true;
|
||||
for (const stufe of ZEITSTUFEN) {
|
||||
const drin = faecher.get(stufe.schluessel) || [];
|
||||
if (!drin.length) continue; /* leere Stufe: gar nicht erst */
|
||||
|
||||
const kopf = el('button', 'zeitgruppe__kopf');
|
||||
kopf.type = 'button';
|
||||
kopf.append(el('span', 'zeitgruppe__wort', stufe.name));
|
||||
kopf.append(el('span', 'zeitgruppe__zahl', String(drin.length)));
|
||||
if (window.klappPfeil) kopf.append(window.klappPfeil());
|
||||
kasten.append(kopf);
|
||||
|
||||
const innen = el('div', 'zeitgruppe__inhalt');
|
||||
innen.dataset.galerie = 'ja';
|
||||
stapelLegen(innen, drin);
|
||||
kasten.append(innen);
|
||||
|
||||
/* DIE NEUESTE GRUPPE STEHT OFFEN, die uebrigen zu. Wer die
|
||||
Seite aufmacht, will sehen was neu ist -- und nicht erst
|
||||
etwas aufklappen muessen. Alles Aeltere ist sichtbar
|
||||
VORHANDEN, ohne den Weg zu verstellen.
|
||||
|
||||
Die eigene Wahl gewinnt: abschnittKlappbar merkt sich je
|
||||
Gruppe, was zuletzt eingestellt war. */
|
||||
/* Der vierte Wert ist ZU-Vorgabe, kein Objekt -- nachgesehen
|
||||
in kopf.js, nicht geraten. Die erste Gruppe steht offen
|
||||
(zu = false), alle weiteren zu. */
|
||||
window.abschnittKlappbar?.(kopf, innen,
|
||||
'zeit:' + merker + ':' + stufe.schluessel, !erste);
|
||||
erste = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Ein Stapel Karten mit der Grenze bei zwoelf -- der Rest auf
|
||||
* einen Druck. Gilt jetzt JE GRUPPE: Auch "Über ein Jahr" kann
|
||||
* dreihundert Eintraege haben, und dann hilft die Gliederung
|
||||
* allein nicht. */
|
||||
function stapelLegen(kasten, fach) {
|
||||
for (const e of fach.slice(0, AUF_EINMAL)) {
|
||||
const k = karte(e);
|
||||
karten.set(e.id, k);
|
||||
@@ -2180,7 +2307,7 @@
|
||||
? `Für ${ZEIT_WORT[zeitFilter].toLowerCase()} steht hier nichts.`
|
||||
: 'Hier steht noch nichts.'));
|
||||
}
|
||||
kartenLegen(kasten, fach);
|
||||
kartenLegen(kasten, fach, bereich + ':kanal:' + (schluessel || 'ohne'));
|
||||
sp.append(kasten);
|
||||
window.abschnittKlappbar?.(kopf, kasten, `highlight:kanal:${schluessel || 'ohne'}`);
|
||||
spalten.append(sp);
|
||||
@@ -2293,7 +2420,7 @@
|
||||
ziel.append(kopf2);
|
||||
|
||||
const kasten = el('div', 'brettabschnitt__inhalt');
|
||||
kartenLegen(kasten, fach);
|
||||
kartenLegen(kasten, fach, bereich + ':art:' + a);
|
||||
ziel.append(kasten);
|
||||
/* Der Merker haengt am BRETT und an der Art -- sonst waere
|
||||
"Regel zugeklappt" auf allen Brettern gleichzeitig zu. */
|
||||
@@ -2335,7 +2462,7 @@
|
||||
if (window.klappPfeil) kopf.append(window.klappPfeil());
|
||||
ziel.append(kopf);
|
||||
const kasten = el('div', 'zeitstrahl__inhalt');
|
||||
kartenLegen(kasten, fach);
|
||||
kartenLegen(kasten, fach, bereich + ':zeit:' + r);
|
||||
ziel.append(kasten);
|
||||
window.abschnittKlappbar?.(kopf, kasten, `ansteht:${r}`, r === 'vorbei');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user