summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/chrome/abstract_web_client.js33
-rw-r--r--addons/web/static/src/js/chrome/action_manager.js5
-rw-r--r--addons/web/static/src/js/chrome/view_manager.js18
-rw-r--r--addons/web/static/src/js/views/form/form_controller.js8
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js5
-rw-r--r--addons/web/static/src/js/widgets/rainbow_man.js77
6 files changed, 121 insertions, 25 deletions
diff --git a/addons/web/static/src/js/chrome/abstract_web_client.js b/addons/web/static/src/js/chrome/abstract_web_client.js
index 481e9a7fc54..2a5bb5310ce 100644
--- a/addons/web/static/src/js/chrome/abstract_web_client.js
+++ b/addons/web/static/src/js/chrome/abstract_web_client.js
@@ -21,6 +21,7 @@ var Dialog = require('web.Dialog');
var Loading = require('web.Loading');
var mixins = require('web.mixins');
var NotificationManager = require('web.notification').NotificationManager;
+var RainbowMan = require('web.rainbow_man');
var session = require('web.session');
var Widget = require('web.Widget');
@@ -43,13 +44,13 @@ var AbstractWebClient = Widget.extend(mixins.ServiceProvider, {
// downstream widgets. Mainly side effects, such as rpcs, notifications
// or cache.
- // notifications and warnings
+ // notifications, warnings and effects
notification: function (e) {
if(this.notification_manager) {
this.notification_manager.notify(e.data.title, e.data.message, e.data.sticky);
}
},
- warning: '_displayWarning',
+ warning: '_onDisplayWarning',
load_views: function (event) {
var params = {
model: event.data.modelName,
@@ -65,6 +66,7 @@ var AbstractWebClient = Widget.extend(mixins.ServiceProvider, {
.load_filters(event.data.dataset, event.data.action_id)
.then(event.data.on_success);
},
+ show_effect: '_onShowEffect',
// session
get_session: function (event) {
if (event.data.callback) {
@@ -82,7 +84,6 @@ var AbstractWebClient = Widget.extend(mixins.ServiceProvider, {
}
});
},
- show_wow: '_onShowWow',
},
init: function (parent) {
this.client_options = {};
@@ -300,7 +301,8 @@ var AbstractWebClient = Widget.extend(mixins.ServiceProvider, {
/**
* Displays a warning in a dialog of with the NotificationManager
-
+ *
+ * @private
* @param {OdooEvent} e
* @param {string} e.data.message the warning's message
* @param {string} e.data.title the warning's title
@@ -308,7 +310,7 @@ var AbstractWebClient = Widget.extend(mixins.ServiceProvider, {
* @param {boolean} [e.data.sticky] whether or not the warning should be
* sticky (if displayed with the NotificationManager)
*/
- _displayWarning: function (e) {
+ _onDisplayWarning: function (e) {
var data = e.data;
if (data.type === 'dialog') {
new Dialog(this, {
@@ -321,20 +323,21 @@ var AbstractWebClient = Widget.extend(mixins.ServiceProvider, {
}
},
/**
- * Displays a thumb up, heart or peace image (randomly) for a moment (e.g.
- * used when an opportunity is won)
+ * Displays a visual effect (for example, a rainbowman0
*
* @private
+ * @param {OdooEvent} e
+ * @param {Object} [e.data] - key-value options to decide rainbowman
+ * behavior / appearance
*/
- _onShowWow: function () {
- var className = 'o_wow_thumbs';
- if (Math.random() > 0.9) {
- var otherClasses = ['o_wow_peace', 'o_wow_heart'];
- className = otherClasses[Math.floor(Math.random()*otherClasses.length)];
+ _onShowEffect: function (e) {
+ var data = e.data || {};
+ var type = data.type || 'rainbow_man';
+ if (type === 'rainbow_man') {
+ new RainbowMan(data).appendTo(this.$el);
+ } else {
+ throw new Error('Unknown effect type: ' + type);
}
- var $body = $('body');
- $body.addClass(className);
- setTimeout($body.removeClass.bind($body, className), 1000);
},
});
diff --git a/addons/web/static/src/js/chrome/action_manager.js b/addons/web/static/src/js/chrome/action_manager.js
index c81479ec1e0..280a90cec8d 100644
--- a/addons/web/static/src/js/chrome/action_manager.js
+++ b/addons/web/static/src/js/chrome/action_manager.js
@@ -862,6 +862,11 @@ var ActionManager = Widget.extend({
options.on_close();
}
this.dialog_stop();
+ // Display rainbowman on appropriate actions
+ if (action.effect) {
+ this.trigger_up('show_effect', action.effect);
+ }
+
return $.when();
},
ir_actions_server: function (action, options) {
diff --git a/addons/web/static/src/js/chrome/view_manager.js b/addons/web/static/src/js/chrome/view_manager.js
index 11be6fa4e6e..14ed4bdebc7 100644
--- a/addons/web/static/src/js/chrome/view_manager.js
+++ b/addons/web/static/src/js/chrome/view_manager.js
@@ -550,6 +550,9 @@ var ViewManager = Widget.extend(ControlPanelMixin, {
* @param {String} [action_data.special=null] special action handlers, closes the dialog if set
* @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'``
* @param {Object} [action_data.context=null] additional action context, to add to the current context
+ * @param {string} [action_data.effect] if given, a visual effect (a
+ * rainbowman by default) will be displayed when the action is complete,
+ * with the string (evaluated) given as options.
* @param {DataSet} dataset a dataset object used to communicate with the server
* @param {integer[]} [res_ids] the res_ids of the objects on which the action is to be applied (fallback on env.ids if not set)
* @param {Function} on_closed callback to execute when dialog is closed or when the action does not generate any result (no new action)
@@ -562,6 +565,14 @@ var ViewManager = Widget.extend(ControlPanelMixin, {
// response handler
var handler = function (action) {
+ // show effect if button have effect attribute
+ // Rainbowman can be displayed from two places : from attribute on a button, or from python.
+ // Code below handles the first case i.e 'effect' attribute on button.
+ var effect = false;
+ if (action_data.effect) {
+ effect = pyeval.py_eval(action_data.effect);
+ };
+
if (action && action.constructor === Object) {
// filter out context keys that are specific to the current action.
// Wrong default_* and search_default_* values will no give the expected result
@@ -580,11 +591,16 @@ var ViewManager = Widget.extend(ControlPanelMixin, {
}
ncontext.add(action.context || {});
action.context = ncontext;
+ // In case effect data is returned from python and also there is rainbow
+ // attribute on button, priority is given to button attribute
+ action.effect = effect || action.effect;
return self.do_action(action, {
on_close: result_handler,
});
} else {
- self.do_action({"type":"ir.actions.act_window_close"});
+ // If action doesn't return anything, but have effect
+ // attribute on button, display rainbowman
+ self.do_action({"type":"ir.actions.act_window_close", 'effect': effect});
return result_handler();
}
};
diff --git a/addons/web/static/src/js/views/form/form_controller.js b/addons/web/static/src/js/views/form/form_controller.js
index f741e98bf4d..c95278aa255 100644
--- a/addons/web/static/src/js/views/form/form_controller.js
+++ b/addons/web/static/src/js/views/form/form_controller.js
@@ -244,7 +244,7 @@ var FormController = BasicController.extend({
* @override
* @private
*/
- _disableButtons: function () {
+ _disableButtons: function () {
this._super.apply(this, arguments);
this.renderer.disableButtons();
},
@@ -254,7 +254,7 @@ var FormController = BasicController.extend({
* @override
* @private
*/
- _enableButtons: function () {
+ _enableButtons: function () {
this._super.apply(this, arguments);
this.renderer.enableButtons();
},
@@ -380,10 +380,6 @@ var FormController = BasicController.extend({
});
}
- if (event.data.showWow) {
- def.then(this.trigger_up.bind(this, 'show_wow'));
- }
-
def.always(this._enableButtons.bind(this));
},
/**
diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js
index 25b72e4fb5a..f7c4861dd2a 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -117,14 +117,14 @@ var FormRenderer = BasicRenderer.extend({
* Disable stat buttons so that they can't be clicked anymore
*
*/
- disableButtons: function() {
+ disableButtons: function() {
this.$('.oe_button_box button').attr('disabled', true);
},
/**
* Enable stat buttons so they can be clicked again
*
*/
- enableButtons: function() {
+ enableButtons: function() {
this.$('.oe_button_box button').removeAttr('disabled');
},
/**
@@ -206,7 +206,6 @@ var FormRenderer = BasicRenderer.extend({
self.trigger_up('button_clicked', {
attrs: node.attrs,
record: self.state,
- showWow: $el.hasClass('o_wow'),
});
});
},
diff --git a/addons/web/static/src/js/widgets/rainbow_man.js b/addons/web/static/src/js/widgets/rainbow_man.js
new file mode 100644
index 00000000000..53624b6322d
--- /dev/null
+++ b/addons/web/static/src/js/widgets/rainbow_man.js
@@ -0,0 +1,77 @@
+odoo.define('web.rainbow_man', function (require) {
+"use strict";
+
+var ajax = require("web.ajax");
+var Widget = require('web.Widget');
+var core = require('web.core');
+var qweb = core.qweb;
+var _t = core._t;
+
+var RainbowMan = Widget.extend({
+ template: 'rainbow_man.notification',
+ /**
+ * @override
+ * @constructor
+ * @param {Object} [options] - key-value options to decide rainbowman behavior / appearance
+ * @param {string} [options.message] - Message to be displayed on rainbowman card
+ * @param {string} [options.fadeout]
+ * Delay for rainbowman to disappear - [options.fadeout='fast'] will make rainbowman
+ * dissapear quickly, [options.fadeout='medium'] and [options.fadeout='slow'] will
+ * wait little longer before disappearing (can be used when [options.message]
+ * is longer), [options.fadeout='no'] will keep rainbowman on screen until
+ * user clicks anywhere outside rainbowman
+ * @param {string} [options.img_url] - URL of the image to be displayed
+ * @param {Boolean} [options.click_close] - If true, destroys rainbowman on click outside
+ */
+ init: function (options) {
+ this._super.apply(this, arguments);
+ var rainbowDelay = {slow: 4500, medium: 3500, fast:2000, no: false };
+ this.options = _.defaults(options || {}, {
+ fadeout: 'medium',
+ img_url: '/web/static/src/img/smile.svg',
+ message: _t('Well Done!'),
+ click_close: true,
+ });
+ this.delay = rainbowDelay[this.options.fadeout];
+ core.bus.on('clear_uncommitted_changes', this, this.destroy);
+ },
+ /**
+ * @override
+ */
+ willStart: function () {
+ var def;
+ if (!qweb.has_template(this.template)) {
+ // we need to manually load the templates when the rainbon_man is used in
+ // the frontend, for example, it may be displayed at the end of a tour.
+ def = ajax.loadXML("/web/static/src/xml/rainbow_man.xml", qweb);
+ }
+ return $.when(this._super.apply(this, arguments), def);
+ },
+ /**
+ * @override
+ */
+ start: function () {
+ var self = this;
+ if (this.options.click_close) {
+ core.bus.on('click', this, function (ev) {
+ if (ev.originalEvent && ev.target.className.indexOf('o_reward') === -1) {
+ this.destroy();
+ }
+ });
+ }
+ if (this.delay) {
+ setTimeout(function () {
+ self.$el.addClass('o_reward_fading');
+ setTimeout(function () {
+ self.destroy();
+ }, 600); // destroy only after fadeout animation is completed
+ }, this.delay);
+ }
+ this.$('.o_reward_msg_content').append(this.options.message);
+ return this._super.apply(this, arguments);
+ }
+});
+
+return RainbowMan;
+
+});