import * as plugins from '../plugins.js'; import * as appstate from '../appstate.js'; import * as shared from './shared/index.js'; import { DeesElement, customElement, html, state, css, cssManager, type TemplateResult, } from '@design.estate/dees-element'; import { type IStatsTile } from '@design.estate/dees-catalog'; @customElement('objst-view-overview') export class ObjstViewOverview extends DeesElement { @state() accessor serverState: appstate.IServerState = { status: null, connectionInfo: null }; @state() accessor bucketsState: appstate.IBucketsState = { buckets: [] }; constructor() { super(); const serverSub = appstate.serverStatePart .select((s) => s) .subscribe((serverState) => { this.serverState = serverState; }); this.rxSubscriptions.push(serverSub); const bucketsSub = appstate.bucketsStatePart .select((s) => s) .subscribe((bucketsState) => { this.bucketsState = bucketsState; }); this.rxSubscriptions.push(bucketsSub); } async connectedCallback() { super.connectedCallback(); appstate.serverStatePart.dispatchAction(appstate.fetchServerStatusAction, null); appstate.bucketsStatePart.dispatchAction(appstate.fetchBucketsAction, null); } public static styles = [ cssManager.defaultStyles, shared.viewHostCss, css` .connectionInfo { margin-top: 32px; padding: 24px; border-radius: 8px; background: ${cssManager.bdTheme('#f5f5f5', '#1a1a2e')}; border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#2a2a4a')}; } .connectionInfo h2 { margin: 0 0 16px 0; font-size: 18px; font-weight: 600; color: ${cssManager.bdTheme('#333', '#ccc')}; } .connectionInfo .row { display: flex; align-items: center; margin-bottom: 8px; font-size: 14px; } .connectionInfo .label { width: 120px; font-weight: 500; color: ${cssManager.bdTheme('#666', '#999')}; } .connectionInfo .value { font-family: monospace; color: ${cssManager.bdTheme('#333', '#e0e0e0')}; padding: 4px 8px; border-radius: 4px; background: ${cssManager.bdTheme('#e8e8e8', '#252540')}; } `, ]; public render(): TemplateResult { const status = this.serverState.status; const connInfo = this.serverState.connectionInfo; const statsTiles: IStatsTile[] = [ { id: 'status', title: 'Server Status', value: status?.running ? 'Online' : 'Offline', type: 'text', icon: 'lucide:server', color: status?.running ? '#4caf50' : '#f44336', description: status ? `Uptime: ${this.formatUptime(status.uptime)}` : 'Loading...', }, { id: 'buckets', title: 'Buckets', value: status?.bucketCount ?? 0, type: 'number', icon: 'lucide:database', color: '#2196f3', }, { id: 'objects', title: 'Total Objects', value: status?.totalObjectCount ?? 0, type: 'number', icon: 'lucide:file', color: '#ff9800', }, { id: 'storage', title: 'Storage Used', value: status ? this.formatBytes(status.totalStorageBytes) : '0 B', type: 'text', icon: 'lucide:hardDrive', color: '#9c27b0', }, { id: 'storagePort', title: 'Storage Port', value: status?.objstPort ?? 9000, type: 'number', icon: 'lucide:network', color: '#00bcd4', }, { id: 'region', title: 'Region', value: status?.region ?? 'us-east-1', type: 'text', icon: 'lucide:globe', color: '#607d8b', }, ]; return html` Overview { await appstate.serverStatePart.dispatchAction( appstate.fetchServerStatusAction, null, ); await appstate.bucketsStatePart.dispatchAction(appstate.fetchBucketsAction, null); }, }, ]} > ${connInfo ? html`

Connection Info

Endpoint ${connInfo.endpoint}:${connInfo.port}
Protocol ${connInfo.useSsl ? 'HTTPS' : 'HTTP'}
Access Key ${connInfo.accessKey}
Region ${connInfo.region}
` : ''} `; } private formatUptime(seconds: number): string { const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (days > 0) return `${days}d ${hours}h ${minutes}m`; if (hours > 0) return `${hours}h ${minutes}m`; return `${minutes}m`; } private formatBytes(bytes: number): string { if (bytes === 0) return '0 B'; const units = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${units[i]}`; } }