import { DeesElement, customElement, html, css, cssManager, property, type TemplateResult, } from '@design.estate/dees-element'; declare global { interface HTMLElementTagNameMap { 'sz-services-backups-view': SzServicesBackupsView; } } export interface IBackupSchedule { id: string; scope: string; retention: string; schedule: string; lastRun?: string; nextRun?: string; status: 'active' | 'failed' | 'disabled'; error?: string; } export interface IBackup { id: string; service: string; createdAt: string; size: string; includes: string[]; } @customElement('sz-services-backups-view') export class SzServicesBackupsView extends DeesElement { public static demo = () => html`
`; public static demoGroups = ['Services']; @property({ type: Array }) public accessor schedules: IBackupSchedule[] = []; @property({ type: Array }) public accessor backups: IBackup[] = []; public static styles = [ cssManager.defaultStyles, css` :host { display: block; } .section { background: ${cssManager.bdTheme('#ffffff', '#09090b')}; border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')}; border-radius: 8px; margin-bottom: 24px; overflow: hidden; } .section-header { display: flex; justify-content: space-between; align-items: flex-start; padding: 16px; border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')}; } .section-info { display: flex; flex-direction: column; gap: 4px; } .section-title { font-size: 16px; font-weight: 600; color: ${cssManager.bdTheme('#18181b', '#fafafa')}; } .section-subtitle { font-size: 13px; color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; } .header-actions { display: flex; gap: 8px; } .action-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; } .action-button:hover { background: ${cssManager.bdTheme('#f4f4f5', '#18181b')}; } .action-button.primary { background: ${cssManager.bdTheme('#18181b', '#fafafa')}; color: ${cssManager.bdTheme('#fafafa', '#18181b')}; border: none; } .action-button.primary:hover { opacity: 0.9; } .table-header { display: grid; 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')}; } .schedules-header { grid-template-columns: 1fr 1fr 1fr 1.5fr 1.5fr 80px 120px; } .backups-header { grid-template-columns: 1.5fr 1.5fr 100px 1fr 120px; } .table-row { display: grid; gap: 16px; padding: 12px 16px; border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#27272a')}; font-size: 14px; color: ${cssManager.bdTheme('#18181b', '#fafafa')}; align-items: center; } .schedules-row { grid-template-columns: 1fr 1fr 1fr 1.5fr 1.5fr 80px 120px; } .backups-row { grid-template-columns: 1.5fr 1.5fr 100px 1fr 120px; } .table-row:last-child { border-bottom: none; } .table-row:hover { background: ${cssManager.bdTheme('#f4f4f5', '#18181b')}; } .status-badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 9999px; font-size: 12px; font-weight: 500; } .status-badge.active { background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')}; color: ${cssManager.bdTheme('#16a34a', '#22c55e')}; } .status-badge.failed { background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')}; color: ${cssManager.bdTheme('#dc2626', '#ef4444')}; } .status-badge.disabled { background: ${cssManager.bdTheme('#f4f4f5', '#27272a')}; color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; } .meta-text { font-size: 13px; color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; } .includes-list { display: flex; flex-wrap: wrap; gap: 4px; } .include-badge { padding: 2px 8px; background: ${cssManager.bdTheme('#dbeafe', 'rgba(59, 130, 246, 0.2)')}; color: ${cssManager.bdTheme('#2563eb', '#60a5fa')}; border-radius: 4px; font-size: 11px; font-weight: 500; } .row-actions { display: flex; gap: 4px; } .icon-button { padding: 6px; background: transparent; border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')}; border-radius: 4px; color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; cursor: pointer; transition: all 200ms ease; } .icon-button:hover { background: ${cssManager.bdTheme('#f4f4f5', '#18181b')}; color: ${cssManager.bdTheme('#18181b', '#fafafa')}; } .icon-button.danger:hover { background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')}; color: ${cssManager.bdTheme('#dc2626', '#ef4444')}; border-color: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.3)')}; } `, ]; public render(): TemplateResult { return html`
Scope Retention Schedule Last Run Next Run Status Actions
${this.schedules.map(schedule => html`
${schedule.scope} ${schedule.retention} ${schedule.schedule} ${schedule.lastRun || '-'} ${schedule.nextRun || '-'} ${schedule.status === 'active' ? 'Active' : schedule.status === 'failed' ? 'Failed' : 'Disabled'}
`)}
Service Created Size Includes Actions
${this.backups.map(backup => html`
${backup.service} ${backup.createdAt} ${backup.size} ${backup.includes.map(inc => html`${inc}`)}
`)}
`; } private handleImport() { this.dispatchEvent(new CustomEvent('import', { bubbles: true, composed: true })); } private handleCreateSchedule() { this.dispatchEvent(new CustomEvent('create-schedule', { bubbles: true, composed: true })); } private handleRunNow(schedule: IBackupSchedule) { this.dispatchEvent(new CustomEvent('run-now', { detail: schedule, bubbles: true, composed: true })); } private handleToggle(schedule: IBackupSchedule) { this.dispatchEvent(new CustomEvent('toggle-schedule', { detail: schedule, bubbles: true, composed: true })); } private handleDeleteSchedule(schedule: IBackupSchedule) { this.dispatchEvent(new CustomEvent('delete-schedule', { detail: schedule, bubbles: true, composed: true })); } private handleDownload(backup: IBackup) { this.dispatchEvent(new CustomEvent('download', { detail: backup, bubbles: true, composed: true })); } private handleDeleteBackup(backup: IBackup) { this.dispatchEvent(new CustomEvent('delete-backup', { detail: backup, bubbles: true, composed: true })); } }