From: Christian Ebner <c.ebner@proxmox.com>
To: pve-devel@lists.proxmox.com, pmg-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH v2 proxmox-widget-toolkit 1/2] fix #4442: adapt DateTimeField to be more declarative
Date: Wed, 9 Aug 2023 12:55:26 +0200 [thread overview]
Message-ID: <20230809105529.58459-2-c.ebner@proxmox.com> (raw)
In-Reply-To: <20230809105529.58459-1-c.ebner@proxmox.com>
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 <c.ebner@proxmox.com>
---
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
next prev parent reply other threads:[~2023-08-09 10:55 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-09 10:55 [pve-devel] [PATCH v2 proxmox-widget-toolkit manager pmg-gui 0/4] #4442: impl firewall log filtering Christian Ebner
2023-08-09 10:55 ` Christian Ebner [this message]
2023-08-09 10:55 ` [pve-devel] [PATCH v2 proxmox-widget-toolkit 2/2] fix #4442: Extend LogView for firewall datetime filtering Christian Ebner
2023-08-09 10:55 ` [pve-devel] [PATCH v2 manager 3/3] fix #4442: Add date-time filtering for firewall logs Christian Ebner
2023-08-09 10:55 ` [pve-devel] [PATCH v2 pmg-gui 4/4] Revert "fix tracking center with newer proxmox-widget-toolkit" Christian Ebner
2023-11-09 9:22 ` [pve-devel] [PATCH v2 proxmox-widget-toolkit manager pmg-gui 0/4] #4442: impl firewall log filtering Christian Ebner
2023-11-14 15:45 ` [pve-devel] applied: " Thomas Lamprecht
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=20230809105529.58459-2-c.ebner@proxmox.com \
--to=c.ebner@proxmox.com \
--cc=pmg-devel@lists.proxmox.com \
--cc=pve-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