Files
eco_os/ecoos_daemon/ts_web/elements/ecoos-overview.ts

194 lines
5.6 KiB
TypeScript
Raw Normal View History

/**
* EcoOS Overview View
* Shows services status, CPU, memory, system info, and controls
*/
import {
html,
DeesElement,
customElement,
property,
css,
type TemplateResult,
} from '@design.estate/dees-element';
import { sharedStyles, formatBytes, formatUptime } from '../styles/shared.js';
import type { IStatus, IServiceStatus } from '../../ts_interfaces/status.js';
@customElement('ecoos-overview')
export class EcoosOverview extends DeesElement {
@property({ type: Object })
public accessor status: IStatus | null = null;
@property({ type: Boolean })
public accessor loading: boolean = false;
public static styles = [
sharedStyles,
css`
:host {
display: block;
padding: 20px;
}
.service-status {
display: flex;
align-items: center;
padding: 8px 0;
}
.controls-section {
margin-top: 16px;
}
.control-status {
margin-top: 8px;
font-size: 12px;
color: var(--ecoos-text-dim);
}
`,
];
render(): TemplateResult {
if (!this.status) {
return html`<div>Loading...</div>`;
}
const { systemInfo, sway, chromium, swayStatus, chromiumStatus } = this.status;
return html`
<div class="grid">
<!-- Services Card -->
<div class="card">
<div class="card-title">Services</div>
<div class="service-status">
<span class="status-dot ${this.getStatusClass(swayStatus)}"></span>
<span>Sway Compositor</span>
</div>
<div class="service-status">
<span class="status-dot ${this.getStatusClass(chromiumStatus)}"></span>
<span>Chromium Browser</span>
</div>
</div>
<!-- CPU Card -->
<div class="card">
<div class="card-title">CPU</div>
<div class="stat">
<div class="stat-label">Model</div>
<div class="stat-value">${systemInfo?.cpu?.model || '-'}</div>
</div>
<div class="stat">
<div class="stat-label">Cores</div>
<div class="stat-value">${systemInfo?.cpu?.cores || '-'}</div>
</div>
<div class="stat">
<div class="stat-label">Usage</div>
<div class="stat-value">${systemInfo?.cpu?.usage || 0}%</div>
<div class="progress-bar">
<div class="progress-fill" style="width: ${systemInfo?.cpu?.usage || 0}%"></div>
</div>
</div>
</div>
<!-- Memory Card -->
<div class="card">
<div class="card-title">Memory</div>
<div class="stat">
<div class="stat-label">Used / Total</div>
<div class="stat-value">
${formatBytes(systemInfo?.memory?.used || 0)} / ${formatBytes(systemInfo?.memory?.total || 0)}
</div>
<div class="progress-bar">
<div class="progress-fill" style="width: ${systemInfo?.memory?.usagePercent || 0}%"></div>
</div>
</div>
</div>
<!-- System Card -->
<div class="card">
<div class="card-title">System</div>
<div class="stat">
<div class="stat-label">Hostname</div>
<div class="stat-value">${systemInfo?.hostname || '-'}</div>
</div>
<div class="stat">
<div class="stat-label">Uptime</div>
<div class="stat-value">${formatUptime(systemInfo?.uptime || 0)}</div>
</div>
<div class="stat">
<div class="stat-label">GPU</div>
<div class="stat-value">
${systemInfo?.gpu?.length ? systemInfo.gpu.map(g => g.name).join(', ') : 'None detected'}
</div>
</div>
</div>
<!-- Controls Card -->
<div class="card">
<div class="card-title">Controls</div>
<button
class="btn btn-primary"
@click=${this.restartChromium}
?disabled=${this.loading || !sway}
>
Restart Browser
</button>
<button
class="btn btn-danger"
@click=${this.rebootSystem}
?disabled=${this.loading}
>
Reboot System
</button>
<div class="control-status" id="control-status"></div>
</div>
</div>
`;
}
private getStatusClass(status: IServiceStatus): string {
switch (status?.state) {
case 'running': return 'running';
case 'starting': return 'starting';
default: return 'stopped';
}
}
private async restartChromium(): Promise<void> {
this.loading = true;
try {
const response = await fetch('/api/restart-chromium', { method: 'POST' });
const result = await response.json();
this.showControlStatus(result.message, !result.success);
} catch (error) {
this.showControlStatus(`Error: ${error}`, true);
} finally {
this.loading = false;
}
}
private async rebootSystem(): Promise<void> {
if (!confirm('Are you sure you want to reboot the system?')) return;
this.loading = true;
try {
const response = await fetch('/api/reboot', { method: 'POST' });
const result = await response.json();
this.showControlStatus(result.message, !result.success);
} catch (error) {
this.showControlStatus(`Error: ${error}`, true);
} finally {
this.loading = false;
}
}
private showControlStatus(message: string, isError: boolean): void {
const el = this.shadowRoot?.getElementById('control-status');
if (el) {
el.textContent = message;
el.style.color = isError ? 'var(--ecoos-error)' : 'var(--ecoos-success)';
}
}
}