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 2A223939C2 for ; Mon, 19 Sep 2022 13:13:56 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1FEEC159C for ; Mon, 19 Sep 2022 13:13:56 +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) server-digest SHA256) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Mon, 19 Sep 2022 13:13:54 +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 D59B4438A2 for ; Mon, 19 Sep 2022 13:13:53 +0200 (CEST) From: Matthias Heiserer To: pbs-devel@lists.proxmox.com Date: Mon, 19 Sep 2022 13:13:47 +0200 Message-Id: <20220919111347.187510-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.183 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 Subject: [pbs-devel] [PATCH v2 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: Mon, 19 Sep 2022 11:13:56 -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 slightly to the left, so the options part looks off-centered. Signed-off-by: Matthias Heiserer --- 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 | 145 +++++++++++++----- 1 file changed, 103 insertions(+), 42 deletions(-) diff --git a/docs/prune-simulator/prune-simulator_source.js b/docs/prune-simulator/prune-simulator_source.js index 84d3461c..e0948c96 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,102 @@ 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', + value: vm.get('now'), + listeners: { + select: function(_, day) { + const date = me.getViewModel().get('now'); + date.setFullYear( + day.getFullYear(), + day.getMonth(), + day.getDay(), + ); + }, + }, + }, + { + 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: { + select: function(_, record) { + const time = record.get('date'); + const date = me.getViewModel().get('now'); + date.setHours(time.getHours()); + date.setMinutes(time.getMinutes()); + }, + }, + }, + ], }, ], }, @@ -734,7 +795,7 @@ Ext.onReady(function() { xtype: 'prunesimulatorPruneList', store: me.pruneStore, reference: 'pruneList', - flex: 1, + flex: 2, }, ], }, -- 2.30.2