-
-
+
-
-
+
- Email Metadata
+
+
+ Email Metadata
+
@@ -684,49 +720,53 @@ export class SzMtaDetailView extends DeesElement {
-
-
-
+
+
- SMTP Transaction Log
-
- ${email.direction}
- ${email.direction === 'outbound'
- ? `${email.connectionInfo.sourceHostname} → ${email.connectionInfo.destinationIp}:${email.connectionInfo.destinationPort}`
- : `${email.connectionInfo.sourceIp} → ${email.connectionInfo.sourceHostname}:${email.connectionInfo.destinationPort}`
- }
-
+
+ this.copySmtpLog()}>
-
+
+ SMTP Transaction Log
+ ${email.direction}
-
+ ${email.direction === 'outbound'
+ ? `${email.connectionInfo.sourceHostname} → ${email.connectionInfo.destinationIp}:${email.connectionInfo.destinationPort}`
+ : `${email.connectionInfo.sourceIp} → ${email.connectionInfo.sourceHostname}:${email.connectionInfo.destinationPort}`
+ }
+
+ ${this.renderSmtpLog(email)}
+
+ this.copySmtpLog()}>
+
Copy Log
- ${this.renderSmtpLog(email)}
-
-
-
-
+
+
Email Body (Escaped)
- Raw content — HTML is not rendered
+
+
+ Email Body (Escaped)
+ Raw content — HTML is not rendered
${email.body}
-
-
-
-
+
-
+
- Connection Info
+
+
+ Connection Info
+
@@ -772,12 +812,14 @@ export class SzMtaDetailView extends DeesElement {
` : ''}
-
diff --git a/ts_web/elements/sz-network-domains-view.ts b/ts_web/elements/sz-network-domains-view.ts
index 29c53ac..8b2179f 100644
--- a/ts_web/elements/sz-network-domains-view.ts
+++ b/ts_web/elements/sz-network-domains-view.ts
@@ -7,8 +7,7 @@ import {
property,
type TemplateResult,
} from '@design.estate/dees-element';
-
-import './sz-stat-card.js';
+import type { IStatsTile } from '@design.estate/dees-catalog';
declare global {
interface HTMLElementTagNameMap {
@@ -91,19 +90,11 @@ export class SzNetworkDomainsView extends DeesElement {
border-color: ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
}
- .stats-grid {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 16px;
+ dees-statsgrid {
+ display: block;
margin-bottom: 24px;
}
- @media (min-width: 768px) {
- .stats-grid {
- grid-template-columns: repeat(4, 1fr);
- }
- }
-
.table-container {
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
@@ -205,6 +196,42 @@ export class SzNetworkDomainsView extends DeesElement {
`,
];
+ private get tiles(): IStatsTile[] {
+ return [
+ {
+ id: 'total',
+ title: 'Total Domains',
+ value: this.stats.total,
+ type: 'number',
+ icon: 'lucide:globe',
+ },
+ {
+ id: 'valid',
+ title: 'Valid Certificates',
+ value: this.stats.valid,
+ type: 'number',
+ icon: 'lucide:shieldCheck',
+ color: '#22c55e',
+ },
+ {
+ id: 'expiring',
+ title: 'Expiring Soon',
+ value: this.stats.expiring,
+ type: 'number',
+ icon: 'lucide:shieldAlert',
+ color: this.stats.expiring > 0 ? '#f59e0b' : undefined,
+ },
+ {
+ id: 'expired',
+ title: 'Expired/Pending',
+ value: this.stats.expired,
+ type: 'number',
+ icon: 'lucide:circleOff',
+ color: this.stats.expired > 0 ? '#ef4444' : undefined,
+ },
+ ];
+ }
+
public render(): TemplateResult {
return html`
-
+
-
+
${email.status === 'rejected' || email.status === 'bounced' ? html`
- Authentication Results
+
+
+ Authentication Results
+
@@ -802,13 +844,15 @@ export class SzMtaDetailView extends DeesElement {
${email.authenticationResults.dmarc}
-
-
+
+
` : ''}
Rejection Details
+
+
+ Rejection Details
+
${email.rejectionReason ? html`
@@ -820,7 +864,7 @@ export class SzMtaDetailView extends DeesElement {
- ${email.bounceMessage}
` : ''}
@@ -212,31 +239,10 @@ export class SzNetworkDomainsView extends DeesElement {
this.handleSync()}>Sync Cloudflare
-
-
-
-
-
-
+
diff --git a/ts_web/elements/sz-network-proxy-view.ts b/ts_web/elements/sz-network-proxy-view.ts
index 3d3bad6..48b6b60 100644
--- a/ts_web/elements/sz-network-proxy-view.ts
+++ b/ts_web/elements/sz-network-proxy-view.ts
@@ -7,8 +7,7 @@ import {
property,
type TemplateResult,
} from '@design.estate/dees-element';
-
-import './sz-stat-card.js';
+import type { IStatsTile } from '@design.estate/dees-catalog';
declare global {
interface HTMLElementTagNameMap {
@@ -113,42 +112,107 @@ export class SzNetworkProxyView extends DeesElement {
background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
}
- .stats-grid {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 16px;
+ dees-statsgrid {
+ display: block;
margin-bottom: 24px;
}
- @media (min-width: 768px) {
- .stats-grid {
- grid-template-columns: repeat(4, 1fr);
- }
- }
-
- .section {
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 8px;
+ dees-tile {
+ display: block;
margin-bottom: 24px;
- overflow: hidden;
}
.section-header {
- padding: 16px;
- border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
+ height: 36px;
+ display: flex;
+ align-items: center;
+ padding: 0 16px;
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ .section-heading {
+ flex: 1;
+ display: flex;
+ align-items: baseline;
+ gap: 8px;
+ min-width: 0;
}
.section-title {
- font-size: 16px;
- font-weight: 600;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
+ font-weight: 500;
+ font-size: 13px;
+ letter-spacing: -0.01em;
+ color: var(--dees-color-text-secondary);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.section-subtitle {
- font-size: 13px;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
- margin-top: 2px;
+ font-size: 12px;
+ color: var(--dees-color-text-muted);
+ letter-spacing: -0.01em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .section-footer {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 0;
+ height: 36px;
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ .tile-button {
+ padding: 0 16px;
+ height: 100%;
+ text-align: center;
+ font-size: 12px;
+ font-weight: 500;
+ cursor: pointer;
+ user-select: none;
+ transition: all 0.15s ease;
+ background: transparent;
+ border: none;
+ border-left: 1px solid var(--dees-color-border-subtle);
+ color: var(--dees-color-text-muted);
+ white-space: nowrap;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ }
+
+ .tile-button:first-child {
+ border-left: none;
+ }
+
+ .tile-button:hover {
+ background: var(--dees-color-hover);
+ color: var(--dees-color-text-primary);
+ }
+
+ .tile-button.primary {
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
+ font-weight: 600;
+ }
+
+ .tile-button.primary:hover {
+ background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.08)', 'hsl(213.1 93.9% 67.8% / 0.08)')};
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 50%)', 'hsl(213.1 93.9% 75%)')};
+ }
+
+ .tile-button.danger {
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
+ }
+
+ .tile-button.danger:hover {
+ background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.1)')};
}
.table-header {
@@ -234,61 +298,6 @@ export class SzNetworkProxyView extends DeesElement {
color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
}
- .logs-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 16px;
- border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- }
-
- .logs-actions {
- display: flex;
- gap: 8px;
- }
-
- .stream-button {
- display: inline-flex;
- align-items: center;
- gap: 6px;
- padding: 6px 12px;
- background: ${cssManager.bdTheme('#2563eb', '#3b82f6')};
- border: none;
- border-radius: 4px;
- font-size: 13px;
- font-weight: 500;
- color: white;
- cursor: pointer;
- transition: all 200ms ease;
- }
-
- .stream-button:hover {
- background: ${cssManager.bdTheme('#1d4ed8', '#2563eb')};
- }
-
- .stream-button.streaming {
- background: ${cssManager.bdTheme('#dc2626', '#ef4444')};
- }
-
- .stream-button.streaming:hover {
- background: ${cssManager.bdTheme('#b91c1c', '#dc2626')};
- }
-
- .clear-button {
- padding: 6px 12px;
- background: transparent;
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 4px;
- font-size: 13px;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
- cursor: pointer;
- transition: all 200ms ease;
- }
-
- .clear-button:hover {
- background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
- }
-
.logs-container {
padding: 16px;
font-family: monospace;
@@ -336,41 +345,57 @@ export class SzNetworkProxyView extends DeesElement {
`,
];
+ private get tiles(): IStatsTile[] {
+ return [
+ {
+ id: 'proxy-status',
+ title: 'Proxy Status',
+ value: this.proxyStatus === 'running' ? 'Running' : 'Stopped',
+ type: 'text',
+ icon: 'lucide:server',
+ color: this.proxyStatus === 'running' ? '#22c55e' : '#ef4444',
+ },
+ {
+ id: 'routes',
+ title: 'Routes',
+ value: this.routeCount,
+ type: 'number',
+ icon: 'lucide:server',
+ },
+ {
+ id: 'certificates',
+ title: 'Certificates',
+ value: this.certificateCount,
+ type: 'number',
+ icon: 'lucide:check',
+ },
+ {
+ id: 'targets',
+ title: 'Targets',
+ value: this.targetCount,
+ type: 'number',
+ icon: 'lucide:server',
+ },
+ ];
+ }
+
public render(): TemplateResult {
return html`
this.handleRefresh()}>Refresh
-
-
-
-
-
-
-
+
-
-
+
+
- Traffic Targets
- Services, registry, and platform services with their routing info
+
+
+ Traffic Targets
+ Services, registry, and platform services with their routing info
+
Type
@@ -388,30 +413,13 @@ export class SzNetworkProxyView extends DeesElement {
${target.status}
`)}
-
-
-
-
- Access Logs
- Real-time Caddy access logs
-
- this.toggleStreaming()}>
-
- ${this.streaming ? 'Stop' : 'Stream'}
-
- this.handleClearLogs()}>
-
- Clear logs
-
+
+
+
+
+ Access Logs
+ Real-time Caddy access logs
@@ -428,7 +436,24 @@ export class SzNetworkProxyView extends DeesElement {
- Click "Stream" to start live access log streaming
`}
+ this.toggleStreaming()}>
+
+ ${this.streaming ? 'Stop' : 'Stream'}
+
+ this.handleClearLogs()}>
+
+ Clear logs
+
+
+
`;
}
diff --git a/ts_web/elements/sz-platform-service-detail-view.ts b/ts_web/elements/sz-platform-service-detail-view.ts
index 7ddfef4..73e76ce 100644
--- a/ts_web/elements/sz-platform-service-detail-view.ts
+++ b/ts_web/elements/sz-platform-service-detail-view.ts
@@ -225,39 +225,35 @@ export class SzPlatformServiceDetailView extends DeesElement {
}
}
- .section {
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 8px;
- overflow: hidden;
- }
-
- .section.full-width {
+ dees-tile.full-width {
grid-column: 1 / -1;
}
.section-header {
+ height: 36px;
display: flex;
- justify-content: space-between;
align-items: center;
- padding: 14px 16px;
- border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
+ padding: 0 16px;
+ width: 100%;
+ box-sizing: border-box;
}
.section-title {
- font-size: 14px;
- font-weight: 600;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
+ flex: 1;
display: flex;
align-items: center;
gap: 8px;
+ font-weight: 500;
+ font-size: 13px;
+ letter-spacing: -0.01em;
+ color: var(--dees-color-text-secondary);
}
.section-title svg {
- width: 16px;
- height: 16px;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
+ width: 14px;
+ height: 14px;
+ flex-shrink: 0;
+ color: var(--dees-color-text-secondary);
}
.section-content {
@@ -452,8 +448,8 @@ export class SzPlatformServiceDetailView extends DeesElement {
-
-
+
+
` : ''}
-
+
-
-
+
+
`)}
-
+
${this.service.metrics ? html`
-
-
+
+
-
+
` : ''}
diff --git a/ts_web/elements/sz-service-detail-view.ts b/ts_web/elements/sz-service-detail-view.ts
index 4daa91d..22604b4 100644
--- a/ts_web/elements/sz-service-detail-view.ts
+++ b/ts_web/elements/sz-service-detail-view.ts
@@ -11,8 +11,6 @@ import {
import type { IExecutionEnvironment } from '@design.estate/dees-catalog';
-import './sz-stat-card.js';
-
declare global {
interface HTMLElementTagNameMap {
'sz-service-detail-view': SzServiceDetailView;
@@ -218,31 +216,97 @@ export class SzServiceDetailView extends DeesElement {
gap: 24px;
}
- .card {
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 8px;
- overflow: hidden;
+ .card-header {
+ height: 36px;
+ display: flex;
+ align-items: center;
+ padding: 0 8px 0 16px;
+ width: 100%;
+ box-sizing: border-box;
}
- .card-header {
+ .card-heading {
+ flex: 1;
display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 16px;
- border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
+ align-items: baseline;
+ gap: 8px;
+ min-width: 0;
}
.card-title {
- font-size: 16px;
- font-weight: 600;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
+ font-weight: 500;
+ font-size: 13px;
+ letter-spacing: -0.01em;
+ color: var(--dees-color-text-secondary);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.card-subtitle {
- font-size: 13px;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
- margin-top: 2px;
+ font-size: 12px;
+ color: var(--dees-color-text-muted);
+ letter-spacing: -0.01em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .card-footer {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 0;
+ height: 36px;
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ .tile-button {
+ padding: 0 16px;
+ height: 100%;
+ text-align: center;
+ font-size: 12px;
+ font-weight: 500;
+ cursor: pointer;
+ user-select: none;
+ transition: all 0.15s ease;
+ background: transparent;
+ border: none;
+ border-left: 1px solid var(--dees-color-border-subtle);
+ color: var(--dees-color-text-muted);
+ white-space: nowrap;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ }
+
+ .tile-button:first-child {
+ border-left: none;
+ }
+
+ .tile-button:hover {
+ background: var(--dees-color-hover);
+ color: var(--dees-color-text-primary);
+ }
+
+ .tile-button.primary {
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
+ font-weight: 600;
+ }
+
+ .tile-button.primary:hover {
+ background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.08)', 'hsl(213.1 93.9% 67.8% / 0.08)')};
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 50%)', 'hsl(213.1 93.9% 75%)')};
+ }
+
+ .tile-button.danger {
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
+ }
+
+ .tile-button.danger:hover {
+ background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.1)')};
}
.card-content {
@@ -518,12 +582,11 @@ export class SzServiceDetailView extends DeesElement {
-
-
-
+
-
+
- Service Details
+
+ this.handleEdit()}>Edit
+ Service Details
-
@@ -557,7 +620,10 @@ export class SzServiceDetailView extends DeesElement {
+ this.handleEdit()}>Edit
+
+
-
-
+
-
-
+
- Live stats
+
+
+ Live stats
+
@@ -598,13 +666,13 @@ export class SzServiceDetailView extends DeesElement {
-
-
+
-
-
+
- Actions
- Manage service state
+
+
+ Actions
+ Manage service state
@@ -624,13 +692,13 @@ export class SzServiceDetailView extends DeesElement {
this.handleAction('delete')}>Delete Service
-
+
-
-
-
-
+
Image Source
- ${this.service.registry === 'Docker Hub' ? 'External container registry' : 'Onebox registry'}
+
+
+ Image Source
+ ${this.service.registry === 'Docker Hub' ? 'External container registry' : 'Onebox registry'}
@@ -649,21 +717,14 @@ export class SzServiceDetailView extends DeesElement {
-
`;
diff --git a/ts_web/elements/sz-services-backups-view.ts b/ts_web/elements/sz-services-backups-view.ts
index c6d9641..5f48244 100644
--- a/ts_web/elements/sz-services-backups-view.ts
+++ b/ts_web/elements/sz-services-backups-view.ts
@@ -65,71 +65,94 @@ export class SzServicesBackupsView extends DeesElement {
display: block;
}
- .section {
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 8px;
+ dees-tile {
+ display: block;
margin-bottom: 24px;
- overflow: hidden;
}
.section-header {
+ height: 36px;
display: flex;
- justify-content: space-between;
- align-items: flex-start;
- padding: 16px;
- border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
+ align-items: center;
+ padding: 0 16px;
+ width: 100%;
+ box-sizing: border-box;
}
- .section-info {
+ .section-heading {
+ flex: 1;
display: flex;
- flex-direction: column;
- gap: 4px;
+ align-items: baseline;
+ gap: 8px;
+ min-width: 0;
}
.section-title {
- font-size: 16px;
- font-weight: 600;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
+ font-weight: 500;
+ font-size: 13px;
+ letter-spacing: -0.01em;
+ color: var(--dees-color-text-secondary);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.section-subtitle {
- font-size: 13px;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
+ font-size: 12px;
+ color: var(--dees-color-text-muted);
+ letter-spacing: -0.01em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
- .header-actions {
+ .section-footer {
display: flex;
- gap: 8px;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 0;
+ height: 36px;
+ width: 100%;
+ box-sizing: border-box;
}
- .action-button {
- display: inline-flex;
+ .tile-button {
+ padding: 0 16px;
+ height: 100%;
+ text-align: center;
+ font-size: 12px;
+ font-weight: 500;
+ cursor: pointer;
+ user-select: none;
+ transition: all 0.15s ease;
+ background: transparent;
+ border: none;
+ border-left: 1px solid var(--dees-color-border-subtle);
+ color: var(--dees-color-text-muted);
+ white-space: nowrap;
+ display: flex;
align-items: center;
gap: 6px;
- padding: 8px 14px;
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 6px;
- font-size: 13px;
- font-weight: 500;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
- cursor: pointer;
- transition: all 200ms ease;
}
- .action-button:hover {
- background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
+ .tile-button:first-child {
+ border-left: none;
}
- .action-button.primary {
- background: ${cssManager.bdTheme('#18181b', '#fafafa')};
- color: ${cssManager.bdTheme('#fafafa', '#18181b')};
- border: none;
+ .tile-button:hover {
+ background: var(--dees-color-hover);
+ color: var(--dees-color-text-primary);
}
- .action-button.primary:hover {
- opacity: 0.9;
+ .tile-button.primary {
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
+ font-weight: 600;
+ }
+
+ .tile-button.primary:hover {
+ background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.08)', 'hsl(213.1 93.9% 67.8% / 0.08)')};
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 50%)', 'hsl(213.1 93.9% 75%)')};
}
.table-header {
@@ -253,28 +276,11 @@ export class SzServicesBackupsView extends DeesElement {
public render(): TemplateResult {
return html`
-
-
-
+
-
+ Backups
- Create and manage service backups
+
+ this.handleCreateBackup()}>
-
- Create Backup
-
+ Backups
+ Create and manage service backups
-
@@ -698,7 +759,16 @@ export class SzServiceDetailView extends DeesElement {
`)}
+ this.handleCreateBackup()}>
+
+ Create Backup
+
+
+
-
-
-
- Backup Schedules
- Configure automated backup schedules for your services
-
- this.handleImport()}>
-
- Import Backup
-
- this.handleCreateSchedule()}>
-
- Create Schedule
-
+
+
+
+
+ Backup Schedules
+ Configure automated backup schedules for your services
@@ -318,13 +324,30 @@ export class SzServicesBackupsView extends DeesElement {
`)}
-
+ this.handleImport()}>
+
+ Import Backup
+
+ this.handleCreateSchedule()}>
+
+ Create Schedule
+
+
+
-
-
-
-
+
+
`;
}
diff --git a/ts_web/elements/sz-settings-view.ts b/ts_web/elements/sz-settings-view.ts
index 898fed4..19bb29f 100644
--- a/ts_web/elements/sz-settings-view.ts
+++ b/ts_web/elements/sz-settings-view.ts
@@ -72,28 +72,98 @@ export class SzSettingsView extends DeesElement {
display: block;
}
- .section {
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 8px;
- padding: 20px;
+ dees-tile {
+ display: block;
margin-bottom: 24px;
}
.section-header {
- margin-bottom: 16px;
+ height: 36px;
+ display: flex;
+ align-items: center;
+ padding: 0 16px;
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ .section-heading {
+ flex: 1;
+ display: flex;
+ align-items: baseline;
+ gap: 8px;
+ min-width: 0;
}
.section-title {
- font-size: 16px;
- font-weight: 600;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
+ font-weight: 500;
+ font-size: 13px;
+ letter-spacing: -0.01em;
+ color: var(--dees-color-text-secondary);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.section-subtitle {
- font-size: 13px;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
- margin-top: 2px;
+ font-size: 12px;
+ color: var(--dees-color-text-muted);
+ letter-spacing: -0.01em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .section-content {
+ padding: 20px;
+ }
+
+ .section-footer {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 0;
+ height: 36px;
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ .tile-button {
+ padding: 0 16px;
+ height: 100%;
+ text-align: center;
+ font-size: 12px;
+ font-weight: 500;
+ cursor: pointer;
+ user-select: none;
+ transition: all 0.15s ease;
+ background: transparent;
+ border: none;
+ border-left: 1px solid var(--dees-color-border-subtle);
+ color: var(--dees-color-text-muted);
+ white-space: nowrap;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ }
+
+ .tile-button:first-child {
+ border-left: none;
+ }
+
+ .tile-button:hover {
+ background: var(--dees-color-hover);
+ color: var(--dees-color-text-primary);
+ }
+
+ .tile-button.primary {
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
+ font-weight: 600;
+ }
+
+ .tile-button.primary:hover {
+ background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.08)', 'hsl(213.1 93.9% 67.8% / 0.08)')};
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 50%)', 'hsl(213.1 93.9% 75%)')};
}
.form-group {
@@ -224,161 +294,151 @@ export class SzSettingsView extends DeesElement {
margin-bottom: 4px;
}
- .actions {
- display: flex;
- justify-content: flex-end;
- gap: 12px;
- padding-top: 16px;
- border-top: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- margin-top: 24px;
- }
-
- .button {
- padding: 10px 20px;
- border-radius: 6px;
- font-size: 14px;
- font-weight: 500;
- cursor: pointer;
- transition: all 200ms ease;
- }
-
- .button.secondary {
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
- }
-
- .button.secondary:hover {
- background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
- }
-
- .button.primary {
- background: ${cssManager.bdTheme('#18181b', '#fafafa')};
- border: none;
- color: ${cssManager.bdTheme('#fafafa', '#18181b')};
- }
-
- .button.primary:hover {
- opacity: 0.9;
- }
`,
];
public render(): TemplateResult {
return html`
- All Backups
- Browse and manage all backups across services
+
+
+ All Backups
+ Browse and manage all backups across services
@@ -358,7 +381,7 @@ export class SzServicesBackupsView extends DeesElement {
`)}
-
-
-
-
-
- Appearance
- Customize the look and feel
-
-
-
- Dark Mode
- Toggle dark mode on or off
-
- this.toggleDarkMode()}>
-
-
-
-
-
- Cloudflare Integration
- Configure Cloudflare API for DNS management
-
-
-
-
- API Token
- this.updateSetting('cloudflareToken', (e.target as HTMLInputElement).value)}>
-
-
- Zone ID (Optional)
- this.updateSetting('cloudflareZoneId', (e.target as HTMLInputElement).value)}>
- Get your API token from the Cloudflare dashboard with DNS edit permissions.
-
-
-
-
-
- SSL/TLS Settings
- Configure certificate management
-
-
-
- Auto-Renew Certificates
- Automatically renew certificates before expiry
-
- this.toggleSetting('autoRenewCerts')}>
-
-
- Renewal Threshold (days)
- this.updateSetting('renewalThreshold', parseInt((e.target as HTMLInputElement).value))}>
- Renew certificates when they have fewer than this many days remaining.
-
-
- ACME Email
- this.updateSetting('acmeEmail', (e.target as HTMLInputElement).value)}>
- Email address for Let's Encrypt notifications.
-
-
-
- Network Settings
- Configure network and proxy settings
-
-
-
- HTTP Port
- this.updateSetting('httpPort', parseInt((e.target as HTMLInputElement).value))}>
-
-
+
-
- HTTPS Port
- this.updateSetting('httpsPort', parseInt((e.target as HTMLInputElement).value))}>
+
+
-
+ Appearance
+ Customize the look and feel
-
-
- Force HTTPS
- Redirect all HTTP traffic to HTTPS
-
- this.toggleSetting('forceHttps')}>
-
-
-
- Account
- Manage your account settings
-
-
- Current User
- ${this.currentUser || 'Unknown'}
-
-
Change Password
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
`;
}
diff --git a/ts_web/elements/sz-stat-card.ts b/ts_web/elements/sz-stat-card.ts
deleted file mode 100644
index 3805daf..0000000
--- a/ts_web/elements/sz-stat-card.ts
+++ /dev/null
@@ -1,189 +0,0 @@
-import {
- DeesElement,
- customElement,
- html,
- css,
- cssManager,
- property,
- type TemplateResult,
-} from '@design.estate/dees-element';
-
-declare global {
- interface HTMLElementTagNameMap {
- 'sz-stat-card': SzStatCard;
- }
-}
-
-@customElement('sz-stat-card')
-export class SzStatCard extends DeesElement {
- public static demo = () => html`
-
- = {
- server: html``,
- check: html``,
- stop: html``,
- container: html``,
- };
-
- return icons[this.icon] || html``;
- }
-}
diff --git a/ts_web/elements/sz-status-grid-cluster.ts b/ts_web/elements/sz-status-grid-cluster.ts
index a3c71b6..a5078b4 100644
--- a/ts_web/elements/sz-status-grid-cluster.ts
+++ b/ts_web/elements/sz-status-grid-cluster.ts
@@ -7,8 +7,7 @@ import {
property,
type TemplateResult,
} from '@design.estate/dees-element';
-
-import './sz-stat-card.js';
+import type { IStatsTile } from '@design.estate/dees-catalog';
declare global {
interface HTMLElementTagNameMap {
@@ -54,54 +53,51 @@ export class SzStatusGridCluster extends DeesElement {
:host {
display: block;
}
-
- .grid {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 16px;
- align-items: stretch;
- }
-
- .grid > * {
- height: 100%;
- }
-
- @media (min-width: 768px) {
- .grid {
- grid-template-columns: repeat(4, 1fr);
- }
- }
`,
];
+ private get tiles(): IStatsTile[] {
+ return [
+ {
+ id: 'total',
+ title: 'Total Services',
+ value: this.stats.totalServices,
+ type: 'number',
+ icon: 'lucide:server',
+ },
+ {
+ id: 'running',
+ title: 'Running',
+ value: this.stats.running,
+ type: 'number',
+ icon: 'lucide:check',
+ color: '#22c55e',
+ },
+ {
+ id: 'stopped',
+ title: 'Stopped',
+ value: this.stats.stopped,
+ type: 'number',
+ icon: 'lucide:circleStop',
+ color: this.stats.stopped > 0 ? '#f59e0b' : undefined,
+ },
+ {
+ id: 'docker',
+ title: 'Docker',
+ value: this.stats.dockerStatus === 'running' ? 'Running' : 'Stopped',
+ type: 'text',
+ icon: 'lucide:container',
+ color: this.stats.dockerStatus === 'running' ? '#22c55e' : '#ef4444',
+ },
+ ];
+ }
+
public render(): TemplateResult {
return html`
-
`;
}
}
diff --git a/ts_web/elements/sz-tokens-view.ts b/ts_web/elements/sz-tokens-view.ts
index 15fd35f..e1b01b0 100644
--- a/ts_web/elements/sz-tokens-view.ts
+++ b/ts_web/elements/sz-tokens-view.ts
@@ -55,56 +55,94 @@ export class SzTokensView extends DeesElement {
display: block;
}
- .section {
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 8px;
+ dees-tile {
+ display: block;
margin-bottom: 24px;
- overflow: hidden;
}
.section-header {
+ height: 36px;
display: flex;
- justify-content: space-between;
- align-items: flex-start;
- padding: 16px;
- border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
+ align-items: center;
+ padding: 0 16px;
+ width: 100%;
+ box-sizing: border-box;
}
- .section-info {
+ .section-heading {
+ flex: 1;
display: flex;
- flex-direction: column;
- gap: 4px;
+ align-items: baseline;
+ gap: 8px;
+ min-width: 0;
}
.section-title {
- font-size: 16px;
- font-weight: 600;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
+ font-weight: 500;
+ font-size: 13px;
+ letter-spacing: -0.01em;
+ color: var(--dees-color-text-secondary);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.section-subtitle {
- font-size: 13px;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
+ font-size: 12px;
+ color: var(--dees-color-text-muted);
+ letter-spacing: -0.01em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
- .create-button {
- display: inline-flex;
+ .section-footer {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 0;
+ height: 36px;
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ .tile-button {
+ padding: 0 16px;
+ height: 100%;
+ text-align: center;
+ font-size: 12px;
+ font-weight: 500;
+ cursor: pointer;
+ user-select: none;
+ transition: all 0.15s ease;
+ background: transparent;
+ border: none;
+ border-left: 1px solid var(--dees-color-border-subtle);
+ color: var(--dees-color-text-muted);
+ white-space: nowrap;
+ display: flex;
align-items: center;
gap: 6px;
- padding: 8px 14px;
- background: ${cssManager.bdTheme('#18181b', '#fafafa')};
- border: none;
- border-radius: 6px;
- font-size: 13px;
- font-weight: 500;
- color: ${cssManager.bdTheme('#fafafa', '#18181b')};
- cursor: pointer;
- transition: all 200ms ease;
}
- .create-button:hover {
- opacity: 0.9;
+ .tile-button:first-child {
+ border-left: none;
+ }
+
+ .tile-button:hover {
+ background: var(--dees-color-hover);
+ color: var(--dees-color-text-primary);
+ }
+
+ .tile-button.primary {
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
+ font-weight: 600;
+ }
+
+ .tile-button.primary:hover {
+ background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.08)', 'hsl(213.1 93.9% 67.8% / 0.08)')};
+ color: ${cssManager.bdTheme('hsl(217.2 91.2% 50%)', 'hsl(213.1 93.9% 75%)')};
}
.token-list {
@@ -192,45 +230,18 @@ export class SzTokensView extends DeesElement {
.empty-text {
font-size: 14px;
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
- margin-bottom: 16px;
- }
-
- .empty-button {
- display: inline-flex;
- align-items: center;
- gap: 6px;
- padding: 8px 14px;
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 6px;
- font-size: 13px;
- font-weight: 500;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
- cursor: pointer;
- transition: all 200ms ease;
- }
-
- .empty-button:hover {
- background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
}
`,
];
public render(): TemplateResult {
return html`
-
-
+
- Current Password
-
+
+
-
+ this.handleChangePassword()}>Update Password
+
+ Dark Mode
+ Toggle dark mode on or off
-
-
- New Password
-
-
-
- Confirm Password
-
- this.toggleDarkMode()}>
- this.handleReset()}>Reset
- this.handleSave()}>Save Settings
-
+
+
+
+ Cloudflare Integration
+ Configure Cloudflare API for DNS management
+
+
+
+
+
+
+
+ API Token
+ this.updateSetting('cloudflareToken', (e.target as HTMLInputElement).value)}>
+
+
+ Zone ID (Optional)
+ this.updateSetting('cloudflareZoneId', (e.target as HTMLInputElement).value)}>
+ Get your API token from the Cloudflare dashboard with DNS edit permissions.
+
+
+
+ SSL/TLS Settings
+ Configure certificate management
+
+
+
+
+
+
+ Auto-Renew Certificates
+ Automatically renew certificates before expiry
+
+ this.toggleSetting('autoRenewCerts')}>
+
+
+ Renewal Threshold (days)
+ this.updateSetting('renewalThreshold', parseInt((e.target as HTMLInputElement).value))}>
+ Renew certificates when they have fewer than this many days remaining.
+
+
+ ACME Email
+ this.updateSetting('acmeEmail', (e.target as HTMLInputElement).value)}>
+ Email address for Let's Encrypt notifications.
+
+
+
+ Network Settings
+ Configure network and proxy settings
+
+
+
+
+
+
+
+ HTTP Port
+ this.updateSetting('httpPort', parseInt((e.target as HTMLInputElement).value))}>
+
+
+ HTTPS Port
+ this.updateSetting('httpsPort', parseInt((e.target as HTMLInputElement).value))}>
+
+
+
+ Force HTTPS
+ Redirect all HTTP traffic to HTTPS
+
+ this.toggleSetting('forceHttps')}>
+
+
+
+ Account
+ Manage your account settings
+
+
+
+
+
+ Current User
+ ${this.currentUser || 'Unknown'}
+
+
+ Change Password
+
+
+
+
+ Current Password
+
+
+
+ New Password
+
+
+
+ Confirm Password
+
+
+ this.handleChangePassword()}>Update Password
+
+
+ Save your changes or reset to defaults.
+
+
+ this.handleReset()}>Reset
+ this.handleSave()}>Save Settings
+
+
-
-
-
-
-
- `;
-
- public static demoGroups = ['Dashboard'];
-
- @property({ type: String })
- public accessor label: string = '';
-
- @property({ type: String })
- public accessor value: string = '';
-
- @property({ type: String })
- public accessor icon: string = '';
-
- @property({ type: String })
- public accessor variant: 'default' | 'success' | 'warning' | 'error' = 'default';
-
- @property({ type: Boolean })
- public accessor valueBadge: boolean = false;
-
- public static styles = [
- cssManager.defaultStyles,
- css`
- :host {
- display: block;
- height: 100%;
- }
-
- .card {
- background: ${cssManager.bdTheme('#ffffff', '#09090b')};
- border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
- border-radius: 8px;
- padding: 20px;
- transition: all 200ms ease;
- height: 100%;
- box-sizing: border-box;
- }
-
- .card:hover {
- border-color: ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
- box-shadow: 0 4px 12px ${cssManager.bdTheme('rgba(0,0,0,0.05)', 'rgba(0,0,0,0.2)')};
- }
-
- .header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 8px;
- }
-
- .label {
- font-size: 14px;
- font-weight: 500;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
- }
-
- .icon {
- width: 20px;
- height: 20px;
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
- }
-
- .value {
- font-size: 28px;
- font-weight: 700;
- color: ${cssManager.bdTheme('#18181b', '#fafafa')};
- line-height: 1.2;
- }
-
- .value.success {
- color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
- }
-
- .value.warning {
- color: ${cssManager.bdTheme('#ca8a04', '#facc15')};
- }
-
- .value.error {
- color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
- }
-
- .badge {
- display: inline-flex;
- align-items: center;
- padding: 4px 12px;
- border-radius: 9999px;
- font-size: 14px;
- font-weight: 500;
- }
-
- .badge.success {
- background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')};
- color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
- }
-
- .badge.warning {
- background: ${cssManager.bdTheme('#fef9c3', 'rgba(250, 204, 21, 0.2)')};
- color: ${cssManager.bdTheme('#ca8a04', '#facc15')};
- }
-
- .badge.error {
- background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')};
- color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
- }
-
- .badge.default {
- background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
- color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
- }
- `,
- ];
-
- public render(): TemplateResult {
- const valueClass = this.valueBadge ? `badge ${this.variant}` : `value ${this.variant}`;
-
- return html`
-
-
- `;
- }
-
- private renderIcon(): TemplateResult {
- const icons: Record
- ${this.label}
- ${this.renderIcon()}
-
- ${this.value}
-
-
-
-
-
-
+
-
-
-
+
Global Tokens
- Tokens that can push images to multiple services
+
+ this.handleCreate('global')}>
-
- Create Token
-
${this.globalTokens.length > 0 ? html`
+ Global Tokens
+ Tokens that can push images to multiple services
-
@@ -239,25 +250,26 @@ export class SzTokensView extends DeesElement {
` : html`
this.handleCreate('global')}>Create Global Token
`}
-
-
- No global tokens created
-
-
- this.handleCreate('ci')}>
-
-
- CI Tokens (Service-specific)
- Tokens tied to individual services for CI/CD pipelines
-