Enables all-day event conversion via drag and drop

Allows users to drag timed events to the header area to convert them to all-day events.

This also enables dragging all-day events to different days
by updating the grid column position.

A header mouseover detection is set up to emit the 'header:mouseover' event,
handling both the timed event to all-day conversion and the
all-day event movement to different days.
This commit is contained in:
Janus Knudsen 2025-08-29 22:49:53 +02:00
parent 2c934a7a1a
commit 383eab7524

View file

@ -63,6 +63,84 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
const { eventId, targetDate, headerRenderer } = (event as CustomEvent).detail;
this.handleConvertToAllDay(eventId, targetDate, headerRenderer);
});
// Listen for header mouseover events (like original ColumnDetector)
eventBus.on('header:mouseover', (event) => {
const { element, targetDate, headerRenderer } = (event as CustomEvent).detail;
if (this.draggedClone && targetDate) {
// Scenario 1: Timed event being dragged to header - convert to all-day
if (this.draggedClone.tagName === 'SWP-EVENT') {
console.log('EventRenderer: Converting timed event to all-day for date:', targetDate);
headerRenderer.addToAllDay(element);
this.convertToAllDayPreview(targetDate);
}
// Scenario 2: All-day event being moved to different day
else if (this.draggedClone.tagName === 'SWP-ALLDAY-EVENT') {
const currentDate = this.draggedClone.parentElement?.getAttribute('data-date');
if (currentDate !== targetDate) {
console.log('EventRenderer: Moving all-day event from', currentDate, 'to', targetDate);
this.moveAllDayToNewDate(targetDate);
}
}
}
});
// Setup header mouseover detection for all-day conversion
this.setupHeaderMouseoverDetection();
}
/**
* Setup header mouseover detection during drag
*/
private setupHeaderMouseoverDetection(): void {
document.addEventListener('mouseover', (event) => {
if (!this.draggedClone) return; // Only during active drag
const target = event.target as HTMLElement;
// Check if mouse is over a day header
let dayHeader = target.closest('swp-day-header') as HTMLElement;
if (dayHeader) {
const targetDate = dayHeader.dataset.date;
if (targetDate && this.draggedClone.tagName === 'SWP-EVENT') {
console.log(`EventRenderer: Mouse over day header for date ${targetDate}`);
// Find the header renderer from the calendar header
const calendarHeader = dayHeader.closest('swp-calendar-header');
if (calendarHeader) {
// Emit header mouseover event like the original ColumnDetector did
eventBus.emit('header:mouseover', {
element: dayHeader,
targetDate: targetDate,
headerRenderer: this.getHeaderRenderer()
});
}
}
}
});
}
/**
* Get the header renderer instance for triggering addToAllDay
*/
private getHeaderRenderer(): any {
// For now, we'll create a simple object with the addToAllDay method
// This mimics what ColumnDetector had access to
return {
addToAllDay: (element: HTMLElement) => {
// Find the calendar header and call the HeaderRenderer's addToAllDay method
const calendarHeader = element.closest('swp-calendar-header') as HTMLElement;
if (calendarHeader) {
// Import and use HeaderRenderer directly
import('./HeaderRenderer').then(({ BaseHeaderRenderer }) => {
const headerRenderer = new BaseHeaderRenderer();
headerRenderer.addToAllDay(element);
});
}
}
};
}
/**
@ -348,6 +426,56 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
element.remove();
}, 300);
}
/**
* Convert dragged clone to all-day event preview
*/
private convertToAllDayPreview(targetDate: string): void {
if (!this.draggedClone) return;
// Only convert once
if (this.draggedClone.tagName === 'SWP-ALLDAY-EVENT') {
return;
}
// Transform clone to all-day format
this.transformCloneToAllDay(this.draggedClone, targetDate);
console.log(`EventRenderer: Converted clone to all-day preview for ${targetDate}`);
}
/**
* Move all-day event to a new date container
*/
private moveAllDayToNewDate(targetDate: string): void {
if (!this.draggedClone) return;
const calendarHeader = document.querySelector('swp-calendar-header');
if (!calendarHeader) return;
// Find the all-day container
const allDayContainer = calendarHeader.querySelector('swp-allday-container');
if (!allDayContainer) return;
// Calculate new column index
const dayHeaders = document.querySelectorAll('swp-day-header');
let columnIndex = 1;
dayHeaders.forEach((header, index) => {
if ((header as HTMLElement).dataset.date === targetDate) {
columnIndex = index + 1;
}
});
// Update grid column position
(this.draggedClone as HTMLElement).style.gridColumn = columnIndex.toString();
// Move to all-day container if not already there
if (this.draggedClone.parentElement !== allDayContainer) {
allDayContainer.appendChild(this.draggedClone);
}
console.log(`EventRenderer: Moved all-day event to date ${targetDate}, column ${columnIndex}`);
}
renderEvents(events: CalendarEvent[], container: HTMLElement, config: CalendarConfig): void {
console.log('BaseEventRenderer: renderEvents called with', events.length, 'events');