mirror of https://github.com/apache/cloudstack.git
Merge a84c486854 into cd5bb09d0d
This commit is contained in:
commit
6af35c4c46
|
|
@ -932,6 +932,7 @@
|
|||
"label.endpoint": "Endpoint",
|
||||
"label.endport": "End port",
|
||||
"label.enter.account.name": "Enter the account name",
|
||||
"label.enter.domain.name": "Enter the domain name",
|
||||
"label.enter.code": "Enter 2FA code to verify",
|
||||
"label.enter.static.pin": "Enter static PIN to verify",
|
||||
"label.enter.token": "Enter token",
|
||||
|
|
@ -2970,6 +2971,9 @@
|
|||
"message.delete.account.processing": "Deleting account",
|
||||
"message.delete.account.success": "Successfully deleted account",
|
||||
"message.delete.account.warning": "Deleting this account will delete all of the instances, volumes and snapshots associated with the account.",
|
||||
"message.delete.domain.confirm": "Please confirm that you want to delete this domain by entering the name of the domain below.",
|
||||
"message.delete.domain.warning": "This domain may contain accounts, users, or sub-domains. All of these must be removed before the domain can be deleted. This action cannot be undone.",
|
||||
"message.delete.domain.failed": "Delete domain failed",
|
||||
"message.delete.acl.processing": "Removing ACL rule...",
|
||||
"message.delete.acl.rule": "Remove ACL rule",
|
||||
"message.delete.acl.rule.failed": "Failed to remove ACL rule.",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
// 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>
|
||||
<a-modal
|
||||
:visible="true"
|
||||
:title="$t('label.action.delete.domain') + ': ' + domain.name"
|
||||
:okText="$t('label.delete.domain')"
|
||||
okType="danger"
|
||||
:confirmLoading="loading"
|
||||
:ok-button-props="{ disabled: !canDelete }"
|
||||
@cancel="emitClose"
|
||||
@ok="emitConfirm">
|
||||
|
||||
<a-alert
|
||||
type="warning"
|
||||
show-icon
|
||||
style="margin-bottom: 16px">
|
||||
<template #message>
|
||||
<div v-html="$t('message.delete.domain.warning')"></div>
|
||||
</template>
|
||||
</a-alert>
|
||||
|
||||
<a-spin v-if="loading" />
|
||||
|
||||
<a-table
|
||||
v-else
|
||||
size="small"
|
||||
:columns="columns"
|
||||
:dataSource="accountVmSummary"
|
||||
:pagination="false"
|
||||
rowKey="account" />
|
||||
|
||||
<div style="margin-top: 16px">
|
||||
<a-alert style="margin-bottom: 10px">
|
||||
<template #message>
|
||||
<div v-html="$t('message.delete.domain.confirm')"></div>
|
||||
</template>
|
||||
</a-alert>
|
||||
<a-input
|
||||
v-model:value="confirmText"
|
||||
:placeholder="$t('label.enter.domain.name')" />
|
||||
</div>
|
||||
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'DomainDeleteConfirm',
|
||||
props: {
|
||||
domain: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
confirmText: '',
|
||||
accountVmSummary: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
canDelete () {
|
||||
return this.confirmText.trim() === this.domain.name.trim()
|
||||
},
|
||||
columns () {
|
||||
return [
|
||||
{ title: this.$t('label.account'), dataIndex: 'account' },
|
||||
{ title: this.$t('label.total') + ' VMs', dataIndex: 'total' },
|
||||
{ title: this.$t('label.running') + ' VMs', dataIndex: 'running' },
|
||||
{ title: this.$t('label.stopped') + ' VMs', dataIndex: 'stopped' }
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.fetchDomainImpact()
|
||||
},
|
||||
methods: {
|
||||
emitClose () {
|
||||
this.$emit('close')
|
||||
},
|
||||
emitConfirm () {
|
||||
if (this.canDelete) {
|
||||
this.$emit('confirm')
|
||||
}
|
||||
},
|
||||
async fetchDomainImpact () {
|
||||
this.loading = true
|
||||
try {
|
||||
const accResp = await api('listAccounts', {
|
||||
domainid: this.domain.id,
|
||||
listall: true
|
||||
})
|
||||
|
||||
const accounts =
|
||||
accResp.listaccountsresponse &&
|
||||
accResp.listaccountsresponse.account
|
||||
? accResp.listaccountsresponse.account
|
||||
: []
|
||||
|
||||
const vmResp = await api('listVirtualMachines', {
|
||||
domainid: this.domain.id,
|
||||
listall: true
|
||||
})
|
||||
|
||||
const vms =
|
||||
vmResp.listvirtualmachinesresponse &&
|
||||
vmResp.listvirtualmachinesresponse.virtualmachine
|
||||
? vmResp.listvirtualmachinesresponse.virtualmachine
|
||||
: []
|
||||
|
||||
this.accountVmSummary = accounts.map(account => {
|
||||
const accountVms = vms.filter(vm => vm.account === account.name)
|
||||
const running = accountVms.filter(vm => vm.state === 'Running').length
|
||||
const stopped = accountVms.length - running
|
||||
|
||||
return {
|
||||
account: account.name,
|
||||
total: accountVms.length,
|
||||
running,
|
||||
stopped
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: e.response?.headers['x-description'] || this.$t('message.request.failed')
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
|
|
@ -74,6 +74,11 @@
|
|||
:resource="resource"
|
||||
:action="action"/>
|
||||
</div>
|
||||
<domain-delete-confirm
|
||||
v-if="showDeleteConfirm"
|
||||
:domain="deleteDomainResource"
|
||||
@close="showDeleteConfirm = false"
|
||||
@confirm="confirmDeleteDomain" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -87,6 +92,7 @@ import ActionButton from '@/components/view/ActionButton'
|
|||
import TreeView from '@/components/view/TreeView'
|
||||
import DomainActionForm from '@/views/iam/DomainActionForm'
|
||||
import ResourceView from '@/components/view/ResourceView'
|
||||
import DomainDeleteConfirm from '@/components/view/DomainDeleteConfirm'
|
||||
import eventBus from '@/config/eventBus'
|
||||
|
||||
export default {
|
||||
|
|
@ -96,7 +102,8 @@ export default {
|
|||
ActionButton,
|
||||
TreeView,
|
||||
DomainActionForm,
|
||||
ResourceView
|
||||
ResourceView,
|
||||
DomainDeleteConfirm
|
||||
},
|
||||
mixins: [mixinDevice],
|
||||
data () {
|
||||
|
|
@ -111,7 +118,9 @@ export default {
|
|||
action: {},
|
||||
dataView: false,
|
||||
domainStore: {},
|
||||
treeDeletedKey: null
|
||||
treeDeletedKey: null,
|
||||
showDeleteConfirm: false,
|
||||
deleteDomainResource: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -205,7 +214,12 @@ export default {
|
|||
})
|
||||
},
|
||||
execAction (action) {
|
||||
this.treeDeletedKey = action.api === 'deleteDomain' ? this.resource.key : null
|
||||
if (action.api === 'deleteDomain') {
|
||||
this.deleteDomainResource = this.resource
|
||||
this.showDeleteConfirm = true
|
||||
return
|
||||
}
|
||||
this.treeDeletedKey = null
|
||||
this.actionData = []
|
||||
this.action = action
|
||||
this.action.params = store.getters.apis[this.action.api].params
|
||||
|
|
@ -319,6 +333,38 @@ export default {
|
|||
closeAction () {
|
||||
this.showAction = false
|
||||
},
|
||||
confirmDeleteDomain () {
|
||||
const domain = this.deleteDomainResource
|
||||
const params = { id: domain.id, cleanup: true }
|
||||
|
||||
api('deleteDomain', params).then(json => {
|
||||
const jobId = json.deletedomainresponse.jobid
|
||||
|
||||
this.$pollJob({
|
||||
jobId,
|
||||
title: this.$t('label.action.delete.domain'),
|
||||
description: domain.name,
|
||||
loadingMessage: `${this.$t('label.action.delete.domain')} ${domain.name}`,
|
||||
successMessage: `${this.$t('label.action.delete.domain')} ${domain.name}`,
|
||||
catchMessage: this.$t('error.fetching.async.job.result'),
|
||||
successMethod: () => {
|
||||
if (this.$route.params.id === domain.id) {
|
||||
this.$router.push({ path: '/domain' })
|
||||
}
|
||||
this.fetchData()
|
||||
}
|
||||
})
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: error.response?.headers['x-description'] || this.$t('message.request.failed')
|
||||
})
|
||||
}).finally(() => {
|
||||
this.showDeleteConfirm = false
|
||||
this.deleteDomainResource = null
|
||||
this.treeDeletedKey = null
|
||||
})
|
||||
},
|
||||
forceRerender () {
|
||||
this.treeViewKey += 1
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue