UNPKG

@api.global/typedserver

Version:

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

421 lines (396 loc) 24 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, tableStyles, buttonStyles } from './sw-dash-styles.js'; /** * Events panel component for sw-dash * * Receives events via property from parent (sw-dash-app). * Filtering is done locally. * Load more and clear operations dispatch events to parent. */ let SwDashEvents = (() => { let _classDecorators = [customElement('sw-dash-events')]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = LitElement; let _events_decorators; let _events_initializers = []; let _events_extraInitializers = []; let _totalCount_decorators; let _totalCount_initializers = []; let _totalCount_extraInitializers = []; let _filter_decorators; let _filter_initializers = []; let _filter_extraInitializers = []; let _searchText_decorators; let _searchText_initializers = []; let _searchText_extraInitializers = []; let _isLoadingMore_decorators; let _isLoadingMore_initializers = []; let _isLoadingMore_extraInitializers = []; var SwDashEvents = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _events_decorators = [property({ type: Array })]; _totalCount_decorators = [property({ type: Number })]; _filter_decorators = [state()]; _searchText_decorators = [state()]; _isLoadingMore_decorators = [state()]; __esDecorate(this, null, _events_decorators, { kind: "accessor", name: "events", static: false, private: false, access: { has: obj => "events" in obj, get: obj => obj.events, set: (obj, value) => { obj.events = value; } }, metadata: _metadata }, _events_initializers, _events_extraInitializers); __esDecorate(this, null, _totalCount_decorators, { kind: "accessor", name: "totalCount", static: false, private: false, access: { has: obj => "totalCount" in obj, get: obj => obj.totalCount, set: (obj, value) => { obj.totalCount = value; } }, metadata: _metadata }, _totalCount_initializers, _totalCount_extraInitializers); __esDecorate(this, null, _filter_decorators, { kind: "accessor", name: "filter", static: false, private: false, access: { has: obj => "filter" in obj, get: obj => obj.filter, set: (obj, value) => { obj.filter = value; } }, metadata: _metadata }, _filter_initializers, _filter_extraInitializers); __esDecorate(this, null, _searchText_decorators, { kind: "accessor", name: "searchText", static: false, private: false, access: { has: obj => "searchText" in obj, get: obj => obj.searchText, set: (obj, value) => { obj.searchText = value; } }, metadata: _metadata }, _searchText_initializers, _searchText_extraInitializers); __esDecorate(this, null, _isLoadingMore_decorators, { kind: "accessor", name: "isLoadingMore", static: false, private: false, access: { has: obj => "isLoadingMore" in obj, get: obj => obj.isLoadingMore, set: (obj, value) => { obj.isLoadingMore = value; } }, metadata: _metadata }, _isLoadingMore_initializers, _isLoadingMore_extraInitializers); __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); SwDashEvents = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } static styles = [ sharedStyles, panelStyles, tableStyles, buttonStyles, css ` :host { display: block; } .events-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-4); gap: var(--space-3); flex-wrap: wrap; } .filter-group { display: flex; align-items: center; gap: var(--space-2); } .filter-label { font-size: 12px; color: var(--text-tertiary); } .filter-select { background: var(--bg-secondary); border: 1px solid var(--border-default); border-radius: var(--radius-sm); padding: var(--space-1) var(--space-2); color: var(--text-primary); font-size: 12px; } .filter-select:focus { outline: none; border-color: var(--accent-primary); } .events-list { display: flex; flex-direction: column; gap: var(--space-2); max-height: 600px; overflow-y: auto; } .event-card { background: var(--bg-secondary); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: var(--space-3); } .event-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-2); } .event-type { display: inline-flex; align-items: center; padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm); font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; } .event-type.sw { background: rgba(99, 102, 241, 0.15); color: var(--accent-primary); } .event-type.speedtest { background: rgba(59, 130, 246, 0.15); color: #3b82f6; } .event-type.network { background: rgba(34, 197, 94, 0.15); color: var(--accent-success); } .event-type.cache { background: rgba(251, 191, 36, 0.15); color: var(--accent-warning); } .event-type.error { background: rgba(239, 68, 68, 0.15); color: var(--accent-error); } .event-time { font-size: 11px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; } .event-message { font-size: 13px; color: var(--text-primary); margin-bottom: var(--space-2); } .event-details { font-size: 11px; color: var(--text-tertiary); background: var(--bg-tertiary); padding: var(--space-2); border-radius: var(--radius-sm); font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace; white-space: pre-wrap; word-break: break-all; } .stats-bar { display: flex; gap: var(--space-4); margin-bottom: var(--space-4); padding: var(--space-3); background: var(--bg-secondary); border-radius: var(--radius-md); border: 1px solid var(--border-default); } .stat-item { display: flex; flex-direction: column; gap: var(--space-1); } .stat-value { font-size: 18px; font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; } .stat-label { font-size: 11px; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.5px; } .empty-state { text-align: center; padding: var(--space-6); color: var(--text-tertiary); } .clear-btn { background: rgba(239, 68, 68, 0.1); color: var(--accent-error); border: 1px solid transparent; } .clear-btn:hover { background: rgba(239, 68, 68, 0.2); border-color: var(--accent-error); } .pagination { display: flex; justify-content: center; align-items: center; gap: var(--space-2); margin-top: var(--space-4); } .page-info { font-size: 12px; color: var(--text-tertiary); } ` ]; #events_accessor_storage = __runInitializers(this, _events_initializers, []); // Received from parent (sw-dash-app) get events() { return this.#events_accessor_storage; } set events(value) { this.#events_accessor_storage = value; } #totalCount_accessor_storage = (__runInitializers(this, _events_extraInitializers), __runInitializers(this, _totalCount_initializers, 0)); get totalCount() { return this.#totalCount_accessor_storage; } set totalCount(value) { this.#totalCount_accessor_storage = value; } #filter_accessor_storage = (__runInitializers(this, _totalCount_extraInitializers), __runInitializers(this, _filter_initializers, 'all')); // Local state for filtering get filter() { return this.#filter_accessor_storage; } set filter(value) { this.#filter_accessor_storage = value; } #searchText_accessor_storage = (__runInitializers(this, _filter_extraInitializers), __runInitializers(this, _searchText_initializers, '')); get searchText() { return this.#searchText_accessor_storage; } set searchText(value) { this.#searchText_accessor_storage = value; } #isLoadingMore_accessor_storage = (__runInitializers(this, _searchText_extraInitializers), __runInitializers(this, _isLoadingMore_initializers, false)); get isLoadingMore() { return this.#isLoadingMore_accessor_storage; } set isLoadingMore(value) { this.#isLoadingMore_accessor_storage = value; } handleFilterChange(e) { this.filter = e.target.value; // Local filtering - no HTTP request } handleSearch(e) { this.searchText = e.target.value.toLowerCase(); } handleClear() { if (!confirm('Are you sure you want to clear the event log? This cannot be undone.')) { return; } // Dispatch event to parent to clear via DeesComms this.dispatchEvent(new CustomEvent('clear-events', { bubbles: true, composed: true, })); } loadMore() { if (this.isLoadingMore || this.events.length === 0) return; this.isLoadingMore = true; const oldestEvent = this.events[this.events.length - 1]; // Dispatch event to parent to load more via DeesComms this.dispatchEvent(new CustomEvent('load-more-events', { detail: { before: oldestEvent.timestamp }, bubbles: true, composed: true, })); // Reset loading state after a short delay (parent will update events prop) setTimeout(() => { this.isLoadingMore = false; }, 1000); } getTypeClass(type) { if (type.startsWith('sw_')) return 'sw'; if (type.startsWith('speedtest_')) return 'speedtest'; if (type.startsWith('network_') || type.startsWith('backend_')) return 'network'; if (type.startsWith('cache_') || type === 'update_check') return 'cache'; if (type === 'error') return 'error'; return 'sw'; } formatTimestamp(ts) { const date = new Date(ts); return date.toLocaleString(); } formatTypeLabel(type) { return type.replace(/_/g, ' '); } /** * Filter events locally based on type and search text */ getFilteredEvents() { let result = this.events; // Filter by type if (this.filter !== 'all') { result = result.filter(e => e.type === this.filter); } // Filter by search text if (this.searchText) { result = result.filter(e => e.message.toLowerCase().includes(this.searchText) || e.type.toLowerCase().includes(this.searchText) || (e.details && JSON.stringify(e.details).toLowerCase().includes(this.searchText))); } return result; } render() { const filteredEvents = this.getFilteredEvents(); return html ` <div class="stats-bar"> <div class="stat-item"> <span class="stat-value">${this.totalCount}</span> <span class="stat-label">Total Events</span> </div> <div class="stat-item"> <span class="stat-value">${filteredEvents.length}</span> <span class="stat-label">Showing</span> </div> </div> <div class="events-header"> <div class="filter-group"> <span class="filter-label">Filter:</span> <select class="filter-select" @change="${this.handleFilterChange}"> <option value="all">All Events</option> <option value="sw_installed">SW Installed</option> <option value="sw_activated">SW Activated</option> <option value="sw_updated">SW Updated</option> <option value="speedtest_started">Speedtest Started</option> <option value="speedtest_completed">Speedtest Completed</option> <option value="speedtest_failed">Speedtest Failed</option> <option value="network_online">Network Online</option> <option value="network_offline">Network Offline</option> <option value="cache_invalidated">Cache Invalidated</option> <option value="error">Errors</option> </select> <input type="text" class="search-input" placeholder="Search events..." .value="${this.searchText}" @input="${this.handleSearch}" style="width: 200px;" > </div> <button class="btn clear-btn" @click="${this.handleClear}">Clear Log</button> </div> ${this.events.length === 0 ? html ` <div class="empty-state">No events recorded</div> ` : filteredEvents.length === 0 ? html ` <div class="empty-state">No events match filter</div> ` : html ` <div class="events-list"> ${filteredEvents.map(event => html ` <div class="event-card"> <div class="event-header"> <span class="event-type ${this.getTypeClass(event.type)}">${this.formatTypeLabel(event.type)}</span> <span class="event-time">${this.formatTimestamp(event.timestamp)}</span> </div> <div class="event-message">${event.message}</div> ${event.details ? html ` <div class="event-details">${JSON.stringify(event.details, null, 2)}</div> ` : ''} </div> `)} </div> ${this.events.length < this.totalCount ? html ` <div class="pagination"> <button class="btn btn-secondary" @click="${this.loadMore}" ?disabled="${this.isLoadingMore}"> ${this.isLoadingMore ? 'Loading...' : 'Load More'} </button> <span class="page-info">${this.events.length} of ${this.totalCount} events</span> </div> ` : ''} `} `; } constructor() { super(...arguments); __runInitializers(this, _isLoadingMore_extraInitializers); } static { __runInitializers(_classThis, _classExtraInitializers); } }; return SwDashEvents = _classThis; })(); export { SwDashEvents }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ctZGFzaC1ldmVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zd2Rhc2gvc3ctZGFzaC1ldmVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUVyRixPQUFPLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFnQjNGOzs7Ozs7R0FNRztJQUVVLFlBQVk7NEJBRHhCLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQzs7OztzQkFDRSxVQUFVOzs7Ozs7Ozs7Ozs7Ozs7OzRCQUFsQixTQUFRLFdBQVU7Ozs7a0NBMEt6QyxRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7c0NBQ3pCLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztrQ0FHMUIsS0FBSyxFQUFFO3NDQUNQLEtBQUssRUFBRTt5Q0FDUCxLQUFLLEVBQUU7WUFObUIsdUtBQVMsTUFBTSw2QkFBTixNQUFNLHVGQUF3QjtZQUN0QyxtTEFBUyxVQUFVLDZCQUFWLFVBQVUsK0ZBQUs7WUFHM0MsdUtBQVMsTUFBTSw2QkFBTixNQUFNLHVGQUF1QjtZQUN0QyxtTEFBUyxVQUFVLDZCQUFWLFVBQVUsK0ZBQU07WUFDekIsNExBQVMsYUFBYSw2QkFBYixhQUFhLHFHQUFTO1lBaEwxQyw2S0E0VUM7Ozs7UUEzVVEsTUFBTSxDQUFDLE1BQU0sR0FBZ0I7WUFDbEMsWUFBWTtZQUNaLFdBQVc7WUFDWCxXQUFXO1lBQ1gsWUFBWTtZQUNaLEdBQUcsQ0FBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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