diff options
| author | Aaron Bohy <aab@odoo.com> | 2016-04-08 14:53:34 +0200 |
|---|---|---|
| committer | Géry Debongnie <ged@odoo.com> | 2016-04-21 15:21:39 +0200 |
| commit | 977db823c7c84e9edc7c8cf8384eb9cf47275b3a (patch) | |
| tree | c3312f745baf11d51f976a60d6e285480f557d4c /addons/web/static/src/js/action_manager.js | |
| parent | e1bfd3fbda97ac7a64a585b07be161d5be606cf9 (diff) | |
[REF] web: stop duplicating web
Avoid duplicating web addon in enterprise by extracting a common basis.
Enterprise features stay in enterprise, but use that common basis.
Mainly:
- JS refactoring and linting
- Conversion of .sass into .less split into multiple files
- Templates cleaning and DOM simplification
- Re-generation of web.pot, and update of .po files
Diffstat (limited to 'addons/web/static/src/js/action_manager.js')
| -rw-r--r-- | addons/web/static/src/js/action_manager.js | 212 |
1 files changed, 112 insertions, 100 deletions
diff --git a/addons/web/static/src/js/action_manager.js b/addons/web/static/src/js/action_manager.js index 359b174a28d..be5e6c6c996 100644 --- a/addons/web/static/src/js/action_manager.js +++ b/addons/web/static/src/js/action_manager.js @@ -23,24 +23,17 @@ var Action = core.Class.extend({ this.title = action.display_name || action.name; }, /** - * Not implemented for client actions - * @return {Deferred} a rejected Deferred - */ - appendTo: function() { - return $.Deferred().reject(); - }, - /** * This method should restore this previously loaded action - * Calls on_reverse_breadcrumb callback if defined + * Calls on_reverse_breadcrumb_callback if defined * @return {Deferred} resolved when widget is enabled */ restore: function() { - if (this.on_reverse_breadcrumb) { - return this.on_reverse_breadcrumb(); + if (this.on_reverse_breadcrumb_callback) { + return this.on_reverse_breadcrumb_callback(); } }, /** - * Not implemented for functions + * There is nothing to detach in the case of a client function */ detach: function() { }, @@ -50,11 +43,16 @@ var Action = core.Class.extend({ destroy: function() { }, /** - * Sets the on_reverse_breadcrumb callback to be called when coming back to that action - * @param {Function} [on_reverse_breadcrumb] the callback + * Sets the on_reverse_breadcrumb_callback to be called when coming back to that action + * @param {Function} [callback] the callback + */ + set_on_reverse_breadcrumb: function(callback) { + this.on_reverse_breadcrumb_callback = callback; + }, + /** + * Not implemented for client actions */ - set_on_reverse_breadcrumb: function(on_reverse_breadcrumb) { - this.on_reverse_breadcrumb = on_reverse_breadcrumb; + set_scrollTop: function() { }, /** * Stores the DOM fragment of the action @@ -65,8 +63,10 @@ var Action = core.Class.extend({ }, /** * Not implemented for client actions + * @return {int} the number of pixels the webclient is scrolled when leaving the action */ - set_is_in_DOM: function() { + get_scrollTop: function() { + return 0; }, /** * @return {Object} the description of the action @@ -113,16 +113,6 @@ var WidgetAction = Action.extend({ }); }, /** - * Wraps the action's widget in a container and appends it to el - * @param {DocumentFragment} [el] where to append the widget - * @return {Deferred} resolved when the widget is appended - */ - appendTo: function(el) { - this.$client_action_container = $('<div>').addClass('oe_client_action'); - this.$client_action_container.appendTo(el); - return this.widget.appendTo(this.$client_action_container); - }, - /** * Restores WidgetAction by calling do_show on its widget */ restore: function() { @@ -132,18 +122,20 @@ var WidgetAction = Action.extend({ }); }, /** - * Detaches the client action's container from the DOM - * @return {jQuery} the action's container + * Detaches the action's widget from the DOM + * @return the widget's $el */ detach: function() { - return this.$client_action_container.detach(); + // Hack to remove badly inserted nvd3 tooltips ; should be removed when upgrading nvd3 lib + $('body > .nvtooltip').remove(); + + return framework.detach([{widget: this.widget}]); }, /** * Destroys the widget */ destroy: function() { this.widget.destroy(); - this.detach(); }, }); /** @@ -151,14 +143,6 @@ var WidgetAction = Action.extend({ */ var ViewManagerAction = WidgetAction.extend({ /** - * Appends the action's widget to el - * @param {DocumentFragment} [el] where to append the widget - * @return {Deferred} resolved when the widget is appended - */ - appendTo: function(el) { - return this.widget.appendTo(el); - }, - /** * Restores a ViewManagerAction * Switches to the requested view by calling select_view on the ViewManager * @param {int} [view_index] the index of the view to select @@ -170,27 +154,27 @@ var ViewManagerAction = WidgetAction.extend({ }); }, /** - * Sets is_in_DOM on this.widget - * @param {Boolean} [is_in_DOM] true iff the widget is attached in the DOM + * Sets the on_reverse_breadcrumb_callback and the scrollTop to apply when + * coming back to that action + * @param {Function} [callback] the callback + * @param {int} [scrollTop] the number of pixels to scroll */ - set_is_in_DOM: function(is_in_DOM) { - this.widget.is_in_DOM = is_in_DOM; + set_on_reverse_breadcrumb: function(callback, scrollTop) { + this._super(callback); + this.set_scrollTop(scrollTop); }, /** - * Detaches the view_manager from the DOM - * @return {jQuery} the view_manager's $el + * Sets the scroll position of the widgets's active_view + * @param {int} [scrollTop] the number of pixels to scroll */ - detach: function() { - // Hack to remove badly inserted nvd3 tooltips ; should be removed when upgrading nvd3 lib - $('body > .nvtooltip').remove(); - - return this.widget.$el.detach(); + set_scrollTop: function(scrollTop) { + this.widget.active_view.controller.set_scrollTop(scrollTop); }, /** - * Destroys the widget + * @return {int} the number of pixels the webclient is scrolled when leaving the action */ - destroy: function() { - this.widget.destroy(); + get_scrollTop: function() { + return this.widget.active_view.controller.get_scrollTop(); }, /** * @return {Array} array of Objects that will be interpreted to display the breadcrumbs @@ -214,13 +198,31 @@ var ViewManagerAction = WidgetAction.extend({ }); var ActionManager = Widget.extend({ - template: "ActionManager", - init: function(parent) { + template: 'ActionManager', + /** + * Called each time the action manager is attached into the DOM + */ + on_attach_callback: function() { + this.is_in_DOM = true; + if (this.inner_widget && this.inner_widget.on_attach_callback) { + this.inner_widget.on_attach_callback(); + } + }, + /** + * Called each time the action manager is detached from the DOM + */ + on_detach_callback: function() { + this.is_in_DOM = false; + if (this.inner_widget && this.inner_widget.on_detach_callback) { + this.inner_widget.on_detach_callback(); + } + }, + init: function(parent, options) { this._super(parent); this.action_stack = []; this.inner_action = null; this.inner_widget = null; - this.webclient = parent; + this.webclient = options && options.webclient; this.dialog = null; this.dialog_widget = null; this.on('history_back', this, this.proxy('history_back')); @@ -236,8 +238,15 @@ var ActionManager = Widget.extend({ this.select_action(action, index); }, 200, true)); - // Append the main control panel to the DOM (inside the ActionManager jQuery element) - this.main_control_panel.appendTo(this.$el); + // Listen to event "DOM_updated" to restore the scroll position + core.bus.on('DOM_updated', this, function() { + if (this.inner_action) { + this.trigger_up('scrollTo', {offset: this.inner_action.get_scrollTop() || 0}); + } + }); + + // Insert the main control panel into the DOM + return this.main_control_panel.insertBefore(this.$el); }, dialog_stop: function (reason) { if (this.dialog) { @@ -256,9 +265,9 @@ var ActionManager = Widget.extend({ */ push_action: function(widget, action_descr, options) { var self = this; - var old_widget = this.inner_widget; - var old_action = this.inner_action; var old_action_stack = this.action_stack; + var old_action = this.inner_action; + var old_widget = this.inner_widget; options = options || {}; // Empty action_stack if requested @@ -277,8 +286,8 @@ var ActionManager = Widget.extend({ } // Set on_reverse_breadcrumb callback on previous inner_action - if (old_action) { - old_action.set_on_reverse_breadcrumb(options.on_reverse_breadcrumb); + if (this.webclient && old_action) { + old_action.set_on_reverse_breadcrumb(options.on_reverse_breadcrumb, this.webclient.get_scrollTop()); } // Update action_stack (must be done before appendTo to properly @@ -295,25 +304,19 @@ var ActionManager = Widget.extend({ // render the inner_widget in a fragment, and append it to the // document only when it's ready var new_widget_fragment = document.createDocumentFragment(); - return $.when(this.inner_action.appendTo(new_widget_fragment)).done(function() { + return $.when(this.inner_widget.appendTo(new_widget_fragment)).done(function() { // Detach the fragment of the previous action and store it within the action if (old_action) { old_action.set_fragment(old_action.detach()); - old_action.set_is_in_DOM(false); } if (!widget.need_control_panel) { // Hide the main ControlPanel for widgets that do not use it self.main_control_panel.do_hide(); } - - framework.append(self.$el, new_widget_fragment, true); - self.inner_action.set_is_in_DOM(true); - - // Hide the old_widget as it will be removed from the DOM when it - // is destroyed - if (old_widget) { - old_widget.do_hide(); - } + framework.append(self.$el, new_widget_fragment, { + in_DOM: self.is_in_DOM, + callbacks: [{widget: self.inner_widget}], + }); if (options.clear_breadcrumbs) { self.clear_action_stack(old_action_stack); } @@ -325,6 +328,11 @@ var ActionManager = Widget.extend({ self.inner_widget = old_widget; }); }, + set_scrollTop: function(scrollTop) { + if (this.inner_action) { + this.inner_action.set_scrollTop(scrollTop); + } + }, get_breadcrumbs: function () { return _.flatten(_.map(this.action_stack, function (action) { return action.get_breadcrumbs(); @@ -368,7 +376,9 @@ var ActionManager = Widget.extend({ }, select_action: function(action, index) { var self = this; - return this.webclient.clear_uncommitted_changes().then(function() { + var def = this.webclient && this.webclient.clear_uncommitted_changes() || $.when(); + + return def.then(function() { // Set the new inner_action/widget and update the action stack var old_action = self.inner_action; var action_index = self.action_stack.indexOf(action); @@ -376,19 +386,21 @@ var ActionManager = Widget.extend({ self.inner_action = action; self.inner_widget = action.widget; - // Hide the ControlPanel if the widget doesn't use it - if (!self.inner_widget.need_control_panel) { - self.main_control_panel.do_hide(); - } - return $.when(action.restore(index)).done(function() { + // Hide the ControlPanel if the widget doesn't use it + if (!self.inner_widget.need_control_panel) { + self.main_control_panel.do_hide(); + } + // Attach the DOM of the action and restore the scroll position only if necessary if (action !== old_action) { // Clear the action stack (this also removes the current action from the DOM) self.clear_action_stack(to_destroy); // Append the fragment of the action to restore to self.$el - framework.append(self.$el, action.get_fragment(), true); - self.inner_action.set_is_in_DOM(true); + framework.append(self.$el, action.get_fragment(), { + in_DOM: self.is_in_DOM, + callbacks: [{widget: action.widget}], + }); } }); }).fail(function() { @@ -406,7 +418,7 @@ var ActionManager = Widget.extend({ } }, do_push_state: function(state) { - if (!this.webclient || !this.webclient.do_push_state || this.dialog) { + if (!this.webclient || this.dialog) { return; } state = state || {}; @@ -491,13 +503,6 @@ var ActionManager = Widget.extend({ res_id: state.id, view_type: state.view_type, }); - $.when(action_loaded || null).done(function() { - self.webclient.menu.is_bound.done(function() { - if (self.inner_action && self.inner_action.get_action_descr().id) { - self.webclient.menu.open_action(self.inner_action.get_action_descr().id); - } - }); - }); } } } else if (state.model && state.id) { @@ -524,9 +529,9 @@ var ActionManager = Widget.extend({ }); } - $.when(action_loaded || null).done(function() { + return $.when(action_loaded || null).done(function() { if (self.inner_widget && self.inner_widget.do_load_state) { - self.inner_widget.do_load_state(state, warm); + return self.inner_widget.do_load_state(state, warm); } }); }, @@ -628,7 +633,9 @@ var ActionManager = Widget.extend({ }); } - return this[type](action, options); + return $.when(this[type](action, options)).then(function() { + return action; + }); }, null_action: function() { this.dialog_stop(); @@ -645,6 +652,7 @@ var ActionManager = Widget.extend({ * @return {*} */ ir_actions_common: function(executor, options) { + var self = this; if (executor.action.target === 'new') { var pre_dialog = (this.dialog && !this.dialog.isDestroyed()) ? this.dialog : null; if (pre_dialog){ @@ -693,13 +701,16 @@ var ActionManager = Widget.extend({ this.dialog_widget.set_cp_bus(new core.Bus()); } this.dialog_widget.setParent(this.dialog); - this.dialog.open(); - - return this.dialog_widget.appendTo(this.dialog.$el); + + var fragment = document.createDocumentFragment(); + return this.dialog_widget.appendTo(fragment).then(function() { + self.dialog.open().$el.append(fragment); + if(options.state && self.dialog_widget.do_load_state) { + return self.dialog_widget.do_load_state(options.state); + } + }).then(function () { return executor.action; }); } - // Clear uncommitted changes on the current inner widget if there is one - var self = this; - var def = (this.inner_widget && this.webclient.clear_uncommitted_changes()) || $.when(); + var def = this.inner_action && this.webclient && this.webclient.clear_uncommitted_changes() || $.when(); return def.then(function() { self.dialog_stop(executor.action); return self.push_action(executor.widget(), executor.action, options); @@ -764,11 +775,11 @@ var ActionManager = Widget.extend({ }, ir_actions_server: function (action, options) { var self = this; - this.rpc('/web/action/run', { + return this.rpc('/web/action/run', { action_id: action.id, context: action.context || {} - }).done(function (action) { - self.do_action(action, options); + }).then(function (action) { + return self.do_action(action, options); }); }, ir_actions_report_xml: function(action, options) { @@ -818,6 +829,7 @@ var ActionManager = Widget.extend({ if (action.target === 'self') { framework.redirect(url); + return $.Deferred(); // The action is finished only when the redirection is done } else { window.open(url, '_blank'); } |
