[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