Боковая панель в данных для журнала
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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,9 +678,28 @@ function initTabs(): void {
|
||||
const targetTab = document.getElementById(`tab-${tabName}`);
|
||||
if (targetTab) targetTab.classList.add('active');
|
||||
|
||||
if (tabName === 'events' && state.currentEvents.length === 0) {
|
||||
// ===== УПРАВЛЕНИЕ БОКОВОЙ ПАНЕЛЬЮ =====
|
||||
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] Инициализация завершена');
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user