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). |
|||
|
|||
from . import models |
@ -1,3 +1,4 @@ |
|||
# pylint: disable=missing-docstring |
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
|||
|
|||
from . import res_users |
@ -1,46 +1,87 @@ |
|||
# pylint: disable=missing-docstring |
|||
# Copyright 2016 ACSONE SA/NV |
|||
# 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): |
|||
_inherit = 'res.users' |
|||
_inherit = "res.users" |
|||
|
|||
@api.depends('create_date') |
|||
@api.depends("create_date") |
|||
def _compute_channel_names(self): |
|||
for record in self: |
|||
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): |
|||
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( |
|||
_('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 = { |
|||
'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> |
|||
* 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. |
|||
|
|||
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. |
|||
|
|||
* 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) { |
|||
"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"?> |
|||
<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> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue