user notification settings

This commit is contained in:
Matthias 2022-04-04 23:46:19 +02:00
parent 2fee6b02db
commit 1eb511e8a0
No known key found for this signature in database
GPG Key ID: F50EF5741D33E076
9 changed files with 153 additions and 3 deletions

View File

@ -265,6 +265,12 @@ class BaseInvenTreeSetting(models.Model):
filters['plugin'] = plugin filters['plugin'] = plugin
kwargs['plugin'] = plugin kwargs['plugin'] = plugin
# Filter by method
method = kwargs.get('method', None)
if method is not None:
filters['method'] = method
try: try:
setting = settings.filter(**filters).first() setting = settings.filter(**filters).first()
except (ValueError, cls.DoesNotExist): except (ValueError, cls.DoesNotExist):

View File

@ -5,6 +5,7 @@ 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 plugin import registry from plugin import registry
from plugin.models import NotificationUserSetting
logger = logging.getLogger('inventree') logger = logging.getLogger('inventree')
@ -20,6 +21,7 @@ class NotificationMethod:
CONTEXT_BUILTIN = ['name', 'message', ] CONTEXT_BUILTIN = ['name', 'message', ]
CONTEXT_EXTRA = [] CONTEXT_EXTRA = []
GLOBAL_SETTING = None GLOBAL_SETTING = None
USER_SETTING = None
def __init__(self, obj, category, targets, context) -> None: def __init__(self, obj, category, targets, context) -> None:
# Check if a sending fnc is defined # Check if a sending fnc is defined
@ -127,10 +129,33 @@ class BulkNotificationMethod(NotificationMethod):
class MethodStorageClass: class MethodStorageClass:
liste = None liste = None
user_settings = {}
def collect(self): def collect(self):
storage.liste = inheritors(NotificationMethod) - IGNORED_NOTIFICATION_CLS storage.liste = inheritors(NotificationMethod) - IGNORED_NOTIFICATION_CLS
def get_usersettings(self, user):
methods = []
for item in storage.liste:
if item.USER_SETTING:
new_key = f'NOTIFICATION_METHOD_{item.METHOD_NAME.upper()}'
# make sure the setting exists
self.user_settings[new_key] = item.USER_SETTING
NotificationUserSetting.get_setting(
key=new_key,
user=user,
method=item.METHOD_NAME,
)
# save definition
methods.append({
'key': new_key,
'icon': 'envelope',
'method': item.METHOD_NAME,
})
return methods
IGNORED_NOTIFICATION_CLS = set([ IGNORED_NOTIFICATION_CLS = set([
SingleNotificationMethod, SingleNotificationMethod,

View File

@ -27,7 +27,7 @@ import InvenTree.helpers
from common.models import InvenTreeSetting, ColorTheme, InvenTreeUserSetting from common.models import InvenTreeSetting, ColorTheme, InvenTreeUserSetting
from common.settings import currency_code_default from common.settings import currency_code_default
from plugin.models import PluginSetting from plugin.models import PluginSetting, NotificationUserSetting
register = template.Library() register = template.Library()
@ -306,6 +306,9 @@ def setting_object(key, *args, **kwargs):
return PluginSetting.get_setting_object(key, plugin=plugin) return PluginSetting.get_setting_object(key, plugin=plugin)
if 'method' in kwargs:
return NotificationUserSetting.get_setting_object(key, user=kwargs['user'], method=kwargs['method'])
if 'user' in kwargs: if 'user' in kwargs:
return InvenTreeUserSetting.get_setting_object(key, user=kwargs['user']) return InvenTreeUserSetting.get_setting_object(key, user=kwargs['user'])

View File

@ -42,6 +42,11 @@ class CoreNotificationsPlugin(SettingsMixin, IntegrationPluginBase):
('template', 'subject', ), ('template', 'subject', ),
] ]
GLOBAL_SETTING = 'ENABLE_NOTIFICATION_EMAILS' GLOBAL_SETTING = 'ENABLE_NOTIFICATION_EMAILS'
USER_SETTING = {
'name': _('Enable email notifications'),
'description': _('Allow sending of emails for event notifications'),
'default': True,
'validator': bool,
} }
def get_targets(self): def get_targets(self):

View File

@ -0,0 +1,29 @@
# Generated by Django 3.2.12 on 2022-04-03 23:38
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('plugin', '0004_alter_pluginsetting_key'),
]
operations = [
migrations.CreateModel(
name='NotificationUserSetting',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('key', models.CharField(help_text='Settings key (must be unique - case insensitive)', max_length=50)),
('value', models.CharField(blank=True, help_text='Settings value', max_length=200)),
('method', models.CharField(max_length=255, verbose_name='Method')),
('user', models.ForeignKey(blank=True, help_text='User', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'unique_together': {('method', 'user', 'key')},
},
),
]

View File

@ -7,6 +7,7 @@ from __future__ import unicode_literals
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
from django.contrib.auth.models import User
import common.models import common.models
@ -182,3 +183,71 @@ class PluginSetting(common.models.BaseInvenTreeSetting):
verbose_name=_('Plugin'), verbose_name=_('Plugin'),
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
class NotificationUserSetting(common.models.BaseInvenTreeSetting):
"""
This model represents notification settings for a user
"""
class Meta:
unique_together = [
('method', 'user', 'key'),
]
def clean(self, **kwargs):
kwargs['method'] = self.method
super().clean(**kwargs)
"""
We override the following class methods,
so that we can pass the method instance
"""
def is_bool(self, **kwargs):
kwargs['method'] = self.method
return super().is_bool(**kwargs)
@property
def name(self):
return self.__class__.get_setting_name(self.key, method=self.method)
@property
def default_value(self):
return self.__class__.get_setting_default(self.key, method=self.method)
@property
def description(self):
return self.__class__.get_setting_description(self.key, method=self.method)
@property
def units(self):
return self.__class__.get_setting_units(self.key, method=self.method)
def choices(self):
return self.__class__.get_setting_choices(self.key, method=self.method)
@classmethod
def get_setting_definition(cls, key, method, **kwargs):
from common.notifications import storage
kwargs['settings'] = storage.user_settings
return super().get_setting_definition(key, **kwargs)
method = models.CharField(
max_length=255,
verbose_name=_('Method'),
)
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
blank=True, null=True,
verbose_name=_('User'),
help_text=_('User'),
)

View File

@ -8,7 +8,7 @@ from django.urls import reverse
from common.models import InvenTreeSetting from common.models import InvenTreeSetting
from plugin import registry from plugin import registry
from common.notifications import storage
register = template.Library() register = template.Library()
@ -73,3 +73,10 @@ def plugin_errors(*args, **kwargs):
All plugin errors in the current session All plugin errors in the current session
""" """
return registry.errors return registry.errors
@register.simple_tag(takes_context=True)
def notification_settings_list(context, *args, **kwargs):
"""
List of all user notification settings
"""
return storage.get_usersettings(user=context.get('user', None))

View File

@ -5,6 +5,8 @@
{% setting_object key plugin=plugin as setting %} {% setting_object key plugin=plugin as setting %}
{% elif user_setting %} {% elif user_setting %}
{% setting_object key user=request.user as setting %} {% setting_object key user=request.user as setting %}
{% elif notification_setting %}
{% setting_object key method=method user=request.user as setting %}
{% else %} {% else %}
{% setting_object key as setting %} {% setting_object key as setting %}
{% endif %} {% endif %}

View File

@ -2,6 +2,7 @@
{% load i18n %} {% load i18n %}
{% load inventree_extras %} {% load inventree_extras %}
{% load plugin_extras %}
{% block label %}user-notifications{% endblock label %} {% block label %}user-notifications{% endblock label %}
@ -12,7 +13,10 @@
<div class='row'> <div class='row'>
<table class='table table-striped table-condensed'> <table class='table table-striped table-condensed'>
<tbody> <tbody>
{% include "InvenTree/settings/setting.html" with key="NOTIFICATION_SEND_EMAILS" icon='fa-envelope' user_setting=True %} {% notification_settings_list as settings %}
{% for setting in settings %}
{% include "InvenTree/settings/setting.html" with key=setting.key icon=setting.icon method=setting.method notification_setting=True %}
{% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>