Tarefas executáveis, broadcast global para agendamentos e dashboard persistente
- Tarefas agora são templates executáveis com botão play e seleção de agente - Dropdown de tarefas salvas no modal de execução para reutilização rápida - Broadcast global no manager para execuções agendadas via cron aparecerem no terminal - Dashboard atividade recente agora consulta executionsStore persistente - Suporte a exibição de pipelines e agentes na atividade recente
This commit is contained in:
@@ -294,12 +294,34 @@ const AgentsUI = {
|
||||
const instructionsEl = document.getElementById('execute-instructions');
|
||||
if (instructionsEl) instructionsEl.value = '';
|
||||
|
||||
AgentsUI._loadSavedTasks();
|
||||
|
||||
Modal.open('execute-modal-overlay');
|
||||
} catch (err) {
|
||||
Toast.error(`Erro ao abrir modal de execução: ${err.message}`);
|
||||
}
|
||||
},
|
||||
|
||||
async _loadSavedTasks() {
|
||||
const savedTaskSelect = document.getElementById('execute-saved-task');
|
||||
if (!savedTaskSelect) return;
|
||||
|
||||
try {
|
||||
const tasks = await API.tasks.list();
|
||||
savedTaskSelect.innerHTML = '<option value="">Digitar manualmente...</option>' +
|
||||
tasks.map((t) => {
|
||||
const label = t.category ? `[${t.category.toUpperCase()}] ${t.name}` : t.name;
|
||||
return `<option value="${t.id}">${label}</option>`;
|
||||
}).join('');
|
||||
AgentsUI._savedTasksCache = tasks;
|
||||
} catch {
|
||||
savedTaskSelect.innerHTML = '<option value="">Digitar manualmente...</option>';
|
||||
AgentsUI._savedTasksCache = [];
|
||||
}
|
||||
},
|
||||
|
||||
_savedTasksCache: [],
|
||||
|
||||
async export(agentId) {
|
||||
try {
|
||||
const data = await API.agents.export(agentId);
|
||||
|
||||
@@ -66,19 +66,27 @@ const DashboardUI = {
|
||||
list.innerHTML = executions.map((exec) => {
|
||||
const statusClass = DashboardUI._statusBadgeClass(exec.status);
|
||||
const statusLabel = DashboardUI._statusLabel(exec.status);
|
||||
const name = exec.agentName || exec.pipelineName || exec.agentId || 'Execução';
|
||||
const taskText = exec.task || exec.input || '';
|
||||
const typeBadge = exec.type === 'pipeline'
|
||||
? '<span class="badge badge--purple" style="font-size:0.6rem;padding:1px 5px;">Pipeline</span> '
|
||||
: '';
|
||||
const time = exec.startedAt
|
||||
? new Date(exec.startedAt).toLocaleTimeString('pt-BR')
|
||||
? new Date(exec.startedAt).toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })
|
||||
: '—';
|
||||
const date = exec.startedAt
|
||||
? new Date(exec.startedAt).toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' })
|
||||
: '';
|
||||
|
||||
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>
|
||||
<span class="activity-item-agent">${typeBadge}${name}</span>
|
||||
<span class="activity-item-task">${taskText.length > 80 ? taskText.slice(0, 80) + '...' : taskText}</span>
|
||||
</div>
|
||||
<div class="activity-item-meta">
|
||||
<span class="badge ${statusClass}">${statusLabel}</span>
|
||||
<span class="activity-item-time">${time}</span>
|
||||
<span class="activity-item-time">${date} ${time}</span>
|
||||
</div>
|
||||
</li>
|
||||
`;
|
||||
|
||||
@@ -75,6 +75,9 @@ const TasksUI = {
|
||||
${createdAt}
|
||||
</span>
|
||||
<div class="task-card-actions">
|
||||
<button class="btn btn-primary btn-sm" data-action="execute-task" data-id="${task.id}" title="Executar tarefa">
|
||||
<i data-lucide="play"></i>
|
||||
</button>
|
||||
<button class="btn btn--ghost btn--sm" data-action="edit-task" data-id="${task.id}" title="Editar tarefa">
|
||||
<i data-lucide="pencil"></i>
|
||||
</button>
|
||||
@@ -209,6 +212,49 @@ const TasksUI = {
|
||||
}
|
||||
},
|
||||
|
||||
async execute(taskId) {
|
||||
const task = TasksUI.tasks.find((t) => t.id === taskId);
|
||||
if (!task) return;
|
||||
|
||||
try {
|
||||
const agents = await API.agents.list();
|
||||
const activeAgents = agents.filter((a) => a.status === 'active');
|
||||
|
||||
if (activeAgents.length === 0) {
|
||||
Toast.warning('Nenhum agente ativo disponível para executar');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectEl = document.getElementById('execute-agent-select');
|
||||
if (selectEl) {
|
||||
selectEl.innerHTML = '<option value="">Selecionar agente...</option>' +
|
||||
activeAgents.map((a) => `<option value="${a.id}">${a.agent_name || a.name}</option>`).join('');
|
||||
selectEl.value = '';
|
||||
}
|
||||
|
||||
const hiddenId = document.getElementById('execute-agent-id');
|
||||
if (hiddenId) hiddenId.value = '';
|
||||
|
||||
const taskEl = document.getElementById('execute-task-desc');
|
||||
if (taskEl) {
|
||||
const parts = [task.name];
|
||||
if (task.description) parts.push(task.description);
|
||||
taskEl.value = parts.join('\n\n');
|
||||
}
|
||||
|
||||
const instructionsEl = document.getElementById('execute-instructions');
|
||||
if (instructionsEl) instructionsEl.value = '';
|
||||
|
||||
await AgentsUI._loadSavedTasks();
|
||||
const savedTaskSelect = document.getElementById('execute-saved-task');
|
||||
if (savedTaskSelect) savedTaskSelect.value = task.id;
|
||||
|
||||
Modal.open('execute-modal-overlay');
|
||||
} catch (err) {
|
||||
Toast.error(`Erro ao abrir execução: ${err.message}`);
|
||||
}
|
||||
},
|
||||
|
||||
_categoryClass(category) {
|
||||
const map = {
|
||||
'code-review': 'badge--blue',
|
||||
|
||||
Reference in New Issue
Block a user