feat: add selected all | clear all actions for selected VM

Signed-off-by: Andy Lee <andy.lee@suse.com>
This commit is contained in:
Andy Lee 2026-07-31 14:03:27 +08:00
parent 7db6c81c5c
commit facddcb9a7
No known key found for this signature in database
GPG Key ID: 39DC4436AE3564D5
2 changed files with 63 additions and 4 deletions

View File

@ -94,7 +94,7 @@ const showSelectAllBanner = computed(() => {
const theadElement = computed(() => sortableTableRef.value?.$el?.querySelector('thead'));
const headers = [
const headers = ref([
{
name: 'vmName',
labelKey: 'harvester.addons.vmMigration.selectVms.columns.vmName',
@ -139,7 +139,7 @@ const headers = [
subLabel: t('harvester.addons.vmMigration.generic.identifier'),
width: 200,
},
];
]);
const buildTableRows = () => {
return discoveredVMs.value.map((vm) => {
@ -190,6 +190,7 @@ const buildTableRows = () => {
return {
_original: vm,
_key: vm.id || vm.vmId || vm.metadata?.name,
selectedSort: selectedVMIds.value.has(vm.id) ? 0 : 1,
vmName: vm.name || vm.metadata?.name || '-',
vmId: vm.id || vm.vmId || vm.metadata?.name || '-',
os: vm.guestName || vm.guestOS || vm.os || '-',
@ -243,6 +244,29 @@ const clearSelection = () => {
});
};
// Re-sorts the table so currently-selected VMs appear on the first pages.
const showSelectedFirst = () => {
if (selectedVMIds.value.size === 0) {
return;
}
tableRows.value.forEach((row) => {
row.selectedSort = selectedVMIds.value.has(row._original?.id) ? 0 : 1;
});
headers.value = headers.value.map((h) => (
h.name === 'vmName' ? { ...h, sort: ['selectedSort', 'vmName'] } : h
));
nextTick(() => {
const table = sortableTableRef.value;
if (table) {
table.page = 1;
}
});
};
const selectAllVMs = () => {
allVMsSelected.value = true;
selectedVMIds.value = new Set(discoveredVMs.value.map((vm) => vm.id));
@ -450,7 +474,24 @@ init();
<h3 class="m-0">
{{ t('harvester.addons.vmMigration.selectVms.availableVms') }}
</h3>
<span class="text-deemphasized">{{ selectedCount }} {{ t('harvester.addons.vmMigration.selectVms.selected') }}</span>
<span class="selected-actions">
<a
role="button"
:class="{ disabled: selectedCount === 0 }"
@click.prevent="showSelectedFirst"
>
{{ selectedCount }} {{ t('harvester.addons.vmMigration.selectVms.selected') }}
</a>
<template v-if="selectedCount > 0">
<span class="text-deemphasized">|</span>
<a
role="button"
@click.prevent="clearSelection"
>
{{ t('harvester.addons.vmMigration.selectVms.clearAll') }}
</a>
</template>
</span>
</div>
</template>
<template #cell:vmName="{ row }">
@ -466,7 +507,7 @@ init();
<template #cell:powerState="{ row }">
<BadgeState
:label="row.powerState"
:color="row.powerStateClass === 'power-on' ? 'bg-warning' : 'bg-darker'"
:color="row.powerStateClass === 'power-on' ? 'bg-success' : 'bg-darker'"
/>
</template>
<template #cell:network="{ row }">
@ -533,6 +574,23 @@ init();
.text-deemphasized {
font-size: 13px;
}
.selected-actions {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
a {
cursor: pointer;
&.disabled {
color: var(--muted);
cursor: default;
pointer-events: none;
}
}
}
}
.vm-name-cell {

View File

@ -1922,6 +1922,7 @@ harvester:
refreshNow: Refresh now
availableVms: Available Virtual Machines
selected: selected
clearAll: Clear All
saveSelection: Save Selection and Continue
selectAllBanner:
pageOnly: "Your current selection includes only VMs currently shown on the page."