@serve.zone/catalog 2.3.0 → 2.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_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/index.d.ts +3 -0
- package/dist_ts_web/elements/index.js +5 -1
- package/dist_ts_web/elements/sz-config-overview.d.ts +14 -0
- package/dist_ts_web/elements/sz-config-overview.js +141 -0
- package/dist_ts_web/elements/sz-config-section.d.ts +31 -0
- package/dist_ts_web/elements/sz-config-section.js +591 -0
- package/dist_ts_web/elements/sz-demo-view-config.d.ts +11 -0
- package/dist_ts_web/elements/sz-demo-view-config.js +193 -0
- package/dist_watch/bundle.js +889 -158
- package/dist_watch/bundle.js.map +4 -4
- package/package.json +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/index.ts +5 -0
- package/ts_web/elements/sz-config-overview.ts +92 -0
- package/ts_web/elements/sz-config-section.ts +531 -0
- package/ts_web/elements/sz-demo-view-config.ts +164 -0
package/package.json
CHANGED
package/ts_web/elements/index.ts
CHANGED
|
@@ -53,6 +53,10 @@ export * from './sz-mta-detail-view.js';
|
|
|
53
53
|
export * from './sz-route-card.js';
|
|
54
54
|
export * from './sz-route-list-view.js';
|
|
55
55
|
|
|
56
|
+
// Config Views
|
|
57
|
+
export * from './sz-config-section.js';
|
|
58
|
+
export * from './sz-config-overview.js';
|
|
59
|
+
|
|
56
60
|
// Demo Views
|
|
57
61
|
export * from './sz-demo-view-dashboard.js';
|
|
58
62
|
export * from './sz-demo-view-services.js';
|
|
@@ -62,3 +66,4 @@ export * from './sz-demo-view-tokens.js';
|
|
|
62
66
|
export * from './sz-demo-view-settings.js';
|
|
63
67
|
export * from './sz-demo-view-mta.js';
|
|
64
68
|
export * from './sz-demo-view-routes.js';
|
|
69
|
+
export * from './sz-demo-view-config.js';
|
|
@@ -0,0 +1,92 @@
|
|
|
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-config-overview': SzConfigOverview;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@customElement('sz-config-overview')
|
|
18
|
+
export class SzConfigOverview extends DeesElement {
|
|
19
|
+
public static demo = () => html`<sz-config-overview
|
|
20
|
+
heading="Configuration"
|
|
21
|
+
infoText="This is a read-only view of the current running configuration."
|
|
22
|
+
>
|
|
23
|
+
<div style="padding: 20px; text-align: center; color: #71717a; font-size: 14px;">
|
|
24
|
+
Place <sz-config-section> elements here
|
|
25
|
+
</div>
|
|
26
|
+
</sz-config-overview>`;
|
|
27
|
+
|
|
28
|
+
public static demoGroups = ['Configuration'];
|
|
29
|
+
|
|
30
|
+
@property({ type: String })
|
|
31
|
+
public accessor heading: string = '';
|
|
32
|
+
|
|
33
|
+
@property({ type: String })
|
|
34
|
+
public accessor infoText: string = '';
|
|
35
|
+
|
|
36
|
+
public static styles = [
|
|
37
|
+
cssManager.defaultStyles,
|
|
38
|
+
css`
|
|
39
|
+
:host {
|
|
40
|
+
display: block;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.heading {
|
|
44
|
+
font-size: 20px;
|
|
45
|
+
font-weight: 600;
|
|
46
|
+
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
|
|
47
|
+
margin-bottom: 16px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.info-banner {
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: flex-start;
|
|
53
|
+
gap: 12px;
|
|
54
|
+
padding: 14px 18px;
|
|
55
|
+
margin-bottom: 20px;
|
|
56
|
+
border-radius: 8px;
|
|
57
|
+
background: ${cssManager.bdTheme('#eff6ff', 'rgba(59,130,246,0.08)')};
|
|
58
|
+
border: 1px solid ${cssManager.bdTheme('#bfdbfe', 'rgba(59,130,246,0.2)')};
|
|
59
|
+
color: ${cssManager.bdTheme('#1e40af', '#93c5fd')};
|
|
60
|
+
font-size: 13px;
|
|
61
|
+
line-height: 1.5;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.info-banner dees-icon {
|
|
65
|
+
flex-shrink: 0;
|
|
66
|
+
font-size: 18px;
|
|
67
|
+
margin-top: 1px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
::slotted(sz-config-section) {
|
|
71
|
+
margin-bottom: 12px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
::slotted(sz-config-section:last-child) {
|
|
75
|
+
margin-bottom: 0;
|
|
76
|
+
}
|
|
77
|
+
`,
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
public render(): TemplateResult {
|
|
81
|
+
return html`
|
|
82
|
+
${this.heading ? html`<div class="heading">${this.heading}</div>` : ''}
|
|
83
|
+
${this.infoText ? html`
|
|
84
|
+
<div class="info-banner">
|
|
85
|
+
<dees-icon .icon=${'lucide:info'}></dees-icon>
|
|
86
|
+
<span>${this.infoText}</span>
|
|
87
|
+
</div>
|
|
88
|
+
` : ''}
|
|
89
|
+
<slot></slot>
|
|
90
|
+
`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DeesElement,
|
|
3
|
+
customElement,
|
|
4
|
+
html,
|
|
5
|
+
css,
|
|
6
|
+
cssManager,
|
|
7
|
+
property,
|
|
8
|
+
state,
|
|
9
|
+
type TemplateResult,
|
|
10
|
+
} from '@design.estate/dees-element';
|
|
11
|
+
|
|
12
|
+
export interface IConfigField {
|
|
13
|
+
key: string;
|
|
14
|
+
value: string | number | boolean | string[] | null;
|
|
15
|
+
type?: 'text' | 'boolean' | 'badge' | 'pills' | 'code' | 'link';
|
|
16
|
+
description?: string;
|
|
17
|
+
linkTo?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
declare global {
|
|
21
|
+
interface HTMLElementTagNameMap {
|
|
22
|
+
'sz-config-section': SzConfigSection;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@customElement('sz-config-section')
|
|
27
|
+
export class SzConfigSection extends DeesElement {
|
|
28
|
+
public static demo = () => html`
|
|
29
|
+
<sz-config-section
|
|
30
|
+
title="SmartProxy"
|
|
31
|
+
subtitle="HTTP/HTTPS and TCP/SNI reverse proxy"
|
|
32
|
+
icon="lucide:network"
|
|
33
|
+
status="enabled"
|
|
34
|
+
.fields=${[
|
|
35
|
+
{ key: 'Route Count', value: 12 },
|
|
36
|
+
{ key: 'ACME Enabled', value: true, type: 'boolean' },
|
|
37
|
+
{ key: 'Account Email', value: 'admin@example.com' },
|
|
38
|
+
{ key: 'Use Production', value: true, type: 'boolean' },
|
|
39
|
+
{ key: 'Auto Renew', value: true, type: 'boolean' },
|
|
40
|
+
{ key: 'Renew Threshold', value: '30 days' },
|
|
41
|
+
] as IConfigField[]}
|
|
42
|
+
></sz-config-section>
|
|
43
|
+
<sz-config-section
|
|
44
|
+
title="Email Server"
|
|
45
|
+
subtitle="SMTP email handling with smartmta"
|
|
46
|
+
icon="lucide:mail"
|
|
47
|
+
status="disabled"
|
|
48
|
+
.fields=${[
|
|
49
|
+
{ key: 'Ports', value: ['25', '465', '587'], type: 'pills' },
|
|
50
|
+
{ key: 'Hostname', value: null },
|
|
51
|
+
{ key: 'Domains', value: ['example.com', 'mail.example.com'], type: 'pills' },
|
|
52
|
+
] as IConfigField[]}
|
|
53
|
+
></sz-config-section>
|
|
54
|
+
<sz-config-section
|
|
55
|
+
title="DNS Server"
|
|
56
|
+
subtitle="Authoritative DNS with smartdns"
|
|
57
|
+
icon="lucide:globe"
|
|
58
|
+
status="not-configured"
|
|
59
|
+
collapsible
|
|
60
|
+
.fields=${[
|
|
61
|
+
{ key: 'Port', value: 53 },
|
|
62
|
+
{ key: 'NS Domains', value: ['ns1.example.com', 'ns2.example.com'], type: 'pills' },
|
|
63
|
+
] as IConfigField[]}
|
|
64
|
+
></sz-config-section>
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
public static demoGroups = ['Configuration'];
|
|
68
|
+
|
|
69
|
+
@property({ type: String })
|
|
70
|
+
public accessor title: string = '';
|
|
71
|
+
|
|
72
|
+
@property({ type: String })
|
|
73
|
+
public accessor subtitle: string = '';
|
|
74
|
+
|
|
75
|
+
@property({ type: String })
|
|
76
|
+
public accessor icon: string = '';
|
|
77
|
+
|
|
78
|
+
@property({ type: String })
|
|
79
|
+
public accessor status: 'enabled' | 'disabled' | 'not-configured' | 'warning' = 'enabled';
|
|
80
|
+
|
|
81
|
+
@property({ type: Array })
|
|
82
|
+
public accessor fields: IConfigField[] = [];
|
|
83
|
+
|
|
84
|
+
@property({ type: Boolean })
|
|
85
|
+
public accessor collapsible: boolean = false;
|
|
86
|
+
|
|
87
|
+
@property({ type: Boolean })
|
|
88
|
+
public accessor collapsed: boolean = false;
|
|
89
|
+
|
|
90
|
+
@state()
|
|
91
|
+
accessor isCollapsed: boolean = false;
|
|
92
|
+
|
|
93
|
+
public static styles = [
|
|
94
|
+
cssManager.defaultStyles,
|
|
95
|
+
css`
|
|
96
|
+
:host {
|
|
97
|
+
display: block;
|
|
98
|
+
margin-bottom: 16px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.section {
|
|
102
|
+
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
|
|
103
|
+
border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
|
|
104
|
+
border-radius: 8px;
|
|
105
|
+
overflow: hidden;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.section-header {
|
|
109
|
+
display: flex;
|
|
110
|
+
align-items: center;
|
|
111
|
+
justify-content: space-between;
|
|
112
|
+
padding: 14px 20px;
|
|
113
|
+
background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
|
|
114
|
+
border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
|
|
115
|
+
cursor: default;
|
|
116
|
+
user-select: none;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
:host([collapsible]) .section-header {
|
|
120
|
+
cursor: pointer;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
:host([collapsible]) .section-header:hover {
|
|
124
|
+
background: ${cssManager.bdTheme('#ebebed', '#1c1c1f')};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.header-left {
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
gap: 12px;
|
|
131
|
+
min-width: 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.header-icon {
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
width: 36px;
|
|
139
|
+
height: 36px;
|
|
140
|
+
background: ${cssManager.bdTheme('#e4e4e7', '#27272a')};
|
|
141
|
+
border-radius: 8px;
|
|
142
|
+
flex-shrink: 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.header-icon dees-icon {
|
|
146
|
+
font-size: 18px;
|
|
147
|
+
color: ${cssManager.bdTheme('#52525b', '#a1a1aa')};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.header-text {
|
|
151
|
+
min-width: 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.header-title {
|
|
155
|
+
font-size: 15px;
|
|
156
|
+
font-weight: 600;
|
|
157
|
+
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
|
|
158
|
+
line-height: 1.3;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.header-subtitle {
|
|
162
|
+
font-size: 12px;
|
|
163
|
+
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
|
164
|
+
line-height: 1.3;
|
|
165
|
+
margin-top: 1px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.header-right {
|
|
169
|
+
display: flex;
|
|
170
|
+
align-items: center;
|
|
171
|
+
gap: 10px;
|
|
172
|
+
flex-shrink: 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Status badge */
|
|
176
|
+
.status-badge {
|
|
177
|
+
display: inline-flex;
|
|
178
|
+
align-items: center;
|
|
179
|
+
gap: 6px;
|
|
180
|
+
padding: 3px 10px;
|
|
181
|
+
border-radius: 9999px;
|
|
182
|
+
font-size: 12px;
|
|
183
|
+
font-weight: 500;
|
|
184
|
+
white-space: nowrap;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.status-badge.enabled {
|
|
188
|
+
background: ${cssManager.bdTheme('#dcfce7', 'rgba(34,197,94,0.2)')};
|
|
189
|
+
color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.status-badge.disabled {
|
|
193
|
+
background: ${cssManager.bdTheme('#fee2e2', 'rgba(239,68,68,0.2)')};
|
|
194
|
+
color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.status-badge.not-configured {
|
|
198
|
+
background: ${cssManager.bdTheme('#f4f4f5', 'rgba(113,113,122,0.2)')};
|
|
199
|
+
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.status-badge.warning {
|
|
203
|
+
background: ${cssManager.bdTheme('#fef3c7', 'rgba(245,158,11,0.15)')};
|
|
204
|
+
color: ${cssManager.bdTheme('#92400e', '#fbbf24')};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.status-dot {
|
|
208
|
+
width: 7px;
|
|
209
|
+
height: 7px;
|
|
210
|
+
border-radius: 50%;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.status-badge.enabled .status-dot {
|
|
214
|
+
background: ${cssManager.bdTheme('#16a34a', '#22c55e')};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.status-badge.disabled .status-dot {
|
|
218
|
+
background: ${cssManager.bdTheme('#dc2626', '#ef4444')};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.status-badge.not-configured .status-dot {
|
|
222
|
+
background: ${cssManager.bdTheme('#a1a1aa', '#52525b')};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.status-badge.warning .status-dot {
|
|
226
|
+
background: ${cssManager.bdTheme('#f59e0b', '#fbbf24')};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* Chevron */
|
|
230
|
+
.chevron {
|
|
231
|
+
display: flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
transition: transform 200ms ease;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.chevron.collapsed {
|
|
237
|
+
transform: rotate(-90deg);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.chevron dees-icon {
|
|
241
|
+
font-size: 16px;
|
|
242
|
+
color: ${cssManager.bdTheme('#a1a1aa', '#52525b')};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* Content */
|
|
246
|
+
.section-content {
|
|
247
|
+
padding: 0;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.section-content.collapsed {
|
|
251
|
+
display: none;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Field rows */
|
|
255
|
+
.field-row {
|
|
256
|
+
display: flex;
|
|
257
|
+
align-items: flex-start;
|
|
258
|
+
justify-content: space-between;
|
|
259
|
+
padding: 10px 20px;
|
|
260
|
+
border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#1a1a1e')};
|
|
261
|
+
gap: 16px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.field-row:last-child {
|
|
265
|
+
border-bottom: none;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.field-key {
|
|
269
|
+
font-size: 13px;
|
|
270
|
+
font-weight: 500;
|
|
271
|
+
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
|
272
|
+
flex-shrink: 0;
|
|
273
|
+
min-width: 140px;
|
|
274
|
+
padding-top: 1px;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.field-value {
|
|
278
|
+
font-size: 13px;
|
|
279
|
+
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
|
|
280
|
+
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
|
|
281
|
+
text-align: right;
|
|
282
|
+
word-break: break-all;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.field-value.null-value {
|
|
286
|
+
color: ${cssManager.bdTheme('#a1a1aa', '#52525b')};
|
|
287
|
+
font-style: italic;
|
|
288
|
+
font-family: inherit;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* Boolean display */
|
|
292
|
+
.bool-value {
|
|
293
|
+
display: inline-flex;
|
|
294
|
+
align-items: center;
|
|
295
|
+
gap: 5px;
|
|
296
|
+
font-family: inherit;
|
|
297
|
+
font-size: 13px;
|
|
298
|
+
font-weight: 500;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.bool-value.true {
|
|
302
|
+
color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.bool-value.false {
|
|
306
|
+
color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.bool-dot {
|
|
310
|
+
width: 6px;
|
|
311
|
+
height: 6px;
|
|
312
|
+
border-radius: 50%;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.bool-value.true .bool-dot {
|
|
316
|
+
background: ${cssManager.bdTheme('#16a34a', '#22c55e')};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.bool-value.false .bool-dot {
|
|
320
|
+
background: ${cssManager.bdTheme('#dc2626', '#ef4444')};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/* Pills */
|
|
324
|
+
.pills {
|
|
325
|
+
display: flex;
|
|
326
|
+
flex-wrap: wrap;
|
|
327
|
+
gap: 5px;
|
|
328
|
+
justify-content: flex-end;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.pill {
|
|
332
|
+
display: inline-flex;
|
|
333
|
+
align-items: center;
|
|
334
|
+
padding: 2px 9px;
|
|
335
|
+
border-radius: 9999px;
|
|
336
|
+
font-size: 12px;
|
|
337
|
+
font-weight: 500;
|
|
338
|
+
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
|
|
339
|
+
background: ${cssManager.bdTheme('#eff6ff', 'rgba(59,130,246,0.1)')};
|
|
340
|
+
color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* Code value */
|
|
344
|
+
.code-value {
|
|
345
|
+
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
|
|
346
|
+
font-size: 12px;
|
|
347
|
+
background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
|
|
348
|
+
padding: 2px 8px;
|
|
349
|
+
border-radius: 4px;
|
|
350
|
+
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/* Link value */
|
|
354
|
+
.link-value {
|
|
355
|
+
color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
|
|
356
|
+
cursor: pointer;
|
|
357
|
+
text-decoration: none;
|
|
358
|
+
font-family: inherit;
|
|
359
|
+
font-size: 13px;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.link-value:hover {
|
|
363
|
+
text-decoration: underline;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Description hint */
|
|
367
|
+
.field-description {
|
|
368
|
+
font-size: 11px;
|
|
369
|
+
color: ${cssManager.bdTheme('#a1a1aa', '#52525b')};
|
|
370
|
+
margin-top: 3px;
|
|
371
|
+
text-align: right;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* Slot for custom content */
|
|
375
|
+
.slot-content {
|
|
376
|
+
border-top: 1px solid ${cssManager.bdTheme('#f4f4f5', '#1a1a1e')};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.slot-content:empty {
|
|
380
|
+
display: none;
|
|
381
|
+
border-top: none;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/* Badge type */
|
|
385
|
+
.badge-value {
|
|
386
|
+
display: inline-flex;
|
|
387
|
+
align-items: center;
|
|
388
|
+
padding: 2px 9px;
|
|
389
|
+
border-radius: 9999px;
|
|
390
|
+
font-size: 12px;
|
|
391
|
+
font-weight: 500;
|
|
392
|
+
background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
|
|
393
|
+
color: ${cssManager.bdTheme('#52525b', '#a1a1aa')};
|
|
394
|
+
}
|
|
395
|
+
`,
|
|
396
|
+
];
|
|
397
|
+
|
|
398
|
+
async connectedCallback() {
|
|
399
|
+
await super.connectedCallback();
|
|
400
|
+
this.isCollapsed = this.collapsed;
|
|
401
|
+
if (this.collapsible) {
|
|
402
|
+
this.setAttribute('collapsible', '');
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
public render(): TemplateResult {
|
|
407
|
+
const statusLabels: Record<string, string> = {
|
|
408
|
+
'enabled': 'Enabled',
|
|
409
|
+
'disabled': 'Disabled',
|
|
410
|
+
'not-configured': 'Not Configured',
|
|
411
|
+
'warning': 'Warning',
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
return html`
|
|
415
|
+
<div class="section">
|
|
416
|
+
<div
|
|
417
|
+
class="section-header"
|
|
418
|
+
@click=${() => {
|
|
419
|
+
if (this.collapsible) {
|
|
420
|
+
this.isCollapsed = !this.isCollapsed;
|
|
421
|
+
}
|
|
422
|
+
}}
|
|
423
|
+
>
|
|
424
|
+
<div class="header-left">
|
|
425
|
+
${this.icon ? html`
|
|
426
|
+
<div class="header-icon">
|
|
427
|
+
<dees-icon .icon=${this.icon}></dees-icon>
|
|
428
|
+
</div>
|
|
429
|
+
` : ''}
|
|
430
|
+
<div class="header-text">
|
|
431
|
+
<div class="header-title">${this.title}</div>
|
|
432
|
+
${this.subtitle ? html`<div class="header-subtitle">${this.subtitle}</div>` : ''}
|
|
433
|
+
</div>
|
|
434
|
+
</div>
|
|
435
|
+
<div class="header-right">
|
|
436
|
+
${this.status ? html`
|
|
437
|
+
<span class="status-badge ${this.status}">
|
|
438
|
+
<span class="status-dot"></span>
|
|
439
|
+
${statusLabels[this.status] || this.status}
|
|
440
|
+
</span>
|
|
441
|
+
` : ''}
|
|
442
|
+
${this.collapsible ? html`
|
|
443
|
+
<span class="chevron ${this.isCollapsed ? 'collapsed' : ''}">
|
|
444
|
+
<dees-icon .icon=${'lucide:chevronDown'}></dees-icon>
|
|
445
|
+
</span>
|
|
446
|
+
` : ''}
|
|
447
|
+
</div>
|
|
448
|
+
</div>
|
|
449
|
+
<div class="section-content ${this.isCollapsed ? 'collapsed' : ''}">
|
|
450
|
+
${this.fields.map(field => this.renderField(field))}
|
|
451
|
+
<div class="slot-content">
|
|
452
|
+
<slot></slot>
|
|
453
|
+
</div>
|
|
454
|
+
</div>
|
|
455
|
+
</div>
|
|
456
|
+
`;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
private renderField(field: IConfigField): TemplateResult {
|
|
460
|
+
return html`
|
|
461
|
+
<div class="field-row">
|
|
462
|
+
<div class="field-key">${field.key}</div>
|
|
463
|
+
<div>
|
|
464
|
+
${this.renderFieldValue(field)}
|
|
465
|
+
${field.description ? html`<div class="field-description">${field.description}</div>` : ''}
|
|
466
|
+
</div>
|
|
467
|
+
</div>
|
|
468
|
+
`;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
private renderFieldValue(field: IConfigField): TemplateResult {
|
|
472
|
+
const value = field.value;
|
|
473
|
+
const type = field.type || this.inferType(value);
|
|
474
|
+
|
|
475
|
+
// Null / undefined
|
|
476
|
+
if (value === null || value === undefined) {
|
|
477
|
+
return html`<span class="field-value null-value">Not configured</span>`;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
switch (type) {
|
|
481
|
+
case 'boolean':
|
|
482
|
+
return html`
|
|
483
|
+
<span class="bool-value ${value ? 'true' : 'false'}">
|
|
484
|
+
<span class="bool-dot"></span>
|
|
485
|
+
${value ? 'Enabled' : 'Disabled'}
|
|
486
|
+
</span>
|
|
487
|
+
`;
|
|
488
|
+
|
|
489
|
+
case 'pills':
|
|
490
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
491
|
+
return html`<span class="field-value null-value">None</span>`;
|
|
492
|
+
}
|
|
493
|
+
return html`
|
|
494
|
+
<div class="pills">
|
|
495
|
+
${(value as string[]).map(v => html`<span class="pill">${v}</span>`)}
|
|
496
|
+
</div>
|
|
497
|
+
`;
|
|
498
|
+
|
|
499
|
+
case 'code':
|
|
500
|
+
return html`<span class="code-value">${String(value)}</span>`;
|
|
501
|
+
|
|
502
|
+
case 'badge':
|
|
503
|
+
return html`<span class="badge-value">${String(value)}</span>`;
|
|
504
|
+
|
|
505
|
+
case 'link':
|
|
506
|
+
return html`
|
|
507
|
+
<span
|
|
508
|
+
class="link-value"
|
|
509
|
+
@click=${() => {
|
|
510
|
+
if (field.linkTo) {
|
|
511
|
+
this.dispatchEvent(new CustomEvent('navigate', {
|
|
512
|
+
detail: { target: field.linkTo },
|
|
513
|
+
bubbles: true,
|
|
514
|
+
composed: true,
|
|
515
|
+
}));
|
|
516
|
+
}
|
|
517
|
+
}}
|
|
518
|
+
>${String(value)}</span>
|
|
519
|
+
`;
|
|
520
|
+
|
|
521
|
+
default:
|
|
522
|
+
return html`<span class="field-value">${String(value)}</span>`;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
private inferType(value: unknown): string {
|
|
527
|
+
if (typeof value === 'boolean') return 'boolean';
|
|
528
|
+
if (Array.isArray(value)) return 'pills';
|
|
529
|
+
return 'text';
|
|
530
|
+
}
|
|
531
|
+
}
|