[FIX] web: Calendar: correctly display events

Before this rev., the events in Calendar views (month mode) weren't
correctly displayed: the last day of the event wasn't displayed as
being part of the event. For instance, in leaves, a leave of 3 days
from the 16th of Augustus until the 18th was only displayed over
the 16th and the 17th.

Moreover, when an event was created from a Calendar view with
option all_day=False, the default start and end dates weren't
correctly computed according to the user timezone, which could lead
to the creation of multiple days event whereas the user clicked on
a specific day. For instance, with timezone GMT+2, when clicking on
the 18th of Augustus in the Leave Calendar view (month mode), it
opened a dialog for the creation of a 2-day leave from the 18th to
the 19th.

This rev. fixes those two issues.
This commit is contained in:
Adrien Dieudonne
2017-08-17 17:40:41 +02:00
committed by Aaron Bohy
parent f5b7ad80fc
commit bbf63b0b56
2 changed files with 150 additions and 6 deletions
@@ -45,20 +45,26 @@ return AbstractModel.extend({
if (event.allDay || end.diff(start) % 86400000 === 0) {
event.allDay = true;
if (this.scale === 'month') {
if (this.data.scale === 'month') {
// In month, FullCalendar gives the end day as the
// next day at midnight (instead of 23h59).
end.add(-1, 'days');
if (event.r_start) {
start.hours(event.r_start.hours())
.minutes(event.r_start.minutes())
.seconds(event.r_start.seconds())
.utc();
end.add(-1, 'days')
.hours(event.r_end.hours())
end.hours(event.r_end.hours())
.minutes(event.r_end.minutes())
.seconds(event.r_end.seconds())
.utc();
} else {
} else if (this.mapping.all_day) {
start.utc();
end.utc();
} else {
// default hours in the user's timezone
start.hours(7).add(-this.getSession().getTZOffset(start), 'minutes');
end.hours(19).add(-this.getSession().getTZOffset(end), 'minutes');
}
} else if (this.mapping.all_day) {
start.startOf('day');
@@ -622,6 +628,10 @@ return AbstractModel.extend({
// r.start = date_start.format('YYYY-MM-DD');
// r.end = date_stop.format('YYYY-MM-DD');
} else if (this.data.scale === 'month' && this.fields[this.mapping.date_start].type !== 'date') {
// In month, FullCalendar gives the end day as the
// next day at midnight (instead of 23h59).
date_stop.add(1, 'days');
// allow to resize in month mode
r.reset_allday = r.allDay;
r.allDay = true;
+136 -2
View File
@@ -644,8 +644,8 @@ QUnit.module('Views', {
$view.remove();
});
QUnit.test('create all day event', function (assert) {
assert.expect(2);
QUnit.test('create all day event in week mode', function (assert) {
assert.expect(3);
this.data.event.records = [];
@@ -696,6 +696,8 @@ QUnit.module('Views', {
assert.strictEqual($newevent.text().replace(/[\s\n\r]+/g, ''), "newevent",
"should display the new event with time and title");
assert.strictEqual($newevent.parent().attr('colspan'), "2",
"should appear over two days.");
assert.deepEqual($newevent.data('fcSeg').event.record,
{
@@ -712,6 +714,82 @@ QUnit.module('Views', {
$view.remove();
});
QUnit.test('create event in month mode', function (assert) {
assert.expect(4);
this.data.event.records = [];
var calendar = createView({
View: CalendarView,
model: 'event',
data: this.data,
arch:
'<calendar class="o_calendar_test" '+
'event_open_popup="true" '+
'date_start="start" '+
'date_stop="stop" '+
'mode="month" '+
'readonly_form_view_id="1">'+
'<field name="name"/>'+
'</calendar>',
archs: archs,
viewOptions: {
initialDate: initialDate,
},
session: {
getTZOffset: function () {
return 120;
},
},
mockRPC: function (route, args) {
if (args.method === "create") {
assert.deepEqual(args.args[0], {
"name": "new event",
"start": "2016-12-14 05:00:00",
"stop": "2016-12-15 17:00:00",
},
"should send the correct data to create events");
}
return this._super(route, args);
},
});
var $view = $('#qunit-fixture').contents();
$view.prependTo('body'); // => select with click position
var pos = calendar.$('.fc-bg td:eq(20)').offset();
try {
testUtils.triggerPositionalMouseEvent(pos.left+15, pos.top+15, "mousedown");
} catch (e) {
calendar.destroy();
$view.remove();
throw new Error('The test fails to simulate a click in the screen. Your screen is probably too small or your dev tools is open.');
}
pos = calendar.$('.fc-bg td:eq(21)').offset();
testUtils.triggerPositionalMouseEvent(pos.left+15, pos.top+15, "mousemove");
testUtils.triggerPositionalMouseEvent(pos.left+15, pos.top+15, "mouseup");
$('.modal input:first').val('new event').trigger('input');
$('.modal button.btn:contains(Create)').trigger('click');
var $newevent = calendar.$('.fc-event:contains(new event)');
assert.strictEqual($newevent.text().replace(/[\s\n\r]+/g, ''), "newevent",
"should display the new event with time and title");
assert.strictEqual($newevent.parent().attr('colspan'), "2",
"should appear over two days.");
assert.deepEqual($newevent.data('fcSeg').event.record, {
display_name: "new event",
start: fieldUtils.parse.datetime("2016-12-14 05:00:00", this.data.event.fields.start, {isUTC: true}),
stop: fieldUtils.parse.datetime("2016-12-15 17:00:00", this.data.event.fields.stop, {isUTC: true}),
name: "new event",
id: 1
}, "the new record should have the utc datetime (quickCreate)");
calendar.destroy();
$view.remove();
});
QUnit.test('use mini calendar', function (assert) {
assert.expect(12);
@@ -874,6 +952,62 @@ QUnit.module('Views', {
assert.strictEqual($('#ui-datepicker-div:empty').length, 0, "should have a clean body");
});
QUnit.test('create and edit event in month mode (all_day: false)', function (assert) {
assert.expect(2);
var calendar = createView({
View: CalendarView,
model: 'event',
data: this.data,
arch:
'<calendar class="o_calendar_test" '+
'string="Events" ' +
'date_start="start" '+
'date_stop="stop" '+
'mode="month" '+
'readonly_form_view_id="1">'+
'<field name="name"/>'+
'</calendar>',
archs: archs,
viewOptions: {
initialDate: initialDate,
},
session: {
getTZOffset: function () {
return -240;
},
},
});
// create a new event and edit it
var $cell = calendar.$('.fc-day-grid .fc-row:eq(4) .fc-day:eq(2)');
testUtils.triggerMouseEvent($cell, "mousedown");
testUtils.triggerMouseEvent($cell, "mouseup");
$('.modal-body input:first').val('coucou').trigger('input');
testUtils.intercept(calendar, 'do_action', function (event) {
assert.deepEqual(event.data.action,
{
type: "ir.actions.act_window",
res_model: "event",
views: [[false, "form"]],
target: "current",
context: {
"default_name": "coucou",
"default_start": "2016-12-27 11:00:00", // 7:00 + 4h
"default_stop": "2016-12-27 23:00:00", // 19:00 + 4h
}
},
"should open the form view with the context default values");
});
$('.modal button.btn:contains(Edit)').trigger('click');
calendar.destroy();
assert.strictEqual($('#ui-datepicker-div:empty').length, 0, "should have a clean body");
});
QUnit.test('readonly date_start field', function (assert) {
assert.expect(4);