Files
Frederico Castro da22154f66 Evolução da plataforma: dashboard com gráficos, notificações, relatórios automáticos, ícones Lucide local e melhorias gerais
- Dashboard com 5 gráficos Chart.js (execuções, status, custo, agentes, pipelines)
- Sistema de notificações com polling, badge e Browser Notification API
- Relatórios MD automáticos para execuções de agentes e pipelines (data/reports/)
- Lucide local (v0.475.0) com nomes de ícones atualizados e refreshIcons centralizado
- Correção de ícones icon-only (padding CSS sobrescrito por btn-sm)
- Cards de agentes e pipelines com botões alinhados na base (flex column)
- Terminal com busca, download, cópia e auto-scroll toggle
- Histórico com export CSV, retry, paginação e truncamento de texto
- Webhooks com edição e teste inline
- Duplicação de agentes e export/import JSON
- Rate limiting, CORS, correlação de requests e health check no backend
- Escrita atômica em JSON (temp + rename) e store de notificações
- Tema claro/escuro com toggle e persistência em localStorage
- Atalhos de teclado 1-9 para navegação entre seções
2026-02-26 20:41:17 -03:00

65 lines
1.7 KiB
JavaScript

const Toast = {
iconMap: {
success: 'circle-check',
error: 'circle-x',
info: 'info',
warning: 'triangle-alert',
},
colorMap: {
success: 'toast-success',
error: 'toast-error',
info: 'toast-info',
warning: 'toast-warning',
},
show(message, type = 'info', duration = 4000) {
const container = document.getElementById('toast-container');
if (!container) return;
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
const iconName = Toast.iconMap[type] || 'info';
toast.innerHTML = `
<span class="toast-icon" data-lucide="${iconName}"></span>
<span class="toast-message">${message}</span>
<button class="toast-close" aria-label="Fechar notificação">
<i data-lucide="x"></i>
</button>
`;
const closeBtn = toast.querySelector('.toast-close');
closeBtn.addEventListener('click', () => Toast.dismiss(toast));
container.appendChild(toast);
Utils.refreshIcons(toast);
requestAnimationFrame(() => {
toast.classList.add('toast-show');
});
if (duration > 0) {
setTimeout(() => Toast.dismiss(toast), duration);
}
return toast;
},
dismiss(toast) {
toast.classList.remove('toast-show');
toast.classList.add('removing');
toast.addEventListener('animationend', () => toast.remove(), { once: true });
setTimeout(() => toast.remove(), 400);
},
success(message, duration) { return Toast.show(message, 'success', duration); },
error(message, duration) { return Toast.show(message, 'error', duration); },
info(message, duration) { return Toast.show(message, 'info', duration); },
warning(message, duration) { return Toast.show(message, 'warning', duration); },
};
window.Toast = Toast;