continue UI component work, fix minor issue with apis

This commit is contained in:
Manoj Kumar 2026-03-17 19:33:30 +05:30
parent c74a579b86
commit 7f5e2a7d30
No known key found for this signature in database
GPG Key ID: E952B7234D2C6F88
12 changed files with 275 additions and 76 deletions

View File

@ -63,7 +63,7 @@ public class CreateDnsZoneCmd extends BaseAsyncCreateCmd {
description = "The type of zone (Public, Private). Defaults to Public.")
private String type;
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Display text for the zone")
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "The description of the DNS zone")
private String description;
/////////////////////////////////////////////////////

View File

@ -27,6 +27,7 @@ import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.DnsServerResponse;
import org.apache.cloudstack.api.response.DnsZoneResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.dns.DnsServer;
@ -51,6 +52,10 @@ public class DeleteDnsServerCmd extends BaseAsyncCmd {
required = true, description = "the ID of the DNS server")
private Long id;
@Parameter(name = ApiConstants.CLEANUP, type = CommandType.BOOLEAN,
entityType = DnsZoneResponse.class, description = "True if all associated DNS zones have to be cleaned up with this server")
private Boolean cleanup;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -93,4 +98,8 @@ public class DeleteDnsServerCmd extends BaseAsyncCmd {
@Override
public String getEventDescription() { return "Deleting DNS server ID: " + getId(); }
public Boolean getCleanup() {
return Boolean.TRUE.equals(cleanup);
}
}

View File

@ -45,7 +45,7 @@ public class UpdateDnsZoneCmd extends BaseCmd {
required = true, description = "The ID of the DNS zone")
private Long id;
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Display text for the zone")
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "The description of the DNS zone to be updated")
private String description;
/////////////////////////////////////////////////////

View File

@ -40,6 +40,7 @@ import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
@ -185,8 +186,8 @@ public class PowerDnsClient implements AutoCloseable {
nsArray.add(ns.endsWith(".") ? ns : ns + ".");
}
}
HttpPatch request = new HttpPatch(url);
request.setEntity(new org.apache.http.entity.StringEntity(json.toString(), StandardCharsets.UTF_8));
HttpPut request = new HttpPut(url);
request.setEntity(new StringEntity(json.toString(), StandardCharsets.UTF_8));
execute(request, apiKey, 204);
}
@ -221,7 +222,7 @@ public class PowerDnsClient implements AutoCloseable {
}
String encodedZone = URLEncoder.encode(normalizedZone, StandardCharsets.UTF_8);
HttpPatch request = new HttpPatch(buildUrl(baseUrl, port, "/servers/" + externalServerId + "/zones/" + encodedZone));
request.setEntity(new org.apache.http.entity.StringEntity(root.toString(), StandardCharsets.UTF_8));
request.setEntity(new StringEntity(root.toString(), StandardCharsets.UTF_8));
execute(request, apiKey, 204);
return normalizedRecord.endsWith(".") ? normalizedRecord.substring(0, normalizedRecord.length() - 1) : normalizedRecord;
}

View File

@ -51,7 +51,9 @@ import org.apache.cloudstack.dns.dao.DnsServerJoinDao;
import org.apache.cloudstack.dns.dao.DnsZoneDao;
import org.apache.cloudstack.dns.dao.DnsZoneJoinDao;
import org.apache.cloudstack.dns.dao.DnsZoneNetworkMapDao;
import org.apache.cloudstack.dns.exception.DnsConflictException;
import org.apache.cloudstack.dns.exception.DnsNotFoundException;
import org.apache.cloudstack.dns.exception.DnsTransportException;
import org.apache.cloudstack.dns.vo.DnsServerJoinVO;
import org.apache.cloudstack.dns.vo.DnsServerVO;
import org.apache.cloudstack.dns.vo.DnsZoneJoinVO;
@ -176,18 +178,10 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
}
private Pair<List<DnsServerVO>, Integer> searchForDnsServerInternal(ListDnsServersCmd cmd) {
Long dnsServerId = cmd.getId();
Account caller = CallContext.current().getCallingAccount();
if (dnsServerId != null) {
DnsServerVO dnsServerVO = dnsServerDao.findById(dnsServerId);
if (dnsServerVO == null) {
return null;
}
return new Pair<>(Collections.singletonList(dnsServerVO), 1);
}
Set<Long> parentDomainIds = domainDao.getDomainParentIds(caller.getDomainId());
Filter searchFilter = new Filter(DnsServerVO.class, ApiConstants.ID, true, cmd.getStartIndex(), cmd.getPageSizeVal());
return dnsServerDao.searchDnsServer(dnsServerId, caller.getAccountId(), parentDomainIds, cmd.getProviderType(), cmd.getKeyword(), searchFilter);
return dnsServerDao.searchDnsServer(cmd.getId(), caller.getAccountId(), parentDomainIds, cmd.getProviderType(), cmd.getKeyword(), searchFilter);
}
@Override
@ -272,6 +266,9 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
}
Account caller = CallContext.current().getCallingAccount();
accountMgr.checkAccess(caller, dnsServer);
if (cmd.getCleanup()) {
// ToDo cleanup associated dnsZones
}
return dnsServerDao.remove(dnsServerId);
}
@ -322,6 +319,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
try {
DnsProvider provider = getProviderByType(server.getProviderType());
provider.updateZone(server, dnsZone);
dnsZoneDao.update(dnsZone.getId(), dnsZone);
} catch (Exception ex) {
logger.error("Failed to update DNS zone: {} on DNS server: {}", dnsZone.getName(), server.getName(), ex);
throw new CloudRuntimeException("Failed to update DNS zone: " + dnsZone.getName());
@ -375,20 +373,23 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
if (StringUtils.isBlank(recordName)) {
throw new InvalidParameterValueException("Empty DNS record name is not allowed");
}
DnsZoneVO zone = dnsZoneDao.findById(cmd.getDnsZoneId());
if (zone == null) {
DnsZoneVO dnsZone = dnsZoneDao.findById(cmd.getDnsZoneId());
if (dnsZone == null) {
throw new InvalidParameterValueException("DNS zone not found.");
}
Account caller = CallContext.current().getCallingAccount();
accountMgr.checkAccess(caller, null, true, zone);
DnsServerVO server = dnsServerDao.findById(zone.getDnsServerId());
accountMgr.checkAccess(caller, null, true, dnsZone);
DnsServerVO server = dnsServerDao.findById(dnsZone.getDnsServerId());
if (server == null) {
throw new CloudRuntimeException("The underlying DNS server for this DNS zone is missing.");
}
try {
DnsRecord.RecordType type = cmd.getType();
List<String> normalizedContents = cmd.getContents().stream()
.map(value -> DnsProviderUtil.normalizeDnsRecordValue(value, type)).collect(Collectors.toList());
DnsRecord record = new DnsRecord(recordName, type, normalizedContents, cmd.getTtl());
DnsProvider provider = getProviderByType(server.getProviderType());
String normalizedRecordName = provider.addRecord(server, zone, record);
String normalizedRecordName = provider.addRecord(server, dnsZone, record);
record.setName(normalizedRecordName);
return createDnsRecordResponse(record);
} catch (Exception ex) {
@ -507,7 +508,13 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
} catch (Exception ex) {
dnsZoneDao.remove(dnsZoneId);
logger.error("Failed to provision DNS zone: {} on DNS server: {}", dnsZone.getName(), server.getName(), ex);
throw new CloudRuntimeException("Failed to provision DNS zone: " + dnsZone.getName());
String errorMsg = "";
if ( ex instanceof DnsConflictException) {
errorMsg = String.format("DNS zone: %s already exists", dnsZone.getName());
} else if (ex instanceof DnsTransportException){
errorMsg = String.format("DNS server: %s not reachable", server.getName());
}
throw new CloudRuntimeException(errorMsg);
}
return dnsZone;
}
@ -562,6 +569,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
res.setName(record.getName());
res.setType(record.getType());
res.setContent(record.getContents());
res.setTtl(record.getTtl());
return res;
}

View File

@ -716,6 +716,7 @@
"label.create.webhook": "Create Webhook",
"label.created": "Created",
"label.creating": "Creating",
"label.creating.dns.zone": "Creating DNS zone",
"label.creating.iprange": "Creating IP ranges",
"label.nameservers": "DNS Nameservers",
"label.credit": "Credit",
@ -941,12 +942,14 @@
"label.dns": "DNS",
"label.dns1": "DNS 1",
"label.dns2": "DNS 2",
"label.dns.add.record": "Add DNS Record",
"label.dns.create.record": "Create DNS Record",
"label.dns.add.server": "Add DNS Server",
"label.dns.add.zone": "Add DNS Zone",
"label.dns.create.zone": "Create DNS Zone",
"label.dns.credentials": "DNS API key",
"label.dns.delete.server": "Delete DNS Server",
"label.dns.delete.zone": "Delete DNS Zone",
"label.dns.externalserverid": "DNS server ID",
"label.dns.publicdomainsuffix": "Public domain suffix",
"label.dns.records": "DNS Records",
"label.dns.record.name.tooltip": "The hostname or subdomain for this record (e.g. www)",
"label.dns.record.type.tooltip": "The DNS record type",
@ -954,6 +957,7 @@
"label.dns.record.ttl.tooltip": "Time to live in seconds",
"label.dns.record.url": "Instance URL",
"label.dns.server": "DNS Server",
"label.dnsserverid": "DNS Server ID",
"label.dnsservername": "DNS Server name",
"label.dns.servers": "DNS Servers",
"label.dns.zone": "DNS Zone",
@ -2252,6 +2256,7 @@
"label.scope": "Scope",
"label.scope.tooltip": "Primary Storage Pool Scope",
"label.search": "Search",
"label.seconds": "Seconds",
"label.secondary.isolated.vlan.type.isolated": "Isolated",
"label.secondary.isolated.vlan.type.promiscuous": "Promiscuous",
"label.secondary.storage": "Secondary Storage",
@ -3540,6 +3545,7 @@
"message.error.remove.tungsten.routing.policy": "Removing Tungsten-Fabric Routing Policy from Network failed",
"message.error.remove.vm.schedule": "Removing Instance Schedule failed",
"message.error.required.input": "Please enter input",
"message.error.required.publicdomainsuffix": "Please enter the public domain suffix if the public server is enabled",
"message.error.reset.config": "Unable to reset config to default value",
"message.error.retrieve.kubeconfig": "Unable to retrieve Kubernetes Cluster config",
"message.error.routing.policy.term": "Community need to have the following format number:number",
@ -3884,10 +3890,10 @@
"message.success.add.egress.rule": "Successfully added new egress rule",
"message.success.add.firewall.rule": "Successfully added new firewall rule",
"message.success.add.dns.server": "Successfully added DNS server",
"message.success.add.dns.zone": "Successfully added DNS zone",
"message.success.create.dns.zone": "Successfully created DNS zone",
"message.success.create.dns.record": "Successfully created DNS record",
"message.success.update.dns.server": "Successfully updated DNS server",
"message.success.update.dns.zone": "Successfully updated DNS zone",
"message.success.add.dns.record": "Successfully added DNS record",
"message.success.delete.dns.record": "Successfully deleted DNS record",
"message.success.add.guest.network": "Successfully created guest Network",
"message.success.add.gpu.device": "Successfully added GPU device",

View File

@ -1522,8 +1522,7 @@ export default {
label: 'label.dns.update.server',
dataView: true,
popup: true,
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/UpdateDnsServer.vue'))),
show: (record) => { return true }
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/UpdateDnsServer.vue')))
},
{
api: 'deleteDnsServer',
@ -1531,8 +1530,8 @@ export default {
label: 'label.dns.delete.server',
message: 'message.action.delete.dns.server',
dataView: true,
groupAction: true,
show: (record) => { return true },
popup: true,
groupAction: false,
groupMap: (selection) => { return selection.map(x => { return { id: x } }) }
}
]
@ -1542,8 +1541,8 @@ export default {
title: 'label.dns.zones',
icon: 'global-outlined',
permission: ['listDnsZones'],
columns: ['name', 'state', 'dnsservername', 'account'],
details: ['name', 'id', 'state', 'dnsservername', 'dnsserverid', 'account', 'domainpath'],
columns: ['name', 'state', 'dnsservername', 'account', 'description'],
details: ['name', 'id', 'state', 'dnsservername', 'dnsserverid', 'account', 'domainpath', 'description'],
tabs: [{
name: 'details',
component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue')))
@ -1557,11 +1556,10 @@ export default {
{
api: 'createDnsZone',
icon: 'plus-outlined',
label: 'label.dns.add.zone',
label: 'label.dns.create.zone',
listView: true,
popup: true,
disabled: (record) => false,
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/AddDnsZone.vue'))),
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/CreateDnsZone.vue'))),
show: () => {
return true
}
@ -1572,7 +1570,6 @@ export default {
label: 'label.dns.update.zone',
dataView: true,
popup: true,
disabled: (record) => false,
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/UpdateDnsZone.vue'))),
show: (record) => { return true }
},
@ -1582,7 +1579,8 @@ export default {
label: 'label.dns.delete.zone',
message: 'message.action.delete.dns.zone',
dataView: true,
groupAction: true,
popup: true,
groupAction: false,
disabled: (record) => false,
show: (record) => { return true },
groupMap: (selection) => { return selection.map(x => { return { id: x } }) }

View File

@ -91,6 +91,28 @@
:placeholder="apiParams.credentials?.description || 'Enter API Key'" />
</a-form-item>
<a-form-item name="externalserverid" ref="externalserverid">
<template #label>
<tooltip-label
:title="$t('label.dns.externalserverid')"
:tooltip="apiParams.externalserverid?.description" />
</template>
<a-input
v-model:value="form.externalserverid"
:placeholder="apiParams.externalserverid?.description || 'Enter Server ID of PowerDNS e.g. localhost'" />
</a-form-item>
<a-form-item name="publicdomainsuffix" ref="publicdomainsuffix">
<template #label>
<tooltip-label
:title="$t('label.dns.publicdomainsuffix')"
:tooltip="apiParams.publicdomainsuffix?.description" />
</template>
<a-input
v-model:value="form.publicdomainsuffix"
:placeholder="apiParams.publicdomainsuffix?.description || 'Enter Public Domain Suffix e.g. example.com'" />
</a-form-item>
<a-form-item name="nameservers" ref="nameservers">
<template #label>
<tooltip-label
@ -103,7 +125,7 @@
mode="tags"
style="width: 100%"
:token-separators="[',', ' ']"
:placeholder="apiParams.nameservers?.description || 'ns1.example.com, ns2.example.com'" />
:placeholder="apiParams.nameservers?.description" />
</a-form-item>
<a-form-item name="ispublic" ref="ispublic">
@ -146,8 +168,10 @@ export default {
url: '',
provider: '',
port: 8081,
nameservers: '',
ispublic: false
nameservers: [],
ispublic: false,
publicdomainsuffix: '',
externalserverid: 'localhost'
},
rules: {},
fetchingProviders: false,
@ -158,9 +182,22 @@ export default {
this.apiParams = this.$getApiParams('addDnsServer') || {}
this.rules = {
name: [{ required: true, message: this.$t('message.error.required.input') }],
url: [{ required: true, message: this.$t('message.error.required.input') }],
url: [
{ required: true, message: this.$t('message.error.required.input') },
{ validator: this.validateUrl }
],
port: [
{ required: true, message: this.$t('message.error.required.input') },
{ validator: this.validatePort }
],
provider: [{ required: true, message: this.$t('message.error.required.input') }],
credentials: [{ required: true, message: this.$t('message.error.required.input') }]
credentials: [{ required: true, message: this.$t('message.error.required.input') }],
externalserverid: [{ required: true, message: this.$t('message.error.required.input') }],
nameservers: [
{ required: true, type: 'array', min: 1, message: this.$t('message.error.required.input') },
{ validator: this.validateNameservers }
],
publicdomainsuffix: [{ validator: this.validatePublicDomainSuffix }]
}
this.fetchProviders()
},
@ -177,9 +214,22 @@ export default {
}
this.loading = true
try {
await postAPI('addDnsServer', this.form)
const params = {
name: this.form.name.trim(),
url: this.form.url?.trim().replace(/\/$/, ''),
port: this.form.port,
provider: this.form.provider,
credentials: this.form.credentials,
externalserverid: this.form.externalserverid.trim(),
nameservers: this.form.nameservers?.map(ns => ns.toLowerCase().trim()).filter(Boolean),
ispublic: this.form.ispublic
}
if (this.form.ispublic) {
params.publicdomainsuffix = this.form.publicdomainsuffix?.trim().toLowerCase()
}
await postAPI('addDnsServer', params)
this.$notification.success({
message: this.$t('label.add.dns.server'),
message: this.$t('label.dns.add.server'),
description: this.$t('message.success.add.dns.server')
})
this.$emit('refresh-data')
@ -213,6 +263,68 @@ export default {
} finally {
this.fetchingProviders = false
}
},
validateUrl (rule, value) {
if (!value) return Promise.resolve()
try {
const parsed = new URL(value)
if (!['http:', 'https:'].includes(parsed.protocol)) {
return Promise.reject(new Error('URL must start with http:// or https://'))
}
if (parsed.port) {
return Promise.reject(new Error('Do not include port in URL. Use the port field instead.'))
}
} catch (e) {
return Promise.reject(new Error('Invalid URL format'))
}
return Promise.resolve()
},
validatePort (rule, value) {
if (value === undefined || value === null) {
return Promise.resolve()
}
if (value < 1 || value > 65535) {
return Promise.reject(new Error('Port must be between 1 and 65535'))
}
return Promise.resolve()
},
validateNameservers (rule, value) {
if (!value || !value.length) {
return Promise.resolve()
}
const fqdnRegex = /^(?=.{1,253}$)(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z]{2,})+$/
for (const ns of value) {
if (!fqdnRegex.test(ns)) {
return Promise.reject(new Error('Invalid nameserver'))
}
}
if (new Set(value).size !== value.length) {
return Promise.reject(new Error('Nameservers must be unique'))
}
return Promise.resolve()
},
validatePublicDomainSuffix (rule, value) {
if (!this.form.ispublic) {
return Promise.resolve()
}
if (!value) {
return Promise.reject(new Error(this.$t('message.error.required.publicdomainsuffix')))
}
const fqdnRegex = /^(?=.{1,253}$)(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z]{2,})+$/
if (!fqdnRegex.test(value)) {
return Promise.reject(new Error('Invalid domain suffix'))
}
return Promise.resolve()
}
}
}

View File

@ -103,7 +103,7 @@ import { postAPI } from '@/api'
import TooltipLabel from '@/components/widgets/TooltipLabel'
export default {
name: 'AddDnsRecord',
name: 'CreateDnsRecord',
components: {
TooltipLabel
},
@ -147,13 +147,35 @@ export default {
}
this.loading = true
try {
await postAPI('addDnsRecord', {
const params = {
dnszoneid: this.resource.id,
...this.form
})
this.$notification.success({
message: this.$t('label.dns.add.record'),
description: this.$t('message.success.add.dns.record')
name: this.form.name,
type: this.form.type,
contents: this.form.contents.join(','),
ttl: this.form.ttl
}
const response = await postAPI('createDnsRecord', params)
const jobId = response.creatednsrecordresponse.jobid
if (!jobId) {
this.$notification.error({
message: this.$t('message.request.failed'),
description: 'Failed to get jobid for createDnsRecord',
duration: 0
})
}
await this.$pollJob({
jobId: jobId,
title: this.$t('label.dns.create.record'),
description: this.$t('label.creating.dns.record'),
successMethod: () => {
this.$notification.success({
message: this.$t('label.dns.create.record'),
description: this.$t('message.success.create.dns.record')
})
},
loadingMessage: `${this.$t('label.dns.create.record')} ${this.$t('label.in.progress')}`,
catchMessage: this.$t('error.fetching.async.job.result'),
action: { isFetchData: false }
})
this.$emit('refresh-data')
this.closeAction()

View File

@ -58,6 +58,15 @@
</a-select>
</a-form-item>
<a-form-item name="description" ref="description">
<template #label>
<tooltip-label :title="$t('label.description')" :tooltip="apiParams.description.description"/>
</template>
<a-input
v-model:value="form.description"
:placeholder="apiParams.description.description"/>
</a-form-item>
<div class="action-button">
<a-button @click="closeAction">
{{ $t('label.cancel') }}
@ -79,7 +88,7 @@ import { getAPI, postAPI } from '@/api'
import TooltipLabel from '@/components/widgets/TooltipLabel'
export default {
name: 'AddDnsZone',
name: 'CreateDnsZone',
components: {
TooltipLabel
},
@ -89,7 +98,8 @@ export default {
apiParams: {},
form: {
name: '',
dnsserverid: undefined
dnsserverid: undefined,
description: ''
},
rules: {},
fetchingServers: false,
@ -121,10 +131,34 @@ export default {
this.loading = true
try {
await postAPI('createDnsZone', this.form)
this.$notification.success({
message: this.$t('label.dns.add.zone'),
description: this.$t('message.success.add.dns.zone')
const params = {
name: this.form.name.trim(),
dnsserverid: this.form.dnsserverid,
description: this.form.description?.trim()
}
const response = await postAPI('createDnsZone', params)
const jobId = response.creatednszoneresponse.jobid
if (!jobId) {
this.$notification.error({
message: this.$t('message.request.failed'),
description: 'Failed to get jobid for CreateDnsZone',
duration: 0
})
}
await this.$pollJob({
jobId: jobId,
title: this.$t('label.dns.create.zone'),
description: this.$t('label.creating.dns.zone'),
successMethod: () => {
this.$notification.success({
message: this.$t('label.dns.create.zone'),
description: this.$t('message.success.create.dns.zone')
})
},
loadingMessage: `${this.$t('label.dns.create.zone')} ${this.$t('label.in.progress')}`,
catchMessage: this.$t('error.fetching.async.job.result'),
action: { isFetchData: false }
})
this.$emit('refresh-data')
this.closeAction()

View File

@ -22,8 +22,9 @@
shape="round"
style="float: right;margin-bottom: 10px; z-index: 8"
@click="() => { showAddForm = true }">
<template #icon><plus-outlined /></template>
{{ $t('label.dns.add.record') }}
<!-- <template #icon><plus-outlined /></template> -->
{{ $t('label.dns.create.record') }}
<plus-outlined style="margin-left: 5px;" />
</a-button>
<br />
<br />
@ -40,7 +41,10 @@
<template v-if="column.dataIndex === 'contents'">
<a-tag v-for="item in record.contents" :key="item">{{ item }}</a-tag>
</template>
<template v-if="column.key === 'actions'">
<template v-if="column.dataIndex === 'ttl'">
{{ record.ttl }}
</template>
<template v-if="column.key === 'actions' && record.type !== 'NS'">
<a-popconfirm
:title="$t('message.confirm.delete.dns.record')"
@confirm="handleDeleteRecord(record)"
@ -79,14 +83,14 @@
<a-modal
v-if="showAddForm"
:visible="showAddForm"
:title="$t('label.dns.add.record')"
:title="$t('label.dns.create.record')"
:maskClosable="false"
:closable="true"
:footer="null"
@cancel="() => { showAddForm = false }"
centered
width="auto">
<AddDnsRecord
<CreateDnsRecord
:resource="resource"
@refresh-data="fetchData"
@close-action="showAddForm = false" />
@ -97,13 +101,13 @@
<script>
import { getAPI, postAPI } from '@/api'
import TooltipButton from '@/components/widgets/TooltipButton'
import AddDnsRecord from '@/views/network/dns/AddDnsRecord'
import CreateDnsRecord from '@/views/network/dns/CreateDnsRecord'
export default {
name: 'DnsRecordsTab',
components: {
TooltipButton,
AddDnsRecord
CreateDnsRecord
},
props: {
resource: {
@ -137,7 +141,7 @@ export default {
dataIndex: 'contents'
},
{
title: this.$t('label.ttl'),
title: this.$t('label.ttl') + ' (' + this.$t('label.seconds') + ')',
dataIndex: 'ttl'
},
{
@ -180,7 +184,16 @@ export default {
})
},
handleDeleteRecord (record) {
postAPI('deleteDnsRecord', { id: record.id }).then(() => {
const params = {
dnszoneid: this.resource.id,
name: record.name,
type: record.type,
contents: record.contents.join(','),
ttl: record.ttl
}
console.log('DeleteDnsRecord params', params)
postAPI('deleteDnsRecord', params).then(() => {
this.$notification.success({
message: this.$t('message.success.delete.dns.record')
})

View File

@ -24,15 +24,15 @@
:rules="rules"
layout="vertical">
<a-form-item name="name" ref="name">
<a-form-item name="description" ref="description">
<template #label>
<tooltip-label
:title="$t('label.name')"
:tooltip="apiParams.name?.description" />
:title="$t('label.description')"
:tooltip="apiParams.description?.description" />
</template>
<a-input
v-model:value="form.name"
:placeholder="apiParams.name?.description"
v-model:value="form.description"
:placeholder="apiParams.description?.description"
v-focus="true" />
</a-form-item>
@ -72,17 +72,14 @@ export default {
loading: false,
apiParams: {},
form: {
name: ''
description: ''
},
rules: {}
}
},
created () {
this.apiParams = this.$getApiParams('updateDnsZone') || {}
this.rules = {
name: [{ required: true, message: this.$t('message.error.required.input') }]
}
this.form.name = this.resource.name || ''
this.form.description = this.resource.description || ''
},
methods: {
async handleSubmit () {
@ -98,9 +95,8 @@ export default {
}
this.loading = true
try {
await postAPI('updateDnsZone', { id: this.resource.id, name: this.form.name })
await postAPI('updateDnsZone', { id: this.resource.id, description: this.form.description })
this.$notification.success({
message: this.$t('label.dns.update.zone'),