Calendar/docs/drag-drop-header-complete-bug-analysis.md
Janus Knudsen 46b8bf9fb5 Fixes drag and drop to header issues
Addresses two key issues related to dragging events to the header: the premature removal of the original event element and the creation of duplicate all-day events.

The original event is no longer removed when dragging to the header; it is now only removed upon a successful drop.

Also, it prevents the creation of duplicate all-day events by checking for existing all-day events before creating new ones, using DOM queries to ensure accurate state.
2025-09-17 23:39:29 +02:00

3.8 KiB

Komplet Bug Analyse: Drag-Drop Header Problemer

Identificerede Problemer

Problem 1: Original Element Fjernes For Tidligt

Lokation: AllDayManager.handleConvertToAllDay() linje 274

originalElement.remove();  // ❌ FORKERT - skal ikke fjernes her

Problem 2: Duplicate All-Day Events ved Mouseover

Lokation: AllDayManager.handleConvertToAllDay() linje 232-285

Hver gang header:mouseover fyrer (hvilket kan ske mange gange under drag), oprettes et NYT all-day event uden at checke om det allerede eksisterer.

Event Flow Problem

sequenceDiagram
    participant Mouse
    participant Header
    participant AllDay as AllDayManager
    
    Note over Mouse: Dragger over header
    loop Hver mouseover event
        Mouse->>Header: mouseover
        Header->>AllDay: drag:convert-to-allday
        AllDay->>AllDay: Opretter NYT all-day event ❌
        Note over AllDay: Ingen check for eksisterende!
    end
    Note over AllDay: Resultat: Multiple all-day events!

Løsning

Fix 1: Check for Eksisterende All-Day Event

// AllDayManager.handleConvertToAllDay()
private handleConvertToAllDay(targetDate: string, originalElement: HTMLElement): void {
    const eventId = originalElement.dataset.eventId;
    
    // CHECK: Eksisterer all-day event allerede?
    const existingAllDay = document.querySelector(
        `swp-allday-container swp-allday-event[data-event-id="${eventId}"]`
    );
    
    if (existingAllDay) {
        console.log('All-day event already exists, skipping creation');
        return; // Exit early - don't create duplicate
    }
    
    // Fortsæt med at oprette all-day event...
}

Fix 2: Fjern IKKE Original Element

// Linje 274 - skal fjernes eller kommenteres ud:
// originalElement.remove();  // <-- FJERN DENNE LINJE

Fix 3: Track Conversion State (Optional)

For at undgå gentagne conversions, kunne vi tracke state:

// AllDayManager
private convertedEventIds = new Set<string>();

private handleConvertToAllDay(targetDate: string, originalElement: HTMLElement): void {
    const eventId = originalElement.dataset.eventId;
    
    // Check if already converted
    if (this.convertedEventIds.has(eventId)) {
        return;
    }
    
    // Mark as converted
    this.convertedEventIds.add(eventId);
    
    // Create all-day event...
}

private handleConvertFromAllDay(draggedEventId: string): void {
    // Clear conversion state
    this.convertedEventIds.delete(draggedEventId);
    
    // Remove all-day event...
}

Komplet Fix Checklist

  1. AllDayManager.handleConvertToAllDay()

    • Tilføj check for eksisterende all-day event
    • Fjern/kommenter originalElement.remove() linje 274
    • Log når duplicate undgås
  2. AllDayManager.handleConvertFromAllDay()

    • Verificer at all-day event faktisk fjernes
    • Clear evt. conversion state
  3. Test Scenarios

    • Hurtig mouseover frem og tilbage over header
    • Langsom drag over header
    • Drag ind i header → ud → ind igen
    • Multiple events dragges samtidig (hvis muligt)

Root Causes

  1. Manglende idempotency: handleConvertToAllDay() er ikke idempotent
  2. Forkert element lifecycle: Original fjernes for tidligt
  3. Manglende state tracking: Ingen tracking af hvilke events der er konverteret

Performance Overvejelser

HeaderManager throttler mouseover events (linje 41-49), men det er ikke nok når musen bevæger sig langsomt over header. Vi skal have idempotent logik.

Implementeringsrækkefølge

  1. Først: Fix duplicate all-day events (check for existing)
  2. Derefter: Fjern originalElement.remove()
  3. Test: Verificer at begge problemer er løst
  4. Optional: Implementer conversion state tracking for bedre performance