# 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
<!-- Drag Group (oberste Ebene) -->
<div cdkdroplistgroup="" aydnd="" class="flex h-full flex-col">
  
  <!-- Drop Zone (Collections) -->
  <div cdkdroplist="" class="cdk-drop-list" id="collectioncsuaaDVNokl0...">
    
    <!-- Draggable Element (Asset Card) -->
    <li cdkdrag="" class="cdk-drag asset-list-item" draggable="false">
      <img src="./GlobalDAM JRI_files/anPGZszKzgKaSz1SIx2HFgduy" 
           alt="weiss_ORIGINAL">
    </li>
  </div>
</div>
```

### 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
<!-- Asset ID im Element-ID -->
<div id="anPGZszKzgKaSz1SIx2HFgduy">

<!-- Asset ID in der Bild-URL -->
<img src="./GlobalDAM JRI_files/anPGZszKzgKaSz1SIx2HFgduy">

<!-- Asset Name im alt-Attribut -->
<img alt="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
