Calendar/docs/drag-drop-header-implementation-details.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

4.4 KiB

Implementeringsdetaljer: Check for Eksisterende All-Day Event

Hvor skal checket implementeres?

Fil: src/managers/AllDayManager.ts Metode: handleConvertToAllDay() Linje: Lige efter linje 232 (start af metoden)

Præcis Implementation

// AllDayManager.ts - handleConvertToAllDay metode (linje 232)
private handleConvertToAllDay(targetDate: string, originalElement: HTMLElement): void {
    // Extract event data from original element
    const eventId = originalElement.dataset.eventId;
    const title = originalElement.dataset.title || originalElement.textContent || 'Untitled';
    const type = originalElement.dataset.type || 'work';
    const startStr = originalElement.dataset.start;
    const endStr = originalElement.dataset.end;

    if (!eventId || !startStr || !endStr) {
        console.error('Original element missing required data (eventId, start, end)');
        return;
    }

    // ===== NY KODE STARTER HER (efter linje 243) =====
    
    // CHECK 1: Er dette faktisk clone elementet?
    const isClone = eventId.startsWith('clone-');
    const actualEventId = isClone ? eventId.replace('clone-', '') : eventId;
    
    // CHECK 2: Eksisterer all-day event allerede?
    const container = this.getAllDayContainer();
    if (container) {
        const existingAllDay = container.querySelector(
            `swp-allday-event[data-event-id="${actualEventId}"]`
        );
        
        if (existingAllDay) {
            console.log(`All-day event for ${actualEventId} already exists, skipping creation`);
            return; // Exit early - don't create duplicate
        }
    }
    
    // ===== NY KODE SLUTTER HER =====
    
    // Fortsæt med normal oprettelse...
    // Create CalendarEvent for all-day conversion - preserve original times
    const originalStart = new Date(startStr);
    // ... resten af koden
}

Hvorfor virker dette?

  1. Check for clone ID: Vi checker om det draggede element er clone (starter med "clone-")
  2. Normalisér ID: Vi får det faktiske event ID uden "clone-" prefix
  3. Query DOM: Vi søger i all-day container efter eksisterende element med samme ID
  4. Early exit: Hvis det findes, logger vi og returnerer uden at oprette duplicate

Alternative Implementeringer

Option A: Track med Set (Hurtigere)

// AllDayManager class property
private activeAllDayEvents = new Set<string>();

private handleConvertToAllDay(targetDate: string, originalElement: HTMLElement): void {
    const eventId = originalElement.dataset.eventId;
    const actualEventId = eventId?.startsWith('clone-') 
        ? eventId.replace('clone-', '') 
        : eventId;
    
    // Check i memory først (hurtigere)
    if (this.activeAllDayEvents.has(actualEventId)) {
        return;
    }
    
    // Marker som aktiv
    this.activeAllDayEvents.add(actualEventId);
    
    // ... opret all-day event
}

private handleConvertFromAllDay(draggedEventId: string): void {
    // Fjern fra tracking
    this.activeAllDayEvents.delete(draggedEventId);
    
    // ... fjern all-day event
}

Option B: Data Attribute Flag

private handleConvertToAllDay(targetDate: string, originalElement: HTMLElement): void {
    // Check flag på original element
    if (originalElement.dataset.hasAllDayVersion === 'true') {
        return;
    }
    
    // Sæt flag
    originalElement.dataset.hasAllDayVersion = 'true';
    
    // ... opret all-day event
}

private handleConvertFromAllDay(draggedEventId: string): void {
    // Find original og fjern flag
    const original = document.querySelector(`[data-event-id="${draggedEventId}"]`);
    if (original) {
        delete original.dataset.hasAllDayVersion;
    }
    
    // ... fjern all-day event
}

Anbefalet Løsning

DOM Query Check (første løsning) er mest robust fordi:

  1. Den checker faktisk DOM state
  2. Ingen ekstra state at vedligeholde
  3. Fungerer selv hvis events kommer ud af sync

Test Verification

For at teste om det virker:

  1. Åbn browser console
  2. Drag et event langsomt over header
  3. Se efter "already exists" log messages
  4. Verificer kun ÉT all-day event i DOM med:
    document.querySelectorAll('swp-allday-event').length
    

Linje 274 Fix

Samtidig skal vi fjerne/kommentere linje 274:

// originalElement.remove();  // <-- KOMMENTER DENNE UD

Dette sikrer original element ikke fjernes for tidligt.