Merge pull request #2764 from SchrodingersGat/notification-settings

Notification settings
This commit is contained in:
Oliver 2022-03-21 09:29:38 +11:00 committed by GitHub
commit 27b55eb8f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 62 additions and 13 deletions

View File

@ -1200,6 +1200,13 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
'validator': bool, 'validator': bool,
}, },
'NOTIFICATION_SEND_EMAILS': {
'name': _('Enable email notifications'),
'description': _('Allow sending of emails for event notifications'),
'default': True,
'validator': bool,
},
"LABEL_INLINE": { "LABEL_INLINE": {
'name': _('Inline label display'), 'name': _('Inline label display'),
'description': _('Display PDF labels in the browser, instead of downloading as a file'), 'description': _('Display PDF labels in the browser, instead of downloading as a file'),

View File

@ -8,15 +8,19 @@ from allauth.account.models import EmailAddress
from InvenTree.helpers import inheritors from InvenTree.helpers import inheritors
from InvenTree.ready import isImportingData from InvenTree.ready import isImportingData
from common.models import NotificationEntry, NotificationMessage from common.models import NotificationEntry, NotificationMessage
from common.models import InvenTreeUserSetting
import InvenTree.tasks import InvenTree.tasks
logger = logging.getLogger('inventree') logger = logging.getLogger('inventree')
# region notification classes
# region base classes
class NotificationMethod: class NotificationMethod:
"""
Base class for notification methods
"""
METHOD_NAME = '' METHOD_NAME = ''
CONTEXT_BUILTIN = ['name', 'message', ] CONTEXT_BUILTIN = ['name', 'message', ]
CONTEXT_EXTRA = [] CONTEXT_EXTRA = []
@ -95,10 +99,8 @@ class SingleNotificationMethod(NotificationMethod):
class BulkNotificationMethod(NotificationMethod): class BulkNotificationMethod(NotificationMethod):
def send_bulk(self): def send_bulk(self):
raise NotImplementedError('The `send` method must be overriden!') raise NotImplementedError('The `send` method must be overriden!')
# endregion
# region implementations
class EmailNotification(BulkNotificationMethod): class EmailNotification(BulkNotificationMethod):
METHOD_NAME = 'mail' METHOD_NAME = 'mail'
CONTEXT_EXTRA = [ CONTEXT_EXTRA = [
@ -108,13 +110,26 @@ class EmailNotification(BulkNotificationMethod):
] ]
def get_targets(self): def get_targets(self):
"""
Return a list of target email addresses,
only for users which allow email notifications
"""
allowed_users = []
for user in self.targets:
allows_emails = InvenTreeUserSetting.get_setting('NOTIFICATION_SEND_EMAILS', user=user)
if allows_emails:
allowed_users.append(user)
return EmailAddress.objects.filter( return EmailAddress.objects.filter(
user__in=self.targets, user__in=allowed_users,
) )
def send_bulk(self): def send_bulk(self):
html_message = render_to_string(self.context['template']['html'], self.context) html_message = render_to_string(self.context['template']['html'], self.context)
targets = self.targets.values_list('email', flat=True) targets = self.get_targets().values_list('email', flat=True)
InvenTree.tasks.send_email(self.context['template']['subject'], '', targets, html_message=html_message) InvenTree.tasks.send_email(self.context['template']['subject'], '', targets, html_message=html_message)
@ -137,20 +152,20 @@ class UIMessageNotification(SingleNotificationMethod):
message=self.context['message'], message=self.context['message'],
) )
return True return True
# endregion
# endregion
def trigger_notifaction(obj, category=None, obj_ref='pk', targets=None, target_fnc=None, target_args=[], target_kwargs={}, context={}): def trigger_notifaction(obj, category=None, obj_ref='pk', targets=None, target_fnc=None, target_args=[], target_kwargs={}, context={}):
""" """
Send out an notification Send out a notification
""" """
# check if data is importet currently
# Check if data is importing currently
if isImportingData(): if isImportingData():
return return
# Resolve objekt reference # Resolve objekt reference
obj_ref_value = getattr(obj, obj_ref) obj_ref_value = getattr(obj, obj_ref)
# Try with some defaults # Try with some defaults
if not obj_ref_value: if not obj_ref_value:
obj_ref_value = getattr(obj, 'pk') obj_ref_value = getattr(obj, 'pk')

View File

@ -10,7 +10,7 @@
{% endblock %} {% endblock %}
{% block actions %} {% block actions %}
<div class='btn btn-secondary' type='button' id='mark-all' title='{% trans "Mark all as read" %}'> <div class='btn btn-outline-secondary' type='button' id='mark-all' title='{% trans "Mark all as read" %}'>
<span class='fa fa-bookmark'></span> {% trans "Mark all as read" %} <span class='fa fa-bookmark'></span> {% trans "Mark all as read" %}
</div> </div>
<div class='btn btn-secondary' type='button' id='inbox-refresh' title='{% trans "Refresh Pending Notifications" %}'> <div class='btn btn-secondary' type='button' id='inbox-refresh' title='{% trans "Refresh Pending Notifications" %}'>

View File

@ -126,8 +126,12 @@ $("#mark-all").on('click', function() {
{ {
read: false, read: false,
}, },
{
success: function(response) {
updateNotificationTables();
}
}
); );
updateNotificationTables();
}); });
loadNotificationTable("#history-table", { loadNotificationTable("#history-table", {

View File

@ -22,6 +22,7 @@
{% include "InvenTree/settings/user_settings.html" %} {% include "InvenTree/settings/user_settings.html" %}
{% include "InvenTree/settings/user_homepage.html" %} {% include "InvenTree/settings/user_homepage.html" %}
{% include "InvenTree/settings/user_search.html" %} {% include "InvenTree/settings/user_search.html" %}
{% include "InvenTree/settings/user_notifications.html" %}
{% include "InvenTree/settings/user_labels.html" %} {% include "InvenTree/settings/user_labels.html" %}
{% include "InvenTree/settings/user_reports.html" %} {% include "InvenTree/settings/user_reports.html" %}
{% include "InvenTree/settings/user_display.html" %} {% include "InvenTree/settings/user_display.html" %}

View File

@ -14,6 +14,8 @@
{% include "sidebar_item.html" with label='user-home' text=text icon="fa-home" %} {% include "sidebar_item.html" with label='user-home' text=text icon="fa-home" %}
{% trans "Search Settings" as text %} {% trans "Search Settings" as text %}
{% include "sidebar_item.html" with label='user-search' text=text icon="fa-search" %} {% include "sidebar_item.html" with label='user-search' text=text icon="fa-search" %}
{% trans "Notifications" as text %}
{% include "sidebar_item.html" with label='user-notifications' text=text icon="fa-bell" %}
{% trans "Label Printing" as text %} {% trans "Label Printing" as text %}
{% include "sidebar_item.html" with label='user-labels' text=text icon="fa-tag" %} {% include "sidebar_item.html" with label='user-labels' text=text icon="fa-tag" %}
{% trans "Reporting" as text %} {% trans "Reporting" as text %}

View File

@ -0,0 +1,20 @@
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block label %}user-notifications{% endblock label %}
{% block heading %}{% trans "Notification Settings" %}{% endblock heading %}
{% block content %}
<div class='row'>
<table class='table table-striped table-condensed'>
<tbody>
{% include "InvenTree/settings/setting.html" with key="NOTIFICATION_SEND_EMAILS" icon='fa-envelope' user_setting=True %}
</tbody>
</table>
</div>
{% endblock content %}

View File

@ -253,7 +253,7 @@ function openNotificationPanel() {
{ {
success: function(response) { success: function(response) {
if (response.length == 0) { if (response.length == 0) {
html = `<p class='text-muted'>{% trans "No unread notifications" %}</p>`; html = `<p class='text-muted'><em>{% trans "No unread notifications" %}</em><span class='fas fa-check-circle icon-green float-right'></span></p>`;
} else { } else {
// build up items // build up items
response.forEach(function(item, index) { response.forEach(function(item, index) {