Dashboard Status compact în Kanban
- Header colapsabil cu rezumat (ANAF, Git) - Status row: ANAF, Git, ultimul raport cu timestamp - Cron jobs pe un singur rând - Colapsat by default - status.json actualizat de rapoartele zilnice
This commit is contained in:
@@ -15,6 +15,126 @@
|
||||
padding: var(--space-5);
|
||||
}
|
||||
|
||||
/* Dashboard */
|
||||
.dashboard {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg);
|
||||
margin-bottom: var(--space-5);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dashboard-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-3);
|
||||
padding: var(--space-3) var(--space-4);
|
||||
background: linear-gradient(135deg, rgba(99, 102, 241, 0.15), rgba(139, 92, 246, 0.1));
|
||||
border-bottom: 1px solid var(--border);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.dashboard-header:hover {
|
||||
filter: brightness(1.05);
|
||||
}
|
||||
|
||||
.dashboard-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
font-weight: 600;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.dashboard-title svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.dashboard-summary {
|
||||
flex: 1;
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-muted);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.dashboard-toggle {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--text-muted);
|
||||
transition: transform var(--transition-fast);
|
||||
}
|
||||
|
||||
.dashboard.collapsed .dashboard-toggle {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.dashboard.collapsed .dashboard-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dashboard-content {
|
||||
padding: var(--space-2) var(--space-4);
|
||||
}
|
||||
|
||||
.status-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-4);
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
.status-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.status-label {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.status-value {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.status-value.ok { color: #22c55e; }
|
||||
.status-value.warning { color: #f59e0b; }
|
||||
.status-value.error { color: #ef4444; }
|
||||
|
||||
.status-time {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-muted);
|
||||
margin-left: var(--space-1);
|
||||
}
|
||||
|
||||
.cron-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
font-size: var(--text-sm);
|
||||
padding-top: var(--space-2);
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.cron-label {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.cron-list {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.cron-done {
|
||||
color: var(--text-muted);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: var(--space-6);
|
||||
}
|
||||
@@ -352,6 +472,39 @@
|
||||
</header>
|
||||
|
||||
<main class="main">
|
||||
<!-- Status Dashboard -->
|
||||
<div class="dashboard" id="dashboard">
|
||||
<div class="dashboard-header" onclick="toggleDashboard()">
|
||||
<div class="dashboard-title">
|
||||
<i data-lucide="activity"></i>
|
||||
<span>Status</span>
|
||||
</div>
|
||||
<div class="dashboard-summary" id="dashboardSummary">Se încarcă...</div>
|
||||
<i data-lucide="chevron-down" class="dashboard-toggle" id="dashboardToggle"></i>
|
||||
</div>
|
||||
<div class="dashboard-content" id="dashboardContent">
|
||||
<div class="status-row">
|
||||
<div class="status-item">
|
||||
<span class="status-label">ANAF:</span>
|
||||
<span class="status-value" id="anafStatus">OK</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="status-label">Git:</span>
|
||||
<span class="status-value" id="gitStatus">curat</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="status-label">Raport:</span>
|
||||
<span class="status-value" id="lastReport">-</span>
|
||||
<span class="status-time" id="reportTime"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cron-row">
|
||||
<span class="cron-label">Azi:</span>
|
||||
<span class="cron-list" id="cronList">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Task Board</h1>
|
||||
<p class="page-subtitle" id="lastUpdated">Se încarcă...</p>
|
||||
@@ -397,6 +550,86 @@
|
||||
// Init Lucide icons
|
||||
lucide.createIcons();
|
||||
|
||||
// Dashboard
|
||||
function initDashboard() {
|
||||
const collapsed = localStorage.getItem('dashboardCollapsed');
|
||||
const dashboard = document.getElementById('dashboard');
|
||||
// Default collapsed
|
||||
if (collapsed === null || collapsed === 'true') {
|
||||
dashboard.classList.add('collapsed');
|
||||
}
|
||||
loadDashboardStatus();
|
||||
}
|
||||
|
||||
function toggleDashboard() {
|
||||
const dashboard = document.getElementById('dashboard');
|
||||
dashboard.classList.toggle('collapsed');
|
||||
localStorage.setItem('dashboardCollapsed', dashboard.classList.contains('collapsed'));
|
||||
}
|
||||
|
||||
async function loadDashboardStatus() {
|
||||
try {
|
||||
const response = await fetch('status.json?' + Date.now());
|
||||
if (response.ok) {
|
||||
const status = await response.json();
|
||||
updateDashboard(status);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('No status.json yet');
|
||||
}
|
||||
updateCronList();
|
||||
}
|
||||
|
||||
function updateDashboard(status) {
|
||||
// ANAF
|
||||
const anafEl = document.getElementById('anafStatus');
|
||||
if (status.anaf) {
|
||||
anafEl.textContent = status.anaf.status;
|
||||
anafEl.className = 'status-value ' + (status.anaf.ok ? 'ok' : 'warning');
|
||||
}
|
||||
|
||||
// Git
|
||||
const gitEl = document.getElementById('gitStatus');
|
||||
if (status.git) {
|
||||
gitEl.textContent = status.git.status;
|
||||
gitEl.className = 'status-value ' + (status.git.clean ? 'ok' : 'warning');
|
||||
}
|
||||
|
||||
// Last report
|
||||
const reportEl = document.getElementById('lastReport');
|
||||
const timeEl = document.getElementById('reportTime');
|
||||
if (status.lastReport) {
|
||||
reportEl.textContent = status.lastReport.summary || 'OK';
|
||||
timeEl.textContent = status.lastReport.time ? '(' + status.lastReport.time + ')' : '';
|
||||
}
|
||||
|
||||
// Summary in header
|
||||
const summaryEl = document.getElementById('dashboardSummary');
|
||||
let summary = [];
|
||||
if (status.anaf) summary.push('ANAF: ' + status.anaf.status);
|
||||
if (status.git) summary.push('Git: ' + status.git.status);
|
||||
summaryEl.textContent = summary.join(' · ');
|
||||
}
|
||||
|
||||
function updateCronList() {
|
||||
const now = new Date();
|
||||
const hour = now.getHours();
|
||||
|
||||
const jobs = [
|
||||
{ time: '07:30', name: 'coaching', done: hour >= 8 },
|
||||
{ time: '08:30', name: 'raport', done: hour >= 9 },
|
||||
{ time: '20:00', name: 'raport', done: hour >= 20 },
|
||||
{ time: '21:00', name: 'coaching', done: hour >= 21 }
|
||||
];
|
||||
|
||||
const listEl = document.getElementById('cronList');
|
||||
listEl.innerHTML = jobs.map(job =>
|
||||
`<span class="${job.done ? 'cron-done' : ''}">${job.time} ${job.name}</span>`
|
||||
).join(' · ');
|
||||
}
|
||||
|
||||
initDashboard();
|
||||
|
||||
let tasksData = null;
|
||||
let draggedTask = null;
|
||||
let saveTimeout = null;
|
||||
|
||||
21
kanban/status.json
Normal file
21
kanban/status.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"anaf": {
|
||||
"status": "OK",
|
||||
"ok": true,
|
||||
"lastCheck": "2026-01-30T13:50:00Z"
|
||||
},
|
||||
"git": {
|
||||
"status": "curat",
|
||||
"clean": true,
|
||||
"files": 0
|
||||
},
|
||||
"agents": {
|
||||
"count": 5,
|
||||
"list": ["echo-work", "echo-health", "echo-growth", "echo-sprijin", "echo-scout"]
|
||||
},
|
||||
"lastReport": {
|
||||
"type": "test",
|
||||
"summary": "Ecosistem configurat, totul în ordine",
|
||||
"time": "30 ian 2026, 13:55"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user