mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-10-01 03:36:04 +08:00
Update USB devices
- Add columns and filters - Filter other vm devices in pci and usb devices pages when selecting devices Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
This commit is contained in:
@@ -55,10 +55,13 @@ export default {
|
||||
const selectedDevices = [];
|
||||
const oldFormatDevices = [];
|
||||
|
||||
(this.value?.domain?.devices?.hostDevices || []).forEach(({ name, deviceName }) => {
|
||||
const vmDevices = this.value?.domain?.devices?.hostDevices || [];
|
||||
const otherDevices = this.otherDevices(vmDevices).map(({name}) => name);
|
||||
|
||||
vmDevices.forEach(({ name, deviceName }) => {
|
||||
const checkName = (deviceName || '').split('/')?.[1];
|
||||
|
||||
if (checkName && name.includes(checkName)) {
|
||||
if (checkName && name.includes(checkName) && !otherDevices.includes(name)) {
|
||||
oldFormatDevices.push(name);
|
||||
} else if (this.enabledDevices.find(device => device?.metadata?.name === name)) {
|
||||
selectedDevices.push(name);
|
||||
@@ -96,7 +99,12 @@ export default {
|
||||
};
|
||||
});
|
||||
|
||||
set(this.value.domain.devices, 'hostDevices', formatted);
|
||||
const devices = [
|
||||
...this.otherDevices(this.value.domain.devices.hostDevices),
|
||||
...formatted,
|
||||
];
|
||||
|
||||
set(this.value.domain.devices, 'hostDevices', devices);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -187,6 +195,10 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
otherDevices(vmDevices) {
|
||||
return vmDevices.filter((device) => !this.pciDevices.find((pci) => device.name === pci.name));
|
||||
},
|
||||
|
||||
nodeNameFromUid(uid) {
|
||||
for (const deviceUid in this.uniqueDevices) {
|
||||
const nodes = this.uniqueDevices[deviceUid].nodes;
|
||||
|
||||
@@ -34,6 +34,36 @@ export default {
|
||||
const headers = [
|
||||
{ ...STATE },
|
||||
SIMPLE_NAME,
|
||||
{
|
||||
name: 'description',
|
||||
labelKey: 'tableHeaders.description',
|
||||
value: 'status.description',
|
||||
sort: ['status.description']
|
||||
},
|
||||
{
|
||||
name: 'node',
|
||||
labelKey: 'tableHeaders.node',
|
||||
value: 'status.nodeName',
|
||||
sort: ['status.nodeName']
|
||||
},
|
||||
{
|
||||
name: 'pciAddress',
|
||||
label: 'Address',
|
||||
value: 'status.pciAddress',
|
||||
sort: ['status.pciAddress']
|
||||
},
|
||||
{
|
||||
name: 'vendorID',
|
||||
label: 'Vendor ID',
|
||||
value: 'status.vendorID',
|
||||
sort: ['status.vendorID', 'status.productID']
|
||||
},
|
||||
{
|
||||
name: 'productID',
|
||||
label: 'Product ID',
|
||||
value: 'status.productID',
|
||||
sort: ['status.productID', 'status.vendorID']
|
||||
},
|
||||
];
|
||||
|
||||
if (!isSingleProduct) {
|
||||
@@ -58,12 +88,32 @@ export default {
|
||||
handler(v) {
|
||||
this.rows = v;
|
||||
this.filterRows = this.rows;
|
||||
|
||||
console.log(this.filterRows)
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
enableGroup(rows = []) {
|
||||
const row = rows[0];
|
||||
|
||||
if (row) {
|
||||
row.enablePassthroughBulk(rows);
|
||||
}
|
||||
},
|
||||
disableGroup(rows = []) {
|
||||
rows.forEach((row) => {
|
||||
if (row.passthroughClaim) {
|
||||
row.disablePassthrough();
|
||||
}
|
||||
});
|
||||
},
|
||||
groupIsAllEnabled(rows = []) {
|
||||
return !rows.find(device => !device.passthroughClaim);
|
||||
},
|
||||
|
||||
changeRows(filterRows) {
|
||||
this.$set(this, 'filterRows', filterRows);
|
||||
},
|
||||
@@ -94,6 +144,17 @@ export default {
|
||||
:sort-generation-fn="sortGenerationFn"
|
||||
:rows-per-page="10"
|
||||
>
|
||||
<template #group-by="{group}">
|
||||
<div :ref="group.key" v-trim-whitespace class="group-tab">
|
||||
<button v-if="groupIsAllEnabled(group.rows)" type="button" class="btn btn-sm role-secondary mr-5" @click="e=>{disableGroup(group.rows); e.target.blur()}">
|
||||
{{ t('harvester.usb.disableGroup') }}
|
||||
</button>
|
||||
<button v-else type="button" class="btn btn-sm role-secondary mr-5" @click="e=>{enableGroup(group.rows); e.target.blur()}">
|
||||
{{ t('harvester.usb.enableGroup') }}
|
||||
</button>
|
||||
<span v-clean-html="group.key" />
|
||||
</div>
|
||||
</template>
|
||||
<template #cell:claimed="{row}">
|
||||
<span v-if="row.isEnabled">{{ row.claimedBy }}</span>
|
||||
<span v-else class="text-muted">—</span>
|
||||
|
||||
@@ -8,6 +8,9 @@ import Banner from '@components/Banner/Banner.vue';
|
||||
import CompatibilityMatrix from '../CompatibilityMatrix';
|
||||
import DeviceList from './DeviceList';
|
||||
|
||||
import remove from 'lodash/remove';
|
||||
import { get, set } from '@shell/utils/object';
|
||||
|
||||
export default {
|
||||
name: 'VirtualMachineUSBDevices',
|
||||
components: {
|
||||
@@ -44,6 +47,10 @@ export default {
|
||||
for (const key in res) {
|
||||
this[key] = res[key];
|
||||
}
|
||||
|
||||
this.selectedDevices = (this.value?.domain?.devices?.hostDevices || [])
|
||||
.map(({ name }) => name)
|
||||
.filter((name) => this.enabledDevices.find(device => device?.metadata?.name === name));
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -60,13 +67,34 @@ export default {
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
selectedDevices(neu) {
|
||||
const formatted = neu.map((selectedDevice) => {
|
||||
const deviceCRD = this.enabledDevices.find(device => device.metadata.name === selectedDevice);
|
||||
const deviceName = deviceCRD?.status?.resourceName;
|
||||
|
||||
return {
|
||||
deviceName,
|
||||
name: deviceCRD?.metadata.name,
|
||||
};
|
||||
});
|
||||
|
||||
const devices = [
|
||||
...this.otherDevices(this.value.domain.devices.hostDevices),
|
||||
...formatted,
|
||||
];
|
||||
|
||||
set(this.value.domain.devices, 'hostDevices', devices);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
deviceOpts() {
|
||||
const filteredOptions = this.enabledDevices.filter((deviceCRD) => {
|
||||
if (this.selectedDevices.length > 0) {
|
||||
const selectedDevice = this.enabledDevices.find(device => device.metadata.name === this.selectedDevices[0]);
|
||||
|
||||
return !this.devicesInUse[deviceCRD?.metadata.name] && deviceCRD.status.nodeName === selectedDevice.status.nodeName;
|
||||
return !this.devicesInUse[deviceCRD?.metadata.name] && deviceCRD.status.nodeName === selectedDevice?.status.nodeName;
|
||||
}
|
||||
|
||||
return !this.devicesInUse[deviceCRD?.metadata.name];
|
||||
@@ -76,14 +104,14 @@ export default {
|
||||
return {
|
||||
value: deviceCRD?.metadata.name,
|
||||
label: deviceCRD?.metadata.name,
|
||||
displayLabel: deviceCRD?.status?.resourceName,
|
||||
displayLabel: deviceCRD?.status?.description,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
enabledDevices() {
|
||||
return this.devices.filter((device) => {
|
||||
return device.isEnabled;
|
||||
return device.status.enabled;
|
||||
}) || [];
|
||||
},
|
||||
|
||||
@@ -108,7 +136,7 @@ export default {
|
||||
const out = {};
|
||||
|
||||
this.enabledDevices.forEach((deviceCRD) => {
|
||||
const nodeName = deviceCRD.spec?.nodeName;
|
||||
const nodeName = deviceCRD.status?.nodeName;
|
||||
|
||||
if (!out[nodeName]) {
|
||||
out[nodeName] = [deviceCRD];
|
||||
@@ -127,13 +155,19 @@ export default {
|
||||
remove(out, (nodeName) => {
|
||||
const device = this.enabledDevices.find(deviceCRD => deviceCRD.metadata.name === deviceUid);
|
||||
|
||||
return device.spec.nodeName !== nodeName;
|
||||
return device?.status.nodeName !== nodeName;
|
||||
});
|
||||
});
|
||||
|
||||
return out;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
otherDevices(vmDevices) {
|
||||
return vmDevices.filter((device) => !this.devices.find((usb) => device.name === usb.name));
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user