Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] Added general setting to disable all notifications #148 #158

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions openwisp_notifications/admin.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
from django.contrib import admin

from openwisp_notifications.base.admin import NotificationSettingAdminMixin
from openwisp_notifications.base.admin import (
GeneralSettingAdminMixin,
NotificationSettingAdminMixin,
)
from openwisp_notifications.swapper import load_model
from openwisp_notifications.widgets import _add_object_notification_widget
from openwisp_users.admin import UserAdmin
from openwisp_utils.admin import AlwaysHasChangedMixin

Notification = load_model('Notification')
NotificationSetting = load_model('NotificationSetting')
GeneralSetting = load_model('GeneralSetting')


class NotificationSettingInline(
Expand All @@ -20,6 +24,12 @@ def has_change_permission(self, request, obj=None):
return request.user.is_superuser or request.user == obj


UserAdmin.inlines = [NotificationSettingInline] + UserAdmin.inlines
class GeneralSettingAdmin(
GeneralSettingAdminMixin, AlwaysHasChangedMixin, admin.TabularInline
):
model = GeneralSetting


UserAdmin.inlines = [NotificationSettingInline, GeneralSettingAdmin] + UserAdmin.inlines

_add_object_notification_widget()
9 changes: 8 additions & 1 deletion openwisp_notifications/base/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from openwisp_notifications.base.forms import NotificationSettingForm
from openwisp_notifications.base.forms import (
GeneralSettingForm,
NotificationSettingForm,
)


class NotificationSettingAdminMixin:
Expand Down Expand Up @@ -30,3 +33,7 @@ class Media:
'admin/js/jquery.init.js',
'openwisp-notifications/js/notification-settings.js',
]


class GeneralSettingAdminMixin:
form = GeneralSettingForm
8 changes: 8 additions & 0 deletions openwisp_notifications/base/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,11 @@ class Meta:
'web': widgets.CheckboxInput,
'email': widgets.CheckboxInput,
}


class GeneralSettingForm(ModelForm):
class Meta:
widgets = {
'web': widgets.CheckboxInput,
'email': widgets.CheckboxInput,
}
36 changes: 36 additions & 0 deletions openwisp_notifications/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,39 @@ class AbstractIgnoreObjectNotification(UUIDModel):
class Meta:
abstract = True
ordering = ['valid_till']


class AbstractGeneralSetting(UUIDModel):
_DISABLE_HELP = (
'Note: If Yes is selected, ' 'User will not recieve any notifications. '
)
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
web = models.BooleanField(
_('disable web notifications'),
null=True,
blank=True,
help_text=_(_DISABLE_HELP),
)
email = models.BooleanField(
_('disable email notifications'),
null=True,
blank=True,
help_text=_(_DISABLE_HELP),
)

class Meta:
abstract = True
verbose_name = _('general settings')
verbose_name_plural = verbose_name
ordering = ['user']

def __str__(self):
return '{user} - general setting'.format(user=self.user.username)

@property
def email_notification(self):
return self.email

@property
def web_notification(self):
return self.web
16 changes: 15 additions & 1 deletion openwisp_notifications/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
Notification = load_model('Notification')
NotificationSetting = load_model('NotificationSetting')
IgnoreObjectNotification = load_model('IgnoreObjectNotification')
GeneralSetting = load_model('GeneralSetting')
NotificationsAppConfig = apps.get_app_config(NotificationSetting._meta.app_label)

Group = swapper_load_model('openwisp_users', 'Group')
Expand Down Expand Up @@ -178,7 +179,12 @@ def send_email_notification(sender, instance, created, **kwargs):

if not (email_preference and instance.recipient.email):
return

try:
general_setting = instance.recipient.generalsetting
if general_setting.email_notification:
return
except GeneralSetting.DoesNotExist:
pass
try:
subject = instance.email_subject
except NotificationRenderException:
Expand Down Expand Up @@ -227,6 +233,14 @@ def clear_notification_cache(sender, instance, **kwargs):
return
# Reload notification only if notification is created or deleted
# Display when a new notification is created
try:
general_setting = instance.recipient.generalsetting
if general_setting.web_notification:
if kwargs.get('created'):
instance.delete()
return
except GeneralSetting.DoesNotExist:
pass
ws_handlers.notification_update_handler(
recipient=instance.recipient,
reload_widget=kwargs.get('created', True),
Expand Down
64 changes: 64 additions & 0 deletions openwisp_notifications/migrations/0007_generalsetting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Generated by Django 3.1.4 on 2020-12-24 08:43

import uuid

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('openwisp_notifications', '0006_objectnotification'),
]

operations = [
migrations.CreateModel(
name='GeneralSetting',
fields=[
(
'id',
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
'web',
models.BooleanField(
blank=True,
help_text='Note: If Yes is selected, User will not recieve any notifications. ',
null=True,
verbose_name='disable web notifications',
),
),
(
'email',
models.BooleanField(
blank=True,
help_text='Note: If Yes is selected, User will not recieve any notifications. ',
null=True,
verbose_name='disable email notifications',
),
),
(
'user',
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
options={
'verbose_name': 'general settings',
'verbose_name_plural': 'general settings',
'ordering': ['user'],
'abstract': False,
'swappable': 'OPENWISP_NOTIFICATIONS_GENERALSETTING_MODEL',
},
),
]
7 changes: 7 additions & 0 deletions openwisp_notifications/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from swapper import swappable_setting

from openwisp_notifications.base.models import (
AbstractGeneralSetting,
AbstractIgnoreObjectNotification,
AbstractNotification,
AbstractNotificationSetting,
Expand All @@ -26,3 +27,9 @@ class Meta(AbstractIgnoreObjectNotification.Meta):
swappable = swappable_setting(
'openwisp_notifications', 'IgnoreObjectNotification'
)


class GeneralSetting(AbstractGeneralSetting):
class Meta(AbstractGeneralSetting.Meta):
abstract = False
swappable = swappable_setting('openwisp_notifications', 'GeneralSetting')
48 changes: 48 additions & 0 deletions openwisp_notifications/tests/test_general_setting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from django.test import TestCase

from openwisp_notifications.signals import notify
from openwisp_notifications.swapper import load_model
from openwisp_users.tests.utils import TestOrganizationMixin

GeneralSetting = load_model('GeneralSetting')
Notification = load_model('Notification')
on_queryset = Notification.objects


class TestDisableNotifications(TestOrganizationMixin, TestCase):
def setUp(self):
self.admin = self._get_admin()
self.org1 = self._get_org()

def test_disable_only_email_notifications(self):
'''
notification is created and it have emailed = False
'''
GeneralSetting.objects.create(user=self.admin, email=True, web=False)
notify.send(sender=self.admin, type='default', target=self.org1)
self.assertEqual(on_queryset.count(), 1)
notification = on_queryset.all()[0]
self.assertEqual(notification.emailed, False)

def test_disable_only_web_notifications(self):
'''
notification is not created when web notifications
are disabled
'''
GeneralSetting.objects.create(user=self.admin, email=False, web=True)
notify.send(sender=self.admin, type='default', target=self.org1)
self.assertEqual(on_queryset.count(), 0)

def test_disable_all_notifications(self):
'''
notification is not created when all notifications
are disabled
'''
GeneralSetting.objects.create(user=self.admin, email=True, web=True)
notify.send(sender=self.admin, type='default', target=self.org1)
self.assertEqual(on_queryset.count(), 0)

# test when other organizations are created
org2 = self._create_org(name='test org 2', slug='test-org-2')
notify.send(sender=self.admin, type='default', target=org2)
self.assertEqual(on_queryset.count(), 0)
6 changes: 6 additions & 0 deletions tests/openwisp2/sample_notifications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
AbstractNotification,
AbstractNotificationSetting,
AbstractIgnoreObjectNotification,
AbstractGeneralSetting,
)

# Only for testing openwisp_notifications
Expand Down Expand Up @@ -41,6 +42,11 @@ class Meta(AbstractIgnoreObjectNotification.Meta):
abstract = False


class GeneralSetting(DetailsModel, AbstractGeneralSetting):
class Meta(AbstractGeneralSetting.Meta):
abstract = False


class TestApp(UUIDModel):
name = models.CharField(max_length=50)
organization = models.ForeignKey(
Expand Down