From 9cdf4fbe968839fdb67c84aa47f0539684561e45 Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Sat, 13 Sep 2025 20:47:42 +0200 Subject: [PATCH] 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. --- src/managers/DragDropManager.ts | 29 +++++++++++++++------------- src/renderers/AllDayEventRenderer.ts | 9 ++++++++- src/renderers/EventRenderer.ts | 26 ++++++++++++++++++++----- wwwroot/css/calendar-layout-css.css | 13 +++++++++++++ 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/managers/DragDropManager.ts b/src/managers/DragDropManager.ts index 36ae325..4a8a432 100644 --- a/src/managers/DragDropManager.ts +++ b/src/managers/DragDropManager.ts @@ -97,12 +97,17 @@ export class DragDropManager { const { targetDate, headerRenderer } = (event as CustomEvent).detail; if (this.draggedEventId && targetDate) { - // Emit event to convert to all-day - this.eventBus.emit('drag:convert-to-allday', { - targetDate, - originalElement: this.originalElement, - headerRenderer - }); + // Find dragget element dynamisk + const draggedElement = document.querySelector(`swp-event[data-event-id="${this.draggedEventId}"]`); + + if (draggedElement) { + // 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()) { // Convert all-day event to timed event using SwpEventElement factory this.eventBus.emit('drag:convert-allday-to-timed', { - eventId: this.draggedEventId, - originalElement: this.originalElement + eventId: this.draggedEventId }); } }); @@ -197,7 +201,6 @@ export class DragDropManager { // Start drag - emit drag:start event this.isDragStarted = true; this.eventBus.emit('drag:start', { - originalElement: this.originalElement, eventId: this.draggedEventId, mousePosition: this.initialMousePosition, mouseOffset: this.mouseOffset, @@ -274,7 +277,6 @@ export class DragDropManager { this.eventBus.emit('drag:end', { eventId: eventId, - originalElement: originalElement, finalPosition, finalColumn: positionData.column, finalY: positionData.snappedY @@ -283,7 +285,6 @@ export class DragDropManager { // This was just a click - emit click event instead this.eventBus.emit('event:click', { eventId: eventId, - originalElement: originalElement, mousePosition: { x: event.clientX, y: event.clientY } }); } @@ -491,8 +492,10 @@ export class DragDropManager { * Check if an all-day event is currently being dragged */ private isAllDayEventBeingDragged(): boolean { - if (!this.originalElement) return false; - return this.originalElement.dataset.displayType === 'allday'; + if (!this.draggedEventId) return false; + // Check if element exists as all-day event + const allDayElement = document.querySelector(`swp-allday-event[data-event-id="${this.draggedEventId}"]`); + return allDayElement !== null; } /** diff --git a/src/renderers/AllDayEventRenderer.ts b/src/renderers/AllDayEventRenderer.ts index 43d803a..a1725ce 100644 --- a/src/renderers/AllDayEventRenderer.ts +++ b/src/renderers/AllDayEventRenderer.ts @@ -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 { if (!this.container) { const header = document.querySelector('swp-calendar-header'); if (header) { + // Try to find existing 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; diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index 630853e..7ba2970 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -94,8 +94,12 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { protected setupDragEventListeners(): void { // Handle drag start eventBus.on('drag:start', (event) => { - const { originalElement, eventId, mouseOffset, column } = (event as CustomEvent).detail; - this.handleDragStart(originalElement, eventId, mouseOffset, column); + const { eventId, mouseOffset, column } = (event as CustomEvent).detail; + // 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 @@ -118,13 +122,25 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { // Handle drag end eventBus.on('drag:end', (event) => { - const { eventId, originalElement, finalColumn, finalY } = (event as CustomEvent).detail; - this.handleDragEnd(eventId, originalElement, finalColumn, finalY); + const { eventId, finalColumn, finalY } = (event as CustomEvent).detail; + // 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) 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); }); diff --git a/wwwroot/css/calendar-layout-css.css b/wwwroot/css/calendar-layout-css.css index 742b0ed..12d5322 100644 --- a/wwwroot/css/calendar-layout-css.css +++ b/wwwroot/css/calendar-layout-css.css @@ -157,6 +157,19 @@ swp-calendar-header { /* Firefox - hide scrollbar but keep space */ 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; }