@serve.zone/dcrouter 12.10.0 → 13.0.1

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.
Files changed (86) hide show
  1. package/dist_serve/bundle.js +1873 -1850
  2. package/dist_ts/00_commitinfo_data.js +2 -2
  3. package/dist_ts/classes.dcrouter.d.ts +5 -4
  4. package/dist_ts/classes.dcrouter.js +25 -49
  5. package/dist_ts/config/classes.reference-resolver.d.ts +7 -7
  6. package/dist_ts/config/classes.reference-resolver.js +27 -27
  7. package/dist_ts/config/classes.route-config-manager.d.ts +2 -2
  8. package/dist_ts/config/classes.route-config-manager.js +12 -15
  9. package/dist_ts/config/classes.target-profile-manager.d.ts +63 -0
  10. package/dist_ts/config/classes.target-profile-manager.js +295 -0
  11. package/dist_ts/config/index.d.ts +1 -0
  12. package/dist_ts/config/index.js +2 -1
  13. package/dist_ts/db/documents/{classes.security-profile.doc.d.ts → classes.source-profile.doc.d.ts} +4 -4
  14. package/dist_ts/db/documents/{classes.security-profile.doc.js → classes.source-profile.doc.js} +9 -9
  15. package/dist_ts/db/documents/classes.target-profile.doc.d.ts +17 -0
  16. package/dist_ts/db/documents/classes.target-profile.doc.js +124 -0
  17. package/dist_ts/db/documents/classes.vpn-client.doc.d.ts +1 -1
  18. package/dist_ts/db/documents/classes.vpn-client.doc.js +8 -8
  19. package/dist_ts/db/documents/index.d.ts +2 -1
  20. package/dist_ts/db/documents/index.js +3 -2
  21. package/dist_ts/opsserver/classes.opsserver.d.ts +2 -1
  22. package/dist_ts/opsserver/classes.opsserver.js +5 -3
  23. package/dist_ts/opsserver/handlers/index.d.ts +2 -1
  24. package/dist_ts/opsserver/handlers/index.js +3 -2
  25. package/dist_ts/opsserver/handlers/{security-profile.handler.d.ts → source-profile.handler.d.ts} +1 -1
  26. package/dist_ts/opsserver/handlers/{security-profile.handler.js → source-profile.handler.js} +20 -20
  27. package/dist_ts/opsserver/handlers/target-profile.handler.d.ts +10 -0
  28. package/dist_ts/opsserver/handlers/target-profile.handler.js +115 -0
  29. package/dist_ts/opsserver/handlers/vpn.handler.js +5 -5
  30. package/dist_ts/vpn/classes.vpn-manager.d.ts +6 -10
  31. package/dist_ts/vpn/classes.vpn-manager.js +11 -34
  32. package/dist_ts_interfaces/data/index.d.ts +1 -0
  33. package/dist_ts_interfaces/data/index.js +2 -1
  34. package/dist_ts_interfaces/data/remoteingress.d.ts +4 -15
  35. package/dist_ts_interfaces/data/route-management.d.ts +9 -6
  36. package/dist_ts_interfaces/data/target-profile.d.ts +28 -0
  37. package/dist_ts_interfaces/data/target-profile.js +2 -0
  38. package/dist_ts_interfaces/data/vpn.d.ts +2 -1
  39. package/dist_ts_interfaces/requests/index.d.ts +2 -1
  40. package/dist_ts_interfaces/requests/index.js +3 -2
  41. package/dist_ts_interfaces/requests/{security-profiles.d.ts → source-profiles.d.ts} +21 -21
  42. package/dist_ts_interfaces/requests/source-profiles.js +2 -0
  43. package/dist_ts_interfaces/requests/target-profiles.d.ts +103 -0
  44. package/dist_ts_interfaces/requests/target-profiles.js +2 -0
  45. package/dist_ts_interfaces/requests/vpn.d.ts +2 -2
  46. package/dist_ts_web/00_commitinfo_data.js +2 -2
  47. package/dist_ts_web/appstate.d.ts +36 -3
  48. package/dist_ts_web/appstate.js +127 -10
  49. package/dist_ts_web/elements/index.d.ts +2 -1
  50. package/dist_ts_web/elements/index.js +3 -2
  51. package/dist_ts_web/elements/ops-dashboard.js +10 -4
  52. package/dist_ts_web/elements/ops-view-routes.js +8 -8
  53. package/dist_ts_web/elements/{ops-view-securityprofiles.d.ts → ops-view-sourceprofiles.d.ts} +2 -2
  54. package/dist_ts_web/elements/{ops-view-securityprofiles.js → ops-view-sourceprofiles.js} +12 -12
  55. package/dist_ts_web/elements/ops-view-targetprofiles.d.ts +19 -0
  56. package/dist_ts_web/elements/ops-view-targetprofiles.js +412 -0
  57. package/dist_ts_web/elements/ops-view-vpn.js +13 -13
  58. package/dist_ts_web/router.d.ts +1 -1
  59. package/dist_ts_web/router.js +2 -2
  60. package/package.json +3 -3
  61. package/ts/00_commitinfo_data.ts +1 -1
  62. package/ts/classes.dcrouter.ts +33 -50
  63. package/ts/config/classes.reference-resolver.ts +34 -34
  64. package/ts/config/classes.route-config-manager.ts +9 -12
  65. package/ts/config/classes.target-profile-manager.ts +348 -0
  66. package/ts/config/index.ts +2 -1
  67. package/ts/db/documents/{classes.security-profile.doc.ts → classes.source-profile.doc.ts} +7 -7
  68. package/ts/db/documents/classes.target-profile.doc.ts +52 -0
  69. package/ts/db/documents/classes.vpn-client.doc.ts +1 -1
  70. package/ts/db/documents/index.ts +2 -1
  71. package/ts/opsserver/classes.opsserver.ts +4 -2
  72. package/ts/opsserver/handlers/index.ts +2 -1
  73. package/ts/opsserver/handlers/{security-profile.handler.ts → source-profile.handler.ts} +25 -25
  74. package/ts/opsserver/handlers/target-profile.handler.ts +155 -0
  75. package/ts/opsserver/handlers/vpn.handler.ts +4 -4
  76. package/ts/vpn/classes.vpn-manager.ts +14 -38
  77. package/ts_web/00_commitinfo_data.ts +1 -1
  78. package/ts_web/appstate.ts +180 -17
  79. package/ts_web/elements/index.ts +2 -1
  80. package/ts_web/elements/ops-dashboard.ts +9 -3
  81. package/ts_web/elements/ops-view-routes.ts +7 -7
  82. package/ts_web/elements/{ops-view-securityprofiles.ts → ops-view-sourceprofiles.ts} +13 -13
  83. package/ts_web/elements/ops-view-targetprofiles.ts +379 -0
  84. package/ts_web/elements/ops-view-vpn.ts +12 -12
  85. package/ts_web/router.ts +1 -1
  86. package/dist_ts_interfaces/requests/security-profiles.js +0 -2
@@ -0,0 +1,412 @@
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 { DeesElement, html, customElement, css, state, cssManager, } from '@design.estate/dees-element';
36
+ import * as plugins from '../plugins.js';
37
+ import * as appstate from '../appstate.js';
38
+ import * as interfaces from '../../dist_ts_interfaces/index.js';
39
+ import { viewHostCss } from './shared/css.js';
40
+ import {} from '@design.estate/dees-catalog';
41
+ let OpsViewTargetProfiles = (() => {
42
+ let _classDecorators = [customElement('ops-view-targetprofiles')];
43
+ let _classDescriptor;
44
+ let _classExtraInitializers = [];
45
+ let _classThis;
46
+ let _classSuper = DeesElement;
47
+ let _targetProfilesState_decorators;
48
+ let _targetProfilesState_initializers = [];
49
+ let _targetProfilesState_extraInitializers = [];
50
+ var OpsViewTargetProfiles = class extends _classSuper {
51
+ static { _classThis = this; }
52
+ static {
53
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
54
+ _targetProfilesState_decorators = [state()];
55
+ __esDecorate(this, null, _targetProfilesState_decorators, { kind: "accessor", name: "targetProfilesState", static: false, private: false, access: { has: obj => "targetProfilesState" in obj, get: obj => obj.targetProfilesState, set: (obj, value) => { obj.targetProfilesState = value; } }, metadata: _metadata }, _targetProfilesState_initializers, _targetProfilesState_extraInitializers);
56
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
57
+ OpsViewTargetProfiles = _classThis = _classDescriptor.value;
58
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
59
+ }
60
+ #targetProfilesState_accessor_storage = __runInitializers(this, _targetProfilesState_initializers, appstate.targetProfilesStatePart.getState());
61
+ get targetProfilesState() { return this.#targetProfilesState_accessor_storage; }
62
+ set targetProfilesState(value) { this.#targetProfilesState_accessor_storage = value; }
63
+ constructor() {
64
+ super();
65
+ __runInitializers(this, _targetProfilesState_extraInitializers);
66
+ const sub = appstate.targetProfilesStatePart.select().subscribe((newState) => {
67
+ this.targetProfilesState = newState;
68
+ });
69
+ this.rxSubscriptions.push(sub);
70
+ }
71
+ async connectedCallback() {
72
+ await super.connectedCallback();
73
+ await appstate.targetProfilesStatePart.dispatchAction(appstate.fetchTargetProfilesAction, null);
74
+ }
75
+ static styles = [
76
+ cssManager.defaultStyles,
77
+ viewHostCss,
78
+ css `
79
+ .profilesContainer {
80
+ display: flex;
81
+ flex-direction: column;
82
+ gap: 24px;
83
+ }
84
+
85
+ .tagBadge {
86
+ display: inline-flex;
87
+ padding: 2px 8px;
88
+ border-radius: 4px;
89
+ font-size: 12px;
90
+ font-weight: 500;
91
+ background: ${cssManager.bdTheme('#eff6ff', '#172554')};
92
+ color: ${cssManager.bdTheme('#1e40af', '#60a5fa')};
93
+ margin-right: 4px;
94
+ margin-bottom: 2px;
95
+ }
96
+ `,
97
+ ];
98
+ render() {
99
+ const profiles = this.targetProfilesState.profiles;
100
+ const statsTiles = [
101
+ {
102
+ id: 'totalProfiles',
103
+ title: 'Total Profiles',
104
+ type: 'number',
105
+ value: profiles.length,
106
+ icon: 'lucide:target',
107
+ description: 'Reusable target profiles',
108
+ color: '#8b5cf6',
109
+ },
110
+ ];
111
+ return html `
112
+ <ops-sectionheading>Target Profiles</ops-sectionheading>
113
+ <div class="profilesContainer">
114
+ <dees-statsgrid .tiles=${statsTiles}></dees-statsgrid>
115
+ <dees-table
116
+ .heading1=${'Target Profiles'}
117
+ .heading2=${'Define what resources VPN clients can access'}
118
+ .data=${profiles}
119
+ .displayFunction=${(profile) => ({
120
+ Name: profile.name,
121
+ Description: profile.description || '-',
122
+ Domains: profile.domains?.length
123
+ ? html `${profile.domains.map(d => html `<span class="tagBadge">${d}</span>`)}`
124
+ : '-',
125
+ Targets: profile.targets?.length
126
+ ? html `${profile.targets.map(t => html `<span class="tagBadge">${t.host}:${t.port}</span>`)}`
127
+ : '-',
128
+ 'Route Refs': profile.routeRefs?.length
129
+ ? html `${profile.routeRefs.map(r => html `<span class="tagBadge">${r}</span>`)}`
130
+ : '-',
131
+ Created: new Date(profile.createdAt).toLocaleDateString(),
132
+ })}
133
+ .dataActions=${[
134
+ {
135
+ name: 'Create Profile',
136
+ iconName: 'lucide:plus',
137
+ type: ['header'],
138
+ actionFunc: async () => {
139
+ await this.showCreateProfileDialog();
140
+ },
141
+ },
142
+ {
143
+ name: 'Refresh',
144
+ iconName: 'lucide:rotateCw',
145
+ type: ['header'],
146
+ actionFunc: async () => {
147
+ await appstate.targetProfilesStatePart.dispatchAction(appstate.fetchTargetProfilesAction, null);
148
+ },
149
+ },
150
+ {
151
+ name: 'Detail',
152
+ iconName: 'lucide:info',
153
+ type: ['doubleClick'],
154
+ actionFunc: async (actionData) => {
155
+ const profile = actionData.item;
156
+ await this.showDetailDialog(profile);
157
+ },
158
+ },
159
+ {
160
+ name: 'Edit',
161
+ iconName: 'lucide:pencil',
162
+ type: ['inRow', 'contextmenu'],
163
+ actionFunc: async (actionData) => {
164
+ const profile = actionData.item;
165
+ await this.showEditProfileDialog(profile);
166
+ },
167
+ },
168
+ {
169
+ name: 'Delete',
170
+ iconName: 'lucide:trash2',
171
+ type: ['inRow', 'contextmenu'],
172
+ actionFunc: async (actionData) => {
173
+ const profile = actionData.item;
174
+ await this.deleteProfile(profile);
175
+ },
176
+ },
177
+ ]}
178
+ ></dees-table>
179
+ </div>
180
+ `;
181
+ }
182
+ async showCreateProfileDialog() {
183
+ const { DeesModal } = await import('@design.estate/dees-catalog');
184
+ DeesModal.createAndShow({
185
+ heading: 'Create Target Profile',
186
+ content: html `
187
+ <dees-form>
188
+ <dees-input-text .key=${'name'} .label=${'Name'} .required=${true}></dees-input-text>
189
+ <dees-input-text .key=${'description'} .label=${'Description'}></dees-input-text>
190
+ <dees-input-text .key=${'domains'} .label=${'Domains (comma-separated, e.g. *.example.com)'} ></dees-input-text>
191
+ <dees-input-text .key=${'targets'} .label=${'Targets (comma-separated host:port, e.g. 10.0.0.1:443)'}></dees-input-text>
192
+ <dees-input-text .key=${'routeRefs'} .label=${'Route Refs (comma-separated route names/IDs)'}></dees-input-text>
193
+ </dees-form>
194
+ `,
195
+ menuOptions: [
196
+ { name: 'Cancel', iconName: 'lucide:x', action: async (modalArg) => modalArg.destroy() },
197
+ {
198
+ name: 'Create',
199
+ iconName: 'lucide:plus',
200
+ action: async (modalArg) => {
201
+ const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
202
+ if (!form)
203
+ return;
204
+ const data = await form.collectFormData();
205
+ if (!data.name)
206
+ return;
207
+ const domains = data.domains
208
+ ? String(data.domains).split(',').map((s) => s.trim()).filter(Boolean)
209
+ : undefined;
210
+ const targets = data.targets
211
+ ? String(data.targets).split(',').map((s) => {
212
+ const trimmed = s.trim();
213
+ const lastColon = trimmed.lastIndexOf(':');
214
+ if (lastColon === -1)
215
+ return null;
216
+ return {
217
+ host: trimmed.substring(0, lastColon),
218
+ port: parseInt(trimmed.substring(lastColon + 1), 10),
219
+ };
220
+ }).filter((t) => t !== null && !isNaN(t.port))
221
+ : undefined;
222
+ const routeRefs = data.routeRefs
223
+ ? String(data.routeRefs).split(',').map((s) => s.trim()).filter(Boolean)
224
+ : undefined;
225
+ await appstate.targetProfilesStatePart.dispatchAction(appstate.createTargetProfileAction, {
226
+ name: String(data.name),
227
+ description: data.description ? String(data.description) : undefined,
228
+ domains,
229
+ targets,
230
+ routeRefs,
231
+ });
232
+ modalArg.destroy();
233
+ },
234
+ },
235
+ ],
236
+ });
237
+ }
238
+ async showEditProfileDialog(profile) {
239
+ const currentDomains = profile.domains?.join(', ') ?? '';
240
+ const currentTargets = profile.targets?.map(t => `${t.host}:${t.port}`).join(', ') ?? '';
241
+ const currentRouteRefs = profile.routeRefs?.join(', ') ?? '';
242
+ const { DeesModal } = await import('@design.estate/dees-catalog');
243
+ DeesModal.createAndShow({
244
+ heading: `Edit Profile: ${profile.name}`,
245
+ content: html `
246
+ <dees-form>
247
+ <dees-input-text .key=${'name'} .label=${'Name'} .value=${profile.name}></dees-input-text>
248
+ <dees-input-text .key=${'description'} .label=${'Description'} .value=${profile.description || ''}></dees-input-text>
249
+ <dees-input-text .key=${'domains'} .label=${'Domains (comma-separated, e.g. *.example.com)'} .value=${currentDomains}></dees-input-text>
250
+ <dees-input-text .key=${'targets'} .label=${'Targets (comma-separated host:port, e.g. 10.0.0.1:443)'} .value=${currentTargets}></dees-input-text>
251
+ <dees-input-text .key=${'routeRefs'} .label=${'Route Refs (comma-separated route names/IDs)'} .value=${currentRouteRefs}></dees-input-text>
252
+ </dees-form>
253
+ `,
254
+ menuOptions: [
255
+ { name: 'Cancel', iconName: 'lucide:x', action: async (modalArg) => modalArg.destroy() },
256
+ {
257
+ name: 'Save',
258
+ iconName: 'lucide:check',
259
+ action: async (modalArg) => {
260
+ const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
261
+ if (!form)
262
+ return;
263
+ const data = await form.collectFormData();
264
+ const domains = data.domains
265
+ ? String(data.domains).split(',').map((s) => s.trim()).filter(Boolean)
266
+ : [];
267
+ const targets = data.targets
268
+ ? String(data.targets).split(',').map((s) => {
269
+ const trimmed = s.trim();
270
+ if (!trimmed)
271
+ return null;
272
+ const lastColon = trimmed.lastIndexOf(':');
273
+ if (lastColon === -1)
274
+ return null;
275
+ return {
276
+ host: trimmed.substring(0, lastColon),
277
+ port: parseInt(trimmed.substring(lastColon + 1), 10),
278
+ };
279
+ }).filter((t) => t !== null && !isNaN(t.port))
280
+ : [];
281
+ const routeRefs = data.routeRefs
282
+ ? String(data.routeRefs).split(',').map((s) => s.trim()).filter(Boolean)
283
+ : [];
284
+ await appstate.targetProfilesStatePart.dispatchAction(appstate.updateTargetProfileAction, {
285
+ id: profile.id,
286
+ name: String(data.name),
287
+ description: data.description ? String(data.description) : undefined,
288
+ domains,
289
+ targets,
290
+ routeRefs,
291
+ });
292
+ modalArg.destroy();
293
+ },
294
+ },
295
+ ],
296
+ });
297
+ }
298
+ async showDetailDialog(profile) {
299
+ const { DeesModal } = await import('@design.estate/dees-catalog');
300
+ // Fetch usage (which VPN clients reference this profile)
301
+ let usageHtml = html `<p style="color: #9ca3af;">Loading usage...</p>`;
302
+ try {
303
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'getTargetProfileUsage');
304
+ const response = await request.fire({
305
+ identity: appstate.loginStatePart.getState().identity,
306
+ id: profile.id,
307
+ });
308
+ if (response.clients.length > 0) {
309
+ usageHtml = html `
310
+ <div style="margin-top: 8px;">
311
+ ${response.clients.map(c => html `
312
+ <div style="padding: 4px 0; font-size: 13px;">
313
+ <strong>${c.clientId}</strong>${c.description ? html ` - ${c.description}` : ''}
314
+ </div>
315
+ `)}
316
+ </div>
317
+ `;
318
+ }
319
+ else {
320
+ usageHtml = html `<p style="color: #9ca3af; font-size: 13px;">No VPN clients reference this profile.</p>`;
321
+ }
322
+ }
323
+ catch {
324
+ usageHtml = html `<p style="color: #9ca3af;">Usage data unavailable.</p>`;
325
+ }
326
+ DeesModal.createAndShow({
327
+ heading: `Target Profile: ${profile.name}`,
328
+ content: html `
329
+ <div style="display: flex; flex-direction: column; gap: 12px;">
330
+ <div>
331
+ <div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">Description</div>
332
+ <div style="font-size: 14px; margin-top: 4px;">${profile.description || '-'}</div>
333
+ </div>
334
+ <div>
335
+ <div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">Domains</div>
336
+ <div style="font-size: 14px; margin-top: 4px;">
337
+ ${profile.domains?.length
338
+ ? profile.domains.map(d => html `<span class="tagBadge">${d}</span>`)
339
+ : '-'}
340
+ </div>
341
+ </div>
342
+ <div>
343
+ <div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">Targets</div>
344
+ <div style="font-size: 14px; margin-top: 4px;">
345
+ ${profile.targets?.length
346
+ ? profile.targets.map(t => html `<span class="tagBadge">${t.host}:${t.port}</span>`)
347
+ : '-'}
348
+ </div>
349
+ </div>
350
+ <div>
351
+ <div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">Route Refs</div>
352
+ <div style="font-size: 14px; margin-top: 4px;">
353
+ ${profile.routeRefs?.length
354
+ ? profile.routeRefs.map(r => html `<span class="tagBadge">${r}</span>`)
355
+ : '-'}
356
+ </div>
357
+ </div>
358
+ <div>
359
+ <div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">Created</div>
360
+ <div style="font-size: 14px; margin-top: 4px;">${new Date(profile.createdAt).toLocaleString()} by ${profile.createdBy}</div>
361
+ </div>
362
+ <div>
363
+ <div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">Updated</div>
364
+ <div style="font-size: 14px; margin-top: 4px;">${new Date(profile.updatedAt).toLocaleString()}</div>
365
+ </div>
366
+ <div>
367
+ <div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">VPN Clients Using This Profile</div>
368
+ ${usageHtml}
369
+ </div>
370
+ </div>
371
+ `,
372
+ menuOptions: [
373
+ { name: 'Close', iconName: 'lucide:x', action: async (m) => await m.destroy() },
374
+ ],
375
+ });
376
+ }
377
+ async deleteProfile(profile) {
378
+ await appstate.targetProfilesStatePart.dispatchAction(appstate.deleteTargetProfileAction, {
379
+ id: profile.id,
380
+ force: false,
381
+ });
382
+ const currentState = appstate.targetProfilesStatePart.getState();
383
+ if (currentState.error?.includes('in use')) {
384
+ const { DeesModal } = await import('@design.estate/dees-catalog');
385
+ DeesModal.createAndShow({
386
+ heading: 'Profile In Use',
387
+ content: html `<p>${currentState.error} Force delete?</p>`,
388
+ menuOptions: [
389
+ {
390
+ name: 'Force Delete',
391
+ iconName: 'lucide:trash2',
392
+ action: async (modalArg) => {
393
+ await appstate.targetProfilesStatePart.dispatchAction(appstate.deleteTargetProfileAction, {
394
+ id: profile.id,
395
+ force: true,
396
+ });
397
+ modalArg.destroy();
398
+ },
399
+ },
400
+ { name: 'Cancel', iconName: 'lucide:x', action: async (modalArg) => modalArg.destroy() },
401
+ ],
402
+ });
403
+ }
404
+ }
405
+ static {
406
+ __runInitializers(_classThis, _classExtraInitializers);
407
+ }
408
+ };
409
+ return OpsViewTargetProfiles = _classThis;
410
+ })();
411
+ export { OpsViewTargetProfiles };
412
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BzLXZpZXctdGFyZ2V0cHJvZmlsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvZWxlbWVudHMvb3BzLXZpZXctdGFyZ2V0cHJvZmlsZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sRUFDTCxXQUFXLEVBQ1gsSUFBSSxFQUNKLGFBQWEsRUFFYixHQUFHLEVBQ0gsS0FBSyxFQUNMLFVBQVUsR0FDWCxNQUFNLDZCQUE2QixDQUFDO0FBQ3JDLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxLQUFLLFVBQVUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNoRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFtQixNQUFNLDZCQUE2QixDQUFDO0lBU2pELHFCQUFxQjs0QkFEakMsYUFBYSxDQUFDLHlCQUF5QixDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7cUNBQW5CLFNBQVEsV0FBVzs7OzsrQ0FDbkQsS0FBSyxFQUFFO1lBQ1IsOE1BQVMsbUJBQW1CLDZCQUFuQixtQkFBbUIsaUhBQStFO1lBRjdHLDZLQW9XQzs7OztRQWxXQyxtR0FBOEQsUUFBUSxDQUFDLHVCQUF1QixDQUFDLFFBQVEsRUFBRyxFQUFDO1FBQTNHLElBQVMsbUJBQW1CLHlEQUErRTtRQUEzRyxJQUFTLG1CQUFtQiwrREFBK0U7UUFFM0c7WUFDRSxLQUFLLEVBQUUsQ0FBQzs7WUFDUixNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsdUJBQXVCLENBQUMsTUFBTSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7Z0JBQzNFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLENBQUM7WUFDdEMsQ0FBQyxDQUFDLENBQUM7WUFDSCxJ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