feat(web-ui): reorganize network and security views into tabbed subviews with route-aware navigation
This commit is contained in:
119
ts_web/elements/network/ops-view-network.ts
Normal file
119
ts_web/elements/network/ops-view-network.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import * as appstate from '../../appstate.js';
|
||||
import { appRouter } from '../../router.js';
|
||||
import { viewHostCss } from '../shared/css.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
type TemplateResult,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
// Side-effect imports register the subview custom elements
|
||||
import './ops-view-network-activity.js';
|
||||
import './ops-view-routes.js';
|
||||
import './ops-view-sourceprofiles.js';
|
||||
import './ops-view-networktargets.js';
|
||||
import './ops-view-targetprofiles.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'ops-view-network': OpsViewNetwork;
|
||||
}
|
||||
}
|
||||
|
||||
type TNetworkTab = 'activity' | 'routes' | 'sourceprofiles' | 'networktargets' | 'targetprofiles';
|
||||
|
||||
@customElement('ops-view-network')
|
||||
export class OpsViewNetwork extends DeesElement {
|
||||
@state()
|
||||
accessor selectedTab: TNetworkTab = 'activity';
|
||||
|
||||
private tabLabelMap: Record<TNetworkTab, string> = {
|
||||
'activity': 'Network Activity',
|
||||
'routes': 'Routes',
|
||||
'sourceprofiles': 'Source Profiles',
|
||||
'networktargets': 'Network Targets',
|
||||
'targetprofiles': 'Target Profiles',
|
||||
};
|
||||
|
||||
private labelToTab: Record<string, TNetworkTab> = {
|
||||
'Network Activity': 'activity',
|
||||
'Routes': 'routes',
|
||||
'Source Profiles': 'sourceprofiles',
|
||||
'Network Targets': 'networktargets',
|
||||
'Target Profiles': 'targetprofiles',
|
||||
};
|
||||
|
||||
private static isNetworkTab(s: string | null): s is TNetworkTab {
|
||||
return s === 'activity' || s === 'routes' || s === 'sourceprofiles'
|
||||
|| s === 'networktargets' || s === 'targetprofiles';
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// Read initial subview from state (URL-driven)
|
||||
const initialState = appstate.uiStatePart.getState()!;
|
||||
if (OpsViewNetwork.isNetworkTab(initialState.activeSubview)) {
|
||||
this.selectedTab = initialState.activeSubview;
|
||||
}
|
||||
// Subscribe to future changes (back/forward navigation, direct URL entry)
|
||||
const sub = appstate.uiStatePart.select((s) => s.activeSubview).subscribe((sub) => {
|
||||
if (OpsViewNetwork.isNetworkTab(sub) && sub !== this.selectedTab) {
|
||||
this.selectedTab = sub;
|
||||
}
|
||||
});
|
||||
this.rxSubscriptions.push(sub);
|
||||
}
|
||||
|
||||
async firstUpdated() {
|
||||
const toggle = this.shadowRoot!.querySelector('dees-input-multitoggle') as any;
|
||||
if (toggle) {
|
||||
const sub = toggle.changeSubject.subscribe(() => {
|
||||
const tab = this.labelToTab[toggle.selectedOption];
|
||||
if (tab && tab !== this.selectedTab) {
|
||||
// Push URL → router updates state → subscription updates selectedTab
|
||||
appRouter.navigateToView('network', tab);
|
||||
}
|
||||
});
|
||||
this.rxSubscriptions.push(sub);
|
||||
}
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
viewHostCss,
|
||||
css`
|
||||
dees-input-multitoggle {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<dees-heading level="2">Network</dees-heading>
|
||||
|
||||
<dees-input-multitoggle
|
||||
.type=${'single'}
|
||||
.options=${['Network Activity', 'Routes', 'Source Profiles', 'Network Targets', 'Target Profiles']}
|
||||
.selectedOption=${this.tabLabelMap[this.selectedTab]}
|
||||
></dees-input-multitoggle>
|
||||
|
||||
${this.renderTabContent()}
|
||||
`;
|
||||
}
|
||||
|
||||
private renderTabContent(): TemplateResult {
|
||||
switch (this.selectedTab) {
|
||||
case 'activity': return html`<ops-view-network-activity></ops-view-network-activity>`;
|
||||
case 'routes': return html`<ops-view-routes></ops-view-routes>`;
|
||||
case 'sourceprofiles': return html`<ops-view-sourceprofiles></ops-view-sourceprofiles>`;
|
||||
case 'networktargets': return html`<ops-view-networktargets></ops-view-networktargets>`;
|
||||
case 'targetprofiles': return html`<ops-view-targetprofiles></ops-view-targetprofiles>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user