diff --git a/addons/web/static/src/js/views/calendar/calendar_view.js b/addons/web/static/src/js/views/calendar/calendar_view.js index 7f58ca55632..bfeb5c5cbbb 100644 --- a/addons/web/static/src/js/views/calendar/calendar_view.js +++ b/addons/web/static/src/js/views/calendar/calendar_view.js @@ -112,8 +112,20 @@ var CalendarView = AbstractView.extend({ //if quick_add = is NOT False and IS specified in view, we this one for widgets.QuickCreate' 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; + + // If form_view_id is set, then the calendar view will open a form view + // with this id, when it needs to edit or create an event. + this.controllerParams.formViewId = + attrs.form_view_id ? parseInt(attrs.form_view_id, 10) : false; + if (!this.controllerParams.formViewId && params.action) { + var formViewDescr = _.find(params.action.views, function (v) { + return v[1] === 'form'; + }); + if (formViewDescr) { + this.controllerParams.formViewId = formViewDescr[0]; + } + } + 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; diff --git a/addons/web/static/tests/helpers/mock_server.js b/addons/web/static/tests/helpers/mock_server.js index a47cd71fe48..08f3bb95c77 100644 --- a/addons/web/static/tests/helpers/mock_server.js +++ b/addons/web/static/tests/helpers/mock_server.js @@ -110,14 +110,14 @@ var MockServer = Class.extend({ console.log('%c[rpc] response' + route, 'color: blue; font-weight: bold;', JSON.parse(resultString)); } return JSON.parse(resultString); - }).fail(function (result) { + }, function (result, event) { var errorString = JSON.stringify(result || false); if (logLevel === 1) { console.log('Mock: (ERROR)' + route, JSON.parse(errorString)); } else if (logLevel === 2) { console.log('%c[rpc] response (error) ' + route, 'color: orange; font-weight: bold;', JSON.parse(errorString)); } - return JSON.parse(errorString); + return $.Deferred().reject(errorString, event || $.Event()); }); }, diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js index b6bebc0f4a2..4840e05af02 100644 --- a/addons/web/static/tests/views/calendar_tests.js +++ b/addons/web/static/tests/views/calendar_tests.js @@ -1766,6 +1766,101 @@ QUnit.module('Views', { calendar.destroy(); }); + + QUnit.test('form_view_id attribute works (for creating events)', function (assert) { + assert.expect(1); + + var calendar = createView({ + View: CalendarView, + model: 'event', + data: this.data, + arch: ''+ + ''+ + '', + archs: archs, + viewOptions: { + initialDate: initialDate, + }, + mockRPC: function (route, args) { + if (args.method === "create") { + // we simulate here the case where a create call with just + // the field name fails. This is a normal flow, the server + // reject the create rpc (quick create), then the web client + // fall back to a form view. This happens typically when a + // model has required fields + return $.Deferred().reject('None shall pass!'); + } + return this._super(route, args); + }, + intercepts: { + do_action: function (event) { + assert.strictEqual(event.data.action.views[0][0], 42, + "should do a do_action with view id 42"); + }, + }, + }); + + var $cell = calendar.$('.fc-day-grid .fc-row:eq(2) .fc-day:eq(2)'); + testUtils.triggerMouseEvent($cell, "mousedown"); + testUtils.triggerMouseEvent($cell, "mouseup"); + var $input = $('.modal-body input:first'); + $input.val("It's just a fleshwound").trigger('input'); + $('.modal button.btn:contains(Create)').trigger('click'); + + calendar.destroy(); + }); + + QUnit.test('calendar fallback to form view id in action if necessary', function (assert) { + assert.expect(1); + + var calendar = createView({ + View: CalendarView, + model: 'event', + data: this.data, + arch: ' '+ + ''+ + '', + archs: archs, + viewOptions: { + initialDate: initialDate, + action: {views: [[1, 'kanban'], [43, 'form']]} + }, + mockRPC: function (route, args) { + if (args.method === "create") { + // we simulate here the case where a create call with just + // the field name fails. This is a normal flow, the server + // reject the create rpc (quick create), then the web client + // fall back to a form view. This happens typically when a + // model has required fields + return $.Deferred().reject('None shall pass!'); + } + return this._super(route, args); + }, + intercepts: { + do_action: function (event) { + assert.strictEqual(event.data.action.views[0][0], 43, + "should do a do_action with view id 43"); + }, + }, + }); + + var $cell = calendar.$('.fc-day-grid .fc-row:eq(2) .fc-day:eq(2)'); + testUtils.triggerMouseEvent($cell, "mousedown"); + testUtils.triggerMouseEvent($cell, "mouseup"); + var $input = $('.modal-body input:first'); + $input.val("It's just a fleshwound").trigger('input'); + $('.modal button.btn:contains(Create)').trigger('click'); + + calendar.destroy(); + }); + }); }); diff --git a/doc/reference/views.rst b/doc/reference/views.rst index d53ff2b6ce7..d23a0db9da3 100644 --- a/doc/reference/views.rst +++ b/doc/reference/views.rst @@ -954,7 +954,9 @@ calendar view are: ``readonly_form_view_id`` view to open in readonly mode ``form_view_id`` - view to open when the user create or edit an event + view to open when the user create or edit an event. Note that if this attribute + is not set, the calendar view will fall back to the id of the form view in the + current action, if any. ``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