ligbox-ops-platform/deploy/vm112-wizard/patch-wizard-project-ui.py
Ligbox Spec Hub 038fb8f7ce feat(dns): Spec 037 DNS Viewer — Desk, Console e patches Wizard V4
Entrega read-only de apontamentos DNS (Cloudflare, OpenPanel BIND, público)
no Desk e Console /admin/dominio, com spec, scripts de rollback e patches
VM112 para painel lateral no passo DNS do onboarding (deploy wizard pendente).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-25 16:36:25 +00:00

77 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""Wizard UI — provision-email + painel credenciais proj_*."""
from pathlib import Path
import re
APP = Path("/opt/ligbox-wizard/frontend/src/App.jsx")
text = APP.read_text(encoding="utf-8")
if "projectCredentials" not in text:
text = text.replace(
" const [byoToken, setByoToken] = useState('')",
" const [byoToken, setByoToken] = useState('')\n"
" const [projectCredentials, setProjectCredentials] = useState(null)",
)
PROVISION_FN = '''
async function ensureProjectEmail() {
if (projectCredentials?.ligbox_project_email) return projectCredentials
const data = await api('/onboarding/project/provision-email', {
method: 'POST',
body: JSON.stringify({ domain, display_name: companyLabelFromDomain(domain) }),
})
setProjectCredentials(data)
return data
}
'''
if "ensureProjectEmail" not in text:
text = text.replace(" async function choosePortalDns() {", PROVISION_FN + " async function choosePortalDns() {")
# inject ensureProjectEmail at start of choosePortalDns
if "await ensureProjectEmail()" not in text:
text = text.replace(
" startBusy('dns_zone')\n try {\n const resolved = dnsResolve",
" startBusy('dns_zone')\n try {\n const proj = await ensureProjectEmail()\n const resolved = dnsResolve",
)
PANEL = '''
{projectCredentials?.ligbox_project_email && (
<WizardStatusPanel variant="info" icon={ShieldCheck} title="Credenciais do projeto Ligbox">
<p>
E-mail: <strong>{projectCredentials.ligbox_project_email}</strong>
<br />
Webmail: <a href="https://mail.ligbox.com.br/" target="_blank" rel="noreferrer">mail.ligbox.com.br</a>
</p>
{projectCredentials.password_available && !projectCredentials.password && (
<ActionDoneButton
label="Mostrar senha do projeto (uma vez)"
onClick={async () => {
try {
const rev = await api(`/onboarding/project/${domain}/reveal-password`, { method: 'POST' })
setProjectCredentials((p) => ({ ...p, password: rev.password, password_shown: true }))
} catch (e) {
setError(e.message)
}
}}
/>
)}
{projectCredentials.password && (
<p className="sub">
Senha: <code>{projectCredentials.password}</code> — guarde agora.
</p>
)}
</WizardStatusPanel>
)}
'''
if "Credenciais do projeto Ligbox" not in text:
text = text.replace(
" {portalDnsApplied && (",
PANEL + " {portalDnsApplied && (",
)
APP.write_text(text, encoding="utf-8")
print("App.jsx project panel OK")