/** * EcoOS Devices View * Card-based view for network, storage, input, and audio devices */ import { html, DeesElement, customElement, property, css, type TemplateResult, } from '@design.estate/dees-element'; import { DeesPanel, DeesBadge } from '@design.estate/dees-catalog'; import { sharedStyles, formatBytes } from '../styles/shared.js'; import type { ISystemInfo } from '../../ts_interfaces/status.js'; @customElement('ecoos-devices') export class EcoosDevices extends DeesElement { @property({ type: Object }) public accessor systemInfo: ISystemInfo | null = null; public static styles = [ sharedStyles, css` :host { display: block; padding: 16px; } .cards-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; } @media (max-width: 768px) { .cards-grid { grid-template-columns: 1fr; } } .device-row { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--border); gap: 12px; } .device-row:last-child { border-bottom: none; padding-bottom: 0; } .device-row:first-child { padding-top: 0; } .device-name { font-weight: 500; font-size: var(--text-sm); flex-shrink: 0; } .device-info { flex: 1; text-align: right; font-family: 'SF Mono', monospace; font-size: var(--text-xs); color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .device-secondary { font-size: var(--text-xs); color: var(--text-tertiary); margin-top: 2px; } .progress-mini { width: 60px; height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; flex-shrink: 0; } .progress-mini-bar { height: 100%; background: var(--accent); transition: width 300ms ease; } .progress-mini-bar.warning { background: var(--warning); } .progress-mini-bar.error { background: var(--error); } .usage-info { display: flex; align-items: center; gap: 8px; } .usage-text { font-size: var(--text-xs); color: var(--text-secondary); font-family: 'SF Mono', monospace; } .empty-text { font-size: var(--text-sm); color: var(--text-tertiary); padding: 8px 0; } `, ]; render(): TemplateResult { if (!this.systemInfo) { return html`
Loading...
`; } return html`
${this.systemInfo.network?.length ? this.systemInfo.network.map(n => html`
${n.name} ${n.ip || '—'} ${n.state}
`) : html`
No network interfaces
` }
${this.systemInfo.disks?.length ? this.systemInfo.disks.map(d => html`
${d.mountpoint}
${d.device}
${formatBytes(d.used)} / ${formatBytes(d.total)}
`) : html`
No disks
` }
${this.systemInfo.inputDevices?.length ? this.systemInfo.inputDevices.map(d => html`
${d.name} ${d.type}
`) : html`
No input devices
` }
${this.systemInfo.speakers?.length ? this.systemInfo.speakers.map(s => html`
${s.description} ${s.isDefault ? html`Default` : ''}
`) : html`
No speakers
` }
${this.systemInfo.microphones?.length ? this.systemInfo.microphones.map(m => html`
${m.description} ${m.isDefault ? html`Default` : ''}
`) : html`
No microphones
` }
`; } private getUsageClass(usage: number): string { if (usage > 90) return 'error'; if (usage > 75) return 'warning'; return ''; } }