/** * 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 = `
${details.description}
${details.specs.map(spec => `
โ€ข ${spec}
`).join('')}
Status: ${details.status}
`; // Style the tooltip tooltip.style.cssText = ` position: absolute; background: rgba(0, 0, 0, 0.95); color: white; padding: 12px; border-radius: 8px; font-size: 0.8rem; max-width: 250px; z-index: 1000; pointer-events: none; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); `; // Position tooltip const rect = node.getBoundingClientRect(); tooltip.style.left = (rect.left + rect.width + 10) + 'px'; tooltip.style.top = rect.top + 'px'; document.body.appendChild(tooltip); // Auto-remove after 3 seconds setTimeout(() => { tooltip.remove(); }, 3000); } /** * Setup connection highlighting on hover */ setupConnectionHighlighting() { this.connections.forEach(conn => { conn.addEventListener('mouseenter', () => { if (!this.isInteractive) return; conn.style.strokeWidth = '4'; conn.style.opacity = '1'; }); conn.addEventListener('mouseleave', () => { if (!this.isInteractive) return; conn.style.strokeWidth = ''; conn.style.opacity = ''; }); }); } /** * Setup keyboard controls */ setupKeyboardControls() { document.addEventListener('keydown', (e) => { switch(e.key) { case 'Escape': this.resetHighlights(); break; case 'i': case 'I': this.toggleInteractivity(); break; case 'r': case 'R': this.resetDiagram(); break; } }); } /** * Toggle interactivity mode */ toggleInteractivity() { this.isInteractive = !this.isInteractive; console.log(`๐ŸŽฎ Interactivity ${this.isInteractive ? 'enabled' : 'disabled'}`); if (!this.isInteractive) { this.resetHighlights(); } } /** * Reset diagram to initial state */ resetDiagram() { this.resetHighlights(); // Remove any tooltips document.querySelectorAll('.node-tooltip').forEach(tooltip => { tooltip.remove(); }); console.log('๐Ÿ”„ Diagram reset'); } /** * Log system information */ logSystemInfo() { console.log('๐Ÿš€ MYP Professional Network Diagram loaded'); console.log('๐Ÿ“Š System Components:', this.nodes.length); console.log('๐Ÿ”— Connections:', this.connections.length); console.log('๐Ÿญ Location: Mercedes-Benz TBA Marienfelde'); console.log('๐Ÿ–ฅ๏ธ Server: Raspberry Pi 4B (192.168.0.100)'); console.log('๐Ÿ”Œ Smart Plugs: 5x Tapo P110 (192.168.0.101-104, 106)'); console.log('๐Ÿ–จ๏ธ 3D Printers: 5 Arbeitsplรคtze'); console.log('โŒจ๏ธ Keyboard: [I] Toggle Interactivity, [R] Reset, [ESC] Clear'); } } /** * Utility class for diagram export and screenshot optimization */ class DiagramExport { static enableScreenshotMode() { document.body.classList.add('screenshot-mode'); const style = document.createElement('style'); style.id = 'screenshot-styles'; style.textContent = ` .screenshot-mode .node { animation: none !important; } .screenshot-mode .node:hover { transform: none !important; box-shadow: inherit !important; } .screenshot-mode .connection { animation: none !important; } `; document.head.appendChild(style); console.log('๐Ÿ“ธ Screenshot mode enabled'); } static disableScreenshotMode() { document.body.classList.remove('screenshot-mode'); const screenshotStyles = document.getElementById('screenshot-styles'); if (screenshotStyles) { screenshotStyles.remove(); } console.log('๐ŸŽฎ Interactive mode restored'); } static printDiagram() { window.print(); } } /** * Initialize when DOM is ready */ document.addEventListener('DOMContentLoaded', () => { // Initialize the network diagram const networkDiagram = new MYPNetworkDiagram(); // Make utilities globally available window.MYP = { diagram: networkDiagram, export: DiagramExport }; // Check URL parameters for special modes const urlParams = new URLSearchParams(window.location.search); if (urlParams.get('screenshot') === 'true') { DiagramExport.enableScreenshotMode(); } if (urlParams.get('print') === 'true') { setTimeout(() => { DiagramExport.printDiagram(); }, 1000); } console.log('โœ… MYP Professional Network Diagram initialized'); console.log('๐Ÿ”ง Access via: window.MYP.diagram'); console.log('๐Ÿ“ธ Screenshot mode: ?screenshot=true'); });