diff --git a/templates/index.html b/templates/index.html index 918d2ee..edc3fad 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2464,7 +2464,15 @@ async function fetchServices(){ state.services = data; buildTabs(); - if (!state.current && state.services.length) await switchToSingle(state.services[0]); + + // Проверяем, находимся ли мы в Multi View режиме + if (state.multiViewMode && state.selectedContainers.length > 0) { + // В Multi View режиме не переключаемся в single view + console.log('fetchServices: Staying in Multi View mode'); + } else if (!state.current && state.services.length) { + // Только если не в Multi View режиме и нет текущего контейнера + await switchToSingle(state.services[0]); + } // Добавляем обработчики для счетчиков после загрузки сервисов addCounterClickHandlers(); @@ -2498,21 +2506,6 @@ async function sendSnapshot(id){ const o = state.open[id]; if (!o){ alert('not open'); return; } - // Получаем текст логов из современного интерфейса или из legacy - let text = ''; - if (state.current && state.current.id === id && els.logContent) { - text = els.logContent.textContent; - } else if (o.logEl) { - text = o.logEl.textContent; - } - - if (!text || text.trim() === '') { - alert('No logs to save'); - return; - } - - console.log('Saving snapshot with content length:', text.length); - const token = localStorage.getItem('access_token'); if (!token) { console.error('No access token found'); @@ -2520,28 +2513,108 @@ async function sendSnapshot(id){ return; } - const payload = {container_id: id, service: o.serviceName || id, content: text}; - const res = await fetch('/api/snapshot', { - method:'POST', - headers:{ - 'Content-Type':'application/json', - 'Authorization': `Bearer ${token}` - }, - body: JSON.stringify(payload) - }); - if (!res.ok){ - if (res.status === 401) { - console.error('Unauthorized, redirecting to login'); - window.location.href = '/login'; + if (state.multiViewMode && state.selectedContainers.length > 0) { + // В Multi View режиме создаем отдельный файл для каждого контейнера + console.log('Creating snapshots for Multi View mode with containers:', state.selectedContainers); + + let hasLogs = false; + + // Создаем отдельный файл для каждого выбранного контейнера + for (const containerId of state.selectedContainers) { + const multiViewLog = document.querySelector(`.multi-view-log[data-container-id="${containerId}"]`); + if (multiViewLog && multiViewLog.textContent.trim()) { + const service = state.services.find(s => s.id === containerId); + const serviceName = service ? (service.service || service.name) : containerId; + const text = multiViewLog.textContent; + + console.log(`Saving snapshot for ${serviceName} with content length:`, text.length); + + const payload = {container_id: containerId, service: serviceName, content: text}; + + try { + const res = await fetch('/api/snapshot', { + method:'POST', + headers:{ + 'Content-Type':'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify(payload) + }); + + if (!res.ok){ + if (res.status === 401) { + console.error('Unauthorized, redirecting to login'); + window.location.href = '/login'; + return; + } + console.error(`Snapshot failed for ${serviceName}:`, res.status, res.statusText); + alert(`snapshot failed for ${serviceName}`); + return; + } + + const js = await res.json(); + const a = document.createElement('a'); + a.href = js.url; a.download = js.file; a.click(); + + hasLogs = true; + + // Небольшая задержка между скачиваниями файлов + await new Promise(resolve => setTimeout(resolve, 100)); + + } catch (error) { + console.error(`Error saving snapshot for ${serviceName}:`, error); + alert(`Error saving snapshot for ${serviceName}`); + return; + } + } + } + + if (!hasLogs) { + alert('No logs to save in Multi View mode'); return; } - console.error('Snapshot failed:', res.status, res.statusText); - alert('snapshot failed'); - return; + + } else { + // Обычный режим просмотра + let text = ''; + if (state.current && state.current.id === id && els.logContent) { + text = els.logContent.textContent; + } else if (o.logEl) { + text = o.logEl.textContent; + } + + if (!text || text.trim() === '') { + alert('No logs to save'); + return; + } + + console.log('Saving snapshot with content length:', text.length); + + const serviceName = o.serviceName || id; + const payload = {container_id: id, service: serviceName, content: text}; + + const res = await fetch('/api/snapshot', { + method:'POST', + headers:{ + 'Content-Type':'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify(payload) + }); + if (!res.ok){ + if (res.status === 401) { + console.error('Unauthorized, redirecting to login'); + window.location.href = '/login'; + return; + } + console.error('Snapshot failed:', res.status, res.statusText); + alert('snapshot failed'); + return; + } + const js = await res.json(); + const a = document.createElement('a'); + a.href = js.url; a.download = js.file; a.click(); } - const js = await res.json(); - const a = document.createElement('a'); - a.href = js.url; a.download = js.file; a.click(); } function openWs(svc, panel){ @@ -3926,8 +3999,18 @@ async function refreshLogsAndCounters() { // Обновляем мультипросмотр console.log('Refreshing multi-view for containers:', state.selectedContainers); - // Пересчитываем счетчики на основе отображаемых логов - recalculateMultiViewCounters(); + // Очищаем логи в мультипросмотре перед обновлением + state.selectedContainers.forEach(containerId => { + const multiViewLog = document.querySelector(`.multi-view-log[data-container-id="${containerId}"]`); + if (multiViewLog) { + multiViewLog.textContent = 'Refreshing...'; + } + // Очищаем буфер логов для мультипросмотра + const obj = state.open[containerId]; + if (obj && obj.allLogs) { + obj.allLogs = []; + } + }); // Перезапускаем WebSocket соединения для всех выбранных контейнеров state.selectedContainers.forEach(containerId => { @@ -3938,20 +4021,19 @@ async function refreshLogsAndCounters() { } }); - // Очищаем логи в мультипросмотре - state.selectedContainers.forEach(containerId => { - const multiViewLog = document.querySelector(`.multi-view-log[data-container-id="${containerId}"]`); - if (multiViewLog) { - multiViewLog.textContent = 'Refreshing...'; - } - }); + // Пересчитываем счетчики на основе отображаемых логов + setTimeout(() => { + recalculateMultiViewCounters(); + }, 1000); // Небольшая задержка для завершения переподключения } else if (state.current) { // Обычный режим просмотра console.log('Refreshing logs and counters for:', state.current.id); - // Пересчитываем счетчики на основе отображаемых логов - recalculateCounters(); + // Очищаем логи перед обновлением + if (els.logContent) { + els.logContent.textContent = 'Refreshing...'; + } // Перезапускаем WebSocket соединение для получения свежих логов const currentId = state.current.id; @@ -3969,6 +4051,12 @@ async function refreshLogsAndCounters() { cleanDuplicateLines(els.logContent); } } + + // Пересчитываем счетчики на основе отображаемых логов + setTimeout(() => { + recalculateCounters(); + }, 1000); // Небольшая задержка для завершения переподключения + } else { console.log('No container selected'); } @@ -4022,8 +4110,33 @@ els.refreshBtn.onclick = async () => { console.log('Refreshing services...'); await fetchServices(); - // Если есть текущий контейнер, перезапускаем его WebSocket соединение - if (state.current) { + if (state.multiViewMode && state.selectedContainers.length > 0) { + // В Multi View режиме обновляем все выбранные контейнеры + console.log('Refreshing Multi View mode with containers:', state.selectedContainers); + + // Закрываем все текущие соединения + state.selectedContainers.forEach(containerId => { + closeWs(containerId); + }); + + // Перезапускаем соединения для всех выбранных контейнеров + state.selectedContainers.forEach(containerId => { + const service = state.services.find(s => s.id === containerId); + if (service) { + openMultiViewWs(service); + } + }); + + // Очищаем логи в мультипросмотре + state.selectedContainers.forEach(containerId => { + const multiViewLog = document.querySelector(`.multi-view-log[data-container-id="${containerId}"]`); + if (multiViewLog) { + multiViewLog.textContent = 'Refreshing...'; + } + }); + + } else if (state.current) { + // Обычный режим просмотра console.log('Reconnecting to current container:', state.current.id); const currentId = state.current.id; @@ -4339,7 +4452,11 @@ document.addEventListener('DOMContentLoaded', () => { }); if (els.snapshotBtn) { els.snapshotBtn.onclick = ()=>{ - if (state.current) { + if (state.multiViewMode && state.selectedContainers.length > 0) { + // В Multi View режиме используем первый выбранный контейнер как ID для sendSnapshot + // Функция sendSnapshot сама определит, что нужно скачать логи всех контейнеров + sendSnapshot(state.selectedContainers[0]); + } else if (state.current) { sendSnapshot(state.current.id); } else { alert('No container selected');