modified: web/templates/404.html modified: web/templates/base.html modified: web/templates/group_admin/base.html modified: web/templates/group_admin/member_edit.html modified: web/templates/group_admin/members.html
122 lines
4.5 KiB
JavaScript
122 lines
4.5 KiB
JavaScript
/* ============================================================
|
||
MCLogger – main.js
|
||
Author: SimolZimol
|
||
============================================================ */
|
||
|
||
// ── Sidebar Toggle ────────────────────────────────────────
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const btn = document.getElementById('sidebarToggle');
|
||
const sidebar = document.getElementById('sidebar');
|
||
|
||
if (btn && sidebar) {
|
||
btn.addEventListener('click', () => {
|
||
sidebar.classList.toggle('collapsed');
|
||
localStorage.setItem('sidebar-collapsed', sidebar.classList.contains('collapsed'));
|
||
});
|
||
|
||
// Zustand beim Laden wiederherstellen
|
||
if (localStorage.getItem('sidebar-collapsed') === 'true') {
|
||
sidebar.classList.add('collapsed');
|
||
}
|
||
}
|
||
|
||
// Online-Count aktualisieren
|
||
updateOnlineCount();
|
||
setInterval(updateOnlineCount, 30_000);
|
||
|
||
// Client-side clock: always use the user's local PC/browser time
|
||
initClientClock();
|
||
|
||
// Tooltips initialisieren
|
||
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
|
||
new bootstrap.Tooltip(el);
|
||
});
|
||
|
||
// Automatisch Tabellen sortieren ermöglichen
|
||
initTableSort();
|
||
});
|
||
|
||
function initClientClock() {
|
||
const el = document.getElementById('client-clock');
|
||
if (!el) return;
|
||
|
||
const render = () => {
|
||
const now = new Date();
|
||
const locale = navigator.language || 'en-US';
|
||
el.textContent = now.toLocaleString(locale, {
|
||
year: 'numeric',
|
||
month: '2-digit',
|
||
day: '2-digit',
|
||
hour: '2-digit',
|
||
minute: '2-digit',
|
||
second: '2-digit'
|
||
});
|
||
};
|
||
|
||
render();
|
||
setInterval(render, 1000);
|
||
}
|
||
|
||
// ── Online-Count API ──────────────────────────────────────
|
||
function updateOnlineCount() {
|
||
fetch('/api/online')
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
const el = document.getElementById('online-count');
|
||
if (el) el.textContent = data.length;
|
||
})
|
||
.catch(() => {/* Ignorieren wenn nicht eingeloggt */});
|
||
}
|
||
|
||
// ── Einfache Tabellen-Sortierung ──────────────────────────
|
||
function initTableSort() {
|
||
document.querySelectorAll('th[data-sort]').forEach(th => {
|
||
th.style.cursor = 'pointer';
|
||
th.addEventListener('click', () => {
|
||
const table = th.closest('table');
|
||
const idx = Array.from(th.parentNode.children).indexOf(th);
|
||
const asc = th.dataset.order !== 'asc';
|
||
th.dataset.order = asc ? 'asc' : 'desc';
|
||
|
||
const rows = Array.from(table.querySelectorAll('tbody tr'));
|
||
rows.sort((a, b) => {
|
||
const av = a.cells[idx]?.textContent.trim() ?? '';
|
||
const bv = b.cells[idx]?.textContent.trim() ?? '';
|
||
return asc ? av.localeCompare(bv, 'de', {numeric: true}) : bv.localeCompare(av, 'de', {numeric: true});
|
||
});
|
||
const tbody = table.querySelector('tbody');
|
||
rows.forEach(r => tbody.appendChild(r));
|
||
});
|
||
});
|
||
}
|
||
|
||
// ── Formatierung ──────────────────────────────────────────
|
||
function fmtDuration(sec) {
|
||
sec = parseInt(sec) || 0;
|
||
const h = Math.floor(sec / 3600);
|
||
const m = Math.floor((sec % 3600) / 60);
|
||
const s = sec % 60;
|
||
if (h) return `${h}h ${m}m`;
|
||
if (m) return `${m}m ${s}s`;
|
||
return `${s}s`;
|
||
}
|
||
|
||
// ── Live-Chat-Reload (optional) ───────────────────────────
|
||
if (window.location.pathname === '/chat') {
|
||
// Kein automatisches Reload im Chat (würde Filter zurücksetzen)
|
||
}
|
||
|
||
// ── Kopieren in Zwischenablage ────────────────────────────
|
||
document.querySelectorAll('.copy-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const target = document.querySelector(btn.dataset.target);
|
||
if (target) {
|
||
navigator.clipboard.writeText(target.textContent.trim())
|
||
.then(() => {
|
||
btn.innerHTML = '<i class="bi bi-check2"></i>';
|
||
setTimeout(() => btn.innerHTML = '<i class="bi bi-clipboard"></i>', 1500);
|
||
});
|
||
}
|
||
});
|
||
});
|