mirror of https://github.com/OCA/web.git
commit
382959c9a4
|
@ -7,7 +7,7 @@ Web Notify
|
||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:5939f6a4cc411dab0ff9e45a43676cbcf8ecafcd7718961aee386fefc24e189d
|
!! source digest: sha256:1a956defc8dc9d2b860d2c19783b48bc95edb7578e8178737badb6bae2b29cf6
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
|
||||||
|
@ -83,6 +83,27 @@ or
|
||||||
|
|
||||||
self.env.user.notify_default(message='My default message')
|
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:: https://raw.githubusercontent.com/OCA/web/15.0/web_notify/static/description/notifications_screenshot.gif
|
.. figure:: https://raw.githubusercontent.com/OCA/web/15.0/web_notify/static/description/notifications_screenshot.gif
|
||||||
:scale: 80 %
|
:scale: 80 %
|
||||||
:alt: Sample notifications
|
:alt: Sample notifications
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
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
|
||||||
|
from odoo.addons.web.controllers.main import clean_action
|
||||||
|
|
||||||
DEFAULT_MESSAGE = "Default message"
|
DEFAULT_MESSAGE = "Default message"
|
||||||
|
|
||||||
|
@ -48,9 +49,10 @@ class ResUsers(models.Model):
|
||||||
sticky=False,
|
sticky=False,
|
||||||
target=None,
|
target=None,
|
||||||
html=False,
|
html=False,
|
||||||
|
action=None,
|
||||||
):
|
):
|
||||||
title = title or _("Success")
|
title = title or _("Success")
|
||||||
self._notify_channel(SUCCESS, message, title, sticky, target, html)
|
self._notify_channel(SUCCESS, message, title, sticky, target, html, action)
|
||||||
|
|
||||||
def notify_danger(
|
def notify_danger(
|
||||||
self,
|
self,
|
||||||
|
@ -59,9 +61,10 @@ class ResUsers(models.Model):
|
||||||
sticky=False,
|
sticky=False,
|
||||||
target=None,
|
target=None,
|
||||||
html=False,
|
html=False,
|
||||||
|
action=None,
|
||||||
):
|
):
|
||||||
title = title or _("Danger")
|
title = title or _("Danger")
|
||||||
self._notify_channel(DANGER, message, title, sticky, target, html)
|
self._notify_channel(DANGER, message, title, sticky, target, html, action)
|
||||||
|
|
||||||
def notify_warning(
|
def notify_warning(
|
||||||
self,
|
self,
|
||||||
|
@ -70,9 +73,10 @@ class ResUsers(models.Model):
|
||||||
sticky=False,
|
sticky=False,
|
||||||
target=None,
|
target=None,
|
||||||
html=False,
|
html=False,
|
||||||
|
action=None,
|
||||||
):
|
):
|
||||||
title = title or _("Warning")
|
title = title or _("Warning")
|
||||||
self._notify_channel(WARNING, message, title, sticky, target, html)
|
self._notify_channel(WARNING, message, title, sticky, target, html, action)
|
||||||
|
|
||||||
def notify_info(
|
def notify_info(
|
||||||
self,
|
self,
|
||||||
|
@ -81,9 +85,10 @@ class ResUsers(models.Model):
|
||||||
sticky=False,
|
sticky=False,
|
||||||
target=None,
|
target=None,
|
||||||
html=False,
|
html=False,
|
||||||
|
action=None,
|
||||||
):
|
):
|
||||||
title = title or _("Information")
|
title = title or _("Information")
|
||||||
self._notify_channel(INFO, message, title, sticky, target, html)
|
self._notify_channel(INFO, message, title, sticky, target, html, action)
|
||||||
|
|
||||||
def notify_default(
|
def notify_default(
|
||||||
self,
|
self,
|
||||||
|
@ -92,9 +97,10 @@ class ResUsers(models.Model):
|
||||||
sticky=False,
|
sticky=False,
|
||||||
target=None,
|
target=None,
|
||||||
html=False,
|
html=False,
|
||||||
|
action=None,
|
||||||
):
|
):
|
||||||
title = title or _("Default")
|
title = title or _("Default")
|
||||||
self._notify_channel(DEFAULT, message, title, sticky, target, html)
|
self._notify_channel(DEFAULT, message, title, sticky, target, html, action)
|
||||||
|
|
||||||
def _notify_channel(
|
def _notify_channel(
|
||||||
self,
|
self,
|
||||||
|
@ -104,6 +110,7 @@ class ResUsers(models.Model):
|
||||||
sticky=False,
|
sticky=False,
|
||||||
target=None,
|
target=None,
|
||||||
html=False,
|
html=False,
|
||||||
|
action=None,
|
||||||
):
|
):
|
||||||
if not (self.env.user._is_admin() or self.env.su) and any(
|
if not (self.env.user._is_admin() or self.env.su) and any(
|
||||||
user.id != self.env.uid for user in self
|
user.id != self.env.uid for user in self
|
||||||
|
@ -113,12 +120,15 @@ class ResUsers(models.Model):
|
||||||
)
|
)
|
||||||
if not target:
|
if not target:
|
||||||
target = self.env.user.partner_id
|
target = self.env.user.partner_id
|
||||||
|
if action:
|
||||||
|
action = clean_action(action, self.env)
|
||||||
bus_message = {
|
bus_message = {
|
||||||
"type": type_message,
|
"type": type_message,
|
||||||
"message": message,
|
"message": message,
|
||||||
"title": title,
|
"title": title,
|
||||||
"sticky": sticky,
|
"sticky": sticky,
|
||||||
"html": html,
|
"html": html,
|
||||||
|
"action": action,
|
||||||
}
|
}
|
||||||
|
|
||||||
notifications = [[partner, "web.notify", [bus_message]] for partner in target]
|
notifications = [[partner, "web.notify", [bus_message]] for partner in target]
|
||||||
|
|
|
@ -29,6 +29,27 @@ or
|
||||||
|
|
||||||
self.env.user.notify_default(message='My default message')
|
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
|
.. figure:: static/description/notifications_screenshot.gif
|
||||||
:scale: 80 %
|
:scale: 80 %
|
||||||
:alt: Sample notifications
|
:alt: Sample notifications
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -366,7 +367,7 @@ ul.auto-toc {
|
||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:5939f6a4cc411dab0ff9e45a43676cbcf8ecafcd7718961aee386fefc24e189d
|
!! source digest: sha256:1a956defc8dc9d2b860d2c19783b48bc95edb7578e8178737badb6bae2b29cf6
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||||
<p><a class="reference external image-reference" 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 image-reference" 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 image-reference" href="https://github.com/OCA/web/tree/15.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 image-reference" href="https://translation.odoo-community.org/projects/web-15-0/web-15-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 image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=15.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
<p><a class="reference external image-reference" 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 image-reference" 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 image-reference" href="https://github.com/OCA/web/tree/15.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 image-reference" href="https://translation.odoo-community.org/projects/web-15-0/web-15-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 image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=15.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-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>
|
||||||
|
@ -419,6 +420,21 @@ Two kinds of notification are supported.</p>
|
||||||
<pre class="code python literal-block">
|
<pre class="code python literal-block">
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">notify_default</span><span class="p">(</span><span class="n">message</span><span class="o">=</span><span class="s1">'My default message'</span><span class="p">)</span>
|
<span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">notify_default</span><span class="p">(</span><span class="n">message</span><span class="o">=</span><span class="s1">'My default message'</span><span class="p">)</span>
|
||||||
</pre>
|
</pre>
|
||||||
|
<p>The notifications can bring interactivity with some buttons.</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>One allowing to refresh the active view</li>
|
||||||
|
<li>Another allowing to send a window / client action</li>
|
||||||
|
</ul>
|
||||||
|
<p>The reload button is activated when sending the notification with:</p>
|
||||||
|
<p>The action can be used using the <tt class="docutils literal">action</tt> keyword:</p>
|
||||||
|
<pre class="code python literal-block">
|
||||||
|
<span class="n">action</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="p">[</span><span class="s2">"ir.actions.act_window"</span><span class="p">]</span><span class="o">.</span><span class="n">_for_xml_id</span><span class="p">(</span><span class="s1">'sale.action_orders'</span><span class="p">)</span><span class="w">
|
||||||
|
</span> <span class="n">action</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="w">
|
||||||
|
</span> <span class="s1">'res_id'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">,</span><span class="w">
|
||||||
|
</span> <span class="s1">'views'</span><span class="p">:</span> <span class="p">[(</span><span class="kc">False</span><span class="p">,</span> <span class="s1">'form'</span><span class="p">)],</span><span class="w">
|
||||||
|
</span> <span class="p">})</span><span class="w">
|
||||||
|
</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">notify_info</span><span class="p">(</span><span class="s1">'My information message'</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="n">action</span><span class="p">)</span>
|
||||||
|
</pre>
|
||||||
<div class="figure">
|
<div class="figure">
|
||||||
<img alt="Sample notifications" src="https://raw.githubusercontent.com/OCA/web/15.0/web_notify/static/description/notifications_screenshot.gif" />
|
<img alt="Sample notifications" src="https://raw.githubusercontent.com/OCA/web/15.0/web_notify/static/description/notifications_screenshot.gif" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,30 +1,43 @@
|
||||||
/** @odoo-module **/
|
/** @odoo-module **/
|
||||||
|
import {Markup} from "web.utils";
|
||||||
import {browser} from "@web/core/browser/browser";
|
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: ["notification"],
|
dependencies: ["notification", "action"],
|
||||||
|
|
||||||
start(env, {notification}) {
|
start(env, {notification, action}) {
|
||||||
let webNotifTimeouts = {};
|
let webNotifTimeouts = {};
|
||||||
/**
|
/**
|
||||||
* Displays the web notification on user's screen
|
* Displays the web notification on user's screen
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function displaywebNotification(notifications) {
|
function displaywebNotification(notifications) {
|
||||||
Object.values(webNotifTimeouts).forEach((notif) =>
|
Object.values(webNotifTimeouts).forEach((notif) =>
|
||||||
browser.clearTimeout(notif)
|
browser.clearTimeout(notif)
|
||||||
);
|
);
|
||||||
webNotifTimeouts = {};
|
webNotifTimeouts = {};
|
||||||
|
|
||||||
notifications.forEach(function (notif) {
|
notifications.forEach(function (notif) {
|
||||||
browser.setTimeout(function () {
|
browser.setTimeout(function () {
|
||||||
notification.add(notif.message, {
|
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,
|
title: notif.title,
|
||||||
type: notif.type,
|
type: notif.type,
|
||||||
sticky: notif.sticky,
|
sticky: notif.sticky,
|
||||||
className: notif.className,
|
className: notif.className,
|
||||||
messageIsHtml: notif.html,
|
messageIsHtml: notif.html,
|
||||||
|
buttons: buttons,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,6 +19,7 @@ class TestResUsers(common.TransactionCase):
|
||||||
"title": "title",
|
"title": "title",
|
||||||
"sticky": True,
|
"sticky": True,
|
||||||
"html": False,
|
"html": False,
|
||||||
|
"action": None,
|
||||||
}
|
}
|
||||||
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
|
||||||
|
@ -36,6 +37,7 @@ class TestResUsers(common.TransactionCase):
|
||||||
"title": "title",
|
"title": "title",
|
||||||
"sticky": True,
|
"sticky": True,
|
||||||
"html": False,
|
"html": False,
|
||||||
|
"action": None,
|
||||||
}
|
}
|
||||||
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
|
||||||
|
@ -53,6 +55,7 @@ class TestResUsers(common.TransactionCase):
|
||||||
"title": "title",
|
"title": "title",
|
||||||
"sticky": True,
|
"sticky": True,
|
||||||
"html": False,
|
"html": False,
|
||||||
|
"action": None,
|
||||||
}
|
}
|
||||||
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
|
||||||
|
@ -70,6 +73,7 @@ class TestResUsers(common.TransactionCase):
|
||||||
"title": "title",
|
"title": "title",
|
||||||
"sticky": True,
|
"sticky": True,
|
||||||
"html": False,
|
"html": False,
|
||||||
|
"action": None,
|
||||||
}
|
}
|
||||||
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
|
||||||
|
@ -87,6 +91,7 @@ class TestResUsers(common.TransactionCase):
|
||||||
"title": "title",
|
"title": "title",
|
||||||
"sticky": True,
|
"sticky": True,
|
||||||
"html": False,
|
"html": False,
|
||||||
|
"action": None,
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue