Browse Source
[12.0] web_notify: improve popup UI (#1231)
[12.0] web_notify: improve popup UI (#1231)
* [ADD]: all available bootstrap notifications (success/danger/warning/info/default) * [IMP] use black color for text for default notification. * [FIX] reverted require string for `bus.Longpolling` and rename `on_message_received` to `on_message` to prevent collisions.pull/1198/head
Shepilov Vladislav
6 years ago
committed by
Simone Orsi
15 changed files with 310 additions and 107 deletions
-
10web_notify/README.rst
-
1web_notify/__init__.py
-
2web_notify/__manifest__.py
-
1web_notify/models/__init__.py
-
99web_notify/models/res_users.py
-
3web_notify/readme/CONTRIBUTORS.rst
-
9web_notify/readme/DESCRIPTION.rst
-
2web_notify/readme/INSTALL.rst
-
26web_notify/readme/USAGE.rst
-
85web_notify/static/src/js/web_client.js
-
26web_notify/static/src/js/widgets/notification.js
-
24web_notify/static/src/scss/webclient.scss
-
103web_notify/tests/test_res_users.py
-
22web_notify/views/res_users_demo.xml
-
4web_notify/views/web_notify.xml
@ -1,3 +1,4 @@ |
|||||
|
# pylint: disable=missing-docstring |
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from . import models |
from . import models |
@ -1,3 +1,4 @@ |
|||||
|
# pylint: disable=missing-docstring |
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from . import res_users |
from . import res_users |
@ -1,46 +1,87 @@ |
|||||
|
# pylint: disable=missing-docstring |
||||
# 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 |
||||
|
|
||||
|
DEFAULT_MESSAGE = "Default message" |
||||
|
|
||||
|
SUCCESS = "success" |
||||
|
DANGER = "danger" |
||||
|
WARNING = "warning" |
||||
|
INFO = "info" |
||||
|
DEFAULT = "default" |
||||
|
|
||||
|
|
||||
class ResUsers(models.Model): |
class ResUsers(models.Model): |
||||
_inherit = 'res.users' |
|
||||
|
_inherit = "res.users" |
||||
|
|
||||
@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 |
res_id = record.id |
||||
record.notify_info_channel_name = 'notify_info_%s' % res_id |
|
||||
record.notify_warning_channel_name = 'notify_warning_%s' % res_id |
|
||||
|
record.notify_success_channel_name = "notify_success_%s" % res_id |
||||
|
record.notify_danger_channel_name = "notify_danger_%s" % res_id |
||||
|
record.notify_warning_channel_name = "notify_warning_%s" % res_id |
||||
|
record.notify_info_channel_name = "notify_info_%s" % res_id |
||||
|
record.notify_default_channel_name = "notify_default_%s" % res_id |
||||
|
|
||||
|
notify_success_channel_name = fields.Char(compute="_compute_channel_names") |
||||
|
notify_danger_channel_name = fields.Char(compute="_compute_channel_names") |
||||
|
notify_warning_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") |
||||
|
|
||||
|
def notify_success( |
||||
|
self, message="Default message", title=None, sticky=False |
||||
|
): |
||||
|
title = title or _("Success") |
||||
|
self._notify_channel(SUCCESS, message, title, sticky) |
||||
|
|
||||
notify_info_channel_name = fields.Char( |
|
||||
compute='_compute_channel_names') |
|
||||
notify_warning_channel_name = fields.Char( |
|
||||
compute='_compute_channel_names') |
|
||||
|
def notify_danger( |
||||
|
self, message="Default message", title=None, sticky=False |
||||
|
): |
||||
|
title = title or _("Danger") |
||||
|
self._notify_channel(DANGER, message, title, sticky) |
||||
|
|
||||
|
def notify_warning( |
||||
|
self, message="Default message", title=None, sticky=False |
||||
|
): |
||||
|
title = title or _("Warning") |
||||
|
self._notify_channel(WARNING, message, title, sticky) |
||||
|
|
||||
def notify_info(self, message="Default message", title=None, sticky=False): |
def notify_info(self, message="Default message", title=None, sticky=False): |
||||
title = title or _('Information') |
|
||||
self._notify_channel( |
|
||||
'notify_info_channel_name', message, title, sticky) |
|
||||
|
|
||||
def notify_warning(self, message="Default message", |
|
||||
title=None, sticky=False): |
|
||||
title = title or _('Warning') |
|
||||
self._notify_channel( |
|
||||
'notify_warning_channel_name', message, title, sticky) |
|
||||
|
|
||||
def _notify_channel(self, channel_name_field, message, title, sticky): |
|
||||
if (not self.env.user._is_admin() |
|
||||
and any(user.id != self.env.uid for user in self)): |
|
||||
|
title = title or _("Information") |
||||
|
self._notify_channel(INFO, message, title, sticky) |
||||
|
|
||||
|
def notify_default( |
||||
|
self, message="Default message", title=None, sticky=False |
||||
|
): |
||||
|
title = title or _("Default") |
||||
|
self._notify_channel(DEFAULT, message, title, sticky) |
||||
|
|
||||
|
def _notify_channel( |
||||
|
self, |
||||
|
type_message=DEFAULT, |
||||
|
message=DEFAULT_MESSAGE, |
||||
|
title=None, |
||||
|
sticky=False, |
||||
|
): |
||||
|
# pylint: disable=protected-access |
||||
|
if not self.env.user._is_admin() and any( |
||||
|
user.id != self.env.uid for user in self |
||||
|
): |
||||
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) |
||||
bus_message = { |
bus_message = { |
||||
'message': message, |
|
||||
'title': title, |
|
||||
'sticky': sticky |
|
||||
|
"type": type_message, |
||||
|
"message": message, |
||||
|
"title": title, |
||||
|
"sticky": sticky, |
||||
} |
} |
||||
notifications = [(record[channel_name_field], bus_message) |
|
||||
for record in self] |
|
||||
self.env['bus.bus'].sendmany(notifications) |
|
||||
|
notifications = [ |
||||
|
(record[channel_name_field], bus_message) for record in self |
||||
|
] |
||||
|
self.env["bus.bus"].sendmany(notifications) |
@ -1,3 +1,4 @@ |
|||||
* Laurent Mignon <laurent.mignon@acsone.eu> |
* Laurent Mignon <laurent.mignon@acsone.eu> |
||||
* Serpent Consulting Services Pvt. Ltd.<jay.vora@serpentcs.com> |
* Serpent Consulting Services Pvt. Ltd.<jay.vora@serpentcs.com> |
||||
* Aitor Bouzas <aitor.bouzas@adaptivecity.com> |
|
||||
|
* Aitor Bouzas <aitor.bouzas@adaptivecity.com> |
||||
|
* Shepilov Vladislav <shepilov.v@protonmail.com> |
@ -1,7 +1,10 @@ |
|||||
Send instant notification messages to the user in live. |
Send instant notification messages to the user in live. |
||||
|
|
||||
This technical module allows you to send instant notification messages from the server to the user in live. |
|
||||
|
This technical module allows you to send instant notification messages from the server to the user in live. |
||||
Two kinds of notification are supported. |
Two kinds of notification are supported. |
||||
|
|
||||
* Warning: Displayed in a red flying popup div |
|
||||
* Information: Displayed in a light yellow flying popup div |
|
||||
|
* Success: Displayed in a `success` theme color flying popup div |
||||
|
* Danger: Displayed in a `danger` theme color flying popup div |
||||
|
* Warning: Displayed in a `warning` theme color flying popup div |
||||
|
* Information: Displayed in a `info` theme color flying popup div |
||||
|
* Default: Displayed in a `default` theme color flying popup div |
@ -1 +1 @@ |
|||||
This module is based on the Instant Messaging Bus. To work properly, the server must be launched in gevent mode. |
|
||||
|
This module is based on the Instant Messaging Bus. To work properly, the server must be launched in gevent mode. |
@ -1,44 +1,53 @@ |
|||||
odoo.define('web_notify.WebClient', function (require) { |
odoo.define('web_notify.WebClient', function (require) { |
||||
"use strict"; |
|
||||
|
"use strict"; |
||||
|
|
||||
var WebClient = require('web.WebClient'); |
|
||||
var base_bus = require('bus.Longpolling'); |
|
||||
var session = require('web.session'); |
|
||||
require('bus.BusService'); |
|
||||
|
var WebClient = require('web.WebClient'); |
||||
|
var base_bus = require('bus.Longpolling'); |
||||
|
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_warning = 'notify_warning_' + session.uid; |
|
||||
this.channel_info = 'notify_info_' + session.uid; |
|
||||
this.call('bus_service', 'addChannel', this.channel_warning); |
|
||||
this.call('bus_service', 'addChannel', this.channel_info); |
|
||||
this.call('bus_service', 'on', 'notification', this, this.bus_notification); |
|
||||
this.call('bus_service', 'startPolling'); |
|
||||
}, |
|
||||
bus_notification: function(notifications) { |
|
||||
var self = this; |
|
||||
_.each(notifications, function (notification) { |
|
||||
var channel = notification[0]; |
|
||||
var message = notification[1]; |
|
||||
if (channel === self.channel_warning) { |
|
||||
self.on_message_warning(message); |
|
||||
} else if (channel === self.channel_info) { |
|
||||
self.on_message_info(message); |
|
||||
} |
|
||||
}); |
|
||||
}, |
|
||||
on_message_warning: function(message){ |
|
||||
this.do_warn(message.title, message.message, message.sticky); |
|
||||
}, |
|
||||
on_message_info: function(message){ |
|
||||
this.do_notify(message.title, message.message, message.sticky); |
|
||||
} |
|
||||
}); |
|
||||
|
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.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); |
||||
|
this.call('bus_service', 'startPolling'); |
||||
|
}, |
||||
|
bus_notification: function (notifications) { |
||||
|
var self = this; |
||||
|
_.each(notifications, function (notification) { |
||||
|
// Not used: var channel = notification[0];
|
||||
|
var message = notification[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, |
||||
|
} |
||||
|
); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
}); |
}); |
@ -0,0 +1,26 @@ |
|||||
|
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; |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
}); |
@ -0,0 +1,24 @@ |
|||||
|
.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'); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -1,8 +1,12 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<template id="assets_backend" name="web_notify assets" inherit_id="web.assets_backend"> |
<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"> |
<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/web_client.js"/> |
||||
|
<script type="text/javascript" src="/web_notify/static/src/js/widgets/notification.js"/> |
||||
</xpath> |
</xpath> |
||||
</template> |
</template> |
||||
</odoo> |
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue