ui: rework datastore content panel controller

Mostly refactoring, but actually fixes an issue where one seldom run
into a undefined dereference due to the store onLoad callback getting
triggered after some of the componet was destroyed - on quick
switching through the datastores.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2020-05-26 12:46:45 +02:00
parent 40dc103103
commit 3f98b34705

View File

@ -29,109 +29,124 @@ Ext.define('PBS.DataStoreContent', {
throw "no datastore specified"; throw "no datastore specified";
} }
this.data_store = Ext.create('Ext.data.Store', { this.store = Ext.create('Ext.data.Store', {
model: 'pbs-data-store-snapshots', model: 'pbs-data-store-snapshots',
sorters: 'backup-group', sorters: 'backup-group',
groupField: 'backup-group', groupField: 'backup-group',
}); });
this.store.on('load', this.onLoad, this);
Proxmox.Utils.monStoreErrors(view, view.store, true); Proxmox.Utils.monStoreErrors(view, view.store, true);
this.reload(); // initial load this.reload(); // initial load
}, },
reload: function() { reload: function() {
var view = this.getView(); let view = this.getView();
if (!view.store || !this.store) {
console.warn('cannot reload, no store(s)');
return;
}
let url = `/api2/json/admin/datastore/${view.datastore}/snapshots`; let url = `/api2/json/admin/datastore/${view.datastore}/snapshots`;
this.data_store.setProxy({ this.store.setProxy({
type: 'proxmox', type: 'proxmox',
url: url url: url
}); });
this.data_store.load(function(records, operation, success) { this.store.load();
let groups = {}; },
records.forEach(function(item) { getRecordGroups: function(records) {
var btype = item.data["backup-type"]; let groups = {};
let group = btype + "/" + item.data["backup-id"];
if (groups[group] !== undefined) for (const item of records) {
return; var btype = item.data["backup-type"];
let group = btype + "/" + item.data["backup-id"];
var cls = ''; if (groups[group] !== undefined) {
if (btype === 'vm') { continue;
cls = 'fa-desktop'; }
} else if (btype === 'ct') {
cls = 'fa-cube';
} else if (btype === 'host') {
cls = 'fa-building';
} else {
return btype + '/' + value;
}
groups[group] = { var cls = '';
text: group, if (btype === 'vm') {
leaf: false, cls = 'fa-desktop';
iconCls: "fa " + cls, } else if (btype === 'ct') {
expanded: false, cls = 'fa-cube';
backup_type: item.data["backup-type"], } else if (btype === 'host') {
backup_id: item.data["backup-id"], cls = 'fa-building';
children: [] } else {
}; console.warn(`got unkown backup-type '${btype}'`);
}); continue; // FIXME: auto render? what do?
}
let backup_time_to_string = function(backup_time) { groups[group] = {
let pad = function(number) { text: group,
if (number < 10) { leaf: false,
return '0' + number; iconCls: "fa " + cls,
} expanded: false,
return number; backup_type: item.data["backup-type"],
}; backup_id: item.data["backup-id"],
return backup_time.getUTCFullYear() + children: []
'-' + pad(backup_time.getUTCMonth() + 1) +
'-' + pad(backup_time.getUTCDate()) +
'T' + pad(backup_time.getUTCHours()) +
':' + pad(backup_time.getUTCMinutes()) +
':' + pad(backup_time.getUTCSeconds()) +
'Z';
}; };
}
records.forEach(function(item) { return groups;
let group = item.data["backup-type"] + "/" + item.data["backup-id"]; },
let children = groups[group].children;
let data = item.data; onLoad: function(store, records, success) {
let view = this.getView();
data.text = Ext.Date.format(data["backup-time"], 'Y-m-d H:i:s'); if (!success) {
data.text = group + '/' + backup_time_to_string(data["backup-time"]); return;
data.leaf = true; }
data.cls = 'no-leaf-icons';
children.push(data); let groups = this.getRecordGroups(records);
});
let children = []; let backup_time_to_string = function(backup_time) {
Ext.Object.each(groups, function(key, group) { let pad = (number) => number < 10 ? '0' + number : number;
let last_backup = 0; return backup_time.getUTCFullYear() +
group.children.forEach(function(item) { '-' + pad(backup_time.getUTCMonth() + 1) +
if (item["backup-time"] > last_backup) { '-' + pad(backup_time.getUTCDate()) +
last_backup = item["backup-time"]; 'T' + pad(backup_time.getUTCHours()) +
group["backup-time"] = last_backup; ':' + pad(backup_time.getUTCMinutes()) +
group.files = item.files; ':' + pad(backup_time.getUTCSeconds()) +
group.size = item.size; 'Z';
} };
});
group.count = group.children.length;
children.push(group)
})
view.setRootNode({ for (const item of records) {
expanded: true, let group = item.data["backup-type"] + "/" + item.data["backup-id"];
children: children let children = groups[group].children;
});
let data = item.data;
data.text = Ext.Date.format(data["backup-time"], 'Y-m-d H:i:s');
data.text = group + '/' + backup_time_to_string(data["backup-time"]);
data.leaf = true;
data.cls = 'no-leaf-icons';
children.push(data);
}
let children = [];
for (const [_key, group] of Object.entries(groups)) {
let last_backup = 0;
for (const item of group.children) {
if (item["backup-time"] > last_backup) {
last_backup = item["backup-time"];
group["backup-time"] = last_backup;
group.files = item.files;
group.size = item.size;
}
}
group.count = group.children.length;
children.push(group);
}
view.setRootNode({
expanded: true,
children: children
}); });
}, },
onPrune: function() { onPrune: function() {