diff --git a/projects/ops-desk/frontend/assets/app.js b/projects/ops-desk/frontend/assets/app.js index 71a6fe4..660cdf0 100644 --- a/projects/ops-desk/frontend/assets/app.js +++ b/projects/ops-desk/frontend/assets/app.js @@ -84,9 +84,26 @@ const views = { }; function roleLabel(role) { - return { super_admin: 'Super Admin', ops_lead: 'Chefe Ops', technician: 'Suporte', noc: 'NOC' }[role] || role; + return ROLE_LABELS[role] || role; } +const ROLE_LABELS = { + super_admin: 'Super Admin', + ops_lead: 'Chefe Ops', + technician: 'Suporte', + noc: 'NOC', + sales_admin: 'Sales Admin', + sales_support: 'Sales Support', + finance: 'Financeiro', + marketing: 'Marketing', + seo: 'SEO', + developer: 'Developer', + devops: 'DevOps', + security_analyst: 'Segurança / SOC', + content_editor: 'Conteúdo / CMS', + agentic_operator: 'Operador Agentes IA', +}; + function statusLabel(status) { return { pending: 'pendente', @@ -1914,7 +1931,7 @@ async function renderTickets(options = {}) { state.tickets = tickets; listEl.innerHTML = state.tickets.length ? state.tickets.map(ticketRowHtml).join('') - : '
Nenhum ticket nesto filtro
'; + : 'Nenhum ticket neste filtro
'; listEl.querySelectorAll('.ticket-row').forEach((btn) => { btn.addEventListener('click', () => { state.selectedTicketId = Number(btn.dataset.id); @@ -2568,6 +2585,16 @@ function roleBadgeHtml(role) { ops_lead: 'role-lead', technician: 'role-tech', noc: 'role-noc', + sales_admin: 'role-sales-admin', + sales_support: 'role-sales-support', + finance: 'role-finance', + marketing: 'role-marketing', + seo: 'role-seo', + developer: 'role-developer', + devops: 'role-devops', + security_analyst: 'role-security', + content_editor: 'role-content', + agentic_operator: 'role-agentic', }[role] || 'role-default'; return `${esc(roleLabel(role))}`; } @@ -2582,14 +2609,34 @@ function mfaBadgeHtml(user) { } const ROLE_OPTIONS = [ - { value: 'super_admin', label: 'Super Admin' }, - { value: 'ops_lead', label: 'Chefe Ops' }, - { value: 'technician', label: 'Suporte' }, - { value: 'noc', label: 'NOC' }, + { value: 'super_admin', label: 'Super Admin', group: 'Ops' }, + { value: 'ops_lead', label: 'Chefe Ops', group: 'Ops' }, + { value: 'technician', label: 'Suporte', group: 'Ops' }, + { value: 'noc', label: 'NOC', group: 'Ops' }, + { value: 'sales_admin', label: 'Sales Admin', group: 'Comercial' }, + { value: 'sales_support', label: 'Sales Support', group: 'Comercial' }, + { value: 'finance', label: 'Financeiro', group: 'Negócio' }, + { value: 'marketing', label: 'Marketing', group: 'Negócio' }, + { value: 'seo', label: 'SEO', group: 'Negócio' }, + { value: 'developer', label: 'Developer', group: 'Plataforma' }, + { value: 'devops', label: 'DevOps', group: 'Plataforma' }, + { value: 'security_analyst', label: 'Segurança / SOC', group: 'Plataforma' }, + { value: 'content_editor', label: 'Conteúdo / CMS', group: 'Plataforma' }, + { value: 'agentic_operator', label: 'Operador Agentes IA', group: 'Plataforma' }, ]; const ASSIGNABLE_ROLE_OPTIONS = ROLE_OPTIONS.filter((r) => r.value !== 'super_admin'); +function registrationRoleSelectHtml(selected = 'technician') { + const groups = [...new Set(ASSIGNABLE_ROLE_OPTIONS.map((r) => r.group))]; + return groups.map((group) => { + const opts = ASSIGNABLE_ROLE_OPTIONS.filter((r) => r.group === group) + .map((r) => ``) + .join(''); + return ``; + }).join(''); +} + function roleSelectHtml(username, current, assignableOnly = true) { const options = assignableOnly && current !== 'super_admin' ? ASSIGNABLE_ROLE_OPTIONS @@ -2961,7 +3008,7 @@ async function renderModules() { } } -const REG_ROLE_LABELS = { ops_lead: 'Chefe Ops (admin)', technician: 'Técnico', noc: 'NOC' }; +const REG_ROLE_LABELS = ROLE_LABELS; async function renderMessages() { const el = document.getElementById('messages-content'); @@ -2986,9 +3033,7 @@ async function renderMessages() {
+ Suite openpanel-multidomain-api-confirm — provisiona 2 contas temporárias
+ (2 domínios na plataforma), valida listagem e remove. Pode executar quantas vezes quiser.
+ Script CLI: scripts/test-openpanel-multidomain-api.sh
+
Perfis: super_admin, devops, developer.
' : ''} +Alerta se gap > ${health.webhook_gap_alert_minutes || 15} min sem eventos VM112.
+Spec 028 · VM123 bridge :18087 · multidomínio · conta temporária com cleanup automático.
+Erro: ${esc(e.message)}
`; }