diff --git a/src/static/css/style.css b/src/static/css/style.css index 60db7d7..1236995 100644 --- a/src/static/css/style.css +++ b/src/static/css/style.css @@ -2071,6 +2071,41 @@ a:hover { 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 === */ .incident-item.refreshing-item { border: 1px solid transparent; diff --git a/src/static/js/app.js b/src/static/js/app.js index 601880c..277f3de 100644 --- a/src/static/js/app.js +++ b/src/static/js/app.js @@ -577,7 +577,10 @@ const App = { if (data.refreshing && data.refreshing.length > 0) { data.refreshing.forEach(id => this._refreshingIncidents.add(id)); // 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 */ } @@ -711,6 +714,9 @@ const App = { const step = state ? state.step : 'researching'; const isFirst = state ? state.isFirst : false; 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 @@ -2035,8 +2041,10 @@ async handleRefresh() { // Detect first refresh: no summary means first run const inc = this.incidents.find(i => i.id === msg.incident_id); 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) { + UI.showProgress(status, msg.data, msg.incident_id, isFirst); this._updateRefreshButton(status !== 'idle'); } }, diff --git a/src/static/js/components.js b/src/static/js/components.js index 3e477fd..b5347ec 100644 --- a/src/static/js/components.js +++ b/src/static/js/components.js @@ -285,6 +285,11 @@ const UI = { // Update sidebar status text 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) { this._showMiniProgress(status, state); return; @@ -373,6 +378,19 @@ const UI = { // Hide mini bar const mini = document.getElementById('progress-mini'); 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) { @@ -393,6 +411,7 @@ const UI = { const state = this._progressState[incidentId]; if (!state) return; state.minimized = true; + state._userOpenedPopup = false; this._showMiniProgress(state.step, state); }, @@ -401,6 +420,7 @@ const UI = { const state = this._progressState[incidentId]; if (!state) return; state.minimized = false; + state._userOpenedPopup = true; this._showPopupProgress(state.step, {}, state); }, @@ -523,6 +543,9 @@ const UI = { if (mini) mini.style.display = 'none'; } + // Unlock action buttons + this._lockActionsIfFirst(false); + // Remove sidebar status this._removeSidebarRefreshStatus(incidentId); @@ -564,8 +587,11 @@ const UI = { const item = document.querySelector('.incident-item[data-id="' + incidentId + '"]'); if (!item) return; - // Add refreshing class for animated border - item.classList.add('refreshing-item'); + const isQueued = (status === 'queued'); + + // 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 let statusEl = document.getElementById('sidebar-refresh-' + incidentId); @@ -574,18 +600,25 @@ const UI = { if (!textCol) return; statusEl = document.createElement('div'); statusEl.id = 'sidebar-refresh-' + incidentId; - statusEl.className = 'incident-refresh-status'; textCol.appendChild(statusEl); } - const label = this._getStepLabel(status); - statusEl.innerHTML = '' + label + ''; + + if (isQueued) { + const pos = (extra && extra.queue_position) ? extra.queue_position : ''; + statusEl.className = 'incident-refresh-status queued-status'; + statusEl.innerHTML = 'Warteschlange' + (pos ? ' (#' + pos + ')' : '') + ''; + } else { + statusEl.className = 'incident-refresh-status'; + const label = this._getStepLabel(status); + statusEl.innerHTML = '' + label + ''; + } }, _removeSidebarRefreshStatus(incidentId) { const statusEl = document.getElementById('sidebar-refresh-' + incidentId); if (statusEl) statusEl.remove(); 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'); },