// Auth: connect/disconnect Adobe Sign and Docusign, auth status chips import { api } from './api.js'; import { state, setState } from './state.js'; import { escHtml } from './utils.js'; // ── Refresh auth state and update chips ──────────────────────────────────── export async function refreshAuth() { try { const data = await api.auth.status(); setState('auth', { adobe: !!data.adobe, docusign: !!data.docusign, adobeLabel: data.adobe_label || 'Adobe Sign', docusignLabel: data.docusign_label || 'Docusign', }); } catch (e) { console.warn('Auth status failed:', e.message); } renderAuthChips(); } // ── Render connection pills in top bar ───────────────────────────────────── export function renderAuthChips() { renderChip('chip-adobe', state.auth.adobe, 'Adobe Sign', onClickAdobe); renderChip('chip-docusign', state.auth.docusign, 'Docusign', onClickDocusign); } function renderChip(id, connected, label, onClick) { const el = document.getElementById(id); if (!el) return; el.className = 'conn-pill ' + (connected ? 'connected' : 'disconnected'); el.innerHTML = `${escHtml(label)}${connected ? '▾' : ''}`; el.onclick = onClick; } // ── Click handlers ───────────────────────────────────────────────────────── async function onClickAdobe() { if (state.auth.adobe) { showAuthMenu('adobe', 'chip-adobe'); } else { await connectAdobeEnv(); } } async function onClickDocusign() { if (state.auth.docusign) { showAuthMenu('docusign', 'chip-docusign'); } else { await connectDocusign(); } } export async function disconnectPlatform(platform, opts = {}) { const { silent = false, skipRefresh = false } = opts; setChipConnecting(platform === 'adobe' ? 'chip-adobe' : 'chip-docusign'); try { await api.auth.disconnect(platform); setState('auth', { ...state.auth, [platform]: false }); renderAuthChips(); if (!skipRefresh) { const { refreshTemplates } = await import('./templates.js'); refreshTemplates(); } if (!silent) { showToast(`${platform === 'adobe' ? 'Adobe Sign' : 'Docusign'} disconnected.`, 'info'); } } catch (e) { console.error('Disconnect failed:', e.message); renderAuthChips(); if (!silent) { showToast(`Disconnect failed: ${e.message}`, 'error'); } } } export async function switchAccount(platform) { closeAuthMenu(); await disconnectPlatform(platform, { silent: true, skipRefresh: true }); if (platform === 'docusign') { showToast('Starting a fresh Docusign authorization. If Docusign signs you in automatically, sign out there and try again to choose a different account.', 'info'); window.location.href = '/api/auth/docusign/start'; return; } if (platform === 'adobe') { showToast('Adobe Sign disconnected. Reconnect to continue.', 'info'); await connectAdobeEnv(); } } async function connectAdobeEnv() { closeAuthMenu(); setChipConnecting('chip-adobe'); try { const data = await api.auth.connectAdobe(); if (data.connected) { setState('auth', { ...state.auth, adobe: true }); renderAuthChips(); const { refreshTemplates } = await import('./templates.js'); refreshTemplates(); } else if (data.error && data.error.includes('No Adobe Sign credentials')) { renderAuthChips(); showAdobeOAuthDialog(); } else { renderAuthChips(); showToast('Adobe Sign error: ' + (data.error || 'unknown'), 'error'); } } catch (e) { renderAuthChips(); showAdobeOAuthDialog(); } } async function connectDocusign() { closeAuthMenu(); setChipConnecting('chip-docusign'); try { const data = await api.auth.connectDocusign(); if (data.connected) { setState('auth', { ...state.auth, docusign: true }); renderAuthChips(); const { refreshTemplates } = await import('./templates.js'); refreshTemplates(); } else if (data.authorization_required && data.authorization_url) { window.location.href = data.authorization_url; } else { renderAuthChips(); showToast('Docusign error: ' + (data.error || 'unknown'), 'error'); } } catch (e) { renderAuthChips(); showToast('Docusign connection failed: ' + e.message, 'error'); } } function setChipConnecting(id) { const el = document.getElementById(id); if (!el) return; el.className = 'conn-pill connecting'; el.innerHTML = ``; } function closeAuthMenu() { document.getElementById('auth-chip-menu')?.remove(); document.removeEventListener('click', onDocumentClickCloseMenu, true); document.removeEventListener('keydown', onEscapeCloseMenu, true); } function onDocumentClickCloseMenu(event) { const menu = document.getElementById('auth-chip-menu'); if (!menu) return; if (menu.contains(event.target)) return; if (event.target.closest('.conn-pill')) return; closeAuthMenu(); } function onEscapeCloseMenu(event) { if (event.key === 'Escape') closeAuthMenu(); } function showAuthMenu(platform, anchorId) { const anchor = document.getElementById(anchorId); if (!anchor) return; const existing = document.getElementById('auth-chip-menu'); if (existing && existing.dataset.platform === platform && existing.dataset.anchorId === anchorId) { closeAuthMenu(); return; } closeAuthMenu(); const rect = anchor.getBoundingClientRect(); const menu = document.createElement('div'); menu.id = 'auth-chip-menu'; menu.dataset.platform = platform; menu.dataset.anchorId = anchorId; menu.className = 'auth-chip-menu'; menu.style.top = `${rect.bottom + 8}px`; menu.style.left = `${Math.max(12, rect.right - 220)}px`; const accountLabel = platform === 'docusign' ? 'Docusign' : 'Adobe Sign'; const switchLabel = platform === 'docusign' ? 'Switch Account' : 'Reconnect'; const switchHelp = platform === 'docusign' ? 'Clear this browser session and start a fresh login flow.' : 'Disconnect and reconnect Adobe Sign.'; menu.innerHTML = `
`; menu.querySelector('[data-action="disconnect"]')?.addEventListener('click', async () => { closeAuthMenu(); await disconnectPlatform(platform); }); menu.querySelector('[data-action="switch"]')?.addEventListener('click', async () => { await switchAccount(platform); }); document.body.appendChild(menu); document.addEventListener('click', onDocumentClickCloseMenu, true); document.addEventListener('keydown', onEscapeCloseMenu, true); } // ── Adobe OAuth dialog (manual redirect URL paste) ───────────────────────── async function showAdobeOAuthDialog() { const { url } = await api.auth.adobeUrl().catch(() => ({ url: '#' })); const existing = document.getElementById('adobe-auth-dialog'); if (existing) existing.remove(); const dialog = document.createElement('div'); dialog.id = 'adobe-auth-dialog'; dialog.innerHTML = `