# Angular CDK Drag & Drop Analysis - GlobalDAM ## Framework Detection **Web Application:** Agravity GlobalDAM **Framework:** Angular 19.2.14 **Drag & Drop:** Angular CDK (Component Dev Kit) **Styling:** TailwindCSS ## Technical Findings ### 1. Angular CDK Implementation ```html
  • weiss_ORIGINAL
  • ``` ### 2. Key Observations #### Native HTML5 Drag ist DEAKTIVIERT ```html draggable="false" ``` **Bedeutung:** - Kein Zugriff auf native `dragstart`, `drag`, `dragend` Events - Kein `event.dataTransfer` API verfügbar - Angular CDK simuliert Drag & Drop komplett in JavaScript - Daten werden NICHT über natives Clipboard/DataTransfer übertragen #### Angular CDK Direktiven - `cdkdroplistgroup` - Gruppiert mehrere Drop-Zonen - `cdkdroplist` - Markiert Drop-Bereiche (Collections, Clipboard) - `cdkdrag` - Markiert draggbare Elemente (Assets) - `cdkdroplistsortingdisabled` - Sortierung deaktiviert #### Asset Identifikation ```html
    weiss_ORIGINAL ``` ## Impact on WebDrop Bridge ### ❌ Bisheriger Ansatz funktioniert NICHT Unser aktueller Ansatz basiert auf: 1. Interception von nativen Drag-Events 2. Manipulation von `event.dataTransfer.effectAllowed` und `.dropEffect` 3. Setzen von URLs im DataTransfer **Das funktioniert NICHT mit Angular CDK**, da: - Angular CDK das native Drag & Drop komplett umgeht - Keine nativen Events gefeuert werden - DataTransfer API nicht verwendet wird ### ✅ Mögliche Lösungsansätze #### Ansatz 1: JavaScript Injection zur Laufzeit Injiziere JavaScript-Code, der Angular CDK Events abfängt: ```javascript // Überwache Angular CDK Event-Handler document.addEventListener('cdkDragStarted', (event) => { const assetId = event.source.element.nativeElement.id; const assetName = event.source.element.nativeElement.querySelector('img')?.alt; // Sende an Qt WebChannel bridge.handleDragStart(assetId, assetName); }); document.addEventListener('cdkDragDropped', (event) => { // Verhindere das Standard-Verhalten event.preventDefault(); // Starte nativen Drag von Qt aus bridge.initNativeDrag(); }); ``` **Vorteile:** - ✅ Direkter Zugriff auf Angular CDK Events - ✅ Kann Asset-Informationen extrahieren - ✅ Kann Drag-Operationen abfangen **Nachteile:** - ⚠️ Erfordert genaue Kenntnis der Angular CDK Internals - ⚠️ Könnte bei Angular CDK Updates brechen - ⚠️ Komplexer zu implementieren #### Ansatz 2: DOM Mutation Observer Überwache DOM-Änderungen während des Drags: ```javascript const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // Suche nach CDK Drag-Elementen mit bestimmten Klassen const dragElement = document.querySelector('.cdk-drag-preview'); if (dragElement) { const assetId = dragElement.querySelector('[id^="a"]')?.id; bridge.handleDrag(assetId); } }); }); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] }); ``` **Vorteile:** - ✅ Robuster gegenüber Framework-Updates - ✅ Funktioniert mit beliebigen Frameworks **Nachteile:** - ⚠️ Performance-Overhead - ⚠️ Kann falsche Positive erzeugen #### Ansatz 3: Qt WebChannel Bridge mit Custom Events Nutze Qt WebChannel, um mit der Angular-Anwendung zu kommunizieren: ```python # Python-Seite (Qt) class DragBridge(QObject): @Slot(str, str) def onAssetDragStart(self, asset_id: str, asset_name: str): """Called from JavaScript when Angular CDK drag starts.""" logger.info(f"Asset drag started: {asset_id} ({asset_name})") self.convert_and_drag(asset_id, asset_name) ``` ```javascript // JavaScript-Seite (injiziert via QWebEngineScript) new QWebChannel(qt.webChannelTransport, (channel) => { const dragBridge = channel.objects.dragBridge; // Monkey-patch Angular CDK's DragRef const originalStartDraggingSequence = CdkDrag.prototype._startDraggingSequence; CdkDrag.prototype._startDraggingSequence = function(event) { const assetElement = this.element.nativeElement; const assetId = assetElement.id; const assetName = assetElement.querySelector('img')?.alt; // Benachrichtige Qt dragBridge.onAssetDragStart(assetId, assetName); // Rufe original Angular CDK Methode auf return originalStartDraggingSequence.call(this, event); }; }); ``` **Vorteile:** - ✅ Saubere Kommunikation zwischen Qt und Web - ✅ Kann Asset-Informationen zuverlässig extrahieren - ✅ Typensicher (Qt Signals/Slots) **Nachteile:** - ⚠️ Erfordert Monkey-Patching von Angular CDK - ⚠️ Kann bei CDK Updates brechen #### Ansatz 4: Browser DevTools Protocol (Chrome DevTools) Nutze Chrome DevTools Protocol für tiefere Integration: ```python from PySide6.QtWebEngineCore import QWebEngineProfile profile = QWebEngineProfile.defaultProfile() profile.setRequestInterceptor(...) # Intercepte Netzwerk-Requests und injiziere Header # Überwache JavaScript-Execution via CDP ``` **Vorteile:** - ✅ Sehr mächtig, kann JavaScript-Execution überwachen - ✅ Kann Events auf niedrigerer Ebene abfangen **Nachteile:** - ⚠️ Sehr komplex - ⚠️ Erfordert Chrome DevTools Protocol Kenntnisse - ⚠️ Performance-Overhead ## Empfohlener Ansatz ### **Ansatz 3: Qt WebChannel Bridge** (BEVORZUGT) **Begründung:** 1. ✅ Saubere Architektur mit klarer Trennung 2. ✅ Typsicher durch Qt Signals/Slots 3. ✅ Kann Asset-IDs und -Namen zuverlässig extrahieren 4. ✅ Funktioniert auch wenn Angular CDK interne Änderungen hat 5. ✅ Ermöglicht bidirektionale Kommunikation **Implementierungsschritte:** ### Phase 1: Asset-Informationen extrahieren 1. JavaScript via QWebEngineScript injizieren 2. Qt WebChannel setuppen 3. Angular CDK Events überwachen (ohne Monkey-Patching als Test) 4. Asset-IDs und Namen an Qt senden ### Phase 2: Native Drag initiieren 1. Bei CDK Drag-Start: Extrahiere Asset-Informationen 2. Sende Asset-ID an Backend/API 3. Erhalte lokalen Dateipfad oder Azure Blob URL 4. Konvertiere zu lokalem Pfad (wie aktuell) 5. Initiiere nativen Drag mit QDrag ### Phase 3: Drag-Feedback 1. Zeige Drag-Preview in Qt (optional) 2. Update Cursor während Drag 3. Cleanup nach Drag-Ende ## Asset-ID zu Dateipfad Mapping Die Anwendung verwendet Asset-IDs in mehreren Formaten: ```javascript // Asset-ID: anPGZszKzgKaSz1SIx2HFgduy // Mögliche URL-Konstruktion: const assetUrl = `https://dev.agravity.io/api/assets/${assetId}`; const downloadUrl = `https://dev.agravity.io/api/assets/${assetId}/download`; const blobUrl = `https://static.agravity.io/${workspaceId}/${assetId}/${filename}`; ``` **Für WebDrop Bridge:** - Asset-ID aus DOM extrahieren - Asset-Metadaten via API abrufen (falls verfügbar) - Blob-URL konstruieren - URL Converter nutzen (bereits implementiert!) ## Next Steps 1. **Proof of Concept**: Qt WebChannel mit einfachem Event-Logger 2. **Asset-ID Extraction**: JavaScript Injection testen 3. **API Research**: GlobalDAM API untersuchen (Asset-Metadaten) 4. **Integration**: Mit bestehendem URLConverter verbinden 5. **Testing**: Mit echten Assets testen ## Hinweise - Angular CDK Version kann sich unterscheiden - Code muss robust sein - Asset-IDs scheinen eindeutig zu sein (Base64-ähnlich) - Die Anwendung nutzt Azure Blob Storage (basierend auf bisherigen URLs) - Custom Components (`ay-*`) deuten auf eine eigene Component Library hin