yxy
This commit is contained in:
140
public/assets/js/dashboard.js
Normal file
140
public/assets/js/dashboard.js
Normal file
@@ -0,0 +1,140 @@
|
||||
import { apiAction, toast } from './api.js';
|
||||
import { initUserPanel } from './ui-user.js';
|
||||
import { mountLogoutButton, ensureFloatingLogout } from './ui-auth.js';
|
||||
|
||||
const state = {
|
||||
counts: { templates: 0, sections: 0, blocks: 0, snippets: 0, renders_total: 0 },
|
||||
usage: [],
|
||||
};
|
||||
|
||||
async function ensureAuthenticated() {
|
||||
try {
|
||||
const me = await apiAction('auth.me', { method: 'GET' });
|
||||
if (!me?.ok || !me?.user) {
|
||||
window.location.href = '/login.php';
|
||||
return false;
|
||||
}
|
||||
window.__currentUser = me.user;
|
||||
document.documentElement.classList.remove('auth-pending');
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function ensureAccess() {
|
||||
const role = (window.__currentUser?.role || '').toLowerCase();
|
||||
if (role !== 'owner' && role !== 'admin') {
|
||||
toast('Kein Zugriff auf das Dashboard', false);
|
||||
window.location.href = '/account.php';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function renderCounts(counts) {
|
||||
const mapping = {
|
||||
templates: 'count-templates',
|
||||
sections: 'count-sections',
|
||||
blocks: 'count-blocks',
|
||||
snippets: 'count-snippets',
|
||||
renders_total: 'count-usage',
|
||||
};
|
||||
Object.entries(mapping).forEach(([key, id]) => {
|
||||
const el = document.getElementById(id);
|
||||
if (!el) return;
|
||||
const value = counts[key] ?? 0;
|
||||
el.textContent = typeof value === 'number' ? value.toLocaleString('de-DE') : value;
|
||||
});
|
||||
}
|
||||
|
||||
function formatDate(value) {
|
||||
if (!value) return '–';
|
||||
try {
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) return value;
|
||||
return date.toLocaleString('de-DE');
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function renderUsage(list) {
|
||||
const table = document.getElementById('usageTable');
|
||||
if (!table) return;
|
||||
const tbody = table.querySelector('tbody');
|
||||
if (!tbody) return;
|
||||
if (!list.length) {
|
||||
tbody.innerHTML = '<tr><td colspan="4" class="text-sm text-slate-500">Noch keine Daten vorhanden.</td></tr>';
|
||||
return;
|
||||
}
|
||||
tbody.innerHTML = list.map(item => `
|
||||
<tr data-template-id="${item.template_id}">
|
||||
<td>${escapeHtml(item.name)}</td>
|
||||
<td>${item.render_count.toLocaleString('de-DE')}</td>
|
||||
<td>${escapeHtml(formatDate(item.last_rendered_at || item.updated_at))}</td>
|
||||
<td class="text-right">
|
||||
<button type="button" class="btn" data-reset="${item.template_id}">Zähler zurücksetzen</button>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
return String(str ?? '')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
async function loadMetrics() {
|
||||
try {
|
||||
const res = await apiAction('dashboard.metrics', { method: 'GET' });
|
||||
if (!res?.ok) throw new Error(res?.error || 'Dashboard konnte nicht geladen werden');
|
||||
state.counts = res.counts || state.counts;
|
||||
state.usage = Array.isArray(res.usage) ? res.usage : [];
|
||||
renderCounts(state.counts);
|
||||
renderUsage(state.usage);
|
||||
} catch (err) {
|
||||
toast(err.message || 'Fehler beim Laden', false);
|
||||
}
|
||||
}
|
||||
|
||||
async function resetUsage(templateId) {
|
||||
try {
|
||||
await apiAction('dashboard.reset_usage', { method: 'POST', data: { template_id: templateId } });
|
||||
toast('Zähler zurückgesetzt', true);
|
||||
await loadMetrics();
|
||||
} catch (err) {
|
||||
toast(err.message || 'Zurücksetzen fehlgeschlagen', false);
|
||||
}
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
const refresh = document.getElementById('btn-refresh-dashboard');
|
||||
refresh?.addEventListener('click', () => loadMetrics());
|
||||
|
||||
const table = document.getElementById('usageTable');
|
||||
table?.addEventListener('click', ev => {
|
||||
const btn = ev.target.closest('button[data-reset]');
|
||||
if (!btn) return;
|
||||
const id = Number(btn.getAttribute('data-reset'));
|
||||
if (!id) return;
|
||||
if (confirm('Zähler für dieses Template wirklich löschen?')) {
|
||||
resetUsage(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const ok = await ensureAuthenticated();
|
||||
if (!ok) return;
|
||||
if (!ensureAccess()) return;
|
||||
initUserPanel();
|
||||
bindEvents();
|
||||
await loadMetrics();
|
||||
mountLogoutButton('#btn-logout', { redirect: '/login.php' });
|
||||
ensureFloatingLogout({ redirect: '/login.php' });
|
||||
});
|
||||
Reference in New Issue
Block a user