forked from Techsystech/web
[MIG] web_notify: Migration to 15.0
parent
8fb3984604
commit
5c6085d4a6
|
@ -50,7 +50,7 @@ Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
|
||||||
To send a notification to the user you just need to call one of the new methods defined on res.users:
|
To send a notification to the logged in user or target audience you just need to call one of the new methods defined on res.users:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ or
|
||||||
:alt: Sample notifications
|
:alt: Sample notifications
|
||||||
|
|
||||||
You can test the behaviour of the notifications by installing this module in a demo database.
|
You can test the behaviour of the notifications by installing this module in a demo database.
|
||||||
Access the users form through Settings -> Users & Companies. You'll see a tab called "Test web notify", here you'll find two buttons that'll allow you test the module.
|
Access the users form through Settings -> Users & Companies. You'll see a tab called "Test web notify", here you'll find five buttons that'll allow you test the module.
|
||||||
|
|
||||||
.. figure:: https://raw.githubusercontent.com/OCA/web/14.0/web_notify/static/description/test_notifications_demo.png
|
.. figure:: https://raw.githubusercontent.com/OCA/web/14.0/web_notify/static/description/test_notifications_demo.png
|
||||||
:scale: 80 %
|
:scale: 80 %
|
||||||
|
|
|
@ -6,13 +6,18 @@
|
||||||
"name": "Web Notify",
|
"name": "Web Notify",
|
||||||
"summary": """
|
"summary": """
|
||||||
Send notification messages to user""",
|
Send notification messages to user""",
|
||||||
"version": "14.0.1.0.1",
|
"version": "15.0.1.0.0",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"author": "ACSONE SA/NV," "AdaptiveCity," "Odoo Community Association (OCA)",
|
"author": "ACSONE SA/NV," "AdaptiveCity," "Odoo Community Association (OCA)",
|
||||||
"development_status": "Production/Stable",
|
"development_status": "Production/Stable",
|
||||||
"website": "https://github.com/OCA/web",
|
"website": "https://github.com/OCA/web",
|
||||||
"depends": ["web", "bus", "base"],
|
"depends": ["web", "bus", "base", "mail"],
|
||||||
"data": ["views/web_notify.xml"],
|
"assets": {
|
||||||
|
"web.assets_backend": [
|
||||||
|
"web_notify/static/src/js/services/notification.js",
|
||||||
|
"web_notify/static/src/js/services/notification_services.js",
|
||||||
|
]
|
||||||
|
},
|
||||||
"demo": ["views/res_users_demo.xml"],
|
"demo": ["views/res_users_demo.xml"],
|
||||||
"installable": True,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
# 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).
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
DEFAULT_MESSAGE = "Default message"
|
DEFAULT_MESSAGE = "Default message"
|
||||||
|
|
||||||
SUCCESS = "success"
|
SUCCESS = "success"
|
||||||
|
@ -19,12 +22,21 @@ class ResUsers(models.Model):
|
||||||
@api.depends("create_date")
|
@api.depends("create_date")
|
||||||
def _compute_channel_names(self):
|
def _compute_channel_names(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
res_id = record.id
|
record.notify_success_channel_name = json_dump(
|
||||||
record.notify_success_channel_name = "notify_success_%s" % res_id
|
channel_with_db(self.env.cr.dbname, record.partner_id)
|
||||||
record.notify_danger_channel_name = "notify_danger_%s" % res_id
|
)
|
||||||
record.notify_warning_channel_name = "notify_warning_%s" % res_id
|
record.notify_danger_channel_name = json_dump(
|
||||||
record.notify_info_channel_name = "notify_info_%s" % res_id
|
channel_with_db(self.env.cr.dbname, record.partner_id)
|
||||||
record.notify_default_channel_name = "notify_default_%s" % res_id
|
)
|
||||||
|
record.notify_warning_channel_name = json_dump(
|
||||||
|
channel_with_db(self.env.cr.dbname, record.partner_id)
|
||||||
|
)
|
||||||
|
record.notify_info_channel_name = json_dump(
|
||||||
|
channel_with_db(self.env.cr.dbname, record.partner_id)
|
||||||
|
)
|
||||||
|
record.notify_default_channel_name = json_dump(
|
||||||
|
channel_with_db(self.env.cr.dbname, record.partner_id)
|
||||||
|
)
|
||||||
|
|
||||||
notify_success_channel_name = fields.Char(compute="_compute_channel_names")
|
notify_success_channel_name = fields.Char(compute="_compute_channel_names")
|
||||||
notify_danger_channel_name = fields.Char(compute="_compute_channel_names")
|
notify_danger_channel_name = fields.Char(compute="_compute_channel_names")
|
||||||
|
@ -32,28 +44,43 @@ class ResUsers(models.Model):
|
||||||
notify_info_channel_name = fields.Char(compute="_compute_channel_names")
|
notify_info_channel_name = fields.Char(compute="_compute_channel_names")
|
||||||
notify_default_channel_name = fields.Char(compute="_compute_channel_names")
|
notify_default_channel_name = fields.Char(compute="_compute_channel_names")
|
||||||
|
|
||||||
def notify_success(self, message="Default message", title=None, sticky=False):
|
def notify_success(
|
||||||
|
self, message="Default message", title=None, sticky=False, target=None
|
||||||
|
):
|
||||||
title = title or _("Success")
|
title = title or _("Success")
|
||||||
self._notify_channel(SUCCESS, message, title, sticky)
|
self._notify_channel(SUCCESS, message, title, sticky, target)
|
||||||
|
|
||||||
def notify_danger(self, message="Default message", title=None, sticky=False):
|
def notify_danger(
|
||||||
|
self, message="Default message", title=None, sticky=False, target=None
|
||||||
|
):
|
||||||
title = title or _("Danger")
|
title = title or _("Danger")
|
||||||
self._notify_channel(DANGER, message, title, sticky)
|
self._notify_channel(DANGER, message, title, sticky, target)
|
||||||
|
|
||||||
def notify_warning(self, message="Default message", title=None, sticky=False):
|
def notify_warning(
|
||||||
|
self, message="Default message", title=None, sticky=False, target=None
|
||||||
|
):
|
||||||
title = title or _("Warning")
|
title = title or _("Warning")
|
||||||
self._notify_channel(WARNING, message, title, sticky)
|
self._notify_channel(WARNING, message, title, sticky, target)
|
||||||
|
|
||||||
def notify_info(self, message="Default message", title=None, sticky=False):
|
def notify_info(
|
||||||
|
self, message="Default message", title=None, sticky=False, target=None
|
||||||
|
):
|
||||||
title = title or _("Information")
|
title = title or _("Information")
|
||||||
self._notify_channel(INFO, message, title, sticky)
|
self._notify_channel(INFO, message, title, sticky, target)
|
||||||
|
|
||||||
def notify_default(self, message="Default message", title=None, sticky=False):
|
def notify_default(
|
||||||
|
self, message="Default message", title=None, sticky=False, target=None
|
||||||
|
):
|
||||||
title = title or _("Default")
|
title = title or _("Default")
|
||||||
self._notify_channel(DEFAULT, message, title, sticky)
|
self._notify_channel(DEFAULT, message, title, sticky, target)
|
||||||
|
|
||||||
def _notify_channel(
|
def _notify_channel(
|
||||||
self, type_message=DEFAULT, message=DEFAULT_MESSAGE, title=None, sticky=False
|
self,
|
||||||
|
type_message=DEFAULT,
|
||||||
|
message=DEFAULT_MESSAGE,
|
||||||
|
title=None,
|
||||||
|
sticky=False,
|
||||||
|
target=None,
|
||||||
):
|
):
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
if not self.env.user._is_admin() and any(
|
if not self.env.user._is_admin() and any(
|
||||||
|
@ -62,12 +89,14 @@ class ResUsers(models.Model):
|
||||||
raise exceptions.UserError(
|
raise exceptions.UserError(
|
||||||
_("Sending a notification to another user is forbidden.")
|
_("Sending a notification to another user is forbidden.")
|
||||||
)
|
)
|
||||||
channel_name_field = "notify_{}_channel_name".format(type_message)
|
if not target:
|
||||||
|
target = self.env.user.partner_id
|
||||||
bus_message = {
|
bus_message = {
|
||||||
"type": type_message,
|
"type": type_message,
|
||||||
"message": message,
|
"message": message,
|
||||||
"title": title,
|
"title": title,
|
||||||
"sticky": sticky,
|
"sticky": sticky,
|
||||||
}
|
}
|
||||||
notifications = [(record[channel_name_field], bus_message) for record in self]
|
|
||||||
self.env["bus.bus"].sendmany(notifications)
|
notifications = [[partner, "web.notify", [bus_message]] for partner in target]
|
||||||
|
self.env["bus.bus"]._sendmany(notifications)
|
||||||
|
|
|
@ -370,7 +370,7 @@ ul.auto-toc {
|
||||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/web/tree/14.0/web_notify"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/web-14-0/web-14-0-web_notify"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/162/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/web/tree/14.0/web_notify"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/web-14-0/web-14-0-web_notify"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/162/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
||||||
<p>Send instant notification messages to the user in live.</p>
|
<p>Send instant notification messages to the user in live.</p>
|
||||||
<p>This technical module allows you to send instant notification messages from the server to the user in live.
|
<p>This technical module allows you to send instant notification messages from the server to the user in live.
|
||||||
Two kinds of notification are supported.</p>
|
Five kinds of notification are supported.</p>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Success: Displayed in a <cite>success</cite> theme color flying popup div</li>
|
<li>Success: Displayed in a <cite>success</cite> theme color flying popup div</li>
|
||||||
<li>Danger: Displayed in a <cite>danger</cite> theme color flying popup div</li>
|
<li>Danger: Displayed in a <cite>danger</cite> theme color flying popup div</li>
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
odoo.define("web_notify.Notification", function (require) {
|
||||||
|
"use strict";
|
||||||
|
const {Notification} = require("@web/core/notifications/notification");
|
||||||
|
const {patch} = require("web.utils");
|
||||||
|
|
||||||
|
patch(Notification.props, "webNotifyProps", {
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
validate: (t) =>
|
||||||
|
["warning", "danger", "success", "info", "default"].includes(t),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,47 @@
|
||||||
|
odoo.define("web_notify.NotificationService", function (require) {
|
||||||
|
"use strict";
|
||||||
|
const {browser} = require("@web/core/browser/browser");
|
||||||
|
const {registry} = require("@web/core/registry");
|
||||||
|
|
||||||
|
const webNotificationService = {
|
||||||
|
dependencies: ["notification"],
|
||||||
|
|
||||||
|
start(env, {notification}) {
|
||||||
|
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 () {
|
||||||
|
notification.add(notif.message, {
|
||||||
|
title: notif.title,
|
||||||
|
type: notif.type,
|
||||||
|
sticky: notif.sticky,
|
||||||
|
className: notif.className,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
env.bus.on("WEB_CLIENT_READY", null, async () => {
|
||||||
|
const legacyEnv = owl.Component.env;
|
||||||
|
legacyEnv.services.bus_service.onNotification(this, (notifications) => {
|
||||||
|
for (const {payload, type} of notifications) {
|
||||||
|
if (type === "web.notify") {
|
||||||
|
displaywebNotification(payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
legacyEnv.services.bus_service.startPolling();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
registry.category("services").add("webNotification", webNotificationService);
|
||||||
|
});
|
|
@ -1,61 +0,0 @@
|
||||||
odoo.define("web_notify.WebClient", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var WebClient = require("web.WebClient");
|
|
||||||
var session = require("web.session");
|
|
||||||
require("bus.BusService");
|
|
||||||
|
|
||||||
WebClient.include({
|
|
||||||
show_application: function () {
|
|
||||||
var res = this._super();
|
|
||||||
this.start_polling();
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
start_polling: function () {
|
|
||||||
this.channel_success = "notify_success_" + session.uid;
|
|
||||||
this.channel_danger = "notify_danger_" + session.uid;
|
|
||||||
this.channel_warning = "notify_warning_" + session.uid;
|
|
||||||
this.channel_info = "notify_info_" + session.uid;
|
|
||||||
this.channel_default = "notify_default_" + session.uid;
|
|
||||||
this.all_channels = [
|
|
||||||
this.channel_success,
|
|
||||||
this.channel_danger,
|
|
||||||
this.channel_warning,
|
|
||||||
this.channel_info,
|
|
||||||
this.channel_default,
|
|
||||||
];
|
|
||||||
this.call("bus_service", "startPolling");
|
|
||||||
|
|
||||||
if (this.call("bus_service", "isMasterTab")) {
|
|
||||||
this.call("bus_service", "addChannel", this.channel_success);
|
|
||||||
this.call("bus_service", "addChannel", this.channel_danger);
|
|
||||||
this.call("bus_service", "addChannel", this.channel_warning);
|
|
||||||
this.call("bus_service", "addChannel", this.channel_info);
|
|
||||||
this.call("bus_service", "addChannel", this.channel_default);
|
|
||||||
}
|
|
||||||
this.call("bus_service", "on", "notification", this, this.bus_notification);
|
|
||||||
},
|
|
||||||
bus_notification: function (notifications) {
|
|
||||||
var self = this;
|
|
||||||
_.each(notifications, function (notification) {
|
|
||||||
var channel = notification[0];
|
|
||||||
var message = notification[1];
|
|
||||||
if (
|
|
||||||
self.all_channels !== null &&
|
|
||||||
self.all_channels.indexOf(channel) > -1
|
|
||||||
) {
|
|
||||||
self.on_message(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
on_message: function (message) {
|
|
||||||
return this.call("notification", "notify", {
|
|
||||||
type: message.type,
|
|
||||||
title: message.title,
|
|
||||||
message: message.message,
|
|
||||||
sticky: message.sticky,
|
|
||||||
className: message.className,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,26 +0,0 @@
|
||||||
odoo.define("web_notify.Notification", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var Notification = require("web.Notification");
|
|
||||||
|
|
||||||
Notification.include({
|
|
||||||
icon_mapping: {
|
|
||||||
success: "fa-thumbs-up",
|
|
||||||
danger: "fa-exclamation-triangle",
|
|
||||||
warning: "fa-exclamation",
|
|
||||||
info: "fa-info",
|
|
||||||
default: "fa-lightbulb-o",
|
|
||||||
},
|
|
||||||
init: function () {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
// Delete default classes
|
|
||||||
this.className = this.className.replace(" o_error", "");
|
|
||||||
// Add custom icon and custom class
|
|
||||||
this.icon =
|
|
||||||
this.type in this.icon_mapping
|
|
||||||
? this.icon_mapping[this.type]
|
|
||||||
: this.icon_mapping.default;
|
|
||||||
this.className += " o_" + this.type;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,24 +0,0 @@
|
||||||
.o_notification_manager {
|
|
||||||
.o_notification {
|
|
||||||
&.o_success {
|
|
||||||
color: white;
|
|
||||||
background-color: theme-color("success");
|
|
||||||
}
|
|
||||||
&.o_danger {
|
|
||||||
color: white;
|
|
||||||
background-color: theme-color("danger");
|
|
||||||
}
|
|
||||||
&.o_warning {
|
|
||||||
color: white;
|
|
||||||
background-color: theme-color("warning");
|
|
||||||
}
|
|
||||||
&.o_info {
|
|
||||||
color: white;
|
|
||||||
background-color: theme-color("info");
|
|
||||||
}
|
|
||||||
&.o_default {
|
|
||||||
color: black;
|
|
||||||
background-color: theme-color("default");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,97 +2,81 @@
|
||||||
# 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 json
|
import json
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
from odoo import exceptions
|
from odoo import exceptions
|
||||||
from odoo.tests import common
|
from odoo.tests import common
|
||||||
|
|
||||||
from odoo.addons.bus.models.bus import json_dump
|
|
||||||
|
|
||||||
from ..models.res_users import DANGER, DEFAULT, INFO, SUCCESS, WARNING
|
from ..models.res_users import DANGER, DEFAULT, INFO, SUCCESS, WARNING
|
||||||
|
|
||||||
|
|
||||||
class TestResUsers(common.TransactionCase):
|
class TestResUsers(common.TransactionCase):
|
||||||
def test_notify_success(self):
|
def test_notify_success(self):
|
||||||
bus_bus = self.env["bus.bus"]
|
bus_bus = self.env["bus.bus"]
|
||||||
domain = [
|
domain = [("channel", "=", self.env.user.notify_success_channel_name)]
|
||||||
("channel", "=", json_dump(self.env.user.notify_success_channel_name))
|
|
||||||
]
|
|
||||||
existing = bus_bus.search(domain)
|
existing = bus_bus.search(domain)
|
||||||
test_msg = {"message": "message", "title": "title", "sticky": True}
|
test_msg = {"message": "message", "title": "title", "sticky": True}
|
||||||
self.env.user.notify_success(**test_msg)
|
self.env.user.notify_success(**test_msg)
|
||||||
news = bus_bus.search(domain) - existing
|
news = bus_bus.search(domain) - existing
|
||||||
self.assertEqual(1, len(news))
|
self.assertEqual(1, len(news))
|
||||||
test_msg.update({"type": SUCCESS})
|
test_msg.update({"type": SUCCESS})
|
||||||
self.assertDictEqual(test_msg, json.loads(news.message))
|
payload = json.loads(news.message)["payload"][0]
|
||||||
|
self.assertDictEqual(test_msg, payload)
|
||||||
|
|
||||||
def test_notify_danger(self):
|
def test_notify_danger(self):
|
||||||
bus_bus = self.env["bus.bus"]
|
bus_bus = self.env["bus.bus"]
|
||||||
domain = [("channel", "=", json_dump(self.env.user.notify_danger_channel_name))]
|
domain = [("channel", "=", self.env.user.notify_danger_channel_name)]
|
||||||
existing = bus_bus.search(domain)
|
existing = bus_bus.search(domain)
|
||||||
test_msg = {"message": "message", "title": "title", "sticky": True}
|
test_msg = {"message": "message", "title": "title", "sticky": True}
|
||||||
self.env.user.notify_danger(**test_msg)
|
self.env.user.notify_danger(**test_msg)
|
||||||
news = bus_bus.search(domain) - existing
|
news = bus_bus.search(domain) - existing
|
||||||
self.assertEqual(1, len(news))
|
self.assertEqual(1, len(news))
|
||||||
test_msg.update({"type": DANGER})
|
test_msg.update({"type": DANGER})
|
||||||
self.assertDictEqual(test_msg, json.loads(news.message))
|
payload = json.loads(news.message)["payload"][0]
|
||||||
|
self.assertDictEqual(test_msg, payload)
|
||||||
|
|
||||||
def test_notify_warning(self):
|
def test_notify_warning(self):
|
||||||
bus_bus = self.env["bus.bus"]
|
bus_bus = self.env["bus.bus"]
|
||||||
domain = [
|
domain = [("channel", "=", self.env.user.notify_warning_channel_name)]
|
||||||
("channel", "=", json_dump(self.env.user.notify_warning_channel_name))
|
|
||||||
]
|
|
||||||
existing = bus_bus.search(domain)
|
existing = bus_bus.search(domain)
|
||||||
test_msg = {"message": "message", "title": "title", "sticky": True}
|
test_msg = {"message": "message", "title": "title", "sticky": True}
|
||||||
self.env.user.notify_warning(**test_msg)
|
self.env.user.notify_warning(**test_msg)
|
||||||
news = bus_bus.search(domain) - existing
|
news = bus_bus.search(domain) - existing
|
||||||
self.assertEqual(1, len(news))
|
self.assertEqual(1, len(news))
|
||||||
test_msg.update({"type": WARNING})
|
test_msg.update({"type": WARNING})
|
||||||
self.assertDictEqual(test_msg, json.loads(news.message))
|
payload = json.loads(news.message)["payload"][0]
|
||||||
|
self.assertDictEqual(test_msg, payload)
|
||||||
|
|
||||||
def test_notify_info(self):
|
def test_notify_info(self):
|
||||||
bus_bus = self.env["bus.bus"]
|
bus_bus = self.env["bus.bus"]
|
||||||
domain = [("channel", "=", json_dump(self.env.user.notify_info_channel_name))]
|
domain = [("channel", "=", self.env.user.notify_info_channel_name)]
|
||||||
existing = bus_bus.search(domain)
|
existing = bus_bus.search(domain)
|
||||||
test_msg = {"message": "message", "title": "title", "sticky": True}
|
test_msg = {"message": "message", "title": "title", "sticky": True}
|
||||||
self.env.user.notify_info(**test_msg)
|
self.env.user.notify_info(**test_msg)
|
||||||
news = bus_bus.search(domain) - existing
|
news = bus_bus.search(domain) - existing
|
||||||
self.assertEqual(1, len(news))
|
self.assertEqual(1, len(news))
|
||||||
test_msg.update({"type": INFO})
|
test_msg.update({"type": INFO})
|
||||||
self.assertDictEqual(test_msg, json.loads(news.message))
|
payload = json.loads(news.message)["payload"][0]
|
||||||
|
self.assertDictEqual(test_msg, payload)
|
||||||
|
|
||||||
def test_notify_default(self):
|
def test_notify_default(self):
|
||||||
bus_bus = self.env["bus.bus"]
|
bus_bus = self.env["bus.bus"]
|
||||||
domain = [
|
domain = [("channel", "=", self.env.user.notify_default_channel_name)]
|
||||||
("channel", "=", json_dump(self.env.user.notify_default_channel_name))
|
|
||||||
]
|
|
||||||
existing = bus_bus.search(domain)
|
existing = bus_bus.search(domain)
|
||||||
test_msg = {"message": "message", "title": "title", "sticky": True}
|
test_msg = {"message": "message", "title": "title", "sticky": True}
|
||||||
self.env.user.notify_default(**test_msg)
|
self.env.user.notify_default(**test_msg)
|
||||||
news = bus_bus.search(domain) - existing
|
news = bus_bus.search(domain) - existing
|
||||||
self.assertEqual(1, len(news))
|
self.assertEqual(1, len(news))
|
||||||
test_msg.update({"type": DEFAULT})
|
test_msg.update({"type": DEFAULT})
|
||||||
self.assertDictEqual(test_msg, json.loads(news.message))
|
payload = json.loads(news.message)["payload"][0]
|
||||||
|
self.assertDictEqual(test_msg, payload)
|
||||||
|
|
||||||
def test_notify_many(self):
|
def test_notify_many(self):
|
||||||
# check that the notification of a list of users is done with
|
# check that the notification of a list of users is done with
|
||||||
# a single call to the bus
|
# a single call to the bus
|
||||||
with mock.patch("odoo.addons.bus.models.bus.ImBus.sendmany") as mockedSendMany:
|
|
||||||
users = self.env.user.search([(1, "=", 1)])
|
users = self.env.user.search([(1, "=", 1)])
|
||||||
|
|
||||||
self.assertTrue(len(users) > 1)
|
self.assertTrue(len(users) > 1)
|
||||||
users.notify_warning(message="message")
|
self.env.user.notify_warning(message="message", target=users.partner_id)
|
||||||
|
|
||||||
self.assertEqual(1, mockedSendMany.call_count)
|
|
||||||
|
|
||||||
# call_args is a tuple with args (tuple) & kwargs (dict). We check
|
|
||||||
# positional arguments (args), hence the [0].
|
|
||||||
pos_call_args = mockedSendMany.call_args[0]
|
|
||||||
|
|
||||||
# Ensure the first positional argument is a list with as many
|
|
||||||
# elements as we had users.
|
|
||||||
first_pos_call_args = pos_call_args[0]
|
|
||||||
self.assertIsInstance(first_pos_call_args, list)
|
|
||||||
self.assertEqual(len(users), len(first_pos_call_args))
|
|
||||||
|
|
||||||
def test_notify_other_user(self):
|
def test_notify_other_user(self):
|
||||||
other_user = self.env.ref("base.user_demo")
|
other_user = self.env.ref("base.user_demo")
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
class="oe_highlight"
|
class="oe_highlight"
|
||||||
/>
|
/>
|
||||||
</group>
|
</group>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<button
|
<button
|
||||||
name="notify_warning"
|
name="notify_warning"
|
||||||
|
@ -42,6 +44,8 @@
|
||||||
class="oe_highlight"
|
class="oe_highlight"
|
||||||
/>
|
/>
|
||||||
</group>
|
</group>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<button
|
<button
|
||||||
name="notify_default"
|
name="notify_default"
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<odoo>
|
|
||||||
<template
|
|
||||||
id="assets_backend"
|
|
||||||
name="web_notify assets"
|
|
||||||
inherit_id="web.assets_backend"
|
|
||||||
>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
type="text/scss"
|
|
||||||
href="/web/static/src/scss/webclient.scss"
|
|
||||||
position="after"
|
|
||||||
>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
type="text/scss"
|
|
||||||
href="/web_notify/static/src/scss/webclient.scss"
|
|
||||||
/>
|
|
||||||
</link>
|
|
||||||
<xpath expr="." position="inside">
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/web_notify/static/src/js/web_client.js"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/web_notify/static/src/js/widgets/notification.js"
|
|
||||||
/>
|
|
||||||
</xpath>
|
|
||||||
</template>
|
|
||||||
</odoo>
|
|
Loading…
Reference in New Issue