pve-manager/www/manager6/form/VMSelector.js
Dominik Csapak 11fc6d7fb5 ui: guest selector: switch from post-filter to query param for API call
So that we can modify any filters without always having to consider
filtering for the type too. Note that the 'vm' tyoe here is slightly
confusing and should actually be 'guest', as this also returns
containers. Reduces transmission size a bit as nice side effect.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2023-03-11 18:47:34 +01:00

327 lines
6.1 KiB
JavaScript

/* filter is a javascript builtin, but extjs calls it also filter */
Ext.define('PVE.form.VMSelector', {
extend: 'Ext.grid.Panel',
alias: 'widget.vmselector',
mixins: {
field: 'Ext.form.field.Field',
},
allowBlank: true,
selectAll: false,
isFormField: true,
plugins: 'gridfilters',
store: {
model: 'PVEResources',
sorters: 'vmid',
},
columnsDeclaration: [
{
header: 'ID',
dataIndex: 'vmid',
width: 80,
filter: {
type: 'number',
},
},
{
header: gettext('Node'),
dataIndex: 'node',
},
{
header: gettext('Status'),
dataIndex: 'status',
filter: {
type: 'list',
},
},
{
header: gettext('Name'),
dataIndex: 'name',
flex: 1,
filter: {
type: 'string',
},
},
{
header: gettext('Pool'),
dataIndex: 'pool',
filter: {
type: 'list',
},
},
{
header: gettext('Type'),
dataIndex: 'type',
width: 120,
renderer: function(value) {
if (value === 'qemu') {
return gettext('Virtual Machine');
} else if (value === 'lxc') {
return gettext('LXC Container');
}
return '';
},
filter: {
type: 'list',
store: {
data: [
{ id: 'qemu', text: gettext('Virtual Machine') },
{ id: 'lxc', text: gettext('LXC Container') },
],
un: function() {
// Due to EXTJS-18711. we have to do a static list via a store but to avoid
// creating an object, we have to have an empty pseudo un function
},
},
},
},
{
header: 'HA ' + gettext('Status'),
dataIndex: 'hastate',
flex: 1,
filter: {
type: 'list',
},
},
],
// should be a list of 'dataIndex' values, if 'undefined' all declared columns will be included
columnSelection: undefined,
selModel: {
selType: 'checkboxmodel',
mode: 'SIMPLE',
},
checkChangeEvents: [
'selectionchange',
'change',
],
listeners: {
selectionchange: function() {
// to trigger validity and error checks
this.checkChange();
},
},
getValue: function() {
var me = this;
if (me.savedValue !== undefined) {
return me.savedValue;
}
var sm = me.getSelectionModel();
var selection = sm.getSelection();
var values = [];
var store = me.getStore();
selection.forEach(function(item) {
// only add if not filtered
if (store.findExact('vmid', item.data.vmid) !== -1) {
values.push(item.data.vmid);
}
});
return values;
},
setValueSelection: function(value) {
let me = this;
let store = me.getStore();
let selection = value.map(item => store.findRecord('vmid', item, 0, false, true, true)).filter(r => r);
let sm = me.getSelectionModel();
if (selection.length) {
sm.select(selection);
} else {
sm.deselectAll();
}
},
setValue: function(value) {
let me = this;
if (!Ext.isArray(value)) {
value = value.split(',');
}
let store = me.getStore();
if (!store.isLoaded()) {
me.savedValue = value;
store.on('load', function() {
me.setValueSelection(value);
delete me.savedValue;
}, { single: true });
} else {
me.setValueSelection(value);
}
return me.mixins.field.setValue.call(me, value);
},
getErrors: function(value) {
let me = this;
if (me.allowBlank === false &&
me.getSelectionModel().getCount() === 0) {
me.addBodyCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
return [gettext('No VM selected')];
}
me.removeBodyCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
return [];
},
initComponent: function() {
let me = this;
let columns = me.columnsDeclaration.filter((column) =>
me.columnSelection ? me.columnSelection.indexOf(column.dataIndex) !== -1 : true,
).map((x) => x);
me.columns = columns;
me.callParent();
me.getStore().load({ params: { type: 'vm' } });
if (me.nodename) {
me.store.filters.add({
property: 'node',
exactMatch: true,
value: me.nodename,
});
}
// only show the relevant guests by default
if (me.action) {
var statusfilter = '';
switch (me.action) {
case 'startall':
statusfilter = 'stopped';
break;
case 'stopall':
statusfilter = 'running';
break;
}
if (statusfilter !== '') {
me.store.filters.add({
property: 'template',
value: 0,
}, {
id: 'x-gridfilter-status',
operator: 'in',
property: 'status',
value: [statusfilter],
});
}
}
if (me.selectAll) {
me.mon(me.getStore(), 'load', function() {
me.getSelectionModel().selectAll(false);
});
}
},
});
Ext.define('PVE.form.VMComboSelector', {
extend: 'Proxmox.form.ComboGrid',
alias: 'widget.vmComboSelector',
valueField: 'vmid',
displayField: 'vmid',
autoSelect: false,
editable: true,
anyMatch: true,
forceSelection: true,
store: {
model: 'PVEResources',
autoLoad: true,
sorters: 'vmid',
filters: [{
property: 'type',
value: /lxc|qemu/,
}],
},
listConfig: {
width: 600,
plugins: 'gridfilters',
columns: [
{
header: 'ID',
dataIndex: 'vmid',
width: 80,
filter: {
type: 'number',
},
},
{
header: gettext('Name'),
dataIndex: 'name',
flex: 1,
filter: {
type: 'string',
},
},
{
header: gettext('Node'),
dataIndex: 'node',
},
{
header: gettext('Status'),
dataIndex: 'status',
filter: {
type: 'list',
},
},
{
header: gettext('Pool'),
dataIndex: 'pool',
hidden: true,
filter: {
type: 'list',
},
},
{
header: gettext('Type'),
dataIndex: 'type',
width: 120,
renderer: function(value) {
if (value === 'qemu') {
return gettext('Virtual Machine');
} else if (value === 'lxc') {
return gettext('LXC Container');
}
return '';
},
filter: {
type: 'list',
store: {
data: [
{ id: 'qemu', text: gettext('Virtual Machine') },
{ id: 'lxc', text: gettext('LXC Container') },
],
un: function() { /* due to EXTJS-18711 */ },
},
},
},
{
header: 'HA ' + gettext('Status'),
dataIndex: 'hastate',
hidden: true,
flex: 1,
filter: {
type: 'list',
},
},
],
},
});