Skip to content

Commit

Permalink
[FIX] web: search input date in another timezone
Browse files Browse the repository at this point in the history
Put the browser in timezone Sao Paulo (Or like West of UTC)

Trigger the autocomplete (and the subsequent search) on a date field
by writing a date (in the locale format) in the search view

Before this commit, the domain sent to the server contained the date as the day
**before** the one asked for in the input

This is because, the string input is parsed and gives:
input = 12/02/2018
When creating the moment object:
> since there is no explicit time, moment will interpret it as 12am (midnight)
> We force moment to consider the string as being UTC (function: moment.utc())
> the moment contains, as output the time ** 2018-02-12T00:00:00 UTC **

When getting the facet value for making the domain
> we call toDate on the moment object, which, according to the browser is UTC and will
be converted to the locale timezone before formatting
> And the domain will use the date 2018-02-11T22:00:00 Brazil/SaoPaulo
which gives the day before the one we asked for

After this commit, this issue doesn't arise, because we don't convert the moment into a Date,
and we directly format that moment into a string

OPW 1903224

closes #28689
  • Loading branch information
kebeclibre committed Nov 20, 2018
1 parent 8ccc976 commit 4626817
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 7 deletions.
11 changes: 4 additions & 7 deletions addons/web/static/src/js/views/search/search_inputs.js
Expand Up @@ -346,7 +346,8 @@ var BooleanField = SelectionField.extend(/** @lends instance.web.search.BooleanF
*/
var DateField = Field.extend(/** @lends instance.web.search.DateField# */{
value_from: function (facetValue) {
return time.date_to_str(facetValue.get('value'));
var serverFormat = (this.attrs && this.attrs.type === 'datetime') ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
return facetValue.get('valueAsMoment').clone().format(serverFormat);
},
complete: function (needle) {
// Make sure the needle has a correct format before the creation of the moment object. See
Expand All @@ -371,7 +372,7 @@ var DateField = Field.extend(/** @lends instance.web.search.DateField# */{
facet: {
category: this.attrs.string,
field: this,
values: [{label: date_string, value: m.toDate()}]
values: [{label: date_string, value: m.toDate(), valueAsMoment: m.clone()}]
}
}]);
}
Expand All @@ -388,11 +389,7 @@ var DateField = Field.extend(/** @lends instance.web.search.DateField# */{
* @class
* @extends instance.web.DateField
*/
var DateTimeField = DateField.extend(/** @lends instance.web.search.DateTimeField# */{
value_from: function (facetValue) {
return time.datetime_to_str(facetValue.get('value'));
}
});
var DateTimeField = DateField;

var ManyToOneField = CharField.extend({
default_operator: {},
Expand Down
89 changes: 89 additions & 0 deletions addons/web/static/tests/views/search_view_tests.js
Expand Up @@ -461,6 +461,95 @@ QUnit.module('Search View', {

QUnit.module('Filters Menu');

QUnit.test('Search date and datetime fields. Support of timezones', function (assert) {
assert.expect(4);

this.data.partner.fields.birth_datetime = {string: "Birth DateTime", type: "datetime", store: true, sortable: true};
this.data.partner.records = this.data.partner.records.slice(0,-1); // exclude wrong date record

function stringToEvent ($element, string) {
for (var i = 0; i < string.length; i++) {
var keyAscii = string.charCodeAt(i);
$element.val($element.val()+string[i]);
$element.trigger($.Event('keyup', {which: keyAscii, keyCode:keyAscii}));
}
}

var searchReadSequence = 0;
var actionManager = createActionManager({
actions: [{
id: 11,
name: 'Partners Action 11',
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[3, 'list']],
search_view_id: [9, 'search'],
}],
archs: {
'partner,3,list': '<tree>' +
'<field name="foo"/>' +
'<field name="birthday" />' +
'<field name="birth_datetime" />' +
'</tree>',

'partner,9,search': '<search>'+
'<field name="birthday"/>' +
'<field name="birth_datetime" />' +
'</search>',
},
data: this.data,
session: {
getTZOffset: function() {
return 360;
}
},
mockRPC: function (route, args) {
if (route === '/web/dataset/search_read') {
if (searchReadSequence === 1) { // The 0th time is at loading
assert.deepEqual(args.domain, [["birthday", "=", "1983-07-15"]],
'A date should stay what the user has input, but transmitted in server\'s format');
} else if (searchReadSequence === 3) { // the 2nd time is at closing the first facet
assert.deepEqual(args.domain, [["birth_datetime", "=", "1983-07-14 18:00:00"]],
'A datetime should be transformed in UTC and transmitted in server\'s format');
}
searchReadSequence+=1;
}
return this._super.apply(this, arguments);
},
});

actionManager.doAction(11);

// Date case
var $autocomplete = $('.o_searchview_input');
stringToEvent($autocomplete, '07/15/1983');

$autocomplete.trigger($.Event('keyup', {
which: $.ui.keyCode.ENTER,
keyCode: $.ui.keyCode.ENTER,
}));

assert.equal($('.o_searchview_facet .o_facet_values').text().trim(), '07/15/1983',
'The format of the date in the facet should be in locale');

// Close Facet
$('.o_searchview_facet .o_facet_remove').click();

// DateTime case
$autocomplete = $('.o_searchview_input');
stringToEvent($autocomplete, '07/15/1983 00:00:00');

$autocomplete.trigger($.Event('keyup', {
which: $.ui.keyCode.ENTER,
keyCode: $.ui.keyCode.ENTER,
}));

assert.equal($('.o_searchview_facet .o_facet_values').text().trim(), '07/15/1983 00:00:00',
'The format of the datetime in the facet should be in locale');

actionManager.destroy();
});

QUnit.test('add a custom filter works', function (assert) {
assert.expect(1);

Expand Down

0 comments on commit 4626817

Please sign in to comment.