Improves all-day event layout calculation
Refactors all-day event rendering to use a layout engine for overlap detection and positioning, ensuring events are placed in available rows and columns. Removes deprecated method and adds unit tests.
This commit is contained in:
parent
274753936e
commit
a624394ffb
11 changed files with 2898 additions and 145 deletions
|
|
@ -4,6 +4,7 @@ import { SwpAllDayEventElement } from '../elements/SwpEventElement';
|
|||
/**
|
||||
* AllDayEventRenderer - Simple rendering of all-day events
|
||||
* Handles adding and removing all-day events from the header container
|
||||
* NOTE: Layout calculation is now handled by AllDayManager
|
||||
*/
|
||||
export class AllDayEventRenderer {
|
||||
private container: HTMLElement | null = null;
|
||||
|
|
@ -34,19 +35,23 @@ export class AllDayEventRenderer {
|
|||
// REMOVED: createGhostColumns() method - no longer needed!
|
||||
|
||||
/**
|
||||
* Render an all-day event using factory pattern
|
||||
* Render an all-day event with pre-calculated layout
|
||||
*/
|
||||
public renderAllDayEvent(event: CalendarEvent, targetDate?: string): HTMLElement | null {
|
||||
public renderAllDayEventWithLayout(
|
||||
event: CalendarEvent,
|
||||
layout: { startColumn: number; endColumn: number; row: number; columnSpan: number }
|
||||
): HTMLElement | null {
|
||||
const container = this.getContainer();
|
||||
if (!container) return null;
|
||||
|
||||
const allDayElement = SwpAllDayEventElement.fromCalendarEvent(event, targetDate);
|
||||
const allDayElement = SwpAllDayEventElement.fromCalendarEventWithLayout(event, layout);
|
||||
const element = allDayElement.getElement();
|
||||
|
||||
container.appendChild(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove an all-day event by ID
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { CoreEvents } from '../constants/CoreEvents';
|
|||
import { calendarConfig } from '../core/CalendarConfig';
|
||||
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
|
||||
import { EventManager } from '../managers/EventManager';
|
||||
import { AllDayManager } from '../managers/AllDayManager';
|
||||
import { EventRendererStrategy } from './EventRenderer';
|
||||
import { SwpEventElement } from '../elements/SwpEventElement';
|
||||
import { AllDayEventRenderer } from './AllDayEventRenderer';
|
||||
|
|
@ -17,7 +18,7 @@ export class EventRenderingService {
|
|||
private eventManager: EventManager;
|
||||
private strategy: EventRendererStrategy;
|
||||
private allDayEventRenderer: AllDayEventRenderer;
|
||||
|
||||
private allDayManager: AllDayManager;
|
||||
|
||||
private dragMouseLeaveHeaderListener: ((event: Event) => void) | null = null;
|
||||
|
||||
|
|
@ -29,8 +30,9 @@ export class EventRenderingService {
|
|||
const calendarType = calendarConfig.getCalendarMode();
|
||||
this.strategy = CalendarTypeFactory.getEventRenderer(calendarType);
|
||||
|
||||
// Initialize all-day event renderer
|
||||
// Initialize all-day event renderer and manager
|
||||
this.allDayEventRenderer = new AllDayEventRenderer();
|
||||
this.allDayManager = new AllDayManager();
|
||||
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
|
@ -349,13 +351,35 @@ export class EventRenderingService {
|
|||
// Clear existing all-day events first
|
||||
this.clearAllDayEvents();
|
||||
|
||||
// Render each all-day event
|
||||
// Get actual visible dates from DOM headers instead of generating them
|
||||
const weekDates = this.getVisibleDatesFromDOM();
|
||||
|
||||
console.log('🔍 EventRenderingService: Using visible dates from DOM', {
|
||||
weekDates,
|
||||
count: weekDates.length
|
||||
});
|
||||
|
||||
// Calculate layout for ALL all-day events together using AllDayLayoutEngine
|
||||
const layouts = this.allDayManager.calculateAllDayEventsLayout(allDayEvents, weekDates);
|
||||
|
||||
// Render each all-day event with pre-calculated layout
|
||||
allDayEvents.forEach(event => {
|
||||
const renderedElement = this.allDayEventRenderer.renderAllDayEvent(event);
|
||||
const layout = layouts.get(event.id);
|
||||
if (!layout) {
|
||||
console.warn('❌ EventRenderingService: No layout found for all-day event', {
|
||||
id: event.id,
|
||||
title: event.title
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Render with pre-calculated layout
|
||||
const renderedElement = this.allDayEventRenderer.renderAllDayEventWithLayout(event, layout);
|
||||
if (renderedElement) {
|
||||
console.log('✅ EventRenderingService: Rendered all-day event', {
|
||||
console.log('✅ EventRenderingService: Rendered all-day event with AllDayLayoutEngine', {
|
||||
id: event.id,
|
||||
title: event.title,
|
||||
gridArea: layout.gridArea,
|
||||
element: renderedElement.tagName
|
||||
});
|
||||
} else {
|
||||
|
|
@ -392,6 +416,26 @@ export class EventRenderingService {
|
|||
this.clearEvents(container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get visible dates from DOM headers - only the dates that are actually displayed
|
||||
*/
|
||||
private getVisibleDatesFromDOM(): string[] {
|
||||
|
||||
const dayHeaders = document.querySelectorAll('swp-calendar-header swp-day-header');
|
||||
const weekDates: string[] = [];
|
||||
|
||||
dayHeaders.forEach(header => {
|
||||
const dateAttr = header.getAttribute('data-date');
|
||||
if (dateAttr) {
|
||||
weekDates.push(dateAttr);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return weekDates;
|
||||
}
|
||||
|
||||
|
||||
public destroy(): void {
|
||||
this.clearEvents();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue