ui: add search box to DataStore content
which searches the whole tree (name & owner) we do this by traversing the tree and marking elements as matches, then afterwards make a simple filter that matches on a boolean worst case cost of this is O(2n) since we have to traverse the tree (in the worst) case one time, and the filter function does it again Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
3e395378bc
commit
6d55603dcc
@ -35,7 +35,12 @@ Ext.define('pbs-data-store-snapshots', {
|
|||||||
|
|
||||||
return PBS.Utils.calculateCryptMode(crypt);
|
return PBS.Utils.calculateCryptMode(crypt);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
name: 'matchesFilter',
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -126,6 +131,7 @@ Ext.define('PBS.DataStoreContent', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onLoad: function(store, records, success, operation) {
|
onLoad: function(store, records, success, operation) {
|
||||||
|
let me = this;
|
||||||
let view = this.getView();
|
let view = this.getView();
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@ -144,12 +150,14 @@ Ext.define('PBS.DataStoreContent', {
|
|||||||
data.text = group + '/' + PBS.Utils.render_datetime_utc(data["backup-time"]);
|
data.text = group + '/' + PBS.Utils.render_datetime_utc(data["backup-time"]);
|
||||||
data.leaf = false;
|
data.leaf = false;
|
||||||
data.cls = 'no-leaf-icons';
|
data.cls = 'no-leaf-icons';
|
||||||
|
data.matchesFilter = true;
|
||||||
|
|
||||||
data.children = [];
|
data.children = [];
|
||||||
for (const file of data.files) {
|
for (const file of data.files) {
|
||||||
file.text = file.filename,
|
file.text = file.filename,
|
||||||
file['crypt-mode'] = PBS.Utils.cryptmap.indexOf(file['crypt-mode']);
|
file['crypt-mode'] = PBS.Utils.cryptmap.indexOf(file['crypt-mode']);
|
||||||
file.leaf = true;
|
file.leaf = true;
|
||||||
|
file.matchesFilter = true;
|
||||||
|
|
||||||
data.children.push(file);
|
data.children.push(file);
|
||||||
}
|
}
|
||||||
@ -178,6 +186,7 @@ Ext.define('PBS.DataStoreContent', {
|
|||||||
|
|
||||||
}
|
}
|
||||||
group.count = group.children.length;
|
group.count = group.children.length;
|
||||||
|
group.matchesFilter = true;
|
||||||
crypt.count = group.count;
|
crypt.count = group.count;
|
||||||
group['crypt-mode'] = PBS.Utils.calculateCryptMode(crypt);
|
group['crypt-mode'] = PBS.Utils.calculateCryptMode(crypt);
|
||||||
children.push(group);
|
children.push(group);
|
||||||
@ -188,6 +197,11 @@ Ext.define('PBS.DataStoreContent', {
|
|||||||
children: children
|
children: children
|
||||||
});
|
});
|
||||||
Proxmox.Utils.setErrorMask(view, false);
|
Proxmox.Utils.setErrorMask(view, false);
|
||||||
|
if (view.getStore().getFilters().length > 0) {
|
||||||
|
let searchBox = me.lookup("searchbox");
|
||||||
|
let searchvalue = searchBox.getValue();;
|
||||||
|
me.search(searchBox, searchvalue);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onPrune: function(view, rI, cI, item, e, rec) {
|
onPrune: function(view, rI, cI, item, e, rec) {
|
||||||
@ -331,7 +345,71 @@ Ext.define('PBS.DataStoreContent', {
|
|||||||
'backup-type': type,
|
'backup-type': type,
|
||||||
archive: rec.data.filename,
|
archive: rec.data.filename,
|
||||||
}).show();
|
}).show();
|
||||||
}
|
},
|
||||||
|
|
||||||
|
filter: function(item, value) {
|
||||||
|
if (item.data.text.indexOf(value) !== -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.data.owner && item.data.owner.indexOf(value) !== -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
search: function(tf, value) {
|
||||||
|
let me = this;
|
||||||
|
let view = me.getView();
|
||||||
|
let store = view.getStore();
|
||||||
|
if (!value && value !== 0) {
|
||||||
|
store.clearFilter();
|
||||||
|
store.getRoot().collapseChildren(true);
|
||||||
|
tf.triggers.clear.setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tf.triggers.clear.setVisible(true);
|
||||||
|
if (value.length < 2) return;
|
||||||
|
Proxmox.Utils.setErrorMask(view, true);
|
||||||
|
// we do it a little bit later for the error mask to work
|
||||||
|
setTimeout(function() {
|
||||||
|
store.clearFilter();
|
||||||
|
store.getRoot().collapseChildren(true);
|
||||||
|
|
||||||
|
store.beginUpdate();
|
||||||
|
store.getRoot().cascadeBy({
|
||||||
|
before: function(item) {
|
||||||
|
if(me.filter(item, value)) {
|
||||||
|
item.set('matchesFilter', true);
|
||||||
|
if (item.parentNode && item.parentNode.id !== 'root') {
|
||||||
|
item.parentNode.childmatches = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
after: function(item) {
|
||||||
|
if (me.filter(item, value) || item.id === 'root' || item.childmatches) {
|
||||||
|
item.set('matchesFilter', true);
|
||||||
|
if (item.parentNode && item.parentNode.id !== 'root') {
|
||||||
|
item.parentNode.childmatches = true;
|
||||||
|
}
|
||||||
|
if (item.childmatches) {
|
||||||
|
item.expand();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.set('matchesFilter', false);
|
||||||
|
}
|
||||||
|
delete item.childmatches;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
store.endUpdate();
|
||||||
|
|
||||||
|
store.filter((item) => !!item.get('matchesFilter'));
|
||||||
|
Proxmox.Utils.setErrorMask(view, false);
|
||||||
|
}, 10);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
columns: [
|
columns: [
|
||||||
@ -448,5 +526,31 @@ Ext.define('PBS.DataStoreContent', {
|
|||||||
iconCls: 'fa fa-refresh',
|
iconCls: 'fa fa-refresh',
|
||||||
handler: 'reload',
|
handler: 'reload',
|
||||||
},
|
},
|
||||||
|
'->',
|
||||||
|
{
|
||||||
|
xtype: 'tbtext',
|
||||||
|
html: gettext('Search'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xtype: 'textfield',
|
||||||
|
reference: 'searchbox',
|
||||||
|
triggers: {
|
||||||
|
clear: {
|
||||||
|
cls: 'pmx-clear-trigger',
|
||||||
|
weight: -1,
|
||||||
|
hidden: true,
|
||||||
|
handler: function() {
|
||||||
|
this.triggers.clear.setVisible(false);
|
||||||
|
this.setValue('');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
listeners: {
|
||||||
|
change: {
|
||||||
|
fn: 'search',
|
||||||
|
buffer: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user