Enables all-day event conversion on column hover
Allows users to convert all-day events to timed events by dragging them over a day column. This implementation adds logic to the DragDropManager to detect when an all-day event is dragged over a column. It then emits a new event, 'drag:mouseenter-column', carrying the event data and target column information. The event rendering service handles this event.
This commit is contained in:
parent
7a79297854
commit
78ca23c07a
5 changed files with 69 additions and 125 deletions
|
|
@ -289,46 +289,6 @@ export class SwpEventElement extends BaseSwpEventElement {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to convert an all-day HTML element to a timed SwpEventElement
|
||||
*/
|
||||
public static fromAllDayElement(allDayElement: HTMLElement): SwpEventElement {
|
||||
const eventId = allDayElement.dataset.eventId || '';
|
||||
const title = allDayElement.dataset.title || allDayElement.textContent || 'Untitled';
|
||||
const type = allDayElement.dataset.type || 'work';
|
||||
const startStr = allDayElement.dataset.start;
|
||||
const endStr = allDayElement.dataset.end;
|
||||
const durationStr = allDayElement.dataset.duration;
|
||||
|
||||
if (!startStr || !endStr) {
|
||||
throw new Error('All-day element missing start/end dates');
|
||||
}
|
||||
|
||||
const originalStart = new Date(startStr);
|
||||
const duration = durationStr ? parseInt(durationStr) : 60;
|
||||
|
||||
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);
|
||||
|
||||
const calendarEvent: CalendarEvent = {
|
||||
id: eventId,
|
||||
title: title,
|
||||
start: startDate,
|
||||
end: endDate,
|
||||
type: type,
|
||||
allDay: false,
|
||||
syncStatus: 'synced',
|
||||
metadata: {
|
||||
duration: duration.toString()
|
||||
}
|
||||
};
|
||||
|
||||
return SwpEventElement.fromCalendarEvent(calendarEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
DragEndEventPayload,
|
||||
DragMouseEnterHeaderEventPayload,
|
||||
DragMouseLeaveHeaderEventPayload,
|
||||
DragMouseEnterColumnEventPayload,
|
||||
DragColumnChangeEventPayload
|
||||
} from '../types/EventTypes';
|
||||
import { MousePosition } from '../types/DragDropTypes';
|
||||
|
|
@ -116,6 +117,8 @@ export class DragDropManager {
|
|||
const target = e.target as HTMLElement;
|
||||
if (target.closest('swp-calendar-header')) {
|
||||
this.handleHeaderMouseEnter(e as MouseEvent);
|
||||
} else if (target.closest('swp-day-column')) {
|
||||
this.handleColumnMouseEnter(e as MouseEvent);
|
||||
} else if (target.closest('swp-event')) {
|
||||
// Entered an event - activate hover tracking and set color
|
||||
const eventElement = target.closest<HTMLElement>('swp-event');
|
||||
|
|
@ -652,6 +655,46 @@ export class DragDropManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse enter on day column - for converting all-day to timed events
|
||||
*/
|
||||
private handleColumnMouseEnter(event: MouseEvent): void {
|
||||
// Only handle if we're dragging an all-day event
|
||||
if (!this.isDragStarted || !this.draggedClone || !this.draggedClone.hasAttribute('data-allday')) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🎯 DragDropManager: Mouse entered day column');
|
||||
|
||||
const position: MousePosition = { x: event.clientX, y: event.clientY };
|
||||
const targetColumn = ColumnDetectionUtils.getColumnBounds(position);
|
||||
|
||||
if (!targetColumn) {
|
||||
console.warn("No column detected when entering day column");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate snapped Y position
|
||||
const snappedY = this.calculateSnapPosition(position.y, targetColumn);
|
||||
|
||||
// Extract CalendarEvent from the dragged clone
|
||||
const calendarEvent = SwpEventElement.extractCalendarEventFromElement(this.draggedClone);
|
||||
|
||||
const dragMouseEnterPayload: DragMouseEnterColumnEventPayload = {
|
||||
targetColumn: targetColumn,
|
||||
mousePosition: position,
|
||||
snappedY: snappedY,
|
||||
originalElement: this.draggedElement,
|
||||
draggedClone: this.draggedClone,
|
||||
calendarEvent: calendarEvent,
|
||||
// Delegate pattern - allows EventRenderer to replace the clone
|
||||
replaceClone: (newClone: HTMLElement) => {
|
||||
this.draggedClone = newClone;
|
||||
}
|
||||
};
|
||||
this.eventBus.emit('drag:mouseenter-column', dragMouseEnterPayload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse leave from calendar header - simplified using native events
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -71,13 +71,6 @@ export class HeaderManager {
|
|||
originalElement: !!originalElement,
|
||||
cloneElement: !!cloneElement
|
||||
});
|
||||
|
||||
eventBus.emit('header:mouseleave', {
|
||||
element: this.getCalendarHeader(),
|
||||
targetDate,
|
||||
originalElement,
|
||||
cloneElement
|
||||
});
|
||||
};
|
||||
|
||||
// Listen for drag events from DragDropManager
|
||||
|
|
|
|||
|
|
@ -88,17 +88,6 @@ export class EventRenderingService {
|
|||
// Handle all drag events and delegate to appropriate renderer
|
||||
this.setupDragEventListeners();
|
||||
|
||||
// Listen for conversion from all-day event to time event
|
||||
this.eventBus.on('drag:convert-to-time_event', (event: Event) => {
|
||||
const { draggedElement, mousePosition, column } = (event as CustomEvent).detail;
|
||||
console.log('🔄 EventRendererManager: Received drag:convert-to-time_event', {
|
||||
draggedElement: draggedElement?.dataset.eventId,
|
||||
mousePosition,
|
||||
column
|
||||
});
|
||||
this.handleConvertToTimeEvent(draggedElement, mousePosition, column);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -302,59 +291,6 @@ export class EventRenderingService {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle conversion from all-day event to time event
|
||||
*/
|
||||
private handleConvertToTimeEvent(draggedElement: HTMLElement, mousePosition: { x: number; y: number }, column: string): void {
|
||||
// Use the provided draggedElement directly
|
||||
const allDayClone = draggedElement;
|
||||
const draggedEventId = draggedElement?.dataset.eventId?.replace('clone-', '') || '';
|
||||
|
||||
|
||||
// Use SwpEventElement factory to create day event from all-day event
|
||||
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();
|
||||
|
||||
// Set clone ID
|
||||
dayElement.dataset.eventId = `clone-${draggedEventId}`;
|
||||
|
||||
// Find target column
|
||||
const columnElement = document.querySelector(`swp-day-column[data-date="${column}"]`);
|
||||
if (!columnElement) {
|
||||
console.warn('EventRendererManager: Target column not found', { column });
|
||||
return;
|
||||
}
|
||||
|
||||
// Find events layer in the column
|
||||
const eventsLayer = columnElement.querySelector('swp-events-layer');
|
||||
if (!eventsLayer) {
|
||||
console.warn('EventRendererManager: Events layer not found in column');
|
||||
return;
|
||||
}
|
||||
|
||||
// Add to events layer
|
||||
eventsLayer.appendChild(dayElement);
|
||||
|
||||
// Position based on mouse Y coordinate
|
||||
const columnRect = columnElement.getBoundingClientRect();
|
||||
const relativeY = Math.max(0, mousePosition.y - columnRect.top);
|
||||
dayElement.style.top = `${relativeY}px`;
|
||||
|
||||
// Set drag styling
|
||||
dayElement.style.zIndex = '1000';
|
||||
dayElement.style.cursor = 'grabbing';
|
||||
dayElement.style.opacity = '';
|
||||
dayElement.style.transform = '';
|
||||
|
||||
console.log('✅ EventRendererManager: Converted all-day event to time event', {
|
||||
draggedEventId,
|
||||
column,
|
||||
mousePosition,
|
||||
relativeY
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-render affected columns after drag to recalculate stacking/grouping
|
||||
|
|
|
|||
|
|
@ -67,6 +67,18 @@ export interface DragMouseLeaveHeaderEventPayload {
|
|||
draggedClone: HTMLElement| null;
|
||||
}
|
||||
|
||||
// Drag mouse enter column event payload
|
||||
export interface DragMouseEnterColumnEventPayload {
|
||||
targetColumn: ColumnBounds;
|
||||
mousePosition: MousePosition;
|
||||
snappedY: number;
|
||||
originalElement: HTMLElement | null;
|
||||
draggedClone: HTMLElement;
|
||||
calendarEvent: CalendarEvent;
|
||||
// Delegate pattern - allows subscriber to replace the dragged clone
|
||||
replaceClone: (newClone: HTMLElement) => void;
|
||||
}
|
||||
|
||||
// Drag column change event payload
|
||||
export interface DragColumnChangeEventPayload {
|
||||
originalElement: HTMLElement;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue