Refactors event rendering to be event-driven
Moves event rendering logic into a dedicated EventRenderer class that uses a strategy pattern for different calendar types. The rendering is now triggered by `GRID_RENDERED` and `CONTAINER_READY_FOR_EVENTS` events, emitted by the GridManager and NavigationManager respectively. This change decouples the CalendarManager from direct event rendering and allows for more flexible and efficient event updates. The EventManager now has a method to fetch events for a given time period. Removes direct calls to event rendering from CalendarManager. Improves animation transitions by using pre-rendered containers in the NavigationManager.
This commit is contained in:
parent
afe5b6b899
commit
a03f314c4a
9 changed files with 271 additions and 166 deletions
|
|
@ -8,18 +8,15 @@ import { DateUtils } from '../utils/DateUtils';
|
|||
* Interface for event rendering strategies
|
||||
*/
|
||||
export interface EventRendererStrategy {
|
||||
findColumn(event: CalendarEvent): HTMLElement | null;
|
||||
renderEvents(events: CalendarEvent[], config: CalendarConfig): void;
|
||||
clearEvents(): void;
|
||||
renderEvents(events: CalendarEvent[], container: HTMLElement, config: CalendarConfig): void;
|
||||
clearEvents(container?: HTMLElement): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for event renderers with common functionality
|
||||
*/
|
||||
export abstract class BaseEventRenderer implements EventRendererStrategy {
|
||||
abstract findColumn(event: CalendarEvent): HTMLElement | null;
|
||||
|
||||
renderEvents(events: CalendarEvent[], config: CalendarConfig): void {
|
||||
renderEvents(events: CalendarEvent[], container: HTMLElement, config: CalendarConfig): void {
|
||||
console.log('BaseEventRenderer: renderEvents called with', events.length, 'events');
|
||||
|
||||
// NOTE: Removed clearEvents() to support sliding animation
|
||||
|
|
@ -30,10 +27,9 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
|
|||
// Events should already be filtered by DataManager - no need to filter here
|
||||
console.log('BaseEventRenderer: Rendering', events.length, 'pre-filtered events');
|
||||
|
||||
// OPTIMIZATION: Column-first rendering instead of event-first
|
||||
// This is much more efficient when there are many events
|
||||
const columns = this.getColumns();
|
||||
console.log(`BaseEventRenderer: Found ${columns.length} columns to render events in`);
|
||||
// Find columns in the specific container
|
||||
const columns = this.getColumns(container);
|
||||
console.log(`BaseEventRenderer: Found ${columns.length} columns in container`);
|
||||
|
||||
columns.forEach(column => {
|
||||
const columnEvents = this.getEventsForColumn(column, events);
|
||||
|
|
@ -55,8 +51,8 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
|
|||
});
|
||||
}
|
||||
|
||||
// Abstract methods that subclasses must implement for column-first rendering
|
||||
protected abstract getColumns(): HTMLElement[];
|
||||
// Abstract methods that subclasses must implement
|
||||
protected abstract getColumns(container: HTMLElement): HTMLElement[];
|
||||
protected abstract getEventsForColumn(column: HTMLElement, events: CalendarEvent[]): CalendarEvent[];
|
||||
|
||||
protected renderEvent(event: CalendarEvent, container: Element, config: CalendarConfig): void {
|
||||
|
|
@ -138,10 +134,15 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
|
|||
return `${displayHour}:${minutes.toString().padStart(2, '0')} ${period}`;
|
||||
}
|
||||
|
||||
clearEvents(): void {
|
||||
const existingEvents = document.querySelectorAll('swp-event');
|
||||
clearEvents(container?: HTMLElement): void {
|
||||
const selector = 'swp-event';
|
||||
const existingEvents = container
|
||||
? container.querySelectorAll(selector)
|
||||
: document.querySelectorAll(selector);
|
||||
|
||||
if (existingEvents.length > 0) {
|
||||
console.warn(`🗑️ BaseEventRenderer: REMOVING ${existingEvents.length} events from DOM! Stack trace:`, new Error().stack);
|
||||
console.log(`BaseEventRenderer: Clearing ${existingEvents.length} events`,
|
||||
container ? 'from container' : 'globally');
|
||||
}
|
||||
existingEvents.forEach(event => event.remove());
|
||||
}
|
||||
|
|
@ -151,26 +152,9 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
|
|||
* Date-based event renderer
|
||||
*/
|
||||
export class DateEventRenderer extends BaseEventRenderer {
|
||||
findColumn(event: CalendarEvent): HTMLElement | null {
|
||||
const eventDate = new Date(event.start);
|
||||
const dateStr = DateUtils.formatDate(eventDate);
|
||||
const dayColumn = document.querySelector(`swp-day-column[data-date="${dateStr}"]`) as HTMLElement;
|
||||
|
||||
// Debug: Check all available columns
|
||||
const allColumns = document.querySelectorAll('swp-day-column');
|
||||
const availableDates = Array.from(allColumns).map(col => (col as HTMLElement).dataset.date);
|
||||
|
||||
console.log('DateEventRenderer: Event', event.title, 'start:', event.start);
|
||||
console.log('DateEventRenderer: Looking for date:', dateStr);
|
||||
console.log('DateEventRenderer: Available columns with dates:', availableDates);
|
||||
console.log('DateEventRenderer: Found column:', !!dayColumn);
|
||||
|
||||
return dayColumn;
|
||||
}
|
||||
|
||||
protected getColumns(): HTMLElement[] {
|
||||
const columns = document.querySelectorAll('swp-day-column');
|
||||
console.log('DateEventRenderer: Found', columns.length, 'day columns in DOM');
|
||||
protected getColumns(container: HTMLElement): HTMLElement[] {
|
||||
const columns = container.querySelectorAll('swp-day-column');
|
||||
console.log('DateEventRenderer: Found', columns.length, 'day columns in container');
|
||||
return Array.from(columns) as HTMLElement[];
|
||||
}
|
||||
|
||||
|
|
@ -193,21 +177,9 @@ export class DateEventRenderer extends BaseEventRenderer {
|
|||
* Resource-based event renderer
|
||||
*/
|
||||
export class ResourceEventRenderer extends BaseEventRenderer {
|
||||
findColumn(event: CalendarEvent): HTMLElement | null {
|
||||
const resourceName = event.resource?.name;
|
||||
if (!resourceName) {
|
||||
console.warn('ResourceEventRenderer: Event has no resource.name', event);
|
||||
return null;
|
||||
}
|
||||
|
||||
const resourceColumn = document.querySelector(`swp-resource-column[data-resource="${resourceName}"]`) as HTMLElement;
|
||||
console.log('ResourceEventRenderer: Looking for resource column with name', resourceName, 'found:', !!resourceColumn);
|
||||
return resourceColumn;
|
||||
}
|
||||
|
||||
protected getColumns(): HTMLElement[] {
|
||||
const columns = document.querySelectorAll('swp-resource-column');
|
||||
console.log('ResourceEventRenderer: Found', columns.length, 'resource columns in DOM');
|
||||
protected getColumns(container: HTMLElement): HTMLElement[] {
|
||||
const columns = container.querySelectorAll('swp-resource-column');
|
||||
console.log('ResourceEventRenderer: Found', columns.length, 'resource columns in container');
|
||||
return Array.from(columns) as HTMLElement[];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue