From 07d6c0967dc681a9180ba8bb57d2cf135d5f4e76 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Thu, 28 Jan 2021 12:59:47 +0100 Subject: [PATCH] ui: tape: add BackupOverview Panel shows all tapes with the relevant info * which pool it belongs to * what backups are on it * which media-set * location * etc. This is very rough, and maybe not the best way to display this information. It may make sense to reverse the tree, i.e. having pools at top-level, then media-sets, then tapes, then snapshots.. Signed-off-by: Dominik Csapak --- www/Makefile | 1 + www/tape/BackupOverview.js | 150 +++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 www/tape/BackupOverview.js diff --git a/www/Makefile b/www/Makefile index 827633a3..aad5f7ce 100644 --- a/www/Makefile +++ b/www/Makefile @@ -20,6 +20,7 @@ TAPE_UI_FILES= \ tape/window/LabelMedia.js \ tape/window/PoolEdit.js \ tape/window/TapeBackup.js \ + tape/BackupOverview.js \ TapeManagement.js endif diff --git a/www/tape/BackupOverview.js b/www/tape/BackupOverview.js new file mode 100644 index 00000000..4743dcc0 --- /dev/null +++ b/www/tape/BackupOverview.js @@ -0,0 +1,150 @@ +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(); + }, + }, + }).show(); + }, + + reload: async function() { + let me = this; + let view = me.getView(); + + Proxmox.Utils.setErrorMask(view, true); + + try { + let list_response = await PBS.Async.api2({ + url: '/api2/extjs/tape/media/list', + }); + let list = list_response.result.data.sort( + (a, b) => a['label-text'].localeCompare(b['label-text']), + ); + + let content = {}; + + let content_response = await PBS.Async.api2({ + url: '/api2/extjs/tape/media/content', + }); + + let content_list = content_response.result.data.sort( + (a, b) => a.snapshot.localeCompare(b.snapshot), + ); + + for (let entry of content_list) { + let tape = entry['label-text']; + entry['label-text'] = entry.snapshot; + entry.leaf = true; + if (content[tape] === undefined) { + content[tape] = [entry]; + } else { + content[tape].push(entry); + } + } + + for (let child of list) { + let tape = child['label-text']; + if (content[tape]) { + child.children = content[tape]; + child.leaf = false; + } else { + child.leaf = true; + } + } + + view.setRootNode({ + expanded: true, + children: list, + }); + + Proxmox.Utils.setErrorMask(view, false); + } catch (error) { + Proxmox.Utils.setErrorMask(view, error.toString()); + } + }, + }, + + listeners: { + activate: 'reload', + }, + + store: { + sorters: 'label-text', + data: [], + }, + + rootVisible: false, + + tbar: [ + { + text: gettext('Reload'), + handler: 'reload', + }, + '-', + { + text: gettext('New Backup'), + handler: 'backup', + }, + ], + + columns: [ + { + xtype: 'treecolumn', + text: gettext('Tape/Backup'), + dataIndex: 'label-text', + flex: 3, + }, + { + text: gettext('Location'), + dataIndex: 'location', + flex: 1, + renderer: function(value) { + if (!value) { + return ""; + } + let result; + if ((result = /^online-(.+)$/.exec(value)) !== null) { + return Ext.htmlEncode(result[1]); + } + + return value; + }, + }, + { + text: gettext('Status'), + dataIndex: 'status', + flex: 1, + }, + { + text: gettext('Media Set'), + dataIndex: 'media-set-name', + flex: 2, + }, + { + text: gettext('Pool'), + dataIndex: 'pool', + flex: 1, + }, + { + text: gettext('Sequence Nr.'), + dataIndex: 'seq-nr', + flex: 0.5, + }, + { + text: gettext('Backup Time'), + dataIndex: 'backup-time', + renderer: (time) => time !== undefined ? new Date(time*1000) : "", + flex: 1, + }, + ], +}); + -- 2.39.5