This is an automated email from the ASF dual-hosted git repository. davidjumani pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 27d674df7d62f99a16eab4973e79a8052fed90aa Merge: 05a978c 535761b Author: davidjumani <[email protected]> AuthorDate: Tue Jul 20 10:18:16 2021 +0530 Merge branch '4.15' into main ui/src/components/header/HeaderNotice.vue | 78 ++--------- ui/src/components/view/ActionButton.vue | 1 + ui/src/components/view/DedicateData.vue | 44 ++----- ui/src/components/view/DedicateModal.vue | 42 ++---- ui/src/core/bootstrap.js | 4 +- ui/src/store/getters.js | 2 +- ui/src/store/modules/user.js | 33 +++-- ui/src/store/mutation-types.js | 2 +- ui/src/utils/plugins.js | 28 +++- ui/src/views/AutogenView.vue | 143 +++++++++++---------- ui/src/views/compute/AttachIso.vue | 11 +- ui/src/views/compute/CreateKubernetesCluster.vue | 14 +- ui/src/views/compute/CreateSnapshotWizard.vue | 8 +- ui/src/views/compute/DeployVM.vue | 15 +-- ui/src/views/compute/DestroyVM.vue | 10 +- ui/src/views/compute/InstanceTab.vue | 12 -- ui/src/views/compute/MigrateWizard.vue | 12 +- ui/src/views/compute/ScaleKubernetesCluster.vue | 14 +- ui/src/views/compute/StartVirtualMachine.vue | 12 +- ui/src/views/compute/UpgradeKubernetesCluster.vue | 14 +- ui/src/views/iam/DomainActionForm.vue | 47 +++---- ui/src/views/image/IsoZones.vue | 17 +-- ui/src/views/image/TemplateZones.vue | 17 +-- ui/src/views/infra/ClusterAdd.vue | 8 +- ui/src/views/infra/HostAdd.vue | 8 +- ui/src/views/infra/MigrateData.vue | 41 ++---- ui/src/views/infra/PodAdd.vue | 8 +- ui/src/views/infra/network/DedicatedVLANTab.vue | 7 +- ui/src/views/infra/network/EditTrafficLabel.vue | 11 +- .../views/infra/network/IpRangesTabManagement.vue | 16 +-- ui/src/views/infra/network/IpRangesTabStorage.vue | 16 +-- ui/src/views/infra/network/ServiceProvidersTab.vue | 8 +- .../infra/network/providers/AddF5LoadBalancer.vue | 45 ++----- .../network/providers/AddNetscalerLoadBalancer.vue | 45 ++----- .../infra/network/providers/AddNiciraNvpDevice.vue | 45 ++----- .../network/providers/AddPaloAltoFirewall.vue | 45 ++----- .../infra/network/providers/AddSrxFirewall.vue | 45 ++----- .../infra/network/providers/ProviderListView.vue | 18 +-- ui/src/views/network/AclListRulesTab.vue | 35 ++--- ui/src/views/network/CreateVpc.vue | 11 +- ui/src/views/network/CreateVpnCustomerGateway.vue | 11 +- ui/src/views/network/FirewallRules.vue | 4 - .../views/network/IngressEgressRuleConfigure.vue | 10 -- ui/src/views/network/InternalLBAssignVmForm.vue | 7 - ui/src/views/network/LoadBalancing.vue | 18 +-- ui/src/views/network/PortForwarding.vue | 6 - ui/src/views/network/StaticRoutesTab.vue | 14 +- ui/src/views/network/VpcTab.vue | 28 ++-- ui/src/views/network/VpcTiersTab.vue | 8 +- ui/src/views/network/VpnDetails.vue | 4 - ui/src/views/offering/ImportBackupOffering.vue | 11 +- ui/src/views/project/AccountsTab.vue | 10 +- ui/src/views/project/AddAccountOrUserToProject.vue | 2 - ui/src/views/project/InvitationTokenTemplate.vue | 4 +- ui/src/views/project/InvitationsTemplate.vue | 4 +- ui/src/views/storage/AttachVolume.vue | 12 +- .../views/storage/CreateSnapshotFromVMSnapshot.vue | 15 +-- ui/src/views/storage/CreateVolume.vue | 15 +-- ui/src/views/storage/MigrateVolume.vue | 7 - ui/src/views/storage/ResizeVolume.vue | 11 +- ui/src/views/storage/RestoreAttachBackupVolume.vue | 10 +- ui/src/views/storage/TakeSnapshot.vue | 12 +- 62 files changed, 375 insertions(+), 840 deletions(-) diff --cc ui/src/components/header/HeaderNotice.vue index 07d9936,d20f606..fb6b3c5 --- a/ui/src/components/header/HeaderNotice.vue +++ b/ui/src/components/header/HeaderNotice.vue @@@ -32,12 -32,9 +32,12 @@@ <a-button size="small" slot="description" @click="clearJobs">{{ $t('label.clear.list') }}</a-button> </a-list-item-meta> </a-list-item> - <a-list-item v-for="(job, index) in jobs" :key="index"> - <a-list-item-meta :title="job.title"> - <a-avatar :style="notificationAvatar[job.status].style" :icon="notificationAvatar[job.status].icon" slot="avatar"/><br/> - <span v-if="getResourceName(job.description, 'name') && job.path" slot="description"><router-link :to="{ path: job.path}"> {{ getResourceName(job.description, "name") + ' - ' }}</router-link></span> - <span v-if="getResourceName(job.description, 'name') && job.path" slot="description"> {{ getResourceName(job.description, "msg") }}</span> - <span v-else slot="description"> {{ job.description }} </span> + <a-list-item v-for="(notice, index) in notices" :key="index"> + <a-list-item-meta :title="notice.title" :description="notice.description"> + <a-avatar :style="notificationAvatar[notice.status].style" :icon="notificationAvatar[notice.status].icon" slot="avatar"/> ++ <span v-if="getResourceName(notice.description, 'name') && notice.path" slot="description"><router-link :to="{ path: notice.path}"> {{ getResourceName(notice.description, "name") + ' - ' }}</router-link></span> ++ <span v-if="getResourceName(notice.description, 'name') && notice.path" slot="description"> {{ getResourceName(notice.description, "msg") }}</span> ++ <span v-else slot="description"> {{ notice.description }} </span> </a-list-item-meta> </a-list-item> </a-list> @@@ -75,78 -71,17 +74,27 @@@ export default this.visible = !this.visible }, clearJobs () { - this.jobs = this.jobs.filter(x => x.status === 'progress') - this.$store.commit('SET_ASYNC_JOB_IDS', this.jobs) - }, - startPolling () { - this.poller = setInterval(() => { - this.pollJobs() - }, 4000) + this.notices = this.notices.filter(x => x.status === 'progress') + this.$store.commit('SET_HEADER_NOTICES', this.notices) + }, + getResourceName (description, data) { + if (description) { + if (data === 'name') { + const name = description.match(/\(([^)]+)\)/) + return name ? name[1] : null + } + const msg = description.substring(description.indexOf(')') + 1) + return msg + } - }, - async pollJobs () { - var hasUpdated = false - for (var i in this.jobs) { - if (this.jobs[i].status === 'progress') { - await api('queryAsyncJobResult', { jobid: this.jobs[i].jobid }).then(json => { - var result = json.queryasyncjobresultresponse - if (result.jobstatus === 1 && this.jobs[i].status !== 'done') { - hasUpdated = true - const title = this.jobs[i].title - const description = this.jobs[i].description - this.$message.success({ - content: title + (description ? ' - ' + description : ''), - key: this.jobs[i].jobid, - duration: 2 - }) - this.jobs[i].status = 'done' - } else if (result.jobstatus === 2 && this.jobs[i].status !== 'failed') { - hasUpdated = true - this.jobs[i].status = 'failed' - if (result.jobresult.errortext !== null) { - this.jobs[i].description = '(' + this.jobs[i].description + ') ' + result.jobresult.errortext - } - if (!this.jobs[i].bulkAction) { - this.$notification.error({ - message: this.jobs[i].title, - description: this.jobs[i].description, - key: this.jobs[i].jobid, - duration: 0 - }) - } - } - }).catch(function (e) { - console.log(this.$t('error.fetching.async.job.result') + e) - }) - } - } - if (hasUpdated) { - this.$store.commit('SET_ASYNC_JOB_IDS', this.jobs.reverse()) - } } }, - beforeDestroy () { - clearInterval(this.poller) - }, - created () { - this.startPolling() - }, mounted () { - this.jobs = (store.getters.asyncJobIds || []).reverse() + this.notices = (store.getters.headerNotices || []).reverse() this.$store.watch( - (state, getters) => getters.asyncJobIds, + (state, getters) => getters.headerNotices, (newValue, oldValue) => { if (oldValue !== newValue && newValue !== undefined) { - this.jobs = newValue.reverse() + this.notices = newValue.reverse() } } ) diff --cc ui/src/store/modules/user.js index d764ae4,d2a5fd6..2cef4a7 --- a/ui/src/store/modules/user.js +++ b/ui/src/store/modules/user.js @@@ -45,7 -45,8 +45,7 @@@ const user = apis: {}, features: {}, project: {}, -- asyncJobIds: [], + headerNotices: [], isLdapEnabled: false, cloudian: {}, zones: {}, diff --cc ui/src/utils/plugins.js index d452b0d,c7a385c..c44cec9 --- a/ui/src/utils/plugins.js +++ b/ui/src/utils/plugins.js @@@ -49,10 -53,16 +54,17 @@@ export const pollJobPlugin = showLoading = true, catchMessage = i18n.t('label.error.caught'), catchMethod = () => {}, - action = null + action = null, + bulkAction = false } = options + store.dispatch('AddHeaderNotice', { + key: jobId, + title: title, + description: description, + status: 'progress' + }) + api('queryAsyncJobResult', { jobId }).then(json => { const result = json.queryasyncjobresultresponse if (result.jobstatus === 1) { @@@ -68,33 -78,47 +80,44 @@@ key: jobId, duration: 2 }) - eventBus.$emit('async-job-complete', action) + store.dispatch('AddHeaderNotice', { + key: jobId, + title: title, + description: description, + status: 'done', + duration: 2 + }) + if (!action || !('isFetchData' in action) || (action.isFetchData)) { - eventBus.$emit('async-job-complete') ++ eventBus.$emit('async-job-complete', action) + } successMethod(result) } else if (result.jobstatus === 2) { - message.error({ - content: errorMessage, - key: jobId, - duration: 1 - }) - var errTitle = errorMessage + if (!bulkAction) { + message.error({ + content: errorMessage, + key: jobId, + duration: 1 + }) + } + var title = errorMessage if (action && action.label) { - errTitle = i18n.t(action.label) + title = i18n.t(action.label) } var desc = result.jobresult.errortext if (name) { desc = `(${name}) ${desc}` } - notification.error({ - message: errTitle, - description: desc, - key: jobId, - duration: 0 - }) - store.dispatch('AddHeaderNotice', { - key: jobId, - title: title, - description: desc, - status: 'failed', - duration: 0 - }) + if (!bulkAction) { + notification.error({ + message: title, + description: desc, + key: jobId, + duration: 0 + }) + } - eventBus.$emit('async-job-complete', action) + if (!action || !('isFetchData' in action) || (action.isFetchData)) { - eventBus.$emit('async-job-complete') ++ eventBus.$emit('async-job-complete', action) + } errorMethod(result) } else if (result.jobstatus === 0) { if (showLoading) { diff --cc ui/src/views/AutogenView.vue index f88f7fd,f274ecf..f2d4d6f --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@@ -443,8 -401,8 +443,9 @@@ export default actions: [], formModel: {}, confirmDirty: false, - promises: [], - firstIndex: 0 + firstIndex: 0, - modalWidth: '30vw' ++ modalWidth: '30vw', ++ promises: [] } }, beforeCreate () { @@@ -476,60 -425,6 +482,59 @@@ eventBus.$on('exec-action', (action, isGroupAction) => { this.execAction(action, isGroupAction) }) + eventBus.$on('update-bulk-job-status', (items, action) => { + for (const item of items) { - this.$store.getters.asyncJobIds.map(function (j) { ++ this.$store.getters.headerNotices.map(function (j) { + if (j.jobid === item.jobid) { + j.bulkAction = action + } + }) + } + }) + eventBus.$on('update-job-details', (jobId, resourceId) => { + const fullPath = this.$route.fullPath + const path = this.$route.path - var jobs = this.$store.getters.asyncJobIds.map(job => { ++ var jobs = this.$store.getters.headerNotices.map(job => { + if (job.jobid === jobId) { + if (resourceId && !path.includes(resourceId)) { + job.path = path + '/' + resourceId + } else { + job.path = fullPath + } + } + return job + }) - - this.$store.commit('SET_ASYNC_JOB_IDS', jobs) ++ this.$store.commit('SET_HEADER_NOTICES', jobs) + }) + + eventBus.$on('update-resource-state', (selectedItems, resource, state, jobid) => { + if (selectedItems.length === 0) { + return + } + var tempResource = [] + if (selectedItems && resource) { + if (resource.includes(',')) { + resource = resource.split(',') + tempResource = resource + } else { + tempResource.push(resource) + } + for (var r = 0; r < tempResource.length; r++) { + var objIndex = 0 + if (this.$route.path.includes('/template') || this.$route.path.includes('/iso')) { + objIndex = selectedItems.findIndex(obj => (obj.zoneid === tempResource[r])) + } else { + objIndex = selectedItems.findIndex(obj => (obj.id === tempResource[r] || obj.username === tempResource[r])) + } + if (state && objIndex !== -1) { + selectedItems[objIndex].status = state + } + if (jobid && objIndex !== -1) { + selectedItems[objIndex].jobid = jobid + } + } + } + }) if (this.device === 'desktop') { this.pageSize = 20 @@@ -1008,41 -856,34 +1013,42 @@@ }).then(function () { }) }, - pollActionCompletion (jobId, action, resourceName, showLoading = true) { + pollActionCompletion (jobId, action, resourceName, resource, showLoading = true) { + eventBus.$emit('update-job-details', jobId, resource) - this.$pollJob({ - jobId, - name: resourceName, - successMethod: result => { - this.fetchData() - if (this.selectedItems.length > 0) { - eventBus.$emit('update-resource-state', this.selectedItems, resource, 'success') - } - if (action.response) { - const description = action.response(result.jobresult) - if (description) { - this.$notification.info({ - message: this.$t(action.label), - description: (<span domPropsInnerHTML={description}></span>), - duration: 0 - }) + return new Promise((resolve) => { + this.$pollJob({ + jobId, + title: this.$t(action.label), + description: resourceName, + name: resourceName, + successMethod: result => { ++ if (this.selectedItems.length > 0) { ++ eventBus.$emit('update-resource-state', this.selectedItems, resource, 'success') + } - } - if ('successMethod' in action) { - action.successMethod(this, result) - } - }, - errorMethod: () => { - this.fetchData() - if (this.selectedItems.length > 0) { - eventBus.$emit('update-resource-state', this.selectedItems, resource, 'failed') - } - }, - loadingMessage: `${this.$t(action.label)} - ${resourceName}`, - showLoading: showLoading, - catchMessage: this.$t('error.fetching.async.job.result'), - action, - bulkAction: `${this.selectedItems.length > 0}` && this.showGroupActionModal + if (action.response) { + const description = action.response(result.jobresult) + if (description) { + this.$notification.info({ + message: this.$t(action.label), + description: (<span domPropsInnerHTML={description}></span>), + duration: 0 + }) + } + } + resolve(true) + }, + errorMethod: () => { ++ if (this.selectedItems.length > 0) { ++ eventBus.$emit('update-resource-state', this.selectedItems, resource, 'failed') ++ } + resolve(true) + }, + loadingMessage: `${this.$t(action.label)} - ${resourceName}`, + showLoading: showLoading, + catchMessage: this.$t('error.fetching.async.job.result'), - action ++ action, ++ bulkAction: `${this.selectedItems.length > 0}` && this.showGroupActionModal + }) }) }, fillEditFormFieldValues () { @@@ -1062,33 -903,9 +1068,34 @@@ } }) }, + handleCancel () { + eventBus.$emit('update-bulk-job-status', this.selectedItems, false) + this.showGroupActionModal = false + this.selectedItems = [] + this.selectedColumns = [] + this.selectedRowKeys = [] + this.message = {} + }, handleSubmit (e) { + this.promises = [] if (!this.dataView && this.currentAction.groupAction && this.selectedRowKeys.length > 0) { + if (this.selectedRowKeys.length > 0) { + this.selectedColumns = this.chosenColumns + this.selectedItems = this.selectedItems.map(v => ({ ...v, status: 'InProgress' })) + this.selectedColumns.splice(0, 0, { + dataIndex: 'status', + title: this.$t('label.operation.status'), + scopedSlots: { customRender: 'status' }, + filters: [ + { text: 'In Progress', value: 'InProgress' }, + { text: 'Success', value: 'success' }, + { text: 'Failed', value: 'failed' } + ] + }) + this.showGroupActionModal = true + this.modalInfo.title = this.currentAction.label + this.modalInfo.docHelp = this.currentAction.docHelp + } this.form.validateFields((err, values) => { if (!err) { this.actionLoading = true @@@ -1096,11 -913,11 +1103,11 @@@ this.items.map(x => { itemsNameMap[x.id] = x.name || x.displaytext || x.id }) - const paramsList = this.currentAction.groupMap(this.selectedRowKeys, values) + const paramsList = this.currentAction.groupMap(this.selectedRowKeys, values, this.items) for (const params of paramsList) { - var resourceName = itemsNameMap[params.id] + var resourceName = itemsNameMap[params.id || params.vmsnapshotid || params.username || params.name] // Using a method for this since it's an async call and don't want wrong prarms to be passed - this.callGroupApi(params, resourceName) + this.promises.push(this.callGroupApi(params, resourceName)) } this.$message.info({ content: this.$t(this.currentAction.label), @@@ -1119,46 -935,28 +1125,43 @@@ } }, callGroupApi (params, resourceName) { - const action = this.currentAction - api(action.api, params).then(json => { - this.handleResponse(json, resourceName, this.getDataIdentifier(params), action, false) - }).catch(error => { - if ([401].includes(error.response.status)) { - return - } - if (this.selectedItems.length !== 0) { - this.$notifyError(error) - eventBus.$emit('update-resource-state', this.selectedItems, this.getDataIdentifier(params), 'failed') - } + return new Promise((resolve, reject) => { + const action = this.currentAction + api(action.api, params).then(json => { - resolve(this.handleResponse(json, resourceName, action, false)) ++ resolve(this.handleResponse(json, resourceName, this.getDataIdentifier(params), action, false)) + this.closeAction() + }).catch(error => { + if ([401].includes(error.response.status)) { + return + } - this.$notifyError(error) ++ if (this.selectedItems.length !== 0) { ++ this.$notifyError(error) ++ eventBus.$emit('update-resource-state', this.selectedItems, this.getDataIdentifier(params), 'failed') ++ } + }) }) }, - handleResponse (response, resourceName, action, showLoading = true) { + getDataIdentifier (params) { + var dataIdentifier = '' + dataIdentifier = params.id || params.username || params.name || params.vmsnapshotid || params.ids + return dataIdentifier + }, + handleResponse (response, resourceName, resource, action, showLoading = true) { for (const obj in response) { if (obj.includes('response')) { if (response[obj].jobid) { - const jobid = response[obj].jobid - this.$store.dispatch('AddAsyncJob', { - title: this.$t(action.label), - jobid: jobid, - description: resourceName, - status: 'progress', - bulkAction: this.selectedItems.length > 0 && this.showGroupActionModal + return new Promise(resolve => { + const jobid = response[obj].jobid - resolve(this.pollActionCompletion(jobid, action, resourceName, showLoading)) ++ eventBus.$emit('update-resource-state', this.selectedItems, resource, 'InProgress', jobid) ++ resolve(this.pollActionCompletion(jobid, action, resourceName, resource, showLoading)) }) - eventBus.$emit('update-resource-state', this.selectedItems, resource, 'InProgress', jobid) - this.pollActionCompletion(jobid, action, resourceName, resource, showLoading) - return true } else { + if (this.selectedItems.length > 0) { + eventBus.$emit('update-resource-state', this.selectedItems, resource, 'success') + if (resource) { + this.selectedItems.filter(item => item === resource) + } + } var message = action.successMessage ? this.$t(action.successMessage) : this.$t(action.label) + (resourceName ? ' - ' + resourceName : '') var duration = 2 @@@ -1253,14 -1051,16 +1256,16 @@@ args = [action.api, params] } api(...args).then(json => { - hasJobId = this.handleResponse(json, resourceName, this.getDataIdentifier(params), action) - if ((action.icon === 'delete' || ['archiveEvents', 'archiveAlerts', 'unmanageVirtualMachine'].includes(action.api)) && this.dataView) { - this.$router.go(-1) - } else { - if (!hasJobId) { - this.fetchData() - this.handleResponse(json, resourceName, action).then(jobId => { ++ this.handleResponse(json, resourceName, this.getDataIdentifier(params), action).then(jobId => { + hasJobId = jobId + if ((action.icon === 'delete' || ['archiveEvents', 'archiveAlerts', 'unmanageVirtualMachine'].includes(action.api)) && this.dataView) { + this.$router.go(-1) + } else { + if (!hasJobId) { + this.fetchData() + } } - } + }) this.closeAction() }).catch(error => { if ([401].includes(error.response.status)) { diff --cc ui/src/views/compute/StartVirtualMachine.vue index 2a534fa,256e0dd..1c5e95a --- a/ui/src/views/compute/StartVirtualMachine.vue +++ b/ui/src/views/compute/StartVirtualMachine.vue @@@ -234,13 -244,8 +229,10 @@@ export default loadingMessage: `${this.$t('label.action.start.instance')} ${this.resource.name}`, catchMessage: this.$t('error.fetching.async.job.result'), successMessage: `${this.$t('label.action.start.instance')} ${this.resource.name}`, - successMethod: () => { - this.parentFetchData() - }, response: (result) => { return result.virtualmachine && result.virtualmachine.password ? `The password of VM <b>${result.virtualmachine.displayname}</b> is <b>${result.virtualmachine.password}</b>` : null } }) + const resourceId = this.resource.id + eventBus.$emit('update-job-details', jobId, resourceId) this.closeAction() }).catch(error => { this.$notifyError(error) diff --cc ui/src/views/image/IsoZones.vue index 984c6c7,4df911d..b06573f --- a/ui/src/views/image/IsoZones.vue +++ b/ui/src/views/image/IsoZones.vue @@@ -334,43 -246,21 +334,38 @@@ export default this.deleteLoading = true api('deleteIso', params).then(json => { const jobId = json.deleteisoresponse.jobid - this.$store.dispatch('AddAsyncJob', { - title: this.$t('label.action.delete.iso'), - jobid: jobId, - description: this.resource.name, - status: 'progress', - bulkAction: this.selectedItems.length > 0 && this.showGroupActionModal - }) + eventBus.$emit('update-job-details', jobId, null) const singleZone = (this.dataSource.length === 1) this.$pollJob({ jobId, + title: this.$t('label.action.delete.iso'), + description: this.resource.name, successMethod: result => { if (singleZone) { - this.$router.go(-1) + if (this.selectedItems.length === 0) { + this.$router.go(-1) + } } else { + if (this.selectedItems.length === 0) { + this.fetchData() + } + } + if (this.selectedItems.length > 0) { + eventBus.$emit('update-resource-state', this.selectedItems, record.zoneid, 'success') + } + }, + errorMethod: () => { + if (this.selectedItems.length === 0) { this.fetchData() } + if (this.selectedItems.length > 0) { + eventBus.$emit('update-resource-state', this.selectedItems, record.zoneid, 'failed') + } }, - errorMethod: () => this.fetchData(), + showLoading: !(this.selectedItems.length > 0 && this.showGroupActionModal), loadingMessage: `${this.$t('label.deleting.iso')} ${this.resource.name} ${this.$t('label.in.progress')}`, - catchMessage: this.$t('error.fetching.async.job.result') + catchMessage: this.$t('error.fetching.async.job.result'), + bulkAction: this.selectedItems.length > 0 && this.showGroupActionModal }) }).catch(error => { this.$notifyError(error) @@@ -415,15 -305,10 +410,11 @@@ this.copyLoading = true api('copyIso', params).then(json => { const jobId = json.copytemplateresponse.jobid - this.$store.dispatch('AddAsyncJob', { - title: this.$t('label.action.copy.iso'), - jobid: jobId, - description: this.resource.name, - status: 'progress' - }) + eventBus.$emit('update-job-details', jobId, null) this.$pollJob({ jobId, + title: this.$t('label.action.copy.iso'), + description: this.resource.name, successMethod: result => { this.fetchData() }, diff --cc ui/src/views/image/TemplateZones.vue index d8ed93b,edbedbf..692096c --- a/ui/src/views/image/TemplateZones.vue +++ b/ui/src/views/image/TemplateZones.vue @@@ -382,14 -258,6 +382,7 @@@ export default this.deleteLoading = true api('deleteTemplate', params).then(json => { const jobId = json.deletetemplateresponse.jobid - this.$store.dispatch('AddAsyncJob', { - title: this.$t('label.action.delete.template'), - jobid: jobId, - description: this.resource.name, - status: 'progress', - bulkAction: this.selectedItems.length > 0 && this.showGroupActionModal - }) + eventBus.$emit('update-job-details', jobId, null) const singleZone = (this.dataSource.length === 1) this.$pollJob({ jobId, @@@ -483,15 -327,10 +478,11 @@@ this.copyLoading = true api('copyTemplate', params).then(json => { const jobId = json.copytemplateresponse.jobid - this.$store.dispatch('AddAsyncJob', { - title: this.$t('label.action.copy.template'), - jobid: jobId, - description: this.resource.name, - status: 'progress' - }) + eventBus.$emit('update-job-details', jobId, null) this.$pollJob({ jobId, + title: this.$t('label.action.copy.template'), + description: this.resource.name, successMethod: result => { this.fetchData() }, diff --cc ui/src/views/network/LoadBalancing.vue index 8315219,66dd0d8..08e99fa --- a/ui/src/views/network/LoadBalancing.vue +++ b/ui/src/views/network/LoadBalancing.vue @@@ -1032,52 -934,29 +1022,52 @@@ export default api('deleteLoadBalancerRule', { id: rule.id }).then(response => { + const jobId = response.deleteloadbalancerruleresponse.jobid + this.$store.dispatch('AddAsyncJob', { + title: this.$t('label.action.delete.load.balancer'), + jobid: jobId, + description: rule.id, + status: 'progress', + bulkAction: this.selectedItems.length > 0 && this.showGroupActionModal + }) + eventBus.$emit('update-job-details', jobId, null) this.$pollJob({ - jobId: response.deleteloadbalancerruleresponse.jobid, + jobId: jobId, successMessage: this.$t('message.success.remove.rule'), successMethod: () => { - this.parentToggleLoading() - this.fetchData() + if (this.selectedItems.length > 0) { + eventBus.$emit('update-resource-state', this.selectedItems, rule.id, 'success') + } + if (this.selectedRowKeys.length === 0) { - this.parentFetchData() + this.parentToggleLoading() ++ this.fetchData() + } this.closeModal() }, errorMessage: this.$t('message.remove.rule.failed'), errorMethod: () => { - this.parentToggleLoading() - this.fetchData() + if (this.selectedItems.length > 0) { + eventBus.$emit('update-resource-state', this.selectedItems, rule.id, 'failed') + } + if (this.selectedRowKeys.length === 0) { - this.parentFetchData() + this.parentToggleLoading() ++ this.fetchData() + } this.closeModal() }, loadingMessage: this.$t('message.delete.rule.processing'), catchMessage: this.$t('error.fetching.async.job.result'), catchMethod: () => { - this.parentToggleLoading() - this.fetchData() + if (this.selectedRowKeys.length === 0) { - this.parentFetchData() + this.parentToggleLoading() ++ this.parentFetchData() + } this.closeModal() - } + }, + bulkAction: `${this.selectedItems.length > 0}` && this.showGroupActionModal }) }).catch(error => { + console.log(error) this.$notifyError(error) this.loading = false })
