Improves drag and drop functionality and fixes issues

Refactors drag and drop logic to dynamically find the dragged element, ensuring correct behavior even when the DOM changes during the drag operation.

Creates all-day container if it doesn't exist.

This resolves issues where drag and drop operations would fail if the original element was no longer present in the DOM or if the container didn't exist.
This commit is contained in:
Janus Knudsen 2025-09-13 20:47:42 +02:00
parent 7054c0d40a
commit 9cdf4fbe96
4 changed files with 58 additions and 19 deletions

View file

@ -97,12 +97,17 @@ export class DragDropManager {
const { targetDate, headerRenderer } = (event as CustomEvent).detail; const { targetDate, headerRenderer } = (event as CustomEvent).detail;
if (this.draggedEventId && targetDate) { if (this.draggedEventId && targetDate) {
// Emit event to convert to all-day // Find dragget element dynamisk
this.eventBus.emit('drag:convert-to-allday', { const draggedElement = document.querySelector(`swp-event[data-event-id="${this.draggedEventId}"]`);
targetDate,
originalElement: this.originalElement, if (draggedElement) {
headerRenderer // Element findes stadig som day-event, så konverter
}); this.eventBus.emit('drag:convert-to-allday', {
targetDate,
originalElement: draggedElement,
headerRenderer
});
}
} }
}); });
@ -126,8 +131,7 @@ export class DragDropManager {
if (this.draggedEventId && this.isAllDayEventBeingDragged()) { if (this.draggedEventId && this.isAllDayEventBeingDragged()) {
// Convert all-day event to timed event using SwpEventElement factory // Convert all-day event to timed event using SwpEventElement factory
this.eventBus.emit('drag:convert-allday-to-timed', { this.eventBus.emit('drag:convert-allday-to-timed', {
eventId: this.draggedEventId, eventId: this.draggedEventId
originalElement: this.originalElement
}); });
} }
}); });
@ -197,7 +201,6 @@ export class DragDropManager {
// Start drag - emit drag:start event // Start drag - emit drag:start event
this.isDragStarted = true; this.isDragStarted = true;
this.eventBus.emit('drag:start', { this.eventBus.emit('drag:start', {
originalElement: this.originalElement,
eventId: this.draggedEventId, eventId: this.draggedEventId,
mousePosition: this.initialMousePosition, mousePosition: this.initialMousePosition,
mouseOffset: this.mouseOffset, mouseOffset: this.mouseOffset,
@ -274,7 +277,6 @@ export class DragDropManager {
this.eventBus.emit('drag:end', { this.eventBus.emit('drag:end', {
eventId: eventId, eventId: eventId,
originalElement: originalElement,
finalPosition, finalPosition,
finalColumn: positionData.column, finalColumn: positionData.column,
finalY: positionData.snappedY finalY: positionData.snappedY
@ -283,7 +285,6 @@ export class DragDropManager {
// This was just a click - emit click event instead // This was just a click - emit click event instead
this.eventBus.emit('event:click', { this.eventBus.emit('event:click', {
eventId: eventId, eventId: eventId,
originalElement: originalElement,
mousePosition: { x: event.clientX, y: event.clientY } mousePosition: { x: event.clientX, y: event.clientY }
}); });
} }
@ -491,8 +492,10 @@ export class DragDropManager {
* Check if an all-day event is currently being dragged * Check if an all-day event is currently being dragged
*/ */
private isAllDayEventBeingDragged(): boolean { private isAllDayEventBeingDragged(): boolean {
if (!this.originalElement) return false; if (!this.draggedEventId) return false;
return this.originalElement.dataset.displayType === 'allday'; // Check if element exists as all-day event
const allDayElement = document.querySelector(`swp-allday-event[data-event-id="${this.draggedEventId}"]`);
return allDayElement !== null;
} }
/** /**

View file

@ -13,13 +13,20 @@ export class AllDayEventRenderer {
} }
/** /**
* Get or cache all-day container * Get or cache all-day container, create if it doesn't exist
*/ */
private getContainer(): HTMLElement | null { private getContainer(): HTMLElement | null {
if (!this.container) { if (!this.container) {
const header = document.querySelector('swp-calendar-header'); const header = document.querySelector('swp-calendar-header');
if (header) { if (header) {
// Try to find existing container
this.container = header.querySelector('swp-allday-container'); this.container = header.querySelector('swp-allday-container');
// If not found, create it
if (!this.container) {
this.container = document.createElement('swp-allday-container');
header.appendChild(this.container);
}
} }
} }
return this.container; return this.container;

View file

@ -94,8 +94,12 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
protected setupDragEventListeners(): void { protected setupDragEventListeners(): void {
// Handle drag start // Handle drag start
eventBus.on('drag:start', (event) => { eventBus.on('drag:start', (event) => {
const { originalElement, eventId, mouseOffset, column } = (event as CustomEvent).detail; const { eventId, mouseOffset, column } = (event as CustomEvent).detail;
this.handleDragStart(originalElement, eventId, mouseOffset, column); // Find element dynamically
const originalElement = document.querySelector(`swp-event[data-event-id="${eventId}"]`) as HTMLElement;
if (originalElement) {
this.handleDragStart(originalElement, eventId, mouseOffset, column);
}
}); });
// Handle drag move // Handle drag move
@ -118,13 +122,25 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
// Handle drag end // Handle drag end
eventBus.on('drag:end', (event) => { eventBus.on('drag:end', (event) => {
const { eventId, originalElement, finalColumn, finalY } = (event as CustomEvent).detail; const { eventId, finalColumn, finalY } = (event as CustomEvent).detail;
this.handleDragEnd(eventId, originalElement, finalColumn, finalY); // Find element dynamically - could be swp-event or swp-allday-event
let originalElement = document.querySelector(`swp-event[data-event-id="${eventId}"]`) as HTMLElement;
if (!originalElement) {
originalElement = document.querySelector(`swp-allday-event[data-event-id="${eventId}"]`) as HTMLElement;
}
if (originalElement) {
this.handleDragEnd(eventId, originalElement, finalColumn, finalY);
}
}); });
// Handle click (when drag threshold not reached) // Handle click (when drag threshold not reached)
eventBus.on('event:click', (event) => { eventBus.on('event:click', (event) => {
const { eventId, originalElement } = (event as CustomEvent).detail; const { eventId } = (event as CustomEvent).detail;
// Find element dynamically
let originalElement = document.querySelector(`swp-event[data-event-id="${eventId}"]`) as HTMLElement;
if (!originalElement) {
originalElement = document.querySelector(`swp-allday-event[data-event-id="${eventId}"]`) as HTMLElement;
}
this.handleEventClick(eventId, originalElement); this.handleEventClick(eventId, originalElement);
}); });

View file

@ -157,6 +157,19 @@ swp-calendar-header {
/* Firefox - hide scrollbar but keep space */ /* Firefox - hide scrollbar but keep space */
scrollbar-width: auto; /* Normal width to match content scrollbar */ scrollbar-width: auto; /* Normal width to match content scrollbar */
/* All-day events container */
swp-allday-container {
grid-column: 1 / -1;
grid-row: 2;
display: grid;
grid-template-columns: repeat(var(--grid-columns, 7), minmax(var(--day-column-min-width), 1fr));
grid-template-rows: repeat(1, auto);
gap: 2px;
padding: 2px;
align-items: center;
overflow: hidden;
}
scrollbar-color: transparent transparent; scrollbar-color: transparent transparent;
} }