Enables all-day event drag and drop
Implements comprehensive drag and drop for all-day events, allowing movement within the header and conversion to timed events when dragged into the calendar grid. Optimizes column detection with a cached bounding box strategy, improving performance and accuracy. Refactors event conversion logic and renames related event bus events for clarity.
This commit is contained in:
parent
f1d04ae12e
commit
0b7499521e
6 changed files with 338 additions and 106 deletions
|
|
@ -19,6 +19,12 @@ interface Position {
|
|||
y: number;
|
||||
}
|
||||
|
||||
interface ColumnBounds {
|
||||
date: string;
|
||||
left: number;
|
||||
right: number;
|
||||
}
|
||||
|
||||
export class DragDropManager {
|
||||
private eventBus: IEventBus;
|
||||
|
||||
|
|
@ -45,6 +51,9 @@ export class DragDropManager {
|
|||
lastColumnDate: null
|
||||
};
|
||||
|
||||
// Column bounds cache for coordinate-based column detection
|
||||
private columnBoundsCache: ColumnBounds[] = [];
|
||||
|
||||
// Auto-scroll properties
|
||||
private autoScrollAnimationId: number | null = null;
|
||||
private readonly scrollSpeed = 10; // pixels per frame
|
||||
|
|
@ -92,6 +101,19 @@ export class DragDropManager {
|
|||
document.body.addEventListener('mousedown', this.boundHandlers.mouseDown);
|
||||
document.body.addEventListener('mouseup', this.boundHandlers.mouseUp);
|
||||
|
||||
// Initialize column bounds cache
|
||||
this.updateColumnBoundsCache();
|
||||
|
||||
// Listen to resize events to update cache
|
||||
window.addEventListener('resize', () => {
|
||||
this.updateColumnBoundsCache();
|
||||
});
|
||||
|
||||
// Listen to navigation events to update cache
|
||||
this.eventBus.on('navigation:completed', () => {
|
||||
this.updateColumnBoundsCache();
|
||||
});
|
||||
|
||||
// Listen for header mouseover events
|
||||
this.eventBus.on('header:mouseover', (event) => {
|
||||
const { targetDate, headerRenderer } = (event as CustomEvent).detail;
|
||||
|
|
@ -116,7 +138,7 @@ export class DragDropManager {
|
|||
console.log('✅ DragDropManager: Converting to all-day for date:', targetDate);
|
||||
|
||||
// Element findes stadig som day-event, så konverter
|
||||
this.eventBus.emit('drag:convert-to-allday', {
|
||||
this.eventBus.emit('drag:convert-to-allday_event', {
|
||||
targetDate,
|
||||
originalElement: draggedElement,
|
||||
headerRenderer
|
||||
|
|
@ -147,8 +169,13 @@ export class DragDropManager {
|
|||
this.eventBus.on('header:mouseleave', (event) => {
|
||||
// Check if we're dragging ANY event
|
||||
if (this.draggedEventId) {
|
||||
this.eventBus.emit('drag:convert-from-allday', {
|
||||
draggedEventId: this.draggedEventId
|
||||
const mousePosition = { x: this.lastMousePosition.x, y: this.lastMousePosition.y };
|
||||
const column = this.getColumnDateFromX(mousePosition.x);
|
||||
|
||||
this.eventBus.emit('drag:convert-to-time_event', {
|
||||
draggedEventId: this.draggedEventId,
|
||||
mousePosition: mousePosition,
|
||||
column: column
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -358,25 +385,68 @@ export class DragDropManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Optimized column detection with caching
|
||||
* Update column bounds cache for coordinate-based column detection
|
||||
*/
|
||||
private detectColumn(mouseX: number, mouseY: number): string | null {
|
||||
const element = document.elementFromPoint(mouseX, mouseY);
|
||||
if (!element) return null;
|
||||
private updateColumnBoundsCache(): void {
|
||||
// Reset cache
|
||||
this.columnBoundsCache = [];
|
||||
|
||||
// Walk up DOM tree to find swp-day-column
|
||||
let current = element as HTMLElement;
|
||||
while (current && current.tagName !== 'SWP-DAY-COLUMN') {
|
||||
current = current.parentElement as HTMLElement;
|
||||
if (!current) return null;
|
||||
// Find alle kolonner
|
||||
const columns = document.querySelectorAll('swp-day-column');
|
||||
|
||||
// Cache hver kolonnes x-grænser
|
||||
columns.forEach(column => {
|
||||
const rect = column.getBoundingClientRect();
|
||||
const date = (column as HTMLElement).dataset.date;
|
||||
|
||||
if (date) {
|
||||
this.columnBoundsCache.push({
|
||||
date,
|
||||
left: rect.left,
|
||||
right: rect.right
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Sorter efter x-position (fra venstre til højre)
|
||||
this.columnBoundsCache.sort((a, b) => a.left - b.left);
|
||||
|
||||
console.log('📏 DragDropManager: Updated column bounds cache', {
|
||||
columns: this.columnBoundsCache.length
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column date from X coordinate using cached bounds
|
||||
*/
|
||||
private getColumnDateFromX(x: number): string | null {
|
||||
// Opdater cache hvis tom
|
||||
if (this.columnBoundsCache.length === 0) {
|
||||
this.updateColumnBoundsCache();
|
||||
}
|
||||
|
||||
const columnDate = current.dataset.date || null;
|
||||
// Find den kolonne hvor x-koordinaten er indenfor grænserne
|
||||
const column = this.columnBoundsCache.find(col =>
|
||||
x >= col.left && x <= col.right
|
||||
);
|
||||
|
||||
// Update cache if we found a new column
|
||||
return column ? column.date : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coordinate-based column detection (replaces DOM traversal)
|
||||
*/
|
||||
private detectColumn(mouseX: number, mouseY: number): string | null {
|
||||
// Brug den koordinatbaserede metode direkte
|
||||
const columnDate = this.getColumnDateFromX(mouseX);
|
||||
|
||||
// Opdater stadig den eksisterende cache hvis vi finder en kolonne
|
||||
if (columnDate && columnDate !== this.cachedElements.lastColumnDate) {
|
||||
this.cachedElements.currentColumn = current;
|
||||
this.cachedElements.lastColumnDate = columnDate;
|
||||
const columnElement = document.querySelector(`swp-day-column[data-date="${columnDate}"]`) as HTMLElement;
|
||||
if (columnElement) {
|
||||
this.cachedElements.currentColumn = columnElement;
|
||||
this.cachedElements.lastColumnDate = columnDate;
|
||||
}
|
||||
}
|
||||
|
||||
return columnDate;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue