Refactors all-day event layout calculation
Simplifies all-day event rendering by streamlining the layout calculation and event placement process, using the AllDayLayoutEngine to determine the grid positions. This removes deprecated methods and improves overall code clarity.
This commit is contained in:
parent
9dfd4574d8
commit
4141bffca4
7 changed files with 76 additions and 321 deletions
|
|
@ -2,6 +2,7 @@ import { CalendarEvent } from '../types/CalendarTypes';
|
|||
import { calendarConfig } from '../core/CalendarConfig';
|
||||
import { TimeFormatter } from '../utils/TimeFormatter';
|
||||
import { PositionUtils } from '../utils/PositionUtils';
|
||||
import { EventLayout } from '../utils/AllDayLayoutEngine';
|
||||
|
||||
/**
|
||||
* Abstract base class for event DOM elements
|
||||
|
|
@ -75,7 +76,7 @@ export class SwpEventElement extends BaseEventElement {
|
|||
private createInnerStructure(): void {
|
||||
const timeRange = TimeFormatter.formatTimeRange(this.event.start, this.event.end);
|
||||
const durationMinutes = (this.event.end.getTime() - this.event.start.getTime()) / (1000 * 60);
|
||||
|
||||
|
||||
this.element.innerHTML = `
|
||||
<swp-event-time data-duration="${durationMinutes}">${timeRange}</swp-event-time>
|
||||
<swp-event-title>${this.event.title}</swp-event-title>
|
||||
|
|
@ -107,20 +108,20 @@ export class SwpEventElement extends BaseEventElement {
|
|||
public createClone(): SwpEventElement {
|
||||
// Clone the underlying DOM element
|
||||
const clonedElement = this.element.cloneNode(true) as HTMLElement;
|
||||
|
||||
|
||||
// Create new SwpEventElement instance from the cloned DOM
|
||||
const clonedSwpEvent = SwpEventElement.fromExistingElement(clonedElement);
|
||||
|
||||
|
||||
// Apply "clone-" prefix to ID
|
||||
clonedSwpEvent.updateEventId(`clone-${this.event.id}`);
|
||||
|
||||
|
||||
// Cache original duration for drag operations
|
||||
const originalDuration = this.getOriginalEventDuration();
|
||||
clonedSwpEvent.element.dataset.originalDuration = originalDuration.toString();
|
||||
|
||||
|
||||
// Set height from original element
|
||||
clonedSwpEvent.element.style.height = this.element.style.height || `${this.element.getBoundingClientRect().height}px`;
|
||||
|
||||
|
||||
return clonedSwpEvent;
|
||||
}
|
||||
|
||||
|
|
@ -130,11 +131,11 @@ export class SwpEventElement extends BaseEventElement {
|
|||
public static fromExistingElement(element: HTMLElement): SwpEventElement {
|
||||
// Extract CalendarEvent data from DOM element
|
||||
const event = this.extractCalendarEventFromElement(element);
|
||||
|
||||
|
||||
// Create new instance but replace the created element with the existing one
|
||||
const swpEvent = new SwpEventElement(event);
|
||||
swpEvent.element = element;
|
||||
|
||||
|
||||
return swpEvent;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +203,7 @@ export class SwpEventElement extends BaseEventElement {
|
|||
const now = new Date();
|
||||
const startDate = new Date(originalStart);
|
||||
startDate.setHours(now.getHours() || 9, now.getMinutes() || 0, 0, 0);
|
||||
|
||||
|
||||
const endDate = new Date(startDate);
|
||||
endDate.setMinutes(endDate.getMinutes() + duration);
|
||||
|
||||
|
|
@ -228,14 +229,12 @@ export class SwpEventElement extends BaseEventElement {
|
|||
* All-day event element (now using unified swp-event tag)
|
||||
*/
|
||||
export class SwpAllDayEventElement extends BaseEventElement {
|
||||
private columnIndex: number;
|
||||
|
||||
private constructor(event: CalendarEvent, columnIndex: number) {
|
||||
constructor(event: CalendarEvent) {
|
||||
super(event);
|
||||
this.columnIndex = columnIndex;
|
||||
this.setAllDayAttributes();
|
||||
this.createInnerStructure();
|
||||
this.applyGridPositioning();
|
||||
// this.applyGridPositioning();
|
||||
}
|
||||
|
||||
protected createElement(): HTMLElement {
|
||||
|
|
@ -264,128 +263,9 @@ export class SwpAllDayEventElement extends BaseEventElement {
|
|||
/**
|
||||
* Apply CSS grid positioning
|
||||
*/
|
||||
private applyGridPositioning(): void {
|
||||
this.element.style.gridColumn = this.columnIndex.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set grid row for this all-day event
|
||||
*/
|
||||
public setGridRow(row: number): void {
|
||||
this.element.style.gridRow = row.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set grid column span for this all-day event
|
||||
*/
|
||||
public setColumnSpan(startColumn: number, endColumn: number): void {
|
||||
this.element.style.gridColumn = `${startColumn} / ${endColumn + 1}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create from CalendarEvent and layout (provided by AllDayManager)
|
||||
*/
|
||||
public static fromCalendarEventWithLayout(
|
||||
event: CalendarEvent,
|
||||
layout: { startColumn: number; endColumn: number; row: number; columnSpan: number }
|
||||
): SwpAllDayEventElement {
|
||||
// Create element with provided layout
|
||||
const element = new SwpAllDayEventElement(event, layout.startColumn);
|
||||
|
||||
// Set complete grid-area instead of individual properties
|
||||
public applyGridPositioning(layout: EventLayout): void {
|
||||
const gridArea = `${layout.row} / ${layout.startColumn} / ${layout.row + 1} / ${layout.endColumn + 1}`;
|
||||
element.element.style.gridArea = gridArea;
|
||||
|
||||
console.log('✅ SwpAllDayEventElement: Created all-day event with AllDayLayoutEngine', {
|
||||
eventId: event.id,
|
||||
title: event.title,
|
||||
gridArea: gridArea,
|
||||
layout: layout
|
||||
});
|
||||
|
||||
return element;
|
||||
this.element.style.gridArea = gridArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create from CalendarEvent and target date (DEPRECATED - use AllDayManager.calculateAllDayEventLayout)
|
||||
* @deprecated Use AllDayManager.calculateAllDayEventLayout() and fromCalendarEventWithLayout() instead
|
||||
*/
|
||||
public static fromCalendarEvent(event: CalendarEvent, targetDate?: string): SwpAllDayEventElement {
|
||||
console.warn('⚠️ SwpAllDayEventElement.fromCalendarEvent is deprecated. Use AllDayManager.calculateAllDayEventLayout() instead.');
|
||||
|
||||
// Fallback to simple column calculation without overlap detection
|
||||
const { startColumn, endColumn } = this.calculateColumnSpan(event);
|
||||
const finalStartColumn = targetDate ? this.getColumnIndexForDate(targetDate) : startColumn;
|
||||
const finalEndColumn = targetDate ? finalStartColumn : endColumn;
|
||||
|
||||
// Create element with row 1 (no overlap detection)
|
||||
const element = new SwpAllDayEventElement(event, finalStartColumn);
|
||||
element.setGridRow(1);
|
||||
element.setColumnSpan(finalStartColumn, finalEndColumn);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate column span based on event start and end dates
|
||||
*/
|
||||
private static calculateColumnSpan(event: CalendarEvent): { startColumn: number; endColumn: number; columnSpan: number } {
|
||||
const dayHeaders = document.querySelectorAll('swp-day-header');
|
||||
|
||||
// Extract dates from headers
|
||||
const headerDates: string[] = [];
|
||||
dayHeaders.forEach(header => {
|
||||
const date = (header as HTMLElement).dataset.date;
|
||||
if (date) {
|
||||
headerDates.push(date);
|
||||
}
|
||||
});
|
||||
|
||||
// Format event dates for comparison (YYYY-MM-DD format)
|
||||
const eventStartDate = event.start.toISOString().split('T')[0];
|
||||
const eventEndDate = event.end.toISOString().split('T')[0];
|
||||
|
||||
// Find start and end column indices
|
||||
let startColumn = 1;
|
||||
let endColumn = headerDates.length;
|
||||
|
||||
headerDates.forEach((dateStr, index) => {
|
||||
if (dateStr === eventStartDate) {
|
||||
startColumn = index + 1;
|
||||
}
|
||||
if (dateStr === eventEndDate) {
|
||||
endColumn = index + 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure end column is at least start column
|
||||
if (endColumn < startColumn) {
|
||||
endColumn = startColumn;
|
||||
}
|
||||
|
||||
const columnSpan = endColumn - startColumn + 1;
|
||||
|
||||
return { startColumn, endColumn, columnSpan };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column index for a specific date
|
||||
*/
|
||||
private static getColumnIndexForDate(targetDate: string): number {
|
||||
const dayHeaders = document.querySelectorAll('swp-day-header');
|
||||
let columnIndex = 1;
|
||||
dayHeaders.forEach((header, index) => {
|
||||
if ((header as HTMLElement).dataset.date === targetDate) {
|
||||
columnIndex = index + 1;
|
||||
}
|
||||
});
|
||||
return columnIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two column ranges overlap
|
||||
*/
|
||||
private static columnsOverlap(startA: number, endA: number, startB: number, endB: number): boolean {
|
||||
return !(endA < startB || endB < startA);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue