From: Dominik Csapak <d.csapak@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup 3/6] ui: tape: rework BackupOverview
Date: Tue, 2 Feb 2021 14:00:36 +0100 [thread overview]
Message-ID: <20210202130039.6564-3-d.csapak@proxmox.com> (raw)
In-Reply-To: <20210202130039.6564-1-d.csapak@proxmox.com>
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@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
next prev parent reply other threads:[~2021-02-02 13:00 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-02 13:00 [pbs-devel] [PATCH proxmox-backup 1/6] api2/types/tape/media: add media_set_ctime to MediaContentEntry Dominik Csapak
2021-02-02 13:00 ` [pbs-devel] [PATCH proxmox-backup 2/6] ui: refactor get_type_icon_cls Dominik Csapak
2021-02-02 13:00 ` Dominik Csapak [this message]
2021-02-02 13:00 ` [pbs-devel] [PATCH proxmox-backup 4/6] ui: tape: TapeBackupWindow: add missing DriveSelector Dominik Csapak
2021-02-02 13:00 ` [pbs-devel] [PATCH proxmox-backup 5/6] ui: tape: add Restore Window Dominik Csapak
2021-02-02 13:00 ` [pbs-devel] [PATCH proxmox-backup 6/6] ui: tape: add TapeInventory panel Dominik Csapak
2021-02-02 13:49 ` [pbs-devel] applied: [PATCH proxmox-backup 1/6] api2/types/tape/media: add media_set_ctime to MediaContentEntry Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210202130039.6564-3-d.csapak@proxmox.com \
--to=d.csapak@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal