Improves event drag and drop stack handling

Addresses an issue where dragging events that are part of a stack could lead to inconsistencies.

This change ensures that when an event is dragged and dropped, the other events in the stack are also repositioned correctly.
It traverses the stack, removes the related events from their original positions, and re-renders them in the correct column.
It also removes stack link data from the dragged element to prevent unexpected behavior.
This commit is contained in:
Janus Knudsen 2025-09-09 22:57:26 +02:00
parent 5cffc233c5
commit 86fa7d5bab
2 changed files with 375 additions and 54 deletions

View file

@ -372,6 +372,79 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
return;
}
// Check om original event var del af en stack
const originalStackLink = this.originalEvent.dataset.stackLink;
if (originalStackLink) {
try {
const stackData = JSON.parse(originalStackLink);
const stackEventIds: string[] = [];
// Saml ALLE event IDs fra hele stack chain
const allStackEventIds: Set<string> = new Set();
// Recursive funktion til at traversere stack chain
const traverseStack = (linkData: any, visitedIds: Set<string>) => {
if (linkData.prev && !visitedIds.has(linkData.prev)) {
visitedIds.add(linkData.prev);
const prevElement = document.querySelector(`swp-time-grid [data-event-id="${linkData.prev}"]`) as HTMLElement;
if (prevElement?.dataset.stackLink) {
try {
const prevLinkData = JSON.parse(prevElement.dataset.stackLink);
traverseStack(prevLinkData, visitedIds);
} catch (e) {}
}
}
if (linkData.next && !visitedIds.has(linkData.next)) {
visitedIds.add(linkData.next);
const nextElement = document.querySelector(`swp-time-grid [data-event-id="${linkData.next}"]`) as HTMLElement;
if (nextElement?.dataset.stackLink) {
try {
const nextLinkData = JSON.parse(nextElement.dataset.stackLink);
traverseStack(nextLinkData, visitedIds);
} catch (e) {}
}
}
};
// Start traversering fra original event's stackLink
traverseStack(stackData, allStackEventIds);
// Fjern original eventId da det bliver flyttet
allStackEventIds.delete(eventId);
// Find alle stack events og fjern dem
const stackEvents: CalendarEvent[] = [];
let container: HTMLElement | null = null;
allStackEventIds.forEach(id => {
const element = document.querySelector(`swp-time-grid [data-event-id="${id}"]`) as HTMLElement;
if (element) {
// Gem container reference fra første element
if (!container) {
container = element.closest('swp-events-layer') as HTMLElement;
}
const event = this.elementToCalendarEvent(element);
if (event) {
stackEvents.push(event);
}
// Fjern elementet
element.remove();
}
});
// Re-render stack events hvis vi fandt nogle
if (stackEvents.length > 0 && container) {
this.new_handleEventOverlaps(stackEvents, container);
}
} catch (e) {
console.warn('Failed to parse stackLink data:', e);
}
}
// Remove original event from any existing groups first
this.removeEventFromExistingGroups(this.originalEvent);
@ -399,6 +472,12 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
// Detect overlaps with other events in the target column and reposition if needed
this.handleDragDropOverlaps(this.draggedClone, finalColumn);
// Fjern stackLink data fra dropped element
if (this.draggedClone.dataset.stackLink) {
delete this.draggedClone.dataset.stackLink;
}
// Clean up
this.draggedClone = null;
this.originalEvent = null;
@ -1273,6 +1352,13 @@ export abstract class BaseEventRenderer implements EventRendererStrategy {
const element = this.renderEvent(event);
// Gem stack link information på DOM elementet
element.dataset.stackLink = JSON.stringify({
prev: stackLink.prev,
next: stackLink.next,
stackLevel: stackLink.stackLevel
});
// Check om dette event deler kolonne med foregående (samme start tid)
if (stackLink.prev) {
const prevEvent = result.overlappingEvents.find(e => e.id === stackLink.prev);