Renders all-day events based on header data

Refactors all-day event rendering to use header column data.
This ensures events are rendered based on the actual visible
dates in the header, improving accuracy and responsiveness to view changes.

Removes direct dependency on week dates in `AllDayManager` and
`EventRenderingService`, instead, the all-day manager is instantiated
with event manager.

Updates `HeaderManager` to emit header bounds.
This commit is contained in:
Janus C. H. Knudsen 2025-10-01 21:27:13 +02:00
parent ae3aab5dd0
commit d7867d4a9f
7 changed files with 108 additions and 157 deletions

View file

@ -11,9 +11,12 @@ import {
DragStartEventPayload,
DragMoveEventPayload,
DragEndEventPayload,
DragColumnChangeEventPayload
DragColumnChangeEventPayload,
HeaderReadyEventPayload
} from '../types/EventTypes';
import { DragOffset, MousePosition } from '../types/DragDropTypes';
import { CoreEvents } from '../constants/CoreEvents';
import { EventManager } from './EventManager';
/**
* AllDayManager - Handles all-day row height animations and management
@ -21,12 +24,14 @@ import { DragOffset, MousePosition } from '../types/DragDropTypes';
*/
export class AllDayManager {
private allDayEventRenderer: AllDayEventRenderer;
private eventManager: EventManager;
private layoutEngine: AllDayLayoutEngine | null = null;
// State tracking for differential updates
private currentLayouts: EventLayout[] = [];
private currentAllDayEvents: CalendarEvent[] = [];
private currentWeekDates: string[] = [];
private currentWeekDates: ColumnBounds[] = [];
private newLayouts: EventLayout[] = [];
// Expand/collapse state
@ -34,8 +39,8 @@ export class AllDayManager {
private actualRowCount: number = 0;
private readonly MAX_COLLAPSED_ROWS = 4; // Show 4 rows when collapsed (3 events + 1 indicator row)
constructor() {
constructor(eventManager: EventManager) {
this.eventManager = eventManager;
this.allDayEventRenderer = new AllDayEventRenderer();
this.setupEventListeners();
}
@ -53,7 +58,7 @@ export class AllDayManager {
originalElementTag: payload.originalElement?.tagName
});
this.handleConvertToAllDay(payload);
this.handleConvertToAllDay(payload);
});
eventBus.on('drag:mouseleave-header', (event) => {
@ -118,6 +123,26 @@ export class AllDayManager {
});
// Listen for header ready - when dates are populated with period data
eventBus.on('header:ready', (event: Event) => {
let headerReadyEventPayload = (event as CustomEvent<HeaderReadyEventPayload>).detail;
var startDate = headerReadyEventPayload.headerElements.startDate;
var endDate = headerReadyEventPayload.headerElements.endDate;
var events: CalendarEvent[] = this.eventManager.getEventsForPeriod(startDate, endDate);
// Filter for all-day events
const allDayEvents = events.filter(event => event.allDay);
var eventLayouts = this.calculateAllDayEventsLayout(allDayEvents, headerReadyEventPayload.headerElements)
this.allDayEventRenderer.renderAllDayEventsForPeriod(eventLayouts);
this.checkAndAnimateAllDayHeight();
});
eventBus.on(CoreEvents.VIEW_CHANGED, (event: Event) => {
this.allDayEventRenderer.handleViewChanged(event as CustomEvent);
});
}
private getAllDayContainer(): HTMLElement | null {
@ -275,24 +300,11 @@ export class AllDayManager {
}
/**
* Set current events and week dates (called by EventRendererManager)
*/
public setCurrentEvents(events: CalendarEvent[], weekDates: string[]): void {
this.currentAllDayEvents = events;
this.currentWeekDates = weekDates;
console.log('📝 AllDayManager: Set current events', {
eventCount: events.length,
weekDatesCount: weekDates.length
});
}
/**
* Calculate layout for ALL all-day events using AllDayLayoutEngine
* This is the correct method that processes all events together for proper overlap detection
*/
public calculateAllDayEventsLayout(events: CalendarEvent[], weekDates: string[]): EventLayout[] {
private calculateAllDayEventsLayout(events: CalendarEvent[], weekDates: ColumnBounds[]): EventLayout[] {
// Store current state
this.currentAllDayEvents = events;
@ -305,19 +317,6 @@ export class AllDayManager {
return layoutEngine.calculateLayout(events);
}
public initAllDayEventsLayout(events: CalendarEvent[], weekDates: string[]): EventLayout[] {
// Store current state
this.currentAllDayEvents = events;
this.currentWeekDates = weekDates;
// Initialize layout engine with provided week dates
var layoutEngine = new AllDayLayoutEngine(weekDates);
// Calculate layout for all events together - AllDayLayoutEngine handles CalendarEvents directly
this.currentLayouts = layoutEngine.calculateLayout(events);
return this.currentLayouts;
}
/**
* Handle conversion of timed event to all-day event - SIMPLIFIED
@ -430,7 +429,7 @@ export class AllDayManager {
const droppedEvent: CalendarEvent = {
id: eventId,
title: dragEndEvent.draggedClone.dataset.title|| '',
title: dragEndEvent.draggedClone.dataset.title || '',
start: new Date(eventDate),
end: new Date(eventDate),
type: eventType,

View file

@ -6,6 +6,8 @@ import { HeaderRenderContext } from '../renderers/HeaderRenderer';
import { ResourceCalendarData } from '../types/CalendarTypes';
import { DragMouseEnterHeaderEventPayload, DragMouseLeaveHeaderEventPayload, HeaderReadyEventPayload } from '../types/EventTypes';
import { DateCalculator } from '../utils/DateCalculator';
import { PositionUtils } from '../utils/PositionUtils';
import { ColumnDetectionUtils } from '../utils/ColumnDetectionUtils';
/**
* HeaderManager - Handles all header-related event logic
@ -142,10 +144,7 @@ export class HeaderManager {
// Notify other managers that header is ready with period data
const payload: HeaderReadyEventPayload = {
headerElement: calendarHeader,
startDate: weekStart,
endDate: weekEnd,
isNavigation: false
headerElements: ColumnDetectionUtils.getHeaderColumns(),
};
eventBus.emit('header:ready', payload);
}