public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup 4/5] ui: datastore content: add snapshot information to context menu
Date: Tue, 28 Nov 2023 10:44:01 +0100	[thread overview]
Message-ID: <20231128094402.38115-5-d.csapak@proxmox.com> (raw)
In-Reply-To: <20231128094402.38115-1-d.csapak@proxmox.com>

contains a summary of snapshot information, especially interesting since
it contains the upload statistics. This may allow us to reduce the
default column count in the grid.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/Makefile               |   1 +
 www/datastore/Content.js   |  22 +++++
 www/window/SnapshotInfo.js | 182 +++++++++++++++++++++++++++++++++++++
 3 files changed, 205 insertions(+)
 create mode 100644 www/window/SnapshotInfo.js

diff --git a/www/Makefile b/www/Makefile
index 04c12b31..34e0f851 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -86,6 +86,7 @@ JSSRC=							\
 	window/VerifyAll.js				\
 	window/ZFSCreate.js				\
 	window/InfluxDbEdit.js				\
+	window/SnapshotInfo.js				\
 	dashboard/DataStoreStatistics.js		\
 	dashboard/LongestTasks.js			\
 	dashboard/RunningTasks.js			\
diff --git a/www/datastore/Content.js b/www/datastore/Content.js
index 8d5d0815..d9e9d0b4 100644
--- a/www/datastore/Content.js
+++ b/www/datastore/Content.js
@@ -712,6 +712,17 @@ Ext.define('PBS.DataStoreContent', {
 	    });
 	},
 
+	onShowInformation: function(view, rI, cI, item, e, rec) {
+	    let me = this;
+	    Ext.create('PBS.window.SnapshotInfo', {
+		autoShow: true,
+		datastore: view.datastore,
+		'backup-type': rec.data['backup-type'],
+		'backup-id': rec.data['backup-id'],
+		'backup-time': (rec.data["backup-time"].getTime()/1000).toFixed(0),
+	    });
+	},
+
 	onForget: function(table, rI, cI, item, e, { data }) {
 	    let me = this;
 	    let view = this.getView();
@@ -893,6 +904,7 @@ Ext.define('PBS.DataStoreContent', {
 		    title: gettext('Snapshot'),
 		    onVerify: createControllerCallback('onVerify'),
 		    onProtectionChange: createControllerCallback('onProtectionChange'),
+		    onShowInformation: createControllerCallback('onShowInformation'),
 		    onForget: createControllerCallback('onForget'),
 		});
 	    }
@@ -1330,6 +1342,7 @@ Ext.define('PBS.datastore.SnapshotCmdMenu', {
 
     onVerify: undefined,
     onProtectionChange: undefined,
+    onShowInformation: undefined,
     onForget: undefined,
 
     items: [
@@ -1351,6 +1364,15 @@ Ext.define('PBS.datastore.SnapshotCmdMenu', {
 		disabled: '{!onProtectionChange}',
 	    },
 	},
+	{
+	    text: gettext('Show Information'),
+	    iconCls: 'fa fa-info-circle',
+	    handler: function() { this.up('menu').onShowInformation(); },
+	    cbind: {
+		hidden: '{!onShowInformation}',
+		disabled: '{!onShowInformation}',
+	    },
+	},
 	{
 	    text: gettext('Remove'),
 	    iconCls: 'fa critical fa-trash-o',
diff --git a/www/window/SnapshotInfo.js b/www/window/SnapshotInfo.js
new file mode 100644
index 00000000..005f2334
--- /dev/null
+++ b/www/window/SnapshotInfo.js
@@ -0,0 +1,182 @@
+Ext.define('PBS.window.SnapshotInfo', {
+    extend: 'Ext.window.Window',
+    alias: 'widget.pbsSnapshotInfo',
+
+    modal: true,
+    width: 600,
+    resizable: false,
+    referenceHolder: true,
+
+    bodyPadding: 25,
+    defaults: {
+	xtype: 'pmxInfoWidget',
+	printBar: false,
+	padding: '2 0',
+    },
+
+    items: [
+	{
+	    reference: 'backup-time',
+	    iconCls: 'fa fa-clock-o',
+	    title: gettext('Backup Time'),
+	},
+	{
+	    reference: 'protected',
+	    iconCls: 'fa fa-shield',
+	    title: gettext('Protected'),
+	},
+	{
+	    reference: 'size',
+	    iconCls: 'fa fa-hdd-o',
+	    title: gettext('Size'),
+	},
+	{
+	    reference: 'owner',
+	    iconCls: 'fa fa-user-o',
+	    title: gettext('Owner'),
+	},
+	{
+	    // spacer
+	    xtype: 'box',
+	    padding: 10,
+	},
+	{
+	    xtype: 'grid',
+	    reference: 'files',
+	    store: {
+		data: [],
+	    },
+	    height: 170,
+	    scrollable: true,
+	    columns: [
+		{
+		    dataIndex: 'filename',
+		    text: gettext('Filename'),
+		    flex: 1,
+		},
+		{
+		    dataIndex: 'size',
+		    text: gettext('Size'),
+		    flex: 1,
+		    renderer: (v) => v !== undefined ? Proxmox.Utils.format_size(v) : '',
+		},
+		{
+		    dataIndex: 'crypt-mode',
+		    text: gettext('Encrypted'),
+		    flex: 1,
+		    renderer: (v) => {
+			let modeIdx = PBS.Utils.cryptmap[v ?? 'none'] ?? 0;
+			return PBS.Utils.cryptText[modeIdx];
+		    },
+		},
+	    ],
+	},
+	{
+	    // spacer
+	    xtype: 'box',
+	    padding: 10,
+	},
+	{
+	    title: gettext('Verify State'),
+	    iconCls: 'pve-icon-verify-lettering',
+	    reference: 'verify-state',
+	},
+	{
+	    title: gettext('Last Verificaton'),
+	    iconCls: 'fa fa-list-alt',
+	    reference: 'verify-last',
+	},
+	{
+	    // spacer
+	    xtype: 'box',
+	    padding: 10,
+	},
+	{
+	    xtype: 'box',
+	    html: `<i class="fa fa-upload"></i> ${gettext('Upload Statistics')}`,
+	    reference: 'upload-title',
+	    padding: '0 0 10 0',
+	},
+	{
+	    title: gettext('Size'),
+	    reference: 'upload-size',
+	},
+	{
+	    title: gettext('Compressed Size'),
+	    reference: 'compressed-size',
+	},
+	{
+	    title: gettext('Chunk Count'),
+	    reference: 'chunk-count',
+	},
+	{
+	    title: gettext('Duplicate Chunks'),
+	    reference: 'duplicate-chunks',
+	},
+    ],
+
+    initComponent: function() {
+	let me = this;
+	let type = me['backup-type'];
+	let id = me['backup-id'];
+	let time = me['backup-time'];
+	let datetime = new Date(time*1000);
+	if (type === undefined || id === undefined || time === undefined) {
+	    throw "snapshot id not given";
+	}
+
+	let snapshotText = `${type}/${id}/${PBS.Utils.render_datetime_utc(datetime)}`;
+	me.title = Ext.String.format(gettext('Snapshot {0}'), snapshotText);
+
+	me.callParent();
+	Proxmox.Utils.API2Request({
+	    url: `/api2/extjs/admin/datastore/${me.datastore}/snapshot-information`,
+	    params: {
+		'backup-type': type,
+		'backup-id': id,
+		'backup-time': time,
+	    },
+	    method: 'GET',
+	    success: ({ result }) => {
+		me.lookup('backup-time').updateValue(datetime);
+		me.lookup('protected').updateValue(Proxmox.Utils.format_boolean(result.data.protected));
+		me.lookup('size').updateValue(Proxmox.Utils.format_size(result.data.size));
+		me.lookup('owner').updateValue(result.data.owner);
+
+		me.lookup('files').getStore().setData(result.data.files);
+
+		let verification = result.data.verification;
+		if (verification !== undefined) {
+		    let iconCls = 'times critical';
+		    if (verification.state === 'ok') {
+			iconCls = 'check good';
+		    }
+		    let txt = Ext.htmlEncode(verification.state);
+		    let verifyState = `<i class="fa fa-${iconCls}"></i> ${txt}`;
+
+		    let task = Proxmox.Utils.parse_task_upid(verification.upid);
+		    let verifyTime = Proxmox.Utils.render_timestamp(task.starttime);
+		    me.lookup('verify-state').updateValue(verifyState);
+		    me.lookup('verify-last').updateValue(verifyTime);
+		} else {
+		    me.lookup('verify-state').setVisible(false);
+		    me.lookup('verify-last').setVisible(false);
+		}
+
+		let uploadStats = result.data['upload-statistics'];
+		if (uploadStats !== undefined) {
+		    me.lookup('upload-size').updateValue(Proxmox.Utils.format_size(uploadStats.size));
+		    me.lookup('compressed-size').updateValue(Proxmox.Utils.format_size(uploadStats['compressed-size']));
+		    me.lookup('chunk-count').updateValue(uploadStats.count);
+		    me.lookup('duplicate-chunks').updateValue(uploadStats.duplicates);
+		} else {
+		    me.lookup('upload-title').setVisible(false);
+		    me.lookup('upload-size').setVisible(false);
+		    me.lookup('compressed-size').setVisible(false);
+		    me.lookup('chunk-count').setVisible(false);
+		    me.lookup('duplicate-chunks').setVisible(false);
+		}
+	    },
+	});
+    },
+});
-- 
2.39.2




  parent reply	other threads:[~2023-11-28  9:44 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-28  9:43 [pbs-devel] [PATCH proxmox-backup 0/5] add context menu to datastore content Dominik Csapak
2023-11-28  9:43 ` [pbs-devel] [PATCH proxmox-backup 1/5] api-types: add an UploadStatistic api type Dominik Csapak
2023-11-28  9:43 ` [pbs-devel] [PATCH proxmox-backup 2/5] api: datastore admin: add 'snapshot-information' api call Dominik Csapak
2023-11-28  9:44 ` [pbs-devel] [PATCH proxmox-backup 3/5] ui: datastore content: add context menu to groups and snapshots Dominik Csapak
2023-11-28 15:27   ` [pbs-devel] applied: " Thomas Lamprecht
2023-11-29  7:35     ` Dominik Csapak
2023-11-29  7:47       ` Thomas Lamprecht
2023-11-28  9:44 ` Dominik Csapak [this message]
2023-11-28  9:44 ` [pbs-devel] [PATCH proxmox-backup 5/5] ui: datastore content: add 'more actions' menu to actions Dominik Csapak
2023-11-28 11:32 ` [pbs-devel] [PATCH proxmox-backup 0/5] add context menu to datastore content Fabian Grünbichler
2023-11-28 12:48 ` Philipp Hufnagl
2023-11-28 13:41 ` Max Carrara

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=20231128094402.38115-5-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal