pve-manager/www/manager6/grid/ResourceGrid.js
Dominik Csapak aa54d20851 ui: implement 'Tag View' for the resource tree
and keep the functionality in ResourceTree as generic as possible.

We achieve this by having an 'itemMap' function that can split one item
from the store into multiple to add to the tree.

for the updates, we have to have an 'idMapFn' (to get the original id
back)

we also have to modify how the move checks work a bit, since we only
want to move the items when the tags changed only in the tagview case

in the ResourceGrid we have to get the id a bit differently since we now
have 'virtual' ids for the entries tag contain the tag (which can't be
found in the resource store)

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
2024-11-10 11:29:49 +01:00

139 lines
3.1 KiB
JavaScript

Ext.define('PVE.grid.ResourceGrid', {
extend: 'Ext.grid.GridPanel',
alias: ['widget.pveResourceGrid'],
border: false,
defaultSorter: {
property: 'type',
direction: 'ASC',
},
userCls: 'proxmox-tags-full',
initComponent: function() {
let me = this;
let rstore = PVE.data.ResourceStore;
let store = Ext.create('Ext.data.Store', {
model: 'PVEResources',
sorters: me.defaultSorter,
proxy: {
type: 'memory',
},
});
let textfilter = '';
let textfilterMatch = function(item) {
for (const field of ['name', 'storage', 'node', 'type', 'text']) {
let v = item.data[field];
if (v && v.toLowerCase().indexOf(textfilter) >= 0) {
return true;
}
}
return false;
};
let updateGrid = function() {
var filterfn = me.viewFilter ? me.viewFilter.filterfn : null;
store.suspendEvents();
let nodeidx = {};
let gather_child_nodes;
gather_child_nodes = function(node) {
if (!node || !node.childNodes) {
return;
}
for (let child of node.childNodes) {
let orgNode = rstore.data.get(child.data.realId ?? child.data.id);
if (orgNode) {
if ((!filterfn || filterfn(child)) && (!textfilter || textfilterMatch(child))) {
nodeidx[child.data.id] = orgNode;
}
}
gather_child_nodes(child);
}
};
gather_child_nodes(me.pveSelNode);
// remove vanished items
let rmlist = [];
store.each(olditem => {
if (!nodeidx[olditem.data.id]) {
rmlist.push(olditem);
}
});
if (rmlist.length) {
store.remove(rmlist);
}
// add new items
let addlist = [];
for (const [_key, item] of Object.entries(nodeidx)) {
// getById() use find(), which is slow (ExtJS4 DP5)
let olditem = store.data.get(item.data.id);
if (!olditem) {
addlist.push(item);
continue;
}
let changes = false;
for (let field of PVE.data.ResourceStore.fieldNames) {
if (field !== 'id' && item.data[field] !== olditem.data[field]) {
changes = true;
olditem.beginEdit();
olditem.set(field, item.data[field]);
}
}
if (changes) {
olditem.endEdit(true);
olditem.commit(true);
}
}
if (addlist.length) {
store.add(addlist);
}
store.sort();
store.resumeEvents();
store.fireEvent('refresh', store);
};
Ext.apply(me, {
store: store,
stateful: true,
stateId: 'grid-resource',
tbar: [
'->',
gettext('Search') + ':', ' ',
{
xtype: 'textfield',
width: 200,
value: textfilter,
enableKeyEvents: true,
listeners: {
buffer: 500,
keyup: function(field, e) {
textfilter = field.getValue().toLowerCase();
updateGrid();
},
},
},
],
viewConfig: {
stripeRows: true,
},
listeners: {
itemcontextmenu: PVE.Utils.createCmdMenu,
itemdblclick: function(v, record) {
var ws = me.up('pveStdWorkspace');
ws.selectById(record.data.id);
},
afterrender: function() {
updateGrid();
},
},
columns: rstore.defaultColumns(),
});
me.callParent();
me.mon(rstore, 'load', () => updateGrid());
},
});