/** * MYP Professional Network Diagram - Interactive Script * Mercedes-Benz 3D-Druck-Management-System */ class MYPNetworkDiagram { constructor() { this.nodes = document.querySelectorAll('.node'); this.connections = document.querySelectorAll('.connection'); this.isInteractive = true; this.init(); } init() { this.setupNodeInteractions(); this.setupConnectionHighlighting(); this.logSystemInfo(); // Add keyboard shortcuts this.setupKeyboardControls(); } /** * Setup interactive node behaviors */ setupNodeInteractions() { this.nodes.forEach(node => { // Mouse enter - highlight connections node.addEventListener('mouseenter', (e) => { if (!this.isInteractive) return; this.highlightNodeConnections(e.target); }); // Mouse leave - reset highlights node.addEventListener('mouseleave', () => { if (!this.isInteractive) return; this.resetHighlights(); }); // Click - show node details node.addEventListener('click', (e) => { this.showNodeDetails(e.target); }); // Make nodes keyboard accessible node.setAttribute('tabindex', '0'); node.setAttribute('role', 'button'); }); } /** * Highlight connections related to the active node */ highlightNodeConnections(activeNode) { const nodeId = activeNode.id; const nodeType = this.getNodeType(activeNode); // Get connected node IDs const connections = this.getNodeConnections(nodeId, nodeType); // Dim all nodes first this.nodes.forEach(node => { if (node !== activeNode && !connections.includes(node.id)) { node.style.opacity = '0.3'; node.style.filter = 'blur(1px)'; } }); // Highlight connected nodes connections.forEach(connectedId => { const connectedNode = document.getElementById(connectedId); if (connectedNode) { connectedNode.style.opacity = '1'; connectedNode.style.filter = 'none'; connectedNode.style.transform = 'translateY(-4px) scale(1.02)'; } }); // Highlight relevant connections this.highlightConnections(nodeId, connections); } /** * Reset all visual highlights */ resetHighlights() { this.nodes.forEach(node => { node.style.opacity = ''; node.style.filter = ''; node.style.transform = ''; }); this.connections.forEach(conn => { conn.style.opacity = ''; conn.style.strokeWidth = ''; }); } /** * Highlight specific connections */ highlightConnections(nodeId, connectedIds) { this.connections.forEach(conn => { conn.style.opacity = '0.2'; }); // This would need more sophisticated logic to match // connections to specific nodes based on coordinates // For now, we'll use a simplified approach } /** * Get node type from CSS classes */ getNodeType(node) { if (node.classList.contains('frontend-node')) return 'frontend'; if (node.classList.contains('backend-node')) return 'backend'; if (node.classList.contains('smartplug-node')) return 'smartplug'; if (node.classList.contains('printer-node')) return 'printer'; return 'unknown'; } /** * Get connected node IDs for a given node */ getNodeConnections(nodeId, nodeType) { const connectionMap = { // Frontend connections 'kiosk': ['webapp', 'server'], 'webapp': ['kiosk', 'auth', 'flask'], 'auth': ['webapp', 'security'], // Backend connections 'server': ['kiosk', 'flask'], 'flask': ['webapp', 'server', 'database'], 'database': ['flask', 'scheduler'], 'scheduler': ['database', 'security', 'plug1', 'plug2', 'plug3', 'plug4', 'plug6'], 'security': ['auth', 'scheduler', 'monitor'], 'monitor': ['security', 'plug6', 'printer5'], // Smart plug connections 'plug1': ['scheduler', 'printer1'], 'plug2': ['scheduler', 'printer2'], 'plug3': ['scheduler', 'printer3'], 'plug4': ['scheduler', 'printer4'], 'plug6': ['scheduler', 'printer5', 'monitor'], // Printer connections 'printer1': ['plug1'], 'printer2': ['plug2'], 'printer3': ['plug3'], 'printer4': ['plug4'], 'printer5': ['plug6', 'monitor'] }; return connectionMap[nodeId] || []; } /** * Show detailed information about a node */ showNodeDetails(node) { const nodeLabel = node.querySelector('.node-label').textContent; const nodeDetail = node.querySelector('.node-detail').textContent; const nodeType = this.getNodeType(node); const details = this.getNodeDetailedInfo(node.id, nodeType); console.log(`๐ง MYP Node: ${nodeLabel}`); console.log(`๐ Details: ${nodeDetail}`); console.log(`๐ Type: ${nodeType}`); console.log(`๐ Info:`, details); // Visual feedback node.style.transform = 'scale(0.95)'; setTimeout(() => { node.style.transform = ''; }, 150); // Could show a modal or tooltip here this.showTooltip(node, details); } /** * Get detailed information for a node */ getNodeDetailedInfo(nodeId, nodeType) { const detailsMap = { 'kiosk': { description: 'Mercedes-Benz Kiosk Terminal im TBA Marienfelde', specs: ['Touch-Interface', 'HTTPS-only', 'Corporate Design'], status: 'Online' }, 'webapp': { description: 'Next.js Progressive Web App mit Flask Backend', specs: ['React/Next.js', 'PWA Features', 'Responsive Design'], status: 'Active' }, 'auth': { description: 'Authentifizierungssystem mit bcrypt und OTP', specs: ['bcrypt Hashing', 'OTP Guest Access', 'Session Management'], status: 'Secure' }, 'server': { description: 'Raspberry Pi 4B Production Server', specs: ['ARM Cortex-A72', '8GB RAM', 'Debian OS'], status: 'Online - 192.168.0.100' }, 'flask': { description: 'Flask Backend mit 15+ Blueprint Modulen', specs: ['Python Flask', 'SQLAlchemy ORM', 'REST API'], status: 'Running' }, 'database': { description: 'SQLite WAL Database mit Thread-Pool', specs: ['WAL Mode', 'Thread-Safe', 'Auto-Backup'], status: 'Synchronized' }, 'scheduler': { description: 'APScheduler Job Queue System', specs: ['Background Jobs', 'Cron Tasks', 'Queue Management'], status: 'Active' }, 'security': { description: 'Security Suite mit SSL/TLS Management', specs: ['SSL/TLS', 'Audit Logging', 'CSRF Protection'], status: 'Protected' }, 'monitor': { description: 'System Monitoring & Analytics', specs: ['Performance Tracking', 'Error Logging', 'Health Checks'], status: 'Monitoring' } }; // Smart Plugs if (nodeId.startsWith('plug')) { const plugNumber = nodeId.replace('plug', ''); return { description: `TP-Link Tapo P110 Smart Plug #${plugNumber}`, specs: ['Energy Monitoring', '230V AC Control', 'Remote Management'], status: `Online - 192.168.0.10${plugNumber}` }; } // Printers if (nodeId.startsWith('printer')) { const printerNumber = nodeId.replace('printer', ''); const printerModels = { '1': 'Prusa MK3S+', '2': 'Ender 3 Pro', '3': 'Bambu Lab A1', '4': 'Prusa MINI+', '5': 'Artillery X1' }; return { description: `3D-Drucker Arbeitsplatz ${printerNumber}`, specs: [printerModels[printerNumber], 'Smart-Plug Controlled', 'Job Queue Ready'], status: 'Ready for Production' }; } return detailsMap[nodeId] || { description: 'MYP System Component', specs: ['Network Connected', 'Monitored'], status: 'Online' }; } /** * Show tooltip with node information */ showTooltip(node, details) { // Remove existing tooltip const existingTooltip = document.querySelector('.node-tooltip'); if (existingTooltip) { existingTooltip.remove(); } const tooltip = document.createElement('div'); tooltip.className = 'node-tooltip'; tooltip.innerHTML = `