[IMP] web: add 'event_open_popup' option on calendar view

If the option 'event_open_popup' is set to true, then the calendar view will open events (or records) in a FormViewDialog. Otherwise, it will open events in a new form view (with a do_action)
This commit is contained in:
Christophe Matthieu
2017-05-04 17:19:25 +02:00
parent 27ff895dfd
commit 9500f8d3f7
9 changed files with 141 additions and 46 deletions
@@ -2,7 +2,7 @@
<template>
<t t-name="Many2ManyAttendeeTag" t-extend="FieldMany2ManyTag">
<t t-jquery="span:first" t-operation="prepend">
<span t-attf-class="o_calendar_invitation #{attendeesData[el_index].status}"/>
<span t-if="attendeesData[el_index]" t-attf-class="o_calendar_invitation #{attendeesData[el_index].status}"/>
</t>
</t>
+3 -1
View File
@@ -264,7 +264,9 @@
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<calendar string="Meetings" date_start="start" date_stop="stop" date_delay="duration" all_day="allday"
readonly_form_view_id="%(calendar.view_calendar_event_form_popup)s" event_limit="3"
readonly_form_view_id="%(calendar.view_calendar_event_form_popup)s"
event_open_popup="true"
event_limit="3"
color="partner_id">
<field name="name"/>
<field name="partner_ids" write_model="calendar.contacts" write_field="partner_id" avatar_field="image_small"/>
@@ -19,9 +19,6 @@ var _t = core._t;
var QWeb = core.qweb;
var CalendarController = AbstractController.extend({
defaults: _.extend({}, AbstractController.prototype.defaults, {
confirm_on_delete: true,
}),
custom_events: _.extend({}, AbstractController.prototype.custom_events, {
quickCreate: '_onQuickCreate',
openCreate: '_onOpenCreate',
@@ -42,9 +39,9 @@ var CalendarController = AbstractController.extend({
init: function (parent, model, renderer, params) {
this._super.apply(this, arguments);
this.current_start = null;
this.quick_add_pop = params.quick_add_pop;
this.disable_quick_create = params.disable_quick_create;
this.confirm_on_delete = params.confirm_on_delete;
this.quickAddPop = params.quickAddPop;
this.disableQuickCreate = params.disableQuickCreate;
this.eventOpenPopup = params.eventOpenPopup;
this.formViewId = params.formViewId;
this.readonlyFormViewId = params.readonlyFormViewId;
this.mapping = params.mapping;
@@ -156,7 +153,7 @@ var CalendarController = AbstractController.extend({
self.reload(id);
}, function () {
// This will occurs if there are some more fields required
event.data.options.disable_quick_create = true;
event.data.options.disableQuickCreate = true;
event.data.data.on_save = self.quick.destroy.bind(self.quick);
self._onOpenCreate(event.data);
});
@@ -192,11 +189,12 @@ var CalendarController = AbstractController.extend({
var options = _.extend({}, this.options, event.options, {context: context});
if(!options.disable_quick_create && !event.data.disable_quick_create && this.quick_add_pop) {
if (this.quick != null) {
this.quick.destroy();
this.quick = null;
}
if (this.quick != null) {
this.quick.destroy();
this.quick = null;
}
if(!options.disableQuickCreate && !event.data.disableQuickCreate && this.quickAddPop) {
this.quick = new QuickCreate(this, true, options, data, event.data);
this.quick.on('added', this, this.reload.bind(this));
this.quick.open();
@@ -208,18 +206,28 @@ var CalendarController = AbstractController.extend({
if (this.renderer.arch.attrs.string) {
title += ': ' + this.renderer.arch.attrs.string;
}
new dialogs.FormViewDialog(self, {
res_model: this.modelName,
context: context,
title: title,
disable_multiple_selection: true,
on_saved: function () {
if (event.data.on_save) {
event.data.on_save();
}
self.reload();
},
}).open();
if (this.eventOpenPopup) {
new dialogs.FormViewDialog(self, {
res_model: this.modelName,
context: context,
title: title,
disable_multiple_selection: true,
on_saved: function () {
if (event.data.on_save) {
event.data.on_save();
}
self.reload();
},
}).open();
} else {
this.do_action({
type: 'ir.actions.act_window',
res_model: this.modelName,
views: [[this.formViewId || false, 'form']],
target: 'current',
context: context,
});
}
},
/**
* @param {OdooEvent} event
@@ -228,6 +236,19 @@ var CalendarController = AbstractController.extend({
var self = this;
var id = event.data._id;
id = id && parseInt(id).toString() === id ? parseInt(id) : id;
if (!this.eventOpenPopup) {
this.do_action({
type: 'ir.actions.act_window',
res_id: id,
res_model: this.modelName,
views: [[this.formViewId || false, 'form']],
target: 'current',
context: event.context || self.context,
});
return;
}
var open_dialog = function (readonly) {
var options = {
res_model: self.modelName,
@@ -181,13 +181,13 @@ return AbstractModel.extend({
// Check whether the date field is editable (i.e. if the events can be
// dragged and dropped)
this.editable = params.editable;
this.creatable = params.creatable;
this.creatable = this.editable;
// display more button when there are too much event on one day
this.eventLimit = params.eventLimit;
// fields to display color, e.g.: user_id.partner_id
this.field_color = params.field_color;
this.fieldColor = params.fieldColor;
if (!this.preload_def) {
this.preload_def = $.Deferred();
$.when(
@@ -207,7 +207,7 @@ return AbstractModel.extend({
filters: params.filters,
};
// Use scale_zoom attribute in xml file to specify zoom timeline (day,week,month)
// Use mode attribute in xml file to specify zoom timeline (day,week,month)
// by default month.
this.setDate(params.initialDate, true);
this.setScale(params.mode);
@@ -417,8 +417,8 @@ return AbstractModel.extend({
* @returns {Deferred}
*/
_loadColors: function (element, events) {
if (this.field_color) {
var fieldName = this.field_color;
if (this.fieldColor) {
var fieldName = this.fieldColor;
_.each(events, function (event) {
var value = event.record[fieldName];
event.color_index = _.isArray(value) ? value[0] : value;
@@ -45,7 +45,7 @@ var QuickCreate = Dialog.extend({
}
}},
{text: _t("Edit"), click: function () {
dataCalendar.disable_quick_create = true;
dataCalendar.disableQuickCreate = true;
dataCalendar.title = self.$input.val().trim();
dataCalendar.on_save = self.destroy.bind(self);
self.trigger_up('openCreate', dataCalendar);
@@ -62,7 +62,7 @@ var QuickCreate = Dialog.extend({
start: function () {
var self = this;
if (this.options.disable_quick_create) {
if (this.options.disableQuickCreate) {
this.slow_create();
return;
}
@@ -108,12 +108,12 @@ var CalendarView = AbstractView.extend({
//if quick_add = False, we don't allow quick_add
//if quick_add = not specified in view, we use the default widgets.QuickCreate
//if quick_add = is NOT False and IS specified in view, we this one for widgets.QuickCreate'
this.controllerParams.quick_add_pop = (!('quick_add' in attrs) || utils.toBoolElse(attrs.quick_add+'', true));
this.controllerParams.disable_quick_create = params.disable_quick_create || !this.controllerParams.quick_add_pop;
this.controllerParams.confirm_on_delete = true;
this.controllerParams.quickAddPop = (!('quick_add' in attrs) || utils.toBoolElse(attrs.quick_add+'', true));
this.controllerParams.disableQuickCreate = params.disable_quick_create || !this.controllerParams.quickAddPop;
// If this field is set ot true, we don't open the event in form view, but in a popup with the view_id passed by this parameter
this.controllerParams.formViewId = !attrs.form_view_id || !utils.toBoolElse(attrs.form_view_id, true) ? false : attrs.form_view_id;
this.controllerParams.readonlyFormViewId = !attrs.readonly_form_view_id || !utils.toBoolElse(attrs.readonly_form_view_id, true) ? false : attrs.readonly_form_view_id;
this.controllerParams.eventOpenPopup = utils.toBoolElse(attrs.event_open_popup || '', false);
this.controllerParams.mapping = mapping;
this.controllerParams.context = params.context || {};
@@ -124,14 +124,12 @@ var CalendarView = AbstractView.extend({
this.loadParams.mapping = mapping;
this.loadParams.fields = fields;
this.loadParams.fieldsInfo = viewInfo.fieldsInfo;
this.loadParams.editable = !this.controllerParams.read_only_mode && !fields[mapping.date_start].readonly;
this.loadParams.creatable = !this.controllerParams.read_only_mode;
this.loadParams.editable = !fields[mapping.date_start].readonly;
this.loadParams.eventLimit = eventLimit;
this.loadParams.field_color = attrs.color;
this.loadParams.fieldColor = attrs.color;
this.loadParams.filters = filters;
this.loadParams.mode = attrs.mode;
this.loadParams.scale_zoom = attrs.scale_zoom;
this.loadParams.initialDate = moment(params.initialDate || new Date());
},
});
@@ -151,7 +151,7 @@ QUnit.module('Views', {
data: this.data,
arch:
'<calendar class="o_calendar_test" '+
'scale_zoom="week" '+
'event_open_popup="true" '+
'date_start="start" '+
'date_stop="stop" '+
'all_day="allday" '+
@@ -225,7 +225,7 @@ QUnit.module('Views', {
arch:
'<calendar class="o_calendar_test" '+
'string="Events" ' +
'scale_zoom="week" '+
'event_open_popup="true" '+
'date_start="start" '+
'date_stop="stop" '+
'all_day="allday" '+
@@ -360,7 +360,7 @@ QUnit.module('Views', {
data: this.data,
arch:
'<calendar class="o_calendar_test" '+
'scale_zoom="week" '+
'event_open_popup="true" '+
'date_start="start" '+
'date_stop="stop" '+
'all_day="allday" '+
@@ -454,7 +454,7 @@ QUnit.module('Views', {
data: this.data,
arch:
'<calendar class="o_calendar_test" '+
'scale_zoom="week" '+
'event_open_popup="true" '+
'date_start="start" '+
'date_stop="stop" '+
'all_day="allday" '+
@@ -571,7 +571,7 @@ QUnit.module('Views', {
data: this.data,
arch:
'<calendar class="o_calendar_test" '+
'scale_zoom="week" '+
'event_open_popup="true" '+
'date_start="start" '+
'date_stop="stop" '+
'all_day="allday" '+
@@ -629,7 +629,7 @@ QUnit.module('Views', {
data: this.data,
arch:
'<calendar class="o_calendar_test" '+
'scale_zoom="week" '+
'event_open_popup="true" '+
'date_start="start" '+
'date_stop="stop" '+
'all_day="allday" '+
@@ -664,6 +664,7 @@ QUnit.module('Views', {
data: this.data,
arch:
'<calendar class="o_calendar_test" '+
'event_open_popup="true" '+
'date_start="start" '+
'date_stop="stop" '+
'all_day="allday"> '+
@@ -680,6 +681,74 @@ QUnit.module('Views', {
calendar.destroy();
});
QUnit.test('open form view', 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" '+
'all_day="allday" '+
'mode="month" '+
'readonly_form_view_id="1">'+
'<field name="name"/>'+
'</calendar>',
archs: archs,
viewOptions: {
initialDate: initialDate,
},
});
// click on an existing event to open the form view
testUtils.intercept(calendar, 'do_action', function (event) {
assert.deepEqual(event.data.action,
{
type: "ir.actions.act_window",
res_id: 4,
res_model: "event",
views: [[false, "form"]],
target: "current",
context: {}
},
"should open the form view");
});
calendar.$('.fc-event:contains(event 4) .fc-content').trigger('click');
// 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 00:00:00",
"default_stop": "2016-12-27 00:00:00",
"default_allday": true
}
},
"should open the form view with the context default values");
});
$('.modal button.btn:contains(Edit)').trigger('click');
calendar.destroy();
});
});
});
+4
View File
@@ -963,6 +963,10 @@ calendar view are:
view to open in readonly mode
``form_view_id``
view to open when the user create or edit an event
``event_open_popup``
If the option 'event_open_popup' is set to true, then the calendar view will
open events (or records) in a FormViewDialog. Otherwise, it will open events
in a new form view (with a do_action)
``quick_add``
enables quick-event creation on click: only asks the user for a ``name``
and tries to create a new event with just that and the clicked event
+1
View File
@@ -638,6 +638,7 @@
<rng:optional><rng:attribute name="event_limit" /></rng:optional>
<rng:optional><rng:attribute name="quick_add" /></rng:optional>
<rng:optional><rng:attribute name="color" /></rng:optional>
<rng:optional><rng:attribute name="event_open_popup" /></rng:optional>
<rng:optional>
<rng:attribute name="mode">
<rng:choice>