From 1dda32335979869c27ac4f216ccda32d02101b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Fri, 6 Oct 2017 11:15:46 +0200 Subject: [PATCH] [REF] web: refactor notification system This commit aims to bring the code closer to an ideal state. We want notifications to be a simple service, easy to use, and well documented. --- .../calendar/static/src/js/base_calendar.js | 15 ++- .../src/js/chrome/abstract_web_client.js | 2 +- .../src/js/services/notification_manager.js | 90 +++++++++++++ .../web/static/src/js/widgets/notification.js | 119 ++++++++++-------- addons/web/views/webclient_templates.xml | 1 + 5 files changed, 169 insertions(+), 58 deletions(-) create mode 100644 addons/web/static/src/js/services/notification_manager.js diff --git a/addons/calendar/static/src/js/base_calendar.js b/addons/calendar/static/src/js/base_calendar.js index f906958605f..892ab05a064 100644 --- a/addons/calendar/static/src/js/base_calendar.js +++ b/addons/calendar/static/src/js/base_calendar.js @@ -4,7 +4,7 @@ odoo.define('base_calendar.base_calendar', function (require) { var bus = require('bus.bus').bus; var BasicModel = require('web.BasicModel'); var field_registry = require('web.field_registry'); -var Notification = require('web.notification').Notification; +var Notification = require('web.Notification'); var relational_fields = require('web.relational_fields'); var session = require('web.session'); var WebClient = require('web.WebClient'); @@ -15,9 +15,10 @@ var FieldMany2ManyTags = relational_fields.FieldMany2ManyTags; var CalendarNotification = Notification.extend({ template: "CalendarNotification", - init: function(parent, title, text, eid) { - this._super(parent, title, text, true); - this.eid = eid; + init: function(parent, params) { + this._super(parent, params); + this.eid = params.eventID; + this.sticky = true; this.events = _.extend(this.events || {}, { 'click .link2event': function() { @@ -66,7 +67,11 @@ WebClient.include({ // For each notification, set a timeout to display it _.each(notifications, function(notif) { self.calendar_notif_timeouts[notif.event_id] = setTimeout(function() { - var notification = new CalendarNotification(self.notification_manager, notif.title, notif.message, notif.event_id); + var notification = new CalendarNotification(self.notification_manager, { + title: notif.title, + text: notif.message, + eventID: notif.event_id, + }); self.notification_manager.display(notification); self.calendar_notif[notif.event_id] = notification; }, notif.timer * 1000); 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 dbf6937937d..45a2b0b1e8c 100644 --- a/addons/web/static/src/js/chrome/abstract_web_client.js +++ b/addons/web/static/src/js/chrome/abstract_web_client.js @@ -20,7 +20,7 @@ var data_manager = require('web.data_manager'); var Dialog = require('web.Dialog'); var Loading = require('web.Loading'); var mixins = require('web.mixins'); -var NotificationManager = require('web.notification').NotificationManager; +var NotificationManager = require('web.NotificationManager'); var RainbowMan = require('web.RainbowMan'); var session = require('web.session'); var Widget = require('web.Widget'); diff --git a/addons/web/static/src/js/services/notification_manager.js b/addons/web/static/src/js/services/notification_manager.js new file mode 100644 index 00000000000..b9b128be78d --- /dev/null +++ b/addons/web/static/src/js/services/notification_manager.js @@ -0,0 +1,90 @@ +odoo.define('web.NotificationManager', function (require) { +"use strict"; + +/** + * NotificationManager + * + * The NotificationManager is simply a widget that will be instantiated by the + * web client to display notifications in the top/right part of the screen. + * + * If you want to display such a notification, you probably do not want to do it + * by using this file. The proper way is to use the do_warn or do_notify + * methods on the Widget class. + * + * @todo This class should be converted into a proper service. Need the right + * service API to do it. + */ + +var Notification = require('web.Notification'); +var Widget = require('web.Widget'); + +var NotificationManager = Widget.extend({ + className: 'o_notification_manager', + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Display a notification at the appropriate location, and returns the + * reference to the same widget (useful to get back a reference). + * + * Note that this method does not wait for the appendTo method to complete. + * + * @param {Notification} notification + * @returns {Notification} + */ + display: function (notification) { + notification.appendTo(this.$el); + return notification; + }, + /** + * Will display a notification of type 'notification' + * + * @param {string} title + * @param {string} text + * @param {boolean} sticky + * @returns {Notification} + */ + notify: function (title, text, sticky) { + return this._display(title, text, sticky, 'notification'); + }, + /** + * Will display a notification of type 'warning' + * + * @param {string} title + * @param {string} text + * @param {boolean} sticky + * @returns {Notification} + */ + warn: function (title, text, sticky) { + return this._display(title, text, sticky, 'warning'); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Display a notification + * + * @private + * @param {string} title + * @param {string} text + * @param {boolean} sticky + * @param {string} type either 'notification' or 'warning' + * @returns {Notification} + */ + _display: function (title, text, sticky, type) { + return this.display(new Notification(this, { + title: title, + text: text, + sticky: sticky, + type: type, + })); + } +}); + +return NotificationManager; + +}); diff --git a/addons/web/static/src/js/widgets/notification.js b/addons/web/static/src/js/widgets/notification.js index 6e11b4c8647..21c24c99e1b 100644 --- a/addons/web/static/src/js/widgets/notification.js +++ b/addons/web/static/src/js/widgets/notification.js @@ -1,73 +1,88 @@ -odoo.define('web.notification', function (require) { +odoo.define('web.Notification', function (require) { "use strict"; -var core = require('web.core'); +/** + * Notification + * + * This file contains the widget which is used to display a warning/information + * message in the top right of the screen. + * + * If you want to display such a notification, you probably do not want to do it + * by importing this file. The proper way is to use the do_warn or do_notify + * methods on the Widget class. + */ + var Widget = require('web.Widget'); var Notification = Widget.extend({ template: 'Notification', events: { - 'click .o_close': function(e) { - e.preventDefault(); - this.destroy(true); + 'click .o_close': '_onClose', + }, + /** + * @override + * @param {Widget} parent + * @param {Object} params + * @param {string} params.title notification title + * @param {string} params.text notification main text + * @param {string} params.type 'notification' or 'warning' + * @param {boolean} [params.sticky=false] if true, the notification will stay + * visible until the user clicks on it. + */ + init: function (parent, params) { + this._super.apply(this, arguments); + this.title = params.title; + this.text = params.text; + this.sticky = !!params.sticky; + if (params.type === 'warning') { + this.template = 'Warning'; } }, - init: function(parent, title, text, sticky) { - this._super.apply(this, arguments); - this.title = title; - this.text = text; - this.sticky = !!sticky; - }, - start: function() { - this._super.apply(this, arguments); - + /** + * @override + */ + start: function () { var self = this; - this.$el.animate({opacity: 1.0}, 400, "swing", function() { - if(!self.sticky) { - setTimeout(function() { - self.destroy(true); - }, 2500); - } - }); - }, - destroy: function(animate) { - if(!animate) { - return this._super.apply(this, arguments); - } - - var self = this, - superDestroy = this._super; - this.$el.animate({opacity: 0.0}, 400, "swing", function() { - self.$el.animate({height: 0}, 400, "swing", function() { - superDestroy.call(self); + return this._super.apply(this, arguments).then(function () { + self.$el.animate({opacity: 1.0}, 400, "swing", function () { + if(!self.sticky) { + setTimeout(self._destroy.bind(self), 2500); + } }); }); }, -}); -var Warning = Notification.extend({ - template: 'Warning', -}); + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- -var NotificationManager = Widget.extend({ - className: 'o_notification_manager', - - display: function(notification) { - notification.appendTo(this.$el); - return notification; + /** + * This method is used to destroy the widget with a nice animation. We + * first perform an animation, then call the real destroy method. + * + * @private + */ + _destroy: function () { + var self = this; + this.$el.animate({opacity: 0.0}, 400, "swing", function() { + self.$el.animate({height: 0}, 400, "swing", self.destroy.bind(self)); + }); }, - notify: function(title, text, sticky) { - return this.display(new Notification(this, title, text, sticky)); - }, - warn: function(title, text, sticky) { - return this.display(new Warning(this, title, text, sticky)); + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {MouseEvent} ev + */ + _onClose: function (ev) { + ev.preventDefault(); + this._destroy(); }, }); -return { - Notification: Notification, - Warning: Warning, - NotificationManager: NotificationManager, -}; +return Notification; }); diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml index 4f69ed286b3..cdc29635cd1 100644 --- a/addons/web/views/webclient_templates.xml +++ b/addons/web/views/webclient_templates.xml @@ -157,6 +157,7 @@ +