pull/2971/merge
Carlos Jimeno Cordero 2025-04-23 10:20:29 +01:00 committed by GitHub
commit 107c453cba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 62 additions and 2 deletions

View File

@ -143,6 +143,7 @@ Contributors
* Aitor Bouzas <aitor.bouzas@adaptivecity.com> * Aitor Bouzas <aitor.bouzas@adaptivecity.com>
* Shepilov Vladislav <shepilov.v@protonmail.com> * Shepilov Vladislav <shepilov.v@protonmail.com>
* Kevin Khao <kevin.khao@akretion.com> * Kevin Khao <kevin.khao@akretion.com>
* Carlos Jimeno <carlos.jimeno@braintec.com>
* `Tecnativa <https://www.tecnativa.com>`_: * `Tecnativa <https://www.tecnativa.com>`_:
* David Vidal * David Vidal

View File

@ -1,5 +1,7 @@
# Copyright 2016 ACSONE SA/NV # Copyright 2016 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import uuid
from odoo import _, api, exceptions, fields, models from odoo import _, api, exceptions, fields, models
from odoo.addons.bus.models.bus import channel_with_db, json_dump from odoo.addons.bus.models.bus import channel_with_db, json_dump
@ -122,7 +124,11 @@ class ResUsers(models.Model):
target = self.partner_id target = self.partner_id
if action: if action:
action = clean_action(action, self.env) action = clean_action(action, self.env)
unique_id = str(uuid.uuid4())
bus_message = { bus_message = {
"id": unique_id,
"type": type_message, "type": type_message,
"message": message, "message": message,
"title": title, "title": title,
@ -133,3 +139,18 @@ class ResUsers(models.Model):
notifications = [[partner, "web.notify", [bus_message]] for partner in target] notifications = [[partner, "web.notify", [bus_message]] for partner in target]
self.env["bus.bus"]._sendmany(notifications) self.env["bus.bus"]._sendmany(notifications)
@api.model
def notify_dismiss(self, notif_id):
partner_id = self.env.user.partner_id.id
bus_message = {
"id": notif_id,
}
notifications = [
[
(self.env.cr.dbname, "res.partner", partner_id),
"web.notify.dismiss",
[bus_message],
]
]
self.env["bus.bus"]._sendmany(notifications)

View File

@ -3,6 +3,7 @@
* Aitor Bouzas <aitor.bouzas@adaptivecity.com> * Aitor Bouzas <aitor.bouzas@adaptivecity.com>
* Shepilov Vladislav <shepilov.v@protonmail.com> * Shepilov Vladislav <shepilov.v@protonmail.com>
* Kevin Khao <kevin.khao@akretion.com> * Kevin Khao <kevin.khao@akretion.com>
* Carlos Jimeno <carlos.jimeno@braintec.com>
* `Tecnativa <https://www.tecnativa.com>`_: * `Tecnativa <https://www.tecnativa.com>`_:
* David Vidal * David Vidal

View File

@ -473,6 +473,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
<li>Aitor Bouzas &lt;<a class="reference external" href="mailto:aitor.bouzas&#64;adaptivecity.com">aitor.bouzas&#64;adaptivecity.com</a>&gt;</li> <li>Aitor Bouzas &lt;<a class="reference external" href="mailto:aitor.bouzas&#64;adaptivecity.com">aitor.bouzas&#64;adaptivecity.com</a>&gt;</li>
<li>Shepilov Vladislav &lt;<a class="reference external" href="mailto:shepilov.v&#64;protonmail.com">shepilov.v&#64;protonmail.com</a>&gt;</li> <li>Shepilov Vladislav &lt;<a class="reference external" href="mailto:shepilov.v&#64;protonmail.com">shepilov.v&#64;protonmail.com</a>&gt;</li>
<li>Kevin Khao &lt;<a class="reference external" href="mailto:kevin.khao&#64;akretion.com">kevin.khao&#64;akretion.com</a>&gt;</li> <li>Kevin Khao &lt;<a class="reference external" href="mailto:kevin.khao&#64;akretion.com">kevin.khao&#64;akretion.com</a>&gt;</li>
<li>Carlos Jimeno &lt;<a class="reference external" href="mailto:carlos.jimeno&#64;braintec.com">carlos.jimeno&#64;braintec.com</a>&gt;</li>
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul> <li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>David Vidal</li> <li>David Vidal</li>
</ul> </ul>

View File

@ -4,10 +4,11 @@ import {browser} from "@web/core/browser/browser";
import {registry} from "@web/core/registry"; import {registry} from "@web/core/registry";
export const webNotificationService = { export const webNotificationService = {
dependencies: ["bus_service", "notification", "action"], dependencies: ["bus_service", "notification", "action", "orm"],
start(env, {bus_service, notification, action}) { start(env, {bus_service, notification, action, orm}) {
let webNotifTimeouts = {}; let webNotifTimeouts = {};
const displayedNotifications = {};
/** /**
* Displays the web notification on user's screen * Displays the web notification on user's screen
* @param {*} notifications * @param {*} notifications
@ -44,10 +45,17 @@ export const webNotificationService = {
button.onClick = async () => { button.onClick = async () => {
await onClick(); await onClick();
notificationRemove(); notificationRemove();
await orm.call("res.users", "notify_dismiss", [
notif.id,
]);
}; };
return button; return button;
}), }),
onClose: async () => {
await orm.call("res.users", "notify_dismiss", [notif.id]);
},
}); });
displayedNotifications[notif.id] = notificationRemove;
}); });
}); });
} }
@ -56,9 +64,16 @@ export const webNotificationService = {
for (const {payload, type} of notifications) { for (const {payload, type} of notifications) {
if (type === "web.notify") { if (type === "web.notify") {
displaywebNotification(payload); displaywebNotification(payload);
} else if (type === "web.notify.dismiss") {
const notifId = payload[0].id;
if (displayedNotifications[notifId]) {
displayedNotifications[notifId]();
delete displayedNotifications[notifId];
}
} }
} }
}); });
bus_service.start(); bus_service.start();
}, },
}; };

View File

@ -26,6 +26,8 @@ class TestResUsers(common.TransactionCase):
self.assertEqual(1, len(news)) self.assertEqual(1, len(news))
test_msg.update({"type": SUCCESS}) test_msg.update({"type": SUCCESS})
payload = json.loads(news.message)["payload"][0] payload = json.loads(news.message)["payload"][0]
self.assertIn("id", payload)
payload.pop("id", None)
self.assertDictEqual(test_msg, payload) self.assertDictEqual(test_msg, payload)
def test_notify_danger(self): def test_notify_danger(self):
@ -44,6 +46,8 @@ class TestResUsers(common.TransactionCase):
self.assertEqual(1, len(news)) self.assertEqual(1, len(news))
test_msg.update({"type": DANGER}) test_msg.update({"type": DANGER})
payload = json.loads(news.message)["payload"][0] payload = json.loads(news.message)["payload"][0]
self.assertIn("id", payload)
payload.pop("id", None)
self.assertDictEqual(test_msg, payload) self.assertDictEqual(test_msg, payload)
def test_notify_warning(self): def test_notify_warning(self):
@ -62,6 +66,8 @@ class TestResUsers(common.TransactionCase):
self.assertEqual(1, len(news)) self.assertEqual(1, len(news))
test_msg.update({"type": WARNING}) test_msg.update({"type": WARNING})
payload = json.loads(news.message)["payload"][0] payload = json.loads(news.message)["payload"][0]
self.assertIn("id", payload)
payload.pop("id", None)
self.assertDictEqual(test_msg, payload) self.assertDictEqual(test_msg, payload)
def test_notify_info(self): def test_notify_info(self):
@ -80,6 +86,8 @@ class TestResUsers(common.TransactionCase):
self.assertEqual(1, len(news)) self.assertEqual(1, len(news))
test_msg.update({"type": INFO}) test_msg.update({"type": INFO})
payload = json.loads(news.message)["payload"][0] payload = json.loads(news.message)["payload"][0]
self.assertIn("id", payload)
payload.pop("id", None)
self.assertDictEqual(test_msg, payload) self.assertDictEqual(test_msg, payload)
def test_notify_default(self): def test_notify_default(self):
@ -98,6 +106,8 @@ class TestResUsers(common.TransactionCase):
self.assertEqual(1, len(news)) self.assertEqual(1, len(news))
test_msg.update({"type": DEFAULT}) test_msg.update({"type": DEFAULT})
payload = json.loads(news.message)["payload"][0] payload = json.loads(news.message)["payload"][0]
self.assertIn("id", payload)
payload.pop("id", None)
self.assertDictEqual(test_msg, payload) self.assertDictEqual(test_msg, payload)
def test_notify_many(self): def test_notify_many(self):
@ -117,3 +127,14 @@ class TestResUsers(common.TransactionCase):
def test_notify_admin_allowed_other_user(self): def test_notify_admin_allowed_other_user(self):
other_user = self.env.ref("base.user_demo") other_user = self.env.ref("base.user_demo")
other_user.notify_info(message="hello") other_user.notify_info(message="hello")
def test_notify_dismiss(self):
bus_bus = self.env["bus.bus"]
domain = [("channel", "=", self.env.user.notify_default_channel_name)]
existing = bus_bus.search(domain)
notif_id = "test-notif-id"
self.env.user.notify_dismiss(notif_id)
news = bus_bus.search(domain) - existing
self.assertEqual(1, len(news))
payload = json.loads(news.message)["payload"][0]
self.assertEqual(payload["id"], notif_id)