Feat #3: Globale Zeitleiste #6

Merged
florian.wilde merged 1 commits from feat/3-globale-zeitleiste into main 2026-08-18 01:12:55 +00:00
Owner

Eine Seite /verlauf, die den Aktivitätsverlauf fortlaufend über alle Projekte zeigt — ohne Wochengrenze, nach Kalendertagen gegliedert, mit Nachladen älterer Einträge.

Der Kern: Cursor statt Offset

Geblättert wird über (createdAt, id), nicht per skip. Der Verlauf schreibt mehrere Einträge im selben Augenblick — beim Übernehmen von Issues entstehen zehn Zeilen mit identischem Zeitstempel. Ein Offset über eine solche Grenze hinweg überspringt Zeilen oder zeigt sie zweimal, und zwar lautlos. Der zweite Zweig der Bedingung (gleicher Zeitpunkt, kleinere ID) fängt genau das ab.

Geprüft gegen 144 Einträge mit absichtlichen Blöcken gleicher Zeitstempel:

Seiten geblaettert : 15
Eintraege geholt   : 144
davon eindeutig    : 144
Dubletten          : 0
streng absteigend  : true

Die Bedingung steht als prüfbare Funktion in lib/timeline, samt Deckelung der Seitengröße und Abweisen unbrauchbarer Cursor — eine ID aus der Abfragezeichenkette geht nicht ungeprüft in die Abfrage.

Gemeinsame Darstellung mit #2

Zeile und Tagesgruppen sind nach components/ActivityRow gewandert. Bewusst ohne "use client" und ohne Hooks, damit beides sowohl aus der Server-Komponente (Wochenrückblick) als auch aus der Client-Komponente (Zeitleiste mit Nachladen) heraus benutzbar ist. Zwei Kopien wären beim nächsten Feinschliff auseinandergelaufen.

Die Bündelung nach Tagen passiert in der Zeitleiste im Browser. Unbedenklich, weil tagesschluessel eine feste Zeitzone benutzt — Server und Browser kommen auf denselben Kalendertag, die erste Seite hydriert ohne Abweichung.

Erreichbar über

Schnellsuche (Strg+K → „Verlauf") und ein Verweis vom Wochenrückblick. Weiterhin kein zusätzlicher Punkt in der Kopfleiste.

Geprüft

  • 9 neue Unit-Tests zur Cursor-Logik (Grenzfälle, Deckelung, Abweisen von Unsinn)
  • E2E-Test, der die ganze Liste in Dreierseiten durchblättert und gegen einen einzelnen großen Aufruf hält — plus Prüfung, dass ein fremdes Konto keine dieser Zeilen sieht
  • E2E-Test für die Seite selbst
  • axe-core auf 375 px und 1280 px, je vor und nach dem Nachladen: 0 Verstöße, kein seitlicher Überlauf
  • 261 Unit-Tests, 33 E2E-Tests grün

Closes #3

Eine Seite `/verlauf`, die den Aktivitätsverlauf **fortlaufend** über alle Projekte zeigt — ohne Wochengrenze, nach Kalendertagen gegliedert, mit Nachladen älterer Einträge. ## Der Kern: Cursor statt Offset Geblättert wird über `(createdAt, id)`, nicht per `skip`. Der Verlauf schreibt mehrere Einträge im selben Augenblick — beim Übernehmen von Issues entstehen zehn Zeilen mit identischem Zeitstempel. Ein Offset über eine solche Grenze hinweg überspringt Zeilen oder zeigt sie zweimal, und zwar **lautlos**. Der zweite Zweig der Bedingung (gleicher Zeitpunkt, kleinere ID) fängt genau das ab. Geprüft gegen 144 Einträge mit absichtlichen Blöcken gleicher Zeitstempel: ``` Seiten geblaettert : 15 Eintraege geholt : 144 davon eindeutig : 144 Dubletten : 0 streng absteigend : true ``` Die Bedingung steht als prüfbare Funktion in `lib/timeline`, samt Deckelung der Seitengröße und Abweisen unbrauchbarer Cursor — eine ID aus der Abfragezeichenkette geht nicht ungeprüft in die Abfrage. ## Gemeinsame Darstellung mit #2 Zeile und Tagesgruppen sind nach `components/ActivityRow` gewandert. Bewusst **ohne** `"use client"` und ohne Hooks, damit beides sowohl aus der Server-Komponente (Wochenrückblick) als auch aus der Client-Komponente (Zeitleiste mit Nachladen) heraus benutzbar ist. Zwei Kopien wären beim nächsten Feinschliff auseinandergelaufen. Die Bündelung nach Tagen passiert in der Zeitleiste im Browser. Unbedenklich, weil `tagesschluessel` eine feste Zeitzone benutzt — Server und Browser kommen auf denselben Kalendertag, die erste Seite hydriert ohne Abweichung. ## Erreichbar über Schnellsuche (`Strg+K` → „Verlauf") und ein Verweis vom Wochenrückblick. Weiterhin **kein** zusätzlicher Punkt in der Kopfleiste. ## Geprüft - 9 neue Unit-Tests zur Cursor-Logik (Grenzfälle, Deckelung, Abweisen von Unsinn) - E2E-Test, der die ganze Liste in Dreierseiten durchblättert und gegen einen einzelnen großen Aufruf hält — plus Prüfung, dass ein fremdes Konto keine dieser Zeilen sieht - E2E-Test für die Seite selbst - axe-core auf 375 px und 1280 px, je **vor und nach** dem Nachladen: 0 Verstöße, kein seitlicher Überlauf - 261 Unit-Tests, 33 E2E-Tests grün Closes #3
florian.wilde added 1 commit 2026-08-17 23:55:29 +00:00
Globale Zeitleiste ueber alle Projekte
CI / pruefen (pull_request) Canceled after 0s
9cdd51fba8
Eine Seite /verlauf, die den Aktivitaetsverlauf fortlaufend ueber alle
Projekte zeigt - ohne Wochengrenze, nach Kalendertagen gegliedert, mit
Nachladen aelterer Eintraege. Erste Seite serverseitig, alles Weitere ueber
/api/activity.

Geblaettert wird per Cursor ueber (createdAt, id), nicht per skip. Der
Verlauf schreibt mehrere Eintraege im selben Augenblick - beim Uebernehmen
von Issues entstehen zehn Zeilen mit identischem Zeitstempel. Ein Offset
ueber eine solche Grenze hinweg ueberspringt Zeilen oder zeigt sie zweimal,
und zwar lautlos. Der zweite Zweig der Bedingung (gleicher Zeitpunkt,
kleinere ID) faengt genau das ab.

Geprueft gegen 144 Eintraege mit absichtlichen Bloecken gleicher Zeitstempel:
15 Seiten, 144 Zeilen, keine Dublette, streng absteigend.

Die Bedingung selbst steht als pruefbare Funktion in lib/timeline, samt
Deckelung der Seitengroesse und Abweisen unbrauchbarer Cursor - eine ID aus
der Abfragezeichenkette geht nicht ungeprueft in die Abfrage.

Damit Rueckblick und Zeitleiste wirklich gleich aussehen, sind Zeile und
Tagesgruppen nach components/ActivityRow gewandert. Bewusst ohne "use
client" und ohne Hooks, damit beides sowohl aus der Server-Komponente
(Rueckblick) als auch aus der Client-Komponente (Zeitleiste) heraus
benutzbar ist. Die Buendelung im Browser ist unbedenklich, weil
tagesschluessel eine feste Zeitzone benutzt - Server und Browser kommen auf
denselben Kalendertag.

Erreichbar ueber die Schnellsuche und vom Wochenrueckblick aus.

Geprueft: 9 neue Unit-Tests zur Cursor-Logik, ein E2E-Test, der die ganze
Liste in Dreierseiten durchblaettert und gegen einen einzelnen grossen
Aufruf haelt, ein E2E-Test fuer die Seite, axe-core auf 375px und 1280px
je vor und nach dem Nachladen ohne Beanstandung.

Refs #3
florian.wilde merged commit 0ef0b3d5ca into main 2026-08-18 01:12:55 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: florian.wilde/nebula#6