Files
Projektarbeit-MYP/network-visualization/script.js

471 lines
15 KiB
JavaScript

/**
* 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 = `
<div class="tooltip-header">${details.description}</div>
<div class="tooltip-specs">
${details.specs.map(spec => `<div class="tooltip-spec">• ${spec}</div>`).join('')}
</div>
<div class="tooltip-status">Status: ${details.status}</div>
`;
// 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');
});