proxmox-backup/www/tape/BackupOverview.js
Thomas Lamprecht 104ae6093a ui: tape: small code/style cleanups
It was not actually bad, so they're quite opinionated to be honest,
but at least xtypes props must go first and variable declaration
should try to be as near as possible to the actual use as long as
code stays sensible readable/short.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2021-05-21 15:19:51 +02:00

298 lines
6.7 KiB
JavaScript

Ext.define('PBS.TapeManagement.BackupOverview', {
extend: 'Ext.tree.Panel',
alias: 'widget.pbsBackupOverview',
controller: {
xclass: 'Ext.app.ViewController',
backup: function() {
let me = this;
Ext.create('PBS.TapeManagement.TapeBackupWindow', {
listeners: {
destroy: function() {
me.reload();
},
},
autoShow: true,
});
},
restoreBackups: function(view, rI, cI, item, e, rec) {
let me = this;
let mediaset = rec.data.is_media_set ? rec.data.text : rec.data['media-set'];
Ext.create('PBS.TapeManagement.TapeRestoreWindow', {
autoShow: true,
uuid: rec.data['media-set-uuid'],
prefilter: rec.data.prefilter,
mediaset,
});
},
loadContent: async function() {
let me = this;
let content_response = await PBS.Async.api2({
url: '/api2/extjs/tape/media/list?update-status=false',
});
let data = {};
for (const entry of content_response.result.data) {
let pool = entry.pool;
if (pool === undefined) {
continue; // pools not belonging to a pool cannot contain data
}
let media_set = entry['media-set-name'];
if (media_set === undefined) {
continue; // tape does not belong to media-set (yet))
}
if (data[pool] === undefined) {
data[pool] = {};
}
if (data[pool][media_set] === undefined) {
data[pool][media_set] = entry;
data[pool][media_set].text = media_set;
data[pool][media_set].restore =true;
data[pool][media_set].tapes = 1;
data[pool][media_set]['seq-nr'] = undefined;
data[pool][media_set].is_media_set = true;
} else {
data[pool][media_set].tapes++;
}
}
let list = [];
for (const [pool, media_sets] of Object.entries(data)) {
let pool_entry = Ext.create('Ext.data.TreeModel', {
text: pool,
leaf: false,
});
let children = [];
for (const media_set of Object.values(media_sets)) {
let entry = Ext.create('Ext.data.TreeModel', media_set);
entry.on('beforeexpand', (node) => me.beforeExpand(node));
children.push(entry);
}
pool_entry.set('children', children);
list.push(pool_entry);
}
return list;
},
reload: async function() {
let me = this;
let view = me.getView();
Proxmox.Utils.setErrorMask(view, true);
try {
let list = await me.loadContent();
view.setRootNode({
expanded: true,
children: list,
});
Proxmox.Utils.setErrorMask(view, false);
} catch (error) {
Proxmox.Utils.setErrorMask(view, error.toString());
}
},
loadMediaSet: async function(node) {
let me = this;
let view = me.getView();
Proxmox.Utils.setErrorMask(view, true);
const media_set_uuid = node.data['media-set-uuid'];
const media_set = node.data.text;
try {
let list = await PBS.Async.api2({
method: 'GET',
url: `/api2/extjs/tape/media/content`,
params: {
'media-set': media_set_uuid,
},
});
list.result.data.sort(function(a, b) {
let storeRes = a.store.localeCompare(b.store);
if (storeRes === 0) {
return a.snapshot.localeCompare(b.snapshot);
} else {
return storeRes;
}
});
let stores = {};
for (let entry of list.result.data) {
entry.text = entry.snapshot;
entry.restore = true;
entry.leaf = true;
entry.children = [];
entry['media-set'] = media_set;
entry.prefilter = {
store: entry.store,
snapshot: entry.snapshot,
};
let iconCls = PBS.Utils.get_type_icon_cls(entry.snapshot);
if (iconCls !== '') {
entry.iconCls = `fa ${iconCls}`;
}
let store = entry.store;
let tape = entry['label-text'];
if (stores[store] === undefined) {
stores[store] = {
text: store,
'media-set-uuid': entry['media-set-uuid'],
iconCls: 'fa fa-database',
tapes: {},
};
}
if (stores[store].tapes[tape] === undefined) {
stores[store].tapes[tape] = {
text: tape,
'media-set-uuid': entry['media-set-uuid'],
'seq-nr': entry['seq-nr'],
iconCls: 'pbs-icon-tape',
expanded: true,
children: [],
};
}
let [type, group, _id] = PBS.Utils.parse_snapshot_id(entry.snapshot);
let children = stores[store].tapes[tape].children;
let text = `${type}/${group}`;
if (children.length < 1 || children[children.length - 1].text !== text) {
children.push({
text,
'media-set-uuid': entry['media-set-uuid'],
leaf: false,
restore: true,
prefilter: {
store,
snapshot: `${type}/${group}/`,
},
'media-set': media_set,
iconCls: `fa ${iconCls}`,
children: [],
});
}
children[children.length - 1].children.push(entry);
}
let storeList = Object.values(stores);
let storeNameList = Object.keys(stores);
let expand = storeList.length === 1;
for (const store of storeList) {
store.children = Object.values(store.tapes);
store.expanded = expand;
delete store.tapes;
node.appendChild(store);
}
if (list.result.data.length === 0) {
node.set('leaf', true);
}
node.set('loaded', true);
node.set('datastores', storeNameList);
Proxmox.Utils.setErrorMask(view, false);
node.expand();
} catch (error) {
Proxmox.Utils.setErrorMask(view, false);
Ext.Msg.alert('Error', error.toString());
}
},
beforeExpand: function(node, e) {
let me = this;
if (node.isLoaded()) {
return true;
}
me.loadMediaSet(node);
return false;
},
},
listeners: {
activate: 'reload',
},
store: {
data: [],
sorters: function(a, b) {
if (a.data.is_media_set && b.data.is_media_set) {
return a.data['media-set-ctime'] - b.data['media-set-ctime'];
} else {
return a.data.text.localeCompare(b.data.text);
}
},
},
rootVisible: false,
tbar: [
{
text: gettext('Reload'),
handler: 'reload',
},
'-',
{
text: gettext('New Backup'),
handler: 'backup',
},
],
columns: [
{
xtype: 'treecolumn',
text: gettext('Pool/Media Set/Snapshot'),
dataIndex: 'text',
sortable: false,
flex: 3,
},
{
header: gettext('Actions'),
xtype: 'actioncolumn',
items: [
{
handler: 'restoreBackups',
tooltip: gettext('Restore'),
getClass: (v, m, rec) => rec.data.restore ? 'fa fa-fw fa-undo' : 'pmx-hidden',
isDisabled: (v, r, c, i, rec) => !rec.data.restore,
},
],
},
{
text: gettext('Tapes'),
dataIndex: 'tapes',
sortable: false,
},
{
text: gettext('Seq. Nr.'),
dataIndex: 'seq-nr',
sortable: false,
},
{
text: gettext('Media Set UUID'),
dataIndex: 'media-set-uuid',
hidden: true,
sortable: false,
width: 280,
},
],
});