[pve-devel] [PATCH v2 proxmox-widget-toolkit 1/2] fix #4442: adapt DateTimeField to be more declarative

Christian Ebner c.ebner at proxmox.com
Wed Aug 9 12:55:26 CEST 2023


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 at 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






More information about the pve-devel mailing list