import * as plugins from '../plugins.js'; import * as shared from './shared/index.js'; import * as appstate from '../appstate.js'; import { DeesElement, customElement, html, state, css, cssManager, } from '@design.estate/dees-element'; @customElement('ops-view-overview') export class OpsViewOverview extends DeesElement { @state() private statsState: appstate.IStatsState = { serverStats: null, emailStats: null, dnsStats: null, securityMetrics: null, lastUpdated: 0, isLoading: false, error: null, }; constructor() { super(); const subscription = appstate.statsStatePart .select((stateArg) => stateArg) .subscribe((statsState) => { this.statsState = statsState; }); this.rxSubscriptions.push(subscription); } public static styles = [ cssManager.defaultStyles, shared.viewHostCss, css` .statsGrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-gap: 16px; margin-bottom: 40px; } .statCard { background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 8px; padding: 24px; } .statCard h3 { margin: 0 0 16px 0; font-size: 18px; font-weight: 600; color: #333; } .statValue { font-size: 32px; font-weight: 700; color: #2196F3; margin-bottom: 8px; } .statLabel { font-size: 14px; color: #666; } .chartGrid { display: grid; grid-template-columns: repeat(2, 1fr); grid-gap: 16px; margin-top: 32px; } .loadingMessage { text-align: center; padding: 40px; color: #666; } .errorMessage { background-color: #fee; border: 1px solid #fcc; border-radius: 4px; padding: 16px; color: #c00; margin: 16px 0; } `, ]; public render() { return html` Overview ${this.statsState.isLoading ? html`

Loading statistics...

` : this.statsState.error ? html`
Error loading statistics: ${this.statsState.error}
` : html`
${this.statsState.serverStats ? html`

Server Status

${this.statsState.serverStats.uptime ? 'Online' : 'Offline'}
Uptime: ${this.formatUptime(this.statsState.serverStats.uptime)}

Connections

${this.statsState.serverStats.activeConnections}
Active connections

Memory Usage

${this.formatBytes(this.statsState.serverStats.memoryUsage.heapUsed)}
of ${this.formatBytes(this.statsState.serverStats.memoryUsage.heapTotal)}

CPU Usage

${Math.round((this.statsState.serverStats.cpuUsage.user + this.statsState.serverStats.cpuUsage.system) / 2)}%
Average load
` : ''}
${this.statsState.emailStats ? html`

Email Statistics

Emails Sent

${this.statsState.emailStats.sent}
Total sent

Emails Received

${this.statsState.emailStats.received}
Total received

Failed Deliveries

${this.statsState.emailStats.failed}
Delivery failures

Queued

${this.statsState.emailStats.queued}
In queue
` : ''} ${this.statsState.dnsStats ? html`

DNS Statistics

DNS Queries

${this.statsState.dnsStats.totalQueries}
Total queries handled

Cache Hit Rate

${Math.round(this.statsState.dnsStats.cacheHitRate * 100)}%
Cache efficiency
` : ''}
`} `; } private formatUptime(seconds: number): string { const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (days > 0) { return `${days}d ${hours}h ${minutes}m`; } else if (hours > 0) { return `${hours}h ${minutes}m`; } else { return `${minutes}m`; } } private formatBytes(bytes: number): string { const units = ['B', 'KB', 'MB', 'GB', 'TB']; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } return `${size.toFixed(1)} ${units[unitIndex]}`; } }