From cae9c5467a3c04fb52db3fde4b5a85d2f0a03e76 Mon Sep 17 00:00:00 2001 From: UserIsMH Date: Fri, 1 May 2026 15:13:17 +0200 Subject: [PATCH] Ereignis-Timeline: Lagebericht-Stempel zusammenfassen, Bar-Cap entfernen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mehrere Snapshots in derselben Achsen-Position erzeugten verschmierte, übereinanderliegende Pin-Symbole. Zusätzlich war der goldene Streifen auf der Bar (Bar-Cap) redundant zur vertikalen Snapshot-Linie. - Snapshots werden pro Achsen-Position (auf 0,5%-Genauigkeit) gruppiert. Eine einzige Linie + ein einziger Pin pro Gruppe; bei mehreren Lageberichten zeigt der Pin die Anzahl als Zahl statt das Stempel- Symbol. - Bar-Cap (separates Element über der Bar) entfernt. Stattdessen bekommt die Bar-Füllung bei has-snapshot eine dezente goldene Top-Linie via ::before — keine Doppel-Markierung mehr. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/static/css/style.css | 31 ++++++++++++++++++++++--------- src/static/js/app.js | 32 ++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/static/css/style.css b/src/static/css/style.css index 4480a6b..87f518c 100644 --- a/src/static/css/style.css +++ b/src/static/css/style.css @@ -2691,16 +2691,22 @@ a.dev-source-pill:hover { height: 4px; background: var(--border); } -.ht-bar-snap-cap { +/* Bar mit Lagebericht im gleichen Bucket: dezente goldene Top-Linie auf der Fuellung */ +.ht-bar.has-snapshot .ht-bar-fill::before { + content: ''; position: absolute; - top: -8px; - left: -2px; - right: -2px; - height: 6px; + top: 0; + left: 0; + right: 0; + height: 3px; background: var(--accent); - border-radius: 2px; - box-shadow: var(--glow-accent); + border-radius: 2px 2px 0 0; } +.ht-bar.has-snapshot.snapshot-only .ht-bar-fill::before { + /* Nur Snapshot, keine Artikel: kleiner goldener Strich auf Achse */ + height: 4px; +} +.ht-bar-fill { position: relative; } .ht-bars:has(.ht-bar.active) .ht-bar:not(.active) { opacity: 0.45; } /* Aktiver Bar: dezenter Marker oben */ @@ -2833,17 +2839,24 @@ a.dev-source-pill:hover { bottom: -7px; left: 50%; transform: translateX(-50%); - width: 14px; + min-width: 14px; height: 14px; + padding: 0 2px; background: var(--bg-card); border: 1px solid var(--accent); - border-radius: 50%; + border-radius: 7px; color: var(--accent); display: flex; align-items: center; justify-content: center; z-index: 4; } +.ht-snapshot-line-count { + font-size: 9px; + font-weight: 700; + font-family: var(--font-mono); + line-height: 1; +} /* "Heute"-Linie (nur bei taeglicher/woechentlicher/monatlicher Granularitaet aktiv) */ .ht-today-line { diff --git a/src/static/js/app.js b/src/static/js/app.js index e5821ed..696f2d9 100644 --- a/src/static/js/app.js +++ b/src/static/js/app.js @@ -1165,19 +1165,30 @@ const App = { }); html += ''; - // Lagebericht-Linien quer durch die Achse (klickbar, oeffnet Snapshot) + // Lagebericht-Linien quer durch die Achse (deduplikiert nach Achsen-Position) html += '
'; - const snapshots = entries.filter(e => e.kind === 'snapshot'); - snapshots.forEach(snap => { + const snapshotsByPos = {}; + entries.filter(e => e.kind === 'snapshot').forEach(snap => { const ts = new Date(snap.timestamp || 0).getTime(); if (rangeEnd === rangeStart) return; const pos = ((ts - rangeStart) / (rangeEnd - rangeStart)) * 100; if (pos < 0 || pos > 100) return; - const dateStr = new Date(snap.timestamp).toLocaleDateString('de-DE', { day: '2-digit', month: 'short', timeZone: TIMEZONE }); - html += `
`; - html += ``; + const posKey = Math.round(pos * 2) / 2; + if (!snapshotsByPos[posKey]) snapshotsByPos[posKey] = { pos: posKey, snapshots: [] }; + snapshotsByPos[posKey].snapshots.push(snap); + }); + Object.values(snapshotsByPos).forEach(group => { + const count = group.snapshots.length; + const first = group.snapshots[0]; + const dateStr = new Date(first.timestamp).toLocaleDateString('de-DE', { day: '2-digit', month: 'short', timeZone: TIMEZONE }); + const titleAttr = count === 1 + ? `Lagebericht ${dateStr}` + : `${count} Lageberichte ${dateStr}`; + const capInner = count === 1 + ? '' + : `${count}`; + html += `
`; + html += ``; html += `
`; }); html += '
'; @@ -1229,15 +1240,12 @@ const App = { if (isActive) barClass += ' active'; html += `
`; - // Saeule selbst (gefuellt zur Hoehe) + // Saeule selbst (gefuellt zur Hoehe). has-snapshot setzt golden Top-Border via CSS. if (articleCount > 0) { html += `
`; } else { html += `
`; } - if (snapshotCount > 0) { - html += ``; - } // Hover-Vorschaukarte html += `
${UI.escape(bucket.label)} · ${articleCount + snapshotCount} Eintr${(articleCount + snapshotCount) === 1 ? 'ag' : 'äge'}
`;