diff --git a/frappe/public/js/frappe/form/control.js b/frappe/public/js/frappe/form/control.js index 83e8022f52..6a85c24c2f 100755 --- a/frappe/public/js/frappe/form/control.js +++ b/frappe/public/js/frappe/form/control.js @@ -751,29 +751,38 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ if(!$.fn.datepicker.language[lang]) { lang = 'en'; } + this.today_text = __("Today"); this.datepicker_options = { language: lang, autoClose: true, - todayButton: new Date(), + todayButton: frappe.datetime.now_date(true), dateFormat: (frappe.boot.sysdefaults.date_format || 'yyyy-mm-dd'), - onSelect: function(dateStr) { - me.$input.trigger('change'); + startDate: frappe.datetime.now_date(true), + onSelect: () => { + this.$input.trigger('change'); }, - onShow: function() { - $('.datepicker--button:visible').text(__('Today')); - - if(!me.frm) return; - var window_height = $(window).height(); - var window_scroll_top = $(window).scrollTop(); - var el_offset_top = me.$input.offset().top + 280; - var position = 'top left'; - if(window_height + window_scroll_top >= el_offset_top) { - position = 'bottom left'; - } - me.datepicker.update('position', position); + onShow: () => { + this.datepicker.$datepicker + .find('.datepicker--button:visible') + .text(me.today_text); + + this.update_datepicker_position(); } }; }, + update_datepicker_position: function() { + if(!this.frm) return; + // show datepicker above or below the input + // based on scroll position + var window_height = $(window).height(); + var window_scroll_top = $(window).scrollTop(); + var el_offset_top = this.$input.offset().top + 280; + var position = 'top left'; + if(window_height + window_scroll_top >= el_offset_top) { + position = 'bottom left'; + } + this.datepicker.update('position', position); + }, set_datepicker: function() { this.$input.datepicker(this.datepicker_options); this.datepicker = this.$input.data('datepicker'); @@ -813,6 +822,30 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ } }); +frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ + set_date_options: function() { + this._super(); + this.today_text = __("Now"); + $.extend(this.datepicker_options, { + timepicker: true, + timeFormat: "hh:ii:ss", + todayButton: frappe.datetime.now_datetime(true) + }); + }, + set_description: function() { + const { description } = this.df; + const { time_zone } = frappe.sys_defaults; + if (!frappe.datetime.is_timezone_same()) { + if (!description) { + this.df.description = time_zone; + } else if (!description.includes(time_zone)) { + this.df.description += '
' + time_zone; + } + } + this._super(); + } +}); + frappe.ui.form.ControlTime = frappe.ui.form.ControlData.extend({ make_input: function() { var me = this; @@ -822,13 +855,14 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlData.extend({ timepicker: true, onlyTimepicker: true, timeFormat: "hh:ii:ss", + startDate: frappe.datetime.now_time(true), onSelect: function() { me.$input.trigger('change'); }, onShow: function() { $('.datepicker--button:visible').text(__('Now')); }, - todayButton: new Date() + todayButton: frappe.datetime.now_time(true) }); this.datepicker = this.$input.data('datepicker'); this.refresh(); @@ -839,33 +873,21 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlData.extend({ && ((this.last_value && this.last_value !== this.value) || (!this.datepicker.selectedDates.length))) { - this.datepicker.selectDate(moment(value, 'hh:mm:ss')._d); + var date_obj = frappe.datetime.moment_to_date_obj(moment(value, 'hh:mm:ss')); + this.datepicker.selectDate(date_obj); } }, -}); - -frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ - set_date_options: function() { - this._super(); - this.datepicker_options.timepicker = true; - this.datepicker_options.timeFormat = "hh:ii:ss"; - this.datepicker_options.onShow = function() { - $('.datepicker--button:visible').text(__('Now')); - }; - }, - parse: function(value) { - if(value) { - // parse and convert - value = frappe.datetime.convert_to_system_tz(frappe.datetime.user_to_str(value)); - } - return value; - }, - format_for_input: function(value) { - if(value) { - // convert and format - value = frappe.datetime.str_to_user(frappe.datetime.convert_to_user_tz(value)); + set_description: function() { + const { description } = this.df; + const { time_zone } = frappe.sys_defaults; + if (!frappe.datetime.is_timezone_same()) { + if (!description) { + this.df.description = time_zone; + } else if (!description.includes(time_zone)) { + this.df.description += '
' + time_zone; + } } - return value || ""; + this._super(); } }); diff --git a/frappe/public/js/frappe/misc/datetime.js b/frappe/public/js/frappe/misc/datetime.js index 25d409524d..1e49848c38 100644 --- a/frappe/public/js/frappe/misc/datetime.js +++ b/frappe/public/js/frappe/misc/datetime.js @@ -3,8 +3,11 @@ frappe.provide('frappe.datetime'); -moment.defaultFormat = "YYYY-MM-DD"; -moment.defaultDatetimeFormat = "YYYY-MM-DD HH:mm:ss" +moment.defaultDateFormat = "YYYY-MM-DD"; +moment.defaultTimeFormat = "HH:mm:ss"; +moment.defaultDatetimeFormat = moment.defaultDateFormat + " " + moment.defaultTimeFormat; +moment.defaultFormat = moment.defaultDateFormat; + frappe.provide("frappe.datetime"); $.extend(frappe.datetime, { @@ -91,8 +94,14 @@ $.extend(frappe.datetime, { return frappe.sys_defaults.date_format || "yyyy-mm-dd"; }, - str_to_user: function(val, no_time_str) { + str_to_user: function(val, only_time = false) { if(!val) return ""; + + if(only_time) { + return moment(val, moment.defaultTimeFormat) + .format(moment.defaultTimeFormat); + } + var user_fmt = frappe.datetime.get_user_fmt().toUpperCase(); if(typeof val !== "string" || val.indexOf(" ")===-1) { return moment(val).format(user_fmt); @@ -101,15 +110,17 @@ $.extend(frappe.datetime, { } }, - now_datetime: function() { - return moment().format("YYYY-MM-DD HH:mm:ss"); - }, - get_datetime_as_string: function(d) { return moment(d).format("YYYY-MM-DD HH:mm:ss"); }, - user_to_str: function(val, no_time_str) { + user_to_str: function(val, only_time = false) { + + if(only_time) { + return moment(val, moment.defaultTimeFormat) + .format(moment.defaultTimeFormat); + } + var user_fmt = frappe.datetime.get_user_fmt().toUpperCase(); var system_fmt = "YYYY-MM-DD"; @@ -136,21 +147,60 @@ $.extend(frappe.datetime, { } }, - get_today: function() { - return moment().locale("en").format(); + now_date: function(as_obj = false) { + return frappe.datetime._date(moment.defaultDateFormat, as_obj); + }, + + now_time: function(as_obj = false) { + return frappe.datetime._date(moment.defaultTimeFormat, as_obj); + }, + + now_datetime: function(as_obj = false) { + return frappe.datetime._date(moment.defaultDatetimeFormat, as_obj); + }, + + _date: function(format, as_obj = false) { + const { time_zone } = frappe.sys_defaults; + let date; + if (time_zone) { + date = moment.tz(time_zone); + } else { + date = moment(); + } + if (as_obj) { + return frappe.datetime.moment_to_date_obj(date); + } else { + return date.format(format); + } + }, + + moment_to_date_obj: function(moment) { + const date_obj = new Date(); + const date_array = moment.toArray(); + date_obj.setFullYear(date_array[0]); + date_obj.setMonth(date_array[1]); + date_obj.setDate(date_array[2]); + date_obj.setHours(date_array[3]); + date_obj.setMinutes(date_array[4]); + date_obj.setSeconds(date_array[5]); + date_obj.setMilliseconds(date_array[6]); + return date_obj; }, nowdate: function() { - return frappe.datetime.get_today(); + return frappe.datetime.now_date(); }, - now_time: function() { - return frappe.datetime.convert_to_system_tz(moment(), false) - .locale("en").format("HH:mm:ss"); + get_today: function() { + return frappe.datetime.now_date(); }, validate: function(d) { - return moment(d).isValid(); + return moment(d, [ + moment.defaultDateFormat, + moment.defaultDatetimeFormat, + moment.defaultTimeFormat + ], true).isValid(); }, });