import { customElement, DeesElement, type TemplateResult, html, property, css, cssManager, state, } from '@design.estate/dees-element'; import { DeesAppuiSecondarymenu, DeesIcon, DeesStatsGrid } from '@design.estate/dees-catalog'; import type { ISecondaryMenuGroup, ISecondaryMenuItem } from '../../elements/interfaces/secondarymenu.js'; import { demo } from './eco-view-system.demo.js'; // Ensure components are registered DeesAppuiSecondarymenu; DeesIcon; DeesStatsGrid; declare global { interface HTMLElementTagNameMap { 'eco-view-system': EcoViewSystem; } } export type TSystemPanel = | 'overview' | 'cpu' | 'memory' | 'storage' | 'network' | 'processes'; @customElement('eco-view-system') export class EcoViewSystem extends DeesElement { public static demo = demo; public static demoGroup = 'Views'; public static styles = [ cssManager.defaultStyles, css` :host { display: block; width: 100%; height: 100%; background: ${cssManager.bdTheme('#f5f5f7', 'hsl(240 6% 10%)')}; color: ${cssManager.bdTheme('hsl(0 0% 10%)', 'hsl(0 0% 98%)')}; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } .system-container { display: flex; height: 100%; } dees-appui-secondarymenu { flex-shrink: 0; background: ${cssManager.bdTheme('#ffffff', 'hsl(240 6% 8%)')}; border-right: 1px solid ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(240 5% 15%)')}; } .content { flex: 1; overflow-y: auto; padding: 32px 48px; } .panel-header { margin-bottom: 32px; } .panel-title { font-size: 28px; font-weight: 600; color: ${cssManager.bdTheme('hsl(0 0% 10%)', 'hsl(0 0% 98%)')}; margin-bottom: 8px; } .panel-description { font-size: 14px; color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 60%)')}; } .stats-section { margin-bottom: 32px; } .section-title { font-size: 13px; font-weight: 600; color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 50%)')}; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 16px; } dees-statsgrid { --dees-statsgrid-gap: 16px; } .process-list { background: ${cssManager.bdTheme('#ffffff', 'hsl(240 6% 12%)')}; border: 1px solid ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(240 5% 18%)')}; border-radius: 12px; overflow: hidden; } .process-header { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; padding: 12px 16px; background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(240 5% 14%)')}; border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(240 5% 18%)')}; font-size: 12px; font-weight: 600; color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 55%)')}; text-transform: uppercase; letter-spacing: 0.5px; } .process-row { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; padding: 12px 16px; border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 94%)', 'hsl(240 5% 15%)')}; font-size: 14px; color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 85%)')}; } .process-row:last-child { border-bottom: none; } .process-name { font-weight: 500; } .process-value { color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 65%)')}; } .process-value.high { color: hsl(0 84% 60%); font-weight: 500; } `, ]; @property({ type: String }) accessor activePanel: TSystemPanel = 'overview'; // System data (can be set externally) @property({ type: Number }) accessor cpuUsage = 0; @property({ type: Number }) accessor memoryUsage = 0; @property({ type: Number }) accessor diskUsage = 0; @property({ type: Number }) accessor cpuTemp = 0; @property({ type: String }) accessor uptime = '--'; @property({ type: Number }) accessor cpuCores = 0; @property({ type: String }) accessor cpuModel = 'Unknown'; @property({ type: Number }) accessor cpuSpeed = 0; @property({ type: Number }) accessor memoryTotal = 0; @property({ type: Number }) accessor memoryUsed = 0; @property({ type: Number }) accessor memoryFree = 0; @property({ type: String }) accessor hostname = 'Unknown'; @property({ type: String }) accessor platform = 'Unknown'; @property({ type: Array }) accessor loadAvg: number[] = [0, 0, 0]; @state() accessor networkIn = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; @state() accessor networkOut = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // Public method to update metrics from backend public setMetrics(metrics: { cpu: { usage: number; cores: number; model: string; speed: number; loadAvg: number[] }; memory: { total: number; used: number; free: number; usagePercent: number }; system: { platform: string; hostname: string; uptimeFormatted: string }; }): void { this.cpuUsage = metrics.cpu.usage; this.cpuCores = metrics.cpu.cores; this.cpuModel = metrics.cpu.model; this.cpuSpeed = metrics.cpu.speed; this.loadAvg = metrics.cpu.loadAvg; this.memoryUsage = metrics.memory.usagePercent; this.memoryTotal = metrics.memory.total; this.memoryUsed = metrics.memory.used; this.memoryFree = metrics.memory.free; this.hostname = metrics.system.hostname; this.platform = metrics.system.platform; this.uptime = metrics.system.uptimeFormatted; } // Helper to format bytes private formatBytes(bytes: number): string { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; } private getMenuGroups(): ISecondaryMenuGroup[] { return [ { name: 'Monitor', iconName: 'lucide:activity', items: [ { key: 'overview', iconName: 'lucide:layoutDashboard', action: () => this.activePanel = 'overview', }, ], }, { name: 'Hardware', iconName: 'lucide:cpu', items: [ { key: 'cpu', iconName: 'lucide:cpu', action: () => this.activePanel = 'cpu', }, { key: 'memory', iconName: 'lucide:memoryStick', action: () => this.activePanel = 'memory', }, { key: 'storage', iconName: 'lucide:hardDrive', action: () => this.activePanel = 'storage', }, ], }, { name: 'Network', iconName: 'lucide:network', items: [ { key: 'network', iconName: 'lucide:wifi', action: () => this.activePanel = 'network', }, ], }, { name: 'Software', iconName: 'lucide:layers', items: [ { key: 'processes', iconName: 'lucide:listTree', action: () => this.activePanel = 'processes', }, ], }, ]; } private getSelectedItem(): ISecondaryMenuItem | null { for (const group of this.getMenuGroups()) { for (const item of group.items) { if ('key' in item && item.key === this.activePanel) { return item; } } } return null; } public render(): TemplateResult { return html`
${this.renderActivePanel()}
`; } private renderActivePanel(): TemplateResult { switch (this.activePanel) { case 'overview': return this.renderOverviewPanel(); case 'cpu': return this.renderCpuPanel(); case 'memory': return this.renderMemoryPanel(); case 'storage': return this.renderStoragePanel(); case 'network': return this.renderNetworkPanel(); case 'processes': return this.renderProcessesPanel(); default: return this.renderOverviewPanel(); } } private renderOverviewPanel(): TemplateResult { const overviewTiles = [ { id: 'cpu', title: 'CPU Usage', value: this.cpuUsage, type: 'gauge' as const, icon: 'lucide:cpu', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 60, color: 'hsl(45 93% 47%)' }, { value: 80, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'memory', title: 'Memory Usage', value: this.memoryUsage, type: 'gauge' as const, icon: 'lucide:memoryStick', description: this.memoryTotal ? `${this.formatBytes(this.memoryUsed)} of ${this.formatBytes(this.memoryTotal)}` : undefined, gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 70, color: 'hsl(45 93% 47%)' }, { value: 85, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'disk', title: 'Disk Usage', value: this.diskUsage, type: 'gauge' as const, icon: 'lucide:hardDrive', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 75, color: 'hsl(45 93% 47%)' }, { value: 90, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'temp', title: 'CPU Temp', value: this.cpuTemp, unit: '°C', type: 'gauge' as const, icon: 'lucide:thermometer', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(217 91% 60%)' }, { value: 50, color: 'hsl(142 71% 45%)' }, { value: 70, color: 'hsl(45 93% 47%)' }, { value: 85, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'network-in', title: 'Network In', value: '85', unit: 'Mbps', type: 'trend' as const, icon: 'lucide:download', trendData: this.networkIn, color: 'hsl(142 71% 45%)', }, { id: 'network-out', title: 'Network Out', value: '65', unit: 'Mbps', type: 'trend' as const, icon: 'lucide:upload', trendData: this.networkOut, color: 'hsl(217 91% 60%)', }, { id: 'uptime', title: 'System Uptime', value: this.uptime, type: 'text' as const, icon: 'lucide:clock', color: 'hsl(142 71% 45%)', description: 'Since last reboot', }, { id: 'hostname', title: 'Hostname', value: this.hostname, type: 'text' as const, icon: 'lucide:server', description: `${this.platform} - ${this.cpuCores} cores`, }, ]; return html`
System Overview
Real-time system performance metrics
`; } private renderCpuPanel(): TemplateResult { const cpuTiles = [ { id: 'cpu-total', title: 'Total CPU Usage', value: this.cpuUsage, type: 'gauge' as const, icon: 'lucide:cpu', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 60, color: 'hsl(45 93% 47%)' }, { value: 80, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'core-0', title: 'Core 0', value: 38, type: 'gauge' as const, gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 60, color: 'hsl(45 93% 47%)' }, { value: 80, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'core-1', title: 'Core 1', value: 52, type: 'gauge' as const, gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 60, color: 'hsl(45 93% 47%)' }, { value: 80, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'core-2', title: 'Core 2', value: 45, type: 'gauge' as const, gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 60, color: 'hsl(45 93% 47%)' }, { value: 80, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'core-3', title: 'Core 3', value: 33, type: 'gauge' as const, gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 60, color: 'hsl(45 93% 47%)' }, { value: 80, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'load-avg', title: 'Load Average', value: '2.45', type: 'trend' as const, icon: 'lucide:activity', trendData: [1.8, 2.1, 2.4, 2.2, 2.5, 2.3, 2.6, 2.4, 2.45], description: '1m: 2.45, 5m: 2.32, 15m: 2.18', }, { id: 'cpu-temp', title: 'Temperature', value: this.cpuTemp, unit: '°C', type: 'gauge' as const, icon: 'lucide:thermometer', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(217 91% 60%)' }, { value: 50, color: 'hsl(142 71% 45%)' }, { value: 70, color: 'hsl(45 93% 47%)' }, { value: 85, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'freq', title: 'Clock Speed', value: '3.2', unit: 'GHz', type: 'number' as const, icon: 'lucide:gauge', description: 'Max: 4.2 GHz', }, ]; return html`
CPU
Processor usage and performance
`; } private renderMemoryPanel(): TemplateResult { const memoryTiles = [ { id: 'ram-usage', title: 'RAM Usage', value: this.memoryUsage, type: 'gauge' as const, icon: 'lucide:memoryStick', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 70, color: 'hsl(45 93% 47%)' }, { value: 85, color: 'hsl(0 84% 60%)' }, ], }, description: '10.7 GB of 16 GB', }, { id: 'swap-usage', title: 'Swap Usage', value: 12, type: 'gauge' as const, icon: 'lucide:hardDrive', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 50, color: 'hsl(45 93% 47%)' }, { value: 75, color: 'hsl(0 84% 60%)' }, ], }, description: '0.5 GB of 4 GB', }, { id: 'mem-trend', title: 'Memory History', value: '67%', type: 'trend' as const, icon: 'lucide:trendingUp', trendData: [58, 62, 65, 63, 68, 72, 70, 65, 67], description: 'Last hour', }, { id: 'cached', title: 'Cached', value: '3.2', unit: 'GB', type: 'number' as const, icon: 'lucide:database', color: 'hsl(217 91% 60%)', }, { id: 'buffers', title: 'Buffers', value: '512', unit: 'MB', type: 'number' as const, icon: 'lucide:layers', color: 'hsl(262 83% 58%)', }, { id: 'available', title: 'Available', value: '5.3', unit: 'GB', type: 'number' as const, icon: 'lucide:checkCircle', color: 'hsl(142 71% 45%)', }, ]; return html`
Memory
RAM and swap usage details
`; } private renderStoragePanel(): TemplateResult { const storageTiles = [ { id: 'disk-main', title: 'System Drive', value: this.diskUsage, type: 'percentage' as const, icon: 'lucide:hardDrive', description: '275 GB of 512 GB used', color: 'hsl(217 91% 60%)', }, { id: 'disk-data', title: 'Data Drive', value: 38, type: 'percentage' as const, icon: 'lucide:hardDrive', description: '380 GB of 1 TB used', color: 'hsl(142 71% 45%)', }, { id: 'read-speed', title: 'Read Speed', value: '245', unit: 'MB/s', type: 'trend' as const, icon: 'lucide:download', trendData: [180, 220, 195, 280, 245, 210, 265, 230, 245], color: 'hsl(142 71% 45%)', }, { id: 'write-speed', title: 'Write Speed', value: '128', unit: 'MB/s', type: 'trend' as const, icon: 'lucide:upload', trendData: [95, 110, 85, 145, 120, 105, 138, 115, 128], color: 'hsl(217 91% 60%)', }, { id: 'iops-read', title: 'Read IOPS', value: '12.4k', type: 'number' as const, icon: 'lucide:gauge', description: 'Operations/sec', }, { id: 'iops-write', title: 'Write IOPS', value: '8.2k', type: 'number' as const, icon: 'lucide:gauge', description: 'Operations/sec', }, ]; return html`
Storage
Disk usage and I/O performance
`; } private renderNetworkPanel(): TemplateResult { const networkTiles = [ { id: 'download', title: 'Download', value: '85.2', unit: 'Mbps', type: 'trend' as const, icon: 'lucide:download', trendData: this.networkIn, color: 'hsl(142 71% 45%)', }, { id: 'upload', title: 'Upload', value: '64.8', unit: 'Mbps', type: 'trend' as const, icon: 'lucide:upload', trendData: this.networkOut, color: 'hsl(217 91% 60%)', }, { id: 'latency', title: 'Latency', value: 12, unit: 'ms', type: 'gauge' as const, icon: 'lucide:activity', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: 'hsl(142 71% 45%)' }, { value: 30, color: 'hsl(45 93% 47%)' }, { value: 60, color: 'hsl(0 84% 60%)' }, ], }, }, { id: 'packets-in', title: 'Packets In', value: '1.2M', type: 'number' as const, icon: 'lucide:arrowDownCircle', description: 'Per second', }, { id: 'packets-out', title: 'Packets Out', value: '892k', type: 'number' as const, icon: 'lucide:arrowUpCircle', description: 'Per second', }, { id: 'connections', title: 'Active Connections', value: 48, type: 'number' as const, icon: 'lucide:link', description: '12 established, 36 waiting', }, { id: 'total-down', title: 'Total Downloaded', value: '24.5', unit: 'GB', type: 'number' as const, icon: 'lucide:database', description: 'This session', color: 'hsl(142 71% 45%)', }, { id: 'total-up', title: 'Total Uploaded', value: '8.2', unit: 'GB', type: 'number' as const, icon: 'lucide:database', description: 'This session', color: 'hsl(217 91% 60%)', }, ]; return html`
Network
Network traffic and connectivity
`; } private renderProcessesPanel(): TemplateResult { const processTiles = [ { id: 'total-processes', title: 'Total Processes', value: 247, type: 'number' as const, icon: 'lucide:layers', }, { id: 'running', title: 'Running', value: 12, type: 'number' as const, icon: 'lucide:play', color: 'hsl(142 71% 45%)', }, { id: 'sleeping', title: 'Sleeping', value: 235, type: 'number' as const, icon: 'lucide:moon', color: 'hsl(217 91% 60%)', }, { id: 'threads', title: 'Threads', value: 1842, type: 'number' as const, icon: 'lucide:gitBranch', }, ]; const topProcesses = [ { name: 'node', pid: 1234, cpu: 12.5, memory: 8.2 }, { name: 'chrome', pid: 2345, cpu: 8.3, memory: 15.4 }, { name: 'code', pid: 3456, cpu: 5.2, memory: 12.1 }, { name: 'docker', pid: 4567, cpu: 4.8, memory: 6.8 }, { name: 'postgres', pid: 5678, cpu: 3.2, memory: 4.5 }, { name: 'nginx', pid: 6789, cpu: 1.5, memory: 2.1 }, { name: 'redis', pid: 7890, cpu: 0.8, memory: 1.8 }, ]; return html`
Processes
Running processes and resource usage
Top Processes by CPU
Process PID CPU % Memory %
${topProcesses.map(proc => html`
${proc.name} ${proc.pid} ${proc.cpu}% ${proc.memory}%
`)}
`; } }