From 792e77f8245872038fc259c4359c99afd280a2fc Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Thu, 18 Sep 2025 10:39:11 +0000 Subject: [PATCH] feat(dees-dashboardgrid): enhance widget placement validation and logging for drag-and-drop interactions --- .../dees-dashboardgrid.demo.ts | 156 +++++++++++++++++- .../dees-dashboardgrid/dees-dashboardgrid.ts | 42 +++-- ts_web/elements/dees-dashboardgrid/layout.ts | 4 +- 3 files changed, 187 insertions(+), 15 deletions(-) diff --git a/ts_web/elements/dees-dashboardgrid/dees-dashboardgrid.demo.ts b/ts_web/elements/dees-dashboardgrid/dees-dashboardgrid.demo.ts index 8254083..61e5c54 100644 --- a/ts_web/elements/dees-dashboardgrid/dees-dashboardgrid.demo.ts +++ b/ts_web/elements/dees-dashboardgrid/dees-dashboardgrid.demo.ts @@ -159,21 +159,169 @@ export const demoFunc = () => { } }); + // Enhanced logging for reflow events + let lastPlaceholderPosition = null; + let moveEventCounter = 0; + + // Helper function to log grid state + const logGridState = (eventName: string, details?: any) => { + const layout = grid.getLayout(); + console.group(`🔄 ${eventName} [Event #${++moveEventCounter}]`); + console.log('Timestamp:', new Date().toISOString()); + console.log('Grid Configuration:', { + columns: grid.columns, + cellHeight: grid.cellHeight, + margin: grid.margin, + editable: grid.editable, + activeBreakpoint: grid.activeBreakpoint + }); + console.log('Current Layout:', layout); + console.log('Widget Count:', layout.length); + console.log('Grid Bounds:', { + totalWidgets: grid.widgets.length, + maxY: Math.max(...layout.map(w => w.y + w.h)), + occupied: layout.map(w => `${w.id}: (${w.x},${w.y}) ${w.w}x${w.h}`).join(', ') + }); + if (details) { + console.log('Event Details:', details); + } + console.groupEnd(); + }; + + // Monitor placeholder position changes using MutationObserver + const placeholderObserver = new MutationObserver(() => { + const placeholder = grid.shadowRoot?.querySelector('.placeholder') as HTMLElement; + if (placeholder) { + const currentPosition = { + left: placeholder.style.left, + top: placeholder.style.top, + width: placeholder.style.width, + height: placeholder.style.height + }; + + if (JSON.stringify(currentPosition) !== JSON.stringify(lastPlaceholderPosition)) { + console.group('📍 Placeholder Position Changed'); + console.log('Previous:', lastPlaceholderPosition); + console.log('Current:', currentPosition); + + // Extract grid coordinates from style + const gridInfo = grid.shadowRoot?.querySelector('.grid-container'); + if (gridInfo) { + console.log('Grid Container Dimensions:', { + width: gridInfo.clientWidth, + height: gridInfo.clientHeight + }); + } + console.groupEnd(); + lastPlaceholderPosition = currentPosition; + } + } + }); + + // Start observing the shadow DOM for placeholder changes + if (grid.shadowRoot) { + placeholderObserver.observe(grid.shadowRoot, { + childList: true, + subtree: true, + attributes: true, + attributeFilter: ['style'] + }); + } + + // Log initial state + logGridState('Initial Grid State'); + grid.addEventListener('widget-move', (e: CustomEvent) => { - console.log('Widget moved:', e.detail.widget, 'Displaced:', e.detail.displaced); + logGridState('Widget Move', { + widget: e.detail.widget, + displaced: e.detail.displaced, + swappedWith: e.detail.swappedWith + }); }); + grid.addEventListener('widget-resize', (e: CustomEvent) => { - console.log('Widget resized:', e.detail.widget, 'Displaced:', e.detail.displaced); + logGridState('Widget Resize', { + widget: e.detail.widget, + displaced: e.detail.displaced, + swappedWith: e.detail.swappedWith + }); }); + grid.addEventListener('widget-remove', (e: CustomEvent) => { - console.log('Widget removed:', e.detail.widget); + logGridState('Widget Remove', { + removedWidget: e.detail.widget + }); updateStatus(); }); + grid.addEventListener('layout-change', () => { - console.log('Layout changed:', grid.getLayout()); + logGridState('Layout Change'); updateStatus(); }); + // Monitor during drag/resize operations using pointer events + grid.addEventListener('pointerdown', (e: PointerEvent) => { + const isHeader = (e.target as HTMLElement).closest('.widget-header'); + const isResizeHandle = (e.target as HTMLElement).closest('.resize-handle'); + + if (isHeader || isResizeHandle) { + console.group(`🎯 Interaction Started: ${isHeader ? 'Drag' : 'Resize'}`); + console.log('Target Widget:', (e.target as HTMLElement).closest('.widget')?.getAttribute('data-widget-id')); + console.log('Pointer Position:', { x: e.clientX, y: e.clientY }); + console.groupEnd(); + + // Track pointer move during interaction + const handlePointerMove = (moveEvent: PointerEvent) => { + const widget = (e.target as HTMLElement).closest('.widget'); + if (widget) { + console.log(`↔️ Pointer Move:`, { + widgetId: widget.getAttribute('data-widget-id'), + position: { x: moveEvent.clientX, y: moveEvent.clientY }, + delta: { + x: moveEvent.clientX - e.clientX, + y: moveEvent.clientY - e.clientY + } + }); + } + }; + + const handlePointerUp = () => { + console.group('🏁 Interaction Ended'); + logGridState('Final State After Interaction'); + console.groupEnd(); + document.removeEventListener('pointermove', handlePointerMove); + document.removeEventListener('pointerup', handlePointerUp); + }; + + document.addEventListener('pointermove', handlePointerMove); + document.addEventListener('pointerup', handlePointerUp); + } + }); + + // Log when widgets are added + const originalAddWidget = grid.addWidget.bind(grid); + grid.addWidget = (widget: any, autoPosition?: boolean) => { + console.group('➕ Adding Widget'); + console.log('New Widget:', widget); + console.log('Auto Position:', autoPosition); + const result = originalAddWidget(widget, autoPosition); + logGridState('After Widget Added'); + console.groupEnd(); + return result; + }; + + // Log compact operations + const originalCompact = grid.compact.bind(grid); + grid.compact = (direction?: string) => { + console.group('🗜️ Compacting Grid'); + console.log('Direction:', direction || 'vertical'); + logGridState('Before Compact'); + const result = originalCompact(direction); + logGridState('After Compact'); + console.groupEnd(); + return result; + }; + updateStatus(); }}>