besper-frontend-site-dev-main
Version:
Professional B-esper Frontend Site - Site-wide integration toolkit for full website bot deployment
1,139 lines (1,005 loc) • 33.9 kB
JavaScript
/**
* Home Page Script - Bulletproof loading pattern
* Welcome to our new platform experience
*/
class HomeNewPage {
constructor(options = {}) {
this.options = {
containerId: 'besper-site-content',
environment: 'prod',
...options,
};
this.initialized = false;
// BULLETPROOF: Defer all complex operations to avoid blocking class export
this.authService = null;
this.operatorsService = null;
this.isAuthenticated = false;
// Initialize auth safely in next tick to ensure class export completes first
if (typeof window !== 'undefined') {
setTimeout(() => {
this.initializeAuth();
}, 1);
}
}
/**
* Initialize authentication safely without blocking class export
*/
initializeAuth() {
try {
this.authService = this.getAuthService();
this.operatorsService = this.getOperatorsService();
} catch (error) {
console.warn('Auth initialization failed, using fallback:', error);
this.authService = this.createFallbackAuthService();
this.operatorsService = this.createFallbackOperatorsService();
}
}
/**
* Get authentication service from global scope or create simple fallback
*/
getAuthService() {
// Try to access global token auth service if available
if (typeof window !== 'undefined' && window.tokenAuthService) {
return window.tokenAuthService;
}
return this.createFallbackAuthService();
}
/**
* Get operators service from global scope or create simple fallback
*/
getOperatorsService() {
// Try to access global page operators service if available
if (typeof window !== 'undefined' && window.pageOperatorsService) {
return window.pageOperatorsService;
}
return this.createFallbackOperatorsService();
}
/**
* Create safe fallback auth service
*/
createFallbackAuthService() {
return {
isUserAuthenticated: () => {
try {
return (
typeof window !== 'undefined' &&
window.auth &&
typeof window.auth.getToken === 'function' &&
!!window.auth.getToken()
);
} catch (error) {
return false;
}
},
getToken: () => {
try {
if (
typeof window !== 'undefined' &&
window.auth &&
typeof window.auth.getToken === 'function'
) {
return window.auth.getToken();
}
} catch (error) {
console.warn('Token access failed:', error);
}
return null;
},
getUserPermission: key => {
try {
if (typeof window === 'undefined') return null;
const mappings = {
contactId: window.contact_id || window.user_contactid,
userName: window.user_name,
name: window.user_name,
userEmail: window.user_email,
email: window.user_email,
workspaceId: window.workspace_id,
accountId: window.account_id,
subscriptionId: window.subscription_id,
};
return mappings[key] || null;
} catch (error) {
console.warn('User permission access failed:', error);
return null;
}
},
};
}
/**
* Create safe fallback operators service
*/
createFallbackOperatorsService() {
return {
callOperator: async () => {
console.warn(
'Operators service not available, returning empty response'
);
return { success: false, message: 'Service not available' };
},
};
}
/**
* Initialize the page - IMMEDIATE RENDERING
* Shows UI instantly without waiting for authentication
*/
async initialize(_data = {}) {
if (this.initialized) return;
try {
// IMMEDIATE: Show the UI without any loading delays
this.renderImmediateUI();
// IMMEDIATE: Setup basic interactions
this.setupInteractions();
this.initialized = true;
// DEFERRED: Initialize authentication features in background
this.initializeAuthenticationFeaturesInBackground();
} catch (error) {
console.error('Error initializing home page:', error);
this.showError(error);
}
}
/**
* Render immediate UI structure - shows content instantly
*/
renderImmediateUI() {
const container = document.getElementById(this.options.containerId);
if (!container) return;
// Clear any existing loading indicators
container.innerHTML = '';
// Show immediate home interface
container.innerHTML = `
<div style="background: #f8f9fa; color: #022d54; font-family: Arial, sans-serif;">
<div style="max-width: 1200px; margin: 0 auto; padding: 2rem 1rem;">
<!-- Header -->
<div style="margin-bottom: 2rem;">
<h1 style="color: #022d54; font-weight: 300; font-size: 28px; margin-bottom: 0.5rem;">Home</h1>
<p style="color: #6c757d; font-size: 14px; margin: 0;">Welcome to our new platform experience</p>
</div>
<!-- Main Content Area with Skeleton Loading -->
<div style="background: white; border-radius: 8px; border: 1px solid #e0e0e0; overflow: hidden;">
<div style="padding: 1rem; border-bottom: 1px solid #e0e0e0;">
<h3 style="margin: 0; color: #022d54; font-size: 16px; font-weight: 500;">Loading Content...</h3>
</div>
<div id="page-content-area" style="padding: 2rem;">
<!-- Skeleton Loading Animation -->
<div style="height: 20px; background: #e0e0e0; border-radius: 4px; margin-bottom: 1rem; animation: pulse 1.5s ease-in-out infinite;"></div>
<div style="height: 20px; background: #e0e0e0; border-radius: 4px; margin-bottom: 1rem; width: 80%; animation: pulse 1.5s ease-in-out infinite;"></div>
<div style="height: 20px; background: #e0e0e0; border-radius: 4px; margin-bottom: 1rem; width: 60%; animation: pulse 1.5s ease-in-out infinite;"></div>
<div style="height: 100px; background: #e0e0e0; border-radius: 4px; animation: pulse 1.5s ease-in-out infinite;"></div>
</div>
</div>
</div>
</div>
<!-- Skeleton Loading Animation -->
<style>
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
</style>
`;
}
/**
* Setup interactions - immediate setup without waiting
*/
setupInteractions() {
// TODO: Add page-specific interactions here
console.log('Home interactions ready');
}
/**
* Initialize authentication features completely in background - NO UI BLOCKING
*/
async initializeAuthenticationFeaturesInBackground() {
// Use requestIdleCallback for true background processing
const initializeAuth = () => {
try {
// Ensure services are ready
if (!this.authService) {
this.initializeAuth();
}
// Check authentication status without blocking
if (this.authService) {
this.isAuthenticated = this.authService.isUserAuthenticated();
if (this.isAuthenticated) {
// Load data in background
this.loadDataInBackground();
} else {
this.showUnauthenticatedView();
}
}
} catch (error) {
console.warn(
'Background authentication features initialization failed:',
error
);
// Continue silently - authentication is not critical for UI display
}
};
// Use requestIdleCallback for non-blocking background execution
if (typeof requestIdleCallback !== 'undefined') {
requestIdleCallback(initializeAuth, { timeout: 5000 });
} else {
// Fallback for browsers without requestIdleCallback
setTimeout(initializeAuth, 50);
}
}
/**
* Load data in background
*/
async loadDataInBackground() {
try {
console.log('Loading home data in background...');
// TODO: Replace with actual data loading
// Example:
// const data = await this.fetchData();
// this.updateUIWithData(data);
// For now, just remove skeleton loading after delay
setTimeout(() => {
this.updateUIWithActualContent();
}, 1000);
} catch (error) {
console.error('Background data loading failed:', error);
}
}
/**
* Update UI with actual content (replace skeleton loading)
* Full-featured home dashboard interface based on new_home_ui.html template
*/
updateUIWithActualContent() {
const contentArea = document.getElementById('page-content-area');
if (contentArea) {
// Get user's preferred language
const language = this.getCurrentLanguage();
const translations = this.getTranslations(language);
contentArea.innerHTML = this.generateHomeDashboardHTML(translations);
// Initialize home dashboard functionality
this.initializeHomeDashboardFeatures(translations);
}
}
/**
* Get current language (German or English)
*/
getCurrentLanguage() {
// Check URL parameter first
const urlParams = new URLSearchParams(window.location.search);
const langParam = urlParams.get('lang');
if (langParam && ['en', 'de'].includes(langParam)) {
return langParam;
}
// Check localStorage
const storedLang = localStorage.getItem('bsp_language');
if (storedLang && ['en', 'de'].includes(storedLang)) {
return storedLang;
}
// Check browser language
const browserLang = navigator.language.toLowerCase();
if (browserLang.startsWith('de')) {
return 'de';
}
// Default to English
return 'en';
}
/**
* Get translations for the specified language
*/
getTranslations(language) {
const translations = {
en: {
title: 'Welcome to B-esper',
subtitle: 'Your intelligent automation platform',
totalWorkspaces: 'Total Workspaces',
activeBots: 'Active Bots',
monthlyProcessed: 'Monthly Processed',
avgResponseTime: 'Avg Response Time',
workspacesManaged: 'workspaces managed',
botsRunning: 'bots running',
documentsProcessed: 'documents processed',
responseTime: 'average response',
quickActions: 'Quick Actions',
createBot: 'Create New Bot',
manageWorkspaces: 'Manage Workspaces',
viewAnalytics: 'View Analytics',
recentActivity: 'Recent Activity',
systemHealth: 'System Health',
noRecentActivity: 'No recent activity',
viewAllActivity: 'View All Activity',
cpuUsage: 'CPU Usage',
memoryUsage: 'Memory Usage',
apiCalls: 'API Calls Today',
uptime: 'System Uptime',
},
de: {
title: 'Willkommen bei B-esper',
subtitle: 'Ihre intelligente Automatisierungsplattform',
totalWorkspaces: 'Gesamte Arbeitsbereiche',
activeBots: 'Aktive Bots',
monthlyProcessed: 'Monatlich verarbeitet',
avgResponseTime: 'Durchschn. Antwortzeit',
workspacesManaged: 'verwaltete Arbeitsbereiche',
botsRunning: 'laufende Bots',
documentsProcessed: 'verarbeitete Dokumente',
responseTime: 'durchschnittliche Antwort',
quickActions: 'Schnellaktionen',
createBot: 'Neuen Bot erstellen',
manageWorkspaces: 'Arbeitsbereiche verwalten',
viewAnalytics: 'Analysen anzeigen',
recentActivity: 'Letzte Aktivität',
systemHealth: 'Systemzustand',
noRecentActivity: 'Keine kürzliche Aktivität',
viewAllActivity: 'Alle Aktivitäten anzeigen',
cpuUsage: 'CPU-Auslastung',
memoryUsage: 'Speicherauslastung',
apiCalls: 'API-Aufrufe heute',
uptime: 'System-Betriebszeit',
},
};
return translations[language] || translations.en;
}
/**
* Generate the complete home dashboard HTML interface
*/
generateHomeDashboardHTML(translations) {
return `
<div class="dashboard-container">
<!-- Header -->
<div class="dashboard-header">
<div class="header-left">
<h1>${translations.title}</h1>
<div class="subtitle">${translations.subtitle}</div>
</div>
<div class="header-actions">
<select class="language-selector" onchange="window.homeNewPage.changeLanguage(this.value)">
<option value="en" ${this.getCurrentLanguage() === 'en' ? 'selected' : ''}>English</option>
<option value="de" ${this.getCurrentLanguage() === 'de' ? 'selected' : ''}>Deutsch</option>
</select>
</div>
</div>
<!-- KPI Cards -->
<div class="kpi-grid">
<div class="kpi-card">
<div class="kpi-label">${translations.totalWorkspaces}</div>
<div class="kpi-value" id="totalWorkspaces">-</div>
<div class="kpi-change positive" id="workspacesChange">+2 ${translations.workspacesManaged}</div>
</div>
<div class="kpi-card">
<div class="kpi-label">${translations.activeBots}</div>
<div class="kpi-value" id="activeBots">-</div>
<div class="kpi-change positive" id="botsChange">+5 ${translations.botsRunning}</div>
</div>
<div class="kpi-card">
<div class="kpi-label">${translations.monthlyProcessed}</div>
<div class="kpi-value" id="monthlyProcessed">-</div>
<div class="kpi-change neutral" id="processedChange">1.2k ${translations.documentsProcessed}</div>
</div>
<div class="kpi-card">
<div class="kpi-label">${translations.avgResponseTime}</div>
<div class="kpi-value" id="avgResponseTime">-</div>
<div class="kpi-change positive" id="responseTimeChange">245ms ${translations.responseTime}</div>
</div>
</div>
<!-- Main Dashboard Grid -->
<div class="dashboard-grid">
<!-- Quick Actions Card -->
<div class="dashboard-card">
<div class="card-header">
<h3>${translations.quickActions}</h3>
</div>
<div class="card-content">
<div class="quick-actions">
<button class="action-btn primary" onclick="window.homeNewPage.createBot()">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<path d="M8 14s1.5 2 4 2 4-2 4-2"/>
<line x1="9" y1="9" x2="9.01" y2="9"/>
<line x1="15" y1="9" x2="15.01" y2="9"/>
</svg>
${translations.createBot}
</button>
<button class="action-btn secondary" onclick="window.homeNewPage.manageWorkspaces()">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
<line x1="9" y1="9" x2="15" y2="9"/>
<line x1="9" y1="15" x2="15" y2="15"/>
</svg>
${translations.manageWorkspaces}
</button>
<button class="action-btn secondary" onclick="window.homeNewPage.viewAnalytics()">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 3v18h18"/>
<path d="M18.7 8l-5.1 5.2-2.8-2.7L7 14.3"/>
</svg>
${translations.viewAnalytics}
</button>
</div>
</div>
</div>
<!-- Recent Activity Card -->
<div class="dashboard-card">
<div class="card-header">
<h3>${translations.recentActivity}</h3>
<button class="btn-link" onclick="window.homeNewPage.viewAllActivity()">
${translations.viewAllActivity}
</button>
</div>
<div class="card-content">
<div class="activity-list" id="activityList">
<!-- Activity items will be populated here -->
</div>
</div>
</div>
<!-- System Health Card -->
<div class="dashboard-card">
<div class="card-header">
<h3>${translations.systemHealth}</h3>
</div>
<div class="card-content">
<div class="health-metrics">
<div class="metric-item">
<div class="metric-label">${translations.cpuUsage}</div>
<div class="metric-bar">
<div class="metric-fill" style="width: 45%" data-value="45"></div>
</div>
<div class="metric-value">45%</div>
</div>
<div class="metric-item">
<div class="metric-label">${translations.memoryUsage}</div>
<div class="metric-bar">
<div class="metric-fill" style="width: 68%" data-value="68"></div>
</div>
<div class="metric-value">68%</div>
</div>
<div class="metric-item">
<div class="metric-label">${translations.apiCalls}</div>
<div class="metric-bar">
<div class="metric-fill" style="width: 32%" data-value="32"></div>
</div>
<div class="metric-value">1.2k</div>
</div>
<div class="metric-item">
<div class="metric-label">${translations.uptime}</div>
<div class="metric-bar">
<div class="metric-fill success" style="width: 99%" data-value="99"></div>
</div>
<div class="metric-value">99.9%</div>
</div>
</div>
</div>
</div>
</div>
${this.generateHomeDashboardCSS()}
</div>
`;
}
/**
* Generate CSS styles for the home dashboard interface
*/
generateHomeDashboardCSS() {
return `
<style>
.dashboard-container {
max-width: 1400px;
margin: 0 auto;
padding: 32px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
background: #f8f9fa;
color: #022d54;
line-height: 1.6;
}
.dashboard-header {
margin-bottom: 40px;
display: flex;
justify-content: space-between;
align-items: center;
}
.dashboard-header h1 {
font-size: 28px;
font-weight: 300;
color: #022d54;
margin-bottom: 8px;
letter-spacing: -0.5px;
margin: 0;
}
.subtitle {
color: #6c757d;
font-size: 14px;
}
.header-actions {
display: flex;
gap: 12px;
align-items: center;
}
.language-selector {
padding: 8px 12px;
border: 1px solid #e0e0e0;
border-radius: 4px;
font-size: 14px;
background: white;
}
/* KPI Cards */
.kpi-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 40px;
}
.kpi-card {
background: white;
padding: 24px;
border-radius: 8px;
border: 1px solid #e0e0e0;
transition: all 0.2s ease;
}
.kpi-card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
transform: translateY(-2px);
}
.kpi-label {
font-size: 12px;
text-transform: uppercase;
color: #6c757d;
letter-spacing: 0.5px;
margin-bottom: 8px;
}
.kpi-value {
font-size: 32px;
font-weight: 600;
color: #022d54;
line-height: 1;
margin-bottom: 12px;
}
.kpi-change {
font-size: 13px;
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
}
.kpi-change.positive {
color: #10b981;
background: #d1fae5;
}
.kpi-change.negative {
color: #f59e0b;
background: #fef3c7;
}
.kpi-change.neutral {
color: #6b7280;
background: #f3f4f6;
}
/* Dashboard Grid */
.dashboard-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 24px;
}
.dashboard-card {
background: white;
border-radius: 8px;
border: 1px solid #e0e0e0;
overflow: hidden;
}
.card-header {
padding: 20px 24px;
border-bottom: 1px solid #e0e0e0;
display: flex;
justify-content: space-between;
align-items: center;
}
.card-header h3 {
font-size: 16px;
font-weight: 500;
color: #022d54;
margin: 0;
}
.btn-link {
color: #022d54;
text-decoration: none;
font-size: 14px;
font-weight: 500;
border: none;
background: none;
cursor: pointer;
transition: color 0.2s;
}
.btn-link:hover {
color: #011831;
}
.card-content {
padding: 24px;
}
/* Quick Actions */
.quick-actions {
display: flex;
flex-direction: column;
gap: 12px;
}
.action-btn {
display: flex;
align-items: center;
gap: 12px;
padding: 16px 20px;
border: none;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
text-align: left;
width: 100%;
}
.action-btn.primary {
background: #022d54;
color: white;
}
.action-btn.primary:hover {
background: #011831;
}
.action-btn.secondary {
background: #f8f9fa;
color: #022d54;
border: 1px solid #e0e0e0;
}
.action-btn.secondary:hover {
background: #e9ecef;
border-color: #6c757d;
}
/* Activity List */
.activity-list {
max-height: 300px;
overflow-y: auto;
}
.activity-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 0;
border-bottom: 1px solid #f0f0f0;
}
.activity-item:last-child {
border-bottom: none;
}
.activity-icon {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, #022d54 0%, #033e6b 100%);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 14px;
font-weight: 600;
}
.activity-content {
flex: 1;
}
.activity-title {
font-weight: 500;
color: #022d54;
margin-bottom: 2px;
}
.activity-meta {
font-size: 12px;
color: #6c757d;
}
.activity-time {
font-size: 12px;
color: #6c757d;
}
/* Health Metrics */
.health-metrics {
display: flex;
flex-direction: column;
gap: 16px;
}
.metric-item {
display: flex;
align-items: center;
gap: 12px;
}
.metric-label {
flex: 0 0 120px;
font-size: 13px;
color: #6c757d;
}
.metric-bar {
flex: 1;
height: 8px;
background: #f0f0f0;
border-radius: 4px;
overflow: hidden;
}
.metric-fill {
height: 100%;
background: linear-gradient(90deg, #10b981 0%, #059669 100%);
border-radius: 4px;
transition: width 0.3s ease;
}
.metric-fill.success {
background: linear-gradient(90deg, #10b981 0%, #059669 100%);
}
.metric-value {
flex: 0 0 50px;
text-align: right;
font-size: 13px;
font-weight: 500;
color: #022d54;
}
.empty-activity {
text-align: center;
padding: 40px 20px;
color: #6c757d;
}
.empty-activity svg {
width: 48px;
height: 48px;
margin-bottom: 16px;
stroke: #cbd5e0;
}
@media (max-width: 768px) {
.dashboard-container {
padding: 16px;
}
.dashboard-header {
flex-direction: column;
align-items: flex-start;
gap: 16px;
}
.kpi-grid {
grid-template-columns: 1fr;
}
.dashboard-grid {
grid-template-columns: 1fr;
}
.metric-item {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.metric-label {
flex: none;
}
.metric-bar {
width: 100%;
}
.metric-value {
flex: none;
text-align: left;
}
}
</style>
`;
}
/**
* Initialize home dashboard features
*/
initializeHomeDashboardFeatures(translations) {
this.translations = translations;
this.dashboardData = {
kpis: {
totalWorkspaces: 0,
activeBots: 0,
monthlyProcessed: 0,
avgResponseTime: 0,
},
activities: [],
};
// Load dashboard data from APIM APIs
this.loadDashboardDataFromAPIM();
}
/**
* Load dashboard data from APIM using operators
*/
async loadDashboardDataFromAPIM() {
try {
console.log(
'[HomeDashboard] Loading dashboard data using APIM operators...'
);
// Ensure authentication is available
if (!this.authService?.isUserAuthenticated()) {
throw new Error('Authentication required for dashboard operations');
}
// Load dashboard KPIs using APIM operators
const kpiResponse = await this.operatorsService.callOperator(
'dashboard',
'get_kpis',
{
authData: this.authService.getAuthData(),
}
);
// Load dashboard activity using APIM operators
const activityResponse = await this.operatorsService.callOperator(
'dashboard',
'get_activity',
{
authData: this.authService.getAuthData(),
limit: 10,
}
);
if (!kpiResponse.success && !activityResponse.success) {
throw new Error('Failed to load dashboard data from APIM operators');
}
// Process the dashboard data
this.processDashboardData(kpiResponse.data, activityResponse.data);
console.log(
'[HomeDashboard] [SUCCESS] Successfully loaded dashboard data using APIM operators'
);
} catch (error) {
console.error(
'[HomeDashboard] [ERROR] Failed to load dashboard data:',
error
);
throw error; // Re-throw error instead of falling back to sample data
}
}
/**
* Process dashboard data from APIM operators response
*/
processDashboardData(kpiData, activityData) {
this.dashboardData = {
kpis: {
totalWorkspaces: kpiData?.totalWorkspaces || 0,
activeBots: kpiData?.activeBots || 0,
monthlyProcessed: kpiData?.monthlyProcessed || '0',
avgResponseTime: kpiData?.avgResponseTime || '0ms',
},
activities: activityData?.activities || [],
};
this.updateKPIDisplay();
this.renderActivity();
}
/**
* DEPRECATED: Load sample dashboard data for demonstration
* This method should never be called in production
*/
loadSampleDashboardData() {
console.warn(
'[HomeDashboard] loadSampleDashboardData is deprecated and should not be used'
);
throw new Error(
'Sample dashboard data is not allowed. Use APIM operators instead.'
);
}
/**
* Update KPI display
*/
updateKPIDisplay() {
const kpis = this.dashboardData.kpis;
const totalWorkspacesEl = document.getElementById('totalWorkspaces');
const activeBotsEl = document.getElementById('activeBots');
const monthlyProcessedEl = document.getElementById('monthlyProcessed');
const avgResponseTimeEl = document.getElementById('avgResponseTime');
if (totalWorkspacesEl) totalWorkspacesEl.textContent = kpis.totalWorkspaces;
if (activeBotsEl) activeBotsEl.textContent = kpis.activeBots;
if (monthlyProcessedEl)
monthlyProcessedEl.textContent = kpis.monthlyProcessed;
if (avgResponseTimeEl) avgResponseTimeEl.textContent = kpis.avgResponseTime;
}
/**
* Render activity list
*/
renderActivity() {
const activityList = document.getElementById('activityList');
if (!activityList) return;
if (this.dashboardData.activities.length === 0) {
activityList.innerHTML = `
<div class="empty-activity">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<div>${this.translations.noRecentActivity}</div>
</div>
`;
return;
}
activityList.innerHTML = this.dashboardData.activities
.map(
activity => `
<div class="activity-item">
<div class="activity-icon">${activity.icon}</div>
<div class="activity-content">
<div class="activity-title">${activity.title}</div>
<div class="activity-meta">${activity.meta}</div>
</div>
<div class="activity-time">${activity.time}</div>
</div>
`
)
.join('');
}
/**
* Change language
*/
changeLanguage(language) {
localStorage.setItem('bsp_language', language);
this.updateUIWithActualContent(); // Re-render with new language
}
/**
* Quick action handlers
*/
createBot() {
console.log('Create new bot');
// TODO: Navigate to bot creation page or integrate with APIM bot creation API
window.location.href = '/bot-management-new';
}
manageWorkspaces() {
console.log('Manage workspaces');
// TODO: Navigate to workspace management page
window.location.href = '/workspace-management-new';
}
viewAnalytics() {
console.log('View analytics');
// TODO: Navigate to analytics page
window.location.href = '/analytics';
}
viewAllActivity() {
console.log('View all activity');
// TODO: Navigate to activity page or show detailed activity view
alert('View all activity - integrate with APIM activity API');
}
/**
* Show unauthenticated view
*/
showUnauthenticatedView() {
const contentArea = document.getElementById('page-content-area');
if (contentArea) {
contentArea.innerHTML = `
<div style="text-align: center; padding: 2rem;">
<h2 style="color: #022d54;">Authentication Required</h2>
<p style="color: #6c757d;">Please log in to access home.</p>
</div>
`;
}
}
/**
* Show error message
*/
showError(error) {
const container = document.getElementById(this.options.containerId);
if (container) {
container.innerHTML = `
<div style="background: #f8f9fa; display: flex; align-items: center; justify-content: center;">
<div style="text-align: center; padding: 2rem; background: white; border-radius: 8px; border: 1px solid #e0e0e0; max-width: 500px;">
<h3 style="color: #d32f2f; margin-bottom: 1rem;">Error Loading Home</h3>
<p style="color: #6c757d; margin-bottom: 1.5rem;">${error.message || error}</p>
<button onclick="location.reload()" style="padding: 10px 20px; background: #022d54; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 14px;">
Try Again
</button>
</div>
</div>
`;
}
}
}
// BULLETPROOF EXPORT MECHANISM - Ensures class is always available
(function () {
'use strict';
// Multiple export strategies to ensure maximum compatibility
// Strategy 1: Direct window assignment (most reliable)
if (typeof window !== 'undefined') {
window.HomeNewPage = HomeNewPage;
// Also make instance globally accessible for method calls
window.homeNewPage = new HomeNewPage();
}
// Strategy 2: Module exports for Node.js environments
if (typeof module !== 'undefined' && module.exports) {
module.exports = HomeNewPage;
}
// Strategy 3: Global fallback
if (typeof global !== 'undefined') {
global.HomeNewPage = HomeNewPage;
}
// Strategy 4: AMD/RequireJS support
if (typeof define === 'function' && define.amd) {
define([], function () {
return HomeNewPage;
});
}
// Strategy 5: Self-executing verification
setTimeout(function () {
if (typeof window !== 'undefined' && !window.HomeNewPage) {
console.warn('HomeNewPage export failed, retrying...');
window.HomeNewPage = HomeNewPage;
}
}, 10);
})();