diff --git a/templates/index.html b/templates/index.html index 2694bea..06948f4 100644 --- a/templates/index.html +++ b/templates/index.html @@ -101,21 +101,65 @@ a{color:var(--link)} .sidebar.collapsed ~ .main-content .header .header-filter { flex: 1; - max-width: 200px; - margin: 0; + max-width: none; + margin: 0 8px; + min-width: 150px; } .sidebar.collapsed ~ .main-content .header .header-controls { display: flex; align-items: center; gap: 8px; margin-left: auto; } -/* Скрыть тему в компактном header */ -.sidebar.collapsed ~ .main-content .header .theme-toggle { display: none; } +/* Скрыть кнопки loglevels в компактном header */ +.sidebar.collapsed ~ .main-content .header .header-compact-controls { display: none; } -/* Скрыть весь log-header в компактном режиме */ -.sidebar.collapsed ~ .main-content .log-header { display: none; } +/* Скрыть весь log-header */ +.log-header { display: none; } /* Минимальный padding для log-content в свернутом состоянии */ .sidebar.collapsed ~ .main-content .log-content { - padding: 2px; + padding: 0; +} + +/* Обеспечиваем правильное отображение логов при свернутом sidebar */ +.sidebar.collapsed ~ .main-content .log-area { + height: calc(100vh - var(--header-height)) !important; + overflow: hidden !important; +} + +.sidebar.collapsed ~ .main-content .log-content { + overflow: visible !important; + height: 100% !important; + padding: 0 !important; +} + +.sidebar.collapsed ~ .main-content .single-view-content .log, +.sidebar.collapsed ~ .main-content .multi-view-log { + height: calc(100vh - var(--header-height)) !important; + overflow: auto !important; + display: block !important; + max-height: none !important; + min-height: 200px !important; + position: relative !important; +} + +/* Обеспечиваем правильное отображение логов при развернутом sidebar */ +.sidebar:not(.collapsed) ~ .main-content .single-view-content .log, +.sidebar:not(.collapsed) ~ .main-content .multi-view-log { + height: 100% !important; + overflow: auto !important; + display: block !important; + min-height: 200px !important; + position: relative !important; +} + +/* Стили для multi-view-content контейнеров */ +.sidebar.collapsed ~ .main-content .multi-view-content { + height: calc(100vh - var(--header-height) - 60px) !important; + overflow: hidden !important; +} + +.sidebar:not(.collapsed) ~ .main-content .multi-view-content { + height: 100% !important; + overflow: hidden !important; } /* Multi-view panel для Single View режима */ @@ -236,64 +280,12 @@ a{color:var(--link)} .sidebar:not(.collapsed) .help-btn { display: none; } .sidebar.collapsed .help-btn { display: flex; } -/* Компактные контролы в header: по умолчанию скрыты, видны в свернутом режиме */ +/* Компактные контролы в header: по умолчанию скрыты */ .header-compact-controls { display: none; align-items: center; gap: 6px; } -.sidebar.collapsed ~ .main-content .header .header-compact-controls { display: flex; } -/* Стили для компактных кнопок в header - такие же как в развернутом состоянии */ -.sidebar.collapsed ~ .main-content .header .counter-btn { - display: inline-flex; - flex-direction: row; - align-items: center; - justify-content: center; - padding: 6px 12px; - margin: 0 4px; - border: none; - border-radius: 6px; - font-size: 11px; - font-weight: 500; - cursor: pointer; - transition: all 0.2s ease; - min-width: 70px; -} -.sidebar.collapsed ~ .main-content .header .counter-btn:hover { - transform: translateY(-1px); - box-shadow: 0 2px 4px rgba(0,0,0,0.2); -} -.sidebar.collapsed ~ .main-content .header .counter-label { - font-size: 10px; - opacity: 0.9; - margin-right: 4px; -} -.sidebar.collapsed ~ .main-content .header .counter-value { - font-size: 12px; - font-weight: bold; -} - -.sidebar.collapsed ~ .main-content .header .log-refresh-btn { - background: var(--accent); - color: white; - border: none; - border-radius: 6px; - transition: all 0.2s ease; - padding: 6px 24px; - font-size: 11px; - font-weight: 500; - display: inline-flex; - align-items: center; - justify-content: center; - height: fit-content; -} - -.sidebar.collapsed ~ .main-content .header .log-refresh-btn:hover { - background: var(--accent); - opacity: 0.8; - transform: translateY(-1px); - box-shadow: 0 2px 4px rgba(0,0,0,0.2); -} .options-btn:hover, .help-btn:hover, @@ -668,13 +660,13 @@ a{color:var(--link)} } /* Стили для кнопки refresh */ -#logRefreshBtn { +.log-refresh-btn { background: var(--accent); color: white; border: none; border-radius: 6px; transition: all 0.2s ease; - padding: 6px 24px; /* Увеличиваем ширину в 2 раза */ + padding: 6px 24px; font-size: 11px; font-weight: 500; display: inline-flex; @@ -683,7 +675,7 @@ a{color:var(--link)} height: fit-content; } -#logRefreshBtn:hover { +.log-refresh-btn:hover { background: var(--accent); opacity: 0.8; transform: translateY(-1px); @@ -737,48 +729,49 @@ a{color:var(--link)} /* Цвета для разных уровней логов */ .debug-btn { - background: #6c757d; + background: #6c757d; /* Серый */ color: white; } .debug-btn:hover { - background: #5a6268; + background: #5a6268; /* Затемненный серый */ } .info-btn { - background: #17a2b8; + background: var(--ok); /* Зеленый цвет */ color: white; + border: 1px solid var(--ok); } .info-btn:hover { - background: #138496; + background: #7ea855; /* Затемненный зеленый */ } .warn-btn { - background: #ffc107; + background: #ffc107; /* Оставляем текущий цвет */ color: #212529; } .warn-btn:hover { - background: #e0a800; + background: #e0a800; /* Затемненный желтый */ } .error-btn { - background: #dc3545; + background: #dc3545; /* Оставляем текущий цвет */ color: white; } .error-btn:hover { - background: #c82333; + background: #c82333; /* Затемненный красный */ } .other-btn { - background: #6c757d; - color: white; + background: #f8f9fa; /* Самый светлый серый */ + color: #212529; } .other-btn:hover { - background: #5a6268; + background: #dee2e6; /* Затемненный серый */ } .btn-group { @@ -815,6 +808,7 @@ a{color:var(--link)} align-items: center; padding: 0 20px; gap: 16px; + flex-wrap: wrap; } .header-title { @@ -947,7 +941,7 @@ a{color:var(--link)} .header-filter { flex: 1; min-width: 200px; - max-width: 400px; + max-width: none; padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px; @@ -956,6 +950,7 @@ a{color:var(--link)} font-size: 12px; transition: border-color 0.2s ease; margin: 0 16px; + width: 100%; } .header-filter:focus { @@ -967,6 +962,64 @@ a{color:var(--link)} color: var(--muted); } +/* Адаптивность для header-filter */ +@media (max-width: 1200px) { + .header-filter { + min-width: 150px; + margin: 0 12px; + } + + .sidebar.collapsed ~ .main-content .header .header-filter { + min-width: 120px; + margin: 0 6px; + } +} + +@media (max-width: 768px) { + .header-filter { + min-width: 120px; + margin: 0 8px; + padding: 6px 10px; + font-size: 11px; + } + + .header { + gap: 12px; + padding: 0 16px; + } + + .sidebar.collapsed ~ .main-content .header .header-filter { + min-width: 100px; + margin: 0 4px; + padding: 4px 8px; + font-size: 10px; + } +} + +@media (max-width: 480px) { + .header-filter { + min-width: 100px; + margin: 0 4px; + padding: 4px 8px; + font-size: 10px; + } + + .header { + gap: 8px; + padding: 0 12px; + } + + .header-controls { + gap: 8px; + } + + /* Адаптивность для свернутого sidebar */ + .sidebar.collapsed ~ .main-content .header .header-filter { + min-width: 100px; + margin: 0 4px; + } +} + .header-project-select { padding: 6px 12px; border: 1px solid var(--border); @@ -1304,58 +1357,58 @@ a{color:var(--link)} /* Цвета для разных уровней */ .level-btn.debug-btn { - border-color: var(--ok); - color: var(--ok); + border-color: #6c757d; /* Серый */ + color: #6c757d; } .level-btn.debug-btn:hover, .level-btn.debug-btn.active { - background: var(--ok); - color: #0b0d12; + background: #5a6268; /* Затемненный серый */ + color: white; } .level-btn.info-btn { - border-color: var(--accent); - color: var(--accent); + border-color: var(--ok); /* Зеленый цвет */ + color: var(--ok); } .level-btn.info-btn:hover, .level-btn.info-btn.active { - background: var(--accent); - color: #0b0d12; + background: #7ea855; /* Затемненный зеленый */ + color: white; } .level-btn.warn-btn { - border-color: var(--warn); + border-color: var(--warn); /* Оставляем текущий цвет */ color: var(--warn); } .level-btn.warn-btn:hover, .level-btn.warn-btn.active { - background: var(--warn); + background: #e0a800; /* Затемненный желтый */ color: #0b0d12; } .level-btn.error-btn { - border-color: var(--err); + border-color: var(--err); /* Оставляем текущий цвет */ color: var(--err); } .level-btn.error-btn:hover, .level-btn.error-btn.active { - background: var(--err); - color: #0b0d12; + background: #c82333; /* Затемненный красный */ + color: white; } .level-btn.other-btn { - border-color: var(--muted); - color: var(--muted); + border-color: #f8f9fa; /* Самый светлый серый */ + color: #f8f9fa; } .level-btn.other-btn:hover, .level-btn.other-btn.active { - background: var(--muted); - color: #0b0d12; + background: #dee2e6; /* Затемненный серый */ + color: #212529; } .single-view-content { @@ -1426,7 +1479,7 @@ a{color:var(--link)} .log-content { flex: 1; overflow: hidden; - padding: 16px; + padding: 0; background: var(--bg); } @@ -1918,10 +1971,10 @@ footer{position:fixed;right:10px;bottom:10px;opacity:.6;font-size:11px} OTHER 0 - +
Theme @@ -1932,34 +1985,6 @@ footer{position:fixed;right:10px;bottom:10px;opacity:.6;font-size:11px}
-
-

Select a container to view logs

-
- - - - - - -
-
@@ -2051,13 +2076,11 @@ const els = { // New modern elements containerList: document.getElementById('containerList'), - logTitle: document.getElementById('logTitle'), logContent: document.getElementById('logContent'), mobileToggle: document.getElementById('mobileToggle'), optionsBtn: document.getElementById('optionsBtn'), helpBtn: document.getElementById('helpBtn'), logoutBtn: document.getElementById('logoutBtn'), - logRefreshBtn: document.getElementById('logRefreshBtn'), sidebar: document.getElementById('sidebar'), sidebarToggle: document.getElementById('sidebarToggle'), header: document.getElementById('header'), @@ -2400,6 +2423,22 @@ function updateHeaderCounters(containerId, counters) { // Функция для инициализации состояния кнопок уровней логирования function initializeLevelButtons() { + // Восстанавливаем состояние кнопок loglevels из localStorage + const savedLevelsState = getLogLevelsStateFromStorage(); + if (savedLevelsState) { + console.log('Restoring log levels state from localStorage'); + + // Восстанавливаем глобальные настройки для single-view + if (savedLevelsState.globalLevels) { + state.levels = { ...state.levels, ...savedLevelsState.globalLevels }; + } + + // Восстанавливаем настройки контейнеров для multi-view + if (savedLevelsState.containerLevels) { + state.containerLevels = { ...state.containerLevels, ...savedLevelsState.containerLevels }; + } + } + // Инициализируем кнопки для single-view const singleLevelBtns = document.querySelectorAll('.single-view-levels .level-btn'); singleLevelBtns.forEach(btn => { @@ -2430,6 +2469,12 @@ function initializeLevelButtons() { btn.classList.toggle('active', isActive); btn.classList.toggle('disabled', !isActive); }); + + // Обновляем стили логов после инициализации кнопок + updateLogStyles(); + + // Применяем настройки wrap text + applyWrapSettings(); } function applyFilter(line){ if(!state.filter) return true; @@ -2925,9 +2970,6 @@ function updateContainerSelectionUI() { } }); - // Обновляем заголовок - updateLogTitle(); - // Обновляем single-view-title если он существует const singleViewTitle = document.getElementById('singleViewTitle'); if (singleViewTitle && state.selectedContainers.length === 1) { @@ -2973,6 +3015,58 @@ function getSelectedContainerFromStorage() { return containerId; } +// Функция для сохранения режима просмотра в localStorage +function saveViewMode(multiViewMode, selectedContainers) { + const viewModeData = { + multiViewMode: multiViewMode, + selectedContainers: selectedContainers || [] + }; + localStorage.setItem('lb_view_mode', JSON.stringify(viewModeData)); + console.log('Saved view mode to localStorage:', viewModeData); +} + +// Функция для восстановления режима просмотра из localStorage +function getViewModeFromStorage() { + const viewModeData = localStorage.getItem('lb_view_mode'); + if (viewModeData) { + try { + const data = JSON.parse(viewModeData); + console.log('Retrieved view mode from localStorage:', data); + return data; + } catch (error) { + console.error('Error parsing view mode from localStorage:', error); + return null; + } + } + return null; +} + +// Функция для сохранения состояния кнопок loglevels в localStorage +function saveLogLevelsState() { + const levelsData = { + globalLevels: state.levels, + containerLevels: state.containerLevels + }; + localStorage.setItem('lb_log_levels', JSON.stringify(levelsData)); + console.log('Saved log levels state to localStorage:', levelsData); +} + +// Функция для восстановления состояния кнопок loglevels из localStorage +function getLogLevelsStateFromStorage() { + const levelsData = localStorage.getItem('lb_log_levels'); + if (levelsData) { + try { + const data = JSON.parse(levelsData); + console.log('Retrieved log levels state from localStorage:', data); + return data; + } catch (error) { + console.error('Error parsing log levels state from localStorage:', error); + return null; + } + } + return null; +} + async function updateMultiViewMode() { console.log(`updateMultiViewMode called: selectedContainers.length = ${state.selectedContainers.length}, containers:`, state.selectedContainers); @@ -2980,6 +3074,10 @@ async function updateMultiViewMode() { state.multiViewMode = true; state.current = null; // Сбрасываем текущий контейнер console.log('Setting up multi-view mode'); + + // Сохраняем режим просмотра в localStorage + saveViewMode(true, state.selectedContainers); + await setupMultiView(); } else if (state.selectedContainers.length === 1) { // Переключаемся в single view для одного контейнера @@ -2990,6 +3088,9 @@ async function updateMultiViewMode() { console.log('Switching to single view for:', selectedService.name); console.log('updateMultiViewMode: About to call switchToSingle - VERSION 2'); + // Сохраняем режим просмотра в localStorage + saveViewMode(false, [selectedService.id]); + // Сохраняем выбранный контейнер в localStorage saveSelectedContainer(selectedService.id); @@ -3002,6 +3103,10 @@ async function updateMultiViewMode() { // Когда снимаем все галочки, переключаемся в single view state.multiViewMode = false; state.current = null; + + // Сохраняем режим просмотра в localStorage + saveViewMode(false, []); + clearLogArea(); // Очищаем область логов и показываем пустое состояние @@ -3013,14 +3118,14 @@ async function updateMultiViewMode() { } } - // Обновляем заголовок - if (els.logTitle) { - els.logTitle.textContent = 'LogBoard+'; - } + } console.log(`Multi-view mode updated: multiViewMode = ${state.multiViewMode}`); + // Сохраняем состояние кнопок loglevels при переключении режимов + saveLogLevelsState(); + // Обновляем состояние кнопок уровней логирования при переключении режимов setTimeout(() => { initializeLevelButtons(); @@ -3140,6 +3245,11 @@ async function setupMultiView() { setTimeout(() => { recalculateMultiViewCounters(); }, 1000); // Небольшая задержка для завершения загрузки логов + + // Применяем стили логов после настройки multi view + setTimeout(() => { + updateLogStyles(); + }, 1500); // Задержка после настройки счетчиков } function createMultiViewPanel(service) { @@ -3217,6 +3327,12 @@ function createMultiViewPanel(service) { }, 100); console.log(`Multi-view panel created for ${service.name}`); + + // Применяем стили к новой панели + setTimeout(() => { + updateLogStyles(); + }, 200); + return panel; } @@ -3355,46 +3471,7 @@ function clearLogArea() { } } -function updateLogTitle() { - const logTitle = document.getElementById('logTitle'); - const multiViewPanelTitle = document.getElementById('multiViewPanelTitle'); - const singleViewTitle = document.getElementById('singleViewTitle'); - if (!logTitle) return; - - console.log('updateLogTitle called, selected containers:', state.selectedContainers.length); - - if (state.selectedContainers.length === 0) { - logTitle.textContent = 'LogBoard+'; - if (multiViewPanelTitle) { - multiViewPanelTitle.textContent = 'LogBoard+'; - } - if (singleViewTitle) { - singleViewTitle.textContent = 'No container selected'; - } - console.log('Log title set to: LogBoard+'); - } else if (state.selectedContainers.length === 1) { - const service = state.services.find(s => s.id === state.selectedContainers[0]); - if (service) { - logTitle.textContent = `${service.name} (${service.service || service.name})`; - if (multiViewPanelTitle) { - multiViewPanelTitle.textContent = `${service.name} (${service.service || service.name})`; - } - if (singleViewTitle) { - singleViewTitle.textContent = `${service.name} (${service.service || service.name})`; - } - console.log('Log title set to single container:', service.name); - } - } else { - logTitle.textContent = `Multi-view: ${state.selectedContainers.length} containers`; - if (multiViewPanelTitle) { - multiViewPanelTitle.textContent = `Multi-view: ${state.selectedContainers.length} containers`; - } - if (singleViewTitle) { - singleViewTitle.textContent = `Multi-view: ${state.selectedContainers.length} containers`; - } - console.log('Log title set to multi-view:', state.selectedContainers.length, 'containers'); - } -} + function applyWrapSettings() { const wrapEnabled = els.wrapToggle && els.wrapToggle.checked; @@ -3455,13 +3532,52 @@ async function fetchServices(){ buildTabs(); - // Проверяем, находимся ли мы в 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]); + // Восстанавливаем режим просмотра из localStorage + const savedViewMode = getViewModeFromStorage(); + if (savedViewMode) { + console.log('Restoring view mode from localStorage:', savedViewMode); + + if (savedViewMode.multiViewMode && savedViewMode.selectedContainers.length > 1) { + // Восстанавливаем Multi View режим + console.log('Restoring Multi View mode with containers:', savedViewMode.selectedContainers); + state.multiViewMode = true; + state.selectedContainers = savedViewMode.selectedContainers; + + // Отмечаем чекбоксы для выбранных контейнеров + savedViewMode.selectedContainers.forEach(containerId => { + const checkbox = document.querySelector(`.container-checkbox[data-container-id="${containerId}"]`); + if (checkbox) { + checkbox.checked = true; + const containerItem = checkbox.closest('.container-item'); + if (containerItem) { + containerItem.classList.add('selected'); + } + } + }); + + // Настраиваем Multi View + await setupMultiView(); + } else if (savedViewMode.selectedContainers.length === 1) { + // Восстанавливаем Single View режим + console.log('Restoring Single View mode for container:', savedViewMode.selectedContainers[0]); + state.multiViewMode = false; + const selectedService = state.services.find(s => s.id === savedViewMode.selectedContainers[0]); + if (selectedService) { + await switchToSingle(selectedService); + } + } else { + // Нет сохраненного режима, используем первый контейнер + console.log('No saved view mode, using first container'); + if (state.services.length) { + await switchToSingle(state.services[0]); + } + } + } else { + // Нет сохраненного режима, используем первый контейнер + console.log('No saved view mode found, using first container'); + if (state.services.length) { + await switchToSingle(state.services[0]); + } } // Добавляем обработчики для счетчиков после загрузки сервисов @@ -4628,10 +4744,13 @@ async function switchToSingle(svc){ // Обновляем состояние выбранных контейнеров для корректного отображения заголовка state.selectedContainers = [svc.id]; - // Modern interface updates - if (els.logTitle) { - els.logTitle.textContent = `${svc.name} (${svc.service || svc.name})`; - } + // Сохраняем режим просмотра в localStorage + saveViewMode(false, [svc.id]); + + // Сохраняем состояние кнопок loglevels в localStorage + saveLogLevelsState(); + + if (els.multiViewPanelTitle) { els.multiViewPanelTitle.textContent = `${svc.name} (${svc.service || svc.name})`; } @@ -4681,9 +4800,6 @@ async function switchToSingle(svc){ // Обновляем состояние чекбоксов после переключения контейнера updateContainerSelectionUI(); - // Обновляем заголовок - updateLogTitle(); - // Обновляем счетчики для нового контейнера setTimeout(() => { recalculateCounters(); @@ -5220,7 +5336,7 @@ els.refreshBtn.onclick = async () => { }; // Обработчик для кнопок refresh логов (в log-header и в header) -document.querySelectorAll('#logRefreshBtn, .header-compact-controls .log-refresh-btn').forEach(btn=>{ + document.querySelectorAll('.log-refresh-btn').forEach(btn=>{ btn.addEventListener('click', refreshLogsAndCounters); }); @@ -5417,6 +5533,104 @@ function toggleSidebar() { els.sidebarToggle.title = 'Развернуть панель (Ctrl+B / Ctrl+И)'; localStorage.setItem('lb_sidebar_collapsed', 'true'); } + + // Принудительно обновляем стили логов после переключения sidebar + setTimeout(() => { + updateLogStyles(); + }, 100); + } +} + +// Функция для обновления стилей логов +function updateLogStyles() { + const isCollapsed = els.sidebar && els.sidebar.classList.contains('collapsed'); + + // Обновляем стили для single-view логов + const singleViewLogs = document.querySelectorAll('.single-view-content .log'); + singleViewLogs.forEach(log => { + if (isCollapsed) { + log.style.height = 'calc(100vh - var(--header-height))'; + log.style.overflow = 'auto'; + } else { + log.style.height = '100%'; + log.style.overflow = 'auto'; + } + }); + + // Обновляем стили для multi-view логов (более агрессивно) + const multiViewLogs = document.querySelectorAll('.multi-view-log'); + console.log(`Found ${multiViewLogs.length} multi-view logs to update`); + + multiViewLogs.forEach((log, index) => { + const containerId = log.getAttribute('data-container-id'); + console.log(`Updating multi-view log ${index + 1}/${multiViewLogs.length} for container: ${containerId}`); + + if (isCollapsed) { + log.style.height = 'calc(100vh - var(--header-height))'; + log.style.overflow = 'auto'; + log.style.maxHeight = 'none'; + log.style.display = 'block'; + log.style.minHeight = '200px'; + log.style.position = 'relative'; + } else { + log.style.height = '100%'; + log.style.overflow = 'auto'; + log.style.maxHeight = 'none'; + log.style.display = 'block'; + log.style.minHeight = '200px'; + log.style.position = 'relative'; + } + + // Принудительно вызываем пересчет layout + log.style.transform = 'translateZ(0)'; + }); + + // Также обновляем стили для multi-view-content контейнеров + const multiViewContents = document.querySelectorAll('.multi-view-content'); + multiViewContents.forEach(content => { + if (isCollapsed) { + content.style.height = 'calc(100vh - var(--header-height) - 60px)'; + content.style.overflow = 'hidden'; + } else { + content.style.height = '100%'; + content.style.overflow = 'hidden'; + } + }); + + // Применяем настройки wrap text + applyWrapSettings(); + + console.log('Log styles updated, sidebar collapsed:', isCollapsed, 'multi-view logs found:', multiViewLogs.length); + + // Дополнительная проверка через 500ms для multi view логов + if (multiViewLogs.length > 0) { + setTimeout(() => { + console.log('Performing delayed update for multi-view logs...'); + const delayedLogs = document.querySelectorAll('.multi-view-log'); + delayedLogs.forEach((log, index) => { + const containerId = log.getAttribute('data-container-id'); + console.log(`Delayed update for multi-view log ${index + 1}/${delayedLogs.length} for container: ${containerId}`); + + if (isCollapsed) { + log.style.height = 'calc(100vh - var(--header-height))'; + log.style.overflow = 'auto'; + log.style.maxHeight = 'none'; + log.style.display = 'block'; + log.style.minHeight = '200px'; + log.style.position = 'relative'; + } else { + log.style.height = '100%'; + log.style.overflow = 'auto'; + log.style.maxHeight = 'none'; + log.style.display = 'block'; + log.style.minHeight = '200px'; + log.style.position = 'relative'; + } + + // Принудительно вызываем пересчет layout + log.style.transform = 'translateZ(0)'; + }); + }, 500); } } @@ -5593,6 +5807,11 @@ document.addEventListener('DOMContentLoaded', () => { }); } + // Инициализируем стили логов при загрузке страницы + updateLogStyles(); + + // Применяем настройки wrap text при загрузке + applyWrapSettings(); }); if (els.snapshotBtn) { @@ -5873,7 +6092,7 @@ window.addEventListener('keydown', async (e)=>{ console.log('Elements found:', { containerList: !!els.containerList, - logTitle: !!els.logTitle, + logContent: !!els.logContent, mobileToggle: !!els.mobileToggle, themeSwitch: !!els.themeSwitch @@ -6061,6 +6280,9 @@ window.addEventListener('keydown', async (e)=>{ } state.containerLevels[containerId][level] = !isActive; + // Сохраняем состояние кнопок loglevels в localStorage + saveLogLevelsState(); + // Обновляем видимость логов только для этого контейнера updateContainerLogVisibility(containerId); @@ -6080,6 +6302,9 @@ window.addEventListener('keydown', async (e)=>{ // Для single-view: глобальные настройки state.levels[level] = !isActive; + // Сохраняем состояние кнопок loglevels в localStorage + saveLogLevelsState(); + // Обновляем видимость логов только для текущего контейнера if (state.current) { updateLogVisibility(els.logContent);