2025-07-24 22:17:38 +02:00
|
|
|
import { EventBus } from '../core/EventBus';
|
2025-08-16 00:51:12 +02:00
|
|
|
import { IEventBus, CalendarEvent, RenderContext } from '../types/CalendarTypes';
|
2025-08-20 19:52:18 +02:00
|
|
|
import { CoreEvents } from '../constants/CoreEvents';
|
2025-07-24 22:17:38 +02:00
|
|
|
import { calendarConfig } from '../core/CalendarConfig';
|
2025-08-07 00:15:44 +02:00
|
|
|
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
|
2025-08-17 22:54:00 +02:00
|
|
|
import { EventManager } from '../managers/EventManager';
|
|
|
|
|
import { EventRendererStrategy } from './EventRenderer';
|
2025-09-19 00:20:30 +02:00
|
|
|
import { SwpEventElement } from '../elements/SwpEventElement';
|
2025-09-22 21:53:18 +02:00
|
|
|
import { AllDayEventRenderer } from './AllDayEventRenderer';
|
2025-09-21 15:48:13 +02:00
|
|
|
import { DragStartEventPayload, DragMoveEventPayload, DragEndEventPayload, DragMouseEnterHeaderEventPayload, DragMouseLeaveHeaderEventPayload } from '../types/EventTypes';
|
2025-07-24 22:17:38 +02:00
|
|
|
/**
|
2025-08-17 23:44:30 +02:00
|
|
|
* EventRenderingService - Render events i DOM med positionering using Strategy Pattern
|
2025-07-24 22:17:38 +02:00
|
|
|
* Håndterer event positioning og overlap detection
|
|
|
|
|
*/
|
2025-08-17 23:44:30 +02:00
|
|
|
export class EventRenderingService {
|
2025-07-24 22:17:38 +02:00
|
|
|
private eventBus: IEventBus;
|
2025-08-16 00:51:12 +02:00
|
|
|
private eventManager: EventManager;
|
|
|
|
|
private strategy: EventRendererStrategy;
|
2025-09-22 21:53:18 +02:00
|
|
|
private allDayEventRenderer: AllDayEventRenderer;
|
|
|
|
|
|
|
|
|
|
// Store all-day events until header is ready with dates
|
|
|
|
|
private pendingAllDayEvents: CalendarEvent[] = [];
|
|
|
|
|
private isHeaderReady: boolean = false;
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-09-21 15:48:13 +02:00
|
|
|
private dragMouseLeaveHeaderListener: ((event: Event) => void) | null = null;
|
|
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
constructor(eventBus: IEventBus, eventManager: EventManager) {
|
2025-07-24 22:17:38 +02:00
|
|
|
this.eventBus = eventBus;
|
2025-08-16 00:51:12 +02:00
|
|
|
this.eventManager = eventManager;
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
// Cache strategy at initialization
|
|
|
|
|
const calendarType = calendarConfig.getCalendarMode();
|
|
|
|
|
this.strategy = CalendarTypeFactory.getEventRenderer(calendarType);
|
2025-09-22 21:53:18 +02:00
|
|
|
|
|
|
|
|
// Initialize all-day event renderer
|
|
|
|
|
this.allDayEventRenderer = new AllDayEventRenderer();
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
this.setupEventListeners();
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-09 01:16:04 +02:00
|
|
|
/**
|
2025-08-16 00:51:12 +02:00
|
|
|
* Render events in a specific container for a given period
|
2025-08-09 01:16:04 +02:00
|
|
|
*/
|
2025-08-16 00:51:12 +02:00
|
|
|
public renderEvents(context: RenderContext): void {
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-20 20:22:51 +02:00
|
|
|
// Clear existing events in the specific container first
|
|
|
|
|
this.strategy.clearEvents(context.container);
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
// Get events from EventManager for the period
|
|
|
|
|
const events = this.eventManager.getEventsForPeriod(
|
|
|
|
|
context.startDate,
|
|
|
|
|
context.endDate
|
|
|
|
|
);
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
if (events.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-22 21:53:18 +02:00
|
|
|
// Filter events by type
|
|
|
|
|
const timedEvents = events.filter(event => !event.allDay);
|
|
|
|
|
const allDayEvents = events.filter(event => event.allDay);
|
|
|
|
|
|
|
|
|
|
console.log('🎯 EventRenderingService: Event filtering', {
|
|
|
|
|
totalEvents: events.length,
|
|
|
|
|
timedEvents: timedEvents.length,
|
|
|
|
|
allDayEvents: allDayEvents.length,
|
|
|
|
|
allDayEventIds: allDayEvents.map(e => e.id)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Render timed events using existing strategy
|
|
|
|
|
if (timedEvents.length > 0) {
|
|
|
|
|
this.strategy.renderEvents(timedEvents, context.container);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Render all-day events - wait for header if not ready
|
|
|
|
|
if (allDayEvents.length > 0) {
|
|
|
|
|
if (this.isHeaderReady) {
|
|
|
|
|
this.renderAllDayEvents(allDayEvents);
|
|
|
|
|
// Check and adjust all-day container height after rendering
|
|
|
|
|
this.eventBus.emit('allday:checkHeight');
|
|
|
|
|
} else {
|
|
|
|
|
console.log('🕐 EventRendererManager: Header not ready, storing all-day events for later');
|
|
|
|
|
// Only store if we don't already have pending events to avoid duplicates
|
|
|
|
|
if (this.pendingAllDayEvents.length === 0) {
|
|
|
|
|
this.pendingAllDayEvents = [...allDayEvents];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-23 00:01:59 +02:00
|
|
|
// Emit EVENTS_RENDERED event for filtering system
|
|
|
|
|
this.eventBus.emit(CoreEvents.EVENTS_RENDERED, {
|
|
|
|
|
events: events,
|
|
|
|
|
container: context.container
|
|
|
|
|
});
|
2025-08-09 01:16:04 +02:00
|
|
|
}
|
2025-08-02 23:59:52 +02:00
|
|
|
|
2025-08-09 01:16:04 +02:00
|
|
|
private setupEventListeners(): void {
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
this.eventBus.on(CoreEvents.GRID_RENDERED, (event: Event) => {
|
2025-08-16 00:51:12 +02:00
|
|
|
this.handleGridRendered(event as CustomEvent);
|
|
|
|
|
});
|
|
|
|
|
|
2025-08-20 20:22:51 +02:00
|
|
|
this.eventBus.on(CoreEvents.VIEW_CHANGED, (event: Event) => {
|
2025-08-16 00:51:12 +02:00
|
|
|
this.handleViewChanged(event as CustomEvent);
|
2025-08-09 01:16:04 +02:00
|
|
|
});
|
2025-09-19 00:20:30 +02:00
|
|
|
|
2025-09-22 21:53:18 +02:00
|
|
|
// Listen for header ready - when dates are populated
|
|
|
|
|
this.eventBus.on('header:ready', () => {
|
|
|
|
|
console.log('🎯 EventRendererManager: Header ready, rendering pending all-day events');
|
|
|
|
|
this.isHeaderReady = true;
|
|
|
|
|
|
|
|
|
|
if (this.pendingAllDayEvents.length > 0) {
|
|
|
|
|
this.renderAllDayEvents(this.pendingAllDayEvents);
|
|
|
|
|
this.pendingAllDayEvents = []; // Clear after rendering
|
|
|
|
|
|
|
|
|
|
// Check and adjust all-day container height after rendering
|
|
|
|
|
this.eventBus.emit('allday:checkHeight');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-09-20 09:40:56 +02:00
|
|
|
// Handle all drag events and delegate to appropriate renderer
|
|
|
|
|
this.setupDragEventListeners();
|
2025-09-19 00:20:30 +02:00
|
|
|
|
|
|
|
|
// Listen for conversion from all-day event to time event
|
|
|
|
|
this.eventBus.on('drag:convert-to-time_event', (event: Event) => {
|
2025-09-20 09:40:56 +02:00
|
|
|
const { draggedElement, mousePosition, column } = (event as CustomEvent).detail;
|
2025-09-19 00:20:30 +02:00
|
|
|
console.log('🔄 EventRendererManager: Received drag:convert-to-time_event', {
|
2025-09-20 09:40:56 +02:00
|
|
|
draggedElement: draggedElement?.dataset.eventId,
|
2025-09-19 00:20:30 +02:00
|
|
|
mousePosition,
|
|
|
|
|
column
|
|
|
|
|
});
|
2025-09-20 09:40:56 +02:00
|
|
|
this.handleConvertToTimeEvent(draggedElement, mousePosition, column);
|
2025-09-19 00:20:30 +02:00
|
|
|
});
|
|
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-09 01:16:04 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
/**
|
|
|
|
|
* Handle GRID_RENDERED event - render events in the current grid
|
|
|
|
|
*/
|
|
|
|
|
private handleGridRendered(event: CustomEvent): void {
|
2025-08-20 19:52:18 +02:00
|
|
|
const { container, startDate, endDate, currentDate } = event.detail;
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
if (!container) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
let periodStart: Date;
|
|
|
|
|
let periodEnd: Date;
|
|
|
|
|
|
|
|
|
|
if (startDate && endDate) {
|
2025-08-20 21:51:49 +02:00
|
|
|
// Direct date format - use as provided
|
2025-08-20 19:52:18 +02:00
|
|
|
periodStart = startDate;
|
|
|
|
|
periodEnd = endDate;
|
|
|
|
|
} else if (currentDate) {
|
2025-08-20 21:51:49 +02:00
|
|
|
return;
|
2025-08-20 19:52:18 +02:00
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
this.renderEvents({
|
|
|
|
|
container: container,
|
|
|
|
|
startDate: periodStart,
|
|
|
|
|
endDate: periodEnd
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle CONTAINER_READY_FOR_EVENTS event - render events in pre-rendered container
|
|
|
|
|
*/
|
|
|
|
|
private handleContainerReady(event: CustomEvent): void {
|
|
|
|
|
const { container, startDate, endDate } = event.detail;
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
if (!container || !startDate || !endDate) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.renderEvents({
|
|
|
|
|
container: container,
|
|
|
|
|
startDate: new Date(startDate),
|
|
|
|
|
endDate: new Date(endDate)
|
|
|
|
|
});
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
/**
|
|
|
|
|
* Handle VIEW_CHANGED event - clear and re-render for new view
|
|
|
|
|
*/
|
|
|
|
|
private handleViewChanged(event: CustomEvent): void {
|
|
|
|
|
// Clear all existing events since view structure may have changed
|
2025-08-09 01:16:04 +02:00
|
|
|
this.clearEvents();
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
// New rendering will be triggered by subsequent GRID_RENDERED event
|
|
|
|
|
}
|
2025-09-19 00:20:30 +02:00
|
|
|
|
|
|
|
|
|
2025-09-20 09:40:56 +02:00
|
|
|
/**
|
|
|
|
|
* Setup all drag event listeners - moved from EventRenderer for better separation of concerns
|
|
|
|
|
*/
|
|
|
|
|
private setupDragEventListeners(): void {
|
|
|
|
|
// Handle drag start
|
|
|
|
|
this.eventBus.on('drag:start', (event: Event) => {
|
2025-09-21 15:48:13 +02:00
|
|
|
const { draggedElement, mouseOffset, column } = (event as CustomEvent<DragStartEventPayload>).detail;
|
|
|
|
|
// Use the draggedElement directly - no need for DOM query
|
|
|
|
|
if (draggedElement && this.strategy.handleDragStart && column) {
|
|
|
|
|
const eventId = draggedElement.dataset.eventId || '';
|
|
|
|
|
this.strategy.handleDragStart(draggedElement, eventId, mouseOffset, column);
|
2025-09-20 09:40:56 +02:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Handle drag move
|
|
|
|
|
this.eventBus.on('drag:move', (event: Event) => {
|
2025-09-21 15:48:13 +02:00
|
|
|
const { draggedElement, snappedY, column, mouseOffset } = (event as CustomEvent<DragMoveEventPayload>).detail;
|
|
|
|
|
if (this.strategy.handleDragMove && column) {
|
|
|
|
|
const eventId = draggedElement.dataset.eventId || '';
|
2025-09-20 09:40:56 +02:00
|
|
|
this.strategy.handleDragMove(eventId, snappedY, column, mouseOffset);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Handle drag auto-scroll
|
|
|
|
|
this.eventBus.on('drag:auto-scroll', (event: Event) => {
|
2025-09-21 15:48:13 +02:00
|
|
|
const { draggedElement, snappedY } = (event as CustomEvent).detail;
|
2025-09-20 09:40:56 +02:00
|
|
|
if (this.strategy.handleDragAutoScroll) {
|
2025-09-21 15:48:13 +02:00
|
|
|
const eventId = draggedElement.dataset.eventId || '';
|
2025-09-20 09:40:56 +02:00
|
|
|
this.strategy.handleDragAutoScroll(eventId, snappedY);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Handle drag end events and delegate to appropriate renderer
|
|
|
|
|
this.eventBus.on('drag:end', (event: Event) => {
|
2025-09-21 15:48:13 +02:00
|
|
|
const { draggedElement, finalPosition, target } = (event as CustomEvent<DragEndEventPayload>).detail;
|
|
|
|
|
const finalColumn = finalPosition.column;
|
|
|
|
|
const finalY = finalPosition.snappedY;
|
|
|
|
|
const eventId = draggedElement.dataset.eventId || '';
|
|
|
|
|
|
2025-09-20 09:40:56 +02:00
|
|
|
// Only handle day column drops for EventRenderer
|
2025-09-21 15:48:13 +02:00
|
|
|
if (target === 'swp-day-column' && finalColumn) {
|
|
|
|
|
// Find dragged clone - use draggedElement as original
|
2025-09-20 09:40:56 +02:00
|
|
|
const draggedClone = document.querySelector(`swp-day-column swp-event[data-event-id="clone-${eventId}"]`) as HTMLElement;
|
2025-09-21 15:48:13 +02:00
|
|
|
|
|
|
|
|
if (draggedElement && draggedClone && this.strategy.handleDragEnd) {
|
|
|
|
|
this.strategy.handleDragEnd(eventId, draggedElement, draggedClone, finalColumn, finalY);
|
2025-09-20 09:40:56 +02:00
|
|
|
}
|
|
|
|
|
}
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-20 09:40:56 +02:00
|
|
|
// Clean up any remaining day event clones
|
2025-09-21 21:30:51 +02:00
|
|
|
const dayEventClone = document.querySelector(`swp-day-column swp-event[data-event-id="clone-${eventId}"]`);
|
2025-09-20 09:40:56 +02:00
|
|
|
if (dayEventClone) {
|
|
|
|
|
dayEventClone.remove();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Handle click (when drag threshold not reached)
|
|
|
|
|
this.eventBus.on('event:click', (event: Event) => {
|
2025-09-21 15:48:13 +02:00
|
|
|
const { draggedElement } = (event as CustomEvent).detail;
|
|
|
|
|
// Use draggedElement directly - no need for DOM query
|
|
|
|
|
if (draggedElement && this.strategy.handleEventClick) {
|
|
|
|
|
const eventId = draggedElement.dataset.eventId || '';
|
|
|
|
|
this.strategy.handleEventClick(eventId, draggedElement);
|
2025-09-20 09:40:56 +02:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Handle column change
|
|
|
|
|
this.eventBus.on('drag:column-change', (event: Event) => {
|
2025-09-21 15:48:13 +02:00
|
|
|
const { draggedElement, newColumn } = (event as CustomEvent).detail;
|
2025-09-20 09:40:56 +02:00
|
|
|
if (this.strategy.handleColumnChange) {
|
2025-09-21 15:48:13 +02:00
|
|
|
const eventId = draggedElement.dataset.eventId || '';
|
2025-09-20 09:40:56 +02:00
|
|
|
this.strategy.handleColumnChange(eventId, newColumn);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-09-21 15:48:13 +02:00
|
|
|
|
|
|
|
|
this.dragMouseLeaveHeaderListener = (event: Event) => {
|
|
|
|
|
const { targetDate, mousePosition, originalElement, cloneElement } = (event as CustomEvent<DragMouseLeaveHeaderEventPayload>).detail;
|
|
|
|
|
|
|
|
|
|
if (cloneElement)
|
|
|
|
|
cloneElement.style.display = '';
|
|
|
|
|
|
|
|
|
|
console.log('🚪 EventRendererManager: Received drag:mouseleave-header', {
|
|
|
|
|
targetDate,
|
|
|
|
|
originalElement: originalElement,
|
|
|
|
|
cloneElement: cloneElement
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.eventBus.on('drag:mouseleave-header', this.dragMouseLeaveHeaderListener);
|
|
|
|
|
|
2025-09-20 09:40:56 +02:00
|
|
|
// Handle navigation period change
|
|
|
|
|
this.eventBus.on(CoreEvents.NAVIGATION_COMPLETED, () => {
|
|
|
|
|
// Delegate to strategy if it handles navigation
|
|
|
|
|
if (this.strategy.handleNavigationCompleted) {
|
|
|
|
|
this.strategy.handleNavigationCompleted();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
/**
|
|
|
|
|
* Handle conversion from all-day event to time event
|
|
|
|
|
*/
|
2025-09-20 09:40:56 +02:00
|
|
|
private handleConvertToTimeEvent(draggedElement: HTMLElement, mousePosition: any, column: string): void {
|
|
|
|
|
// Use the provided draggedElement directly
|
|
|
|
|
const allDayClone = draggedElement;
|
|
|
|
|
const draggedEventId = draggedElement?.dataset.eventId?.replace('clone-', '') || '';
|
2025-09-21 15:48:13 +02:00
|
|
|
|
|
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
// Use SwpEventElement factory to create day event from all-day event
|
|
|
|
|
const dayEventElement = SwpEventElement.fromAllDayElement(allDayClone as HTMLElement);
|
|
|
|
|
const dayElement = dayEventElement.getElement();
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
// Remove the all-day clone - it's no longer needed since we're converting to day event
|
|
|
|
|
allDayClone.remove();
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
// Set clone ID
|
|
|
|
|
dayElement.dataset.eventId = `clone-${draggedEventId}`;
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
// Find target column
|
|
|
|
|
const columnElement = document.querySelector(`swp-day-column[data-date="${column}"]`);
|
|
|
|
|
if (!columnElement) {
|
|
|
|
|
console.warn('EventRendererManager: Target column not found', { column });
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
// Find events layer in the column
|
|
|
|
|
const eventsLayer = columnElement.querySelector('swp-events-layer');
|
|
|
|
|
if (!eventsLayer) {
|
|
|
|
|
console.warn('EventRendererManager: Events layer not found in column');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
// Add to events layer
|
|
|
|
|
eventsLayer.appendChild(dayElement);
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
// Position based on mouse Y coordinate
|
|
|
|
|
const columnRect = columnElement.getBoundingClientRect();
|
|
|
|
|
const relativeY = Math.max(0, mousePosition.y - columnRect.top);
|
|
|
|
|
dayElement.style.top = `${relativeY}px`;
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
// Set drag styling
|
|
|
|
|
dayElement.style.zIndex = '1000';
|
|
|
|
|
dayElement.style.cursor = 'grabbing';
|
|
|
|
|
dayElement.style.opacity = '';
|
|
|
|
|
dayElement.style.transform = '';
|
2025-09-21 15:48:13 +02:00
|
|
|
|
2025-09-19 00:20:30 +02:00
|
|
|
console.log('✅ EventRendererManager: Converted all-day event to time event', {
|
|
|
|
|
draggedEventId,
|
|
|
|
|
column,
|
|
|
|
|
mousePosition,
|
|
|
|
|
relativeY
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-22 21:53:18 +02:00
|
|
|
/**
|
|
|
|
|
* Render all-day events using AllDayEventRenderer
|
|
|
|
|
*/
|
|
|
|
|
private renderAllDayEvents(allDayEvents: CalendarEvent[]): void {
|
|
|
|
|
console.log('🏗️ EventRenderingService: Rendering all-day events', {
|
|
|
|
|
count: allDayEvents.length,
|
|
|
|
|
events: allDayEvents.map(e => ({ id: e.id, title: e.title }))
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Header always exists now, so we can render directly
|
|
|
|
|
allDayEvents.forEach(event => {
|
|
|
|
|
const renderedElement = this.allDayEventRenderer.renderAllDayEvent(event);
|
|
|
|
|
if (renderedElement) {
|
|
|
|
|
console.log('✅ EventRenderingService: Rendered all-day event', {
|
|
|
|
|
id: event.id,
|
|
|
|
|
title: event.title,
|
|
|
|
|
element: renderedElement.tagName
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.warn('❌ EventRenderingService: Failed to render all-day event', {
|
|
|
|
|
id: event.id,
|
|
|
|
|
title: event.title
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
private clearEvents(container?: HTMLElement): void {
|
|
|
|
|
this.strategy.clearEvents(container);
|
2025-09-22 21:53:18 +02:00
|
|
|
|
|
|
|
|
// Also clear all-day events
|
|
|
|
|
const allDayContainer = document.querySelector('swp-allday-container');
|
|
|
|
|
if (allDayContainer) {
|
|
|
|
|
allDayContainer.querySelectorAll('swp-event').forEach(event => event.remove());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear pending all-day events
|
|
|
|
|
this.pendingAllDayEvents = [];
|
|
|
|
|
this.isHeaderReady = false;
|
2025-08-16 00:51:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public refresh(container?: HTMLElement): void {
|
|
|
|
|
// Clear events in specific container or globally
|
|
|
|
|
this.clearEvents(container);
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public destroy(): void {
|
|
|
|
|
this.clearEvents();
|
|
|
|
|
}
|
|
|
|
|
}
|