[FIX] web: fix calendar server values parsing
The record data given to fullCalendar to use in the renderEvent function was not parsed like it is in basic model for example. As a result, date(time) fields were string rather than moment objects, which was triggering the crash that started this commit.
This commit is contained in:
@@ -15,6 +15,7 @@ odoo.define('web.AbstractModel', function (require) {
|
||||
*/
|
||||
|
||||
var Class = require('web.Class');
|
||||
var fieldUtils = require('web.field_utils');
|
||||
var mixins = require('web.mixins');
|
||||
var ServicesMixin = require('web.ServicesMixin');
|
||||
|
||||
@@ -63,6 +64,30 @@ var AbstractModel = Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
reload: function (params) {
|
||||
return $.when();
|
||||
},
|
||||
/**
|
||||
* Processes date(time) and selection field values sent by the server.
|
||||
* Converts data(time) values to moment instances.
|
||||
* Converts false values of selection fields to 0 if 0 is a valid key,
|
||||
* because the server doesn't make a distinction between false and 0, and
|
||||
* always sends false when value is 0.
|
||||
*
|
||||
* @param {Object} field the field description
|
||||
* @param {*} value
|
||||
* @returns {*} the processed value
|
||||
*/
|
||||
_parseServerValue: function (field, value) {
|
||||
if (field.type === 'date' || field.type === 'datetime') {
|
||||
// process date(time): convert into a moment instance
|
||||
value = fieldUtils.parse[field.type](value, field, {isUTC: true});
|
||||
} else if (field.type === 'selection' && value === false) {
|
||||
// process selection: convert false to 0, if 0 is a valid key
|
||||
var hasKey0 = _.find(field.selection, function (option) {
|
||||
return option[0] === 0;
|
||||
});
|
||||
value = hasKey0 ? 0 : value;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
});
|
||||
|
||||
return AbstractModel;
|
||||
|
||||
@@ -87,7 +87,6 @@ var concurrency = require('web.concurrency');
|
||||
var Context = require('web.Context');
|
||||
var core = require('web.core');
|
||||
var Domain = require('web.Domain');
|
||||
var fieldUtils = require('web.field_utils');
|
||||
var session = require('web.session');
|
||||
|
||||
var _t = core._t;
|
||||
@@ -2946,30 +2945,6 @@ var BasicModel = AbstractModel.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Processes date(time) and selection field values sent by the server.
|
||||
* Converts data(time) values to moment instances.
|
||||
* Converts false values of selection fields to 0 if 0 is a valid key,
|
||||
* because the server doesn't make a distinction between false and 0, and
|
||||
* always sends false when value is 0.
|
||||
*
|
||||
* @param {Object} field the field description
|
||||
* @param {*} value
|
||||
* @returns {*} the processed value
|
||||
*/
|
||||
_parseServerValue: function (field, value) {
|
||||
if (field.type === 'date' || field.type === 'datetime') {
|
||||
// process date(time): convert into a moment instance
|
||||
value = fieldUtils.parse[field.type](value, field, {isUTC: true});
|
||||
} else if (field.type === 'selection' && value === false) {
|
||||
// process selection: convert false to 0, if 0 is a valid key
|
||||
var hasKey0 = _.find(field.selection, function (option) {
|
||||
return option[0] === 0;
|
||||
});
|
||||
value = hasKey0 ? 0 : value;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
/**
|
||||
* This method is quite important: it is supposed to perform the /onchange
|
||||
* rpc and apply the result.
|
||||
|
||||
@@ -406,12 +406,13 @@ return AbstractModel.extend({
|
||||
});
|
||||
}
|
||||
return eventsDef.then(function (events) {
|
||||
self.data.data = _.map(events, self._recordToCalendarEvent.bind(self));
|
||||
return $.when(
|
||||
self._loadColors(self.data, self.data.data),
|
||||
self._loadRecordsToFilters(self.data, self.data.data)
|
||||
);
|
||||
});
|
||||
self._parseServerData(events);
|
||||
self.data.data = _.map(events, self._recordToCalendarEvent.bind(self));
|
||||
return $.when(
|
||||
self._loadColors(self.data, self.data.data),
|
||||
self._loadRecordsToFilters(self.data, self.data.data)
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -566,11 +567,24 @@ return AbstractModel.extend({
|
||||
if (filter.filters.length && (filter.filters[0].avatar_model in to_read)) {
|
||||
_.each(filter.filters, function (f) {
|
||||
f.label = to_read[f.avatar_model][f.value];
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* parse the server values to javascript framwork
|
||||
*
|
||||
* @param {Object} data the server data to parse
|
||||
*/
|
||||
_parseServerData: function (data) {
|
||||
var self = this;
|
||||
_.each(data, function(event) {
|
||||
_.each(self.fieldNames, function (fieldName) {
|
||||
event[fieldName] = self._parseServerValue(self.fields[fieldName], event[fieldName]);
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Transform OpenERP event object to fullcalendar event object
|
||||
*/
|
||||
@@ -583,11 +597,11 @@ return AbstractModel.extend({
|
||||
attendees = [];
|
||||
|
||||
if (!all_day) {
|
||||
date_start = fieldUtils.parse.datetime(evt[this.mapping.date_start]);
|
||||
date_stop = this.mapping.date_stop ? fieldUtils.parse.datetime(evt[this.mapping.date_stop]) : null;
|
||||
date_start = evt[this.mapping.date_start].clone();
|
||||
date_stop = this.mapping.date_stop ? evt[this.mapping.date_stop].clone() : null;
|
||||
} else {
|
||||
date_start = fieldUtils.parse.datetime(evt[this.mapping.date_start].split(' ')[0]);
|
||||
date_stop = this.mapping.date_stop ? fieldUtils.parse.datetime(evt[this.mapping.date_stop].split(' ')[0]) : null;
|
||||
date_start = evt[this.mapping.date_start].clone().startOf('day');
|
||||
date_stop = this.mapping.date_stop ? evt[this.mapping.date_stop].clone().startOf('day') : null;
|
||||
}
|
||||
|
||||
if (!date_stop && date_delay) {
|
||||
@@ -605,8 +619,8 @@ return AbstractModel.extend({
|
||||
'record': evt,
|
||||
'start': date_start,
|
||||
'end': date_stop,
|
||||
'r_start':date_start.clone(),
|
||||
'r_end':date_stop.clone(),
|
||||
'r_start': date_start,
|
||||
'r_end': date_stop,
|
||||
'title': the_title,
|
||||
'allDay': this.mapping.all_day && evt[this.mapping.all_day] || false,
|
||||
'id': evt.id,
|
||||
|
||||
@@ -3,6 +3,7 @@ odoo.define('web.calendar_tests', function (require) {
|
||||
|
||||
var CalendarView = require('web.CalendarView');
|
||||
var CalendarRenderer = require('web.CalendarRenderer');
|
||||
var fieldUtils = require('web.field_utils');
|
||||
var testUtils = require('web.test_utils');
|
||||
var session = require('web.session');
|
||||
|
||||
@@ -431,6 +432,7 @@ QUnit.module('Views', {
|
||||
'mode="week" '+
|
||||
'readonly_form_view_id="1">'+
|
||||
'<field name="name"/>'+
|
||||
'<field name="start"/>'+
|
||||
'</calendar>',
|
||||
archs: archs,
|
||||
viewOptions: {
|
||||
@@ -478,14 +480,14 @@ QUnit.module('Views', {
|
||||
$('.modal button.btn:contains(Create)').trigger('click');
|
||||
var $newevent = calendar.$('.fc-event:contains(new event)');
|
||||
|
||||
assert.strictEqual($newevent.text().replace(/[\s\n\r]+/g, ''), "08:00-10:00newevent",
|
||||
assert.strictEqual($newevent.text().replace(/[\s\n\r]+/g, ''), "08:00-10:00newevent12/13/201608:00:00",
|
||||
"should display the new event with time and title");
|
||||
|
||||
assert.deepEqual($newevent.data('fcSeg').event.record,
|
||||
{
|
||||
display_name: "new event",
|
||||
start: "2016-12-13 06:00:00",
|
||||
stop: "2016-12-13 08:00:00",
|
||||
start: fieldUtils.parse.datetime("2016-12-13 06:00:00", this.data.event.fields.start, {isUTC: true}),
|
||||
stop: fieldUtils.parse.datetime("2016-12-13 08:00:00", this.data.event.fields.stop, {isUTC: true}),
|
||||
allday: false,
|
||||
name: "new event",
|
||||
id: 1
|
||||
@@ -616,8 +618,8 @@ QUnit.module('Views', {
|
||||
assert.deepEqual($newevent.data('fcSeg').event.record,
|
||||
{
|
||||
display_name: "new event",
|
||||
start: "2016-12-13 06:00:00",
|
||||
stop: "2016-12-13 08:00:00",
|
||||
start: fieldUtils.parse.datetime("2016-12-13 06:00:00", this.data.event.fields.start, {isUTC: true}),
|
||||
stop: fieldUtils.parse.datetime("2016-12-13 08:00:00", this.data.event.fields.stop, {isUTC: true}),
|
||||
allday: false,
|
||||
name: "new event",
|
||||
id: 1
|
||||
@@ -691,8 +693,8 @@ QUnit.module('Views', {
|
||||
assert.deepEqual($newevent.data('fcSeg').event.record,
|
||||
{
|
||||
display_name: "new event",
|
||||
start: "2016-12-14 00:00:00",
|
||||
stop: "2016-12-15 00:00:00",
|
||||
start: fieldUtils.parse.datetime("2016-12-14 00:00:00", this.data.event.fields.start, {isUTC: true}),
|
||||
stop: fieldUtils.parse.datetime("2016-12-15 00:00:00", this.data.event.fields.stop, {isUTC: true}),
|
||||
allday: true,
|
||||
name: "new event",
|
||||
id: 1
|
||||
|
||||
Reference in New Issue
Block a user