- Settings persistentes (modelo padrão, workdir, max concurrent) - Import/export de agentes via JSON - Agendamentos persistentes com restore no startup - Edição de agendamentos e tarefas existentes - Filtros e busca em todas as seções - Isolamento de WebSocket por clientId - Autenticação via AUTH_TOKEN e CORS configurável - Graceful shutdown com cancelamento de execuções - Correção: --max-tokens removido (flag inválida do CLI) - Correção: pipeline agora verifica exit code e propaga erros - Correção: streaming de output em pipelines via WebSocket - Permission mode bypassPermissions como padrão - Página de configurações do sistema - Contagem diária de execuções no dashboard - Histórico de execuções recentes
119 lines
3.5 KiB
JavaScript
119 lines
3.5 KiB
JavaScript
const DashboardUI = {
|
|
async load() {
|
|
try {
|
|
const [status, recentExecs] = await Promise.all([
|
|
API.system.status(),
|
|
API.executions.recent(10),
|
|
]);
|
|
|
|
DashboardUI.updateMetrics(status);
|
|
DashboardUI.updateRecentActivity(recentExecs || []);
|
|
DashboardUI.updateSystemStatus(status);
|
|
} catch (err) {
|
|
Toast.error(`Erro ao carregar dashboard: ${err.message}`);
|
|
}
|
|
},
|
|
|
|
updateMetrics(status) {
|
|
const metrics = {
|
|
'metric-total-agents': status.agents?.total ?? 0,
|
|
'metric-active-agents': status.agents?.active ?? 0,
|
|
'metric-executions-today': status.executions?.today ?? 0,
|
|
'metric-schedules': status.schedules?.total ?? 0,
|
|
};
|
|
|
|
for (const [id, target] of Object.entries(metrics)) {
|
|
const el = document.getElementById(id);
|
|
if (!el) continue;
|
|
|
|
const current = parseInt(el.textContent, 10) || 0;
|
|
DashboardUI._animateCount(el, current, target);
|
|
}
|
|
},
|
|
|
|
_animateCount(el, from, to) {
|
|
const duration = 600;
|
|
const start = performance.now();
|
|
|
|
const step = (now) => {
|
|
const elapsed = now - start;
|
|
const progress = Math.min(elapsed / duration, 1);
|
|
const eased = 1 - Math.pow(1 - progress, 3);
|
|
const value = Math.round(from + (to - from) * eased);
|
|
el.textContent = value;
|
|
|
|
if (progress < 1) requestAnimationFrame(step);
|
|
};
|
|
|
|
requestAnimationFrame(step);
|
|
},
|
|
|
|
updateRecentActivity(executions) {
|
|
const list = document.getElementById('activity-list');
|
|
if (!list) return;
|
|
|
|
if (!executions || executions.length === 0) {
|
|
list.innerHTML = `
|
|
<li class="activity-empty">
|
|
<i data-lucide="inbox"></i>
|
|
<span>Nenhuma execução recente</span>
|
|
</li>
|
|
`;
|
|
if (window.lucide) lucide.createIcons({ nodes: [list] });
|
|
return;
|
|
}
|
|
|
|
list.innerHTML = executions.map((exec) => {
|
|
const statusClass = DashboardUI._statusBadgeClass(exec.status);
|
|
const statusLabel = DashboardUI._statusLabel(exec.status);
|
|
const time = exec.startedAt
|
|
? new Date(exec.startedAt).toLocaleTimeString('pt-BR')
|
|
: '—';
|
|
|
|
return `
|
|
<li class="activity-item">
|
|
<div class="activity-item-info">
|
|
<span class="activity-item-agent">${exec.agentName || exec.agentId || 'Agente'}</span>
|
|
<span class="activity-item-task">${exec.task || ''}</span>
|
|
</div>
|
|
<div class="activity-item-meta">
|
|
<span class="badge ${statusClass}">${statusLabel}</span>
|
|
<span class="activity-item-time">${time}</span>
|
|
</div>
|
|
</li>
|
|
`;
|
|
}).join('');
|
|
},
|
|
|
|
updateSystemStatus(status) {
|
|
const wsBadge = document.getElementById('system-ws-status-badge');
|
|
if (wsBadge) {
|
|
const wsConnected = document.getElementById('ws-indicator')?.classList.contains('ws-indicator--connected');
|
|
wsBadge.textContent = wsConnected ? 'Conectado' : 'Desconectado';
|
|
wsBadge.className = `badge ${wsConnected ? 'badge--green' : 'badge--red'}`;
|
|
}
|
|
},
|
|
|
|
_statusBadgeClass(status) {
|
|
const map = {
|
|
running: 'badge--blue',
|
|
completed: 'badge--green',
|
|
error: 'badge--red',
|
|
cancelled: 'badge--gray',
|
|
};
|
|
return map[status] || 'badge--gray';
|
|
},
|
|
|
|
_statusLabel(status) {
|
|
const map = {
|
|
running: 'Em execução',
|
|
completed: 'Concluído',
|
|
error: 'Erro',
|
|
cancelled: 'Cancelado',
|
|
};
|
|
return map[status] || status || 'Desconhecido';
|
|
},
|
|
};
|
|
|
|
window.DashboardUI = DashboardUI;
|