// Dual Portal Demo Extension UI // Uses @alga/extension-iframe-sdk for postMessage communication import { IframeBridge } from '@alga-psa/extension-iframe-sdk'; // Initialize the SDK bridge const bridge = new IframeBridge({ // Allow wildcard for development; in production the SDK validates parent origin devAllowWildcard: true, }); // Parse URL parameters const params = new URLSearchParams(window.location.search); const extensionId = params.get('extensionId') || 'unknown'; const tenant = params.get('tenant') || 'unknown'; const path = params.get('path') || '/'; // Detect which portal we're running in based on the parent URL const referrer = document.referrer || ''; const isClientPortal = referrer.includes('/client-portal/') || window.location.href.includes('/client-portal/'); const portalType = isClientPortal ? 'client' : 'msp'; // DOM elements const ctxEl = document.getElementById('ctx'); const handlerEl = document.getElementById('handler-result'); const badgeEl = document.getElementById('badge'); const portalIndicatorEl = document.getElementById('portal-indicator'); const featuresEl = document.getElementById('features'); /** * Apply portal-specific styling and content */ function applyPortalContext(): void { document.body.classList.add(isClientPortal ? 'client-portal' : 'msp-portal'); if (badgeEl) { badgeEl.textContent = isClientPortal ? 'Client Portal' : 'MSP Portal'; } if (portalIndicatorEl) { const icon = isClientPortal ? ` ` : ` `; const message = isClientPortal ? 'Running in Client Portal context' : 'Running in MSP Portal context'; portalIndicatorEl.innerHTML = `${icon}${message}`; } if (featuresEl) { const checkIcon = ` `; const mspFeatures = [ 'View and manage all client data', 'Access administrative settings', 'Configure extension for all tenants', 'View usage analytics and reports', 'Manage user permissions', ]; const clientFeatures = [ 'View your own data only', 'Submit support requests', 'Access self-service portal', 'View your billing information', 'Update account preferences', ]; const features = isClientPortal ? clientFeatures : mspFeatures; featuresEl.innerHTML = features.map((f) => `
  • ${checkIcon}${f}
  • `).join(''); } } /** * Update context display */ function updateContextDisplay(): void { if (ctxEl) { ctxEl.innerHTML = `
    Portal ${isClientPortal ? 'Client Portal' : 'MSP Portal'}
    Extension ID ${extensionId}
    Tenant ${tenant}
    Path ${path}
    `; } } /** * Helper to call proxy and parse JSON response */ async function callProxyJson(route: string, payload?: unknown): Promise { // Encode payload to Uint8Array if provided let payloadBytes: Uint8Array | undefined; if (payload !== undefined) { const jsonStr = JSON.stringify(payload); payloadBytes = new TextEncoder().encode(jsonStr); } // Use the SDK's uiProxy to make the call const responseBytes = await bridge.uiProxy.callRoute(route, payloadBytes); // Decode response const text = new TextDecoder().decode(responseBytes); return text.length ? JSON.parse(text) : undefined; } interface HandlerResponse { ok?: boolean; message?: string; user?: { userName: string; userEmail: string; userType: string; clientId?: string; }; userError?: string; portalType?: string; context?: { tenantId?: string; extensionId?: string; requestId?: string; }; timestamp?: string; version?: string; } /** * Call the WASM handler via the SDK's uiProxy */ async function callHandler(): Promise { if (handlerEl) { handlerEl.innerHTML = `Calling handler via proxy...`; } try { console.log('[dual-portal-demo] Calling handler via SDK proxy'); const data = await callProxyJson('/', { portalType }); if (!data) { if (handlerEl) { handlerEl.innerHTML = `
    Empty response from handler
    `; } return; } // Format user info for display const userDisplay = data.user ? `${data.user.userName} (${data.user.userEmail})` : data.userError ? `Error: ${data.userError}` : 'N/A'; const userTypeDisplay = data.user?.userType || 'N/A'; const clientIdDisplay = data.user?.clientId || 'N/A'; if (handlerEl) { handlerEl.innerHTML = `
    Handler Response (via SDK Proxy)
    Message ${data.message || 'N/A'}
    Current User ${userDisplay}
    User Type ${userTypeDisplay}
    Client ID ${clientIdDisplay}
    Portal Type ${data.portalType || portalType}
    Tenant ID ${data.context?.tenantId || 'N/A'}
    Extension ID ${data.context?.extensionId || 'N/A'}
    Request ID ${data.context?.requestId || 'N/A'}
    Timestamp ${data.timestamp || 'N/A'}
    Version ${data.version || 'N/A'}
    `; } console.log('[dual-portal-demo] Handler success via SDK proxy', data); } catch (err) { const message = err instanceof Error ? err.message : String(err); if (handlerEl) { handlerEl.innerHTML = `
    Error: ${message}
    `; } console.error('[dual-portal-demo] Handler call failed', err); } } // Initialize on load window.addEventListener('load', () => { console.log(`[dual-portal-demo] Initializing in ${portalType} portal context (using SDK)`); applyPortalContext(); updateContextDisplay(); // Signal ready to host using the SDK bridge.ready(); // Call the handler callHandler(); });