import { DeesElement, customElement, html, css, cssManager, property, type TemplateResult, } from '@design.estate/dees-element'; declare global { interface HTMLElementTagNameMap { 'sz-services-list-view': SzServicesListView; } } export interface IService { name: string; image: string; domain: string | null; status: 'running' | 'stopped' | 'starting' | 'error'; } @customElement('sz-services-list-view') export class SzServicesListView extends DeesElement { public static demo = () => html`
`; public static demoGroups = ['Services']; @property({ type: Array }) public accessor services: IService[] = []; public static styles = [ cssManager.defaultStyles, css` :host { display: block; } .table-container { background: ${cssManager.bdTheme('#ffffff', '#09090b')}; border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')}; border-radius: 8px; overflow: hidden; } .table-header { display: grid; grid-template-columns: 1.5fr 2fr 1.5fr 100px 200px; gap: 16px; padding: 12px 16px; background: ${cssManager.bdTheme('#f4f4f5', '#18181b')}; border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')}; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; } .table-row { display: grid; grid-template-columns: 1.5fr 2fr 1.5fr 100px 200px; gap: 16px; padding: 12px 16px; border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#27272a')}; font-size: 14px; color: ${cssManager.bdTheme('#18181b', '#fafafa')}; align-items: center; transition: background 200ms ease; } .table-row:last-child { border-bottom: none; } .table-row:hover { background: ${cssManager.bdTheme('#f4f4f5', '#18181b')}; } .service-name { font-weight: 500; color: ${cssManager.bdTheme('#2563eb', '#60a5fa')}; cursor: pointer; } .service-name:hover { text-decoration: underline; } .image { font-family: monospace; font-size: 13px; color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .domain-link { color: ${cssManager.bdTheme('#2563eb', '#60a5fa')}; text-decoration: none; } .domain-link:hover { text-decoration: underline; } .status-badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 9999px; font-size: 12px; font-weight: 500; } .status-badge.running { background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')}; color: ${cssManager.bdTheme('#16a34a', '#22c55e')}; } .status-badge.stopped { background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')}; color: ${cssManager.bdTheme('#dc2626', '#ef4444')}; } .status-badge.starting { background: ${cssManager.bdTheme('#fef9c3', 'rgba(250, 204, 21, 0.2)')}; color: ${cssManager.bdTheme('#ca8a04', '#facc15')}; } .status-badge.error { background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')}; color: ${cssManager.bdTheme('#dc2626', '#ef4444')}; } .actions { display: flex; gap: 8px; } .action-button { padding: 4px 10px; background: transparent; border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')}; border-radius: 4px; font-size: 12px; cursor: pointer; transition: all 200ms ease; } .action-button:hover { background: ${cssManager.bdTheme('#f4f4f5', '#18181b')}; } .action-button.stop { color: ${cssManager.bdTheme('#ca8a04', '#facc15')}; border-color: ${cssManager.bdTheme('#fef9c3', 'rgba(250, 204, 21, 0.3)')}; } .action-button.start { color: ${cssManager.bdTheme('#16a34a', '#22c55e')}; border-color: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.3)')}; } .action-button.restart { color: ${cssManager.bdTheme('#2563eb', '#60a5fa')}; border-color: ${cssManager.bdTheme('#dbeafe', 'rgba(59, 130, 246, 0.3)')}; } .action-button.delete { color: ${cssManager.bdTheme('#dc2626', '#ef4444')}; border-color: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.3)')}; } .empty-state { padding: 48px 24px; text-align: center; color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; } `, ]; public render(): TemplateResult { return html`
Name Image Domain Status Actions
${this.services.length > 0 ? this.services.map(service => html`
this.handleServiceClick(service)}>${service.name} ${service.image} ${service.domain ? html`${service.domain}` : '-'} ${service.status} ${service.status === 'running' ? html`` : html`` }
`) : html`
No services deployed
`}
`; } private handleServiceClick(service: IService) { this.dispatchEvent(new CustomEvent('service-click', { detail: service, bubbles: true, composed: true })); } private handleAction(service: IService, action: 'start' | 'stop' | 'restart' | 'delete') { this.dispatchEvent(new CustomEvent('service-action', { detail: { service, action }, bubbles: true, composed: true })); } }