feat(dns): add domain migration between dcrouter and provider-managed DNS with unified ACME managed-domain handling
This commit is contained in:
@@ -149,6 +149,15 @@ export class OpsViewDomains extends DeesElement {
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Migrate',
|
||||
iconName: 'lucide:arrow-right-left',
|
||||
type: ['inRow', 'contextmenu'] as any,
|
||||
actionFunc: async (actionData: any) => {
|
||||
const domain = actionData.item as interfaces.data.IDomain;
|
||||
await this.showMigrateDialog(domain);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
iconName: 'lucide:trash2',
|
||||
@@ -308,6 +317,96 @@ export class OpsViewDomains extends DeesElement {
|
||||
});
|
||||
}
|
||||
|
||||
private async showMigrateDialog(domain: interfaces.data.IDomain) {
|
||||
const { DeesModal, DeesToast } = await import('@design.estate/dees-catalog');
|
||||
const providers = this.domainsState.providers;
|
||||
|
||||
// Build target options based on current source
|
||||
const targetOptions: { option: string; key: string }[] = [];
|
||||
if (domain.source === 'provider') {
|
||||
targetOptions.push({ option: 'DcRouter (authoritative)', key: 'dcrouter' });
|
||||
}
|
||||
// Add all providers (except the current one if already provider-managed)
|
||||
for (const p of providers) {
|
||||
if (domain.source === 'provider' && domain.providerId === p.id) continue;
|
||||
targetOptions.push({ option: `${p.name} (${p.type})`, key: `provider:${p.id}` });
|
||||
}
|
||||
if (domain.source === 'dcrouter') {
|
||||
targetOptions.unshift({ option: 'DcRouter (authoritative)', key: 'dcrouter' });
|
||||
}
|
||||
|
||||
if (targetOptions.length === 0) {
|
||||
DeesToast.show({
|
||||
message: 'No migration targets available. Add a DNS provider first.',
|
||||
type: 'warning',
|
||||
duration: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const currentLabel = domain.source === 'dcrouter'
|
||||
? 'DcRouter (authoritative)'
|
||||
: providers.find((p) => p.id === domain.providerId)?.name || 'Provider';
|
||||
|
||||
DeesModal.createAndShow({
|
||||
heading: `Migrate: ${domain.name}`,
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text
|
||||
.key=${'currentSource'}
|
||||
.label=${'Current source'}
|
||||
.value=${currentLabel}
|
||||
.disabled=${true}
|
||||
></dees-input-text>
|
||||
<dees-input-dropdown
|
||||
.key=${'target'}
|
||||
.label=${'Migrate to'}
|
||||
.description=${'Select the target DNS management'}
|
||||
.options=${targetOptions}
|
||||
.required=${true}
|
||||
></dees-input-dropdown>
|
||||
<dees-input-checkbox
|
||||
.key=${'deleteExisting'}
|
||||
.label=${'Delete existing records at provider first'}
|
||||
.description=${'Removes all records at the provider before pushing migrated records'}
|
||||
.value=${true}
|
||||
></dees-input-checkbox>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'Cancel', action: async (m: any) => m.destroy() },
|
||||
{
|
||||
name: 'Migrate',
|
||||
action: async (m: any) => {
|
||||
const form = m.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
|
||||
if (!form) return;
|
||||
const data = await form.collectFormData();
|
||||
const targetKey = typeof data.target === 'object' ? data.target.key : data.target;
|
||||
if (!targetKey) return;
|
||||
|
||||
let targetSource: interfaces.data.TDomainSource;
|
||||
let targetProviderId: string | undefined;
|
||||
if (targetKey === 'dcrouter') {
|
||||
targetSource = 'dcrouter';
|
||||
} else {
|
||||
targetSource = 'provider';
|
||||
targetProviderId = targetKey.replace('provider:', '');
|
||||
}
|
||||
|
||||
await appstate.domainsStatePart.dispatchAction(appstate.migrateDomainAction, {
|
||||
id: domain.id,
|
||||
targetSource,
|
||||
targetProviderId,
|
||||
deleteExistingProviderRecords: targetSource === 'provider' ? Boolean(data.deleteExisting) : false,
|
||||
});
|
||||
DeesToast.show({ message: `Domain ${domain.name} migrated successfully`, type: 'success', duration: 3000 });
|
||||
m.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
private async deleteDomain(domain: interfaces.data.IDomain) {
|
||||
const { DeesModal } = await import('@design.estate/dees-catalog');
|
||||
DeesModal.createAndShow({
|
||||
|
||||
Reference in New Issue
Block a user