@serve.zone/dcrouter 7.4.2 → 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.
@@ -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
- this.fetchLogs();
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
- if (view === 'emails') {
33
- // Email root - default to queued
34
- this.router.on('/emails', async () => {
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 = this.getExpectedPath(uiState.activeView);
45
+ const expectedPath = `/${uiState.activeView}`;
70
46
 
71
- // Only update URL if it doesn't match current state
72
- if (!currentPath.startsWith(expectedPath)) {
47
+ if (currentPath !== expectedPath) {
73
48
  this.suppressStateUpdate = true;
74
- if (uiState.activeView === 'emails') {
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;