Merge PR #2598 into 16.0

Signed-off-by pedrobaeza
pull/2788/head
OCA-git-bot 2024-04-01 06:29:50 +00:00
commit 7f0081339f
5 changed files with 126 additions and 22 deletions

View File

@ -75,13 +75,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 %
@ -121,6 +136,7 @@ Contributors
* Aitor Bouzas <aitor.bouzas@adaptivecity.com>
* Shepilov Vladislav <shepilov.v@protonmail.com>
* Kevin Khao <kevin.khao@akretion.com>
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
* `Tecnativa <https://www.tecnativa.com>`_:
* David Vidal

View File

@ -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 @@ class ResUsers(models.Model):
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 @@ class ResUsers(models.Model):
title=None,
sticky=False,
target=None,
action=None,
):
if not (self.env.user._is_admin() or self.env.su) and any(
user.id != self.env.uid for user in self
@ -87,11 +114,14 @@ class ResUsers(models.Model):
)
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]

View File

@ -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

View File

@ -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,
});
});
});

View File

@ -14,7 +14,12 @@ class TestResUsers(common.TransactionCase):
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 @@ class TestResUsers(common.TransactionCase):
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 @@ class TestResUsers(common.TransactionCase):
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 @@ class TestResUsers(common.TransactionCase):
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 @@ class TestResUsers(common.TransactionCase):
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))