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 835F8B4EA; Wed, 9 Aug 2023 12:55:52 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 21BBA13D6B; Wed, 9 Aug 2023 12:55:52 +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; Wed, 9 Aug 2023 12:55:50 +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 6AA0643529; Wed, 9 Aug 2023 12:55:50 +0200 (CEST) From: Christian Ebner To: pve-devel@lists.proxmox.com, pmg-devel@lists.proxmox.com Date: Wed, 9 Aug 2023 12:55:26 +0200 Message-Id: <20230809105529.58459-2-c.ebner@proxmox.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230809105529.58459-1-c.ebner@proxmox.com> References: <20230809105529.58459-1-c.ebner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.145 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 SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pmg-devel] [PATCH v2 proxmox-widget-toolkit 1/2] fix #4442: adapt DateTimeField to be more declarative X-BeenThere: pmg-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Mail Gateway development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Aug 2023 10:55:52 -0000 Reworks the current implementation of the DateTimeField to be more declarative by using a ViewModel and data bindings as well as formulas, in order to reduce code and unwanted complexity. Signed-off-by: Christian Ebner --- changes since v1: - This patch was not part of the previous series, but it reworks the component, including modifications made by an applied patch of v1. src/form/DateTimeField.js | 281 ++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 160 deletions(-) diff --git a/src/form/DateTimeField.js b/src/form/DateTimeField.js index 13b1ed1..4bfa9bd 100644 --- a/src/form/DateTimeField.js +++ b/src/form/DateTimeField.js @@ -6,205 +6,166 @@ Ext.define('Proxmox.DateTimeField', { layout: 'hbox', - referenceHolder: true, + viewModel: { + data: { + datetime: null, + minDatetime: null, + maxDatetime: null, + }, + + formulas: { + date: { + get: function(get) { + return get('datetime'); + }, + set: function(date) { + if (!date) { + this.set('datetime', null); + return; + } + let datetime = new Date(this.get('datetime')); + datetime.setDate(date.getDate()); + datetime.setMonth(date.getMonth()); + datetime.setFullYear(date.getFullYear()); + this.set('datetime', datetime); + }, + }, + + time: { + get: function(get) { + return get('datetime'); + }, + set: function(time) { + if (!time) { + this.set('datetime', null); + return; + } + let datetime = new Date(this.get('datetime')); + datetime.setHours(time.getHours()); + datetime.setMinutes(time.getMinutes()); + datetime.setSeconds(time.getSeconds()); + datetime.setMilliseconds(time.getMilliseconds()); + this.set('datetime', datetime); + }, + }, + + minDate: { + get: function(get) { + let datetime = get('minDatetime'); + return datetime ? new Date(datetime) : null; + }, + }, + + maxDate: { + get: function(get) { + let datetime = get('maxDatetime'); + return datetime ? new Date(datetime) : null; + }, + }, + + minTime: { + get: function(get) { + let current = get('datetime'); + let min = get('minDatetime'); + if (min && current && !this.isSameDay(current, min)) { + return new Date(min).setHours('00', '00', '00', '000'); + } + return min; + }, + }, + + maxTime: { + get: function(get) { + let current = get('datetime'); + let max = get('maxDatetime'); + if (max && current && !this.isSameDay(current, max)) { + return new Date(max).setHours('23', '59', '59', '999'); + } + return max; + }, + }, + }, + + // Helper function to check if dates are the same day of the year + isSameDay: function(date1, date2) { + return date1.getDate() === date2.getDate() && + date1.getMonth() === date2.getMonth() && + date1.getFullYear() === date2.getFullYear(); + }, + }, config: { + value: null, submitFormat: 'U', disabled: false, }, setValue: function(value) { - let me = this; - me.setDate(value); - me.setTime(value); - - // Notify all 'value' bindings of state change - me.publishState('value', value); + this.getViewModel().set('datetime', value); }, getValue: function() { - let me = this; - let date = me.lookupReference('dateentry').getValue(); - - if (date === undefined || date === null) { return null; } - - let time = me.lookupReference('timeentry').getValue(); + return this.getViewModel().get('datetime'); + }, - if (time === undefined || time === null) { return null; } + getSubmitValue: function() { + let me = this; + let value = me.getValue(); + return value ? Ext.Date.format(value, me.submitFormat) : null; + }, - date.setHours(time.getHours()); - date.setMinutes(time.getMinutes()); - date.setSeconds(time.getSeconds()); - return date; + setMinValue: function(value) { + this.getViewModel().set('minDatetime', value); }, - getSubmitValue: function() { - let me = this; - let format = me.submitFormat; - let value = me.getValue(); + getMinValue: function() { + return this.getViewModel().get('minDatetime'); + }, - return value ? Ext.Date.format(value, format) : null; + setMaxValue: function(value) { + this.getViewModel().set('maxDatetime', value); }, - setDate: function(date) { - let me = this; - let dateEntry = me.lookupReference('dateentry'); - dateEntry.setValue(date); - dateEntry.publishState('value', date); + getMaxValue: function() { + return this.getViewModel().get('maxDatetime'); }, - setTime: function(time) { + initComponent: function() { let me = this; - let timeEntry = me.lookupReference('timeentry'); - timeEntry.setValue(time); - timeEntry.publishState('value', time); + me.callParent(); + + let vm = me.getViewModel(); + vm.set('datetime', me.config.value); + // Propagate state change to binding + vm.bind('{datetime}', function(value) { + me.publishState('value', value); + me.fireEvent('change', value); + }); }, items: [ { xtype: 'datefield', editable: false, - reference: 'dateentry', flex: 1, format: 'Y-m-d', bind: { - disabled: '{disabled}', - }, - listeners: { - 'change': function(field, newValue, oldValue) { - let dateTimeField = field.up('fieldcontainer'); - dateTimeField.setDate(newValue); - let value = dateTimeField.getValue(); - dateTimeField.publishState('value', value); - }, + value: '{date}', + minValue: '{minDate}', + maxValue: '{maxDate}', }, }, { xtype: 'timefield', - reference: 'timeentry', format: 'H:i', width: 80, value: '00:00', increment: 60, bind: { - disabled: '{disabled}', - }, - listeners: { - 'change': function(field, newValue, oldValue) { - let dateTimeField = field.up('fieldcontainer'); - dateTimeField.setTime(newValue); - let value = dateTimeField.getValue(); - dateTimeField.publishState('value', value); - }, + value: '{time}', + minValue: '{minTime}', + maxValue: '{maxTime}', }, }, ], - - setMinValue: function(value) { - let me = this; - let current = me.getValue(); - if (!value || !current) { - return; - } - - // Clone to avoid modifying the referenced value - let clone = new Date(value); - let minhours = clone.getHours(); - let minminutes = clone.getMinutes(); - - let hours = current.getHours(); - let minutes = current.getMinutes(); - - clone.setHours(0); - clone.setMinutes(0); - clone.setSeconds(0); - current.setHours(0); - current.setMinutes(0); - current.setSeconds(0); - - let time = new Date(); - if (current-clone > 0) { - time.setHours(0); - time.setMinutes(0); - time.setSeconds(0); - time.setMilliseconds(0); - } else { - time.setHours(minhours); - time.setMinutes(minminutes); - } - me.lookup('timeentry').setMinValue(time); - - // current time is smaller than the time part of the new minimum - // so we have to add 1 to the day - if (minhours*60+minminutes > hours*60+minutes) { - clone.setDate(clone.getDate()+1); - } - me.lookup('dateentry').setMinValue(clone); - }, - - setMaxValue: function(value) { - let me = this; - let current = me.getValue(); - if (!value || !current) { - return; - } - - // Clone to avoid modifying the referenced value - let clone = new Date(value); - let maxhours = clone.getHours(); - let maxminutes = clone.getMinutes(); - - let hours = current.getHours(); - let minutes = current.getMinutes(); - - clone.setHours(0); - clone.setMinutes(0); - clone.setSeconds(0); - clone.setMilliseconds(0); - current.setHours(0); - current.setMinutes(0); - current.setSeconds(0); - current.setMilliseconds(0); - - let time = new Date(); - if (clone-current > 0) { - time.setHours(23); - time.setMinutes(59); - time.setSeconds(59); - } else { - time.setHours(maxhours); - time.setMinutes(maxminutes); - } - me.lookup('timeentry').setMaxValue(time); - - // current time is bigger than the time part of the new maximum - // so we have to subtract 1 to the day - if (maxhours*60+maxminutes < hours*60+minutes) { - clone.setDate(clone.getDate()-1); - } - - me.lookup('dateentry').setMaxValue(clone); - }, - - initComponent: function() { - let me = this; - - me.callParent(); - - let value = me.value || new Date(); - - me.lookupReference('dateentry').setValue(value); - me.lookupReference('timeentry').setValue(value); - - if (me.minValue) { - me.setMinValue(me.minValue); - } - - if (me.maxValue) { - me.setMaxValue(me.maxValue); - } - - me.relayEvents(me.lookupReference('dateentry'), ['change']); - me.relayEvents(me.lookupReference('timeentry'), ['change']); - }, }); -- 2.39.2