Refactor event rendering with column-based event management
Improves event rendering by integrating event filtering directly into column data sources Key changes: - Moves event filtering responsibility to IColumnDataSource - Simplifies event rendering pipeline by pre-filtering events per column - Supports both date and resource-based calendar modes - Enhances drag and drop event update mechanism Optimizes calendar rendering performance and flexibility
This commit is contained in:
parent
eeaeddeef8
commit
17909696ed
9 changed files with 179 additions and 250 deletions
|
|
@ -1,6 +1,7 @@
|
|||
// Event rendering strategy interface and implementations
|
||||
|
||||
import { ICalendarEvent } from '../types/CalendarTypes';
|
||||
import { IColumnInfo } from '../types/ColumnDataSource';
|
||||
import { Configuration } from '../configurations/CalendarConfig';
|
||||
import { SwpEventElement } from '../elements/SwpEventElement';
|
||||
import { PositionUtils } from '../utils/PositionUtils';
|
||||
|
|
@ -12,9 +13,12 @@ import { EventLayoutCoordinator, IGridGroupLayout, IStackedEventLayout } from '.
|
|||
|
||||
/**
|
||||
* Interface for event rendering strategies
|
||||
*
|
||||
* Note: renderEvents now receives columns with pre-filtered events,
|
||||
* not a flat array of events. Each column contains its own events.
|
||||
*/
|
||||
export interface IEventRenderer {
|
||||
renderEvents(events: ICalendarEvent[], container: HTMLElement): void;
|
||||
renderEvents(columns: IColumnInfo[], container: HTMLElement): void;
|
||||
clearEvents(container?: HTMLElement): void;
|
||||
renderSingleColumnEvents?(column: IColumnBounds, events: ICalendarEvent[]): void;
|
||||
handleDragStart?(payload: IDragStartEventPayload): void;
|
||||
|
|
@ -98,28 +102,22 @@ export class DateEventRenderer implements IEventRenderer {
|
|||
|
||||
/**
|
||||
* Handle drag move event
|
||||
* Only updates visual position and time - date stays the same
|
||||
*/
|
||||
public handleDragMove(payload: IDragMoveEventPayload): void {
|
||||
|
||||
const swpEvent = payload.draggedClone as SwpEventElement;
|
||||
const columnDate = this.dateService.parseISO(payload.columnBounds!!.identifier);
|
||||
swpEvent.updatePosition(columnDate, payload.snappedY);
|
||||
swpEvent.updatePosition(payload.snappedY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle column change during drag
|
||||
* Only moves the element visually - no data updates here
|
||||
* Data updates happen on drag:end in EventRenderingService
|
||||
*/
|
||||
public handleColumnChange(payload: IDragColumnChangeEventPayload): void {
|
||||
|
||||
const eventsLayer = payload.newColumn.element.querySelector('swp-events-layer');
|
||||
if (eventsLayer && payload.draggedClone.parentElement !== eventsLayer) {
|
||||
eventsLayer.appendChild(payload.draggedClone);
|
||||
|
||||
// Recalculate timestamps with new column date
|
||||
const currentTop = parseFloat(payload.draggedClone.style.top) || 0;
|
||||
const swpEvent = payload.draggedClone as SwpEventElement;
|
||||
const columnDate = this.dateService.parseISO(payload.newColumn.identifier);
|
||||
swpEvent.updatePosition(columnDate, currentTop);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,32 +218,36 @@ export class DateEventRenderer implements IEventRenderer {
|
|||
}
|
||||
|
||||
|
||||
renderEvents(events: ICalendarEvent[], container: HTMLElement): void {
|
||||
// Filter out all-day events - they should be handled by AllDayEventRenderer
|
||||
const timedEvents = events.filter(event => !event.allDay);
|
||||
renderEvents(columns: IColumnInfo[], container: HTMLElement): void {
|
||||
// Find column DOM elements in the container
|
||||
const columnElements = this.getColumns(container);
|
||||
|
||||
// Find columns in the specific container for regular events
|
||||
const columns = this.getColumns(container);
|
||||
// Render events for each column using pre-filtered events from IColumnInfo
|
||||
columns.forEach((columnInfo, index) => {
|
||||
const columnElement = columnElements[index];
|
||||
if (!columnElement) return;
|
||||
|
||||
columns.forEach(column => {
|
||||
const columnEvents = this.getEventsForColumn(column, timedEvents);
|
||||
const eventsLayer = column.querySelector('swp-events-layer') as HTMLElement;
|
||||
// Filter out all-day events - they should be handled by AllDayEventRenderer
|
||||
const timedEvents = columnInfo.events.filter(event => !event.allDay);
|
||||
|
||||
if (eventsLayer) {
|
||||
this.renderColumnEvents(columnEvents, eventsLayer);
|
||||
const eventsLayer = columnElement.querySelector('swp-events-layer') as HTMLElement;
|
||||
if (eventsLayer && timedEvents.length > 0) {
|
||||
this.renderColumnEvents(timedEvents, eventsLayer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Render events for a single column
|
||||
* Note: events are already filtered for this column
|
||||
*/
|
||||
public renderSingleColumnEvents(column: IColumnBounds, events: ICalendarEvent[]): void {
|
||||
const columnEvents = this.getEventsForColumn(column.element, events);
|
||||
// Filter out all-day events
|
||||
const timedEvents = events.filter(event => !event.allDay);
|
||||
const eventsLayer = column.element.querySelector('swp-events-layer') as HTMLElement;
|
||||
|
||||
if (eventsLayer) {
|
||||
this.renderColumnEvents(columnEvents, eventsLayer);
|
||||
if (eventsLayer && timedEvents.length > 0) {
|
||||
this.renderColumnEvents(timedEvents, eventsLayer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -388,24 +390,4 @@ export class DateEventRenderer implements IEventRenderer {
|
|||
const columns = container.querySelectorAll('swp-day-column');
|
||||
return Array.from(columns) as HTMLElement[];
|
||||
}
|
||||
|
||||
protected getEventsForColumn(column: HTMLElement, events: ICalendarEvent[]): ICalendarEvent[] {
|
||||
const columnId = column.dataset.columnId;
|
||||
if (!columnId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Create start and end of day for interval overlap check
|
||||
// In date-mode, columnId is ISO date string like "2024-11-13"
|
||||
const columnStart = this.dateService.parseISO(`${columnId}T00:00:00`);
|
||||
const columnEnd = this.dateService.parseISO(`${columnId}T23:59:59.999`);
|
||||
|
||||
const columnEvents = events.filter(event => {
|
||||
// Interval overlap: event overlaps with column day if event.start < columnEnd AND event.end > columnStart
|
||||
const overlaps = event.start < columnEnd && event.end > columnStart;
|
||||
return overlaps;
|
||||
});
|
||||
|
||||
return columnEvents;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue