import * as plugins from '../plugins.js'; import * as shared from '../elements/shared/index.js'; import { DeesElement, customElement, html, state, css, cssManager, } from '@design.estate/dees-element'; import * as appstate from '../appstate.js'; @customElement('cloudly-view-dns') export class CloudlyViewDns extends DeesElement { @state() private data: appstate.IDataState = { secretGroups: [], secretBundles: [], dnsEntries: [], domains: [], }; constructor() { super(); const subscription = appstate.dataState .select((stateArg) => stateArg) .subscribe((dataArg) => { this.data = dataArg; }); this.rxSubscriptions.push(subscription); } async connectedCallback() { super.connectedCallback(); // Load all data including domains and DNS entries await appstate.dataState.dispatchAction(appstate.getAllDataAction, {}); } public static styles = [ cssManager.defaultStyles, shared.viewHostCss, css` .dns-type-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 0.85em; font-weight: 500; color: white; } .type-A { background: #4CAF50; } .type-AAAA { background: #45a049; } .type-CNAME { background: #2196F3; } .type-MX { background: #FF9800; } .type-TXT { background: #9C27B0; } .type-NS { background: #795548; } .type-SOA { background: #607D8B; } .type-SRV { background: #E91E63; } .type-CAA { background: #00BCD4; } .type-PTR { background: #673AB7; } .status-active { color: #4CAF50; } .status-inactive { color: #f44336; } `, ]; private getRecordTypeBadge(type: string) { return html`${type}`; } private getStatusBadge(active: boolean) { return html` ${active ? '✓ Active' : '✗ Inactive'} `; } public render() { return html` DNS Management { return { Type: this.getRecordTypeBadge(itemArg.data.type), Name: itemArg.data.name === '@' ? '' : itemArg.data.name, Value: itemArg.data.value, TTL: `${itemArg.data.ttl}s`, Priority: itemArg.data.priority || '-', Zone: itemArg.data.zone, Status: this.getStatusBadge(itemArg.data.active), Description: itemArg.data.description || '-', }; }} .dataActions=${[ { name: 'Add DNS Entry', iconName: 'plus', type: ['header', 'footer'], actionFunc: async (dataActionArg) => { const modal = await plugins.deesCatalog.DeesModal.createAndShow({ heading: 'Add DNS Entry', content: html` ({ key: domain.id, option: domain.data.name })) || []} .required=${true}> `, menuOptions: [ { name: 'Create DNS Entry', action: async (modalArg) => { const form = modalArg.shadowRoot.querySelector('dees-form') as any; const formData = await form.gatherData(); await appstate.dataState.dispatchAction(appstate.createDnsEntryAction, { dnsEntryData: { type: formData.type, domainId: formData.domainId, zone: '', // Will be set by backend from domain 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(); }, }, { name: 'Cancel', action: async (modalArg) => { modalArg.destroy(); }, }, ], }); }, }, { name: 'Edit', iconName: 'edit', type: ['contextmenu', 'inRow'], actionFunc: async (actionDataArg) => { const dnsEntry = actionDataArg.item as plugins.interfaces.data.IDnsEntry; const modal = await plugins.deesCatalog.DeesModal.createAndShow({ heading: `Edit DNS Entry`, content: html` ({ key: domain.id, option: domain.data.name })) || []} .value=${dnsEntry.data.domainId || ''} .required=${true}> `, menuOptions: [ { name: 'Update DNS Entry', action: async (modalArg) => { const form = modalArg.shadowRoot.querySelector('dees-form') as any; const formData = await form.gatherData(); await appstate.dataState.dispatchAction(appstate.updateDnsEntryAction, { dnsEntryId: dnsEntry.id, dnsEntryData: { ...dnsEntry.data, type: formData.type, domainId: formData.domainId, zone: '', // Will be set by backend from domain 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(); }, }, { name: 'Cancel', action: async (modalArg) => { modalArg.destroy(); }, }, ], }); }, }, { name: 'Duplicate', iconName: 'copy', type: ['contextmenu', 'inRow'], actionFunc: async (actionDataArg) => { const dnsEntry = actionDataArg.item as plugins.interfaces.data.IDnsEntry; await appstate.dataState.dispatchAction(appstate.createDnsEntryAction, { dnsEntryData: { ...dnsEntry.data, description: `Copy of ${dnsEntry.data.description || dnsEntry.data.name}`, }, }); }, }, { name: 'Toggle Active', iconName: 'power', type: ['contextmenu', 'inRow'], actionFunc: async (actionDataArg) => { const dnsEntry = actionDataArg.item as plugins.interfaces.data.IDnsEntry; await appstate.dataState.dispatchAction(appstate.updateDnsEntryAction, { dnsEntryId: dnsEntry.id, dnsEntryData: { ...dnsEntry.data, active: !dnsEntry.data.active, }, }); }, }, { name: 'Delete', iconName: 'trash', type: ['contextmenu', 'inRow'], actionFunc: async (actionDataArg) => { const dnsEntry = actionDataArg.item as plugins.interfaces.data.IDnsEntry; plugins.deesCatalog.DeesModal.createAndShow({ heading: `Delete DNS Entry`, content: html`
Are you sure you want to delete this DNS entry?
${dnsEntry.data.type} - ${dnsEntry.data.name}.${dnsEntry.data.zone}
${dnsEntry.data.value}
${dnsEntry.data.description ? html`
${dnsEntry.data.description}
` : ''}
`, menuOptions: [ { name: 'Cancel', action: async (modalArg) => { await modalArg.destroy(); }, }, { name: 'Delete', action: async (modalArg) => { await appstate.dataState.dispatchAction(appstate.deleteDnsEntryAction, { dnsEntryId: dnsEntry.id, }); await modalArg.destroy(); }, }, ], }); }, }, ] as plugins.deesCatalog.ITableAction[]} >
`; } }