From e0b83ebd70eea4ec23b38937041637b229a1150f Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Thu, 11 Sep 2025 12:10:34 +0200 Subject: [PATCH] wip, buggy --- src/managers/DragDropManager.ts | 4 +- src/renderers/EventRenderer.ts | 146 +++++++++++++++++++++----------- 2 files changed, 100 insertions(+), 50 deletions(-) diff --git a/src/managers/DragDropManager.ts b/src/managers/DragDropManager.ts index 0836b8c..9130511 100644 --- a/src/managers/DragDropManager.ts +++ b/src/managers/DragDropManager.ts @@ -144,7 +144,7 @@ export class DragDropManager { let eventElement = target; while (eventElement && eventElement.tagName !== 'SWP-EVENTS-LAYER') { - if (eventElement.tagName === 'SWP-EVENT' || eventElement.tagName === 'SWP-ALLDAY-EVENT') { + if (eventElement.tagName === 'SWP-EVENT') { break; } eventElement = eventElement.parentElement as HTMLElement; @@ -496,7 +496,7 @@ export class DragDropManager { */ private isAllDayEventBeingDragged(): boolean { if (!this.originalElement) return false; - return this.originalElement.tagName === 'SWP-ALLDAY-EVENT'; + return this.originalElement.dataset.displayType === 'allday'; } /** diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index 431d4e4..72f05c3 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -489,7 +489,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { // Behold z-index hvis det er et stacked event // Update dataset with new times after successful drop (only for timed events) - if (this.draggedClone.tagName !== 'SWP-ALLDAY-EVENT') { + if (this.draggedClone.dataset.displayType !== 'allday') { const newEvent = this.elementToCalendarEvent(this.draggedClone); if (newEvent) { this.draggedClone.dataset.start = newEvent.start.toISOString(); @@ -692,7 +692,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { if (!this.draggedClone) return; // Only convert once - if (this.draggedClone.tagName === 'SWP-ALLDAY-EVENT') return; + if (this.draggedClone.dataset.displayType === 'allday') return; // Transform clone to all-day format this.transformCloneToAllDay(this.draggedClone, targetDate); @@ -703,7 +703,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { } /** - * Transform clone from timed to all-day event + * Transform clone from timed to all-day event by modifying existing element */ private transformCloneToAllDay(clone: HTMLElement, targetDate: string): void { const calendarHeader = document.querySelector('swp-calendar-header'); @@ -713,15 +713,14 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { const allDayContainer = calendarHeader.querySelector('swp-allday-container'); if (!allDayContainer) return; - // Extract all original event data + // Extract event data for transformation const titleElement = clone.querySelector('swp-event-title'); const eventTitle = titleElement ? titleElement.textContent || 'Untitled' : 'Untitled'; const timeElement = clone.querySelector('swp-event-time'); - const eventTime = timeElement ? timeElement.textContent || '' : ''; const eventDuration = timeElement ? timeElement.getAttribute('data-duration') || '' : ''; - // Calculate column index + // Calculate column index for CSS Grid positioning const dayHeaders = document.querySelectorAll('swp-day-header'); let columnIndex = 1; dayHeaders.forEach((header, index) => { @@ -730,37 +729,37 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { } }); - // Create CalendarEvent object for the factory - const tempEvent: CalendarEvent = { - id: clone.dataset.eventId || '', - title: eventTitle, - start: new Date(`${targetDate}T00:00:00`), - end: new Date(`${targetDate}T23:59:59`), - type: clone.dataset.type || 'work', - allDay: true, - syncStatus: 'synced', - metadata: { - duration: eventDuration - } - }; - - // Create all-day event using factory - const swpAllDayEvent = SwpAllDayEventElement.fromCalendarEvent(tempEvent, targetDate); - const allDayEvent = swpAllDayEvent.getElement(); - - console.log("allDayEvent", allDayEvent.dataset); - // grid-row will be set by checkAndAnimateAllDayHeight() based on actual position - - // Remove original clone - if (clone.parentElement) { - clone.parentElement.removeChild(clone); + // Transform the existing element in-place instead of creating new one + // Update dataset for all-day format + clone.dataset.displayType = "allday"; + clone.dataset.allDay = "true"; + clone.dataset.start = `${targetDate}T00:00:00`; + clone.dataset.end = `${targetDate}T23:59:59`; + if (eventDuration) { + clone.dataset.duration = eventDuration; } - // Add to all-day container - allDayContainer.appendChild(allDayEvent); + // Change content to all-day format (just title) + clone.innerHTML = eventTitle; - // Update reference - this.draggedClone = allDayEvent; + // Clear timed event positioning + clone.style.position = ''; + clone.style.top = ''; + clone.style.height = ''; + clone.style.left = ''; + clone.style.right = ''; + + // Apply CSS grid positioning for all-day + clone.style.gridColumn = columnIndex.toString(); + + // Move element to all-day container + const parent = clone.parentElement; + if (parent) { + parent.removeChild(clone); + } + allDayContainer.appendChild(clone); + + // draggedClone reference stays the same since it's the same element // Check if height animation is needed this.triggerAllDayHeightAnimation(); @@ -773,38 +772,89 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { if (!this.draggedClone) return; // Only convert if it's an all-day event - if (this.draggedClone.tagName !== 'SWP-ALLDAY-EVENT') return; + if (this.draggedClone.dataset.displayType !== 'allday') return; // Transform clone to timed format this.transformAllDayToTimed(this.draggedClone, targetColumn, targetY); } /** - * Handle all-day to timed conversion using SwpEventElement factory + * Handle all-day to timed conversion by transforming existing element */ private handleConvertAllDayToTimed(eventId: string, originalElement: HTMLElement): void { if (!this.draggedClone) return; // Only convert if it's an all-day event - if (this.draggedClone.tagName !== 'SWP-ALLDAY-EVENT') return; + if (this.draggedClone.dataset.displayType !== 'allday') return; - // Use SwpEventElement factory to create a proper timed event - const swpTimedEvent = SwpEventElement.fromAllDayElement(this.draggedClone); - const newTimedElement = swpTimedEvent.getElement(); + // Transform the existing element instead of creating a new one + this.transformAllDayToTimedInPlace(this.draggedClone); + } + + /** + * Transform all-day element to timed by modifying existing element in place + */ + private transformAllDayToTimedInPlace(allDayElement: HTMLElement): void { + // Extract event data + const eventId = allDayElement.dataset.eventId || ''; + const eventTitle = allDayElement.dataset.title || allDayElement.textContent || 'Untitled'; + const eventType = allDayElement.dataset.type || 'work'; + const duration = parseInt(allDayElement.dataset.duration || '60'); - // Apply drag styling to the new element - this.applyDragStyling(newTimedElement); + // Calculate position for timed event (use current time or 9 AM default) + const now = new Date(); + const startHour = now.getHours() || 9; + const startMinutes = now.getMinutes() || 0; - // Get parent container - const parent = this.draggedClone.parentElement; + // Transform the existing element in-place instead of creating new one + // Update dataset for timed format + allDayElement.dataset.displayType = "timed"; + delete allDayElement.dataset.allDay; - // Replace the all-day clone with the new timed event element + // Set timed event structure + const startTime = this.formatTime(new Date(2000, 0, 1, startHour, startMinutes)); + const endTime = this.formatTime(new Date(2000, 0, 1, startHour, startMinutes + duration)); + + allDayElement.innerHTML = ` + ${startTime} - ${endTime} + ${eventTitle} + `; + + // Clear all-day positioning + allDayElement.style.gridColumn = ''; + + // Apply timed event positioning + allDayElement.style.position = 'absolute'; + allDayElement.style.left = '2px'; + allDayElement.style.right = '2px'; + allDayElement.style.top = '100px'; // Default position, will be adjusted by drag system + allDayElement.style.height = '57px'; // Default height for 1 hour + + // Find a day column to place the element (try to use today's column) + const columns = document.querySelectorAll('swp-day-column'); + let targetColumn = columns[0]; // fallback + + const today = new Date().toISOString().split('T')[0]; + columns.forEach(col => { + if ((col as HTMLElement).dataset.date === today) { + targetColumn = col; + } + }); + + const eventsLayer = targetColumn?.querySelector('swp-events-layer'); + + // Move element from all-day container to events layer + const parent = allDayElement.parentElement; if (parent) { - parent.replaceChild(newTimedElement, this.draggedClone); + parent.removeChild(allDayElement); } - // Update our reference to the new element - this.draggedClone = newTimedElement; + // Add to events layer + if (eventsLayer) { + eventsLayer.appendChild(allDayElement); + } + + // draggedClone reference stays the same since it's the same element } /**