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.
This commit is contained in:
Janus Knudsen 2025-09-04 20:06:09 +02:00
parent 6afea2571b
commit 1aef54bffb

View file

@ -366,22 +366,51 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
const eventsLayer = columnElement.querySelector('swp-events-layer'); const eventsLayer = columnElement.querySelector('swp-events-layer');
if (!eventsLayer) return; 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 // Convert dropped element to CalendarEvent using its NEW position
const droppedEvent = this.elementToCalendarEventWithNewPosition(droppedElement, targetColumn); const droppedEvent = this.elementToCalendarEventWithNewPosition(droppedElement, targetColumn);
if (!droppedEvent) return; 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 // Check if dropped event overlaps with any existing events
let hasOverlaps = false; let hasOverlaps = false;
const overlappingEvents: CalendarEvent[] = [droppedEvent]; const overlappingEvents: CalendarEvent[] = [];
for (const existingElement of existingEvents) { for (const existingElement of existingEvents) {
const existingEvent = this.elementToCalendarEvent(existingElement); const existingEvent = this.elementToCalendarEvent(existingElement);
if (!existingEvent) continue; 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); const overlapType = this.overlapManager.detectOverlap(droppedEvent, existingEvent);
if (overlapType !== OverlapType.NONE) { if (overlapType !== OverlapType.NONE) {
hasOverlaps = true; 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 // Only re-render if there are actual overlaps
if (!hasOverlaps) { if (!hasOverlaps) {
// No overlaps - just update the dropped element's dataset with new times // No overlaps - just update the dropped element's dataset with new times