UNPKG

@api.global/typedserver

Version:

A TypeScript-based project for easy serving of static files with support for live reloading, compression, and typed requests.

328 lines (322 loc) 28.8 kB
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; import { LitElement, html, css, property, state, customElement } from './plugins.js'; import { sharedStyles, panelStyles, gaugeStyles, buttonStyles, speedtestStyles } from './sw-dash-styles.js'; import { SwDashTable } from './sw-dash-table.js'; /** * Overview panel component with metrics gauges and stats */ let SwDashOverview = (() => { let _classDecorators = [customElement('sw-dash-overview')]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = LitElement; let _metrics_decorators; let _metrics_initializers = []; let _metrics_extraInitializers = []; let _eventCountLastHour_decorators; let _eventCountLastHour_initializers = []; let _eventCountLastHour_extraInitializers = []; let _speedtestRunning_decorators; let _speedtestRunning_initializers = []; let _speedtestRunning_extraInitializers = []; let _speedtestPhase_decorators; let _speedtestPhase_initializers = []; let _speedtestPhase_extraInitializers = []; let _speedtestProgress_decorators; let _speedtestProgress_initializers = []; let _speedtestProgress_extraInitializers = []; let _speedtestElapsed_decorators; let _speedtestElapsed_initializers = []; let _speedtestElapsed_extraInitializers = []; var SwDashOverview = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _metrics_decorators = [property({ type: Object })]; _eventCountLastHour_decorators = [property({ type: Number })]; _speedtestRunning_decorators = [state()]; _speedtestPhase_decorators = [state()]; _speedtestProgress_decorators = [state()]; _speedtestElapsed_decorators = [state()]; __esDecorate(this, null, _metrics_decorators, { kind: "accessor", name: "metrics", static: false, private: false, access: { has: obj => "metrics" in obj, get: obj => obj.metrics, set: (obj, value) => { obj.metrics = value; } }, metadata: _metadata }, _metrics_initializers, _metrics_extraInitializers); __esDecorate(this, null, _eventCountLastHour_decorators, { kind: "accessor", name: "eventCountLastHour", static: false, private: false, access: { has: obj => "eventCountLastHour" in obj, get: obj => obj.eventCountLastHour, set: (obj, value) => { obj.eventCountLastHour = value; } }, metadata: _metadata }, _eventCountLastHour_initializers, _eventCountLastHour_extraInitializers); __esDecorate(this, null, _speedtestRunning_decorators, { kind: "accessor", name: "speedtestRunning", static: false, private: false, access: { has: obj => "speedtestRunning" in obj, get: obj => obj.speedtestRunning, set: (obj, value) => { obj.speedtestRunning = value; } }, metadata: _metadata }, _speedtestRunning_initializers, _speedtestRunning_extraInitializers); __esDecorate(this, null, _speedtestPhase_decorators, { kind: "accessor", name: "speedtestPhase", static: false, private: false, access: { has: obj => "speedtestPhase" in obj, get: obj => obj.speedtestPhase, set: (obj, value) => { obj.speedtestPhase = value; } }, metadata: _metadata }, _speedtestPhase_initializers, _speedtestPhase_extraInitializers); __esDecorate(this, null, _speedtestProgress_decorators, { kind: "accessor", name: "speedtestProgress", static: false, private: false, access: { has: obj => "speedtestProgress" in obj, get: obj => obj.speedtestProgress, set: (obj, value) => { obj.speedtestProgress = value; } }, metadata: _metadata }, _speedtestProgress_initializers, _speedtestProgress_extraInitializers); __esDecorate(this, null, _speedtestElapsed_decorators, { kind: "accessor", name: "speedtestElapsed", static: false, private: false, access: { has: obj => "speedtestElapsed" in obj, get: obj => obj.speedtestElapsed, set: (obj, value) => { obj.speedtestElapsed = value; } }, metadata: _metadata }, _speedtestElapsed_initializers, _speedtestElapsed_extraInitializers); __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); SwDashOverview = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } static styles = [ sharedStyles, panelStyles, gaugeStyles, buttonStyles, speedtestStyles, css ` :host { display: block; } .panel-content { padding: var(--space-4); } .section-divider { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--border-muted); } ` ]; #metrics_accessor_storage = __runInitializers(this, _metrics_initializers, null); get metrics() { return this.#metrics_accessor_storage; } set metrics(value) { this.#metrics_accessor_storage = value; } #eventCountLastHour_accessor_storage = (__runInitializers(this, _metrics_extraInitializers), __runInitializers(this, _eventCountLastHour_initializers, 0)); get eventCountLastHour() { return this.#eventCountLastHour_accessor_storage; } set eventCountLastHour(value) { this.#eventCountLastHour_accessor_storage = value; } #speedtestRunning_accessor_storage = (__runInitializers(this, _eventCountLastHour_extraInitializers), __runInitializers(this, _speedtestRunning_initializers, false)); get speedtestRunning() { return this.#speedtestRunning_accessor_storage; } set speedtestRunning(value) { this.#speedtestRunning_accessor_storage = value; } #speedtestPhase_accessor_storage = (__runInitializers(this, _speedtestRunning_extraInitializers), __runInitializers(this, _speedtestPhase_initializers, 'idle')); get speedtestPhase() { return this.#speedtestPhase_accessor_storage; } set speedtestPhase(value) { this.#speedtestPhase_accessor_storage = value; } #speedtestProgress_accessor_storage = (__runInitializers(this, _speedtestPhase_extraInitializers), __runInitializers(this, _speedtestProgress_initializers, 0)); get speedtestProgress() { return this.#speedtestProgress_accessor_storage; } set speedtestProgress(value) { this.#speedtestProgress_accessor_storage = value; } #speedtestElapsed_accessor_storage = (__runInitializers(this, _speedtestProgress_extraInitializers), __runInitializers(this, _speedtestElapsed_initializers, 0)); get speedtestElapsed() { return this.#speedtestElapsed_accessor_storage; } set speedtestElapsed(value) { this.#speedtestElapsed_accessor_storage = value; } // Speedtest timing constants (must match service worker) static TEST_DURATION_MS = 5000; // 5 seconds per test progressInterval = (__runInitializers(this, _speedtestElapsed_extraInitializers), null); async runSpeedtest() { if (this.speedtestRunning) return; this.speedtestRunning = true; this.speedtestPhase = 'latency'; this.speedtestProgress = 0; this.speedtestElapsed = 0; // Start progress animation (total ~10.5s: latency ~0.5s + 5s download + 5s upload) const totalEstimatedMs = 10500; const startTime = Date.now(); this.progressInterval = window.setInterval(() => { this.speedtestElapsed = Date.now() - startTime; this.speedtestProgress = Math.min(100, (this.speedtestElapsed / totalEstimatedMs) * 100); // Estimate phase based on elapsed time if (this.speedtestElapsed < 500) { this.speedtestPhase = 'latency'; } else if (this.speedtestElapsed < 5500) { this.speedtestPhase = 'download'; } else { this.speedtestPhase = 'upload'; } }, 100); try { const response = await fetch('/sw-dash/speedtest'); const result = await response.json(); this.speedtestPhase = 'complete'; this.speedtestProgress = 100; // Dispatch event to parent to update metrics this.dispatchEvent(new CustomEvent('speedtest-complete', { detail: result, bubbles: true, composed: true })); } catch (err) { console.error('Speedtest failed:', err); this.speedtestPhase = 'idle'; } finally { if (this.progressInterval) { window.clearInterval(this.progressInterval); this.progressInterval = null; } // Keep showing complete state briefly, then reset setTimeout(() => { this.speedtestRunning = false; this.speedtestPhase = 'idle'; this.speedtestProgress = 0; }, 1500); } } getPhaseLabel() { switch (this.speedtestPhase) { case 'latency': return 'Testing latency'; case 'download': return 'Download test'; case 'upload': return 'Upload test'; case 'complete': return 'Complete'; default: return ''; } } formatElapsed() { const seconds = Math.floor(this.speedtestElapsed / 1000); return `${seconds}s`; } render() { if (!this.metrics) { return html `<div class="panel"><div class="panel-content">Loading metrics...</div></div>`; } const m = this.metrics; const gaugeClass = SwDashTable.getGaugeClass; return html ` <div class="grid"> <!-- Cache Panel --> <div class="panel"> <div class="panel-title">Cache</div> <div class="panel-content"> <div class="gauge"> <div class="gauge-header"> <span class="gauge-label">Hit Rate</span> <span class="gauge-value">${m.cacheHitRate}%</span> </div> <div class="gauge-bar"> <div class="gauge-fill ${gaugeClass(m.cacheHitRate)}" style="width: ${m.cacheHitRate}%"></div> </div> </div> <div class="row"><span class="label">Hits</span><span class="value success">${SwDashTable.formatNumber(m.cache.hits)}</span></div> <div class="row"><span class="label">Misses</span><span class="value warning">${SwDashTable.formatNumber(m.cache.misses)}</span></div> <div class="row"><span class="label">Errors</span><span class="value ${m.cache.errors > 0 ? 'error' : ''}">${SwDashTable.formatNumber(m.cache.errors)}</span></div> <div class="row"><span class="label">From Cache</span><span class="value">${SwDashTable.formatBytes(m.cache.bytesServedFromCache)}</span></div> <div class="row"><span class="label">Fetched</span><span class="value">${SwDashTable.formatBytes(m.cache.bytesFetched)}</span></div> <div class="row"><span class="label">Resources</span><span class="value">${m.resourceCount}</span></div> </div> </div> <!-- Network Panel --> <div class="panel"> <div class="panel-title">Network</div> <div class="panel-content"> <div class="gauge"> <div class="gauge-header"> <span class="gauge-label">Success Rate</span> <span class="gauge-value">${m.networkSuccessRate}%</span> </div> <div class="gauge-bar"> <div class="gauge-fill ${gaugeClass(m.networkSuccessRate)}" style="width: ${m.networkSuccessRate}%"></div> </div> </div> <div class="row"><span class="label">Total Requests</span><span class="value">${SwDashTable.formatNumber(m.network.totalRequests)}</span></div> <div class="row"><span class="label">Successful</span><span class="value success">${SwDashTable.formatNumber(m.network.successfulRequests)}</span></div> <div class="row"><span class="label">Failed</span><span class="value ${m.network.failedRequests > 0 ? 'error' : ''}">${SwDashTable.formatNumber(m.network.failedRequests)}</span></div> <div class="row"><span class="label">Timeouts</span><span class="value ${m.network.timeouts > 0 ? 'warning' : ''}">${SwDashTable.formatNumber(m.network.timeouts)}</span></div> <div class="row"><span class="label">Avg Latency</span><span class="value">${m.network.averageLatency}ms</span></div> <div class="row"><span class="label">Transferred</span><span class="value">${SwDashTable.formatBytes(m.network.totalBytesTransferred)}</span></div> </div> </div> <!-- Updates Panel --> <div class="panel"> <div class="panel-title">Updates</div> <div class="panel-content"> <div class="row"><span class="label">Total Checks</span><span class="value">${SwDashTable.formatNumber(m.update.totalChecks)}</span></div> <div class="row"><span class="label">Successful</span><span class="value success">${SwDashTable.formatNumber(m.update.successfulChecks)}</span></div> <div class="row"><span class="label">Failed</span><span class="value ${m.update.failedChecks > 0 ? 'error' : ''}">${SwDashTable.formatNumber(m.update.failedChecks)}</span></div> <div class="row"><span class="label">Updates Found</span><span class="value">${SwDashTable.formatNumber(m.update.updatesFound)}</span></div> <div class="row"><span class="label">Updates Applied</span><span class="value success">${SwDashTable.formatNumber(m.update.updatesApplied)}</span></div> <div class="row"><span class="label">Last Check</span><span class="value">${SwDashTable.formatTimestamp(m.update.lastCheckTimestamp)}</span></div> </div> </div> <!-- Connections Panel --> <div class="panel"> <div class="panel-title">Connections</div> <div class="panel-content"> <div class="row"><span class="label">Active Clients</span><span class="value success">${SwDashTable.formatNumber(m.connection.connectedClients)}</span></div> <div class="row"><span class="label">Total Attempts</span><span class="value">${SwDashTable.formatNumber(m.connection.totalConnectionAttempts)}</span></div> <div class="row"><span class="label">Successful</span><span class="value success">${SwDashTable.formatNumber(m.connection.successfulConnections)}</span></div> <div class="row"><span class="label">Failed</span><span class="value ${m.connection.failedConnections > 0 ? 'error' : ''}">${SwDashTable.formatNumber(m.connection.failedConnections)}</span></div> <div class="section-divider"> <div class="row"><span class="label">Events (1h)</span><span class="value">${this.eventCountLastHour}</span></div> <div class="row"><span class="label">Started</span><span class="value">${SwDashTable.formatTimestamp(m.startTime)}</span></div> </div> </div> </div> <!-- Speedtest Panel --> <div class="panel"> <div class="panel-title">Speedtest</div> <div class="panel-content"> <div class="online-indicator ${m.speedtest.isOnline ? 'online' : 'offline'}"> <span class="online-dot"></span> <span>${m.speedtest.isOnline ? 'Online' : 'Offline'}</span> </div> ${this.speedtestRunning ? html ` <div class="speedtest-progress"> <div class="progress-header"> <span class="progress-phase">${this.getPhaseLabel()}</span> <span class="progress-time">${this.formatElapsed()}</span> </div> <div class="progress-bar"> <div class="progress-fill ${this.speedtestPhase === 'complete' ? 'complete' : ''}" style="width: ${this.speedtestProgress}%"></div> </div> </div> ` : html ` <div class="speedtest-results"> <div class="speedtest-metric"> <div class="speedtest-value">${m.speedtest.lastDownloadSpeedMbps.toFixed(1)}</div> <div class="speedtest-unit">Mbps</div> <div class="speedtest-label">Download</div> </div> <div class="speedtest-metric"> <div class="speedtest-value">${m.speedtest.lastUploadSpeedMbps.toFixed(1)}</div> <div class="speedtest-unit">Mbps</div> <div class="speedtest-label">Upload</div> </div> <div class="speedtest-metric"> <div class="speedtest-value">${m.speedtest.lastLatencyMs.toFixed(0)}</div> <div class="speedtest-unit">ms</div> <div class="speedtest-label">Latency</div> </div> </div> `} <div class="btn-row"> <button class="btn btn-secondary" ?disabled="${this.speedtestRunning}" @click="${this.runSpeedtest}"> ${this.speedtestRunning ? 'Testing...' : 'Run Test'} </button> </div> </div> </div> </div> `; } static { __runInitializers(_classThis, _classExtraInitializers); } }; return SwDashOverview = _classThis; })(); export { SwDashOverview }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ctZGFzaC1vdmVydmlldy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3N3ZGFzaC9zdy1kYXNoLW92ZXJ2aWV3LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFckYsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM1RyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFpRGpEOztHQUVHO0lBRVUsY0FBYzs0QkFEMUIsYUFBYSxDQUFDLGtCQUFrQixDQUFDOzs7O3NCQUNFLFVBQVU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OEJBQWxCLFNBQVEsV0FBVTs7OzttQ0F3QjNDLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQzs4Q0FDMUIsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOzRDQUMxQixLQUFLLEVBQUU7MENBQ1AsS0FBSyxFQUFFOzZDQUNQLEtBQUssRUFBRTs0Q0FDUCxLQUFLLEVBQUU7WUFMb0IsMEtBQVMsT0FBTyw2QkFBUCxPQUFPLHlGQUE2QjtZQUM3QywyTUFBUyxrQkFBa0IsNkJBQWxCLGtCQUFrQiwrR0FBSztZQUNuRCxxTUFBUyxnQkFBZ0IsNkJBQWhCLGdCQUFnQiwyR0FBUztZQUNsQywrTEFBUyxjQUFjLDZCQUFkLGNBQWMsdUdBQW1FO1lBQzFGLHdNQUFTLGlCQUFpQiw2QkFBakIsaUJBQWlCLDZHQUFLO1lBQy9CLHFNQUFTLGdCQUFnQiw2QkFBaEIsZ0JBQWdCLDJHQUFLO1lBN0J6Qyw2S0EwT0M7Ozs7UUF6T1EsTUFBTSxDQUFD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