mirror of
https://git.proxmox.com/git/proxmox-widget-toolkit
synced 2025-05-22 22:00:18 +00:00
fix #4442: adapt DateTimeField to be more declarative
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>
This commit is contained in:
parent
8fc1d232ea
commit
0e3cb037d6
@ -6,205 +6,166 @@ Ext.define('Proxmox.DateTimeField', {
|
|||||||
|
|
||||||
layout: 'hbox',
|
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: {
|
config: {
|
||||||
|
value: null,
|
||||||
submitFormat: 'U',
|
submitFormat: 'U',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
setValue: function(value) {
|
setValue: function(value) {
|
||||||
let me = this;
|
this.getViewModel().set('datetime', value);
|
||||||
me.setDate(value);
|
|
||||||
me.setTime(value);
|
|
||||||
|
|
||||||
// Notify all 'value' bindings of state change
|
|
||||||
me.publishState('value', value);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getValue: function() {
|
getValue: function() {
|
||||||
let me = this;
|
return this.getViewModel().get('datetime');
|
||||||
let date = me.lookupReference('dateentry').getValue();
|
|
||||||
|
|
||||||
if (date === undefined || date === null) { return null; }
|
|
||||||
|
|
||||||
let time = me.lookupReference('timeentry').getValue();
|
|
||||||
|
|
||||||
if (time === undefined || time === null) { return null; }
|
|
||||||
|
|
||||||
date.setHours(time.getHours());
|
|
||||||
date.setMinutes(time.getMinutes());
|
|
||||||
date.setSeconds(time.getSeconds());
|
|
||||||
return date;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getSubmitValue: function() {
|
getSubmitValue: function() {
|
||||||
let me = this;
|
let me = this;
|
||||||
let format = me.submitFormat;
|
let value = me.getValue();
|
||||||
let value = me.getValue();
|
return value ? Ext.Date.format(value, me.submitFormat) : null;
|
||||||
|
|
||||||
return value ? Ext.Date.format(value, format) : null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setDate: function(date) {
|
setMinValue: function(value) {
|
||||||
let me = this;
|
this.getViewModel().set('minDatetime', value);
|
||||||
let dateEntry = me.lookupReference('dateentry');
|
|
||||||
dateEntry.setValue(date);
|
|
||||||
dateEntry.publishState('value', date);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setTime: function(time) {
|
getMinValue: function() {
|
||||||
|
return this.getViewModel().get('minDatetime');
|
||||||
|
},
|
||||||
|
|
||||||
|
setMaxValue: function(value) {
|
||||||
|
this.getViewModel().set('maxDatetime', value);
|
||||||
|
},
|
||||||
|
|
||||||
|
getMaxValue: function() {
|
||||||
|
return this.getViewModel().get('maxDatetime');
|
||||||
|
},
|
||||||
|
|
||||||
|
initComponent: function() {
|
||||||
let me = this;
|
let me = this;
|
||||||
let timeEntry = me.lookupReference('timeentry');
|
me.callParent();
|
||||||
timeEntry.setValue(time);
|
|
||||||
timeEntry.publishState('value', time);
|
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: [
|
items: [
|
||||||
{
|
{
|
||||||
xtype: 'datefield',
|
xtype: 'datefield',
|
||||||
editable: false,
|
editable: false,
|
||||||
reference: 'dateentry',
|
|
||||||
flex: 1,
|
flex: 1,
|
||||||
format: 'Y-m-d',
|
format: 'Y-m-d',
|
||||||
bind: {
|
bind: {
|
||||||
disabled: '{disabled}',
|
value: '{date}',
|
||||||
},
|
minValue: '{minDate}',
|
||||||
listeners: {
|
maxValue: '{maxDate}',
|
||||||
'change': function(field, newValue, oldValue) {
|
|
||||||
let dateTimeField = field.up('fieldcontainer');
|
|
||||||
dateTimeField.setDate(newValue);
|
|
||||||
let value = dateTimeField.getValue();
|
|
||||||
dateTimeField.publishState('value', value);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
xtype: 'timefield',
|
xtype: 'timefield',
|
||||||
reference: 'timeentry',
|
|
||||||
format: 'H:i',
|
format: 'H:i',
|
||||||
width: 80,
|
width: 80,
|
||||||
value: '00:00',
|
value: '00:00',
|
||||||
increment: 60,
|
increment: 60,
|
||||||
bind: {
|
bind: {
|
||||||
disabled: '{disabled}',
|
value: '{time}',
|
||||||
},
|
minValue: '{minTime}',
|
||||||
listeners: {
|
maxValue: '{maxTime}',
|
||||||
'change': function(field, newValue, oldValue) {
|
|
||||||
let dateTimeField = field.up('fieldcontainer');
|
|
||||||
dateTimeField.setTime(newValue);
|
|
||||||
let value = dateTimeField.getValue();
|
|
||||||
dateTimeField.publishState('value', value);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
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']);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user