mirror of https://github.com/apache/cloudstack.git
UI related work and fixes in updateDnsServer cmd
This commit is contained in:
parent
0df50cedf8
commit
a9afbce186
|
|
@ -41,7 +41,7 @@ public interface DnsServer extends InternalIdentity, Identity, ControlledEntity
|
|||
|
||||
long getAccountId();
|
||||
|
||||
boolean isPublicServer();
|
||||
boolean getPublicServer();
|
||||
|
||||
Date getCreated();
|
||||
|
||||
|
|
|
|||
|
|
@ -3640,7 +3640,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||
if (caller.getId() == dnsServer.getAccountId()) {
|
||||
return;
|
||||
}
|
||||
if (!dnsServer.isPublicServer()) {
|
||||
if (!dnsServer.getPublicServer()) {
|
||||
throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + dnsServer.getName());
|
||||
}
|
||||
Account owner = getAccount(dnsServer.getAccountId());
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
dnsServer.setPort(cmd.getPort());
|
||||
}
|
||||
if (cmd.isPublic() != null) {
|
||||
dnsServer.setIsPublic(cmd.isPublic());
|
||||
dnsServer.setPublicServer(cmd.isPublic());
|
||||
}
|
||||
|
||||
if (cmd.getPublicDomainSuffix() != null) {
|
||||
|
|
@ -476,7 +476,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
Account caller = CallContext.current().getCallingAccount();
|
||||
boolean isOwner = (server.getAccountId() == caller.getId());
|
||||
if (!isOwner) {
|
||||
if (!server.isPublicServer()) {
|
||||
if (!server.getPublicServer()) {
|
||||
throw new PermissionDeniedException("You do not have permission to use this DNS server.");
|
||||
}
|
||||
dnsZoneName = DnsProviderUtil.appendPublicSuffixToZone(dnsZoneName, server.getPublicDomainSuffix());
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ public class DnsServerDaoImpl extends GenericDaoBase<DnsServerVO, Long> implemen
|
|||
|
||||
sb.and().op(ApiConstants.ACCOUNT_ID, sb.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
if (!CollectionUtils.isEmpty(domainIds)) {
|
||||
sb.or().op(ApiConstants.IS_PUBLIC, sb.entity().isPublicServer(), SearchCriteria.Op.EQ);
|
||||
sb.or().op(ApiConstants.IS_PUBLIC, sb.entity().getPublicServer(), SearchCriteria.Op.EQ);
|
||||
sb.and(ApiConstants.DOMAIN_IDS, sb.entity().getDomainId(), SearchCriteria.Op.IN);
|
||||
sb.cp();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import javax.persistence.TemporalType;
|
|||
|
||||
import org.apache.cloudstack.dns.DnsProviderType;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
import org.apache.cloudstack.dns.DnsZone;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.db.Encrypt;
|
||||
|
|
@ -123,7 +122,7 @@ public class DnsServerVO implements DnsServer {
|
|||
this.publicDomainSuffix = publicDomainSuffix;
|
||||
this.publicServer = isPublic;
|
||||
this.state = State.Enabled;
|
||||
this.nameServers = String.join(",", nameServers);;
|
||||
this.nameServers = String.join(",", nameServers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -133,7 +132,7 @@ public class DnsServerVO implements DnsServer {
|
|||
|
||||
@Override
|
||||
public Class<?> getEntityType() {
|
||||
return DnsZone.class;
|
||||
return DnsServer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -176,7 +175,7 @@ public class DnsServerVO implements DnsServer {
|
|||
return uuid;
|
||||
}
|
||||
|
||||
public boolean isPublicServer() {
|
||||
public boolean getPublicServer() {
|
||||
return publicServer;
|
||||
}
|
||||
|
||||
|
|
@ -202,8 +201,8 @@ public class DnsServerVO implements DnsServer {
|
|||
this.nameServers = nameServers;
|
||||
}
|
||||
|
||||
public void setIsPublic(boolean value) {
|
||||
publicServer = value;
|
||||
public void setPublicServer(boolean value) {
|
||||
this.publicServer = value;
|
||||
}
|
||||
|
||||
public void setPublicDomainSuffix(String publicDomainSuffix) {
|
||||
|
|
|
|||
|
|
@ -292,11 +292,6 @@
|
|||
"label.add.internal.lb": "Add internal LB",
|
||||
"label.add.ip.range": "Add IP Range",
|
||||
"label.add.ipv4.subnet": "Add IPv4 Subnet for Routed Networks",
|
||||
"label.dns.server": "DNS Server",
|
||||
"label.dns.add.server": "Add DNS Server",
|
||||
"label.dns.update.server": "Update DNS Server",
|
||||
"label.dns.delete.server": "Delete DNS Server",
|
||||
"label.dnsrecords": "DNS Records",
|
||||
"label.add.ip.v6.prefix": "Add IPv6 prefix",
|
||||
"label.add.isolated.network": "Add Isolated Network",
|
||||
"label.add.kubernetes.cluster": "Add Kubernetes Cluster",
|
||||
|
|
@ -654,6 +649,7 @@
|
|||
"label.console.proxy": "Console proxy",
|
||||
"label.console.proxy.vm": "Console proxy VM",
|
||||
"label.contains": "Contains",
|
||||
"label.contents": "Contents",
|
||||
"label.continue": "Continue",
|
||||
"label.continue.install": "Continue with installation",
|
||||
"label.controlnodes": "Control nodes",
|
||||
|
|
@ -718,7 +714,6 @@
|
|||
"label.created": "Created",
|
||||
"label.creating": "Creating",
|
||||
"label.creating.iprange": "Creating IP ranges",
|
||||
"label.dns.credentials": "DNS API key",
|
||||
"label.nameservers": "DNS Nameservers",
|
||||
"label.credit": "Credit",
|
||||
"label.cron": "Cron expression",
|
||||
|
|
@ -943,9 +938,26 @@
|
|||
"label.dns": "DNS",
|
||||
"label.dns1": "DNS 1",
|
||||
"label.dns2": "DNS 2",
|
||||
"label.dns.add.record": "Add DNS Record",
|
||||
"label.dns.add.server": "Add DNS Server",
|
||||
"label.dns.add.zone": "Add DNS Zone",
|
||||
"label.dns.credentials": "DNS API key",
|
||||
"label.dns.delete.server": "Delete DNS Server",
|
||||
"label.dns.delete.zone": "Delete DNS Zone",
|
||||
"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",
|
||||
"label.dns.record.contents.tooltip": "The content values for this DNS record (type and press Enter to add)",
|
||||
"label.dns.record.ttl.tooltip": "Time to live in seconds",
|
||||
"label.dns.record.url": "Instance URL",
|
||||
"label.dns.server": "DNS Server",
|
||||
"label.dnsservername": "DNS Server name",
|
||||
"label.dns.servers": "DNS Servers",
|
||||
"label.dns.zone": "DNS Zone",
|
||||
"label.dns.zones": "DNS Zones",
|
||||
"label.dns.update.server": "Update DNS Server",
|
||||
"label.dns.update.zone": "Update DNS Zone",
|
||||
"label.dnsrecords": "DNS Records",
|
||||
"label.domain": "Domain",
|
||||
"label.domain.id": "Domain ID",
|
||||
"label.domain.name": "Domain name",
|
||||
|
|
@ -2594,6 +2606,7 @@
|
|||
"label.two.factor.authentication.static.pin": "Your Two factor authentication static PIN",
|
||||
"label.two.factor.authentication": "Two Factor Authentication",
|
||||
"label.2FA": "2FA",
|
||||
"label.ttl": "TTL",
|
||||
"label.tungsten.fabric": "Tungsten Fabric",
|
||||
"label.tungsten.fabric.provider": "Tungsten Fabric Provider",
|
||||
"label.tungsten.fabric.routing": "Tungsten Fabric Routing",
|
||||
|
|
@ -2954,7 +2967,9 @@
|
|||
"message.action.delete.backup.schedule": "Please confirm that you want to delete this backup schedule?",
|
||||
"message.action.delete.cluster": "Please confirm that you want to delete this Cluster.",
|
||||
"message.action.delete.custom.action": "Please confirm that you want to delete this custom action.",
|
||||
"message.confirm.delete.dns.record": "Are you sure you want to delete this DNS record?",
|
||||
"message.action.delete.dns.server": "Please confirm you want to delete this DNS server.",
|
||||
"message.action.delete.dns.zone": "Please confirm you want to delete this DNS zone.",
|
||||
"message.action.delete.domain": "Please confirm that you want to delete this domain.",
|
||||
"message.action.delete.extension": "Please confirm that you want to delete the extension",
|
||||
"message.action.delete.external.firewall": "Please confirm that you would like to remove this external firewall. Warning: If you are planning to add back the same external firewall, you must reset usage data on the device.",
|
||||
|
|
@ -3862,6 +3877,12 @@
|
|||
"message.success.add.bgp.peer": "Successfully added new BGP peer",
|
||||
"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.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",
|
||||
"message.success.add.interface.static.route": "Successfully added interface Static Route",
|
||||
|
|
@ -4158,6 +4179,9 @@
|
|||
"migrate.from": "Migrate from",
|
||||
"migrate.to": "Migrate to",
|
||||
"migrationPolicy": "Migration policy",
|
||||
"placeholder.dns.record.name": "e.g. www",
|
||||
"placeholder.dns.record.type": "Select record type",
|
||||
"placeholder.dns.record.contents": "Type a value and hit Enter",
|
||||
"placeholder.quota.tariff.activationrule": "Quota tariff's activation rule",
|
||||
"placeholder.quota.tariff.description": "Quota tariff's description",
|
||||
"placeholder.quota.tariff.enddate": "Quota tariff's end date",
|
||||
|
|
|
|||
|
|
@ -1219,7 +1219,7 @@ export default {
|
|||
'/zone', '/pod', '/cluster', '/host', '/storagepool', '/imagestore', '/systemvm', '/router', '/ilbvm', '/annotation',
|
||||
'/computeoffering', '/systemoffering', '/diskoffering', '/backupoffering', '/networkoffering', '/vpcoffering',
|
||||
'/tungstenfabric', '/oauthsetting', '/guestos', '/guestoshypervisormapping', '/webhook', 'webhookdeliveries', 'webhookfilters', '/quotatariff', '/sharedfs',
|
||||
'/ipv4subnets', '/managementserver', '/gpucard', '/gpudevices', '/vgpuprofile', '/extension', '/snapshotpolicy', '/backupschedule'].join('|'))
|
||||
'/ipv4subnets', '/managementserver', '/gpucard', '/gpudevices', '/vgpuprofile', '/extension', '/snapshotpolicy', '/backupschedule', '/dnsserver', '/dnszone'].join('|'))
|
||||
.test(this.$route.path)
|
||||
},
|
||||
enableGroupAction () {
|
||||
|
|
|
|||
|
|
@ -1488,47 +1488,15 @@ export default {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'dnsrecords',
|
||||
title: 'label.dns.records',
|
||||
icon: 'global-outlined',
|
||||
hidden: true,
|
||||
permission: ['listDnsRecords'],
|
||||
columns: ['name', 'url', 'provider'],
|
||||
details: ['name', 'url', 'provider', 'ispublic', 'port', 'nameservers'],
|
||||
related: [{
|
||||
name: 'vm',
|
||||
title: 'label.dns.zone',
|
||||
param: 'dnszoneid'
|
||||
}]
|
||||
},
|
||||
{
|
||||
name: 'dnszones',
|
||||
title: 'label.dns.zones',
|
||||
icon: 'global-outlined',
|
||||
hidden: true,
|
||||
permission: ['listDnsZones'],
|
||||
columns: ['name', 'state', 'dnsservername', 'dnsserveraccount'],
|
||||
details: ['name', 'state', 'dnsservername', 'dnsserveraccount'],
|
||||
tabs: [{
|
||||
name: 'details',
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue')))
|
||||
},
|
||||
{
|
||||
name: 'dnsrecords',
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/InternalLBAssignedVmTab.vue'))),
|
||||
show: () => true
|
||||
}]
|
||||
},
|
||||
{
|
||||
name: 'dnsserver',
|
||||
title: 'label.dns.server',
|
||||
icon: 'global-outlined',
|
||||
permission: ['listDnsServers'],
|
||||
columns: ['name', 'url', 'provider'],
|
||||
details: ['name', 'url', 'abc', 'provider', 'ispublic', 'port', 'nameservers', 'domain', 'account'],
|
||||
details: ['name', 'url', 'provider', 'ispublic', 'port', 'nameservers', 'domain', 'account'],
|
||||
related: [{
|
||||
name: 'dnszones',
|
||||
name: 'dnszone',
|
||||
title: 'label.dns.zone',
|
||||
param: 'dnsserverid'
|
||||
}],
|
||||
|
|
@ -1550,7 +1518,7 @@ export default {
|
|||
label: 'label.dns.update.server',
|
||||
dataView: true,
|
||||
popup: true,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/AddDnsServer.vue'))),
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/UpdateDnsServer.vue'))),
|
||||
show: (record) => { return true }
|
||||
},
|
||||
{
|
||||
|
|
@ -1564,6 +1532,58 @@ export default {
|
|||
groupMap: (selection) => { return selection.map(x => { return { id: x } }) }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'dnszone',
|
||||
title: 'label.dns.zones',
|
||||
icon: 'global-outlined',
|
||||
permission: ['listDnsZones'],
|
||||
columns: ['name', 'state', 'dnsservername', 'account'],
|
||||
details: ['name', 'id', 'state', 'dnsservername', 'dnsserverid', 'account', 'domainpath'],
|
||||
tabs: [{
|
||||
name: 'details',
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue')))
|
||||
},
|
||||
{
|
||||
name: 'dns.records',
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/DnsRecordsTab.vue'))),
|
||||
show: () => true
|
||||
}],
|
||||
actions: [
|
||||
{
|
||||
api: 'createDnsZone',
|
||||
icon: 'plus-outlined',
|
||||
label: 'label.dns.add.zone',
|
||||
listView: true,
|
||||
popup: true,
|
||||
disabled: (record) => false,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/AddDnsZone.vue'))),
|
||||
show: () => {
|
||||
return true
|
||||
}
|
||||
},
|
||||
{
|
||||
api: 'updateDnsZone',
|
||||
icon: 'edit-outlined',
|
||||
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 }
|
||||
},
|
||||
{
|
||||
api: 'deleteDnsZone',
|
||||
icon: 'delete-outlined',
|
||||
label: 'label.dns.delete.zone',
|
||||
message: 'message.action.delete.dns.zone',
|
||||
dataView: true,
|
||||
groupAction: true,
|
||||
disabled: (record) => false,
|
||||
show: (record) => { return true },
|
||||
groupMap: (selection) => { return selection.map(x => { return { id: x } }) }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@
|
|||
{{ record.isolationuri }}
|
||||
</a-descriptions-item>
|
||||
|
||||
<a-descriptions-item :label="$t('label.dns_url')" v-if="record.dns_url">
|
||||
{{ record.dns_url }}
|
||||
<a-descriptions-item :label="$t('label.dns.record.url')" v-if="record.dnsrecordurl">
|
||||
{{ record.dnsrecordurl }}
|
||||
</a-descriptions-item>
|
||||
</template>
|
||||
</a-descriptions>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,192 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
<template>
|
||||
<div class="form-layout" v-ctrl-enter="handleSubmit">
|
||||
<a-spin :spinning="loading">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
layout="vertical">
|
||||
|
||||
<a-form-item name="name" ref="name">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.name')"
|
||||
:tooltip="$t('label.dns.record.name.tooltip')" />
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.name"
|
||||
:placeholder="$t('placeholder.dns.record.name')"
|
||||
v-focus="true" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="type" ref="type">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.type')"
|
||||
:tooltip="$t('label.dns.record.type.tooltip')" />
|
||||
</template>
|
||||
<a-select
|
||||
v-model:value="form.type"
|
||||
:placeholder="$t('placeholder.dns.record.type')"
|
||||
showSearch>
|
||||
<a-select-option
|
||||
v-for="rtype in recordTypes"
|
||||
:key="rtype"
|
||||
:value="rtype">
|
||||
{{ rtype }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="contents" ref="contents">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.contents')"
|
||||
:tooltip="$t('label.dns.record.contents.tooltip')" />
|
||||
</template>
|
||||
<a-select
|
||||
v-model:value="form.contents"
|
||||
mode="tags"
|
||||
:placeholder="$t('placeholder.dns.record.contents')"
|
||||
style="width: 100%"
|
||||
:token-separators="[',']" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="ttl" ref="ttl">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.ttl')"
|
||||
:tooltip="$t('label.dns.record.ttl.tooltip')" />
|
||||
</template>
|
||||
<a-input-number
|
||||
v-model:value="form.ttl"
|
||||
:min="1"
|
||||
:max="2147483647"
|
||||
style="width: 100%" />
|
||||
</a-form-item>
|
||||
|
||||
<div class="action-button">
|
||||
<a-button @click="closeAction">
|
||||
{{ $t('label.cancel') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="handleSubmit">
|
||||
{{ $t('label.ok') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { postAPI } from '@/api'
|
||||
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
||||
|
||||
export default {
|
||||
name: 'AddDnsRecord',
|
||||
components: {
|
||||
TooltipLabel
|
||||
},
|
||||
props: {
|
||||
resource: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
form: {
|
||||
name: '',
|
||||
type: 'A',
|
||||
contents: [],
|
||||
ttl: 3600
|
||||
},
|
||||
rules: {},
|
||||
recordTypes: ['A', 'AAAA', 'CNAME', 'MX', 'TXT', 'SRV', 'PTR', 'NS']
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.rules = {
|
||||
name: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
type: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
contents: [{ required: true, type: 'array', min: 1, message: this.$t('message.error.required.input') }],
|
||||
ttl: [{ required: true, message: this.$t('message.error.required.input') }]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async handleSubmit () {
|
||||
if (this.loading) return
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (error) {
|
||||
if (error.errorFields && error.errorFields.length > 0) {
|
||||
this.$refs.formRef.scrollToField(error.errorFields[0].name)
|
||||
}
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
try {
|
||||
await postAPI('addDnsRecord', {
|
||||
dnszoneid: this.resource.id,
|
||||
...this.form
|
||||
})
|
||||
this.$notification.success({
|
||||
message: this.$t('label.dns.add.record'),
|
||||
description: this.$t('message.success.add.dns.record')
|
||||
})
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
} catch (error) {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: error?.response?.headers['x-description'] || error.message,
|
||||
duration: 0
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
closeAction () {
|
||||
this.$emit('close-action')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.form-layout {
|
||||
width: 80vw;
|
||||
@media (min-width: 600px) {
|
||||
width: 450px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-button {
|
||||
text-align: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.action-button button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -97,14 +97,18 @@
|
|||
:title="$t('label.nameservers')"
|
||||
:tooltip="apiParams.nameservers?.description" />
|
||||
</template>
|
||||
<a-input
|
||||
|
||||
<a-select
|
||||
v-model:value="form.nameservers"
|
||||
:placeholder="apiParams.nameservers?.description" />
|
||||
mode="tags"
|
||||
style="width: 100%"
|
||||
:token-separators="[',', ' ']"
|
||||
:placeholder="apiParams.nameservers?.description || 'ns1.example.com, ns2.example.com'" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="ispublic" ref="ispublic">
|
||||
<a-checkbox v-model:checked="form.ispublic">
|
||||
{{ "Public server" }}
|
||||
{{ $t('label.ispublic') }}
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
|
||||
|
|
@ -163,32 +167,21 @@ export default {
|
|||
methods: {
|
||||
async handleSubmit () {
|
||||
if (this.loading) return
|
||||
|
||||
// 1. Validate the form natively using Vue 3 $refs
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (error) {
|
||||
// Scroll to the first field with an error
|
||||
if (error.errorFields && error.errorFields.length > 0) {
|
||||
this.$refs.formRef.scrollToField(error.errorFields[0].name)
|
||||
}
|
||||
return // Abort submission
|
||||
return
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
|
||||
// 2. Execute the API
|
||||
try {
|
||||
console.log('form data ', this.form)
|
||||
// Pass the form object directly
|
||||
await postAPI('addDnsServer', this.form)
|
||||
|
||||
this.$notification.success({
|
||||
message: this.$t('label.add.dns.server'),
|
||||
description: this.$t('message.success.add.dns.server')
|
||||
})
|
||||
|
||||
// Refresh the parent table and close modal
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
<template>
|
||||
<div class="form-layout" v-ctrl-enter="handleSubmit">
|
||||
<a-spin :spinning="loading">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
layout="vertical">
|
||||
|
||||
<a-form-item name="name" ref="name">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.name')"
|
||||
:tooltip="apiParams.name?.description" />
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.name"
|
||||
:placeholder="apiParams.name?.description || 'e.g. example.com'"
|
||||
v-focus="true" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="dnsserverid" ref="dnsserverid">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.dns.server')"
|
||||
:tooltip="apiParams.dnsserverid?.description" />
|
||||
</template>
|
||||
<a-select
|
||||
v-model:value="form.dnsserverid"
|
||||
:placeholder="apiParams.dnsserverid?.description || 'Select DNS Server'"
|
||||
:loading="fetchingServers"
|
||||
showSearch
|
||||
optionFilterProp="label">
|
||||
<a-select-option
|
||||
v-for="server in dnsServers"
|
||||
:key="server.id"
|
||||
:value="server.id"
|
||||
:label="server.name">
|
||||
{{ server.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<div class="action-button">
|
||||
<a-button @click="closeAction">
|
||||
{{ $t('label.cancel') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="handleSubmit">
|
||||
{{ $t('label.ok') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getAPI, postAPI } from '@/api'
|
||||
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
||||
|
||||
export default {
|
||||
name: 'AddDnsZone',
|
||||
components: {
|
||||
TooltipLabel
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
apiParams: {},
|
||||
form: {
|
||||
name: '',
|
||||
dnsserverid: undefined
|
||||
},
|
||||
rules: {},
|
||||
fetchingServers: false,
|
||||
dnsServers: []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.apiParams = this.$getApiParams('createDnsZone') || {}
|
||||
this.rules = {
|
||||
name: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
dnsserverid: [{ required: true, message: this.$t('message.error.required.input') }]
|
||||
}
|
||||
this.fetchDnsServers()
|
||||
},
|
||||
methods: {
|
||||
async handleSubmit () {
|
||||
if (this.loading) return
|
||||
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (error) {
|
||||
const field = error?.errorFields?.[0]?.name
|
||||
if (field) {
|
||||
this.$refs.formRef.scrollToField(field)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
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')
|
||||
})
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
} catch (error) {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: error?.response?.headers['x-description'] || error.message,
|
||||
duration: 0
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
closeAction () {
|
||||
this.$emit('close-action')
|
||||
},
|
||||
async fetchDnsServers () {
|
||||
this.fetchingServers = true
|
||||
try {
|
||||
const response = await getAPI('listDnsServers')
|
||||
const listResponse = response?.listdnsserversresponse || {}
|
||||
this.dnsServers = listResponse.dnsserver || []
|
||||
if (this.dnsServers.length > 0) {
|
||||
this.form.dnsserverid = this.dnsServers[0].id
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch DNS servers', error)
|
||||
this.$message.warning('Could not load DNS servers.')
|
||||
} finally {
|
||||
this.fetchingServers = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.form-layout {
|
||||
width: 80vw;
|
||||
@media (min-width: 600px) {
|
||||
width: 450px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-button {
|
||||
text-align: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.action-button button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<a-spin :spinning="fetchLoading">
|
||||
<a-button
|
||||
shape="round"
|
||||
style="float: right;margin-bottom: 10px; z-index: 8"
|
||||
@click="() => { showAddForm = true }">
|
||||
<template #icon><plus-outlined /></template>
|
||||
{{ $t('label.dns.add.record') }}
|
||||
</a-button>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<a-table
|
||||
size="small"
|
||||
style="overflow-y: auto; width: 100%;"
|
||||
:columns="columns"
|
||||
:dataSource="records"
|
||||
:rowKey="item => item.id"
|
||||
:pagination="false">
|
||||
|
||||
<template #bodyCell="{ column, record }">
|
||||
<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'">
|
||||
<a-popconfirm
|
||||
:title="$t('message.confirm.delete.dns.record')"
|
||||
@confirm="handleDeleteRecord(record)"
|
||||
:okText="$t('label.yes')"
|
||||
:cancelText="$t('label.no')">
|
||||
<tooltip-button
|
||||
tooltipPlacement="bottom"
|
||||
:tooltip="$t('label.delete')"
|
||||
type="primary"
|
||||
:danger="true"
|
||||
icon="delete-outlined" />
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
<a-divider/>
|
||||
|
||||
<a-pagination
|
||||
class="row-element pagination"
|
||||
size="small"
|
||||
:current="page"
|
||||
:pageSize="pageSize"
|
||||
:total="total"
|
||||
:showTotal="total => `${$t('label.total')} ${total} ${$t('label.items')}`"
|
||||
:pageSizeOptions="['10', '20', '40', '80', '100']"
|
||||
@change="changePage"
|
||||
@showSizeChange="changePageSize"
|
||||
showSizeChanger>
|
||||
<template #buildOptionText="props">
|
||||
<span>{{ props.value }} / {{ $t('label.page') }}</span>
|
||||
</template>
|
||||
</a-pagination>
|
||||
</a-spin>
|
||||
|
||||
<a-modal
|
||||
v-if="showAddForm"
|
||||
:visible="showAddForm"
|
||||
:title="$t('label.dns.add.record')"
|
||||
:maskClosable="false"
|
||||
:closable="true"
|
||||
:footer="null"
|
||||
@cancel="() => { showAddForm = false }"
|
||||
centered
|
||||
width="auto">
|
||||
<AddDnsRecord
|
||||
:resource="resource"
|
||||
@refresh-data="fetchData"
|
||||
@close-action="showAddForm = false" />
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getAPI, postAPI } from '@/api'
|
||||
import TooltipButton from '@/components/widgets/TooltipButton'
|
||||
import AddDnsRecord from '@/views/network/dns/AddDnsRecord'
|
||||
|
||||
export default {
|
||||
name: 'DnsRecordsTab',
|
||||
components: {
|
||||
TooltipButton,
|
||||
AddDnsRecord
|
||||
},
|
||||
props: {
|
||||
resource: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
fetchLoading: false,
|
||||
showAddForm: false,
|
||||
total: 0,
|
||||
records: [],
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('label.name'),
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.type'),
|
||||
dataIndex: 'type'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.contents'),
|
||||
dataIndex: 'contents'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.ttl'),
|
||||
dataIndex: 'ttl'
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
title: this.$t('label.actions')
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.fetchData()
|
||||
},
|
||||
watch: {
|
||||
resource: {
|
||||
deep: true,
|
||||
handler (newItem) {
|
||||
if (!newItem || !newItem.id) {
|
||||
return
|
||||
}
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchData () {
|
||||
const params = {
|
||||
dnszoneid: this.resource.id,
|
||||
page: this.page,
|
||||
pagesize: this.pageSize
|
||||
}
|
||||
this.fetchLoading = true
|
||||
getAPI('listDnsRecords', params).then(json => {
|
||||
const response = json.listdnsrecordsresponse || {}
|
||||
this.total = response.count || 0
|
||||
this.records = response.dnsrecord || []
|
||||
}).catch(error => {
|
||||
console.error('Failed to fetch DNS records', error)
|
||||
}).finally(() => {
|
||||
this.fetchLoading = false
|
||||
})
|
||||
},
|
||||
handleDeleteRecord (record) {
|
||||
postAPI('deleteDnsRecord', { id: record.id }).then(() => {
|
||||
this.$notification.success({
|
||||
message: this.$t('message.success.delete.dns.record')
|
||||
})
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: error?.response?.headers['x-description'] || error.message,
|
||||
duration: 0
|
||||
})
|
||||
}).finally(() => {
|
||||
this.fetchData()
|
||||
})
|
||||
},
|
||||
changePage (page, pageSize) {
|
||||
this.page = page
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
},
|
||||
changePageSize (currentPage, pageSize) {
|
||||
this.page = currentPage
|
||||
this.pageSize = pageSize
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
<template>
|
||||
<div class="form-layout" v-ctrl-enter="handleSubmit">
|
||||
<a-spin :spinning="loading">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
layout="vertical">
|
||||
|
||||
<a-form-item name="name" ref="name">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.name')"
|
||||
:tooltip="apiParams.name?.description" />
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.name"
|
||||
:placeholder="apiParams.name?.description"
|
||||
v-focus="true" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="url" ref="url">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.url')"
|
||||
:tooltip="apiParams.url?.description" />
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.url"
|
||||
:placeholder="apiParams.url?.description" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="port" ref="port">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.port')"
|
||||
:tooltip="apiParams.port?.description" />
|
||||
</template>
|
||||
<a-input-number
|
||||
v-model:value="form.port"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
style="width: 100%" />
|
||||
</a-form-item>
|
||||
|
||||
<div class="action-button">
|
||||
<a-button @click="closeAction">
|
||||
{{ $t('label.cancel') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="handleSubmit">
|
||||
{{ $t('label.ok') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { postAPI } from '@/api'
|
||||
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
||||
|
||||
export default {
|
||||
name: 'UpdateDnsServer',
|
||||
components: {
|
||||
TooltipLabel
|
||||
},
|
||||
props: {
|
||||
resource: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
apiParams: {},
|
||||
form: {
|
||||
name: '',
|
||||
url: '',
|
||||
port: 53
|
||||
},
|
||||
rules: {}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.apiParams = this.$getApiParams('updateDnsServer') || {}
|
||||
this.rules = {
|
||||
name: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
url: [{ required: true, message: this.$t('message.error.required.input') }]
|
||||
}
|
||||
this.form.name = this.resource.name || ''
|
||||
this.form.url = this.resource.url || ''
|
||||
this.form.port = this.resource.port || 53
|
||||
},
|
||||
methods: {
|
||||
async handleSubmit () {
|
||||
if (this.loading) return
|
||||
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (error) {
|
||||
if (error.errorFields && error.errorFields.length > 0) {
|
||||
this.$refs.formRef.scrollToField(error.errorFields[0].name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
|
||||
try {
|
||||
await postAPI('updateDnsServer', { id: this.resource.id, ...this.form })
|
||||
|
||||
this.$notification.success({
|
||||
message: this.$t('label.dns.update.server'),
|
||||
description: this.$t('message.success.update.dns.server')
|
||||
})
|
||||
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
} catch (error) {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: error?.response?.headers['x-description'] || error.message,
|
||||
duration: 0
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
closeAction () {
|
||||
this.$emit('close-action')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.form-layout {
|
||||
width: 80vw;
|
||||
@media (min-width: 600px) {
|
||||
width: 450px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-button {
|
||||
text-align: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.action-button button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
<template>
|
||||
<div class="form-layout" v-ctrl-enter="handleSubmit">
|
||||
<a-spin :spinning="loading">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
layout="vertical">
|
||||
|
||||
<a-form-item name="name" ref="name">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.name')"
|
||||
:tooltip="apiParams.name?.description" />
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.name"
|
||||
:placeholder="apiParams.name?.description"
|
||||
v-focus="true" />
|
||||
</a-form-item>
|
||||
|
||||
<div class="action-button">
|
||||
<a-button @click="closeAction">
|
||||
{{ $t('label.cancel') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="handleSubmit">
|
||||
{{ $t('label.ok') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { postAPI } from '@/api'
|
||||
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
||||
|
||||
export default {
|
||||
name: 'UpdateDnsZone',
|
||||
components: {
|
||||
TooltipLabel
|
||||
},
|
||||
props: {
|
||||
resource: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
apiParams: {},
|
||||
form: {
|
||||
name: ''
|
||||
},
|
||||
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 || ''
|
||||
},
|
||||
methods: {
|
||||
async handleSubmit () {
|
||||
if (this.loading) return
|
||||
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (error) {
|
||||
if (error.errorFields && error.errorFields.length > 0) {
|
||||
this.$refs.formRef.scrollToField(error.errorFields[0].name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
|
||||
try {
|
||||
await postAPI('updateDnsZone', { id: this.resource.id, name: this.form.name })
|
||||
|
||||
this.$notification.success({
|
||||
message: this.$t('label.dns.update.zone'),
|
||||
description: this.$t('message.success.update.dns.zone')
|
||||
})
|
||||
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
} catch (error) {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: error?.response?.headers['x-description'] || error.message,
|
||||
duration: 0
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
closeAction () {
|
||||
this.$emit('close-action')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.form-layout {
|
||||
width: 80vw;
|
||||
@media (min-width: 600px) {
|
||||
width: 450px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-button {
|
||||
text-align: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.action-button button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue