Dashboard Overview

0

Active Plugins

Online

Server Status

1

Total Users

99.9%

Uptime

Recent Activity

System Started

Just now

Quick Stats

Memory Usage 45%
CPU Usage 23%
Disk Space 67%

Plugin Management

System Settings

Server Configuration

Security Settings

Appearance

User Management

ID Username Email Role Status Last Active Actions
1 admin admin@example.com Admin Active Just now

Loading...

=== assets/css/styles.css === :root { --primary-color: #4F46E5; --secondary-color: #6366F1; --success-color: #10B981; --warning-color: #F59E0B; --danger-color: #EF4444; --dark-color: #1F2937; --light-color: #F9FAFB; --border-color: #E5E7EB; --text-primary: #111827; --text-secondary: #6B7280; --shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); --radius: 8px; --transition: all 0.2s ease; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; line-height: 1.6; color: var(--text-primary); background-color: var(--light-color); } .container { max-width: 1200px; margin: 0 auto; padding: 0 1rem; } /* Header */ .header { background: white; border-bottom: 1px solid var(--border-color); position: fixed; top: 0; left: 0; right: 0; z-index: 1000; box-shadow: var(--shadow); } .header-content { display: flex; align-items: center; justify-content: space-between; height: 4rem; } .logo { display: flex; align-items: center; gap: 0.5rem; color: var(--primary-color); } .logo i { font-size: 1.5rem; } .logo h1 { font-size: 1.25rem; font-weight: 600; } .nav-toggle { display: none; background: none; border: none; font-size: 1.25rem; color: var(--text-primary); cursor: pointer; } .nav-menu { display: flex; list-style: none; gap: 1rem; } .nav-link { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 1rem; text-decoration: none; color: var(--text-secondary); border-radius: var(--radius); transition: var(--transition); } .nav-link:hover, .nav-link.active { color: var(--primary-color); background-color: rgba(79, 70, 229, 0.1); } .user-info { display: flex; align-items: center; gap: 0.5rem; } .user-avatar { width: 2rem; height: 2rem; border-radius: 50%; } /* Main Content */ .main { margin-top: 4rem; padding: 2rem 0; } .section { display: none; } .section.active { display: block; } .section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2rem; } .section-header h2 { font-size: 1.5rem; font-weight: 600; display: flex; align-items: center; gap: 0.5rem; } .header-actions { display: flex; gap: 0.5rem; } /* Stats Grid */ .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5rem; margin-bottom: 2rem; } .stat-card { background: white; border-radius: var(--radius); padding: 1.5rem; box-shadow: var(--shadow); display: flex; align-items: center; gap: 1rem; transition: var(--transition); } .stat-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-1px); } .stat-icon { width: 3rem; height: 3rem; border-radius: 50%; background: rgba(79, 70, 229, 0.1); display: flex; align-items: center; justify-content: center; color: var(--primary-color); font-size: 1.25rem; } .stat-content h3 { font-size: 1.5rem; font-weight: 700; margin-bottom: 0.25rem; } .stat-content p { color: var(--text-secondary); font-size: 0.875rem; } /* Cards */ .card { background: white; border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; margin-bottom: 1.5rem; } .card-header { padding: 1rem 1.5rem; border-bottom: 1px solid var(--border-color); background: rgba(249, 250, 251, 0.5); } .card-header h3 { font-size: 1rem; font-weight: 600; display: flex; align-items: center; gap: 0.5rem; } .card-content { padding: 1.5rem; } /* Content Grid */ .content-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 1.5rem; margin-bottom: 2rem; } /* Activity List */ .activity-list { display: flex; flex-direction: column; gap: 1rem; } .activity-item { display: flex; align-items: center; gap: 1rem; padding: 0.75rem; border-radius: var(--radius); background: var(--light-color); } .activity-icon { width: 2rem; height: 2rem; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.875rem; } .activity-content p { margin-bottom: 0.25rem; } .activity-time { font-size: 0.75rem; color: var(--text-secondary); } /* Quick Stats */ .quick-stats { display: flex; flex-direction: column; gap: 1rem; } .quick-stat { display: flex; justify-content: space-between; align-items: center; } .quick-stat .label { color: var(--text-secondary); } .quick-stat .value { font-weight: 600; color: var(--primary-color); } /* Buttons */ .btn { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.5rem 1rem; border: none; border-radius: var(--radius); font-size: 0.875rem; font-weight: 500; text-decoration: none; cursor: pointer; transition: var(--transition); } .btn-primary { background: var(--primary-color); color: white; } .btn-primary:hover { background: var(--secondary-color); transform: translateY(-1px); } .btn-secondary { background: white; color: var(--text-primary); border: 1px solid var(--border-color); } .btn-secondary:hover { background: var(--light-color); } .btn-icon { width: 2rem; height: 2rem; border: none; border-radius: var(--radius); background: none; color: var(--text-secondary); cursor: pointer; transition: var(--transition); display: flex; align-items: center; justify-content: center; } .btn-icon:hover { background: var(--light-color); color: var(--text-primary); } /* Plugin Categories */ .plugin-categories { display: flex; gap: 0.5rem; margin-bottom: 1.5rem; flex-wrap: wrap; } .category-btn { padding: 0.5rem 1rem; border: 1px solid var(--border-color); background: white; color: var(--text-secondary); border-radius: var(--radius); cursor: pointer; transition: var(--transition); font-size: 0.875rem; } .category-btn:hover, .category-btn.active { background: var(--primary-color); color: white; border-color: var(--primary-color); } /* Plugins Grid */ .plugins-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1.5rem; } .plugin-card { background: white; border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; transition: var(--transition); } .plugin-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-2px); } .plugin-header { padding: 1.5rem; border-bottom: 1px solid var(--border-color); } .plugin-info h4 { margin-bottom: 0.5rem; color: var(--text-primary); } .plugin-info p { color: var(--text-secondary); font-size: 0.875rem; margin-bottom: 1rem; } .plugin-meta { display: flex; gap: 1rem; font-size: 0.75rem; color: var(--text-secondary); } .plugin-actions { padding: 1rem 1.5rem; background: var(--light-color); display: flex; gap: 0.5rem; } .plugin-status { padding: 0.25rem 0.5rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 500; } .status-active { background: rgba(16, 185, 129, 0.1); color: var(--success-color); } .status-inactive { background: rgba(239, 68, 68, 0.1); color: var(--danger-color); } /* Settings Grid */ .settings-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 1.5rem; } /* Forms */ .settings-form { display: flex; flex-direction: column; gap: 1rem; } .form-group { display: flex; flex-direction: column; gap: 0.5rem; } .form-group label { font-weight: 500; color: var(--text-primary); } .form-group input, .form-group select { padding: 0.5rem; border: 1px solid var(--border-color); border-radius: var(--radius); font-size: 0.875rem; transition: var(--transition); } .form-group input:focus, .form-group select:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); } .checkbox-wrapper { display: flex; align-items: center; gap: 0.5rem; } .checkbox-wrapper input[type="checkbox"] { width: 1rem; height: 1rem; } /* Table */ .table-controls { display: flex; gap: 1rem; align-items: center; } .search-input { padding: 0.5rem; border: 1px solid var(--border-color); border-radius: var(--radius); font-size: 0.875rem; width: 200px; } .filter-select { padding: 0.5rem; border: 1px solid var(--border-color); border-radius: var(--radius); font-size: 0.875rem; } .table-container { overflow-x: auto; } .data-table { width: 100%; border-collapse: collapse; } .data-table th, .data-table td { padding: 0.75rem; text-align: left; border-bottom: 1px solid var(--border-color); } .data-table th { background: var(--light-color); font-weight: 600; color: var(--text-primary); } /* Badges */ .badge { padding: 0.25rem 0.5rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 500; } .badge-admin { background: rgba(79, 70, 229, 0.1); color: var(--primary-color); } .badge-success { background: rgba(16, 185, 129, 0.1); color: var(--success-color); } /* Modal */ .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 2000; align-items: center; justify-content: center; } .modal.show { display: flex; } .modal-content { background: white; border-radius: var(--radius); max-width: 500px; width: 90%; max-height: 90vh; overflow-y: auto; box-shadow: var(--shadow-lg); } .modal-header { padding: 1.5rem; border-bottom: 1px solid var(--border-color); display: flex; align-items: center; justify-content: space-between; } .modal-close { background: none; border: none; font-size: 1.25rem; color: var(--text-secondary); cursor: pointer; } .modal-body { padding: 1.5rem; } .modal-footer { padding: 1.5rem; border-top: 1px solid var(--border-color); display: flex; gap: 0.5rem; justify-content: flex-end; } /* Loading Overlay */ .loading-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.9); z-index: 3000; align-items: center; justify-content: center; } .loading-overlay.show { display: flex; } .loading-spinner { text-align: center; color: var(--primary-color); } .loading-spinner i { font-size: 2rem; margin-bottom: 1rem; } /* Notifications */ .notification-container { position: fixed; top: 1rem; right: 1rem; z-index: 2500; display: flex; flex-direction: column; gap: 0.5rem; } .notification { padding: 1rem; border-radius: var(--radius); box-shadow: var(--shadow-lg); display: flex; align-items: center; gap: 0.5rem; min-width: 300px; animation: slideIn 0.3s ease; } .notification-success { background: var(--success-color); color: white; } .notification-error { background: var(--danger-color); color: white; } .notification-warning { background: var(--warning-color); color: white; } .notification-info { background: var(--primary-color); color: white; } @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } /* Footer */ .footer { background: white; border-top: 1px solid var(--border-color); padding: 2rem 0; margin-top: 4rem; } .footer-content { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 1rem; } .footer-links { display: flex; gap: 1rem; } .footer-links a { color: var(--text-secondary); text-decoration: none; transition: var(--transition); } .footer-links a:hover { color: var(--primary-color); } .footer-info { display: flex; align-items: center; gap: 1rem; color: var(--text-secondary); font-size: 0.875rem; } .divider { color: var(--border-color); } /* Text Colors */ .text-success { color: var(--success-color); } .text-warning { color: var(--warning-color); } .text-danger { color: var(--danger-color); } /* Responsive */ @media (max-width: 768px) { .nav-toggle { display: block; } .nav-menu { display: none; position: absolute; top: 100%; left: 0; right: 0; background: white; flex-direction: column; border-top: 1px solid var(--border-color); box-shadow: var(--shadow); padding: 1rem; } .nav-menu.show { display: flex; } .header-actions { flex-wrap: wrap; } .stats-grid { grid-template-columns: 1fr; } .content-grid { grid-template-columns: 1fr; } .settings-grid { grid-template-columns: 1fr; } .plugins-grid { grid-template-columns: 1fr; } .table-controls { flex-wrap: wrap; } .search-input { width: 100%; } .footer-content { flex-direction: column; text-align: center; } .main { padding: 1rem 0; } .section-header { flex-direction: column; align-items: flex-start; gap: 1rem; } } @media (max-width: 480px) { .container { padding: 0 0.5rem; } .stat-card { padding: 1rem; } .card-content { padding: 1rem; } .modal-content { width: 95%; } .notification { min-width: 250px; } } /* Dark Theme */ @media (prefers-color-scheme: dark) { :root { --text-primary: #F9FAFB; --text-secondary: #D1D5DB; --light-color: #111827; --border-color: #374151; --dark-color: #1F2937; } body { background-color: var(--dark-color); color: var(--text-primary); } .header, .card, .modal-content { background: #1F2937; border-color: var(--border-color); } .form-group input, .form-group select, .search-input, .filter-select { background: #374151; border-color: var(--border-color); color: var(--text-primary); } } /* Print Styles */ @media print { .header, .footer, .modal, .loading-overlay, .notification-container { display: none !important; } .main { margin-top: 0; } } === assets/js/plugins.js === /** * Plugin Management System * Handles plugin registration, loading, and configuration */ class PluginManager { constructor() { this.plugins = new Map(); this.activePlugins = new Set(); this.pluginCategories = new Map(); this.listeners = new Map(); this.initializeDefaultPlugins(); } /** * Initialize default system plugins */ initializeDefaultPlugins() { // Core System Plugin this.registerPlugin({ id: 'core-system', name: 'Core System', description: 'Essential system functionality and API', version: '1.0.0', author: 'System', category: 'core', status: 'active', dependencies: [], config: { autoStart: true, debug: false } }); // UI Enhancement Plugin this.registerPlugin({ id: 'ui-enhancement', name: 'UI Enhancement', description: 'Advanced UI components and animations', version: '2.1.0', author: 'UI Team', category: 'ui', status: 'active', dependencies: ['core-system'], config: { enableAnimations: true, theme: 'auto', compactMode: false } }); // Analytics Plugin this.registerPlugin({ id: 'analytics', name: 'Analytics Dashboard', description: 'Real-time analytics and reporting', version: '1.5.2', author: 'Analytics Team', category: 'analytics', status: 'inactive', dependencies: ['core-system'], config: { trackingEnabled: true, dataRetention: 30, realTimeUpdates: true } }); // Security Plugin this.registerPlugin({ id: 'security-module', name: 'Security Module', description: 'Advanced security and access control', version: '3.0.1', author: 'Security Team', category: 'security', status: 'active', dependencies: ['core-system'], config: { twoFactorRequired: false, sessionTimeout: 30, maxLoginAttempts: 5 } }); // Log Viewer Plugin this.registerPlugin({ id: 'log-viewer', name: 'Log Viewer', description: 'System log monitoring and analysis', version: '1.2.0', author: 'DevOps Team', category: 'core', status: 'inactive', dependencies: ['core-system'], config: { maxLogSize: '10MB', autoRefresh: true, refreshInterval: 5000 } }); // Performance Monitor Plugin this.registerPlugin({ id: 'performance-monitor', name: 'Performance Monitor', description: 'System performance monitoring and optimization', version: '2.0.0', author: 'Performance Team', category: 'core', status: 'active', dependencies: ['core-system'], config: { monitoringEnabled: true, alertsEnabled: true, alertThreshold: 80 } }); } /** * Register a new plugin */ registerPlugin(pluginData) { if (this.plugins.has(pluginData.id)) { console.warn(`Plugin ${pluginData.id} is already registered`); return false; } // Validate plugin data const requiredFields = ['id', 'name', 'description', 'version']; for (const field of requiredFields) { if (!pluginData[field]) { console.error(`Missing required field: ${field}`); return false; } } // Set defaults pluginData.status = pluginData.status || 'inactive'; pluginData.category = pluginData.category || 'uncategorized'; pluginData.dependencies = pluginData.dependencies || []; pluginData.config = pluginData.config || {}; pluginData.api = pluginData.api || {}; pluginData.hooks = pluginData.hooks || {}; // Store plugin this.plugins.set(pluginData.id, pluginData); // Add to category if (!this.pluginCategories.has(pluginData.category)) { this.pluginCategories.set(pluginData.category, []); } this.pluginCategories.get(pluginData.category).push(pluginData.id); // Activate if marked as active if (pluginData.status === 'active') { this.activatePlugin(pluginData.id); } this.emit('plugin:registered', pluginData); return true; } /** * Activate a plugin */ async activatePlugin(pluginId) { const plugin = this.plugins.get(pluginId); if (!plugin) { throw new Error(`Plugin ${pluginId} not found`); } if (this.activePlugins.has(pluginId)) { console.warn(`Plugin ${pluginId} is already active`); return; } // Check dependencies for (const depId of plugin.dependencies) { if (!this.activePlugins.has(depId)) { throw new Error(`Plugin ${pluginId} requires ${depId} to be active`); } } try { // Call plugin activation hooks if (plugin.hooks.onActivate) { await plugin.hooks.onActivate(plugin.config); } this.activePlugins.add(pluginId); plugin.status = 'active'; this.emit('plugin:activated', plugin); console.log(`Plugin ${pluginId} activated successfully`); } catch (error) { console.error(`Failed to activate plugin ${pluginId}:`, error); throw error; } } /** * Deactivate a plugin */ async deactivatePlugin(pluginId) { const plugin = this.plugins.get(pluginId); if (!plugin) { throw new Error(`Plugin ${pluginId} not found`); } if (!this.activePlugins.has(pluginId)) { console.warn(`Plugin ${pluginId} is not active`); return; } // Check if other plugins depend on this one for (const [id, otherPlugin] of this.plugins) { if (otherPlugin.dependencies.includes(pluginId) && this.activePlugins.has(id)) { throw new Error(`Cannot deactivate ${pluginId} because ${id} depends on it`); } } try { // Call plugin deactivation hooks if (plugin.hooks.onDeactivate) { await plugin.hooks.onDeactivate(); } this.activePlugins.delete(pluginId); plugin.status = 'inactive'; this.emit('plugin:deactivated', plugin); console.log(`Plugin ${pluginId} deactivated successfully`); } catch (error) { console.error(`Failed to deactivate plugin ${pluginId}:`, error); throw error; } } /** * Update plugin configuration */ updatePluginConfig(pluginId, newConfig) { const plugin = this.plugins.get(pluginId); if (!plugin) { throw new Error(`Plugin ${pluginId} not found`); } // Merge new config with existing plugin.config = { ...plugin.config, ...newConfig }; // Notify plugin of config change if (plugin.hooks.onConfigChange) { plugin.hooks.onConfigChange(plugin.config); } this.emit('plugin:configUpdated', { pluginId, config: plugin.config }); console.log(`Plugin ${pluginId} configuration updated`); } /** * Get plugin by ID */ getPlugin(pluginId) { return this.plugins.get(pluginId); } /** * Get all plugins */ getAllPlugins() { return Array.from(this.plugins.values()); } /** * Get active plugins */ getActivePlugins() { return Array.from(this.activePlugins).map(id => this.plugins.get(id)); } /** * Get plugins by category */ getPluginsByCategory(category) { return this.getAllPlugins().filter(plugin => plugin.category === category); } /** * Get plugin categories */ getCategories() { return Array.from(this.pluginCategories.keys()); } /** * Remove a plugin */ async removePlugin(pluginId) { const plugin = this.plugins.get(pluginId); if (!plugin) { throw new Error(`Plugin ${pluginId} not found`); } // Deactivate if active if (this.activePlugins.has(pluginId)) { await this.deactivatePlugin(pluginId); } // Call cleanup hooks if (plugin.hooks.onRemove) { await plugin.hooks.onRemove(); } // Remove from storage this.plugins.delete(pluginId); this.activePlugins.delete(pluginId); // Remove from category const categoryPlugins = this.pluginCategories.get(plugin.category); if (categoryPlugins) { const index = categoryPlugins.indexOf(pluginId); if (index > -1) { categoryPlugins.splice(index, 1); } if (categoryPlugins.length === 0) { this.pluginCategories.delete(plugin.category); } } this.emit('plugin:removed', plugin); console.log(`Plugin ${pluginId} removed successfully`); } /** * Plugin API - exposes methods to plugins */ getPluginAPI() { return { registerHook: (pluginId, hookName, handler) => { const plugin = this.plugins.get(pluginId); if (plugin && plugin.hooks) { plugin.hooks[hookName] = handler; } }, emit: (event, data) => { this.emit(`plugin:${pluginId}:${event}`, data); }, getConfig: (pluginId) => { const plugin = this.plugins.get(pluginId); return plugin ? plugin.config : null; }, log: (pluginId, level, message) => { console[level](`[${pluginId}] ${message}`); } }; } /** * Event system */ on(event, callback) { if (!this.listeners.has(event)) { this.listeners.set(event, []); } this.listeners.get(event).push(callback); } off(event, callback) { const listeners = this.listeners.get(event); if (listeners) { const index = listeners.indexOf(callback); if (index > -1) { listeners.splice(index, 1); } } } emit(event, data) { const listeners = this.listeners.get(event); if (listeners) { listeners.forEach(callback => { try { callback(data); } catch (error) { console.error(`Error in event listener for ${event}:`, error); } }); } } /** * Plugin validation */ validatePlugin(pluginData) { const errors = []; // Required fields if (!pluginData.id) errors.push('Plugin ID is required'); if (!pluginData.name) errors.push('Plugin name is required'); if (!pluginData.description) errors.push('Plugin description is required'); if (!pluginData.version) errors.push('Plugin version is required'); // ID format validation if (pluginData.id && !/^[a-z0-9-]+$/.test(pluginData.id)) { errors.push('Plugin ID must contain only lowercase letters, numbers, and hyphens'); } // Version format validation if (pluginData.version && !/^\d+\.\d+\.\d+(-[a-zA-Z0-9-]+)?$/.test(pluginData.version)) { errors.push('Plugin version must be in semantic versioning format (e.g., 1.0.0)'); } return { valid: errors.length === 0, errors }; } /** * Export plugin configuration */ exportConfig() { const config = { plugins: {}, activePlugins: Array.from(this.activePlugins), categories: {} }; for (const [id, plugin] of this.plugins) { config.plugins[id] = { ...plugin, api: undefined, // Don't export API functions hooks: undefined // Don't export hooks }; } for (const [category, pluginIds] of this.pluginCategories) { config.categories[category] = pluginIds; } return config; } /** * Import plugin configuration */ async importConfig(configData) { try { // Validate imported data if (!configData.plugins || typeof configData.plugins !== 'object') { throw new Error('Invalid configuration format'); } // Remove all existing plugins except core system for (const plugin of this.getAllPlugins()) { if (plugin.id !== 'core-system') { await this.removePlugin(plugin.id); } } // Import plugins for (const [id, pluginData] of Object.entries(configData.plugins)) { if (id !== 'core-system') { // Don't import core system this.registerPlugin(pluginData); } } // Activate plugins that were active if (configData.activePlugins) { for (const pluginId of configData.activePlugins) { if (this.plugins.has(pluginId) && pluginId !== 'core-system') { try { await this.activatePlugin(pluginId); } catch (error) { console.warn(`Failed to activate plugin ${pluginId}:`, error); } } } } console.log('Plugin configuration imported successfully'); } catch (error) { console.error('Failed to import plugin configuration:', error); throw error; } } } // Initialize global plugin manager window.pluginManager = new PluginManager(); // Plugin examples and testing functions window.PluginExamples = { // Example: Custom analytics plugin createAnalyticsPlugin: () => { window.pluginManager.registerPlugin({ id: 'custom-analytics', name: 'Custom Analytics', description: 'Custom analytics tracking and reporting', version: '1.0.0', author: 'Custom Developer', category: 'analytics', status: 'inactive', dependencies: ['core-system'], config: { trackingId: '', anonymizeIp: true, sampleRate: 100 }, hooks: { onActivate: (config) => { console.log('Custom analytics activated with config:', config); // Initialize tracking }, onDeactivate: () => { console.log('Custom analytics deactivated'); // Cleanup tracking } } }); }, // Example: Social sharing plugin createSocialPlugin: () => { window.pluginManager.registerPlugin({ id: 'social-sharing', name: 'Social Media Sharing', description: 'Add social media sharing buttons', version: '1.2.0', author: 'UI Developer', category: 'ui', status: 'inactive', dependencies: ['core-system'], config: { platforms: ['twitter', 'facebook', 'linkedin'], position: 'bottom', showLabels: true }, hooks: { onActivate: (config) => { console.log('Social sharing plugin activated'); // Add sharing buttons to page }, onDeactivate: () => { console.log('Social sharing plugin deactivated'); // Remove sharing buttons } } }); } }; console.log('Plugin Management System initialized'); === assets/js/admin.js === /** * Admin Panel Application * Main application logic and UI management */ class AdminPanel { constructor() { this.currentSection = 'dashboard'; this.isLoading = false; this.notifications = []; this.pluginManager = window.pluginManager; this.init(); } /** * Initialize the admin panel */ init() { this.bindEvents(); this.initializeNavigation(); this.loadDashboardData(); this.renderPlugins(); this.setupEventListeners(); console.log('Admin Panel initialized'); } /** * Bind DOM events */ bindEvents() { // Navigation document.getElementById('navToggle')?.addEventListener('click', () => { this.toggleNavigation(); }); // Navigation links document.querySelectorAll('.nav-link').forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const section = link.dataset.section; this.switchSection(section); }); }); // Dashboard document.getElementById('refreshData')?.addEventListener('click', () => { this.refreshDashboard(); }); // Plugins document.getElementById('addPlugin')?.addEventListener('click', () => { this.showAddPluginModal(); }); document.getElementById('installPlugin')?.addEventListener('click', () => { this.showInstallPluginModal(); }); document.getElementById('pluginModalClose')?.addEventListener('click', () => { this.closeModal('pluginModal'); }); document.getElementById('pluginModalCancel')?.addEventListener('click', () => { this.closeModal('pluginModal'); }); document.getElementById('pluginModalSave')?.addEventListener('click', () => { this.savePluginConfig(); }); // Plugin categories document.querySelectorAll('.category-btn').forEach(btn => { btn.addEventListener('click', () => { const category = btn.dataset.category; this.filterPluginsByCategory(category); }); }); // Settings document.getElementById('saveSettings')?.addEventListener('click', () => { this.saveSettings(); }); // Users document.getElementById('addUser')?.addEventListener('click', () => { this.showAddUserModal(); }); document.getElementById('userSearch')?.addEventListener('input', () => { this.filterUsers(); }); document.getElementById('roleFilter')?.addEventListener('change', () => { this.filterUsers(); }); // Keyboard shortcuts document.addEventListener('keydown', (e) => { this.handleKeyboardShortcuts(e); }); // Click outside modal to close document.addEventListener('click', (e) => { if (e.target.classList.contains('modal')) { this.closeModal(e.target.id); } }); } /** * Setup additional event listeners */ setupEventListeners() { // Plugin manager events this.pluginManager.on('plugin:registered', (plugin) => { this.showNotification(`Plugin "${plugin.name}" registered successfully`, 'success'); this.renderPlugins(); this.updateDashboardStats(); }); this.pluginManager.on('plugin:activated', (plugin) => { this.showNotification(`Plugin "${plugin.name}" activated`, 'success'); this.renderPlugins(); this.updateDashboardStats(); }); this.pluginManager.on('plugin:deactivated', (plugin) => { this.showNotification(`Plugin "${plugin.name}" deactivated`, 'warning'); this.renderPlugins(); this.updateDashboardStats(); }); this.pluginManager.on('plugin:configUpdated', (data) => { this.showNotification(`Plugin configuration updated`, 'success'); }); // Window resize window.addEventListener('resize', () => { this.handleResize(); }); } /** * Initialize navigation system */ initializeNavigation() { // Set initial active section this.switchSection('dashboard'); } /** * Switch between sections */ switchSection(sectionId) { // Hide all sections document.querySelectorAll('.section').forEach(section => { section.classList.remove('active'); }); // Show target section const targetSection = document.getElementById(sectionId); if (targetSection) { targetSection.classList.add('active'); } // Update navigation document.querySelectorAll('.nav-link').forEach(link => { link.classList.remove('active'); }); const activeLink = document.querySelector(`[data-section="${sectionId}"]`); if (activeLink) { activeLink.classList.add('active'); } this.currentSection = sectionId; // Load section-specific data switch (sectionId) { case 'dashboard': this.loadDashboardData(); break; case 'plugins': this.renderPlugins(); break; case 'settings': this.loadSettings(); break; case 'users': this.loadUsersData(); break; } // Update URL hash window.location.hash = sectionId; } /** * Toggle mobile navigation */ toggleNavigation() { const navMenu = document.getElementById('navMenu'); navMenu.classList.toggle('show'); } /** * Load dashboard data */ loadDashboardData() { this.showLoading(true); // Simulate API call setTimeout(() => { this.updateDashboardStats(); this.updateActivityFeed(); this.updateSystemMetrics(); this.showLoading(false); }, 500); } /** * Update dashboard statistics */ updateDashboardStats() { const pluginCount = this.pluginManager.getActivePlugins().length; const userCount = 1; // This would come from a real API const uptime = '99.9%'; const serverStatus = 'Online'; // Update DOM elements const elements = { pluginCount, userCount, uptime, serverStatus }; for (const [id, value] of Object.entries(elements)) { const element = document.getElementById(id); if (element) { element.textContent = value; } } } /** * Update activity feed */ updateActivityFeed() { const activityList = document.getElementById('activityList'); if (!activityList) return; const activities = [ { icon: 'fas fa-plug', iconClass: 'text-success', message: 'Plugin system initialized', time: 'Just now' }, { icon: 'fas fa-server', iconClass: 'text-info', message: 'Server connection established', time: '2 minutes ago' }, { icon: 'fas fa-shield-alt', iconClass: 'text-warning', message: 'Security scan completed', time: '5 minutes ago' }, { icon: 'fas fa-database', iconClass: 'text-success', message: 'Database backup completed', time: '1 hour ago' } ]; activityList.innerHTML = activities.map(activity => `

${activity.message}

${activity.time}
`).join(''); } /** * Update system metrics */ updateSystemMetrics() { // Simulate changing metrics const metrics = { memoryUsage: Math.floor(Math.random() * 40) + 30 + '%', cpuUsage: Math.floor(Math.random() * 30) + 10 + '%', diskSpace: Math.floor(Math.random() * 20) + 60 + '%' }; for (const [id, value] of Object.entries(metrics)) { const element = document.getElementById(id); if (element) { element.textContent = value; } } } /** * Render plugins grid */ renderPlugins(filter = 'all') { const pluginsGrid = document.getElementById('pluginsGrid'); if (!pluginsGrid) return; const plugins = filter === 'all' ? this.pluginManager.getAllPlugins() : this.pluginManager.getPluginsByCategory(filter); pluginsGrid.innerHTML = plugins.map(plugin => `

${plugin.name}

${plugin.description}

v${plugin.version} by ${plugin.author} ${plugin.status}
${plugin.status === 'active' ? `` : `` }
`).join(''); // Update category buttons this.updateCategoryButtons(); } /** * Update plugin category buttons */ updateCategoryButtons() { const categories = this.pluginManager.getCategories(); const pluginsGrid = document.getElementById('pluginsGrid'); // Update button states document.querySelectorAll('.category-btn').forEach(btn => { const category = btn.dataset.category; const categoryPlugins = category === 'all' ? this.pluginManager.getAllPlugins() : this.pluginManager.getPluginsByCategory(category); btn.disabled = categoryPlugins.length === 0; btn.style.opacity = categoryPlugins.length === 0 ? '0.5' : '1'; }); } /** * Filter plugins by category */ filterPluginsByCategory(category) { // Update category buttons document.querySelectorAll('.category-btn').forEach(btn => { btn.classList.remove('active'); }); document.querySelector(`[data-category="${category}"]`).classList.add('active'); // Render filtered plugins this.renderPlugins(category); } /** * Plugin management methods */ async activatePlugin(pluginId) { try { this.showLoading(true); await this.pluginManager.activatePlugin(pluginId); } catch (error) { this.showNotification(`Failed to activate plugin: ${error.message}`, 'error'); } finally { this.showLoading(false); } } async deactivatePlugin(pluginId) { try { this.showLoading(true); await this.pluginManager.deactivatePlugin(pluginId); } catch (error) { this.showNotification(`Failed to deactivate plugin: ${error.message}`, 'error'); } finally { this.showLoading(false); } } async removePlugin(pluginId) { if (!confirm('Are you sure you want to remove this plugin?')) { return; } try { this.showLoading(true); await this.pluginManager.removePlugin(pluginId); } catch (error) { this.showNotification(`Failed to remove plugin: ${error.message}`, 'error'); } finally { this.showLoading(false); } } configurePlugin(pluginId) { const plugin = this.pluginManager.getPlugin(pluginId); if (!plugin) return; const modal = document.getElementById('pluginModal'); const modalTitle = document.getElementById('pluginModalTitle'); const modalBody = document.getElementById('pluginModalBody'); modalTitle.textContent = `Configure ${plugin.name}`; modalBody.innerHTML = this.generatePluginConfigForm(plugin); modal.classList.add('show'); } generatePluginConfigForm(plugin) { let formHtml = `
`; // Generate config fields based on plugin config for (const [key, value] of Object.entries(plugin.config)) { const inputType = typeof value === 'boolean' ? 'checkbox' : 'text'; const inputValue = typeof value === 'boolean' ? '' : value; const checked = typeof value === 'boolean' && value ? 'checked' : ''; formHtml += `
${inputType === 'checkbox' ? `
` : `` }
`; } return formHtml; } formatConfigKey(key) { return key.replace(/([A-Z])/g, ' $1') .replace(/^./, str => str.toUpperCase()) .trim(); } savePluginConfig() { const modalBody = document.getElementById('pluginModalBody'); const pluginName = document.getElementById('pluginModalTitle').textContent; const pluginId = pluginName.replace('Configure ', ''); // Find plugin by name (in real app, would use ID) const plugin = this.pluginManager.getAllPlugins().find(p => p.name === pluginId); if (!plugin) return; const configInputs = modalBody.querySelectorAll('[data-config-key]'); const newConfig = {}; configInputs.forEach(input => { const key = input.dataset.configKey; if (input.type === 'checkbox') { newConfig[key] = input.checked; } else { newConfig[key] = input.value; } }); try { this.pluginManager.updatePluginConfig(plugin.id, newConfig); this.closeModal('pluginModal'); this.showNotification('Plugin configuration saved successfully', 'success'); } catch (error) { this.showNotification(`Failed to save configuration: ${error.message}`, 'error'); } } showAddPluginModal() { const modalBody = `

Note: This is a demo. In a real system, you would upload plugin files or install from a repository.

`; document.getElementById('pluginModalTitle').textContent = 'Add New Plugin'; document.getElementById('pluginModalBody').innerHTML = modalBody; document.getElementById('pluginModal').classList.add('show'); // Override save button for adding plugin document.getElementById('pluginModalSave').onclick = () => { this.addNewPlugin(); }; } addNewPlugin() { const name = document.getElementById('pluginName').value; const description = document.getElementById('pluginDescription').value; const version = document.getElementById('pluginVersion').value; const author = document.getElementById('pluginAuthor').value; const category = document.getElementById('pluginCategory').value; if (!name || !description || !version) { this.showNotification('Please fill in all required fields', 'error'); return; } const pluginId = name.toLowerCase().replace(/[^a-z0-9]/g, '-'); try { this.pluginManager.registerPlugin({ id: pluginId, name, description, version, author, category, status: 'inactive', dependencies: ['core-system'], config: { enabled: false, customSetting: '' } }); this.closeModal('pluginModal'); this.showNotification('Plugin added successfully', 'success'); } catch (error) { this.showNotification(`Failed to add plugin: ${error.message}`, 'error'); } } showInstallPluginModal() { this.showNotification('Plugin installation from repository is not implemented in this demo', 'info'); } /** * Settings management */ loadSettings() { // Load saved settings or defaults const savedSettings = localStorage.getItem('adminPanelSettings'); if (savedSettings) { const settings = JSON.parse(savedSettings); this.populateSettingsForm(settings); } } populateSettingsForm(settings) { for (const [key, value] of Object.entries(settings)) { const element = document.getElementById(key); if (element) { if (element.type === 'checkbox') { element.checked = value; } else { element.value = value; } } } } saveSettings() { const settings = {}; // Collect all form data const forms = ['serverSettingsForm', 'securitySettingsForm', 'appearanceSettingsForm']; forms.forEach(formId => { const form = document.getElementById(formId); if (form) { const inputs = form.querySelectorAll('input, select'); inputs.forEach(input => { if (input.type === 'checkbox') { settings[input.id] = input.checked; } else if (input.value !== '') { settings[input.id] = input.value; } }); } }); // Save to localStorage localStorage.setItem('adminPanelSettings', JSON.stringify(settings)); this.showNotification('Settings saved successfully', 'success'); } /** * User management */ loadUsersData() { // In a real application, this would fetch user data from an API const users = [ { id: 1, username: 'admin', email: 'admin@example.com', role: 'admin', status: 'active', lastActive: 'Just now' } ]; this.renderUsersTable(users); } renderUsersTable(users) { const tbody = document.querySelector('#usersTable tbody'); if (!tbody) return; tbody.innerHTML = users.map(user => ` ${user.id} ${user.username} ${user.email} ${user.role} ${user.status} ${user.lastActive} `).join(''); } filterUsers() { const searchTerm = document.getElementById('userSearch').value.toLowerCase(); const roleFilter = document.getElementById('roleFilter').value; // In a real application, this would filter the actual user data console.log('Filtering users:', { searchTerm, roleFilter }); } showAddUserModal() { this.showNotification('Add user functionality not implemented in this demo', 'info'); } editUser(userId) { this.showNotification(`Edit user ${userId} functionality not implemented in this demo`, 'info'); } deleteUser(userId) { if (confirm('Are you sure you want to delete this user?')) { this.showNotification(`User ${userId} deleted (demo)`, 'success'); } } /** * Utility methods */ refreshDashboard() { this.loadDashboardData(); this.showNotification('Dashboard data refreshed', 'success'); } showLoading(show) { const overlay = document.getElementById('loadingOverlay'); if (overlay) { overlay