summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views/abstract_controller.js
diff options
context:
space:
mode:
authoreco-odoo <eco@odoo.com>2018-07-03 10:28:44 +0200
committerYannick Tivisse <yti@odoo.com>2018-07-20 11:59:12 +0200
commitc1498ff36be4ce0b175f340e2f5690a37421ccd7 (patch)
tree498abacd2425b83c54759a4565ddb95702947639 /addons/web/static/src/js/views/abstract_controller.js
parent0dd6a0b2bf0be0698d21e039ad4ead33133d8267 (diff)
[IMP] web: add option to display a banner above a view
Add a banner_route attribute to AbstractView to allow fetching html from a controller route and displaying it above the view. The initial use case was the onboarding panels. Supported views are the ones inheriting both AbstractView and AbstractController.
Diffstat (limited to 'addons/web/static/src/js/views/abstract_controller.js')
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js84
1 files changed, 80 insertions, 4 deletions
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index bf4f3a616f3..f4f323b01ba 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -12,6 +12,7 @@ odoo.define('web.AbstractController', function (require) {
* reading localstorage, ...) has to go through the controller.
*/
+var ajax = require('web.ajax');
var concurrency = require('web.concurrency');
var ControlPanelMixin = require('web.ControlPanelMixin');
var core = require('web.core');
@@ -54,7 +55,7 @@ var AbstractController = AbstractAction.extend(ControlPanelMixin, {
this.activeActions = params.activeActions;
this.controllerID = params.controllerID;
this.initialState = params.initialState;
-
+ this.bannerRoute = params.bannerRoute;
// use a DropPrevious to correctly handle concurrent updates
this.dp = new concurrency.DropPrevious();
// those arguments are temporary, they won't be necessary as soon as the
@@ -280,6 +281,54 @@ var AbstractController = AbstractAction.extend(ControlPanelMixin, {
state: state || {},
});
},
+ /**
+ * Renders the html provided by the route specified by the
+ * bannerRoute attribute on the controller (banner_route in the template).
+ * Renders it before the view output and add a css class 'o_has_banner' to it.
+ * There can be only one banner displayed at a time.
+ *
+ * If the banner contains stylesheet links, they are moved to <head>
+ * (and will only be fetched once).
+ *
+ * Route example:
+ * @http.route('/module/hello', auth='user', type='json')
+ * def hello(self):
+ * return {'html': '<h1>hello, world</h1>'}
+ *
+ * @private
+ * @returns {Deferred}
+ */
+ _renderBanner: function () {
+ if (this.bannerRoute !== undefined) {
+ var self = this;
+ return this.dp
+ .add(this._rpc({route: this.bannerRoute}))
+ .then(function (response) {
+ if (!response.html) {
+ self.$el.removeClass('o_has_banner');
+ return $.when();
+ }
+ self.$el.addClass('o_has_banner');
+ var $banner = $(response.html);
+ // we should only display one banner at a time
+ if (self._$banner && self._$banner.remove) {
+ self._$banner.remove();
+ }
+ // Stylesheets are moved to <head> and we wait for them to be loaded
+ // to prevent displaying unstyled content.
+ var defs = [];
+ $('link[rel="stylesheet"]', $banner).each(function (i, link) {
+ defs.push(ajax.loadCSS(link.href));
+ link.remove();
+ });
+ return $.when.apply($, defs).then(function () {
+ $banner.prependTo(self.$el);
+ self._$banner = $banner;
+ });
+ });
+ }
+ return $.when();
+ },
/**
* Renders the control elements (buttons, pager and sidebar) of the current
* view.
@@ -370,7 +419,7 @@ var AbstractController = AbstractAction.extend(ControlPanelMixin, {
});
this._pushState();
- return $.when();
+ return this._renderBanner();
},
//--------------------------------------------------------------------------
@@ -405,12 +454,39 @@ var AbstractController = AbstractAction.extend(ControlPanelMixin, {
* When a user clicks on an <a> link with type="action", we need to actually
* do the action. This kind of links is used a lot in no-content helpers.
*
+ * The <a> may have
+ * - a data-method and data-model attribute, in that case the corresponding
+ * rpc will be called. If that rpc returns an action it will be executed.
+ * - a data-reload-on-close attribute, in that case the view will be
+ * reloaded after the dialog has been closed.
+ *
* @private
* @param {OdooEvent} event
*/
_onActionClicked: function (event) {
- event.preventDefault();
- this.do_action(event.currentTarget.name);
+ var $target = $(event.currentTarget);
+ var self = this;
+ var model = $target.data('model');
+ var method = $target.data('method');
+
+ if (method !== undefined && model !== undefined) {
+ var options = {};
+ if ($target.data('reload-on-close')) {
+ options.on_close = function () {
+ self.trigger_up('reload');
+ };
+ }
+ this.dp.add(this._rpc({
+ model: model,
+ method: method,
+ })).then(function (action) {
+ if (action !== undefined) {
+ self.do_action(action, options);
+ }
+ });
+ } else {
+ this.do_action($target.attr('name'));
+ }
},
/**
* Intercepts the 'switch_view' event to add the controllerID into the data,