Боковая панель в данных для журнала

This commit is contained in:
Maxim
2026-06-18 15:24:24 +03:00
parent 6f7617b174
commit 7fc5b79bf5
3 changed files with 101 additions and 14 deletions

View File

@@ -618,3 +618,32 @@
@keyframes spin {
to { transform: rotate(360deg); }
}
/* ===== БОКОВАЯ ПАНЕЛЬ ===== */
.logs-sidebar {
flex: 0 0 280px;
border-right: 1px solid #00ff88;
padding-right: 16px;
padding-left: 4px;
overflow-y: auto;
overflow-x: visible;
transition: all 0.3s ease;
}
.logs-sidebar.hidden {
flex: 0 0 0 !important;
width: 0 !important;
min-width: 0 !important;
padding: 0 !important;
border: none !important;
overflow: hidden !important;
opacity: 0;
}
.logs-container {
display: flex;
gap: 20px;
height: calc(100vh - 120px);
overflow: visible;
transition: gap 0.3s ease;
}

View File

@@ -108,6 +108,10 @@ const DOM = {
eventsContent: document.getElementById('eventsContent') as HTMLElement | null,
serverTime: document.getElementById('server-time') as HTMLElement | null,
// Боковая панель
logsSidebar: document.querySelector('.logs-sidebar') as HTMLElement | null,
logsContainer: document.querySelector('.logs-container') as HTMLElement | null,
// Элементы пагинации для данных
dataPageInfo: document.getElementById('dataPageInfo') as HTMLElement | null,
dataPrevPageBtn: document.getElementById('dataPrevPage') as HTMLButtonElement | null,
@@ -127,6 +131,29 @@ const DOM = {
goToPageBtn: document.getElementById('goToPage') as HTMLButtonElement | null,
};
// ============================================
// УПРАВЛЕНИЕ БОКОВОЙ ПАНЕЛЬЮ
// ============================================
/**
* Показать/скрыть боковую панель в зависимости от активной вкладки
*/
function toggleSidebar(show: boolean): void {
if (!DOM.logsSidebar || !DOM.logsContainer) return;
if (show) {
// Показываем панель
DOM.logsSidebar.style.display = 'block';
DOM.logsSidebar.style.flex = '0 0 280px';
DOM.logsContainer.style.gap = '20px';
} else {
// Скрываем панель
DOM.logsSidebar.style.display = 'none';
DOM.logsSidebar.style.flex = '0 0 0';
DOM.logsContainer.style.gap = '0';
}
}
// ============================================
// ФУНКЦИИ ЗАГРУЗКИ ДАННЫХ
// ============================================
@@ -206,7 +233,6 @@ async function loadFileData(filename: string, page: number = 1): Promise<void> {
const response = await fetch(url);
// Проверяем статус ответа
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
@@ -222,7 +248,6 @@ async function loadFileData(filename: string, page: number = 1): Promise<void> {
} catch (error) {
console.error('[Logs] Ошибка загрузки данных:', error);
if (DOM.dataTableContainer) {
// Показываем информативное сообщение, а не красную ошибку
DOM.dataTableContainer.innerHTML = `
<div class="empty-state">
<div class="empty-message">Нет данных для отображения</div>
@@ -230,7 +255,6 @@ async function loadFileData(filename: string, page: number = 1): Promise<void> {
</div>
`;
}
// Сбрасываем пагинацию
if (DOM.dataPageInfo) {
DOM.dataPageInfo.textContent = 'Нет записей';
}
@@ -319,15 +343,13 @@ function renderData(data: LogDataResponse): void {
`;
}
// График - показываем все данные (ограничиваем для производительности)
// График
if (DOM.logChart && data.total > 0) {
// Для графика загружаем все данные (но не более 5000 точек)
// В реальности лучше отдельный API для графика
const history = samples.map((s: LogSample) => s.signal);
drawChart(DOM.logChart, history);
}
// Таблица - показываем текущую страницу
// Таблица
if (samples.length > 0 && DOM.dataTableContainer) {
let html = `<table class="data-table">
<thead>
@@ -360,7 +382,12 @@ function renderData(data: LogDataResponse): void {
html += '</tbody></table>';
DOM.dataTableContainer.innerHTML = html;
} else if (DOM.dataTableContainer) {
DOM.dataTableContainer.innerHTML = '<p>Нет данных</p>';
DOM.dataTableContainer.innerHTML = `
<div class="empty-state">
<div class="empty-message">Нет данных</div>
<div class="empty-hint">Выберите файл с данными</div>
</div>
`;
}
}
@@ -372,7 +399,12 @@ function renderEvents(data: EventsResponse): void {
let html = '';
if (data.events.length === 0) {
html = '<div style="color:#666;">Нет событий</div>';
html = `
<div class="empty-state">
<div class="empty-message">Нет событий</div>
<div class="empty-hint">Журнал событий пуст</div>
</div>
`;
} else {
data.events.forEach((e: Event, index: number) => {
const num = index + 1;
@@ -514,7 +546,6 @@ function initDataPaginationControls(): void {
let paginationContainer = document.getElementById('dataPaginationContainer');
if (!paginationContainer) {
// Ищем место для вставки (перед таблицей)
const tableContainer = document.getElementById('dataTableContainer');
if (!tableContainer) return;
@@ -535,7 +566,6 @@ function initDataPaginationControls(): void {
</div>
`;
// Вставляем перед таблицей
dataTab.insertBefore(paginationContainer, tableContainer);
}
@@ -648,8 +678,27 @@ function initTabs(): void {
const targetTab = document.getElementById(`tab-${tabName}`);
if (targetTab) targetTab.classList.add('active');
if (tabName === 'events' && state.currentEvents.length === 0) {
void loadEvents(1);
// ===== УПРАВЛЕНИЕ БОКОВОЙ ПАНЕЛЬЮ =====
if (tabName === 'data') {
// Показываем боковую панель для вкладки "Данные"
toggleSidebar(true);
// Если данные ещё не загружены, загружаем
if (!state.currentData) {
const firstFile = document.querySelector('.log-file-item');
if (firstFile) {
const fileName = firstFile.querySelector('.file-name')?.textContent;
if (fileName) {
void loadFileData(fileName, 1);
}
}
}
} else if (tabName === 'events') {
// Скрываем боковую панель для вкладки "События"
toggleSidebar(false);
// Загружаем события, если их нет
if (state.currentEvents.length === 0) {
void loadEvents(1);
}
}
});
});
@@ -658,6 +707,9 @@ function initTabs(): void {
async function init(): Promise<void> {
console.log('[Logs] Инициализация...');
// По умолчанию показываем боковую панель
toggleSidebar(true);
initDataPaginationControls();
initEventsPaginationControls();
initTabs();
@@ -669,9 +721,15 @@ async function init(): Promise<void> {
void updateTime();
}, 1000);
// Проверяем, какая вкладка активна при загрузке
const dataTab = document.getElementById('tab-data');
const eventsTab = document.getElementById('tab-events');
if (eventsTab && eventsTab.classList.contains('active')) {
toggleSidebar(false);
await loadEvents(1);
} else {
toggleSidebar(true);
}
console.log('[Logs] Инициализация завершена');

View File

@@ -37,7 +37,7 @@
<div class="logs-container">
<!-- Боковая панель с файлами -->
<div class="logs-sidebar">
<div class="logs-sidebar" id="logsSidebar">
<h3>Файлы данных</h3>
<div id="fileList"></div>
</div>