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

128 lines
3.0 KiB
TypeScript

/**
* EcoOS Logs View
* Tabbed log viewer for daemon and system logs with auto-scroll
*/
import {
html,
DeesElement,
customElement,
property,
state,
css,
type TemplateResult,
} from '@design.estate/dees-element';
import { sharedStyles } from '../styles/shared.js';
@customElement('ecoos-logs')
export class EcoosLogs extends DeesElement {
@property({ type: Array })
public accessor daemonLogs: string[] = [];
@property({ type: Array })
public accessor systemLogs: string[] = [];
@state()
private accessor activeTab: 'daemon' | 'system' = 'daemon';
public static styles = [
sharedStyles,
css`
:host {
display: block;
padding: 20px;
}
.logs-container {
background: var(--ecoos-card);
border: 1px solid var(--ecoos-border);
border-radius: 8px;
overflow: hidden;
}
.logs-header {
padding: 12px 16px;
border-bottom: 1px solid var(--ecoos-border);
}
.logs-content {
height: 500px;
overflow-y: auto;
font-family: 'SF Mono', Monaco, monospace;
font-size: 12px;
line-height: 1.6;
background: #0d0d0d;
padding: 12px;
}
.log-entry {
white-space: pre-wrap;
word-break: break-all;
padding: 2px 0;
}
.empty-message {
color: var(--ecoos-text-dim);
padding: 20px;
text-align: center;
}
`,
];
render(): TemplateResult {
const logs = this.activeTab === 'daemon' ? this.daemonLogs : this.systemLogs;
return html`
<div class="logs-container">
<div class="logs-header">
<div class="tabs">
<div
class="tab ${this.activeTab === 'daemon' ? 'active' : ''}"
@click=${() => this.switchTab('daemon')}
>
Daemon Logs
</div>
<div
class="tab ${this.activeTab === 'system' ? 'active' : ''}"
@click=${() => this.switchTab('system')}
>
System Logs
</div>
</div>
</div>
<div class="logs-content" id="logs-content">
${logs.length === 0
? html`<div class="empty-message">No logs available</div>`
: logs.map(log => html`<div class="log-entry">${log}</div>`)
}
</div>
</div>
`;
}
private switchTab(tab: 'daemon' | 'system'): void {
this.activeTab = tab;
this.scrollToBottom();
}
updated(changedProperties: Map<string, unknown>): void {
super.updated(changedProperties);
// Auto-scroll when logs change
if (changedProperties.has('daemonLogs') || changedProperties.has('systemLogs')) {
this.scrollToBottom();
}
}
private scrollToBottom(): void {
requestAnimationFrame(() => {
const content = this.shadowRoot?.getElementById('logs-content');
if (content) {
content.scrollTop = content.scrollHeight;
}
});
}
}