feat(domains): enhance domain management with activation states and sync options
This commit is contained in:
		| @@ -93,6 +93,12 @@ export class CloudlyViewDns extends DeesElement { | ||||
|                   { name: 'Create DNS Entry', action: async (modalArg: any) => { | ||||
|                       const form = modalArg.shadowRoot.querySelector('dees-form') as any; | ||||
|                       const formData = await form.gatherData(); | ||||
|                       // Guard: only allow on activated domains | ||||
|                       const domain = (this.data.domains || []).find((d: any) => d.id === formData.domainId); | ||||
|                       if (!domain || (domain.data as any).activationState !== 'activated') { | ||||
|                         plugins.deesCatalog.DeesToast.createAndShow({ message: 'Selected domain is not activated. Activate it first.', type: 'error' }); | ||||
|                         return; | ||||
|                       } | ||||
|                       await appstate.dataState.dispatchAction(appstate.createDnsEntryAction, { dnsEntryData: { type: formData.type, domainId: formData.domainId, zone: '', name: formData.name || '@', value: formData.value, ttl: parseInt(formData.ttl) || 3600, priority: formData.priority ? parseInt(formData.priority) : undefined, weight: formData.weight ? parseInt(formData.weight) : undefined, port: formData.port ? parseInt(formData.port) : undefined, active: formData.active, description: formData.description || undefined, }, }); | ||||
|                       await modalArg.destroy(); | ||||
|                     } }, | ||||
| @@ -123,6 +129,13 @@ export class CloudlyViewDns extends DeesElement { | ||||
|                   { name: 'Update DNS Entry', action: async (modalArg: any) => { | ||||
|                       const form = modalArg.shadowRoot.querySelector('dees-form') as any; | ||||
|                       const formData = await form.gatherData(); | ||||
|                       if (formData.domainId) { | ||||
|                         const domain = (this.data.domains || []).find((d: any) => d.id === formData.domainId); | ||||
|                         if (!domain || (domain.data as any).activationState !== 'activated') { | ||||
|                           plugins.deesCatalog.DeesToast.createAndShow({ message: 'Selected domain is not activated. Activate it first.', type: 'error' }); | ||||
|                           return; | ||||
|                         } | ||||
|                       } | ||||
|                       await appstate.dataState.dispatchAction(appstate.updateDnsEntryAction, { dnsEntryId: dnsEntry.id, dnsEntryData: { ...dnsEntry.data, type: formData.type, domainId: formData.domainId, zone: '', name: formData.name || '@', value: formData.value, ttl: parseInt(formData.ttl) || 3600, priority: formData.priority ? parseInt(formData.priority) : undefined, weight: formData.weight ? parseInt(formData.weight) : undefined, port: formData.port ? parseInt(formData.port) : undefined, active: formData.active, description: formData.description || undefined, }, }); | ||||
|                       await modalArg.destroy(); | ||||
|                     } }, | ||||
| @@ -140,4 +153,3 @@ export class CloudlyViewDns extends DeesElement { | ||||
| } | ||||
|  | ||||
| declare global { interface HTMLElementTagNameMap { 'cloudly-view-dns': CloudlyViewDns; } } | ||||
|  | ||||
|   | ||||
| @@ -37,6 +37,10 @@ export class CloudlyViewDomains extends DeesElement { | ||||
|       .ssl-expired { color: #f44336; } | ||||
|       .ssl-none { color: #9E9E9E; } | ||||
|       .nameserver-list { font-size: 0.85em; color: #666; } | ||||
|       .activation-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 0.85em; font-weight: 500; } | ||||
|       .activation-available { background: #2b2b2b; color: #bbb; border: 1px solid #444; } | ||||
|       .activation-activated { background: #4CAF50; color: #fff; } | ||||
|       .activation-ignored { background: #9E9E9E; color: #fff; } | ||||
|       .expiry-warning { color: #FF9800; font-weight: 500; } | ||||
|       .expiry-critical { color: #f44336; font-weight: bold; } | ||||
|     `, | ||||
| @@ -45,6 +49,7 @@ export class CloudlyViewDomains extends DeesElement { | ||||
|   private getStatusBadge(status: string) { return html`<span class="status-badge status-${status}">${status.toUpperCase()}</span>`; } | ||||
|   private getVerificationBadge(status: string) { const displayText = status === 'not_required' ? 'Not Required' : status.replace('_', ' ').toUpperCase(); return html`<span class="verification-badge verification-${status}">${displayText}</span>`; } | ||||
|   private getSslBadge(sslStatus?: string) { if (!sslStatus) return html`<span class="ssl-badge ssl-none">—</span>`; const icon = sslStatus === 'active' ? '🔒' : sslStatus === 'expired' ? '⚠️' : '🔓'; return html`<span class="ssl-badge ssl-${sslStatus}">${icon} ${sslStatus.toUpperCase()}</span>`; } | ||||
|   private getActivationBadge(state?: 'available'|'activated'|'ignored') { const s = state || 'available'; return html`<span class="activation-badge activation-${s}">${s.toUpperCase()}</span>`; } | ||||
|   private formatDate(timestamp?: number) { if (!timestamp) return '—'; const date = new Date(timestamp); return date.toLocaleDateString(); } | ||||
|   private getDaysUntilExpiry(expiresAt?: number) { if (!expiresAt) return null; const days = Math.floor((expiresAt - Date.now()) / (1000 * 60 * 60 * 24)); return days; } | ||||
|   private getExpiryDisplay(expiresAt?: number) { const days = this.getDaysUntilExpiry(expiresAt); if (days === null) return '—'; if (days < 0) { return html`<span class="expiry-critical">Expired ${Math.abs(days)} days ago</span>`; } else if (days <= 30) { return html`<span class="expiry-warning">Expires in ${days} days</span>`; } else { return `${days} days`; } } | ||||
| @@ -63,6 +68,7 @@ export class CloudlyViewDomains extends DeesElement { | ||||
|             Status: this.getStatusBadge(itemArg.data.status), | ||||
|             Verification: this.getVerificationBadge(itemArg.data.verificationStatus), | ||||
|             SSL: this.getSslBadge(itemArg.data.sslStatus), | ||||
|             Activation: this.getActivationBadge((itemArg.data as any).activationState), | ||||
|             'DNS Records': dnsCount, | ||||
|             Registrar: itemArg.data.registrar?.name || '—', | ||||
|             Expires: this.getExpiryDisplay(itemArg.data.expiresAt), | ||||
| @@ -71,6 +77,7 @@ export class CloudlyViewDomains extends DeesElement { | ||||
|           }; | ||||
|         }} | ||||
|         .dataActions=${[ | ||||
|           { name: 'Sync from Cloudflare', iconName: 'cloud', type: ['header'], actionFunc: async () => { await appstate.dataState.dispatchAction(appstate.taskActions.triggerTask, { taskName: 'cloudflare-domain-sync' } as any); await appstate.dataState.dispatchAction(appstate.getAllDataAction, null); plugins.deesCatalog.DeesToast.createAndShow({ message: 'Triggered Cloudflare sync', type: 'success' }); } }, | ||||
|           { name: 'Add Domain', iconName: 'plus', type: ['header', 'footer'], actionFunc: async () => { | ||||
|               const modal = await plugins.deesCatalog.DeesModal.createAndShow({ | ||||
|                 heading: 'Add Domain', | ||||
| @@ -164,6 +171,9 @@ export class CloudlyViewDomains extends DeesElement { | ||||
|                 menuOptions: [ { name: 'Cancel', action: async (modalArg: any) => { await modalArg.destroy(); } }, { name: 'Delete', action: async (modalArg: any) => { await appstate.dataState.dispatchAction(appstate.deleteDomainAction, { domainId: domain.id, }); await modalArg.destroy(); } }, ], | ||||
|               }); | ||||
|             } }, | ||||
|           { name: 'Activate', iconName: 'check', type: ['contextmenu', 'inRow'], actionFunc: async (actionDataArg: any) => { const domain = actionDataArg.item as plugins.interfaces.data.IDomain; await appstate.dataState.dispatchAction(appstate.updateDomainAction, { domainId: domain.id, domainData: { ...(domain.data as any), activationState: 'activated' } as any }); } }, | ||||
|           { name: 'Deactivate', iconName: 'slash', type: ['contextmenu', 'inRow'], actionFunc: async (actionDataArg: any) => { const domain = actionDataArg.item as plugins.interfaces.data.IDomain; await appstate.dataState.dispatchAction(appstate.updateDomainAction, { domainId: domain.id, domainData: { ...(domain.data as any), activationState: 'available' } as any }); } }, | ||||
|           { name: 'Ignore', iconName: 'ban', type: ['contextmenu', 'inRow'], actionFunc: async (actionDataArg: any) => { const domain = actionDataArg.item as plugins.interfaces.data.IDomain; await appstate.dataState.dispatchAction(appstate.updateDomainAction, { domainId: domain.id, domainData: { ...(domain.data as any), activationState: 'ignored' } as any }); } }, | ||||
|         ] as plugins.deesCatalog.ITableAction[]} | ||||
|       ></dees-table> | ||||
|     `; | ||||
| @@ -173,4 +183,3 @@ export class CloudlyViewDomains extends DeesElement { | ||||
| declare global { | ||||
|   interface HTMLElementTagNameMap { 'cloudly-view-domains': CloudlyViewDomains; } | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user