@serve.zone/dcrouter 7.4.3 → 8.0.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 +10752 -3469
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +22 -2
- package/dist_ts/opsserver/handlers/email-ops.handler.js +166 -159
- package/dist_ts_interfaces/requests/email-ops.d.ts +51 -108
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +2 -16
- package/dist_ts_web/appstate.js +7 -176
- package/dist_ts_web/elements/ops-view-emails.d.ts +8 -31
- package/dist_ts_web/elements/ops-view-emails.js +54 -769
- package/dist_ts_web/elements/ops-view-logs.d.ts +2 -8
- package/dist_ts_web/elements/ops-view-logs.js +4 -101
- package/dist_ts_web/plugins.d.ts +2 -1
- package/dist_ts_web/plugins.js +4 -2
- package/dist_ts_web/router.d.ts +0 -6
- package/dist_ts_web/router.js +7 -81
- package/package.json +2 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/opsserver/handlers/email-ops.handler.ts +177 -225
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +8 -221
- package/ts_web/elements/ops-view-emails.ts +40 -749
- package/ts_web/elements/ops-view-logs.ts +2 -87
- package/ts_web/plugins.ts +4 -0
- package/ts_web/router.ts +6 -81
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as plugins from '../plugins.js';
|
|
2
1
|
import * as shared from './shared/index.js';
|
|
3
2
|
import * as appstate from '../appstate.js';
|
|
4
3
|
|
|
@@ -20,15 +19,6 @@ export class OpsViewLogs extends DeesElement {
|
|
|
20
19
|
filters: {},
|
|
21
20
|
};
|
|
22
21
|
|
|
23
|
-
@state()
|
|
24
|
-
accessor filterLevel: string | undefined;
|
|
25
|
-
|
|
26
|
-
@state()
|
|
27
|
-
accessor filterCategory: string | undefined;
|
|
28
|
-
|
|
29
|
-
@state()
|
|
30
|
-
accessor filterLimit: number = 100;
|
|
31
|
-
|
|
32
22
|
private lastPushedCount = 0;
|
|
33
23
|
|
|
34
24
|
constructor() {
|
|
@@ -44,63 +34,13 @@ export class OpsViewLogs extends DeesElement {
|
|
|
44
34
|
public static styles = [
|
|
45
35
|
cssManager.defaultStyles,
|
|
46
36
|
shared.viewHostCss,
|
|
47
|
-
css
|
|
48
|
-
.controls {
|
|
49
|
-
display: flex;
|
|
50
|
-
gap: 16px;
|
|
51
|
-
margin-bottom: 24px;
|
|
52
|
-
flex-wrap: wrap;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.filterGroup {
|
|
56
|
-
display: flex;
|
|
57
|
-
align-items: center;
|
|
58
|
-
gap: 8px;
|
|
59
|
-
}
|
|
60
|
-
`,
|
|
37
|
+
css``,
|
|
61
38
|
];
|
|
62
39
|
|
|
63
40
|
public render() {
|
|
64
41
|
return html`
|
|
65
42
|
<ops-sectionheading>Logs</ops-sectionheading>
|
|
66
43
|
|
|
67
|
-
<div class="controls">
|
|
68
|
-
<div class="filterGroup">
|
|
69
|
-
<dees-button
|
|
70
|
-
@click=${() => this.fetchLogs()}
|
|
71
|
-
>
|
|
72
|
-
Refresh Logs
|
|
73
|
-
</dees-button>
|
|
74
|
-
</div>
|
|
75
|
-
|
|
76
|
-
<div class="filterGroup">
|
|
77
|
-
<label>Level:</label>
|
|
78
|
-
<dees-input-dropdown
|
|
79
|
-
.options=${['all', 'debug', 'info', 'warn', 'error']}
|
|
80
|
-
.selectedOption=${'all'}
|
|
81
|
-
@selectedOption=${(e: any) => this.updateFilter('level', e.detail)}
|
|
82
|
-
></dees-input-dropdown>
|
|
83
|
-
</div>
|
|
84
|
-
|
|
85
|
-
<div class="filterGroup">
|
|
86
|
-
<label>Category:</label>
|
|
87
|
-
<dees-input-dropdown
|
|
88
|
-
.options=${['all', 'smtp', 'dns', 'security', 'system', 'email']}
|
|
89
|
-
.selectedOption=${'all'}
|
|
90
|
-
@selectedOption=${(e: any) => this.updateFilter('category', e.detail)}
|
|
91
|
-
></dees-input-dropdown>
|
|
92
|
-
</div>
|
|
93
|
-
|
|
94
|
-
<div class="filterGroup">
|
|
95
|
-
<label>Limit:</label>
|
|
96
|
-
<dees-input-dropdown
|
|
97
|
-
.options=${['50', '100', '200', '500']}
|
|
98
|
-
.selectedOption=${'100'}
|
|
99
|
-
@selectedOption=${(e: any) => this.updateFilter('limit', e.detail)}
|
|
100
|
-
></dees-input-dropdown>
|
|
101
|
-
</div>
|
|
102
|
-
</div>
|
|
103
|
-
|
|
104
44
|
<dees-chart-log
|
|
105
45
|
.label=${'Application Logs'}
|
|
106
46
|
.autoScroll=${true}
|
|
@@ -115,7 +55,7 @@ export class OpsViewLogs extends DeesElement {
|
|
|
115
55
|
this.lastPushedCount = 0;
|
|
116
56
|
// Only fetch if state is empty (streaming will handle new entries)
|
|
117
57
|
if (this.logState.recentLogs.length === 0) {
|
|
118
|
-
|
|
58
|
+
await appstate.logStatePart.dispatchAction(appstate.fetchRecentLogsAction, { limit: 100 });
|
|
119
59
|
}
|
|
120
60
|
}
|
|
121
61
|
|
|
@@ -166,29 +106,4 @@ export class OpsViewLogs extends DeesElement {
|
|
|
166
106
|
}));
|
|
167
107
|
}
|
|
168
108
|
|
|
169
|
-
private async fetchLogs() {
|
|
170
|
-
await appstate.logStatePart.dispatchAction(appstate.fetchRecentLogsAction, {
|
|
171
|
-
limit: this.filterLimit,
|
|
172
|
-
level: this.filterLevel as 'debug' | 'info' | 'warn' | 'error' | undefined,
|
|
173
|
-
category: this.filterCategory as 'smtp' | 'dns' | 'security' | 'system' | 'email' | undefined,
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
private updateFilter(type: string, value: string) {
|
|
178
|
-
const resolved = value === 'all' ? undefined : value;
|
|
179
|
-
|
|
180
|
-
switch (type) {
|
|
181
|
-
case 'level':
|
|
182
|
-
this.filterLevel = resolved;
|
|
183
|
-
break;
|
|
184
|
-
case 'category':
|
|
185
|
-
this.filterCategory = resolved;
|
|
186
|
-
break;
|
|
187
|
-
case 'limit':
|
|
188
|
-
this.filterLimit = resolved ? parseInt(resolved, 10) : 100;
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
this.fetchLogs();
|
|
193
|
-
}
|
|
194
109
|
}
|
package/ts_web/plugins.ts
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
import * as deesElement from '@design.estate/dees-element';
|
|
3
3
|
import * as deesCatalog from '@design.estate/dees-catalog';
|
|
4
4
|
|
|
5
|
+
// @serve.zone scope
|
|
6
|
+
import * as szCatalog from '@serve.zone/catalog';
|
|
7
|
+
|
|
5
8
|
// TypedSocket for real-time push communication
|
|
6
9
|
import * as typedsocket from '@api.global/typedsocket';
|
|
7
10
|
|
|
8
11
|
export {
|
|
9
12
|
deesElement,
|
|
10
13
|
deesCatalog,
|
|
14
|
+
szCatalog,
|
|
11
15
|
typedsocket,
|
|
12
16
|
}
|
|
13
17
|
|
package/ts_web/router.ts
CHANGED
|
@@ -4,10 +4,8 @@ import * as appstate from './appstate.js';
|
|
|
4
4
|
const SmartRouter = plugins.domtools.plugins.smartrouter.SmartRouter;
|
|
5
5
|
|
|
6
6
|
export const validViews = ['overview', 'network', 'emails', 'logs', 'configuration', 'security', 'certificates', 'remoteingress'] as const;
|
|
7
|
-
export const validEmailFolders = ['queued', 'sent', 'failed', 'security'] as const;
|
|
8
7
|
|
|
9
8
|
export type TValidView = typeof validViews[number];
|
|
10
|
-
export type TValidEmailFolder = typeof validEmailFolders[number];
|
|
11
9
|
|
|
12
10
|
class AppRouter {
|
|
13
11
|
private router: InstanceType<typeof SmartRouter>;
|
|
@@ -27,31 +25,10 @@ class AppRouter {
|
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
private setupRoutes(): void {
|
|
30
|
-
// Main views
|
|
31
28
|
for (const view of validViews) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.updateViewState('emails');
|
|
36
|
-
this.updateEmailFolder('queued');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// Email with folder parameter
|
|
40
|
-
this.router.on('/emails/:folder', async (routeInfo) => {
|
|
41
|
-
const folder = routeInfo.params.folder as string;
|
|
42
|
-
if (validEmailFolders.includes(folder as TValidEmailFolder)) {
|
|
43
|
-
this.updateViewState('emails');
|
|
44
|
-
this.updateEmailFolder(folder as TValidEmailFolder);
|
|
45
|
-
} else {
|
|
46
|
-
// Invalid folder, redirect to queued
|
|
47
|
-
this.navigateTo('/emails/queued');
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
} else {
|
|
51
|
-
this.router.on(`/${view}`, async () => {
|
|
52
|
-
this.updateViewState(view);
|
|
53
|
-
});
|
|
54
|
-
}
|
|
29
|
+
this.router.on(`/${view}`, async () => {
|
|
30
|
+
this.updateViewState(view);
|
|
31
|
+
});
|
|
55
32
|
}
|
|
56
33
|
|
|
57
34
|
// Root redirect
|
|
@@ -61,60 +38,32 @@ class AppRouter {
|
|
|
61
38
|
}
|
|
62
39
|
|
|
63
40
|
private setupStateSync(): void {
|
|
64
|
-
// Sync URL when state changes programmatically (not from router)
|
|
65
41
|
appstate.uiStatePart.state.subscribe((uiState) => {
|
|
66
42
|
if (this.suppressStateUpdate) return;
|
|
67
43
|
|
|
68
44
|
const currentPath = window.location.pathname;
|
|
69
|
-
const expectedPath =
|
|
45
|
+
const expectedPath = `/${uiState.activeView}`;
|
|
70
46
|
|
|
71
|
-
|
|
72
|
-
if (!currentPath.startsWith(expectedPath)) {
|
|
47
|
+
if (currentPath !== expectedPath) {
|
|
73
48
|
this.suppressStateUpdate = true;
|
|
74
|
-
|
|
75
|
-
const emailState = appstate.emailOpsStatePart.getState();
|
|
76
|
-
this.router.pushUrl(`/emails/${emailState.currentView}`);
|
|
77
|
-
} else {
|
|
78
|
-
this.router.pushUrl(`/${uiState.activeView}`);
|
|
79
|
-
}
|
|
49
|
+
this.router.pushUrl(expectedPath);
|
|
80
50
|
this.suppressStateUpdate = false;
|
|
81
51
|
}
|
|
82
52
|
});
|
|
83
53
|
}
|
|
84
54
|
|
|
85
|
-
private getExpectedPath(view: string): string {
|
|
86
|
-
if (view === 'emails') {
|
|
87
|
-
return '/emails';
|
|
88
|
-
}
|
|
89
|
-
return `/${view}`;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
55
|
private handleInitialRoute(): void {
|
|
93
56
|
const path = window.location.pathname;
|
|
94
57
|
|
|
95
58
|
if (!path || path === '/') {
|
|
96
|
-
// Redirect root to overview
|
|
97
59
|
this.router.pushUrl('/overview');
|
|
98
60
|
} else {
|
|
99
|
-
// Parse current path and update state
|
|
100
61
|
const segments = path.split('/').filter(Boolean);
|
|
101
62
|
const view = segments[0];
|
|
102
63
|
|
|
103
64
|
if (validViews.includes(view as TValidView)) {
|
|
104
65
|
this.updateViewState(view as TValidView);
|
|
105
|
-
|
|
106
|
-
if (view === 'emails' && segments[1]) {
|
|
107
|
-
const folder = segments[1];
|
|
108
|
-
if (validEmailFolders.includes(folder as TValidEmailFolder)) {
|
|
109
|
-
this.updateEmailFolder(folder as TValidEmailFolder);
|
|
110
|
-
} else {
|
|
111
|
-
this.updateEmailFolder('queued');
|
|
112
|
-
}
|
|
113
|
-
} else if (view === 'emails') {
|
|
114
|
-
this.updateEmailFolder('queued');
|
|
115
|
-
}
|
|
116
66
|
} else {
|
|
117
|
-
// Invalid view, redirect to overview
|
|
118
67
|
this.router.pushUrl('/overview');
|
|
119
68
|
}
|
|
120
69
|
}
|
|
@@ -132,18 +81,6 @@ class AppRouter {
|
|
|
132
81
|
this.suppressStateUpdate = false;
|
|
133
82
|
}
|
|
134
83
|
|
|
135
|
-
private updateEmailFolder(folder: TValidEmailFolder): void {
|
|
136
|
-
this.suppressStateUpdate = true;
|
|
137
|
-
const currentState = appstate.emailOpsStatePart.getState();
|
|
138
|
-
if (currentState.currentView !== folder) {
|
|
139
|
-
appstate.emailOpsStatePart.setState({
|
|
140
|
-
...currentState,
|
|
141
|
-
currentView: folder as appstate.IEmailOpsState['currentView'],
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
this.suppressStateUpdate = false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
84
|
public navigateTo(path: string): void {
|
|
148
85
|
this.router.pushUrl(path);
|
|
149
86
|
}
|
|
@@ -156,22 +93,10 @@ class AppRouter {
|
|
|
156
93
|
}
|
|
157
94
|
}
|
|
158
95
|
|
|
159
|
-
public navigateToEmailFolder(folder: string): void {
|
|
160
|
-
if (validEmailFolders.includes(folder as TValidEmailFolder)) {
|
|
161
|
-
this.navigateTo(`/emails/${folder}`);
|
|
162
|
-
} else {
|
|
163
|
-
this.navigateTo('/emails/queued');
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
96
|
public getCurrentView(): string {
|
|
168
97
|
return appstate.uiStatePart.getState().activeView;
|
|
169
98
|
}
|
|
170
99
|
|
|
171
|
-
public getCurrentEmailFolder(): string {
|
|
172
|
-
return appstate.emailOpsStatePart.getState().currentView;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
100
|
public destroy(): void {
|
|
176
101
|
this.router.destroy();
|
|
177
102
|
this.initialized = false;
|