feat: clear selected VM after doing bulk action (#929)

* feat: clear selected VM rows after click bulk action

Signed-off-by: Andy Lee <andy.lee@suse.com>

* refactor: await altStopVM action

Signed-off-by: Andy Lee <andy.lee@suse.com>

* refactor: multiple VM start actions

Signed-off-by: Andy Lee <andy.lee@suse.com>

* refactor: modify altRestartVM()

Signed-off-by: Andy Lee <andy.lee@suse.com>

---------

Signed-off-by: Andy Lee <andy.lee@suse.com>
This commit is contained in:
Andy Lee 2026-06-17 13:55:01 +08:00 committed by GitHub
parent f115261889
commit 5e3f12de35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 52 additions and 21 deletions

View File

@ -98,9 +98,9 @@ export default {
methods: { methods: {
escapeHtml, escapeHtml,
close() { close(data) {
this.errors = []; this.errors = [];
this.$emit('close'); this.$emit('close', data);
}, },
async apply(buttonDone) { async apply(buttonDone) {
@ -109,7 +109,7 @@ export default {
await resource.doActionGrowl(this.modalData.action, {}); await resource.doActionGrowl(this.modalData.action, {});
} }
buttonDone(true); buttonDone(true);
this.close(); this.close({ performCallback: true, clearTableSelection: true });
} catch (e) { } catch (e) {
this.errors = exceptionToErrorsArray(e); this.errors = exceptionToErrorsArray(e);
buttonDone(false); buttonDone(false);

View File

@ -117,10 +117,10 @@ export default {
}, },
methods: { methods: {
close() { close(data) {
this.nodeName = ''; this.nodeName = '';
this.errors = []; this.errors = [];
this.$emit('close'); this.$emit('close', data);
}, },
async apply(buttonDone) { async apply(buttonDone) {
@ -166,7 +166,7 @@ export default {
} }
buttonDone(true); buttonDone(true);
this.close(); this.close({ performCallback: true, clearTableSelection: true });
} catch (err) { } catch (err) {
const error = err?.data || err; const error = err?.data || err;
const message = exceptionToErrorsArray(error); const message = exceptionToErrorsArray(error);

View File

@ -1,4 +1,5 @@
<script> <script>
import { mapGetters } from 'vuex';
import ResourceTable from '@shell/components/ResourceTable'; import ResourceTable from '@shell/components/ResourceTable';
import { STATE, AGE, NAME, NAMESPACE } from '@shell/config/table-headers'; import { STATE, AGE, NAME, NAMESPACE } from '@shell/config/table-headers';
import { import {
@ -116,6 +117,8 @@ export default {
}, },
computed: { computed: {
...mapGetters({ actionCb: 'action-menu/performCallbackData' }),
headers() { headers() {
const restoreCol = { const restoreCol = {
name: 'restoreProgress', name: 'restoreProgress',
@ -182,6 +185,13 @@ export default {
}, },
watch: { watch: {
actionCb(neu) {
if (neu?.clearTableSelection) {
this.$refs.resourceTable.clearSelection();
this.$store.dispatch('action-menu/clearCallbackData');
}
},
vmRestartRequiredNames(vmNames) { vmRestartRequiredNames(vmNames) {
const count = vmNames.length; const count = vmNames.length;
@ -220,6 +230,7 @@ export default {
<Loading v-if="$fetchState.pending" /> <Loading v-if="$fetchState.pending" />
<div v-else> <div v-else>
<ResourceTable <ResourceTable
ref="resourceTable"
v-bind="$attrs" v-bind="$attrs"
:headers="headers" :headers="headers"
default-sort-by="age" default-sort-by="age"

View File

@ -184,11 +184,12 @@ export default class VirtVm extends HarvesterResource {
label: this.t('harvester.action.softreboot') label: this.t('harvester.action.softreboot')
}, },
{ {
action: 'startVM', action: 'startVM',
enabled: !!this.actions?.start, enabled: !!this.actions?.start,
icon: 'icon icon-play', icon: 'icon icon-play',
label: this.t('harvester.action.start'), label: this.t('harvester.action.start'),
bulkable: true bulkable: true,
bulkAction: 'startVM'
}, },
{ {
action: 'backupVM', action: 'backupVM',
@ -378,10 +379,6 @@ export default class VirtVm extends HarvesterResource {
this.metadata.annotations[HCI_ANNOTATIONS.VOLUME_CLAIM_TEMPLATE] = JSON.stringify(deleteDataSource); this.metadata.annotations[HCI_ANNOTATIONS.VOLUME_CLAIM_TEMPLATE] = JSON.stringify(deleteDataSource);
} }
altRestartVM() {
this.doActionGrowl('restart', {});
}
restartVM(resources = this) { restartVM(resources = this) {
this.$dispatch('promptModal', { this.$dispatch('promptModal', {
resources, resources,
@ -553,16 +550,38 @@ export default class VirtVm extends HarvesterResource {
}); });
} }
altStopVM() { async altRestartVM() {
this.doActionGrowl('stop', {}); await this.doActionGrowl('restart', {});
this.$dispatch('promptModal', { performCallback: true, clearTableSelection: true });
} }
forceStop() { async altStopVM() {
this.doActionGrowl('forceStop', {}); await this.doActionGrowl('stop', {});
this.$dispatch('promptModal', { performCallback: true, clearTableSelection: true });
} }
startVM() { async forceStop() {
this.doActionGrowl('start', {}); await this.doActionGrowl('forceStop', {});
this.$dispatch('promptModal', { performCallback: true, clearTableSelection: true });
}
async startVM(resources = this) {
const list = Array.isArray(resources) ? resources : [resources];
for (const r of list) {
await r.doActionGrowl('start', {});
}
this.$dispatch('promptModal', { performCallback: true, clearTableSelection: true });
}
async download() {
await super.download();
this.$dispatch('promptModal', { performCallback: true, clearTableSelection: true });
}
async downloadBulk(items) {
await super.downloadBulk(items);
this.$dispatch('promptModal', { performCallback: true, clearTableSelection: true });
} }
migrateVM(resources = this) { migrateVM(resources = this) {

View File

@ -123,6 +123,7 @@ export default {
this.value?.[0]?.currentRouter().push(goTo); this.value?.[0]?.currentRouter().push(goTo);
} }
this.close(); this.close();
this.$store.commit('action-menu/togglePromptModal', { performCallback: true, clearTableSelection: true });
}).catch((err) => { }).catch((err) => {
this.$emit('errors', err); this.$emit('errors', err);
}); });