diff --git a/web_notify/README.rst b/web_notify/README.rst index 05202946de68..1535e49a0cff 100644 --- a/web_notify/README.rst +++ b/web_notify/README.rst @@ -72,13 +72,28 @@ or .. code-block:: python - self.env.user.notify_info(message='My information message') + self.env.user.notify_default(message='My default message') -or + +The notifications can bring interactivity with some buttons. + +* One allowing to refresh the active view +* Another allowing to send a window / client action + +The reload button is activated when sending the notification with: + + +The action can be used using the ``action`` keyword: .. code-block:: python - self.env.user.notify_default(message='My default message') + action = self.env.ref('sale.action_orders').read()[0] + action.update({ + 'res_id': self.id, + 'views': [(False, 'form')], + }) + self.env.user.notify_info('My information message', action=action) + .. figure:: https://raw.githubusercontent.com/OCA/web/16.0/web_notify/static/description/notifications_screenshot.gif :scale: 80 % @@ -118,6 +133,7 @@ Contributors * Aitor Bouzas * Shepilov Vladislav * Kevin Khao +* Guewen Baconnier * `Tecnativa `_: * David Vidal diff --git a/web_notify/models/res_users.py b/web_notify/models/res_users.py index db8614758659..cdec3507f5ac 100644 --- a/web_notify/models/res_users.py +++ b/web_notify/models/res_users.py @@ -3,6 +3,7 @@ from odoo import _, api, exceptions, fields, models from odoo.addons.bus.models.bus import channel_with_db, json_dump +from odoo.addons.web.controllers.main import clean_action DEFAULT_MESSAGE = "Default message" @@ -42,34 +43,59 @@ def _compute_channel_names(self): notify_default_channel_name = fields.Char(compute="_compute_channel_names") def notify_success( - self, message="Default message", title=None, sticky=False, target=None + self, + message="Default message", + title=None, + sticky=False, + target=None, + action=None, ): title = title or _("Success") - self._notify_channel(SUCCESS, message, title, sticky, target) + self._notify_channel(SUCCESS, message, title, sticky, target, action) def notify_danger( - self, message="Default message", title=None, sticky=False, target=None + self, + message="Default message", + title=None, + sticky=False, + target=None, + action=None, ): title = title or _("Danger") - self._notify_channel(DANGER, message, title, sticky, target) + self._notify_channel(DANGER, message, title, sticky, target, action) def notify_warning( - self, message="Default message", title=None, sticky=False, target=None + self, + message="Default message", + title=None, + sticky=False, + target=None, + action=None, ): title = title or _("Warning") - self._notify_channel(WARNING, message, title, sticky, target) + self._notify_channel(WARNING, message, title, sticky, target, action) def notify_info( - self, message="Default message", title=None, sticky=False, target=None + self, + message="Default message", + title=None, + sticky=False, + target=None, + action=None, ): title = title or _("Information") - self._notify_channel(INFO, message, title, sticky, target) + self._notify_channel(INFO, message, title, sticky, target, action) def notify_default( - self, message="Default message", title=None, sticky=False, target=None + self, + message="Default message", + title=None, + sticky=False, + target=None, + action=None, ): title = title or _("Default") - self._notify_channel(DEFAULT, message, title, sticky, target) + self._notify_channel(DEFAULT, message, title, sticky, target, action) def _notify_channel( self, @@ -78,6 +104,7 @@ def _notify_channel( title=None, sticky=False, target=None, + action=None, ): if not self.env.user._is_admin() and any( user.id != self.env.uid for user in self @@ -87,11 +114,14 @@ def _notify_channel( ) if not target: target = self.partner_id + if action: + action = clean_action(action, self.env) bus_message = { "type": type_message, "message": message, "title": title, "sticky": sticky, + "action": action, } notifications = [[partner, "web.notify", [bus_message]] for partner in target] diff --git a/web_notify/readme/USAGE.rst b/web_notify/readme/USAGE.rst index f31a5341fefa..c86b1ad3ac27 100644 --- a/web_notify/readme/USAGE.rst +++ b/web_notify/readme/USAGE.rst @@ -29,6 +29,27 @@ or self.env.user.notify_default(message='My default message') + +The notifications can bring interactivity with some buttons. + +* One allowing to refresh the active view +* Another allowing to send a window / client action + +The reload button is activated when sending the notification with: + + +The action can be used using the ``action`` keyword: + +.. code-block:: python + + action = self.env["ir.actions.act_window"]._for_xml_id('sale.action_orders') + action.update({ + 'res_id': self.id, + 'views': [(False, 'form')], + }) + self.env.user.notify_info('My information message', action=action) + + .. figure:: static/description/notifications_screenshot.gif :scale: 80 % :alt: Sample notifications diff --git a/web_notify/static/src/js/services/notification_services.esm.js b/web_notify/static/src/js/services/notification_services.esm.js index d364150a1c26..efec2be17baa 100644 --- a/web_notify/static/src/js/services/notification_services.esm.js +++ b/web_notify/static/src/js/services/notification_services.esm.js @@ -4,27 +4,39 @@ import {browser} from "@web/core/browser/browser"; import {registry} from "@web/core/registry"; export const webNotificationService = { - dependencies: ["bus_service", "notification"], + dependencies: ["bus_service", "notification", "action"], - start(env, {bus_service, notification}) { + start(env, {bus_service, notification, action}) { let webNotifTimeouts = {}; /** * Displays the web notification on user's screen */ - function displaywebNotification(notifications) { Object.values(webNotifTimeouts).forEach((notif) => browser.clearTimeout(notif) ); webNotifTimeouts = {}; - notifications.forEach(function (notif) { browser.setTimeout(function () { + let buttons = []; + + if (notif.action) { + buttons = [ + { + name: env._t("Open"), + primary: true, + onClick: async () => { + await action.doAction(notif.action); + }, + }, + ]; + } notification.add(Markup(notif.message), { title: notif.title, type: notif.type, sticky: notif.sticky, className: notif.className, + buttons: buttons, }); }); }); diff --git a/web_notify/tests/test_res_users.py b/web_notify/tests/test_res_users.py index 6f3f34493f28..76fedc1182a9 100644 --- a/web_notify/tests/test_res_users.py +++ b/web_notify/tests/test_res_users.py @@ -14,7 +14,12 @@ def test_notify_success(self): bus_bus = self.env["bus.bus"] domain = [("channel", "=", self.env.user.notify_success_channel_name)] existing = bus_bus.search(domain) - test_msg = {"message": "message", "title": "title", "sticky": True} + test_msg = { + "message": "message", + "title": "title", + "sticky": True, + "action": None, + } self.env.user.notify_success(**test_msg) news = bus_bus.search(domain) - existing self.assertEqual(1, len(news)) @@ -26,7 +31,12 @@ def test_notify_danger(self): bus_bus = self.env["bus.bus"] domain = [("channel", "=", self.env.user.notify_danger_channel_name)] existing = bus_bus.search(domain) - test_msg = {"message": "message", "title": "title", "sticky": True} + test_msg = { + "message": "message", + "title": "title", + "sticky": True, + "action": None, + } self.env.user.notify_danger(**test_msg) news = bus_bus.search(domain) - existing self.assertEqual(1, len(news)) @@ -38,7 +48,12 @@ def test_notify_warning(self): bus_bus = self.env["bus.bus"] domain = [("channel", "=", self.env.user.notify_warning_channel_name)] existing = bus_bus.search(domain) - test_msg = {"message": "message", "title": "title", "sticky": True} + test_msg = { + "message": "message", + "title": "title", + "sticky": True, + "action": None, + } self.env.user.notify_warning(**test_msg) news = bus_bus.search(domain) - existing self.assertEqual(1, len(news)) @@ -50,7 +65,12 @@ def test_notify_info(self): bus_bus = self.env["bus.bus"] domain = [("channel", "=", self.env.user.notify_info_channel_name)] existing = bus_bus.search(domain) - test_msg = {"message": "message", "title": "title", "sticky": True} + test_msg = { + "message": "message", + "title": "title", + "sticky": True, + "action": None, + } self.env.user.notify_info(**test_msg) news = bus_bus.search(domain) - existing self.assertEqual(1, len(news)) @@ -62,7 +82,12 @@ def test_notify_default(self): bus_bus = self.env["bus.bus"] domain = [("channel", "=", self.env.user.notify_default_channel_name)] existing = bus_bus.search(domain) - test_msg = {"message": "message", "title": "title", "sticky": True} + test_msg = { + "message": "message", + "title": "title", + "sticky": True, + "action": None, + } self.env.user.notify_default(**test_msg) news = bus_bus.search(domain) - existing self.assertEqual(1, len(news))