@serve.zone/catalog 1.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 (122) hide show
  1. package/dist_ts_web/00_commitinfo_data.d.ts +8 -0
  2. package/dist_ts_web/00_commitinfo_data.js +9 -0
  3. package/dist_ts_web/elements/index.d.ts +33 -0
  4. package/dist_ts_web/elements/index.js +45 -0
  5. package/dist_ts_web/elements/sz-certificates-card.d.ts +14 -0
  6. package/dist_ts_web/elements/sz-certificates-card.js +210 -0
  7. package/dist_ts_web/elements/sz-dashboard-view.d.ts +33 -0
  8. package/dist_ts_web/elements/sz-dashboard-view.js +242 -0
  9. package/dist_ts_web/elements/sz-demo-view-dashboard.d.ts +18 -0
  10. package/dist_ts_web/elements/sz-demo-view-dashboard.js +184 -0
  11. package/dist_ts_web/elements/sz-demo-view-network.d.ts +32 -0
  12. package/dist_ts_web/elements/sz-demo-view-network.js +384 -0
  13. package/dist_ts_web/elements/sz-demo-view-registries.d.ts +22 -0
  14. package/dist_ts_web/elements/sz-demo-view-registries.js +240 -0
  15. package/dist_ts_web/elements/sz-demo-view-services.d.ts +32 -0
  16. package/dist_ts_web/elements/sz-demo-view-services.js +468 -0
  17. package/dist_ts_web/elements/sz-demo-view-settings.d.ts +19 -0
  18. package/dist_ts_web/elements/sz-demo-view-settings.js +151 -0
  19. package/dist_ts_web/elements/sz-demo-view-tokens.d.ts +20 -0
  20. package/dist_ts_web/elements/sz-demo-view-tokens.js +141 -0
  21. package/dist_ts_web/elements/sz-dns-ssl-card.d.ts +13 -0
  22. package/dist_ts_web/elements/sz-dns-ssl-card.js +180 -0
  23. package/dist_ts_web/elements/sz-domain-detail-view.d.ts +48 -0
  24. package/dist_ts_web/elements/sz-domain-detail-view.js +789 -0
  25. package/dist_ts_web/elements/sz-login-view.d.ts +18 -0
  26. package/dist_ts_web/elements/sz-login-view.js +384 -0
  27. package/dist_ts_web/elements/sz-network-dns-view.d.ts +20 -0
  28. package/dist_ts_web/elements/sz-network-dns-view.js +244 -0
  29. package/dist_ts_web/elements/sz-network-domains-view.d.ts +28 -0
  30. package/dist_ts_web/elements/sz-network-domains-view.js +312 -0
  31. package/dist_ts_web/elements/sz-network-proxy-view.d.ts +39 -0
  32. package/dist_ts_web/elements/sz-network-proxy-view.js +510 -0
  33. package/dist_ts_web/elements/sz-platform-service-detail-view.d.ts +49 -0
  34. package/dist_ts_web/elements/sz-platform-service-detail-view.js +733 -0
  35. package/dist_ts_web/elements/sz-platform-services-card.d.ts +19 -0
  36. package/dist_ts_web/elements/sz-platform-services-card.js +196 -0
  37. package/dist_ts_web/elements/sz-quick-actions-card.d.ts +19 -0
  38. package/dist_ts_web/elements/sz-quick-actions-card.js +194 -0
  39. package/dist_ts_web/elements/sz-registry-external-view.d.ts +22 -0
  40. package/dist_ts_web/elements/sz-registry-external-view.js +313 -0
  41. package/dist_ts_web/elements/sz-registry-onebox-view.d.ts +14 -0
  42. package/dist_ts_web/elements/sz-registry-onebox-view.js +307 -0
  43. package/dist_ts_web/elements/sz-resource-usage-card.d.ts +25 -0
  44. package/dist_ts_web/elements/sz-resource-usage-card.js +323 -0
  45. package/dist_ts_web/elements/sz-reverse-proxy-card.d.ts +16 -0
  46. package/dist_ts_web/elements/sz-reverse-proxy-card.js +216 -0
  47. package/dist_ts_web/elements/sz-service-create-view.d.ts +67 -0
  48. package/dist_ts_web/elements/sz-service-create-view.js +828 -0
  49. package/dist_ts_web/elements/sz-service-detail-view.d.ts +57 -0
  50. package/dist_ts_web/elements/sz-service-detail-view.js +728 -0
  51. package/dist_ts_web/elements/sz-services-backups-view.d.ts +37 -0
  52. package/dist_ts_web/elements/sz-services-backups-view.js +413 -0
  53. package/dist_ts_web/elements/sz-services-list-view.d.ts +20 -0
  54. package/dist_ts_web/elements/sz-services-list-view.js +272 -0
  55. package/dist_ts_web/elements/sz-settings-view.d.ts +30 -0
  56. package/dist_ts_web/elements/sz-settings-view.js +448 -0
  57. package/dist_ts_web/elements/sz-stat-card.d.ts +17 -0
  58. package/dist_ts_web/elements/sz-stat-card.js +249 -0
  59. package/dist_ts_web/elements/sz-status-grid-cluster.d.ts +19 -0
  60. package/dist_ts_web/elements/sz-status-grid-cluster.js +142 -0
  61. package/dist_ts_web/elements/sz-status-grid-infra.d.ts +17 -0
  62. package/dist_ts_web/elements/sz-status-grid-infra.js +140 -0
  63. package/dist_ts_web/elements/sz-status-grid-network.d.ts +30 -0
  64. package/dist_ts_web/elements/sz-status-grid-network.js +190 -0
  65. package/dist_ts_web/elements/sz-status-grid-services.d.ts +17 -0
  66. package/dist_ts_web/elements/sz-status-grid-services.js +145 -0
  67. package/dist_ts_web/elements/sz-tokens-view.d.ts +26 -0
  68. package/dist_ts_web/elements/sz-tokens-view.js +344 -0
  69. package/dist_ts_web/elements/sz-traffic-card.d.ts +24 -0
  70. package/dist_ts_web/elements/sz-traffic-card.js +255 -0
  71. package/dist_ts_web/index.d.ts +2 -0
  72. package/dist_ts_web/index.js +3 -0
  73. package/dist_ts_web/pages/index.d.ts +3 -0
  74. package/dist_ts_web/pages/index.js +4 -0
  75. package/dist_ts_web/pages/mainpage.d.ts +1 -0
  76. package/dist_ts_web/pages/mainpage.js +46 -0
  77. package/dist_ts_web/pages/sz-demo-app-shell.d.ts +13 -0
  78. package/dist_ts_web/pages/sz-demo-app-shell.js +212 -0
  79. package/dist_ts_web/pages/sz-demo-app.d.ts +2 -0
  80. package/dist_ts_web/pages/sz-demo-app.js +20 -0
  81. package/npmextra.json +24 -0
  82. package/package.json +45 -0
  83. package/ts_web/00_commitinfo_data.ts +8 -0
  84. package/ts_web/elements/index.ts +54 -0
  85. package/ts_web/elements/sz-certificates-card.ts +155 -0
  86. package/ts_web/elements/sz-dashboard-view.ts +217 -0
  87. package/ts_web/elements/sz-demo-view-dashboard.ts +150 -0
  88. package/ts_web/elements/sz-demo-view-network.ts +354 -0
  89. package/ts_web/elements/sz-demo-view-registries.ts +206 -0
  90. package/ts_web/elements/sz-demo-view-services.ts +434 -0
  91. package/ts_web/elements/sz-demo-view-settings.ts +118 -0
  92. package/ts_web/elements/sz-demo-view-tokens.ts +109 -0
  93. package/ts_web/elements/sz-dns-ssl-card.ts +130 -0
  94. package/ts_web/elements/sz-domain-detail-view.ts +766 -0
  95. package/ts_web/elements/sz-login-view.ts +329 -0
  96. package/ts_web/elements/sz-network-dns-view.ts +208 -0
  97. package/ts_web/elements/sz-network-domains-view.ts +273 -0
  98. package/ts_web/elements/sz-network-proxy-view.ts +456 -0
  99. package/ts_web/elements/sz-platform-service-detail-view.ts +714 -0
  100. package/ts_web/elements/sz-platform-services-card.ts +163 -0
  101. package/ts_web/elements/sz-quick-actions-card.ts +161 -0
  102. package/ts_web/elements/sz-registry-external-view.ts +279 -0
  103. package/ts_web/elements/sz-registry-onebox-view.ts +258 -0
  104. package/ts_web/elements/sz-resource-usage-card.ts +284 -0
  105. package/ts_web/elements/sz-reverse-proxy-card.ts +151 -0
  106. package/ts_web/elements/sz-service-create-view.ts +773 -0
  107. package/ts_web/elements/sz-service-detail-view.ts +710 -0
  108. package/ts_web/elements/sz-services-backups-view.ts +390 -0
  109. package/ts_web/elements/sz-services-list-view.ts +237 -0
  110. package/ts_web/elements/sz-settings-view.ts +417 -0
  111. package/ts_web/elements/sz-stat-card.ts +187 -0
  112. package/ts_web/elements/sz-status-grid-cluster.ts +105 -0
  113. package/ts_web/elements/sz-status-grid-infra.ts +88 -0
  114. package/ts_web/elements/sz-status-grid-network.ts +152 -0
  115. package/ts_web/elements/sz-status-grid-services.ts +99 -0
  116. package/ts_web/elements/sz-tokens-view.ts +308 -0
  117. package/ts_web/elements/sz-traffic-card.ts +222 -0
  118. package/ts_web/index.ts +2 -0
  119. package/ts_web/pages/index.ts +3 -0
  120. package/ts_web/pages/mainpage.ts +46 -0
  121. package/ts_web/pages/sz-demo-app-shell.ts +179 -0
  122. package/ts_web/pages/sz-demo-app.ts +20 -0
@@ -0,0 +1,390 @@
1
+ import {
2
+ DeesElement,
3
+ customElement,
4
+ html,
5
+ css,
6
+ cssManager,
7
+ property,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ 'sz-services-backups-view': SzServicesBackupsView;
14
+ }
15
+ }
16
+
17
+ export interface IBackupSchedule {
18
+ id: string;
19
+ scope: string;
20
+ retention: string;
21
+ schedule: string;
22
+ lastRun?: string;
23
+ nextRun?: string;
24
+ status: 'active' | 'failed' | 'disabled';
25
+ error?: string;
26
+ }
27
+
28
+ export interface IBackup {
29
+ id: string;
30
+ service: string;
31
+ createdAt: string;
32
+ size: string;
33
+ includes: string[];
34
+ }
35
+
36
+ @customElement('sz-services-backups-view')
37
+ export class SzServicesBackupsView extends DeesElement {
38
+ public static demo = () => html`
39
+ <div style="padding: 24px; max-width: 1200px;">
40
+ <sz-services-backups-view
41
+ .schedules=${[
42
+ { id: '1', scope: 'All Services', retention: 'D:7, W:4, M:12', schedule: '0 2 * * *', lastRun: '1/2/2026, 2:00:03 AM', nextRun: '1/3/2026, 2:00:00 AM', status: 'active' },
43
+ ]}
44
+ .backups=${[
45
+ { id: '1', service: 'test-nginx', createdAt: '1/2/2026, 2:00:03 AM', size: '22.0 MB', includes: ['Image'] },
46
+ { id: '2', service: 'hello-world', createdAt: '1/2/2026, 2:00:02 AM', size: '21.5 MB', includes: ['Image'] },
47
+ { id: '3', service: 'test-ch-final', createdAt: '1/2/2026, 2:00:00 AM', size: '22.0 MB', includes: ['Image', 'clickhouse'] },
48
+ ]}
49
+ ></sz-services-backups-view>
50
+ </div>
51
+ `;
52
+
53
+ @property({ type: Array })
54
+ public accessor schedules: IBackupSchedule[] = [];
55
+
56
+ @property({ type: Array })
57
+ public accessor backups: IBackup[] = [];
58
+
59
+ public static styles = [
60
+ cssManager.defaultStyles,
61
+ css`
62
+ :host {
63
+ display: block;
64
+ }
65
+
66
+ .section {
67
+ background: ${cssManager.bdTheme('#ffffff', '#09090b')};
68
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
69
+ border-radius: 8px;
70
+ margin-bottom: 24px;
71
+ overflow: hidden;
72
+ }
73
+
74
+ .section-header {
75
+ display: flex;
76
+ justify-content: space-between;
77
+ align-items: flex-start;
78
+ padding: 16px;
79
+ border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
80
+ }
81
+
82
+ .section-info {
83
+ display: flex;
84
+ flex-direction: column;
85
+ gap: 4px;
86
+ }
87
+
88
+ .section-title {
89
+ font-size: 16px;
90
+ font-weight: 600;
91
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
92
+ }
93
+
94
+ .section-subtitle {
95
+ font-size: 13px;
96
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
97
+ }
98
+
99
+ .header-actions {
100
+ display: flex;
101
+ gap: 8px;
102
+ }
103
+
104
+ .action-button {
105
+ display: inline-flex;
106
+ align-items: center;
107
+ gap: 6px;
108
+ padding: 8px 14px;
109
+ background: ${cssManager.bdTheme('#ffffff', '#09090b')};
110
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
111
+ border-radius: 6px;
112
+ font-size: 13px;
113
+ font-weight: 500;
114
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
115
+ cursor: pointer;
116
+ transition: all 200ms ease;
117
+ }
118
+
119
+ .action-button:hover {
120
+ background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
121
+ }
122
+
123
+ .action-button.primary {
124
+ background: ${cssManager.bdTheme('#18181b', '#fafafa')};
125
+ color: ${cssManager.bdTheme('#fafafa', '#18181b')};
126
+ border: none;
127
+ }
128
+
129
+ .action-button.primary:hover {
130
+ opacity: 0.9;
131
+ }
132
+
133
+ .table-header {
134
+ display: grid;
135
+ gap: 16px;
136
+ padding: 12px 16px;
137
+ background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
138
+ border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
139
+ font-size: 12px;
140
+ font-weight: 600;
141
+ text-transform: uppercase;
142
+ letter-spacing: 0.05em;
143
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
144
+ }
145
+
146
+ .schedules-header {
147
+ grid-template-columns: 1fr 1fr 1fr 1.5fr 1.5fr 80px 120px;
148
+ }
149
+
150
+ .backups-header {
151
+ grid-template-columns: 1.5fr 1.5fr 100px 1fr 120px;
152
+ }
153
+
154
+ .table-row {
155
+ display: grid;
156
+ gap: 16px;
157
+ padding: 12px 16px;
158
+ border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#27272a')};
159
+ font-size: 14px;
160
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
161
+ align-items: center;
162
+ }
163
+
164
+ .schedules-row {
165
+ grid-template-columns: 1fr 1fr 1fr 1.5fr 1.5fr 80px 120px;
166
+ }
167
+
168
+ .backups-row {
169
+ grid-template-columns: 1.5fr 1.5fr 100px 1fr 120px;
170
+ }
171
+
172
+ .table-row:last-child {
173
+ border-bottom: none;
174
+ }
175
+
176
+ .table-row:hover {
177
+ background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
178
+ }
179
+
180
+ .status-badge {
181
+ display: inline-flex;
182
+ align-items: center;
183
+ padding: 2px 8px;
184
+ border-radius: 9999px;
185
+ font-size: 12px;
186
+ font-weight: 500;
187
+ }
188
+
189
+ .status-badge.active {
190
+ background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')};
191
+ color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
192
+ }
193
+
194
+ .status-badge.failed {
195
+ background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')};
196
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
197
+ }
198
+
199
+ .status-badge.disabled {
200
+ background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
201
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
202
+ }
203
+
204
+ .meta-text {
205
+ font-size: 13px;
206
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
207
+ }
208
+
209
+ .includes-list {
210
+ display: flex;
211
+ flex-wrap: wrap;
212
+ gap: 4px;
213
+ }
214
+
215
+ .include-badge {
216
+ padding: 2px 8px;
217
+ background: ${cssManager.bdTheme('#dbeafe', 'rgba(59, 130, 246, 0.2)')};
218
+ color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
219
+ border-radius: 4px;
220
+ font-size: 11px;
221
+ font-weight: 500;
222
+ }
223
+
224
+ .row-actions {
225
+ display: flex;
226
+ gap: 4px;
227
+ }
228
+
229
+ .icon-button {
230
+ padding: 6px;
231
+ background: transparent;
232
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
233
+ border-radius: 4px;
234
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
235
+ cursor: pointer;
236
+ transition: all 200ms ease;
237
+ }
238
+
239
+ .icon-button:hover {
240
+ background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
241
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
242
+ }
243
+
244
+ .icon-button.danger:hover {
245
+ background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')};
246
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
247
+ border-color: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.3)')};
248
+ }
249
+ `,
250
+ ];
251
+
252
+ public render(): TemplateResult {
253
+ return html`
254
+ <div class="section">
255
+ <div class="section-header">
256
+ <div class="section-info">
257
+ <div class="section-title">Backup Schedules</div>
258
+ <div class="section-subtitle">Configure automated backup schedules for your services</div>
259
+ </div>
260
+ <div class="header-actions">
261
+ <button class="action-button" @click=${() => this.handleImport()}>
262
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
263
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
264
+ <polyline points="17 8 12 3 7 8"/>
265
+ <line x1="12" y1="3" x2="12" y2="15"/>
266
+ </svg>
267
+ Import Backup
268
+ </button>
269
+ <button class="action-button primary" @click=${() => this.handleCreateSchedule()}>
270
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
271
+ <line x1="12" y1="5" x2="12" y2="19"></line>
272
+ <line x1="5" y1="12" x2="19" y2="12"></line>
273
+ </svg>
274
+ Create Schedule
275
+ </button>
276
+ </div>
277
+ </div>
278
+ <div class="table-header schedules-header">
279
+ <span>Scope</span>
280
+ <span>Retention</span>
281
+ <span>Schedule</span>
282
+ <span>Last Run</span>
283
+ <span>Next Run</span>
284
+ <span>Status</span>
285
+ <span>Actions</span>
286
+ </div>
287
+ ${this.schedules.map(schedule => html`
288
+ <div class="table-row schedules-row">
289
+ <span>${schedule.scope}</span>
290
+ <span class="meta-text" title="Keep: ${schedule.retention}">${schedule.retention}</span>
291
+ <span class="meta-text">${schedule.schedule}</span>
292
+ <span class="meta-text">${schedule.lastRun || '-'}</span>
293
+ <span class="meta-text">${schedule.nextRun || '-'}</span>
294
+ <span>
295
+ <span class="status-badge ${schedule.status}" title="${schedule.error || ''}">
296
+ ${schedule.status === 'active' ? 'Active' : schedule.status === 'failed' ? 'Failed' : 'Disabled'}
297
+ </span>
298
+ </span>
299
+ <span class="row-actions">
300
+ <button class="icon-button" title="Run backup now" @click=${() => this.handleRunNow(schedule)}>
301
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><polygon points="5,3 19,12 5,21"/></svg>
302
+ </button>
303
+ <button class="icon-button" title="${schedule.status === 'disabled' ? 'Enable' : 'Disable'}" @click=${() => this.handleToggle(schedule)}>
304
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
305
+ ${schedule.status === 'disabled'
306
+ ? html`<polyline points="20 6 9 17 4 12"></polyline>`
307
+ : html`<rect x="6" y="6" width="12" height="12" rx="1"/>`
308
+ }
309
+ </svg>
310
+ </button>
311
+ <button class="icon-button danger" title="Delete" @click=${() => this.handleDeleteSchedule(schedule)}>
312
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
313
+ <polyline points="3,6 5,6 21,6"/><path d="M19,6v14a2,2,0,0,1-2,2H7a2,2,0,0,1-2-2V6m3,0V4a2,2,0,0,1,2-2h4a2,2,0,0,1,2,2v2"/>
314
+ </svg>
315
+ </button>
316
+ </span>
317
+ </div>
318
+ `)}
319
+ </div>
320
+
321
+ <div class="section">
322
+ <div class="section-header">
323
+ <div class="section-info">
324
+ <div class="section-title">All Backups</div>
325
+ <div class="section-subtitle">Browse and manage all backups across services</div>
326
+ </div>
327
+ </div>
328
+ <div class="table-header backups-header">
329
+ <span>Service</span>
330
+ <span>Created</span>
331
+ <span>Size</span>
332
+ <span>Includes</span>
333
+ <span>Actions</span>
334
+ </div>
335
+ ${this.backups.map(backup => html`
336
+ <div class="table-row backups-row">
337
+ <span>${backup.service}</span>
338
+ <span class="meta-text">${backup.createdAt}</span>
339
+ <span class="meta-text">${backup.size}</span>
340
+ <span class="includes-list">
341
+ ${backup.includes.map(inc => html`<span class="include-badge">${inc}</span>`)}
342
+ </span>
343
+ <span class="row-actions">
344
+ <button class="icon-button" title="Download backup" @click=${() => this.handleDownload(backup)}>
345
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
346
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
347
+ <polyline points="7 10 12 15 17 10"/>
348
+ <line x1="12" y1="15" x2="12" y2="3"/>
349
+ </svg>
350
+ </button>
351
+ <button class="icon-button danger" title="Delete" @click=${() => this.handleDeleteBackup(backup)}>
352
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
353
+ <polyline points="3,6 5,6 21,6"/><path d="M19,6v14a2,2,0,0,1-2,2H7a2,2,0,0,1-2-2V6m3,0V4a2,2,0,0,1,2-2h4a2,2,0,0,1,2,2v2"/>
354
+ </svg>
355
+ </button>
356
+ </span>
357
+ </div>
358
+ `)}
359
+ </div>
360
+ `;
361
+ }
362
+
363
+ private handleImport() {
364
+ this.dispatchEvent(new CustomEvent('import', { bubbles: true, composed: true }));
365
+ }
366
+
367
+ private handleCreateSchedule() {
368
+ this.dispatchEvent(new CustomEvent('create-schedule', { bubbles: true, composed: true }));
369
+ }
370
+
371
+ private handleRunNow(schedule: IBackupSchedule) {
372
+ this.dispatchEvent(new CustomEvent('run-now', { detail: schedule, bubbles: true, composed: true }));
373
+ }
374
+
375
+ private handleToggle(schedule: IBackupSchedule) {
376
+ this.dispatchEvent(new CustomEvent('toggle-schedule', { detail: schedule, bubbles: true, composed: true }));
377
+ }
378
+
379
+ private handleDeleteSchedule(schedule: IBackupSchedule) {
380
+ this.dispatchEvent(new CustomEvent('delete-schedule', { detail: schedule, bubbles: true, composed: true }));
381
+ }
382
+
383
+ private handleDownload(backup: IBackup) {
384
+ this.dispatchEvent(new CustomEvent('download', { detail: backup, bubbles: true, composed: true }));
385
+ }
386
+
387
+ private handleDeleteBackup(backup: IBackup) {
388
+ this.dispatchEvent(new CustomEvent('delete-backup', { detail: backup, bubbles: true, composed: true }));
389
+ }
390
+ }
@@ -0,0 +1,237 @@
1
+ import {
2
+ DeesElement,
3
+ customElement,
4
+ html,
5
+ css,
6
+ cssManager,
7
+ property,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ 'sz-services-list-view': SzServicesListView;
14
+ }
15
+ }
16
+
17
+ export interface IService {
18
+ name: string;
19
+ image: string;
20
+ domain: string | null;
21
+ status: 'running' | 'stopped' | 'starting' | 'error';
22
+ }
23
+
24
+ @customElement('sz-services-list-view')
25
+ export class SzServicesListView extends DeesElement {
26
+ public static demo = () => html`
27
+ <div style="padding: 24px; max-width: 1200px;">
28
+ <sz-services-list-view
29
+ .services=${[
30
+ { name: 'test-nginx', image: 'nginx:alpine', domain: 'app.bleu.de', status: 'running' },
31
+ { name: 'hello-world', image: 'localhost:3000/hello-world:latest', domain: 'hello.task.vc', status: 'running' },
32
+ { name: 'test-v2', image: 'localhost:3000/test-registry:v1', domain: null, status: 'running' },
33
+ { name: 'api-service', image: 'node:18-alpine', domain: 'api.example.com', status: 'stopped' },
34
+ ]}
35
+ ></sz-services-list-view>
36
+ </div>
37
+ `;
38
+
39
+ @property({ type: Array })
40
+ public accessor services: IService[] = [];
41
+
42
+ public static styles = [
43
+ cssManager.defaultStyles,
44
+ css`
45
+ :host {
46
+ display: block;
47
+ }
48
+
49
+ .table-container {
50
+ background: ${cssManager.bdTheme('#ffffff', '#09090b')};
51
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
52
+ border-radius: 8px;
53
+ overflow: hidden;
54
+ }
55
+
56
+ .table-header {
57
+ display: grid;
58
+ grid-template-columns: 1.5fr 2fr 1.5fr 100px 200px;
59
+ gap: 16px;
60
+ padding: 12px 16px;
61
+ background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
62
+ border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
63
+ font-size: 12px;
64
+ font-weight: 600;
65
+ text-transform: uppercase;
66
+ letter-spacing: 0.05em;
67
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
68
+ }
69
+
70
+ .table-row {
71
+ display: grid;
72
+ grid-template-columns: 1.5fr 2fr 1.5fr 100px 200px;
73
+ gap: 16px;
74
+ padding: 12px 16px;
75
+ border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#27272a')};
76
+ font-size: 14px;
77
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
78
+ align-items: center;
79
+ transition: background 200ms ease;
80
+ }
81
+
82
+ .table-row:last-child {
83
+ border-bottom: none;
84
+ }
85
+
86
+ .table-row:hover {
87
+ background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
88
+ }
89
+
90
+ .service-name {
91
+ font-weight: 500;
92
+ color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
93
+ cursor: pointer;
94
+ }
95
+
96
+ .service-name:hover {
97
+ text-decoration: underline;
98
+ }
99
+
100
+ .image {
101
+ font-family: monospace;
102
+ font-size: 13px;
103
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
104
+ overflow: hidden;
105
+ text-overflow: ellipsis;
106
+ white-space: nowrap;
107
+ }
108
+
109
+ .domain-link {
110
+ color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
111
+ text-decoration: none;
112
+ }
113
+
114
+ .domain-link:hover {
115
+ text-decoration: underline;
116
+ }
117
+
118
+ .status-badge {
119
+ display: inline-flex;
120
+ align-items: center;
121
+ padding: 2px 8px;
122
+ border-radius: 9999px;
123
+ font-size: 12px;
124
+ font-weight: 500;
125
+ }
126
+
127
+ .status-badge.running {
128
+ background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')};
129
+ color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
130
+ }
131
+
132
+ .status-badge.stopped {
133
+ background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')};
134
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
135
+ }
136
+
137
+ .status-badge.starting {
138
+ background: ${cssManager.bdTheme('#fef9c3', 'rgba(250, 204, 21, 0.2)')};
139
+ color: ${cssManager.bdTheme('#ca8a04', '#facc15')};
140
+ }
141
+
142
+ .status-badge.error {
143
+ background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')};
144
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
145
+ }
146
+
147
+ .actions {
148
+ display: flex;
149
+ gap: 8px;
150
+ }
151
+
152
+ .action-button {
153
+ padding: 4px 10px;
154
+ background: transparent;
155
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
156
+ border-radius: 4px;
157
+ font-size: 12px;
158
+ cursor: pointer;
159
+ transition: all 200ms ease;
160
+ }
161
+
162
+ .action-button:hover {
163
+ background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
164
+ }
165
+
166
+ .action-button.stop {
167
+ color: ${cssManager.bdTheme('#ca8a04', '#facc15')};
168
+ border-color: ${cssManager.bdTheme('#fef9c3', 'rgba(250, 204, 21, 0.3)')};
169
+ }
170
+
171
+ .action-button.start {
172
+ color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
173
+ border-color: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.3)')};
174
+ }
175
+
176
+ .action-button.restart {
177
+ color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
178
+ border-color: ${cssManager.bdTheme('#dbeafe', 'rgba(59, 130, 246, 0.3)')};
179
+ }
180
+
181
+ .action-button.delete {
182
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
183
+ border-color: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.3)')};
184
+ }
185
+
186
+ .empty-state {
187
+ padding: 48px 24px;
188
+ text-align: center;
189
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
190
+ }
191
+ `,
192
+ ];
193
+
194
+ public render(): TemplateResult {
195
+ return html`
196
+ <div class="table-container">
197
+ <div class="table-header">
198
+ <span>Name</span>
199
+ <span>Image</span>
200
+ <span>Domain</span>
201
+ <span>Status</span>
202
+ <span>Actions</span>
203
+ </div>
204
+ ${this.services.length > 0 ? this.services.map(service => html`
205
+ <div class="table-row">
206
+ <span class="service-name" @click=${() => this.handleServiceClick(service)}>${service.name}</span>
207
+ <span class="image" title="${service.image}">${service.image}</span>
208
+ <span>
209
+ ${service.domain
210
+ ? html`<a class="domain-link" href="https://${service.domain}" target="_blank">${service.domain}</a>`
211
+ : '-'}
212
+ </span>
213
+ <span><span class="status-badge ${service.status}">${service.status}</span></span>
214
+ <span class="actions">
215
+ ${service.status === 'running'
216
+ ? html`<button class="action-button stop" @click=${() => this.handleAction(service, 'stop')}>Stop</button>`
217
+ : html`<button class="action-button start" @click=${() => this.handleAction(service, 'start')}>Start</button>`
218
+ }
219
+ <button class="action-button restart" @click=${() => this.handleAction(service, 'restart')}>Restart</button>
220
+ <button class="action-button delete" @click=${() => this.handleAction(service, 'delete')}>Delete</button>
221
+ </span>
222
+ </div>
223
+ `) : html`
224
+ <div class="empty-state">No services deployed</div>
225
+ `}
226
+ </div>
227
+ `;
228
+ }
229
+
230
+ private handleServiceClick(service: IService) {
231
+ this.dispatchEvent(new CustomEvent('service-click', { detail: service, bubbles: true, composed: true }));
232
+ }
233
+
234
+ private handleAction(service: IService, action: 'start' | 'stop' | 'restart' | 'delete') {
235
+ this.dispatchEvent(new CustomEvent('service-action', { detail: { service, action }, bubbles: true, composed: true }));
236
+ }
237
+ }