Refactors event element handling with web components
Introduces web components for event elements, separating timed and all-day events into distinct components for better organization and reusability. This change also simplifies event rendering and drag-and-drop operations by leveraging the properties and lifecycle methods of web components.
This commit is contained in:
parent
1a47214831
commit
a9d6d14c93
6 changed files with 253 additions and 274 deletions
|
|
@ -76,10 +76,10 @@ export class AllDayEventRenderer {
|
|||
const container = this.getContainer();
|
||||
if (!container) return null;
|
||||
|
||||
let dayEvent = new SwpAllDayEventElement(event);
|
||||
dayEvent.applyGridPositioning(layout);
|
||||
const dayEvent = SwpAllDayEventElement.fromCalendarEvent(event);
|
||||
dayEvent.applyGridPositioning(layout.row, layout.startColumn, layout.endColumn);
|
||||
|
||||
container.appendChild(dayEvent.getElement());
|
||||
container.appendChild(dayEvent);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -43,86 +43,6 @@ export class DateEventRenderer implements EventRendererStrategy {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update clone timestamp based on new position
|
||||
*/
|
||||
private updateCloneTimestamp(payload: DragMoveEventPayload): void {
|
||||
if (payload.draggedClone.dataset.allDay === "true" || !payload.columnBounds) return;
|
||||
|
||||
const gridSettings = calendarConfig.getGridSettings();
|
||||
const { hourHeight, dayStartHour, snapInterval } = gridSettings;
|
||||
|
||||
if (!payload.draggedClone.dataset.originalDuration) {
|
||||
throw new DOMException("missing clone.dataset.originalDuration");
|
||||
}
|
||||
|
||||
// Calculate snapped start minutes
|
||||
const minutesFromGridStart = (payload.snappedY / hourHeight) * 60;
|
||||
const snappedStartMinutes = this.calculateSnappedMinutes(
|
||||
minutesFromGridStart, dayStartHour, snapInterval
|
||||
);
|
||||
|
||||
// Calculate end minutes
|
||||
const originalDuration = parseInt(payload.draggedClone.dataset.originalDuration);
|
||||
const endTotalMinutes = snappedStartMinutes + originalDuration;
|
||||
|
||||
// Update UI
|
||||
this.updateTimeDisplay(payload.draggedClone, snappedStartMinutes, endTotalMinutes);
|
||||
|
||||
// Update data attributes
|
||||
this.updateDateTimeAttributes(
|
||||
payload.draggedClone,
|
||||
new Date(payload.columnBounds.date),
|
||||
snappedStartMinutes,
|
||||
endTotalMinutes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate snapped minutes from grid start
|
||||
*/
|
||||
private calculateSnappedMinutes(minutesFromGridStart: number, dayStartHour: number, snapInterval: number): number {
|
||||
const actualStartMinutes = (dayStartHour * 60) + minutesFromGridStart;
|
||||
return Math.round(actualStartMinutes / snapInterval) * snapInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update time display in the UI
|
||||
*/
|
||||
private updateTimeDisplay(element: HTMLElement, startMinutes: number, endMinutes: number): void {
|
||||
const timeElement = element.querySelector('swp-event-time');
|
||||
if (!timeElement) return;
|
||||
|
||||
const startTime = this.formatTimeFromMinutes(startMinutes);
|
||||
const endTime = this.formatTimeFromMinutes(endMinutes);
|
||||
timeElement.textContent = `${startTime} - ${endTime}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update data-start and data-end attributes with ISO timestamps
|
||||
*/
|
||||
private updateDateTimeAttributes(element: HTMLElement, columnDate: Date, startMinutes: number, endMinutes: number): void {
|
||||
const startDate = this.dateService.createDateAtTime(columnDate, startMinutes);
|
||||
|
||||
let endDate = this.dateService.createDateAtTime(columnDate, endMinutes);
|
||||
|
||||
// Handle cross-midnight events
|
||||
if (endMinutes >= 1440) {
|
||||
const extraDays = Math.floor(endMinutes / 1440);
|
||||
endDate = this.dateService.addDays(endDate, extraDays);
|
||||
}
|
||||
|
||||
// Convert to UTC before storing as ISO string
|
||||
element.dataset.start = this.dateService.toUTC(startDate);
|
||||
element.dataset.end = this.dateService.toUTC(endDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format minutes since midnight to time string
|
||||
*/
|
||||
private formatTimeFromMinutes(totalMinutes: number): string {
|
||||
return this.dateService.minutesToTime(totalMinutes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle drag start event
|
||||
|
|
@ -155,15 +75,12 @@ export class DateEventRenderer implements EventRendererStrategy {
|
|||
* Handle drag move event
|
||||
*/
|
||||
public handleDragMove(payload: DragMoveEventPayload): void {
|
||||
if (!this.draggedClone) return;
|
||||
|
||||
// Update position - snappedY is already the event top position
|
||||
// Add +1px to match the initial positioning offset from SwpEventElement
|
||||
this.draggedClone.style.top = (payload.snappedY + 1) + 'px';
|
||||
|
||||
// Update timestamp display
|
||||
this.updateCloneTimestamp(payload);
|
||||
if (!this.draggedClone || !payload.columnBounds) return;
|
||||
|
||||
// Delegate to SwpEventElement to update position and timestamps
|
||||
const swpEvent = this.draggedClone as SwpEventElement;
|
||||
const columnDate = new Date(payload.columnBounds.date);
|
||||
swpEvent.updatePosition(columnDate, payload.snappedY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -191,16 +108,9 @@ export class DateEventRenderer implements EventRendererStrategy {
|
|||
|
||||
// Recalculate timestamps with new column date
|
||||
const currentTop = parseFloat(this.draggedClone.style.top) || 0;
|
||||
const mockPayload: DragMoveEventPayload = {
|
||||
draggedElement: dragColumnChangeEvent.originalElement,
|
||||
draggedClone: this.draggedClone,
|
||||
mousePosition: dragColumnChangeEvent.mousePosition,
|
||||
mouseOffset: { x: 0, y: 0 },
|
||||
columnBounds: dragColumnChangeEvent.newColumn,
|
||||
snappedY: currentTop
|
||||
};
|
||||
|
||||
this.updateCloneTimestamp(mockPayload);
|
||||
const swpEvent = this.draggedClone as SwpEventElement;
|
||||
const columnDate = new Date(dragColumnChangeEvent.newColumn.date);
|
||||
swpEvent.updatePosition(columnDate, currentTop);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -272,8 +182,7 @@ export class DateEventRenderer implements EventRendererStrategy {
|
|||
}
|
||||
|
||||
private renderEvent(event: CalendarEvent): HTMLElement {
|
||||
const swpEvent = SwpEventElement.fromCalendarEvent(event);
|
||||
return swpEvent.getElement();
|
||||
return SwpEventElement.fromCalendarEvent(event);
|
||||
}
|
||||
|
||||
protected calculateEventPosition(event: CalendarEvent): { top: number; height: number } {
|
||||
|
|
|
|||
|
|
@ -247,8 +247,7 @@ export class EventRenderingService {
|
|||
|
||||
|
||||
// Use SwpEventElement factory to create day event from all-day event
|
||||
const dayEventElement = SwpEventElement.fromAllDayElement(allDayClone as HTMLElement);
|
||||
const dayElement = dayEventElement.getElement();
|
||||
const dayElement = SwpEventElement.fromAllDayElement(allDayClone as HTMLElement);
|
||||
|
||||
// Remove the all-day clone - it's no longer needed since we're converting to day event
|
||||
allDayClone.remove();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue