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 5A12493F0D for ; Tue, 20 Sep 2022 15:22:14 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 95EB21D150 for ; Tue, 20 Sep 2022 15:22:13 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (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 firstgate.proxmox.com (Proxmox) with ESMTPS for ; Tue, 20 Sep 2022 15:22:07 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 5B11643868 for ; Tue, 20 Sep 2022 15:22:05 +0200 (CEST) From: Matthias Heiserer To: pbs-devel@lists.proxmox.com Date: Tue, 20 Sep 2022 15:21:28 +0200 Message-Id: <20220920132128.380765-1-m.heiserer@proxmox.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.181 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [proxmox.com] Subject: [pbs-devel] [PATCH v3 proxmox-backup] prune-simulator: allow setting a custom date/time 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, 20 Sep 2022 13:22:14 -0000 With this, the prune simulator will be more flexible, which might clear up questions such as these: https://forum.proxmox.com/threads/pbs-prune-simulator-monthly-backups.115081 In order to have the configuration window not take up too much space, I added another column and moved the border to the left. Signed-off-by: Matthias Heiserer --- Thanks to fiona for the many suggestions! CHANGES FROM v2: use getDate (gives day of month) instead of getDay (day of week) change instead of select, and check that input is valid use Y-m-d in date selector to stay consistent with rest of page include backup happening at selected time in simulation slightly reworded commit message CHANGES FROM v1: squash patches wider column so no fields are cut off smaller year/time labels use viewmodel instead of `const NOW` improve patch title 24h (hh:mm) format for time .../prune-simulator/prune-simulator_source.js | 151 +++++++++++++----- 1 file changed, 109 insertions(+), 42 deletions(-) diff --git a/docs/prune-simulator/prune-simulator_source.js b/docs/prune-simulator/prune-simulator_source.js index 84d3461c..fe0ea22b 100644 --- a/docs/prune-simulator/prune-simulator_source.js +++ b/docs/prune-simulator/prune-simulator_source.js @@ -2,7 +2,6 @@ function gettext(val) { return val; }; Ext.onReady(function() { - const NOW = new Date(); const COLORS = { 'keep-last': 'orange', 'keep-hourly': 'purple', @@ -180,7 +179,7 @@ Ext.onReady(function() { let html = ''; - let now = new Date(NOW.getTime()); + let now = new Date(me.up().getViewModel().get('now')); let skip = 7 - parseInt(Ext.Date.format(now, 'N'), 10); let tableStartDate = Ext.Date.add(now, Ext.Date.DAY, skip); @@ -295,6 +294,9 @@ Ext.onReady(function() { alias: 'widget.prunesimulatorPanel', viewModel: { + data: { + now: new Date(), + }, }, getValues: function() { @@ -424,6 +426,8 @@ Ext.onReady(function() { // backups are sorted descending by date populateFromSchedule: function(weekdays, hours, minutes, weekCount) { + const me = this; + let weekdayFlags = [ weekdays.includes('sun'), weekdays.includes('mon'), @@ -434,7 +438,8 @@ Ext.onReady(function() { weekdays.includes('sat'), ]; - let todaysDate = new Date(NOW.getTime()); + const vmDate = me.getViewModel().get('now'); + let todaysDate = new Date(vmDate); let timesOnSingleDay = []; @@ -456,9 +461,10 @@ Ext.onReady(function() { let weekday = parseInt(Ext.Date.format(daysDate, 'w'), 10); if (weekdayFlags[weekday]) { timesOnSingleDay.forEach(function(time) { - backups.push({ - backuptime: Ext.Date.subtract(new Date(time), Ext.Date.DAY, i), - }); + const backuptime = Ext.Date.subtract(new Date(time), Ext.Date.DAY, i); + if (backuptime <= vmDate) { + backups.push({ backuptime: backuptime }); + } }); } } @@ -619,6 +625,7 @@ Ext.onReady(function() { initComponent: function() { var me = this; + const vm = me.getViewModel(); me.pruneStore = Ext.create('Ext.data.Store', { model: 'pbs-prune-list', @@ -661,48 +668,108 @@ Ext.onReady(function() { { xtype: "panel", width: 1, border: 1 }, { xtype: 'form', - layout: 'anchor', - flex: 1, + layout: 'hbox', + flex: 2, border: false, title: 'Simulated Backup Schedule', - defaults: { - labelWidth: 120, - }, bodyPadding: 10, items: [ { - xtype: 'prunesimulatorDayOfWeekSelector', - name: 'schedule-weekdays', - fieldLabel: 'Day of week', - value: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'], - allowBlank: false, - multiSelect: true, - padding: '0 0 0 10', + xtype: 'container', + layout: 'anchor', + defaults: { + labelWidth: 120, + }, + items: [ + { + xtype: 'prunesimulatorDayOfWeekSelector', + name: 'schedule-weekdays', + fieldLabel: 'Day of week', + value: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'], + allowBlank: false, + multiSelect: true, + padding: '0 0 0 10', + }, + { + xtype: 'prunesimulatorCalendarEvent', + name: 'schedule-time', + allowBlank: false, + value: '0/6:00', + fieldLabel: 'Backup schedule', + padding: '0 0 0 10', + }, + { + xtype: 'numberfield', + name: 'numberOfWeeks', + allowBlank: false, + fieldLabel: 'Number of weeks', + minValue: 1, + value: 15, + maxValue: 260, // five years + padding: '0 0 0 10', + }, + { + xtype: 'button', + name: 'schedule-button', + text: 'Update Schedule', + formBind: true, + handler: 'reloadFull', + }, + ], }, { - xtype: 'prunesimulatorCalendarEvent', - name: 'schedule-time', - allowBlank: false, - value: '0/6:00', - fieldLabel: 'Backup schedule', - padding: '0 0 0 10', - }, - { - xtype: 'numberfield', - name: 'numberOfWeeks', - allowBlank: false, - fieldLabel: 'Number of weeks', - minValue: 1, - value: 15, - maxValue: 260, // five years - padding: '0 0 0 10', - }, - { - xtype: 'button', - name: 'schedule-button', - text: 'Update Schedule', - formBind: true, - handler: 'reloadFull', + xtype: 'container', + layout: 'anchor', + defaults: { + labelWidth: 60, + }, + items: [ + { + xtype: 'datefield', + name: 'currentDate', + fieldLabel: 'Date', + allowBlank: false, + padding: '0 0 0 10', + format: 'Y-m-d', + value: vm.get('now'), + listeners: { + change: function(self, newDate) { + if (!self.isValid()) { + return; + } + const date = me.getViewModel().get('now'); + date.setFullYear( + newDate.getFullYear(), + newDate.getMonth(), + newDate.getDate(), + ); + }, + }, + }, + { + xtype: 'timefield', + name: 'currentTime', + reference: 'currentTime', + fieldLabel: 'Time', + allowBlank: false, + padding: '0 0 0 10', + format: 'H:i', + // cant bind value because ExtJS sets the year + // to 2008 to protect against DST issues + // and date picker zeroes hour/minute + value: vm.get('now'), + listeners: { + change: function(self, time) { + if (!self.isValid()) { + return; + } + const date = me.getViewModel().get('now'); + date.setHours(time.getHours()); + date.setMinutes(time.getMinutes()); + }, + }, + }, + ], }, ], }, @@ -734,7 +801,7 @@ Ext.onReady(function() { xtype: 'prunesimulatorPruneList', store: me.pruneStore, reference: 'pruneList', - flex: 1, + flex: 2, }, ], }, -- 2.30.2