From 4f084a2fe12debbf41d3a560bbee7e7202d7117f Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Mon, 5 Mar 2018 11:55:12 +0100 Subject: [PATCH] [FIX] web: ActionManager: F5 on form view in mobile This rev. fixes two issues with the loading (e.g. after an F5) of form views in mobile. First, the form view being not a mobile-friendly view, it opened the kanban view instead (if there were one defined in the action), whether it should have kept the form view as they don't diplay the same things (one is multiRecord, the other isn't). Second, after fixing the first issue, the main (multiRecord) view which was lazyloaded when loading a form view wasn't mobile-friendly so if the user clicked on the breadcrumbs to go back, he landed on a list view (if the list view was the first view of the action), whether he should be on a kanban view, which is mobile-friendly. --- .../js/chrome/action_manager_act_window.js | 38 +++++++++++++--- .../chrome/action_manager_mobile_tests.js | 43 +++++++++++++++++++ 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/addons/web/static/src/js/chrome/action_manager_act_window.js b/addons/web/static/src/js/chrome/action_manager_act_window.js index 6cc05ebc5d2..dfb512900e8 100644 --- a/addons/web/static/src/js/chrome/action_manager_act_window.js +++ b/addons/web/static/src/js/chrome/action_manager_act_window.js @@ -255,18 +255,26 @@ ActionManager.include({ action.env = self._generateActionEnv(action, options); action.controllers = {}; - // select the first view to display - var lazyLoadFirstView = false; + // select the first view to display, and optionally the main view + // which will be lazyloaded var firstView = options.viewType && _.findWhere(views, {type: options.viewType}); + var mainView; if (firstView) { if (!firstView.multiRecord && views[0].multiRecord) { - lazyLoadFirstView = true; + mainView = views[0]; } } else { firstView = views[0]; } - if (config.device.isMobile && !firstView.isMobileFriendly) { - firstView = _.findWhere(action.views, {isMobileFriendly: true}) || firstView; + + // use mobile-friendly view by default in mobile, if possible + if (config.device.isMobile) { + if (!firstView.isMobileFriendly) { + firstView = self._findMobileView(views, firstView.multiRecord) || firstView; + } + if (mainView && !mainView.isMobileFriendly) { + mainView = self._findMobileView(views, mainView.multiRecord) || mainView; + } } var def; @@ -280,8 +288,8 @@ ActionManager.include({ return $.when(def).then(function () { var defs = []; defs.push(self._createViewController(action, firstView.type)); - if (lazyLoadFirstView) { - defs.push(self._createViewController(action, views[0].type, {}, {lazy: true})); + if (mainView) { + defs.push(self._createViewController(action, mainView.type, {}, {lazy: true})); } return $.when.apply($, defs); }).then(function (controller, lazyLoadedController) { @@ -297,6 +305,22 @@ ActionManager.include({ }); }); }, + /** + * Helper function to find the first mobile-friendly view, if any. + * + * @private + * @param {Array} views an array of views + * @param {boolean} multiRecord set to true iff we search for a multiRecord + * view + * @returns {Object|undefined} a mobile-friendly view of the requested + * multiRecord type, undefined if there is no such view + */ + _findMobileView: function (views, multiRecord) { + return _.findWhere(views, { + isMobileFriendly: true, + multiRecord: multiRecord, + }); + }, /** * Generates the initial environment of a given action, which is a dict * containing information like the model name, the domain, the context... diff --git a/addons/web/static/tests/chrome/action_manager_mobile_tests.js b/addons/web/static/tests/chrome/action_manager_mobile_tests.js index c23d7be19f8..491830578e6 100644 --- a/addons/web/static/tests/chrome/action_manager_mobile_tests.js +++ b/addons/web/static/tests/chrome/action_manager_mobile_tests.js @@ -80,6 +80,49 @@ QUnit.module('ActionManager', { actionManager.destroy(); }); + + QUnit.test('lazy load mobile-friendly view', function (assert) { + assert.expect(11); + + var actionManager = createActionManager({ + actions: this.actions, + archs: this.archs, + data: this.data, + mockRPC: function (route, args) { + assert.step(args.method || route); + return this._super.apply(this, arguments); + }, + }); + actionManager.loadState({ + action: 1, + view_type: 'form', + }); + + assert.strictEqual(actionManager.$('.o_list_view').length, 0, + "should not have rendered a list view"); + assert.strictEqual(actionManager.$('.o_kanban_view').length, 0, + "should not have rendered a kanban view either"); + assert.strictEqual(actionManager.$('.o_form_view').length, 1, + "should have rendered a form view"); + + // go back to lazy loaded view + $('.o_control_panel .breadcrumb a').click(); + assert.strictEqual(actionManager.$('.o_form_view').length, 0, + "should not display the form view anymore"); + assert.strictEqual(actionManager.$('.o_list_view').length, 0, + "should not display the list view either"); + assert.strictEqual(actionManager.$('.o_kanban_view').length, 1, + "should have lazy loaded the kanban view"); + + assert.verifySteps([ + '/web/action/load', + 'load_views', + 'default_get', // default_get to open form view + '/web/dataset/search_read', // search read when coming back to Kanban + ]); + + actionManager.destroy(); + }); }); });