const WebhooksUI = { webhooks: [], agents: [], pipelines: [], async load() { try { const [webhooks, agents, pipelines] = await Promise.all([ API.webhooks.list(), API.agents.list(), API.pipelines.list(), ]); WebhooksUI.webhooks = Array.isArray(webhooks) ? webhooks : []; WebhooksUI.agents = Array.isArray(agents) ? agents : []; WebhooksUI.pipelines = Array.isArray(pipelines) ? pipelines : []; WebhooksUI.render(); } catch (err) { Toast.error(`Erro ao carregar webhooks: ${err.message}`); } }, filter(searchText) { const search = (searchText || '').toLowerCase(); const filtered = WebhooksUI.webhooks.filter((w) => { const name = (w.name || '').toLowerCase(); return !search || name.includes(search); }); WebhooksUI.render(filtered); }, render(filteredWebhooks) { const container = document.getElementById('webhooks-list'); if (!container) return; const webhooks = filteredWebhooks || WebhooksUI.webhooks; if (webhooks.length === 0) { container.innerHTML = `

Nenhum webhook cadastrado

Crie webhooks para disparar agentes ou pipelines via HTTP.

`; Utils.refreshIcons(container); return; } container.innerHTML = webhooks.map((w) => WebhooksUI._renderCard(w)).join(''); Utils.refreshIcons(container); }, _renderCard(webhook) { const typeBadge = webhook.targetType === 'pipeline' ? 'Pipeline' : 'Agente'; const statusBadge = webhook.active ? 'Ativo' : 'Inativo'; const targetName = WebhooksUI._resolveTargetName(webhook); const hookUrl = `${window.location.origin}/hook/${webhook.token}`; const lastTrigger = webhook.lastTriggeredAt ? new Date(webhook.lastTriggeredAt).toLocaleString('pt-BR') : 'Nunca'; return `
${Utils.escapeHtml(webhook.name)} ${typeBadge} ${statusBadge}
Destino ${Utils.escapeHtml(targetName)}
URL
${hookUrl}
${webhook.triggerCount || 0} disparos Último: ${lastTrigger}
`; }, _resolveTargetName(webhook) { if (webhook.targetType === 'agent') { const agent = WebhooksUI.agents.find((a) => a.id === webhook.targetId); return agent ? (agent.agent_name || agent.name) : webhook.targetId; } const pl = WebhooksUI.pipelines.find((p) => p.id === webhook.targetId); return pl ? pl.name : webhook.targetId; }, openCreateModal() { const titleEl = document.getElementById('webhook-modal-title'); if (titleEl) titleEl.textContent = 'Novo Webhook'; const nameEl = document.getElementById('webhook-name'); if (nameEl) nameEl.value = ''; const typeEl = document.getElementById('webhook-target-type'); if (typeEl) { typeEl.value = 'agent'; WebhooksUI._updateTargetSelect('agent'); } const submitBtn = document.getElementById('webhook-form-submit'); if (submitBtn) submitBtn.dataset.editId = ''; Modal.open('webhook-modal-overlay'); }, openEditModal(webhookId) { const webhook = WebhooksUI.webhooks.find(w => w.id === webhookId); if (!webhook) return; const titleEl = document.getElementById('webhook-modal-title'); if (titleEl) titleEl.textContent = 'Editar Webhook'; const nameEl = document.getElementById('webhook-name'); if (nameEl) nameEl.value = webhook.name || ''; const typeEl = document.getElementById('webhook-target-type'); if (typeEl) { typeEl.value = webhook.targetType || 'agent'; WebhooksUI._updateTargetSelect(webhook.targetType || 'agent'); } const targetEl = document.getElementById('webhook-target-id'); if (targetEl) targetEl.value = webhook.targetId || ''; const submitBtn = document.getElementById('webhook-form-submit'); if (submitBtn) submitBtn.dataset.editId = webhookId; Modal.open('webhook-modal-overlay'); }, async test(webhookId) { try { const result = await API.webhooks.test(webhookId); Toast.success(result.message || 'Webhook disparado com sucesso'); if (result.executionId || result.pipelineId) { App.navigateTo('terminal'); } } catch (err) { Toast.error(`Erro ao testar webhook: ${err.message}`); } }, _updateTargetSelect(targetType) { const selectEl = document.getElementById('webhook-target-id'); if (!selectEl) return; if (targetType === 'agent') { selectEl.innerHTML = '' + WebhooksUI.agents.map((a) => ``).join(''); } else { selectEl.innerHTML = '' + WebhooksUI.pipelines.map((p) => ``).join(''); } }, async save() { const name = document.getElementById('webhook-name')?.value.trim(); const targetType = document.getElementById('webhook-target-type')?.value; const targetId = document.getElementById('webhook-target-id')?.value; const submitBtn = document.getElementById('webhook-form-submit'); const editId = submitBtn?.dataset.editId || ''; if (!name) { Toast.warning('Nome do webhook é obrigatório'); return; } if (!targetId) { Toast.warning('Selecione um destino'); return; } try { if (editId) { await API.webhooks.update(editId, { name, targetType, targetId }); Modal.close('webhook-modal-overlay'); Toast.success('Webhook atualizado com sucesso'); } else { await API.webhooks.create({ name, targetType, targetId }); Modal.close('webhook-modal-overlay'); Toast.success('Webhook criado com sucesso'); } await WebhooksUI.load(); } catch (err) { Toast.error(`Erro ao salvar webhook: ${err.message}`); } }, async toggleActive(webhookId) { const webhook = WebhooksUI.webhooks.find((w) => w.id === webhookId); if (!webhook) return; try { await API.webhooks.update(webhookId, { active: !webhook.active }); Toast.success(webhook.active ? 'Webhook desativado' : 'Webhook ativado'); await WebhooksUI.load(); } catch (err) { Toast.error(`Erro ao atualizar webhook: ${err.message}`); } }, async delete(webhookId) { const confirmed = await Modal.confirm( 'Excluir webhook', 'Tem certeza que deseja excluir este webhook? Integrações que usam esta URL deixarão de funcionar.' ); if (!confirmed) return; try { await API.webhooks.delete(webhookId); Toast.success('Webhook excluído'); await WebhooksUI.load(); } catch (err) { Toast.error(`Erro ao excluir webhook: ${err.message}`); } }, async copyUrl(url) { try { await navigator.clipboard.writeText(url); Toast.success('URL copiada'); } catch { Toast.error('Não foi possível copiar a URL'); } }, async copyCurl(webhookId) { const webhook = WebhooksUI.webhooks.find((w) => w.id === webhookId); if (!webhook) return; const hookUrl = `${window.location.origin}/hook/${webhook.token}`; const targetName = WebhooksUI._resolveTargetName(webhook); let payload; if (webhook.targetType === 'pipeline') { payload = JSON.stringify({ input: 'Texto de entrada para o pipeline', workingDirectory: '/caminho/do/projeto (opcional)', }, null, 2); } else { payload = JSON.stringify({ task: 'Descreva a tarefa a ser executada', instructions: 'Instruções adicionais (opcional)', }, null, 2); } const curl = `curl -X POST '${hookUrl}' \\\n -H 'Content-Type: application/json' \\\n -d '${payload}'`; try { await navigator.clipboard.writeText(curl); Toast.success('cURL copiado'); } catch { Toast.error('Não foi possível copiar o cURL'); } }, }; window.WebhooksUI = WebhooksUI;