fix: Accordion toggle with proper cookie handling

This commit is contained in:
mirivlad 2026-04-17 17:36:05 +08:00
parent 32894447f3
commit 4766d4511e
1 changed files with 55 additions and 63 deletions

View File

@ -201,87 +201,79 @@
<script> <script>
(function() { (function() {
const COOKIE_NAME = 'dashboard_accordion'; const COOKIE_NAME = 'dashboard_accordion';
let accordionState = {};
function getCookie(name) { function getState() {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); try {
const match = document.cookie.match(new RegExp('(^| )' + COOKIE_NAME + '=([^;]+)'));
return match ? JSON.parse(decodeURIComponent(match[2])) : {}; return match ? JSON.parse(decodeURIComponent(match[2])) : {};
} catch(e) { return {}; }
} }
function saveCookie(state) { function setState(state) {
document.cookie = COOKIE_NAME + '=' + encodeURIComponent(JSON.stringify(state)) + document.cookie = COOKIE_NAME + '=' + encodeURIComponent(JSON.stringify(state)) + '; path=/; max-age=' + (30*24*60*60);
'; path=/; max-age=' + (30 * 24 * 60 * 60); }
function toggleAccordion(header, target, icon) {
const groupId = header.dataset.group;
const isOpen = target.classList.contains('show');
if (isOpen) {
target.classList.remove('show');
icon.className = 'fas fa-chevron-down';
var state = getState();
state[groupId] = 'collapsed';
setState(state);
} else {
target.classList.add('show');
icon.className = 'fas fa-chevron-up';
var state = getState();
state[groupId] = 'expanded';
setState(state);
}
} }
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
accordionState = getCookie(COOKIE_NAME); var savedState = getState();
// Инициализация: устанавливаем начальное состояние из cookies
document.querySelectorAll('.accordion-header').forEach(function(header) { document.querySelectorAll('.accordion-header').forEach(function(header) {
const groupId = header.dataset.group; var icon = header.querySelector('.accordion-icon');
const targetId = header.dataset.target; var targetId = header.dataset.target;
const target = document.querySelector(targetId); var target = document.querySelector(targetId);
var groupId = header.dataset.group;
if (target) { if (target && icon) {
if (accordionState[groupId] === 'collapsed') { var isCollapsed = savedState[groupId] === 'collapsed';
target.classList.remove('show');
header.querySelector('.accordion-icon').className = 'fas fa-chevron-down';
} else {
// По умолчанию открыто
target.classList.add('show');
header.querySelector('.accordion-icon').className = 'fas fa-chevron-up';
}
}
});
// Клик на заголовке accordion if (isCollapsed) {
document.querySelectorAll('.accordion-header').forEach(function(header) {
header.addEventListener('click', function(e) {
const groupId = this.dataset.group;
const targetId = this.dataset.target;
const target = document.querySelector(targetId);
const icon = this.querySelector('.accordion-icon');
if (target.classList.contains('show')) {
// Сворачиваем
target.classList.remove('show'); target.classList.remove('show');
icon.className = 'fas fa-chevron-down'; icon.className = 'fas fa-chevron-down';
accordionState[groupId] = 'collapsed';
} else { } else {
// Разворачиваем
target.classList.add('show'); target.classList.add('show');
icon.className = 'fas fa-chevron-up'; icon.className = 'fas fa-chevron-up';
accordionState[groupId] = 'expanded';
} }
saveCookie(accordionState);
header.addEventListener('click', function() {
toggleAccordion(header, target, icon);
}); });
}
}); });
// AJAX обновление // AJAX
function updateDashboard() { function updateDashboard() {
fetch('/api/dashboard/stats') fetch('/api/dashboard/stats')
.then(response => response.json()) .then(function(r) { return r.json(); })
.then(data => { .then(function(data) {
data.forEach(server => { data.forEach(function(server) {
const cpuVal = document.getElementById('cpu-val-' + server.id); var cpuVal = document.getElementById('cpu-val-' + server.id);
if (cpuVal && server.metrics.cpu_load) { if (cpuVal && server.metrics.cpu_load) cpuVal.textContent = server.metrics.cpu_load.value + '%';
cpuVal.textContent = server.metrics.cpu_load.value + '%'; var ramVal = document.getElementById('ram-val-' + server.id);
} if (ramVal && server.metrics.ram_used) ramVal.textContent = server.metrics.ram_used.value + '%';
const ramVal = document.getElementById('ram-val-' + server.id); var diskVal = document.getElementById('disk-val-' + server.id);
if (ramVal && server.metrics.ram_used) { if (diskVal && server.metrics.disk) diskVal.textContent = server.metrics.disk.value + '%';
ramVal.textContent = server.metrics.ram_used.value + '%'; var updatedAt = document.getElementById('updated-at-' + server.id);
} if (updatedAt && server.updated_at) updatedAt.textContent = server.updated_at.split(' ')[1].substring(0, 5);
const diskVal = document.getElementById('disk-val-' + server.id); });
if (diskVal && server.metrics.disk) {
diskVal.textContent = server.metrics.disk.value + '%';
}
const updatedAt = document.getElementById('updated-at-' + server.id);
if (updatedAt && server.updated_at) {
updatedAt.textContent = server.updated_at.split(' ')[1].substring(0, 5);
}
}); });
})
.catch(err => console.log('Dashboard update error:', err));
} }
setInterval(updateDashboard, 30000); setInterval(updateDashboard, 30000);