Implements comprehensive drag and drop for all-day events, allowing movement within the header and conversion to timed events when dragged into the calendar grid. Optimizes column detection with a cached bounding box strategy, improving performance and accuracy. Refactors event conversion logic and renames related event bus events for clarity.
123 lines
No EOL
3.8 KiB
Markdown
123 lines
No EOL
3.8 KiB
Markdown
# Komplet Bug Analyse: Drag-Drop Header Problemer
|
|
|
|
## Identificerede Problemer
|
|
|
|
### Problem 1: Original Element Fjernes For Tidligt
|
|
**Lokation**: AllDayManager.handleConvertToAllDay() linje 274
|
|
```typescript
|
|
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
|
|
|
|
```mermaid
|
|
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_event
|
|
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
|
|
```typescript
|
|
// 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
|
|
```typescript
|
|
// 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:
|
|
|
|
```typescript
|
|
// 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 |