Fix: Abbrechen-Dialog, Overlay-Stacking, Queue-Cancel

1. Confirm-Dialog z-index ueber Progress-Popup (10000 > 9000)
2. Progress-Popup wird ausgeblendet waehrend Confirm-Dialog offen
3. Kein dunkler-werdendes Overlay bei mehrfachem Abbrechen-Klick
4. Abbrechen funktioniert jetzt auch fuer Lagen in der Warteschlange
   (werden direkt aus der Queue entfernt statt auf Start zu warten)
5. Cancel-Status wird im Popup-Titel angezeigt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
Claude Dev
2026-04-09 20:50:30 +02:00
Ursprung 990ece1346
Commit fb0c47eee4
3 geänderte Dateien mit 79 neuen und 24 gelöschten Zeilen

Datei anzeigen

@@ -437,11 +437,11 @@ class AgentOrchestrator:
return True return True
async def cancel_refresh(self, incident_id: int) -> bool: async def cancel_refresh(self, incident_id: int) -> bool:
"""Fordert Abbruch eines laufenden Refreshes an.""" """Fordert Abbruch eines laufenden oder wartenden Refreshes an."""
if self._current_task != incident_id: # Check if it's the currently running task
return False if self._current_task == incident_id:
self._cancel_requested.add(incident_id) self._cancel_requested.add(incident_id)
logger.info(f"Cancel angefordert fuer Lage {incident_id}") logger.info(f"Cancel angefordert fuer laufende Lage {incident_id}")
if self._ws_manager: if self._ws_manager:
try: try:
vis, cb, tid = await self._get_incident_visibility(incident_id) vis, cb, tid = await self._get_incident_visibility(incident_id)
@@ -454,6 +454,43 @@ class AgentOrchestrator:
}, vis, cb, tid) }, vis, cb, tid)
return True return True
# Check if it's in the queue (not yet started)
if incident_id in self._queued_ids:
self._queued_ids.discard(incident_id)
# Remove from asyncio queue (rebuild without this ID)
removed = False
new_items = []
while not self._queue.empty():
try:
item = self._queue.get_nowait()
iid = item[0] if isinstance(item, tuple) else item
if iid == incident_id:
removed = True
self._queue.task_done()
else:
new_items.append(item)
except Exception:
break
for item in new_items:
self._queue.put_nowait(item)
logger.info(f"Lage {incident_id} aus Warteschlange entfernt (removed={removed})")
# Send cancelled event
if self._ws_manager:
try:
vis, cb, tid = await self._get_incident_visibility(incident_id)
except Exception:
vis, cb, tid = "public", None, None
await self._ws_manager.broadcast_for_incident({
"type": "refresh_cancelled",
"incident_id": incident_id,
"data": {"status": "cancelled"},
}, vis, cb, tid)
return True
return False
def _check_cancelled(self, incident_id: int): def _check_cancelled(self, incident_id: int):
"""Prüft ob Abbruch angefordert wurde und wirft CancelledError.""" """Prüft ob Abbruch angefordert wurde und wirft CancelledError."""
if incident_id in self._cancel_requested: if incident_id in self._cancel_requested:

Datei anzeigen

@@ -1710,7 +1710,7 @@ a:hover {
inset: 0; inset: 0;
background: var(--backdrop); background: var(--backdrop);
backdrop-filter: blur(4px); backdrop-filter: blur(4px);
z-index: 100; z-index: 10000;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }

Datei anzeigen

@@ -2224,23 +2224,41 @@ async handleRefresh() {
async cancelRefresh() { async cancelRefresh() {
if (!this.currentIncidentId) return; if (!this.currentIncidentId) return;
const ok = await confirmDialog('Laufende Recherche abbrechen?');
if (!ok) return;
// Temporarily hide progress popup so confirm dialog is fully visible
const progressOverlay = document.getElementById('progress-overlay');
if (progressOverlay) progressOverlay.style.display = 'none';
const ok = await confirmDialog('Laufende Recherche abbrechen?');
// Restore progress popup if not confirmed
if (!ok) {
const state = UI._progressState[this.currentIncidentId];
if (state && progressOverlay) progressOverlay.style.display = 'flex';
return;
}
// Show cancelling state in popup
if (progressOverlay) progressOverlay.style.display = 'flex';
const btn = document.getElementById('progress-cancel-btn'); const btn = document.getElementById('progress-cancel-btn');
if (btn) { if (btn) {
btn.textContent = 'Wird abgebrochen...'; btn.textContent = 'Wird abgebrochen...';
btn.disabled = true; btn.disabled = true;
} }
const titleEl = document.getElementById('progress-popup-title');
if (titleEl) titleEl.textContent = 'Wird abgebrochen...';
try { try {
await API.cancelRefresh(this.currentIncidentId); const result = await API.cancelRefresh(this.currentIncidentId);
if (!result) {
UI.showToast('Kein aktiver Refresh zum Abbrechen gefunden.', 'info');
if (btn) { btn.textContent = 'Abbrechen'; btn.disabled = false; }
if (titleEl) titleEl.textContent = 'Aktualisierung l\u00e4uft';
}
} catch (err) { } catch (err) {
UI.showToast('Abbrechen fehlgeschlagen: ' + err.message, 'error'); UI.showToast('Abbrechen fehlgeschlagen: ' + err.message, 'error');
if (btn) { if (btn) { btn.textContent = 'Abbrechen'; btn.disabled = false; }
btn.textContent = 'Abbrechen'; if (titleEl) titleEl.textContent = 'Aktualisierung l\u00e4uft';
btn.disabled = false;
}
} }
}, },