Files
catalog/ts_web/views/eco-view-system/eco-view-system.ts
2026-01-12 10:57:54 +00:00

878 lines
22 KiB
TypeScript

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';
// Mock system data
@state()
accessor cpuUsage = 42;
@state()
accessor memoryUsage = 67;
@state()
accessor diskUsage = 54;
@state()
accessor cpuTemp = 58;
@state()
accessor uptime = '14d 7h 32m';
@state()
accessor networkIn = [45, 52, 38, 65, 72, 68, 75, 82, 79, 85, 88, 72];
@state()
accessor networkOut = [32, 28, 35, 42, 38, 45, 52, 48, 55, 62, 58, 65];
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`
<div class="system-container">
<dees-appui-secondarymenu
.heading=${'System'}
.groups=${this.getMenuGroups()}
.selectedItem=${this.getSelectedItem()}
></dees-appui-secondarymenu>
<div class="content">
${this.renderActivePanel()}
</div>
</div>
`;
}
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',
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: 'processes',
title: 'Processes',
value: 247,
type: 'number' as const,
icon: 'lucide:layers',
description: '12 running, 235 sleeping',
},
];
return html`
<div class="panel-header">
<div class="panel-title">System Overview</div>
<div class="panel-description">Real-time system performance metrics</div>
</div>
<div class="stats-section">
<dees-statsgrid
.tiles=${overviewTiles}
.minTileWidth=${220}
.gap=${16}
></dees-statsgrid>
</div>
`;
}
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`
<div class="panel-header">
<div class="panel-title">CPU</div>
<div class="panel-description">Processor usage and performance</div>
</div>
<div class="stats-section">
<dees-statsgrid
.tiles=${cpuTiles}
.minTileWidth=${200}
.gap=${16}
></dees-statsgrid>
</div>
`;
}
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`
<div class="panel-header">
<div class="panel-title">Memory</div>
<div class="panel-description">RAM and swap usage details</div>
</div>
<div class="stats-section">
<dees-statsgrid
.tiles=${memoryTiles}
.minTileWidth=${220}
.gap=${16}
></dees-statsgrid>
</div>
`;
}
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`
<div class="panel-header">
<div class="panel-title">Storage</div>
<div class="panel-description">Disk usage and I/O performance</div>
</div>
<div class="stats-section">
<dees-statsgrid
.tiles=${storageTiles}
.minTileWidth=${220}
.gap=${16}
></dees-statsgrid>
</div>
`;
}
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`
<div class="panel-header">
<div class="panel-title">Network</div>
<div class="panel-description">Network traffic and connectivity</div>
</div>
<div class="stats-section">
<dees-statsgrid
.tiles=${networkTiles}
.minTileWidth=${220}
.gap=${16}
></dees-statsgrid>
</div>
`;
}
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`
<div class="panel-header">
<div class="panel-title">Processes</div>
<div class="panel-description">Running processes and resource usage</div>
</div>
<div class="stats-section">
<dees-statsgrid
.tiles=${processTiles}
.minTileWidth=${180}
.gap=${16}
></dees-statsgrid>
</div>
<div class="stats-section">
<div class="section-title">Top Processes by CPU</div>
<div class="process-list">
<div class="process-header">
<span>Process</span>
<span>PID</span>
<span>CPU %</span>
<span>Memory %</span>
</div>
${topProcesses.map(proc => html`
<div class="process-row">
<span class="process-name">${proc.name}</span>
<span class="process-value">${proc.pid}</span>
<span class="process-value ${proc.cpu > 10 ? 'high' : ''}">${proc.cpu}%</span>
<span class="process-value ${proc.memory > 10 ? 'high' : ''}">${proc.memory}%</span>
</div>
`)}
</div>
</div>
`;
}
}