import { LitElement, html, css, state, customElement } from './plugins.js'; import type { CSSResult, TemplateResult } from './plugins.js'; import { sharedStyles, terminalStyles, navStyles } from './sw-dash-styles.js'; import type { IMetricsData } from './sw-dash-overview.js'; import type { ICachedResource } from './sw-dash-urls.js'; import type { IDomainStats } from './sw-dash-domains.js'; import type { IContentTypeStats } from './sw-dash-types.js'; // Import components to register them import './sw-dash-overview.js'; import './sw-dash-urls.js'; import './sw-dash-domains.js'; import './sw-dash-types.js'; import './sw-dash-table.js'; type ViewType = 'overview' | 'urls' | 'domains' | 'types'; interface IResourceData { resources: ICachedResource[]; domains: IDomainStats[]; contentTypes: IContentTypeStats[]; resourceCount: number; } /** * Main SW Dashboard application shell */ @customElement('sw-dash-app') export class SwDashApp extends LitElement { public static styles: CSSResult[] = [ sharedStyles, terminalStyles, navStyles, css` :host { display: block; background: var(--sw-bg-dark); min-height: 100vh; padding: 20px; } .view { display: none; } .view.active { display: block; } ` ]; @state() accessor currentView: ViewType = 'overview'; @state() accessor metrics: IMetricsData | null = null; @state() accessor resourceData: IResourceData = { resources: [], domains: [], contentTypes: [], resourceCount: 0 }; @state() accessor lastRefresh = new Date().toLocaleTimeString(); private refreshInterval: ReturnType | null = null; connectedCallback(): void { super.connectedCallback(); this.loadMetrics(); this.loadResourceData(); // Auto-refresh every 2 seconds this.refreshInterval = setInterval(() => { this.loadMetrics(); if (this.currentView !== 'overview') { this.loadResourceData(); } }, 2000); } disconnectedCallback(): void { super.disconnectedCallback(); if (this.refreshInterval) { clearInterval(this.refreshInterval); } } private async loadMetrics(): Promise { try { const response = await fetch('/sw-dash/metrics'); this.metrics = await response.json(); this.lastRefresh = new Date().toLocaleTimeString(); } catch (err) { console.error('Failed to load metrics:', err); } } private async loadResourceData(): Promise { try { const response = await fetch('/sw-dash/resources'); this.resourceData = await response.json(); } catch (err) { console.error('Failed to load resources:', err); } } private setView(view: ViewType): void { this.currentView = view; if (view !== 'overview') { this.loadResourceData(); } } private handleSpeedtestComplete(_e: CustomEvent): void { // Refresh metrics after speedtest this.loadMetrics(); } private formatUptime(ms: number): string { const s = Math.floor(ms / 1000); const m = Math.floor(s / 60); const h = Math.floor(m / 60); const d = Math.floor(h / 24); if (d > 0) return `${d}d ${h % 24}h`; if (h > 0) return `${h}h ${m % 60}m`; if (m > 0) return `${m}m ${s % 60}s`; return `${s}s`; } public render(): TemplateResult { return html`
[SW-DASH] Service Worker Dashboard Uptime: ${this.metrics ? this.formatUptime(this.metrics.uptime) : '...'}
`; } }