Enhances event rendering and grid updates

Improves event rendering by adding styling, filtering out all-day events (handled by GridManager), and calculating accurate positioning within the time grid.

Optimizes grid updates to avoid unnecessary rebuilding, instead updating only the week header for all-day events, leading to better performance.
This commit is contained in:
Janus Knudsen 2025-08-05 00:41:59 +02:00
parent 7ac7e0f7f8
commit dc5063729b
3 changed files with 64 additions and 43 deletions

View file

@ -54,27 +54,28 @@ export class EventRenderer {
private renderEvents(events: CalendarEvent[]): void {
console.log('EventRenderer: renderEvents called with', events.length, 'events');
console.log('EventRenderer: All events:', events.map(e => ({ title: e.title, allDay: e.allDay, start: e.start })));
// Clear existing events first
this.clearEvents();
// Get current week dates for filtering
const currentWeekDates = this.getCurrentWeekDates();
console.log('EventRenderer: Current week dates:', currentWeekDates.map(d => DateUtils.formatDate(d)));
// Filter events for current week
// Filter events for current week and exclude all-day events (handled by GridManager)
const currentWeekEvents = events.filter(event => {
// Skip all-day events - they are handled by GridManager
if (event.allDay) {
return false;
}
const eventDate = new Date(event.start);
const eventDateStr = DateUtils.formatDate(eventDate);
const isInCurrentWeek = currentWeekDates.some(weekDate =>
DateUtils.formatDate(weekDate) === eventDateStr
);
console.log('EventRenderer: Event', event.title, 'on', eventDateStr, 'is in current week:', isInCurrentWeek);
return isInCurrentWeek;
});
console.log('EventRenderer: Rendering', currentWeekEvents.length, 'events for current week');
// Render each event in the correct day column
currentWeekEvents.forEach(event => {
const eventDate = new Date(event.start);
@ -83,7 +84,6 @@ export class EventRenderer {
if (dayColumn) {
const eventsLayer = dayColumn.querySelector('swp-events-layer');
if (eventsLayer) {
console.log('EventRenderer: Rendering event', event.title, 'in day column for', DateUtils.formatDate(eventDate));
this.renderEvent(event, eventsLayer);
} else {
console.warn('EventRenderer: No events layer found in day column for', DateUtils.formatDate(eventDate));
@ -97,6 +97,7 @@ export class EventRenderer {
this.eventBus.emit(EventTypes.EVENT_RENDERED, {
count: currentWeekEvents.length
});
}
/**
@ -139,6 +140,15 @@ export class EventRenderer {
eventElement.style.right = '2px';
eventElement.style.zIndex = '10';
// Style the event element
eventElement.style.backgroundColor = event.metadata?.color || '#3498db';
eventElement.style.color = 'white';
eventElement.style.fontSize = '12px';
eventElement.style.padding = '2px 4px';
eventElement.style.borderRadius = '3px';
eventElement.style.overflow = 'hidden';
eventElement.style.cursor = 'pointer';
// Format time for display
const startTime = this.formatTime(event.start);
const endTime = this.formatTime(event.end);
@ -153,17 +163,19 @@ export class EventRenderer {
this.addEventListeners(eventElement, event);
container.appendChild(eventElement);
// Event successfully rendered
}
private calculateEventPosition(event: CalendarEvent): { top: number; height: number } {
const startDate = new Date(event.start);
const endDate = new Date(event.end);
// Use dayStartHour to match time-axis positioning
const dayStartHour = calendarConfig.get('dayStartHour'); // 0 (midnight)
// Use dayStartHour to match time-axis positioning - this is the visible start hour (6 AM)
const dayStartHour = calendarConfig.get('dayStartHour'); // 6 (6 AM)
const hourHeight = calendarConfig.get('hourHeight');
// Calculate minutes from day start (midnight)
// Calculate minutes from visible day start (6 AM, not midnight)
const eventHour = startDate.getHours();
const eventMinutes = startDate.getMinutes();
const startMinutes = (eventHour - dayStartHour) * 60 + eventMinutes;
@ -171,29 +183,10 @@ export class EventRenderer {
// Calculate duration in minutes
const duration = (endDate.getTime() - startDate.getTime()) / (1000 * 60);
// Convert to pixels - this gives absolute position from top of time-grid
const absoluteTop = startMinutes * (hourHeight / 60);
// Convert to pixels - position relative to visible time-grid (starts at dayStartHour)
const top = startMinutes * (hourHeight / 60);
const height = duration * (hourHeight / 60);
// Get current scroll position to adjust for viewport
const scrollableContent = document.querySelector('swp-scrollable-content') as HTMLElement;
const scrollTop = scrollableContent ? scrollableContent.scrollTop : 0;
// Calculate relative position within the visible viewport
// Events are positioned relative to their day-column, not the scrollable content
// So we use the absolute position directly
const top = absoluteTop;
console.log('EventRenderer: Position calculation for', event.title, {
eventTime: `${eventHour}:${eventMinutes.toString().padStart(2, '0')}`,
dayStartHour,
startMinutes,
duration,
absoluteTop,
scrollTop,
finalTop: top,
height
});
return { top, height };
}

View file

@ -117,16 +117,21 @@ export class GridManager {
return;
}
// Clear existing grid and rebuild POC structure
this.grid.innerHTML = '';
// Create POC structure: header-spacer + time-axis + week-container + right-column + bottom spacers
this.createHeaderSpacer();
this.createRightHeaderSpacer();
this.createTimeAxis();
this.createWeekContainer();
this.createRightColumn();
this.createBottomRow();
// Only clear and rebuild if grid is empty (first render)
if (this.grid.children.length === 0) {
console.log('GridManager: First render - creating grid structure');
// Create POC structure: header-spacer + time-axis + week-container + right-column + bottom spacers
this.createHeaderSpacer();
this.createRightHeaderSpacer();
this.createTimeAxis();
this.createWeekContainer();
this.createRightColumn();
this.createBottomRow();
} else {
console.log('GridManager: Re-render - updating existing structure');
// Just update the week header for all-day events
this.updateWeekHeader();
}
console.log('GridManager: Grid rendered successfully with POC structure');
}
@ -269,6 +274,26 @@ export class GridManager {
this.updateSpacerHeights();
}
/**
* Update only the week header (for all-day events) without rebuilding entire grid
*/
private updateWeekHeader(): void {
if (!this.grid || !this.currentWeek) return;
const weekHeader = this.grid.querySelector('swp-week-header');
if (!weekHeader) return;
// Clear existing all-day events but keep day headers
const allDayEvents = weekHeader.querySelectorAll('swp-allday-event');
allDayEvents.forEach(event => event.remove());
// Re-render all-day events
this.renderAllDayEvents(weekHeader as HTMLElement);
// Update spacer heights
this.updateSpacerHeights();
}
/**
* Update all-day events data and re-render if needed
*/
@ -289,9 +314,9 @@ export class GridManager {
console.log('GridManager: Updated all-day events:', this.allDayEvents.length);
// Re-render if grid is already rendered
// Update only the week header if grid is already rendered
if (this.grid && this.grid.children.length > 0) {
this.render();
this.updateWeekHeader();
}
}

View file

@ -370,6 +370,9 @@ swp-day-column:last-child {
swp-events-layer {
position: absolute;
inset: 0;
display: block;
z-index: var(--z-event);
pointer-events: none; /* Allow clicks to pass through to day column */
}
swp-event {