From: Dominik Csapak <d.csapak@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup v2 3/4] ui: datastore content: add snapshot information to context menu
Date: Tue, 5 Dec 2023 11:53:44 +0100 [thread overview]
Message-ID: <20231205105345.1656325-4-d.csapak@proxmox.com> (raw)
In-Reply-To: <20231205105345.1656325-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 | 259 +++++++++++++++++++++++++++++++++++++
3 files changed, 282 insertions(+)
create mode 100644 www/window/SnapshotInfo.js
diff --git a/www/Makefile b/www/Makefile
index be7e27ab..071ef5d8 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -87,6 +87,7 @@ JSSRC= \
window/ZFSCreate.js \
window/InfluxDbEdit.js \
window/DatastoreRepoInfo.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 87317ec1..f715f814 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'),
});
}
@@ -1331,6 +1343,7 @@ Ext.define('PBS.datastore.SnapshotCmdMenu', {
onVerify: undefined,
onProtectionChange: undefined,
+ onShowInformation: undefined,
onForget: undefined,
items: [
@@ -1352,6 +1365,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}',
+ },
+ },
{ xtype: 'menuseparator' },
{
text: gettext('Remove'),
diff --git a/www/window/SnapshotInfo.js b/www/window/SnapshotInfo.js
new file mode 100644
index 00000000..f2cc7a55
--- /dev/null
+++ b/www/window/SnapshotInfo.js
@@ -0,0 +1,259 @@
+Ext.define('PBS.window.SnapshotInfo', {
+ extend: 'Ext.window.Window',
+ alias: 'widget.pbsSnapshotInfo',
+
+ modal: true,
+ width: 700,
+ resizable: true,
+ 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: 'container',
+ layout: {
+ type: 'hbox',
+ align: 'stretch',
+ },
+ items: [
+ {
+ xtype: 'container',
+ flex: 1,
+ layout: {
+ type: 'vbox',
+ align: 'stretch',
+ },
+ defaults: {
+ xtype: 'pmxInfoWidget',
+ printBar: false,
+ padding: '2 0',
+ },
+ items: [
+ {
+ 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',
+ },
+ ],
+ },
+ {
+ // spacer
+ xtype: 'box',
+ padding: 10,
+ },
+ {
+ xtype: 'container',
+ flex: 1,
+ layout: {
+ type: 'vbox',
+ align: 'stretch',
+ },
+ defaults: {
+ xtype: 'pmxInfoWidget',
+ printBar: false,
+ padding: '2 0',
+ },
+ items: [
+ {
+ xtype: 'box',
+ html: `<i class="pve-icon-verify-lettering"></i> ${gettext('Verification')}`,
+ reference: 'verify-title',
+ padding: '0 0 10 0',
+ },
+ {
+ title: gettext('Verify State'),
+ reference: 'verify-state',
+ },
+ {
+ title: gettext('Last Verificaton'),
+ iconCls: 'fa fa-list-alt',
+ reference: 'verify-last',
+ },
+ ],
+ },
+ ],
+ },
+ {
+ // spacer
+ xtype: 'box',
+ padding: 10,
+ },
+ {
+ xtype: 'tabpanel',
+ height: 200,
+ items: [{
+ title: gettext('Files'),
+ xtype: 'grid',
+ reference: 'files',
+ store: {
+ data: [],
+ },
+ 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.indexOf(v);
+ if (modeIdx === -1) {
+ modeIdx = 0;
+ }
+ let iconCls = PBS.Utils.cryptIconCls[modeIdx];
+ return `<i class="fa fa-${iconCls}"></i> ${PBS.Utils.cryptText[modeIdx]}`;
+ },
+ },
+ ],
+ }, {
+ xtype: 'box',
+ padding: 10,
+ style: {
+ 'white-space': 'pre',
+ },
+ scrollable: true,
+ title: gettext('Comment'),
+ reference: 'comment',
+ }, {
+ xtype: 'box',
+ padding: 10,
+ style: {
+ 'white-space': 'pre',
+ },
+ scrollable: true,
+ title: gettext('Group Comment'),
+ reference: 'group-comment',
+ }],
+ },
+ ],
+
+ 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('comment').setData(result.data.comment);
+ me.lookup('group-comment').setData(result.data['group-notes']);
+
+ 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').updateValue(Proxmox.Utils.NoneText);
+ me.lookup('verify-last').updateValue(Proxmox.Utils.NoneText);
+ }
+
+ 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);
+ }
+ },
+ failure: function(response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus, function() {
+ me.close();
+ });
+ },
+ });
+ },
+});
--
2.30.2
next prev parent reply other threads:[~2023-12-05 10:54 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-05 10:53 [pbs-devel] [PATCH proxmox-backup v2 0/4] add 'show information' for snapshots Dominik Csapak
2023-12-05 10:53 ` [pbs-devel] [PATCH proxmox-backup v2 1/4] api-types: add an UploadStatistic api type Dominik Csapak
2023-12-05 10:53 ` [pbs-devel] [PATCH proxmox-backup v2 2/4] api: datastore admin: add 'snapshot-information' api call Dominik Csapak
2023-12-05 10:53 ` Dominik Csapak [this message]
2023-12-05 10:53 ` [pbs-devel] [PATCH proxmox-backup v2 4/4] ui: datastore content: add 'more actions' menu to actions Dominik Csapak
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=20231205105345.1656325-4-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