@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,160 @@
|
|
|
1
|
+
import * as appstate from '../../appstate.js';
|
|
2
|
+
import { viewHostCss } from '../shared/css.js';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
DeesElement,
|
|
6
|
+
customElement,
|
|
7
|
+
html,
|
|
8
|
+
state,
|
|
9
|
+
css,
|
|
10
|
+
cssManager,
|
|
11
|
+
type TemplateResult,
|
|
12
|
+
} from '@design.estate/dees-element';
|
|
13
|
+
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
14
|
+
|
|
15
|
+
declare global {
|
|
16
|
+
interface HTMLElementTagNameMap {
|
|
17
|
+
'ops-view-email-security': OpsViewEmailSecurity;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@customElement('ops-view-email-security')
|
|
22
|
+
export class OpsViewEmailSecurity extends DeesElement {
|
|
23
|
+
@state()
|
|
24
|
+
accessor statsState: appstate.IStatsState = appstate.statsStatePart.getState()!;
|
|
25
|
+
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
const sub = appstate.statsStatePart
|
|
29
|
+
.select((s) => s)
|
|
30
|
+
.subscribe((s) => {
|
|
31
|
+
this.statsState = s;
|
|
32
|
+
});
|
|
33
|
+
this.rxSubscriptions.push(sub);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public static styles = [
|
|
37
|
+
cssManager.defaultStyles,
|
|
38
|
+
viewHostCss,
|
|
39
|
+
css`
|
|
40
|
+
h2 {
|
|
41
|
+
margin: 32px 0 16px 0;
|
|
42
|
+
font-size: 24px;
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
color: ${cssManager.bdTheme('#333', '#ccc')};
|
|
45
|
+
}
|
|
46
|
+
dees-statsgrid {
|
|
47
|
+
margin-bottom: 32px;
|
|
48
|
+
}
|
|
49
|
+
.securityCard {
|
|
50
|
+
background: ${cssManager.bdTheme('#fff', '#222')};
|
|
51
|
+
border: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
|
52
|
+
border-radius: 8px;
|
|
53
|
+
padding: 24px;
|
|
54
|
+
position: relative;
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
}
|
|
57
|
+
.actionButton {
|
|
58
|
+
margin-top: 16px;
|
|
59
|
+
}
|
|
60
|
+
`,
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
public render(): TemplateResult {
|
|
64
|
+
const metrics = this.statsState.securityMetrics;
|
|
65
|
+
|
|
66
|
+
if (!metrics) {
|
|
67
|
+
return html`
|
|
68
|
+
<div class="loadingMessage">
|
|
69
|
+
<p>Loading security metrics...</p>
|
|
70
|
+
</div>
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const tiles: IStatsTile[] = [
|
|
75
|
+
{
|
|
76
|
+
id: 'malware',
|
|
77
|
+
title: 'Malware Detection',
|
|
78
|
+
value: metrics.malwareDetected,
|
|
79
|
+
type: 'number',
|
|
80
|
+
icon: 'lucide:BugOff',
|
|
81
|
+
color: metrics.malwareDetected > 0 ? '#ef4444' : '#22c55e',
|
|
82
|
+
description: 'Malware detected',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'phishing',
|
|
86
|
+
title: 'Phishing Detection',
|
|
87
|
+
value: metrics.phishingDetected,
|
|
88
|
+
type: 'number',
|
|
89
|
+
icon: 'lucide:Fish',
|
|
90
|
+
color: metrics.phishingDetected > 0 ? '#ef4444' : '#22c55e',
|
|
91
|
+
description: 'Phishing attempts detected',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'suspicious',
|
|
95
|
+
title: 'Suspicious Activities',
|
|
96
|
+
value: metrics.suspiciousActivities,
|
|
97
|
+
type: 'number',
|
|
98
|
+
icon: 'lucide:TriangleAlert',
|
|
99
|
+
color: metrics.suspiciousActivities > 5 ? '#ef4444' : '#f59e0b',
|
|
100
|
+
description: 'Suspicious activities detected',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: 'spam',
|
|
104
|
+
title: 'Spam Detection',
|
|
105
|
+
value: metrics.spamDetected,
|
|
106
|
+
type: 'number',
|
|
107
|
+
icon: 'lucide:Ban',
|
|
108
|
+
color: '#f59e0b',
|
|
109
|
+
description: 'Spam emails blocked',
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
return html`
|
|
114
|
+
<dees-heading level="hr">Email Security</dees-heading>
|
|
115
|
+
|
|
116
|
+
<dees-statsgrid
|
|
117
|
+
.tiles=${tiles}
|
|
118
|
+
.minTileWidth=${200}
|
|
119
|
+
></dees-statsgrid>
|
|
120
|
+
|
|
121
|
+
<h2>Email Security Configuration</h2>
|
|
122
|
+
<div class="securityCard">
|
|
123
|
+
<dees-form>
|
|
124
|
+
<dees-input-checkbox
|
|
125
|
+
.key=${'enableSPF'}
|
|
126
|
+
.label=${'Enable SPF checking'}
|
|
127
|
+
.value=${true}
|
|
128
|
+
></dees-input-checkbox>
|
|
129
|
+
<dees-input-checkbox
|
|
130
|
+
.key=${'enableDKIM'}
|
|
131
|
+
.label=${'Enable DKIM validation'}
|
|
132
|
+
.value=${true}
|
|
133
|
+
></dees-input-checkbox>
|
|
134
|
+
<dees-input-checkbox
|
|
135
|
+
.key=${'enableDMARC'}
|
|
136
|
+
.label=${'Enable DMARC policy enforcement'}
|
|
137
|
+
.value=${true}
|
|
138
|
+
></dees-input-checkbox>
|
|
139
|
+
<dees-input-checkbox
|
|
140
|
+
.key=${'enableSpamFilter'}
|
|
141
|
+
.label=${'Enable spam filtering'}
|
|
142
|
+
.value=${true}
|
|
143
|
+
></dees-input-checkbox>
|
|
144
|
+
</dees-form>
|
|
145
|
+
<dees-button
|
|
146
|
+
class="actionButton"
|
|
147
|
+
type="highlighted"
|
|
148
|
+
@click=${() => this.saveEmailSecuritySettings()}
|
|
149
|
+
>
|
|
150
|
+
Save Settings
|
|
151
|
+
</dees-button>
|
|
152
|
+
</div>
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private async saveEmailSecuritySettings() {
|
|
157
|
+
// Config is read-only from the UI for now
|
|
158
|
+
alert('Email security settings are read-only. Update the dcrouter configuration file to change these settings.');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { DeesElement, property, html, customElement, type TemplateResult, css, state, cssManager } from '@design.estate/dees-element';
|
|
2
|
-
import * as plugins from '
|
|
3
|
-
import * as appstate from '
|
|
4
|
-
import * as shared from '
|
|
5
|
-
import * as interfaces from '
|
|
2
|
+
import * as plugins from '../../plugins.js';
|
|
3
|
+
import * as appstate from '../../appstate.js';
|
|
4
|
+
import * as shared from '../shared/index.js';
|
|
5
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
6
6
|
|
|
7
7
|
declare global {
|
|
8
8
|
interface HTMLElementTagNameMap {
|
package/ts_web/elements/index.ts
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
export * from './ops-dashboard.js';
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
2
|
+
export * from './overview/index.js';
|
|
3
|
+
export * from './network/index.js';
|
|
4
|
+
export * from './email/index.js';
|
|
5
5
|
export * from './ops-view-logs.js';
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './ops-view-apitokens.js';
|
|
9
|
-
export * from './ops-view-security.js';
|
|
6
|
+
export * from './access/index.js';
|
|
7
|
+
export * from './security/index.js';
|
|
10
8
|
export * from './ops-view-certificates.js';
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './ops-view-vpn.js';
|
|
13
|
-
export * from './ops-view-sourceprofiles.js';
|
|
14
|
-
export * from './ops-view-networktargets.js';
|
|
15
|
-
export * from './ops-view-targetprofiles.js';
|
|
16
|
-
export * from './shared/index.js';
|
|
9
|
+
export * from './shared/index.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './ops-view-network-activity.js';
|
|
2
|
+
export * from './ops-view-routes.js';
|
|
3
|
+
export * from './ops-view-sourceprofiles.js';
|
|
4
|
+
export * from './ops-view-networktargets.js';
|
|
5
|
+
export * from './ops-view-targetprofiles.js';
|
|
6
|
+
export * from './ops-view-remoteingress.js';
|
|
7
|
+
export * from './ops-view-vpn.js';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { DeesElement, property, html, customElement, type TemplateResult, css, state, cssManager } from '@design.estate/dees-element';
|
|
2
|
-
import * as appstate from '
|
|
3
|
-
import * as interfaces from '
|
|
4
|
-
import { viewHostCss } from '
|
|
2
|
+
import * as appstate from '../../appstate.js';
|
|
3
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
4
|
+
import { viewHostCss } from '../shared/css.js';
|
|
5
5
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
6
6
|
|
|
7
7
|
declare global {
|
|
8
8
|
interface HTMLElementTagNameMap {
|
|
9
|
-
'ops-view-network':
|
|
9
|
+
'ops-view-network-activity': OpsViewNetworkActivity;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -26,14 +26,14 @@ interface INetworkRequest {
|
|
|
26
26
|
route?: string;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
@customElement('ops-view-network')
|
|
30
|
-
export class
|
|
29
|
+
@customElement('ops-view-network-activity')
|
|
30
|
+
export class OpsViewNetworkActivity extends DeesElement {
|
|
31
31
|
/** How far back the traffic chart shows */
|
|
32
32
|
private static readonly CHART_WINDOW_MS = 5 * 60 * 1000; // 5 minutes
|
|
33
33
|
/** How often a new data point is added */
|
|
34
34
|
private static readonly UPDATE_INTERVAL_MS = 1000; // 1 second
|
|
35
35
|
/** Derived: max data points the buffer holds */
|
|
36
|
-
private static readonly MAX_DATA_POINTS =
|
|
36
|
+
private static readonly MAX_DATA_POINTS = OpsViewNetworkActivity.CHART_WINDOW_MS / OpsViewNetworkActivity.UPDATE_INTERVAL_MS;
|
|
37
37
|
|
|
38
38
|
@state()
|
|
39
39
|
accessor statsState = appstate.statsStatePart.getState()!;
|
|
@@ -50,10 +50,10 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
50
50
|
|
|
51
51
|
@state()
|
|
52
52
|
accessor trafficDataOut: Array<{ x: string | number; y: number }> = [];
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
// Track if we need to update the chart to avoid unnecessary re-renders
|
|
55
55
|
private lastChartUpdate = 0;
|
|
56
|
-
private chartUpdateThreshold =
|
|
56
|
+
private chartUpdateThreshold = OpsViewNetworkActivity.UPDATE_INTERVAL_MS; // Minimum ms between chart updates
|
|
57
57
|
|
|
58
58
|
private trafficUpdateTimer: any = null;
|
|
59
59
|
private requestsPerSecHistory: number[] = []; // Track requests/sec over time for trend
|
|
@@ -101,17 +101,17 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
101
101
|
this.updateNetworkData();
|
|
102
102
|
});
|
|
103
103
|
this.rxSubscriptions.push(statsUnsubscribe);
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
const networkUnsubscribe = appstate.networkStatePart.select().subscribe((state) => {
|
|
106
106
|
this.networkState = state;
|
|
107
107
|
this.updateNetworkData();
|
|
108
108
|
});
|
|
109
109
|
this.rxSubscriptions.push(networkUnsubscribe);
|
|
110
110
|
}
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
private initializeTrafficData() {
|
|
113
113
|
const now = Date.now();
|
|
114
|
-
const { MAX_DATA_POINTS, UPDATE_INTERVAL_MS } =
|
|
114
|
+
const { MAX_DATA_POINTS, UPDATE_INTERVAL_MS } = OpsViewNetworkActivity;
|
|
115
115
|
|
|
116
116
|
// Initialize with empty data points for both in and out
|
|
117
117
|
const emptyData = Array.from({ length: MAX_DATA_POINTS }, (_, i) => {
|
|
@@ -148,7 +148,7 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
148
148
|
y: Math.round((p.out * 8) / 1000000 * 10) / 10,
|
|
149
149
|
}));
|
|
150
150
|
|
|
151
|
-
const { MAX_DATA_POINTS, UPDATE_INTERVAL_MS } =
|
|
151
|
+
const { MAX_DATA_POINTS, UPDATE_INTERVAL_MS } = OpsViewNetworkActivity;
|
|
152
152
|
|
|
153
153
|
// Use history as the chart data, keeping the most recent points within the window
|
|
154
154
|
const sliceStart = Math.max(0, historyIn.length - MAX_DATA_POINTS);
|
|
@@ -285,8 +285,8 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
285
285
|
|
|
286
286
|
public render() {
|
|
287
287
|
return html`
|
|
288
|
-
<dees-heading level="
|
|
289
|
-
|
|
288
|
+
<dees-heading level="hr">Network Activity</dees-heading>
|
|
289
|
+
|
|
290
290
|
<div class="networkContainer">
|
|
291
291
|
<!-- Stats Grid -->
|
|
292
292
|
${this.renderNetworkStats()}
|
|
@@ -307,7 +307,7 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
307
307
|
}
|
|
308
308
|
]}
|
|
309
309
|
.realtimeMode=${true}
|
|
310
|
-
.rollingWindow=${
|
|
310
|
+
.rollingWindow=${OpsViewNetworkActivity.CHART_WINDOW_MS}
|
|
311
311
|
.yAxisFormatter=${(val: number) => `${val} Mbit/s`}
|
|
312
312
|
></dees-chart-area>
|
|
313
313
|
|
|
@@ -323,7 +323,6 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
323
323
|
<!-- Requests Table -->
|
|
324
324
|
<dees-table
|
|
325
325
|
.data=${this.networkRequests}
|
|
326
|
-
.showColumnFilters=${true}
|
|
327
326
|
.displayFunction=${(req: INetworkRequest) => ({
|
|
328
327
|
Time: new Date(req.timestamp).toLocaleTimeString(),
|
|
329
328
|
Protocol: html`<span class="protocolBadge ${req.protocol}">${req.protocol.toUpperCase()}</span>`,
|
|
@@ -358,7 +357,7 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
358
357
|
|
|
359
358
|
private async showRequestDetails(request: INetworkRequest) {
|
|
360
359
|
const { DeesModal } = await import('@design.estate/dees-catalog');
|
|
361
|
-
|
|
360
|
+
|
|
362
361
|
await DeesModal.createAndShow({
|
|
363
362
|
heading: 'Request Details',
|
|
364
363
|
content: html`
|
|
@@ -401,10 +400,10 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
401
400
|
if (!statusCode) {
|
|
402
401
|
return html`<span class="statusBadge warning">N/A</span>`;
|
|
403
402
|
}
|
|
404
|
-
|
|
403
|
+
|
|
405
404
|
const statusClass = statusCode >= 200 && statusCode < 300 ? 'success' :
|
|
406
405
|
statusCode >= 400 ? 'error' : 'warning';
|
|
407
|
-
|
|
406
|
+
|
|
408
407
|
return html`<span class="statusBadge ${statusClass}">${statusCode}</span>`;
|
|
409
408
|
}
|
|
410
409
|
|
|
@@ -427,26 +426,26 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
427
426
|
const units = ['B', 'KB', 'MB', 'GB'];
|
|
428
427
|
let size = bytes;
|
|
429
428
|
let unitIndex = 0;
|
|
430
|
-
|
|
429
|
+
|
|
431
430
|
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
432
431
|
size /= 1024;
|
|
433
432
|
unitIndex++;
|
|
434
433
|
}
|
|
435
|
-
|
|
434
|
+
|
|
436
435
|
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
437
436
|
}
|
|
438
|
-
|
|
437
|
+
|
|
439
438
|
private formatBitsPerSecond(bytesPerSecond: number): string {
|
|
440
439
|
const bitsPerSecond = bytesPerSecond * 8; // Convert bytes to bits
|
|
441
440
|
const units = ['bit/s', 'kbit/s', 'Mbit/s', 'Gbit/s'];
|
|
442
441
|
let size = bitsPerSecond;
|
|
443
442
|
let unitIndex = 0;
|
|
444
|
-
|
|
443
|
+
|
|
445
444
|
while (size >= 1000 && unitIndex < units.length - 1) {
|
|
446
445
|
size /= 1000; // Use 1000 for bits (not 1024)
|
|
447
446
|
unitIndex++;
|
|
448
447
|
}
|
|
449
|
-
|
|
448
|
+
|
|
450
449
|
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
451
450
|
}
|
|
452
451
|
|
|
@@ -521,18 +520,9 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
521
520
|
];
|
|
522
521
|
|
|
523
522
|
return html`
|
|
524
|
-
<dees-statsgrid
|
|
523
|
+
<dees-statsgrid
|
|
525
524
|
.tiles=${tiles}
|
|
526
525
|
.minTileWidth=${200}
|
|
527
|
-
.gridActions=${[
|
|
528
|
-
{
|
|
529
|
-
name: 'Export Data',
|
|
530
|
-
iconName: 'lucide:FileOutput',
|
|
531
|
-
action: async () => {
|
|
532
|
-
console.log('Export feature coming soon');
|
|
533
|
-
},
|
|
534
|
-
},
|
|
535
|
-
]}
|
|
536
526
|
></dees-statsgrid>
|
|
537
527
|
`;
|
|
538
528
|
}
|
|
@@ -604,7 +594,6 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
604
594
|
return html`
|
|
605
595
|
<dees-table
|
|
606
596
|
.data=${this.networkState.topIPs}
|
|
607
|
-
.showColumnFilters=${true}
|
|
608
597
|
.displayFunction=${(ipData: { ip: string; count: number }) => {
|
|
609
598
|
const bw = bandwidthByIP.get(ipData.ip);
|
|
610
599
|
return {
|
|
@@ -632,7 +621,6 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
632
621
|
return html`
|
|
633
622
|
<dees-table
|
|
634
623
|
.data=${backends}
|
|
635
|
-
.showColumnFilters=${true}
|
|
636
624
|
.displayFunction=${(item: interfaces.data.IBackendInfo) => {
|
|
637
625
|
const totalErrors = item.connectErrors + item.handshakeErrors + item.requestErrors;
|
|
638
626
|
const protocolClass = item.protocol.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
@@ -735,12 +723,12 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
735
723
|
// Only update if connections changed significantly
|
|
736
724
|
const newConnectionCount = this.networkState.connections.length;
|
|
737
725
|
const oldConnectionCount = this.networkRequests.length;
|
|
738
|
-
|
|
726
|
+
|
|
739
727
|
// Check if we need to update the network requests array
|
|
740
|
-
const shouldUpdate = newConnectionCount !== oldConnectionCount ||
|
|
728
|
+
const shouldUpdate = newConnectionCount !== oldConnectionCount ||
|
|
741
729
|
newConnectionCount === 0 ||
|
|
742
730
|
(newConnectionCount > 0 && this.networkRequests.length === 0);
|
|
743
|
-
|
|
731
|
+
|
|
744
732
|
if (shouldUpdate) {
|
|
745
733
|
// Convert connection data to network requests format
|
|
746
734
|
if (newConnectionCount > 0) {
|
|
@@ -763,62 +751,62 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
763
751
|
this.networkRequests = [];
|
|
764
752
|
}
|
|
765
753
|
}
|
|
766
|
-
|
|
754
|
+
|
|
767
755
|
// Load server-side throughput history into chart (once)
|
|
768
756
|
if (!this.historyLoaded && this.networkState.throughputHistory && this.networkState.throughputHistory.length > 0) {
|
|
769
757
|
this.loadThroughputHistory();
|
|
770
758
|
}
|
|
771
759
|
}
|
|
772
|
-
|
|
760
|
+
|
|
773
761
|
private startTrafficUpdateTimer() {
|
|
774
762
|
this.stopTrafficUpdateTimer(); // Clear any existing timer
|
|
775
763
|
this.trafficUpdateTimer = setInterval(() => {
|
|
776
764
|
this.addTrafficDataPoint();
|
|
777
|
-
},
|
|
765
|
+
}, OpsViewNetworkActivity.UPDATE_INTERVAL_MS);
|
|
778
766
|
}
|
|
779
|
-
|
|
767
|
+
|
|
780
768
|
private addTrafficDataPoint() {
|
|
781
769
|
const now = Date.now();
|
|
782
|
-
|
|
770
|
+
|
|
783
771
|
// Throttle chart updates to avoid excessive re-renders
|
|
784
772
|
if (now - this.lastChartUpdate < this.chartUpdateThreshold) {
|
|
785
773
|
return;
|
|
786
774
|
}
|
|
787
|
-
|
|
775
|
+
|
|
788
776
|
const throughput = this.calculateThroughput();
|
|
789
|
-
|
|
777
|
+
|
|
790
778
|
// Convert to Mbps (bytes * 8 / 1,000,000)
|
|
791
779
|
const throughputInMbps = (throughput.in * 8) / 1000000;
|
|
792
780
|
const throughputOutMbps = (throughput.out * 8) / 1000000;
|
|
793
|
-
|
|
781
|
+
|
|
794
782
|
// Add new data points
|
|
795
783
|
const timestamp = new Date(now).toISOString();
|
|
796
|
-
|
|
784
|
+
|
|
797
785
|
const newDataPointIn = {
|
|
798
786
|
x: timestamp,
|
|
799
787
|
y: Math.round(throughputInMbps * 10) / 10
|
|
800
788
|
};
|
|
801
|
-
|
|
789
|
+
|
|
802
790
|
const newDataPointOut = {
|
|
803
791
|
x: timestamp,
|
|
804
792
|
y: Math.round(throughputOutMbps * 10) / 10
|
|
805
793
|
};
|
|
806
|
-
|
|
794
|
+
|
|
807
795
|
// In-place mutation then reassign for Lit reactivity (avoids 4 intermediate arrays)
|
|
808
|
-
if (this.trafficDataIn.length >=
|
|
796
|
+
if (this.trafficDataIn.length >= OpsViewNetworkActivity.MAX_DATA_POINTS) {
|
|
809
797
|
this.trafficDataIn.shift();
|
|
810
798
|
this.trafficDataOut.shift();
|
|
811
799
|
}
|
|
812
800
|
this.trafficDataIn = [...this.trafficDataIn, newDataPointIn];
|
|
813
801
|
this.trafficDataOut = [...this.trafficDataOut, newDataPointOut];
|
|
814
|
-
|
|
802
|
+
|
|
815
803
|
this.lastChartUpdate = now;
|
|
816
804
|
}
|
|
817
|
-
|
|
805
|
+
|
|
818
806
|
private stopTrafficUpdateTimer() {
|
|
819
807
|
if (this.trafficUpdateTimer) {
|
|
820
808
|
clearInterval(this.trafficUpdateTimer);
|
|
821
809
|
this.trafficUpdateTimer = null;
|
|
822
810
|
}
|
|
823
811
|
}
|
|
824
|
-
}
|
|
812
|
+
}
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
state,
|
|
8
8
|
cssManager,
|
|
9
9
|
} from '@design.estate/dees-element';
|
|
10
|
-
import * as appstate from '
|
|
11
|
-
import * as interfaces from '
|
|
12
|
-
import { viewHostCss } from '
|
|
10
|
+
import * as appstate from '../../appstate.js';
|
|
11
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
12
|
+
import { viewHostCss } from '../shared/css.js';
|
|
13
13
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
14
14
|
|
|
15
15
|
declare global {
|
|
@@ -64,7 +64,7 @@ export class OpsViewNetworkTargets extends DeesElement {
|
|
|
64
64
|
];
|
|
65
65
|
|
|
66
66
|
return html`
|
|
67
|
-
<dees-heading level="
|
|
67
|
+
<dees-heading level="hr">Network Targets</dees-heading>
|
|
68
68
|
<div class="targetsContainer">
|
|
69
69
|
<dees-statsgrid .tiles=${statsTiles}></dees-statsgrid>
|
|
70
70
|
<dees-table
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
state,
|
|
8
8
|
cssManager,
|
|
9
9
|
} from '@design.estate/dees-element';
|
|
10
|
-
import * as appstate from '
|
|
11
|
-
import * as interfaces from '
|
|
12
|
-
import { viewHostCss } from '
|
|
10
|
+
import * as appstate from '../../appstate.js';
|
|
11
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
12
|
+
import { viewHostCss } from '../shared/css.js';
|
|
13
13
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
14
14
|
|
|
15
15
|
declare global {
|
|
@@ -174,7 +174,7 @@ export class OpsViewRemoteIngress extends DeesElement {
|
|
|
174
174
|
];
|
|
175
175
|
|
|
176
176
|
return html`
|
|
177
|
-
<dees-heading level="
|
|
177
|
+
<dees-heading level="hr">Remote Ingress</dees-heading>
|
|
178
178
|
|
|
179
179
|
${this.riState.newEdgeId ? html`
|
|
180
180
|
<div class="secretDialog">
|
|
@@ -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
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
5
5
|
|
|
6
6
|
import {
|
|
@@ -200,7 +200,7 @@ export class OpsViewRoutes extends DeesElement {
|
|
|
200
200
|
});
|
|
201
201
|
|
|
202
202
|
return html`
|
|
203
|
-
<dees-heading level="
|
|
203
|
+
<dees-heading level="hr">Route Management</dees-heading>
|
|
204
204
|
|
|
205
205
|
<div class="routesContainer">
|
|
206
206
|
<dees-statsgrid
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
state,
|
|
8
8
|
cssManager,
|
|
9
9
|
} from '@design.estate/dees-element';
|
|
10
|
-
import * as appstate from '
|
|
11
|
-
import * as interfaces from '
|
|
12
|
-
import { viewHostCss } from '
|
|
10
|
+
import * as appstate from '../../appstate.js';
|
|
11
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
12
|
+
import { viewHostCss } from '../shared/css.js';
|
|
13
13
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
14
14
|
|
|
15
15
|
declare global {
|
|
@@ -64,7 +64,7 @@ export class OpsViewSourceProfiles extends DeesElement {
|
|
|
64
64
|
];
|
|
65
65
|
|
|
66
66
|
return html`
|
|
67
|
-
<dees-heading level="
|
|
67
|
+
<dees-heading level="hr">Source Profiles</dees-heading>
|
|
68
68
|
<div class="profilesContainer">
|
|
69
69
|
<dees-statsgrid .tiles=${statsTiles}></dees-statsgrid>
|
|
70
70
|
<dees-table
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
state,
|
|
8
8
|
cssManager,
|
|
9
9
|
} from '@design.estate/dees-element';
|
|
10
|
-
import * as plugins from '
|
|
11
|
-
import * as appstate from '
|
|
12
|
-
import * as interfaces from '
|
|
13
|
-
import { viewHostCss } from '
|
|
10
|
+
import * as plugins from '../../plugins.js';
|
|
11
|
+
import * as appstate from '../../appstate.js';
|
|
12
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
13
|
+
import { viewHostCss } from '../shared/css.js';
|
|
14
14
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
15
15
|
|
|
16
16
|
declare global {
|
|
@@ -77,7 +77,7 @@ export class OpsViewTargetProfiles extends DeesElement {
|
|
|
77
77
|
];
|
|
78
78
|
|
|
79
79
|
return html`
|
|
80
|
-
<dees-heading level="
|
|
80
|
+
<dees-heading level="hr">Target Profiles</dees-heading>
|
|
81
81
|
<div class="profilesContainer">
|
|
82
82
|
<dees-statsgrid .tiles=${statsTiles}></dees-statsgrid>
|
|
83
83
|
<dees-table
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
state,
|
|
8
8
|
cssManager,
|
|
9
9
|
} from '@design.estate/dees-element';
|
|
10
|
-
import * as plugins from '
|
|
11
|
-
import * as appstate from '
|
|
12
|
-
import * as interfaces from '
|
|
13
|
-
import { viewHostCss } from '
|
|
10
|
+
import * as plugins from '../../plugins.js';
|
|
11
|
+
import * as appstate from '../../appstate.js';
|
|
12
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
13
|
+
import { viewHostCss } from '../shared/css.js';
|
|
14
14
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -223,7 +223,7 @@ export class OpsViewVpn extends DeesElement {
|
|
|
223
223
|
];
|
|
224
224
|
|
|
225
225
|
return html`
|
|
226
|
-
<dees-heading level="
|
|
226
|
+
<dees-heading level="hr">VPN</dees-heading>
|
|
227
227
|
<div class="vpnContainer">
|
|
228
228
|
|
|
229
229
|
${this.vpnState.newClientConfig ? html`
|