import { DeesElement, customElement, html, css, cssManager, state, type TemplateResult } from '../plugins.js'; import { deesCatalog } from '../plugins.js'; import type { IView } from '@design.estate/dees-catalog'; import { NotificationManager } from '../state/notification-manager.js'; import { appRouter, type TSubviewSlug, type TViewSlug } from '../router.js'; import { SipproxyViewOverview } from './sipproxy-view-overview.js'; import { SipproxyViewCalls } from './sipproxy-view-calls.js'; import { SipproxyViewPhone } from './sipproxy-view-phone.js'; import { SipproxyViewContacts } from './sipproxy-view-contacts.js'; import { SipproxyViewProviders } from './sipproxy-view-providers.js'; import { SipproxyViewLog } from './sipproxy-view-log.js'; import { SipproxyViewRoutes } from './sipproxy-view-routes.js'; import { SipproxyViewVoicemail } from './sipproxy-view-voicemail.js'; import { SipproxyViewIvr } from './sipproxy-view-ivr.js'; interface ITabbedView extends IView { slug?: string; subViews?: ITabbedView[]; } const VIEW_TABS: ITabbedView[] = [ { name: 'Overview', slug: 'overview', iconName: 'lucide:layoutDashboard', subViews: [ { name: 'Stats', slug: 'stats', iconName: 'lucide:activity', element: SipproxyViewOverview }, ], }, { name: 'Telephony', slug: 'telephony', iconName: 'lucide:phoneCall', subViews: [ { name: 'Calls', slug: 'calls', iconName: 'lucide:phone', element: SipproxyViewCalls }, { name: 'Phone', slug: 'phone', iconName: 'lucide:headset', element: SipproxyViewPhone }, { name: 'Routes', slug: 'routes', iconName: 'lucide:route', element: SipproxyViewRoutes }, { name: 'Voicemail', slug: 'voicemail', iconName: 'lucide:voicemail', element: SipproxyViewVoicemail }, { name: 'IVR', slug: 'ivr', iconName: 'lucide:ListTree', element: SipproxyViewIvr }, ], }, { name: 'Configuration', slug: 'configuration', iconName: 'lucide:settings', subViews: [ { name: 'Contacts', slug: 'contacts', iconName: 'lucide:contactRound', element: SipproxyViewContacts }, { name: 'Providers', slug: 'providers', iconName: 'lucide:server', element: SipproxyViewProviders }, ], }, { name: 'System', slug: 'system', iconName: 'lucide:serverCog', subViews: [ { name: 'Log', slug: 'log', iconName: 'lucide:scrollText', element: SipproxyViewLog }, ], }, ]; @customElement('sipproxy-app') export class SipproxyApp extends DeesElement { private notificationManager = new NotificationManager(); private appdash: InstanceType | null = null; private viewTabs = VIEW_TABS; public static styles = [ cssManager.defaultStyles, css` :host { display: block; height: 100%; } dees-simple-appdash { height: 100%; } `, ]; private suppressViewSelectEvent = false; private slugFor(view: ITabbedView): string { return view.slug ?? view.name.toLowerCase().replace(/\s+/g, ''); } private findParent(view: ITabbedView): ITabbedView | undefined { return this.viewTabs.find((tab) => tab.subViews?.includes(view)); } private findViewBySlug(viewSlug: string, subviewSlug: string): ITabbedView | undefined { const top = this.viewTabs.find((tab) => this.slugFor(tab) === viewSlug); if (!top) return undefined; return top.subViews?.find((subview) => this.slugFor(subview) === subviewSlug) ?? top; } private get currentViewTab(): ITabbedView { const currentRoute = appRouter.getCurrentRoute(); return this.findViewBySlug(currentRoute.view, currentRoute.subview) ?? this.viewTabs[0].subViews![0]; } async firstUpdated() { this.appdash = this.shadowRoot?.querySelector('dees-simple-appdash') as InstanceType; if (this.appdash) { this.notificationManager.init(this.appdash); // Listen for user tab selections and sync grouped URLs. this.appdash.addEventListener('view-select', ((e: CustomEvent) => { if (this.suppressViewSelectEvent) return; const view = e.detail?.view as ITabbedView | undefined; if (!view) return; const parent = this.findParent(view); if (!parent) return; const parentSlug = this.slugFor(parent) as TViewSlug; const subviewSlug = this.slugFor(view) as TSubviewSlug; if (!appRouter.isCurrentRoute(parentSlug, subviewSlug)) { appRouter.navigateToView(parentSlug, subviewSlug, true); } }) as EventListener); // Wire up router -> appdash (for browser back/forward). appRouter.setNavigateHandler((view, subview) => { const tab = this.findViewBySlug(view, subview); if (tab && this.appdash) { this.suppressViewSelectEvent = true; this.appdash.loadView(tab); this.suppressViewSelectEvent = false; } }); const initialTab = this.currentViewTab; if (initialTab) { this.suppressViewSelectEvent = true; this.appdash.loadView(initialTab); this.suppressViewSelectEvent = false; } } } public async disconnectedCallback() { await super.disconnectedCallback(); this.notificationManager.destroy(); } public render(): TemplateResult { return html` `; } }