From 70aaec3401cdd7e435096c19be2d183efacb1b6d Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Thu, 11 Jun 2026 20:02:04 +0200 Subject: [PATCH] Web: enhance overflow popup with styled all-day bars and continuation arrows All-day events in the "+N weitere" popup now render as colored bars matching the month-grid style: continues-left/right arrows when the event spans beyond the selected day. Timed events keep dot+time+title format. Version bump v50. Co-Authored-By: Claude Sonnet 4.6 --- frontend/css/app.css | 22 ++++++++++++++ frontend/js/version.js | 2 +- frontend/js/views/month.js | 61 +++++++++++++++++++++++++++----------- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/frontend/css/app.css b/frontend/css/app.css index 04b2b66..af0369f 100644 --- a/frontend/css/app.css +++ b/frontend/css/app.css @@ -742,6 +742,7 @@ a { color: var(--primary); text-decoration: none; } box-shadow: var(--shadow-lg); padding: 10px 0; min-width: 220px; max-width: 300px; + overflow: hidden; user-select: none; } .mop-header { @@ -769,6 +770,27 @@ a { color: var(--primary); text-decoration: none; } font-size: 12px; font-weight: 500; color: var(--text-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +/* All-day event bars in overflow popup */ +.mop-bar { + position: relative; display: block; + margin: 2px 8px; padding: 3px 8px; + border-radius: 4px; + font-size: 11px; font-weight: 500; color: #fff; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + cursor: pointer; +} +.mop-bar:hover { filter: brightness(1.15); } +.mop-bar.continues-left { border-radius: 0 4px 4px 0; margin-left: 0; padding-left: 14px; } +.mop-bar.continues-right { border-radius: 4px 0 0 4px; margin-right: 0; padding-right: 14px; } +.mop-bar.continues-left.continues-right { border-radius: 0; } +.mop-bar.continues-left::before { + content: '‹'; position: absolute; left: 3px; top: 50%; + transform: translateY(-50%); font-size: 12px; opacity: 0.85; +} +.mop-bar.continues-right::after { + content: '›'; position: absolute; right: 3px; top: 50%; + transform: translateY(-50%); font-size: 12px; opacity: 0.85; +} /* ── Week / Day Views ───────────────────────────────────── */ .week-view, .day-view { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: scroll; } diff --git a/frontend/js/version.js b/frontend/js/version.js index c485baa..08fcc70 100644 --- a/frontend/js/version.js +++ b/frontend/js/version.js @@ -1,2 +1,2 @@ // Increment APP_VERSION with every code change -export const APP_VERSION = 'v49'; +export const APP_VERSION = 'v50'; diff --git a/frontend/js/views/month.js b/frontend/js/views/month.js index dec482f..4f2359b 100644 --- a/frontend/js/views/month.js +++ b/frontend/js/views/month.js @@ -277,28 +277,53 @@ function showOverflowPopup(anchor, date, events, onEventClick) { popup.appendChild(header); events.forEach(ev => { - const row = document.createElement('div'); - row.className = 'mop-row'; + const evStart = new Date(ev.start); evStart.setHours(0, 0, 0, 0); + const evEnd = new Date(ev.end); evEnd.setHours(0, 0, 0, 0); + // allDay end from API is exclusive → actual last day = evEnd - 1d + const lastDay = ev.allDay ? new Date(evEnd.getTime() - 86400000) : evEnd; + const continuesLeft = evStart < date; + const continuesRight = lastDay > date; + const color = ev.color || ev.calendarColor || '#4285f4'; - const dot = document.createElement('span'); - dot.className = 'mop-dot'; - dot.style.background = ev.color || ev.calendarColor || '#4285f4'; + if (ev.allDay) { + // All-day events → colored bar with continuation arrows + const bar = document.createElement('div'); + bar.className = 'mop-bar' + + (continuesLeft ? ' continues-left' : '') + + (continuesRight ? ' continues-right' : ''); + bar.style.background = color; + bar.textContent = ev.title; + bar.addEventListener('click', e => { + e.stopPropagation(); + popup.remove(); + onEventClick(ev, bar); + }); + popup.appendChild(bar); + } else { + // Timed events → dot + time + title + const row = document.createElement('div'); + row.className = 'mop-row'; - const time = document.createElement('span'); - time.className = 'mop-time'; - time.textContent = ev.allDay ? t('allday_cap') : fmtTime(new Date(ev.start)); + const dot = document.createElement('span'); + dot.className = 'mop-dot'; + dot.style.background = color; - const title = document.createElement('span'); - title.className = 'mop-title'; - title.textContent = ev.title; + const time = document.createElement('span'); + time.className = 'mop-time'; + time.textContent = fmtTime(new Date(ev.start)); - row.append(dot, time, title); - row.addEventListener('click', e => { - e.stopPropagation(); - popup.remove(); - onEventClick(ev, row); - }); - popup.appendChild(row); + const title = document.createElement('span'); + title.className = 'mop-title'; + title.textContent = ev.title; + + row.append(dot, time, title); + row.addEventListener('click', e => { + e.stopPropagation(); + popup.remove(); + onEventClick(ev, row); + }); + popup.appendChild(row); + } }); document.body.appendChild(popup);