UNPKG

gentelella

Version:

Gentelella Admin is a free to use Bootstrap admin template

234 lines (198 loc) 7.15 kB
// CORE ESSENTIALS - Only what every page needs (jQuery-free) // Import and expose security utilities globally import { sanitizeHtml, sanitizeText, setSafeInnerHTML } from './utils/security.js'; window.sanitizeHtml = sanitizeHtml; window.sanitizeText = sanitizeText; window.setSafeInnerHTML = setSafeInnerHTML; // Import and expose validation utilities globally import * as ValidationUtils from './utils/validation.js'; window.ValidationUtils = ValidationUtils; // Import modern DOM utilities import DOM from './utils/dom-modern.js'; // Bootstrap 5 - Essential for all pages import * as bootstrap from 'bootstrap'; window.bootstrap = bootstrap; // Initialize Bootstrap tooltips and popovers document.addEventListener('DOMContentLoaded', function() { // Initialize all tooltips const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); const tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); // Initialize all popovers const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')); const popoverList = popoverTriggerList.map(function (popoverTriggerEl) { return new bootstrap.Popover(popoverTriggerEl); }); }); // Day.js for basic date manipulation - lightweight alternative to moment.js import dayjs from 'dayjs'; window.dayjs = dayjs; // NProgress (Loading bar) - used across many pages import NProgress from 'nprogress'; window.NProgress = NProgress; // Essential UI components are now handled by Bootstrap 5 and custom modules // Add global error boundary to catch and handle errors gracefully window.addEventListener('error', (event) => { console.error('🚨 Global error caught:', { message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, error: event.error }); // Could send to error tracking service in production if (process.env.NODE_ENV === 'production') { // Example: sendErrorToService(event.error); } }); // Performance monitoring for module loading window.moduleLoadTimes = new Map(); // Console logging in development only if (process.env.NODE_ENV === 'development') { const originalLog = console.log; const originalError = console.error; const originalWarn = console.warn; console.log = function(...args) { originalLog(`[${new Date().toLocaleTimeString()}]`, ...args); }; console.error = function(...args) { originalError(`[${new Date().toLocaleTimeString()}] ❌`, ...args); }; console.warn = function(...args) { originalWarn(`[${new Date().toLocaleTimeString()}] ⚠️`, ...args); }; } // Global styles (Bootstrap 5 + custom) import './main.scss'; // Core scripts that all pages need import './js/helpers/smartresize-modern.js'; import './js/sidebar-modern.js'; import './js/init-modern.js'; // Module loading cache to prevent duplicate loads window.moduleCache = new Map(); // Loading states for better UX window.showModuleLoadingState = function(moduleName) { const indicator = document.createElement('div'); indicator.id = `loading-${moduleName}`; indicator.style.cssText = ` position: fixed; top: 20px; right: 20px; background: #1ABB9C; color: white; padding: 10px 15px; border-radius: 4px; font-size: 13px; z-index: 10000; box-shadow: 0 2px 10px rgba(0,0,0,0.1); `; indicator.innerHTML = `<i class="fas fa-spinner fa-spin"></i> Loading ${moduleName}...`; document.body.appendChild(indicator); return indicator; }; window.hideModuleLoadingState = function(indicator) { if (indicator && indicator.parentNode) { indicator.style.opacity = '0'; indicator.style.transform = 'translateX(100%)'; indicator.style.transition = 'all 0.3s ease'; setTimeout(() => indicator.remove(), 300); } }; // Enhanced dynamic loader for page-specific modules window.loadModule = async function(moduleName, showLoading = true) { // Check cache first if (window.moduleCache.has(moduleName)) { return window.moduleCache.get(moduleName); } let loadingIndicator; if (showLoading) { loadingIndicator = window.showModuleLoadingState(moduleName); } try { const startTime = performance.now(); let module; switch(moduleName) { case 'charts': module = await import('./modules/charts.js'); break; case 'forms': module = await import('./modules/forms.js'); break; case 'tables': module = await import('./modules/tables.js'); break; case 'tables-modern': module = await import('./modules/tables-modern.js'); break; case 'ui': module = await import('./modules/ui-components.js'); break; case 'dashboard': module = await import('./modules/dashboard.js'); break; case 'weather': module = await import('./modules/weather.js'); break; case 'maps': module = await import('./modules/maps.js'); break; case 'echarts': module = await import('./modules/echarts-modern.js'); break; default: return null; } // Cache the module and record load time window.moduleCache.set(moduleName, module); const loadTime = performance.now() - startTime; window.moduleLoadTimes.set(moduleName, loadTime); return module; } catch (error) { if (process.env.NODE_ENV === 'development') { console.error(`Failed to load module ${moduleName}:`, error); } return null; } finally { if (loadingIndicator) { window.hideModuleLoadingState(loadingIndicator); } } }; // Utility to preload modules for better performance window.preloadModules = async function(moduleNames) { const promises = moduleNames.map(name => window.loadModule(name, false)); const results = await Promise.allSettled(promises); return results; }; // Debug utility to show module loading stats window.getModuleStats = function() { console.group('📊 Module Loading Statistics'); console.log('Cached modules:', Array.from(window.moduleCache.keys())); console.log('Load times:'); Array.from(window.moduleLoadTimes.entries()) .sort((a, b) => b[1] - a[1]) .forEach(([module, time]) => { console.log(` ${module}: ${time.toFixed(2)}ms`); }); const totalTime = Array.from(window.moduleLoadTimes.values()).reduce((a, b) => a + b, 0); console.log(`Total load time: ${totalTime.toFixed(2)}ms`); console.groupEnd(); }; // Enhanced page readiness detector window.waitForPageReady = function(callback, timeout = 10000) { const startTime = Date.now(); function checkReady() { const basicReady = document.readyState === 'complete'; const bootstrapReady = typeof window.bootstrap !== 'undefined'; const scriptsReady = typeof window.loadModule !== 'undefined'; if (basicReady && bootstrapReady && scriptsReady) { callback(); } else if (Date.now() - startTime < timeout) { setTimeout(checkReady, 50); } else { callback(); } } checkReady(); };