From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id AB8B59E843 for ; Tue, 28 Nov 2023 10:44:04 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 8998A13AFC for ; Tue, 28 Nov 2023 10:44:04 +0100 (CET) Received: from bookworm-dev.localdomain (unknown [94.136.29.99]) by firstgate.proxmox.com (Proxmox) with ESMTP for ; Tue, 28 Nov 2023 10:44:02 +0100 (CET) Received: by bookworm-dev.localdomain (Postfix, from userid 1000) id C9A7C60789; Tue, 28 Nov 2023 10:44:02 +0100 (CET) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Date: Tue, 28 Nov 2023 10:44:01 +0100 Message-Id: <20231128094402.38115-5-d.csapak@proxmox.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231128094402.38115-1-d.csapak@proxmox.com> References: <20231128094402.38115-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.379 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RDNS_NONE 0.793 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record T_SCC_BODY_TEXT_LINE -0.01 - URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [rec.data, result.data] Subject: [pbs-devel] [PATCH proxmox-backup 4/5] ui: datastore content: add snapshot information to context menu X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Nov 2023 09:44:04 -0000 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 --- 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: ` ${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 = ` ${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