import * as plugins from '../plugins.js'; import * as appstate from '../appstate.js'; import { appRouter } from '../router.js'; import { DeesElement, css, cssManager, customElement, html, state, type TemplateResult } from '@design.estate/dees-element'; // Import view components import { OpsViewOverview } from './ops-view-overview.js'; import { OpsViewNetwork } from './ops-view-network.js'; import { OpsViewEmails } from './ops-view-emails.js'; import { OpsViewLogs } from './ops-view-logs.js'; import { OpsViewConfig } from './ops-view-config.js'; import { OpsViewSecurity } from './ops-view-security.js'; @customElement('ops-dashboard') export class OpsDashboard extends DeesElement { @state() accessor loginState: appstate.ILoginState = { identity: null, isLoggedIn: false, }; @state() accessor uiState: appstate.IUiState = { activeView: 'overview', sidebarCollapsed: false, autoRefresh: true, refreshInterval: 1000, theme: 'light', }; // Store viewTabs as a property to maintain object references private viewTabs = [ { name: 'Overview', element: OpsViewOverview, }, { name: 'Network', element: OpsViewNetwork, }, { name: 'Emails', element: OpsViewEmails, }, { name: 'Logs', element: OpsViewLogs, }, { name: 'Configuration', element: OpsViewConfig, }, { name: 'Security', element: OpsViewSecurity, }, ]; /** * Get the current view tab based on the UI state's activeView. * Used to pass the correct selectedView to dees-simple-appdash on initial render. */ private get currentViewTab() { return this.viewTabs.find(t => t.name.toLowerCase() === this.uiState.activeView) || this.viewTabs[0]; } constructor() { super(); document.title = 'DCRouter OpsServer'; // Subscribe to login state const loginSubscription = appstate.loginStatePart .select((stateArg) => stateArg) .subscribe((loginState) => { this.loginState = loginState; // Trigger data fetch when logged in if (loginState.isLoggedIn) { appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null); appstate.configStatePart.dispatchAction(appstate.fetchConfigurationAction, null); } }); this.rxSubscriptions.push(loginSubscription); // Subscribe to UI state const uiSubscription = appstate.uiStatePart .select((stateArg) => stateArg) .subscribe((uiState) => { this.uiState = uiState; // Sync appdash view when state changes (e.g., from URL navigation) this.syncAppdashView(uiState.activeView); }); this.rxSubscriptions.push(uiSubscription); } /** * Sync the dees-simple-appdash view selection with the current state. * This is needed when the URL changes and we need to update the UI. */ private syncAppdashView(viewName: string): void { const appDash = this.shadowRoot?.querySelector('dees-simple-appdash') as any; if (!appDash) return; const targetTab = this.viewTabs.find(t => t.name.toLowerCase() === viewName); if (!targetTab) return; // Check if we need to switch (avoid unnecessary updates) if (appDash.selectedView === targetTab) return; // Update the selected view programmatically appDash.selectedView = targetTab; // Update the displayed content const content = appDash.shadowRoot?.querySelector('.appcontent'); if (content) { if (appDash.currentView) { appDash.currentView.remove(); } const view = new targetTab.element(); content.appendChild(view); appDash.currentView = view; } } public static styles = [ cssManager.defaultStyles, css` :host { display: block; width: 100%; height: 100vh; overflow: hidden; } .maincontainer { position: relative; width: 100%; height: 100%; } `, ]; public render(): TemplateResult { return html`