From 1aef54bffba43a074e9b60c307e5ea8a11ff6a68 Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Thu, 4 Sep 2025 20:06:09 +0200 Subject: [PATCH] Improves event overlap detection logic Refactors event dropping logic to first check for existing event groups. If a group exists and the dropped event overlaps with it, the dropped event is added to the group. Otherwise, it proceeds with full overlap detection against individual events. This change prevents unnecessary group creation and optimizes event arrangement within columns. It also ensures the dragged event is placed on the rightmost side by adding it to the overlapping events array last. --- src/renderers/EventRenderer.ts | 42 ++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index ecff38c..a361f7f 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -366,22 +366,51 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { const eventsLayer = columnElement.querySelector('swp-events-layer'); if (!eventsLayer) return; - // Get all existing events in the column (excluding the dropped element) - const existingEvents = Array.from(eventsLayer.querySelectorAll('swp-event')) - .filter(el => el !== droppedElement) as HTMLElement[]; - // Convert dropped element to CalendarEvent using its NEW position const droppedEvent = this.elementToCalendarEventWithNewPosition(droppedElement, targetColumn); if (!droppedEvent) return; + // Check if there's already an existing swp-event-group in the column + const existingGroup = eventsLayer.querySelector('swp-event-group') as HTMLElement; + if (existingGroup) { + // Check if dropped event overlaps with the group's events + const groupEvents = Array.from(existingGroup.querySelectorAll('swp-event')) as HTMLElement[]; + let overlapsWithGroup = false; + + for (const groupEvent of groupEvents) { + const existingEvent = this.elementToCalendarEvent(groupEvent); + if (!existingEvent) continue; + + const overlapType = this.overlapManager.detectOverlap(droppedEvent, existingEvent); + if (overlapType === OverlapType.COLUMN_SHARING) { + overlapsWithGroup = true; + break; + } + } + + if (overlapsWithGroup) { + // Simply add the dropped event to the existing group + this.updateElementDataset(droppedElement, droppedEvent); + this.overlapManager.addToEventGroup(existingGroup, droppedElement); + return; + } + } + + // No existing group or no overlap with existing group - run full overlap detection + const existingEvents = Array.from(eventsLayer.querySelectorAll('swp-event')) + .filter(el => el !== droppedElement) as HTMLElement[]; + // Check if dropped event overlaps with any existing events let hasOverlaps = false; - const overlappingEvents: CalendarEvent[] = [droppedEvent]; + const overlappingEvents: CalendarEvent[] = []; for (const existingElement of existingEvents) { const existingEvent = this.elementToCalendarEvent(existingElement); if (!existingEvent) continue; + // Skip if it's the same event (comparing IDs) + if (existingEvent.id === droppedEvent.id) continue; + const overlapType = this.overlapManager.detectOverlap(droppedEvent, existingEvent); if (overlapType !== OverlapType.NONE) { hasOverlaps = true; @@ -389,6 +418,9 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { } } + // Add dropped event LAST so it appears rightmost in flexbox + overlappingEvents.push(droppedEvent); + // Only re-render if there are actual overlaps if (!hasOverlaps) { // No overlaps - just update the dropped element's dataset with new times