Fixes event stacking order during drag and drop

Ensures existing events maintain their base positions when a new event is dragged and dropped into an overlapping time slot.

The fix prioritizes existing events in the stack, placing the newly dropped event on top. This ensures correct visual representation and expected behavior during event manipulation.
This commit is contained in:
Janus Knudsen 2025-09-04 23:56:22 +02:00
parent c7716d1b8f
commit 727a6ec53a

View file

@ -574,13 +574,24 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
eventsLayer.appendChild(groupContainer); eventsLayer.appendChild(groupContainer);
} else if (overlapType === OverlapType.STACKING) { } else if (overlapType === OverlapType.STACKING) {
// Handle stacking - sort by duration and stack shorter events on top // CRITICAL FIX: Respect existing event position - they stay as base
const sortedEvents = [...overlappingEvents].sort((a, b) => {
// Separate existing events from the dropped event
const existingInOverlap = overlappingEvents.filter(e => e.id !== droppedEvent.id);
const droppedIsInList = overlappingEvents.find(e => e.id === droppedEvent.id);
// Sort ONLY existing events by duration (among themselves)
const sortedExisting = [...existingInOverlap].sort((a, b) => {
const durationA = new Date(a.end).getTime() - new Date(a.start).getTime(); const durationA = new Date(a.end).getTime() - new Date(a.start).getTime();
const durationB = new Date(b.end).getTime() - new Date(b.start).getTime(); const durationB = new Date(b.end).getTime() - new Date(b.start).getTime();
return durationB - durationA; // Longer duration first (background) return durationB - durationA; // Longer existing first
}); });
// FINAL ORDER: Existing events first (base), dropped event LAST (stacked on top)
const finalEventOrder = droppedIsInList
? [...sortedExisting, droppedEvent]
: sortedExisting;
// Remove overlapping events from DOM // Remove overlapping events from DOM
const overlappingEventIds = new Set(overlappingEvents.map(e => e.id)); const overlappingEventIds = new Set(overlappingEvents.map(e => e.id));
existingEvents existingEvents
@ -590,16 +601,16 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
let underlyingElement: HTMLElement | null = null; let underlyingElement: HTMLElement | null = null;
sortedEvents.forEach((event, index) => { finalEventOrder.forEach((event, index) => {
const eventElement = this.createEventElement(event); const eventElement = this.createEventElement(event);
this.positionEvent(eventElement, event); this.positionEvent(eventElement, event);
if (index === 0) { if (index === 0) {
// First (longest duration) event renders normally at full width // First event (existing) - always remains base position
eventsLayer.appendChild(eventElement); eventsLayer.appendChild(eventElement);
underlyingElement = eventElement; underlyingElement = eventElement;
} else { } else {
// Shorter events are stacked with margin-left offset and higher z-index // Subsequent events (including dropped) - stacked on top
if (underlyingElement) { if (underlyingElement) {
this.overlapManager.createStackedEvent(eventElement, underlyingElement, index); this.overlapManager.createStackedEvent(eventElement, underlyingElement, index);
} }