[pbs-devel] [PATCH proxmox-backup 3/6] ui: tape: rework BackupOverview
Dominik Csapak
d.csapak at proxmox.com
Tue Feb 2 14:00:36 CET 2021
instead of grouping by tape (which is rarely interesting),
group by pool -> group -> id -> mediaset
this way a user looking for a backup of specific vm can do just that
we may want to have an additional view here were we list all snapshots
included in the selected media-set ?
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
www/Utils.js | 9 ++
www/tape/BackupOverview.js | 169 +++++++++++++++++++++----------------
2 files changed, 103 insertions(+), 75 deletions(-)
diff --git a/www/Utils.js b/www/Utils.js
index acfc4556..3bb709e4 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -260,6 +260,15 @@ Ext.define('PBS.Utils', {
return dedup;
},
+ parse_snapshot_id: function(snapshot) {
+ if (!snapshot) {
+ return [undefined, undefined, undefined];
+ }
+ let [_match, type, group, id] = /^([^/]+)\/([^/]+)\/(.+)$/.exec(snapshot);
+
+ return [type, group, id];
+ },
+
get_type_icon_cls: function(btype) {
var cls = '';
if (btype.startsWith('vm')) {
diff --git a/www/tape/BackupOverview.js b/www/tape/BackupOverview.js
index 4743dcc0..f850c29a 100644
--- a/www/tape/BackupOverview.js
+++ b/www/tape/BackupOverview.js
@@ -16,50 +16,98 @@ Ext.define('PBS.TapeManagement.BackupOverview', {
}).show();
},
- reload: async function() {
+ restore: function(button, record) {
let me = this;
let view = me.getView();
+ let selection = view.getSelection();
+ if (!selection || selection.length < 1) {
+ return;
+ }
- Proxmox.Utils.setErrorMask(view, true);
+ let mediaset = selection[0].data.text;
+ let uuid = selection[0].data.uuid;
+ Ext.create('PBS.TapeManagement.TapeRestoreWindow', {
+ mediaset,
+ uuid,
+ listeners: {
+ destroy: function() {
+ me.reload();
+ },
+ },
+ }).show();
+ },
- 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']),
- );
+ loadContent: async function() {
+ let content_response = await PBS.Async.api2({
+ url: '/api2/extjs/tape/media/content',
+ });
+ let data = {};
+
+ for (const entry of content_response.result.data) {
+ let pool = entry.pool;
+ let [type, group_id, id] = PBS.Utils.parse_snapshot_id(entry.snapshot);
+ let group = `${type}/${group_id}`;
+ let media_set = entry['media-set-name'];
+ let uuid = entry['media-set-uuid'];
+ let ctime = entry['media-set-ctime'];
+ if (data[pool] === undefined) {
+ data[pool] = {};
+ }
- let content = {};
+ if (data[pool][group] === undefined) {
+ data[pool][group] = {};
+ }
- let content_response = await PBS.Async.api2({
- url: '/api2/extjs/tape/media/content',
+ if (data[pool][group][id] === undefined) {
+ data[pool][group][id] = [];
+ }
+ data[pool][group][id].push({
+ text: media_set,
+ uuid,
+ ctime,
+ leaf: true,
});
+ }
- 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);
+ let list = [];
+
+ for (const [pool, groups] of Object.entries(data)) {
+ let pool_entry = {
+ text: pool,
+ leaf: false,
+ children: [],
+ };
+ for (const [group, ids] of Object.entries(groups)) {
+ let group_entry = {
+ text: group,
+ iconCls: "fa " + PBS.Utils.get_type_icon_cls(group),
+ leaf: false,
+ children: [],
+ };
+ for (const [id, media_sets] of Object.entries(ids)) {
+ let id_entry = {
+ text: `${group}/${id}`,
+ leaf: false,
+ children: media_sets,
+ };
+ group_entry.children.push(id_entry);
}
+ pool_entry.children.push(group_entry);
}
+ list.push(pool_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;
- }
- }
+ 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,
@@ -78,8 +126,14 @@ Ext.define('PBS.TapeManagement.BackupOverview', {
},
store: {
- sorters: 'label-text',
data: [],
+ sorters: function(a, b) {
+ if (a.data.leaf && b.data.leaf) {
+ return a.data.ctime - b.data.ctime;
+ } else {
+ return a.data.text.localeCompare(b.data.text);
+ }
+ },
},
rootVisible: false,
@@ -99,50 +153,15 @@ Ext.define('PBS.TapeManagement.BackupOverview', {
columns: [
{
xtype: 'treecolumn',
- text: gettext('Tape/Backup'),
- dataIndex: 'label-text',
+ text: gettext('Pool/Group/Snapshot/Media Set'),
+ dataIndex: 'text',
+ sortable: false,
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) : "",
+ text: gettext('Media Set UUID'),
+ dataIndex: 'uuid',
+ sortable: false,
flex: 1,
},
],
--
2.20.1
More information about the pbs-devel
mailing list