@serve.zone/dcrouter 13.2.2 → 13.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_serve/bundle.js +1499 -1413
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +1 -0
- package/dist_ts_web/appstate.js +14 -38
- package/dist_ts_web/elements/access/index.d.ts +1 -0
- package/dist_ts_web/elements/access/index.js +2 -0
- package/dist_ts_web/elements/{ops-view-apitokens.d.ts → access/ops-view-apitokens.d.ts} +1 -1
- package/dist_ts_web/elements/{ops-view-apitokens.js → access/ops-view-apitokens.js} +4 -4
- package/dist_ts_web/elements/email/index.d.ts +2 -0
- package/dist_ts_web/elements/email/index.js +3 -0
- package/dist_ts_web/elements/email/ops-view-email-security.d.ts +14 -0
- package/dist_ts_web/elements/email/ops-view-email-security.js +197 -0
- package/dist_ts_web/elements/{ops-view-emails.d.ts → email/ops-view-emails.d.ts} +2 -2
- package/dist_ts_web/elements/{ops-view-emails.js → email/ops-view-emails.js} +5 -5
- package/dist_ts_web/elements/index.d.ts +5 -12
- package/dist_ts_web/elements/index.js +6 -13
- package/dist_ts_web/elements/network/index.d.ts +7 -0
- package/dist_ts_web/elements/network/index.js +8 -0
- package/dist_ts_web/elements/{ops-view-network.d.ts → network/ops-view-network-activity.d.ts} +3 -3
- package/dist_ts_web/elements/{ops-view-network.js → network/ops-view-network-activity.js} +20 -32
- package/dist_ts_web/elements/{ops-view-networktargets.d.ts → network/ops-view-networktargets.d.ts} +1 -1
- package/dist_ts_web/elements/{ops-view-networktargets.js → network/ops-view-networktargets.js} +5 -5
- package/dist_ts_web/elements/{ops-view-remoteingress.d.ts → network/ops-view-remoteingress.d.ts} +1 -1
- package/dist_ts_web/elements/{ops-view-remoteingress.js → network/ops-view-remoteingress.js} +5 -5
- package/dist_ts_web/elements/{ops-view-routes.d.ts → network/ops-view-routes.d.ts} +1 -1
- package/dist_ts_web/elements/{ops-view-routes.js → network/ops-view-routes.js} +5 -5
- package/dist_ts_web/elements/{ops-view-sourceprofiles.d.ts → network/ops-view-sourceprofiles.d.ts} +1 -1
- package/dist_ts_web/elements/{ops-view-sourceprofiles.js → network/ops-view-sourceprofiles.js} +5 -5
- package/dist_ts_web/elements/{ops-view-targetprofiles.d.ts → network/ops-view-targetprofiles.d.ts} +2 -2
- package/dist_ts_web/elements/{ops-view-targetprofiles.js → network/ops-view-targetprofiles.js} +6 -6
- package/dist_ts_web/elements/{ops-view-vpn.d.ts → network/ops-view-vpn.d.ts} +2 -2
- package/dist_ts_web/elements/{ops-view-vpn.js → network/ops-view-vpn.js} +6 -6
- package/dist_ts_web/elements/ops-dashboard.d.ts +8 -2
- package/dist_ts_web/elements/ops-dashboard.js +101 -83
- package/dist_ts_web/elements/overview/index.d.ts +2 -0
- package/dist_ts_web/elements/overview/index.js +3 -0
- package/dist_ts_web/elements/{ops-view-config.d.ts → overview/ops-view-config.d.ts} +2 -2
- package/dist_ts_web/elements/{ops-view-config.js → overview/ops-view-config.js} +9 -9
- package/dist_ts_web/elements/{ops-view-overview.d.ts → overview/ops-view-overview.d.ts} +2 -2
- package/dist_ts_web/elements/{ops-view-overview.js → overview/ops-view-overview.js} +4 -4
- package/dist_ts_web/elements/security/index.d.ts +3 -0
- package/dist_ts_web/elements/security/index.js +4 -0
- package/dist_ts_web/elements/security/ops-view-security-authentication.d.ts +13 -0
- package/dist_ts_web/elements/security/ops-view-security-authentication.js +157 -0
- package/dist_ts_web/elements/security/ops-view-security-blocked.d.ts +15 -0
- package/dist_ts_web/elements/security/ops-view-security-blocked.js +153 -0
- package/dist_ts_web/elements/security/ops-view-security-overview.d.ts +16 -0
- package/dist_ts_web/elements/security/ops-view-security-overview.js +205 -0
- package/dist_ts_web/router.d.ts +5 -3
- package/dist_ts_web/router.js +75 -17
- package/package.json +2 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +15 -42
- package/ts_web/elements/access/index.ts +1 -0
- package/ts_web/elements/{ops-view-apitokens.ts → access/ops-view-apitokens.ts} +3 -3
- package/ts_web/elements/email/index.ts +2 -0
- package/ts_web/elements/email/ops-view-email-security.ts +160 -0
- package/ts_web/elements/{ops-view-emails.ts → email/ops-view-emails.ts} +4 -4
- package/ts_web/elements/index.ts +6 -13
- package/ts_web/elements/network/index.ts +7 -0
- package/ts_web/elements/{ops-view-network.ts → network/ops-view-network-activity.ts} +43 -55
- package/ts_web/elements/{ops-view-networktargets.ts → network/ops-view-networktargets.ts} +4 -4
- package/ts_web/elements/{ops-view-remoteingress.ts → network/ops-view-remoteingress.ts} +4 -4
- package/ts_web/elements/{ops-view-routes.ts → network/ops-view-routes.ts} +4 -4
- package/ts_web/elements/{ops-view-sourceprofiles.ts → network/ops-view-sourceprofiles.ts} +4 -4
- package/ts_web/elements/{ops-view-targetprofiles.ts → network/ops-view-targetprofiles.ts} +5 -5
- package/ts_web/elements/{ops-view-vpn.ts → network/ops-view-vpn.ts} +5 -5
- package/ts_web/elements/ops-dashboard.ts +125 -90
- package/ts_web/elements/overview/index.ts +2 -0
- package/ts_web/elements/{ops-view-config.ts → overview/ops-view-config.ts} +8 -8
- package/ts_web/elements/{ops-view-overview.ts → overview/ops-view-overview.ts} +3 -3
- package/ts_web/elements/security/index.ts +3 -0
- package/ts_web/elements/security/ops-view-security-authentication.ts +121 -0
- package/ts_web/elements/security/ops-view-security-blocked.ts +118 -0
- package/ts_web/elements/security/ops-view-security-overview.ts +172 -0
- package/ts_web/router.ts +81 -17
- package/dist_ts_web/elements/ops-view-security.d.ts +0 -24
- package/dist_ts_web/elements/ops-view-security.js +0 -484
- package/ts_web/elements/ops-view-security.ts +0 -456
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
6
|
+
var _, done = false;
|
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
8
|
+
var context = {};
|
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
13
|
+
if (kind === "accessor") {
|
|
14
|
+
if (result === void 0) continue;
|
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
19
|
+
}
|
|
20
|
+
else if (_ = accept(result)) {
|
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
|
22
|
+
else descriptor[key] = _;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
|
+
done = true;
|
|
27
|
+
};
|
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
+
var useValue = arguments.length > 2;
|
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
+
}
|
|
33
|
+
return useValue ? value : void 0;
|
|
34
|
+
};
|
|
35
|
+
import * as appstate from '../../appstate.js';
|
|
36
|
+
import { viewHostCss } from '../shared/css.js';
|
|
37
|
+
import { DeesElement, customElement, html, state, css, cssManager, } from '@design.estate/dees-element';
|
|
38
|
+
import {} from '@design.estate/dees-catalog';
|
|
39
|
+
let OpsViewSecurityOverview = (() => {
|
|
40
|
+
let _classDecorators = [customElement('ops-view-security-overview')];
|
|
41
|
+
let _classDescriptor;
|
|
42
|
+
let _classExtraInitializers = [];
|
|
43
|
+
let _classThis;
|
|
44
|
+
let _classSuper = DeesElement;
|
|
45
|
+
let _statsState_decorators;
|
|
46
|
+
let _statsState_initializers = [];
|
|
47
|
+
let _statsState_extraInitializers = [];
|
|
48
|
+
var OpsViewSecurityOverview = class extends _classSuper {
|
|
49
|
+
static { _classThis = this; }
|
|
50
|
+
static {
|
|
51
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
52
|
+
_statsState_decorators = [state()];
|
|
53
|
+
__esDecorate(this, null, _statsState_decorators, { kind: "accessor", name: "statsState", static: false, private: false, access: { has: obj => "statsState" in obj, get: obj => obj.statsState, set: (obj, value) => { obj.statsState = value; } }, metadata: _metadata }, _statsState_initializers, _statsState_extraInitializers);
|
|
54
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
55
|
+
OpsViewSecurityOverview = _classThis = _classDescriptor.value;
|
|
56
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
57
|
+
}
|
|
58
|
+
#statsState_accessor_storage = __runInitializers(this, _statsState_initializers, appstate.statsStatePart.getState());
|
|
59
|
+
get statsState() { return this.#statsState_accessor_storage; }
|
|
60
|
+
set statsState(value) { this.#statsState_accessor_storage = value; }
|
|
61
|
+
constructor() {
|
|
62
|
+
super();
|
|
63
|
+
__runInitializers(this, _statsState_extraInitializers);
|
|
64
|
+
const sub = appstate.statsStatePart
|
|
65
|
+
.select((s) => s)
|
|
66
|
+
.subscribe((s) => {
|
|
67
|
+
this.statsState = s;
|
|
68
|
+
});
|
|
69
|
+
this.rxSubscriptions.push(sub);
|
|
70
|
+
}
|
|
71
|
+
static styles = [
|
|
72
|
+
cssManager.defaultStyles,
|
|
73
|
+
viewHostCss,
|
|
74
|
+
css `
|
|
75
|
+
h2 {
|
|
76
|
+
margin: 32px 0 16px 0;
|
|
77
|
+
font-size: 24px;
|
|
78
|
+
font-weight: 600;
|
|
79
|
+
color: ${cssManager.bdTheme('#333', '#ccc')};
|
|
80
|
+
}
|
|
81
|
+
dees-statsgrid {
|
|
82
|
+
margin-bottom: 32px;
|
|
83
|
+
}
|
|
84
|
+
`,
|
|
85
|
+
];
|
|
86
|
+
render() {
|
|
87
|
+
const metrics = this.statsState.securityMetrics;
|
|
88
|
+
if (!metrics) {
|
|
89
|
+
return html `
|
|
90
|
+
<div class="loadingMessage">
|
|
91
|
+
<p>Loading security metrics...</p>
|
|
92
|
+
</div>
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
const threatLevel = this.calculateThreatLevel(metrics);
|
|
96
|
+
const threatScore = this.getThreatScore(metrics);
|
|
97
|
+
// Derive active sessions from recent successful auth events (last hour)
|
|
98
|
+
const allEvents = metrics.recentEvents || [];
|
|
99
|
+
const oneHourAgo = Date.now() - 3600000;
|
|
100
|
+
const recentAuthSuccesses = allEvents.filter((evt) => evt.type === 'authentication' && evt.success === true && evt.timestamp >= oneHourAgo).length;
|
|
101
|
+
const tiles = [
|
|
102
|
+
{
|
|
103
|
+
id: 'threatLevel',
|
|
104
|
+
title: 'Threat Level',
|
|
105
|
+
value: threatScore,
|
|
106
|
+
type: 'gauge',
|
|
107
|
+
icon: 'lucide:Shield',
|
|
108
|
+
gaugeOptions: {
|
|
109
|
+
min: 0,
|
|
110
|
+
max: 100,
|
|
111
|
+
thresholds: [
|
|
112
|
+
{ value: 0, color: '#ef4444' },
|
|
113
|
+
{ value: 30, color: '#f59e0b' },
|
|
114
|
+
{ value: 70, color: '#22c55e' },
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
description: `Status: ${threatLevel.toUpperCase()}`,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'blockedThreats',
|
|
121
|
+
title: 'Blocked Threats',
|
|
122
|
+
value: (metrics.blockedIPs?.length || 0) + metrics.spamDetected,
|
|
123
|
+
type: 'number',
|
|
124
|
+
icon: 'lucide:ShieldCheck',
|
|
125
|
+
color: '#ef4444',
|
|
126
|
+
description: 'Total threats blocked today',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: 'activeSessions',
|
|
130
|
+
title: 'Active Sessions',
|
|
131
|
+
value: recentAuthSuccesses,
|
|
132
|
+
type: 'number',
|
|
133
|
+
icon: 'lucide:Users',
|
|
134
|
+
color: '#22c55e',
|
|
135
|
+
description: 'Authenticated in last hour',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: 'authFailures',
|
|
139
|
+
title: 'Auth Failures',
|
|
140
|
+
value: metrics.authenticationFailures,
|
|
141
|
+
type: 'number',
|
|
142
|
+
icon: 'lucide:LockOpen',
|
|
143
|
+
color: metrics.authenticationFailures > 10 ? '#ef4444' : '#f59e0b',
|
|
144
|
+
description: 'Failed login attempts today',
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
return html `
|
|
148
|
+
<dees-heading level="hr">Overview</dees-heading>
|
|
149
|
+
|
|
150
|
+
<dees-statsgrid
|
|
151
|
+
.tiles=${tiles}
|
|
152
|
+
.minTileWidth=${200}
|
|
153
|
+
></dees-statsgrid>
|
|
154
|
+
|
|
155
|
+
<h2>Recent Security Events</h2>
|
|
156
|
+
<dees-table
|
|
157
|
+
.heading1=${'Security Events'}
|
|
158
|
+
.heading2=${'Last 24 hours'}
|
|
159
|
+
.data=${this.getSecurityEvents(metrics)}
|
|
160
|
+
.displayFunction=${(item) => ({
|
|
161
|
+
'Time': new Date(item.timestamp).toLocaleTimeString(),
|
|
162
|
+
'Event': item.event,
|
|
163
|
+
'Severity': item.severity,
|
|
164
|
+
'Details': item.details,
|
|
165
|
+
})}
|
|
166
|
+
></dees-table>
|
|
167
|
+
`;
|
|
168
|
+
}
|
|
169
|
+
calculateThreatLevel(metrics) {
|
|
170
|
+
const score = this.getThreatScore(metrics);
|
|
171
|
+
if (score < 30)
|
|
172
|
+
return 'alert';
|
|
173
|
+
if (score < 70)
|
|
174
|
+
return 'warning';
|
|
175
|
+
return 'success';
|
|
176
|
+
}
|
|
177
|
+
getThreatScore(metrics) {
|
|
178
|
+
// Simple scoring algorithm
|
|
179
|
+
let score = 100;
|
|
180
|
+
const blockedCount = Array.isArray(metrics.blockedIPs) ? metrics.blockedIPs.length : (metrics.blockedIPs || 0);
|
|
181
|
+
score -= blockedCount * 2;
|
|
182
|
+
score -= (metrics.authenticationFailures || 0) * 1;
|
|
183
|
+
score -= (metrics.spamDetected || 0) * 0.5;
|
|
184
|
+
score -= (metrics.malwareDetected || 0) * 3;
|
|
185
|
+
score -= (metrics.phishingDetected || 0) * 3;
|
|
186
|
+
score -= (metrics.suspiciousActivities || 0) * 2;
|
|
187
|
+
return Math.max(0, Math.min(100, Math.round(score)));
|
|
188
|
+
}
|
|
189
|
+
getSecurityEvents(metrics) {
|
|
190
|
+
const events = metrics.recentEvents || [];
|
|
191
|
+
return events.map((evt) => ({
|
|
192
|
+
timestamp: evt.timestamp,
|
|
193
|
+
event: evt.message,
|
|
194
|
+
severity: evt.level === 'critical' ? 'critical' : evt.level === 'error' ? 'high' : evt.level === 'warn' ? 'warning' : 'info',
|
|
195
|
+
details: evt.ipAddress ? `IP: ${evt.ipAddress}` : evt.domain ? `Domain: ${evt.domain}` : evt.type,
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
static {
|
|
199
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
return OpsViewSecurityOverview = _classThis;
|
|
203
|
+
})();
|
|
204
|
+
export { OpsViewSecurityOverview };
|
|
205
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BzLXZpZXctc2VjdXJpdHktb3ZlcnZpZXcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90c193ZWIvZWxlbWVudHMvc2VjdXJpdHkvb3BzLXZpZXctc2VjdXJpdHktb3ZlcnZpZXcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sS0FBSyxRQUFRLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRS9DLE9BQU8sRUFDTCxXQUFXLEVBQ1gsYUFBYSxFQUNiLElBQUksRUFDSixLQUFLLEVBQ0wsR0FBRyxFQUNILFVBQVUsR0FFWCxNQUFNLDZCQUE2QixDQUFDO0FBQ3JDLE9BQU8sRUFBbUIsTUFBTSw2QkFBNkIsQ0FBQztJQVNqRCx1QkFBdUI7NEJBRG5DLGFBQWEsQ0FBQyw0QkFBNEIsQ0FBQzs7OztzQkFDQyxXQUFXOzs7O3VDQUFuQixTQUFRLFdBQVc7Ozs7c0NBQ3JELEtBQUssRUFBRTtZQUNSLG1MQUFTLFVBQVUsNkJBQVYsVUFBVSwrRkFBNkQ7WUFGbEYsNktBc0pDOzs7O1FBcEpDLGlGQUE0QyxRQUFRLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRyxFQUFDO1FBQWhGLElBQVMsVUFBVSxnREFBNkQ7UUFBaEYsSUFBUyxVQUFVLHNEQUE2RDtRQUVoRjtZQUNFLEtBQUssRUFBRSxDQUFDOztZQUNSLE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxjQUFjO2lCQUNoQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztpQkFDaEIsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQ2YsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUM7WUFDdEIsQ0FBQyxDQUFDLENBQUM7WUFDTCxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxHQUFH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
|
package/dist_ts_web/router.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export type TValidView = typeof
|
|
1
|
+
export declare const validTopLevelViews: readonly ["logs", "certificates", ...string[]];
|
|
2
|
+
export type TValidView = typeof validTopLevelViews[number];
|
|
3
|
+
export declare function isValidView(view: string): boolean;
|
|
4
|
+
export declare function isValidSubview(view: string, subview: string): boolean;
|
|
3
5
|
declare class AppRouter {
|
|
4
6
|
private router;
|
|
5
7
|
private initialized;
|
|
@@ -11,7 +13,7 @@ declare class AppRouter {
|
|
|
11
13
|
private handleInitialRoute;
|
|
12
14
|
private updateViewState;
|
|
13
15
|
navigateTo(path: string): void;
|
|
14
|
-
navigateToView(view: string): void;
|
|
16
|
+
navigateToView(view: string, subview?: string): void;
|
|
15
17
|
getCurrentView(): string;
|
|
16
18
|
destroy(): void;
|
|
17
19
|
}
|
package/dist_ts_web/router.js
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import * as appstate from './appstate.js';
|
|
3
3
|
const SmartRouter = plugins.domtools.plugins.smartrouter.SmartRouter;
|
|
4
|
-
|
|
4
|
+
// Flat top-level views (no subviews)
|
|
5
|
+
const flatViews = ['logs', 'certificates'];
|
|
6
|
+
// Tabbed views and their valid subviews
|
|
7
|
+
const subviewMap = {
|
|
8
|
+
overview: ['stats', 'configuration'],
|
|
9
|
+
network: ['activity', 'routes', 'sourceprofiles', 'networktargets', 'targetprofiles', 'remoteingress', 'vpn'],
|
|
10
|
+
email: ['log', 'security'],
|
|
11
|
+
access: ['apitokens'],
|
|
12
|
+
security: ['overview', 'blocked', 'authentication'],
|
|
13
|
+
};
|
|
14
|
+
// Default subview when user visits the bare parent URL
|
|
15
|
+
const defaultSubview = {
|
|
16
|
+
overview: 'stats',
|
|
17
|
+
network: 'activity',
|
|
18
|
+
email: 'log',
|
|
19
|
+
access: 'apitokens',
|
|
20
|
+
security: 'overview',
|
|
21
|
+
};
|
|
22
|
+
export const validTopLevelViews = [...flatViews, ...Object.keys(subviewMap)];
|
|
23
|
+
export function isValidView(view) {
|
|
24
|
+
return validTopLevelViews.includes(view);
|
|
25
|
+
}
|
|
26
|
+
export function isValidSubview(view, subview) {
|
|
27
|
+
return subviewMap[view]?.includes(subview) ?? false;
|
|
28
|
+
}
|
|
5
29
|
class AppRouter {
|
|
6
30
|
router;
|
|
7
31
|
initialized = false;
|
|
@@ -18,10 +42,24 @@ class AppRouter {
|
|
|
18
42
|
this.initialized = true;
|
|
19
43
|
}
|
|
20
44
|
setupRoutes() {
|
|
21
|
-
|
|
45
|
+
// Flat views
|
|
46
|
+
for (const view of flatViews) {
|
|
47
|
+
this.router.on(`/${view}`, async () => {
|
|
48
|
+
this.updateViewState(view, null);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Tabbed views
|
|
52
|
+
for (const view of Object.keys(subviewMap)) {
|
|
53
|
+
// Bare parent → redirect to default subview
|
|
22
54
|
this.router.on(`/${view}`, async () => {
|
|
23
|
-
this.
|
|
55
|
+
this.navigateTo(`/${view}/${defaultSubview[view]}`);
|
|
24
56
|
});
|
|
57
|
+
// Each valid subview
|
|
58
|
+
for (const sub of subviewMap[view]) {
|
|
59
|
+
this.router.on(`/${view}/${sub}`, async () => {
|
|
60
|
+
this.updateViewState(view, sub);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
25
63
|
}
|
|
26
64
|
// Root redirect
|
|
27
65
|
this.router.on('/', async () => {
|
|
@@ -33,7 +71,9 @@ class AppRouter {
|
|
|
33
71
|
if (this.suppressStateUpdate)
|
|
34
72
|
return;
|
|
35
73
|
const currentPath = window.location.pathname;
|
|
36
|
-
const expectedPath =
|
|
74
|
+
const expectedPath = uiState.activeSubview
|
|
75
|
+
? `/${uiState.activeView}/${uiState.activeSubview}`
|
|
76
|
+
: `/${uiState.activeView}`;
|
|
37
77
|
if (currentPath !== expectedPath) {
|
|
38
78
|
this.suppressStateUpdate = true;
|
|
39
79
|
this.router.pushUrl(expectedPath);
|
|
@@ -45,25 +85,36 @@ class AppRouter {
|
|
|
45
85
|
const path = window.location.pathname;
|
|
46
86
|
if (!path || path === '/') {
|
|
47
87
|
this.router.pushUrl('/overview');
|
|
88
|
+
return;
|
|
48
89
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
90
|
+
const segments = path.split('/').filter(Boolean);
|
|
91
|
+
const view = segments[0];
|
|
92
|
+
const sub = segments[1];
|
|
93
|
+
if (!isValidView(view)) {
|
|
94
|
+
this.router.pushUrl('/overview');
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (subviewMap[view]) {
|
|
98
|
+
if (sub && isValidSubview(view, sub)) {
|
|
99
|
+
this.updateViewState(view, sub);
|
|
54
100
|
}
|
|
55
101
|
else {
|
|
56
|
-
|
|
102
|
+
// Bare parent or invalid sub → default subview
|
|
103
|
+
this.router.pushUrl(`/${view}/${defaultSubview[view]}`);
|
|
57
104
|
}
|
|
58
105
|
}
|
|
106
|
+
else {
|
|
107
|
+
this.updateViewState(view, null);
|
|
108
|
+
}
|
|
59
109
|
}
|
|
60
|
-
updateViewState(view) {
|
|
110
|
+
updateViewState(view, subview) {
|
|
61
111
|
this.suppressStateUpdate = true;
|
|
62
112
|
const currentState = appstate.uiStatePart.getState();
|
|
63
|
-
if (currentState.activeView !== view) {
|
|
113
|
+
if (currentState.activeView !== view || currentState.activeSubview !== subview) {
|
|
64
114
|
appstate.uiStatePart.setState({
|
|
65
115
|
...currentState,
|
|
66
116
|
activeView: view,
|
|
117
|
+
activeSubview: subview,
|
|
67
118
|
});
|
|
68
119
|
}
|
|
69
120
|
this.suppressStateUpdate = false;
|
|
@@ -71,12 +122,19 @@ class AppRouter {
|
|
|
71
122
|
navigateTo(path) {
|
|
72
123
|
this.router.pushUrl(path);
|
|
73
124
|
}
|
|
74
|
-
navigateToView(view) {
|
|
75
|
-
if (
|
|
76
|
-
this.navigateTo(
|
|
125
|
+
navigateToView(view, subview) {
|
|
126
|
+
if (!isValidView(view)) {
|
|
127
|
+
this.navigateTo('/overview');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (subview && isValidSubview(view, subview)) {
|
|
131
|
+
this.navigateTo(`/${view}/${subview}`);
|
|
132
|
+
}
|
|
133
|
+
else if (subviewMap[view]) {
|
|
134
|
+
this.navigateTo(`/${view}/${defaultSubview[view]}`);
|
|
77
135
|
}
|
|
78
136
|
else {
|
|
79
|
-
this.navigateTo(
|
|
137
|
+
this.navigateTo(`/${view}`);
|
|
80
138
|
}
|
|
81
139
|
}
|
|
82
140
|
getCurrentView() {
|
|
@@ -88,4 +146,4 @@ class AppRouter {
|
|
|
88
146
|
}
|
|
89
147
|
}
|
|
90
148
|
export const appRouter = new AppRouter();
|
|
91
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
149
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfd2ViL3JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEtBQUssUUFBUSxNQUFNLGVBQWUsQ0FBQztBQUUxQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDO0FBRXJFLHFDQUFxQztBQUNyQyxNQUFNLFNBQVMsR0FBRyxDQUFDLE1BQU0sRUFBRSxjQUFjLENBQVUsQ0FBQztBQUVwRCx3Q0FBd0M7QUFDeEMsTUFBTSxVQUFVLEdBQXNDO0lBQ3BELFFBQVEsRUFBRSxDQUFDLE9BQU8sRUFBRSxlQUFlLENBQVU7SUFDN0MsT0FBTyxFQUFFLENBQUMsVUFBVSxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxlQUFlLEVBQUUsS0FBSyxDQUFVO0lBQ3RILEtBQUssRUFBRSxDQUFDLEtBQUssRUFBRSxVQUFVLENBQVU7SUFDbkMsTUFBTSxFQUFFLENBQUMsV0FBVyxDQUFVO0lBQzlCLFFBQVEsRUFBRSxDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLENBQVU7Q0FDN0QsQ0FBQztBQUVGLHVEQUF1RDtBQUN2RCxNQUFNLGNBQWMsR0FBMkI7SUFDN0MsUUFBUSxFQUFFLE9BQU87SUFDakIsT0FBTyxFQUFFLFVBQVU7SUFDbkIsS0FBSyxFQUFFLEtBQUs7SUFDWixNQUFNLEVBQUUsV0FBVztJQUNuQixRQUFRLEVBQUUsVUFBVTtDQUNyQixDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxHQUFHLFNBQVMsRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQVUsQ0FBQztBQUd0RixNQUFNLFVBQVUsV0FBVyxDQUFDLElBQVk7SUFDdEMsT0FBUSxrQkFBd0MsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDbEUsQ0FBQztBQUVELE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBWSxFQUFFLE9BQWU7SUFDMUQsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssQ0FBQztBQUN0RCxDQUFDO0FBRUQsTUFBTSxTQUFTO0lBQ0wsTUFBTSxDQUFtQztJQUN6QyxXQUFXLEdBQUcsS0FBSyxDQUFDO0lBQ3BCLG1CQUFtQixHQUFHLEtBQUssQ0FBQztJQUVwQztRQUNFLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBRU0sSUFBSTtRQUNULElBQUksSUFBSSxDQUFDLFdBQVc7WUFBRSxPQUFPO1FBQzdCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7SUFDMUIsQ0FBQztJQUVPLFdBQVc7UUFDakIsYUFBYTtRQUNiLEtBQUssTUFBTSxJQUFJLElBQUksU0FBUyxFQUFFLENBQUM7WUFDN0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxJQUFJLEVBQUUsRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDcEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDbkMsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsZUFBZTtRQUNmLEtBQUssTUFBTSxJQUFJLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQzNDLDRDQUE0QztZQUM1QyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLElBQUksRUFBRSxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNwQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksSUFBSSxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdEQsQ0FBQyxDQUFDLENBQUM7WUFDSCxxQkFBcUI7WUFDckIsS0FBSyxNQUFNLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxJQUFJLElBQUksR0FBRyxFQUFFLEVBQUUsS0FBSyxJQUFJLEVBQUU7b0JBQzNDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUNsQyxDQUFDLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO1FBRUQsZ0JBQWdCO1FBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxLQUFLLElBQUksRUFBRTtZQUM3QixJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGNBQWM7UUFDcEIsUUFBUSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNsRCxJQUFJLElBQUksQ0FBQyxtQkFBbUI7Z0JBQUUsT0FBTztZQUVyQyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztZQUM3QyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsYUFBYTtnQkFDeEMsQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLFVBQVUsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO2dCQUNuRCxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7WUFFN0IsSUFBSSxXQUFXLEtBQUssWUFBWSxFQUFFLENBQUM7Z0JBQ2pDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUM7Z0JBQ2hDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNsQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsS0FBSyxDQUFDO1lBQ25DLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxrQkFBa0I7UUFDeEIsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFFdEMsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDMUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDakMsT0FBTztRQUNULENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNqRCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekIsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRXhCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNqQyxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDckIsSUFBSSxHQUFHLElBQUksY0FBYyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNyQyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNsQyxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sK0NBQStDO2dCQUMvQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzFELENBQUM7UUFDSCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ25DLENBQUM7SUFDSCxDQUFDO0lBRU8sZUFBZSxDQUFDLElBQVksRUFBRSxPQUFzQjtRQUMxRCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDO1FBQ2hDLE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFHLENBQUM7UUFDdEQsSUFBSSxZQUFZLENBQUMsVUFBVSxLQUFLLElBQUksSUFBSSxZQUFZLENBQUMsYUFBYSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQy9FLFFBQVEsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDO2dCQUM1QixHQUFHLFlBQVk7Z0JBQ2YsVUFBVSxFQUFFLElBQUk7Z0JBQ2hCLGFBQWEsRUFBRSxPQUFPO2FBQ0YsQ0FBQyxDQUFDO1FBQzFCLENBQUM7UUFDRCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsS0FBSyxDQUFDO0lBQ25DLENBQUM7SUFFTSxVQUFVLENBQUMsSUFBWTtRQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRU0sY0FBYyxDQUFDLElBQVksRUFBRSxPQUFnQjtRQUNsRCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM3QixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksT0FBTyxJQUFJLGNBQWMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUM3QyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksSUFBSSxJQUFJLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDekMsQ0FBQzthQUFNLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDNUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLElBQUksSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7UUFDOUIsQ0FBQztJQUNILENBQUM7SUFFTSxjQUFjO1FBQ25CLE9BQU8sUUFBUSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUcsQ0FBQyxVQUFVLENBQUM7SUFDckQsQ0FBQztJQUVNLE9BQU87UUFDWixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO0lBQzNCLENBQUM7Q0FDRjtBQUVELE1BQU0sQ0FBQyxNQUFNLFNBQVMsR0FBRyxJQUFJLFNBQVMsRUFBRSxDQUFDIn0=
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/dcrouter",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "13.
|
|
4
|
+
"version": "13.4.0",
|
|
5
5
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@api.global/typedserver": "^8.4.6",
|
|
36
36
|
"@api.global/typedsocket": "^4.1.2",
|
|
37
37
|
"@apiclient.xyz/cloudflare": "^7.1.0",
|
|
38
|
-
"@design.estate/dees-catalog": "^3.
|
|
38
|
+
"@design.estate/dees-catalog": "^3.68.0",
|
|
39
39
|
"@design.estate/dees-element": "^2.2.4",
|
|
40
40
|
"@push.rocks/lik": "^6.4.0",
|
|
41
41
|
"@push.rocks/projectinfo": "^5.1.0",
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts_web/appstate.ts
CHANGED
|
@@ -30,6 +30,7 @@ export interface IConfigState {
|
|
|
30
30
|
|
|
31
31
|
export interface IUiState {
|
|
32
32
|
activeView: string;
|
|
33
|
+
activeSubview: string | null;
|
|
33
34
|
sidebarCollapsed: boolean;
|
|
34
35
|
autoRefresh: boolean;
|
|
35
36
|
refreshInterval: number; // milliseconds
|
|
@@ -116,16 +117,24 @@ export const configStatePart = await appState.getStatePart<IConfigState>(
|
|
|
116
117
|
// Determine initial view from URL path
|
|
117
118
|
const getInitialView = (): string => {
|
|
118
119
|
const path = typeof window !== 'undefined' ? window.location.pathname : '/';
|
|
119
|
-
const validViews = ['overview', 'network', '
|
|
120
|
+
const validViews = ['overview', 'network', 'email', 'logs', 'access', 'security', 'certificates'];
|
|
120
121
|
const segments = path.split('/').filter(Boolean);
|
|
121
122
|
const view = segments[0];
|
|
122
123
|
return validViews.includes(view) ? view : 'overview';
|
|
123
124
|
};
|
|
124
125
|
|
|
126
|
+
// Determine initial subview (second URL segment) from the path
|
|
127
|
+
const getInitialSubview = (): string | null => {
|
|
128
|
+
const path = typeof window !== 'undefined' ? window.location.pathname : '/';
|
|
129
|
+
const segments = path.split('/').filter(Boolean);
|
|
130
|
+
return segments[1] ?? null;
|
|
131
|
+
};
|
|
132
|
+
|
|
125
133
|
export const uiStatePart = await appState.getStatePart<IUiState>(
|
|
126
134
|
'ui',
|
|
127
135
|
{
|
|
128
136
|
activeView: getInitialView(),
|
|
137
|
+
activeSubview: getInitialSubview(),
|
|
129
138
|
sidebarCollapsed: false,
|
|
130
139
|
autoRefresh: true,
|
|
131
140
|
refreshInterval: 1000, // 1 second
|
|
@@ -435,43 +444,6 @@ export const setActiveViewAction = uiStatePart.createAction<string>(async (state
|
|
|
435
444
|
}, 100);
|
|
436
445
|
}
|
|
437
446
|
|
|
438
|
-
// If switching to routes view, ensure we fetch route data
|
|
439
|
-
if (viewName === 'routes' && currentState.activeView !== 'routes') {
|
|
440
|
-
setTimeout(() => {
|
|
441
|
-
routeManagementStatePart.dispatchAction(fetchMergedRoutesAction, null);
|
|
442
|
-
// Also fetch profiles/targets for the Create Route dropdowns
|
|
443
|
-
profilesTargetsStatePart.dispatchAction(fetchProfilesAndTargetsAction, null);
|
|
444
|
-
}, 100);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// If switching to apitokens view, ensure we fetch token data
|
|
448
|
-
if (viewName === 'apitokens' && currentState.activeView !== 'apitokens') {
|
|
449
|
-
setTimeout(() => {
|
|
450
|
-
routeManagementStatePart.dispatchAction(fetchApiTokensAction, null);
|
|
451
|
-
}, 100);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
// If switching to remoteingress view, ensure we fetch edge data
|
|
455
|
-
if (viewName === 'remoteingress' && currentState.activeView !== 'remoteingress') {
|
|
456
|
-
setTimeout(() => {
|
|
457
|
-
remoteIngressStatePart.dispatchAction(fetchRemoteIngressAction, null);
|
|
458
|
-
}, 100);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// If switching to security profiles or network targets views, fetch profiles/targets data
|
|
462
|
-
if ((viewName === 'sourceprofiles' || viewName === 'networktargets') && currentState.activeView !== viewName) {
|
|
463
|
-
setTimeout(() => {
|
|
464
|
-
profilesTargetsStatePart.dispatchAction(fetchProfilesAndTargetsAction, null);
|
|
465
|
-
}, 100);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// If switching to target profiles view, fetch target profiles data
|
|
469
|
-
if (viewName === 'targetprofiles' && currentState.activeView !== viewName) {
|
|
470
|
-
setTimeout(() => {
|
|
471
|
-
targetProfilesStatePart.dispatchAction(fetchTargetProfilesAction, null);
|
|
472
|
-
}, 100);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
447
|
return {
|
|
476
448
|
...currentState,
|
|
477
449
|
activeView: viewName,
|
|
@@ -1944,6 +1916,7 @@ async function dispatchCombinedRefreshActionInner() {
|
|
|
1944
1916
|
const context = getActionContext();
|
|
1945
1917
|
if (!context.identity) return;
|
|
1946
1918
|
const currentView = uiStatePart.getState()!.activeView;
|
|
1919
|
+
const currentSubview = uiStatePart.getState()!.activeSubview;
|
|
1947
1920
|
|
|
1948
1921
|
try {
|
|
1949
1922
|
// Always fetch basic stats for dashboard widgets
|
|
@@ -2055,8 +2028,8 @@ async function dispatchCombinedRefreshActionInner() {
|
|
|
2055
2028
|
}
|
|
2056
2029
|
}
|
|
2057
2030
|
|
|
2058
|
-
// Refresh remote ingress data if on
|
|
2059
|
-
if (currentView === 'remoteingress') {
|
|
2031
|
+
// Refresh remote ingress data if on the Network → Remote Ingress subview
|
|
2032
|
+
if (currentView === 'network' && currentSubview === 'remoteingress') {
|
|
2060
2033
|
try {
|
|
2061
2034
|
await remoteIngressStatePart.dispatchAction(fetchRemoteIngressAction, null);
|
|
2062
2035
|
} catch (error) {
|
|
@@ -2064,8 +2037,8 @@ async function dispatchCombinedRefreshActionInner() {
|
|
|
2064
2037
|
}
|
|
2065
2038
|
}
|
|
2066
2039
|
|
|
2067
|
-
// Refresh VPN data if on
|
|
2068
|
-
if (currentView === 'vpn') {
|
|
2040
|
+
// Refresh VPN data if on the Network → VPN subview
|
|
2041
|
+
if (currentView === 'network' && currentSubview === 'vpn') {
|
|
2069
2042
|
try {
|
|
2070
2043
|
await vpnStatePart.dispatchAction(fetchVpnAction, null);
|
|
2071
2044
|
} catch (error) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ops-view-apitokens.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as appstate from '
|
|
2
|
-
import * as interfaces from '
|
|
3
|
-
import { viewHostCss } from '
|
|
1
|
+
import * as appstate from '../../appstate.js';
|
|
2
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
3
|
+
import { viewHostCss } from '../shared/css.js';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
DeesElement,
|