Fortschritt: Auto-Minimize, Action-Lock, Queue-Anzeige in Sidebar
1. Aktualisierungen starten minimiert (Mini-Bar), Popup nur per Klick. Verhindert Ueberlagerung von Bearbeiten/Export-Buttons. 2. Erster Durchlauf: Bearbeiten/Export/Archivieren/Loeschen gesperrt, nur Abbrechen moeglich. 3. Sidebar: Warteschlange-Lagen zeigen Position (#1, #2...) mit eigenem visuellen Stil (gedimmt, pulsierender Dot). 4. Sidebar-Status (Recherchiert/Analysiert/Faktencheck) wird fuer ALLE laufenden Lagen angezeigt, nicht nur die aktuelle. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -2071,6 +2071,41 @@ a:hover {
|
|||||||
transition: filter 0.4s ease;
|
transition: filter 0.4s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Disabled Actions During First Refresh === */
|
||||||
|
.incident-header-actions.first-refresh-locked .btn:not(#refresh-btn) {
|
||||||
|
opacity: 0.3;
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
.incident-header-actions.first-refresh-locked #refresh-btn {
|
||||||
|
opacity: 0.3;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === Sidebar Queue Position Badge === */
|
||||||
|
.incident-queue-badge {
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--bg-primary);
|
||||||
|
background: var(--text-disabled);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 1px 5px;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
white-space: nowrap;
|
||||||
|
animation: fadeIn 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incident-item.queued-item {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
.incident-item.queued-item .incident-dot {
|
||||||
|
background: var(--text-disabled);
|
||||||
|
animation: pulse 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
.incident-refresh-status.queued-status {
|
||||||
|
color: var(--text-disabled);
|
||||||
|
}
|
||||||
|
|
||||||
/* === Sidebar Refreshing Indicator === */
|
/* === Sidebar Refreshing Indicator === */
|
||||||
.incident-item.refreshing-item {
|
.incident-item.refreshing-item {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
|
|||||||
@@ -577,7 +577,10 @@ const App = {
|
|||||||
if (data.refreshing && data.refreshing.length > 0) {
|
if (data.refreshing && data.refreshing.length > 0) {
|
||||||
data.refreshing.forEach(id => this._refreshingIncidents.add(id));
|
data.refreshing.forEach(id => this._refreshingIncidents.add(id));
|
||||||
// Sidebar-Dots aktualisieren
|
// Sidebar-Dots aktualisieren
|
||||||
data.refreshing.forEach(id => this._updateSidebarDot(id));
|
data.refreshing.forEach(id => {
|
||||||
|
this._updateSidebarDot(id);
|
||||||
|
UI._updateSidebarRefreshStatus(id, 'researching', {});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) { /* Kein kritischer Fehler */ }
|
} catch (e) { /* Kein kritischer Fehler */ }
|
||||||
|
|
||||||
@@ -711,6 +714,9 @@ const App = {
|
|||||||
const step = state ? state.step : 'researching';
|
const step = state ? state.step : 'researching';
|
||||||
const isFirst = state ? state.isFirst : false;
|
const isFirst = state ? state.isFirst : false;
|
||||||
UI.showProgress(step, {}, id, isFirst);
|
UI.showProgress(step, {}, id, isFirst);
|
||||||
|
} else {
|
||||||
|
// Ensure actions are unlocked when viewing non-refreshing incident
|
||||||
|
UI._lockActionsIfFirst(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alte Inhalte sofort leeren um Flackern beim Wechsel zu vermeiden
|
// Alte Inhalte sofort leeren um Flackern beim Wechsel zu vermeiden
|
||||||
@@ -2035,8 +2041,10 @@ async handleRefresh() {
|
|||||||
// Detect first refresh: no summary means first run
|
// Detect first refresh: no summary means first run
|
||||||
const inc = this.incidents.find(i => i.id === msg.incident_id);
|
const inc = this.incidents.find(i => i.id === msg.incident_id);
|
||||||
const isFirst = inc && !inc.summary;
|
const isFirst = inc && !inc.summary;
|
||||||
UI.showProgress(status, msg.data, msg.incident_id, isFirst);
|
// Always update sidebar status (visible for all incidents)
|
||||||
|
UI._updateSidebarRefreshStatus(msg.incident_id, status, msg.data);
|
||||||
if (msg.incident_id === this.currentIncidentId) {
|
if (msg.incident_id === this.currentIncidentId) {
|
||||||
|
UI.showProgress(status, msg.data, msg.incident_id, isFirst);
|
||||||
this._updateRefreshButton(status !== 'idle');
|
this._updateRefreshButton(status !== 'idle');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -285,6 +285,11 @@ const UI = {
|
|||||||
// Update sidebar status text
|
// Update sidebar status text
|
||||||
this._updateSidebarRefreshStatus(incidentId, status, extra);
|
this._updateSidebarRefreshStatus(incidentId, status, extra);
|
||||||
|
|
||||||
|
// For updates (not first refresh): default to minimized to avoid overlaying buttons
|
||||||
|
if (!state.isFirst && !state._userOpenedPopup) {
|
||||||
|
state.minimized = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (state.minimized) {
|
if (state.minimized) {
|
||||||
this._showMiniProgress(status, state);
|
this._showMiniProgress(status, state);
|
||||||
return;
|
return;
|
||||||
@@ -373,6 +378,19 @@ const UI = {
|
|||||||
// Hide mini bar
|
// Hide mini bar
|
||||||
const mini = document.getElementById('progress-mini');
|
const mini = document.getElementById('progress-mini');
|
||||||
if (mini) mini.style.display = 'none';
|
if (mini) mini.style.display = 'none';
|
||||||
|
|
||||||
|
// Lock action buttons during first refresh
|
||||||
|
this._lockActionsIfFirst(state.isFirst);
|
||||||
|
},
|
||||||
|
|
||||||
|
_lockActionsIfFirst(isFirst) {
|
||||||
|
const actions = document.querySelector('.incident-header-actions');
|
||||||
|
if (!actions) return;
|
||||||
|
if (isFirst) {
|
||||||
|
actions.classList.add('first-refresh-locked');
|
||||||
|
} else {
|
||||||
|
actions.classList.remove('first-refresh-locked');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_showMiniProgress(status, state) {
|
_showMiniProgress(status, state) {
|
||||||
@@ -393,6 +411,7 @@ const UI = {
|
|||||||
const state = this._progressState[incidentId];
|
const state = this._progressState[incidentId];
|
||||||
if (!state) return;
|
if (!state) return;
|
||||||
state.minimized = true;
|
state.minimized = true;
|
||||||
|
state._userOpenedPopup = false;
|
||||||
this._showMiniProgress(state.step, state);
|
this._showMiniProgress(state.step, state);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -401,6 +420,7 @@ const UI = {
|
|||||||
const state = this._progressState[incidentId];
|
const state = this._progressState[incidentId];
|
||||||
if (!state) return;
|
if (!state) return;
|
||||||
state.minimized = false;
|
state.minimized = false;
|
||||||
|
state._userOpenedPopup = true;
|
||||||
this._showPopupProgress(state.step, {}, state);
|
this._showPopupProgress(state.step, {}, state);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -523,6 +543,9 @@ const UI = {
|
|||||||
if (mini) mini.style.display = 'none';
|
if (mini) mini.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unlock action buttons
|
||||||
|
this._lockActionsIfFirst(false);
|
||||||
|
|
||||||
// Remove sidebar status
|
// Remove sidebar status
|
||||||
this._removeSidebarRefreshStatus(incidentId);
|
this._removeSidebarRefreshStatus(incidentId);
|
||||||
|
|
||||||
@@ -564,8 +587,11 @@ const UI = {
|
|||||||
const item = document.querySelector('.incident-item[data-id="' + incidentId + '"]');
|
const item = document.querySelector('.incident-item[data-id="' + incidentId + '"]');
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
// Add refreshing class for animated border
|
const isQueued = (status === 'queued');
|
||||||
item.classList.add('refreshing-item');
|
|
||||||
|
// Add appropriate class
|
||||||
|
item.classList.remove('refreshing-item', 'queued-item');
|
||||||
|
item.classList.add(isQueued ? 'queued-item' : 'refreshing-item');
|
||||||
|
|
||||||
// Add or update status text below meta
|
// Add or update status text below meta
|
||||||
let statusEl = document.getElementById('sidebar-refresh-' + incidentId);
|
let statusEl = document.getElementById('sidebar-refresh-' + incidentId);
|
||||||
@@ -574,18 +600,25 @@ const UI = {
|
|||||||
if (!textCol) return;
|
if (!textCol) return;
|
||||||
statusEl = document.createElement('div');
|
statusEl = document.createElement('div');
|
||||||
statusEl.id = 'sidebar-refresh-' + incidentId;
|
statusEl.id = 'sidebar-refresh-' + incidentId;
|
||||||
statusEl.className = 'incident-refresh-status';
|
|
||||||
textCol.appendChild(statusEl);
|
textCol.appendChild(statusEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isQueued) {
|
||||||
|
const pos = (extra && extra.queue_position) ? extra.queue_position : '';
|
||||||
|
statusEl.className = 'incident-refresh-status queued-status';
|
||||||
|
statusEl.innerHTML = '<span>Warteschlange' + (pos ? ' (#' + pos + ')' : '') + '</span>';
|
||||||
|
} else {
|
||||||
|
statusEl.className = 'incident-refresh-status';
|
||||||
const label = this._getStepLabel(status);
|
const label = this._getStepLabel(status);
|
||||||
statusEl.innerHTML = '<span class="mini-spinner"></span><span>' + label + '</span><span id="sidebar-refresh-timer-' + incidentId + '" style="margin-left:auto;font-family:var(--font-mono,monospace);font-size:10px;color:var(--text-disabled);"></span>';
|
statusEl.innerHTML = '<span class="mini-spinner"></span><span>' + label + '</span><span id="sidebar-refresh-timer-' + incidentId + '" style="margin-left:auto;font-family:var(--font-mono,monospace);font-size:10px;color:var(--text-disabled);"></span>';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_removeSidebarRefreshStatus(incidentId) {
|
_removeSidebarRefreshStatus(incidentId) {
|
||||||
const statusEl = document.getElementById('sidebar-refresh-' + incidentId);
|
const statusEl = document.getElementById('sidebar-refresh-' + incidentId);
|
||||||
if (statusEl) statusEl.remove();
|
if (statusEl) statusEl.remove();
|
||||||
const item = document.querySelector('.incident-item[data-id="' + incidentId + '"]');
|
const item = document.querySelector('.incident-item[data-id="' + incidentId + '"]');
|
||||||
if (item) item.classList.remove('refreshing-item');
|
if (item) item.classList.remove('refreshing-item', 'queued-item');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren