Update the Message of the day (motd) app to support organizations.
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
|
||||
from organizations.managers import CurrentOrganizationManager
|
||||
|
||||
|
||||
class MessageManager(models.Manager):
|
||||
def get_for_now(self):
|
||||
@@ -9,3 +12,10 @@ class MessageManager(models.Manager):
|
||||
return self.filter(enabled=True).filter(
|
||||
Q(start_datetime__isnull=True) | Q(start_datetime__lte=now)
|
||||
).filter(Q(end_datetime__isnull=True) | Q(end_datetime__gte=now))
|
||||
|
||||
|
||||
class OrganizationMessageManager(MessageManager, CurrentOrganizationManager):
|
||||
def get_queryset(self):
|
||||
return super(OrganizationMessageManager, self).get_queryset().filter(
|
||||
**{self._get_field_name() + '__id': settings.ORGANIZATION_ID}
|
||||
)
|
||||
|
||||
@@ -13,12 +13,36 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='MessageOfTheDay',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('label', models.CharField(max_length=32, verbose_name='Label')),
|
||||
('message', models.TextField(verbose_name='Message', blank=True)),
|
||||
('enabled', models.BooleanField(default=True, verbose_name='Enabled')),
|
||||
('start_datetime', models.DateTimeField(verbose_name='Start date time', blank=True)),
|
||||
('end_datetime', models.DateTimeField(verbose_name='End date time', blank=True)),
|
||||
(
|
||||
'id', models.AutoField(
|
||||
verbose_name='ID', serialize=False, auto_created=True,
|
||||
primary_key=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'label',
|
||||
models.CharField(max_length=32, verbose_name='Label')
|
||||
),
|
||||
(
|
||||
'message',
|
||||
models.TextField(verbose_name='Message', blank=True)
|
||||
),
|
||||
(
|
||||
'enabled',
|
||||
models.BooleanField(default=True, verbose_name='Enabled')
|
||||
),
|
||||
(
|
||||
'start_datetime',
|
||||
models.DateTimeField(
|
||||
verbose_name='Start date time', blank=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'end_datetime',
|
||||
models.DateTimeField(
|
||||
verbose_name='End date time', blank=True
|
||||
)
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Message of the day',
|
||||
|
||||
@@ -14,11 +14,15 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='messageoftheday',
|
||||
name='end_datetime',
|
||||
field=models.DateTimeField(null=True, verbose_name='End date time', blank=True),
|
||||
field=models.DateTimeField(
|
||||
null=True, verbose_name='End date time', blank=True
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='messageoftheday',
|
||||
name='start_datetime',
|
||||
field=models.DateTimeField(null=True, verbose_name='Start date time', blank=True),
|
||||
field=models.DateTimeField(
|
||||
null=True, verbose_name='Start date time', blank=True
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -14,21 +14,35 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='end_datetime',
|
||||
field=models.DateTimeField(help_text='Date and time until when this message is to be displayed.', null=True, verbose_name='End date time', blank=True),
|
||||
field=models.DateTimeField(
|
||||
help_text='Date and time until when this message is to be '
|
||||
'displayed.', null=True, verbose_name='End date time',
|
||||
blank=True
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='label',
|
||||
field=models.CharField(help_text='Short description of this message.', max_length=32, verbose_name='Label'),
|
||||
field=models.CharField(
|
||||
help_text='Short description of this message.', max_length=32,
|
||||
verbose_name='Label'
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='message',
|
||||
field=models.TextField(help_text='The actual message to be displayed.', verbose_name='Message'),
|
||||
field=models.TextField(
|
||||
help_text='The actual message to be displayed.',
|
||||
verbose_name='Message'
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='start_datetime',
|
||||
field=models.DateTimeField(help_text='Date and time after which this message will be displayed.', null=True, verbose_name='Start date time', blank=True),
|
||||
field=models.DateTimeField(
|
||||
help_text='Date and time after which this message will be '
|
||||
'displayed.', null=True, verbose_name='Start date time',
|
||||
blank=True
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
24
mayan/apps/motd/migrations/0006_message_organization.py
Normal file
24
mayan/apps/motd/migrations/0006_message_organization.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import organizations.shortcuts
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('organizations', '0002_add_data_default_organization'),
|
||||
('motd', '0005_auto_20160510_0025'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='message',
|
||||
name='organization',
|
||||
field=models.ForeignKey(
|
||||
default=organizations.shortcuts.get_current_organization,
|
||||
to='organizations.Organization'
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -4,11 +4,17 @@ from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .managers import MessageManager
|
||||
from organizations.models import Organization
|
||||
from organizations.shortcuts import get_current_organization
|
||||
|
||||
from .managers import MessageManager, OrganizationMessageManager
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Message(models.Model):
|
||||
organization = models.ForeignKey(
|
||||
Organization, default=get_current_organization
|
||||
)
|
||||
label = models.CharField(
|
||||
max_length=32, help_text=_('Short description of this message.'),
|
||||
verbose_name=_('Label')
|
||||
@@ -30,6 +36,7 @@ class Message(models.Model):
|
||||
)
|
||||
|
||||
objects = MessageManager()
|
||||
on_organization = OrganizationMessageManager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Message')
|
||||
|
||||
@@ -9,4 +9,4 @@ register = Library()
|
||||
|
||||
@register.inclusion_tag('motd/messages.html')
|
||||
def motd():
|
||||
return {'messages': Message.objects.get_for_now()}
|
||||
return {'messages': Message.on_organization.get_for_now()}
|
||||
|
||||
5
mayan/apps/motd/tests/literals.py
Normal file
5
mayan/apps/motd/tests/literals.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
TEST_MESSAGE_LABEL = 'test message label'
|
||||
TEST_MESSAGE_LABEL_EDITED = 'test message label edited'
|
||||
TEST_MESSAGE_TEXT = 'test message text'
|
||||
@@ -5,20 +5,27 @@ from datetime import timedelta
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
|
||||
from organizations.models import Organization
|
||||
from organizations.utils import create_default_organization
|
||||
|
||||
from ..models import Message
|
||||
|
||||
TEST_LABEL = 'test label'
|
||||
TEST_MESSAGE = 'test message'
|
||||
from .literals import TEST_MESSAGE_LABEL, TEST_MESSAGE_TEXT
|
||||
|
||||
|
||||
class MOTDTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.motd = Message.objects.create(
|
||||
label=TEST_LABEL, message=TEST_MESSAGE
|
||||
create_default_organization()
|
||||
self.motd = Message.on_organization.create(
|
||||
label=TEST_MESSAGE_LABEL, message=TEST_MESSAGE_TEXT
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
Organization.objects.all().delete()
|
||||
Organization.objects.clear_cache()
|
||||
|
||||
def test_basic(self):
|
||||
queryset = Message.objects.get_for_now()
|
||||
queryset = Message.on_organization.get_for_now()
|
||||
|
||||
self.assertEqual(queryset.exists(), True)
|
||||
|
||||
@@ -26,7 +33,7 @@ class MOTDTestCase(TestCase):
|
||||
self.motd.start_datetime = timezone.now() - timedelta(days=1)
|
||||
self.motd.save()
|
||||
|
||||
queryset = Message.objects.get_for_now()
|
||||
queryset = Message.on_organization.get_for_now()
|
||||
|
||||
self.assertEqual(queryset.first(), self.motd)
|
||||
|
||||
@@ -35,7 +42,7 @@ class MOTDTestCase(TestCase):
|
||||
self.motd.end_datetime = timezone.now() - timedelta(days=1)
|
||||
self.motd.save()
|
||||
|
||||
queryset = Message.objects.get_for_now()
|
||||
queryset = Message.on_organization.get_for_now()
|
||||
|
||||
self.assertEqual(queryset.exists(), False)
|
||||
|
||||
@@ -43,6 +50,6 @@ class MOTDTestCase(TestCase):
|
||||
self.motd.enabled = False
|
||||
self.motd.save()
|
||||
|
||||
queryset = Message.objects.get_for_now()
|
||||
queryset = Message.on_organization.get_for_now()
|
||||
|
||||
self.assertEqual(queryset.exists(), False)
|
||||
|
||||
67
mayan/apps/motd/tests/test_organization_views.py
Normal file
67
mayan/apps/motd/tests/test_organization_views.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from organizations.tests.test_organization_views import OrganizationViewTestCase
|
||||
|
||||
from ..models import Message
|
||||
|
||||
from .literals import (
|
||||
TEST_MESSAGE_LABEL, TEST_MESSAGE_LABEL_EDITED, TEST_MESSAGE_TEXT
|
||||
)
|
||||
|
||||
|
||||
class MessageOrganizationViewTestCase(OrganizationViewTestCase):
|
||||
def create_message(self):
|
||||
with self.settings(ORGANIZATION_ID=self.organization_a.pk):
|
||||
self.message = Message.on_organization.create(
|
||||
label=TEST_MESSAGE_LABEL, message=TEST_MESSAGE_TEXT
|
||||
)
|
||||
|
||||
def test_message_create_view(self):
|
||||
# Create a message for organization A
|
||||
with self.settings(ORGANIZATION_ID=self.organization_a.pk):
|
||||
response = self.post(
|
||||
'motd:message_create', data={
|
||||
'label': TEST_MESSAGE_LABEL, 'message': TEST_MESSAGE_TEXT
|
||||
}
|
||||
)
|
||||
self.assertNotContains(response, text='danger', status_code=302)
|
||||
self.assertEqual(Message.on_organization.count(), 1)
|
||||
|
||||
with self.settings(ORGANIZATION_ID=self.organization_b.pk):
|
||||
self.assertEqual(Message.on_organization.count(), 0)
|
||||
|
||||
def test_message_delete_view(self):
|
||||
# Create a message for organization A
|
||||
self.create_message()
|
||||
|
||||
with self.settings(ORGANIZATION_ID=self.organization_b.pk):
|
||||
response = self.post(
|
||||
'motd:message_delete', args=(self.message.pk,)
|
||||
)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_message_edit_view(self):
|
||||
# Create a message for organization A
|
||||
self.create_message()
|
||||
|
||||
with self.settings(ORGANIZATION_ID=self.organization_b.pk):
|
||||
# Make sure admin for organization B cannot edit the message
|
||||
response = self.post(
|
||||
'motd:message_edit', args=(self.message.pk,), data={
|
||||
'label': TEST_MESSAGE_LABEL_EDITED
|
||||
}
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_message_messageged_item_list_view(self):
|
||||
# Create a message for organization A
|
||||
self.create_message()
|
||||
|
||||
with self.settings(ORGANIZATION_ID=self.organization_b.pk):
|
||||
# Make sure admin for organization B cannot find the message for
|
||||
# organization A
|
||||
response = self.get('motd:message_list')
|
||||
self.assertNotContains(
|
||||
response, text=self.message.label, status_code=200
|
||||
)
|
||||
@@ -10,7 +10,9 @@ urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^list/$', MessageListView.as_view(), name='message_list'),
|
||||
url(r'^create/$', MessageCreateView.as_view(), name='message_create'),
|
||||
url(r'^(?P<pk>\d+)/edit/$', MessageEditView.as_view(), name='message_edit'),
|
||||
url(
|
||||
r'^(?P<pk>\d+)/edit/$', MessageEditView.as_view(), name='message_edit'
|
||||
),
|
||||
url(
|
||||
r'^(?P<pk>\d+)/delete/$', MessageDeleteView.as_view(),
|
||||
name='message_delete'
|
||||
|
||||
@@ -21,7 +21,6 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class MessageCreateView(SingleObjectCreateView):
|
||||
fields = ('label', 'message', 'enabled', 'start_datetime', 'end_datetime')
|
||||
model = Message
|
||||
view_permission = permission_message_create
|
||||
|
||||
def get_extra_context(self):
|
||||
@@ -29,9 +28,11 @@ class MessageCreateView(SingleObjectCreateView):
|
||||
'title': _('Create message'),
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
return Message.on_organization.all()
|
||||
|
||||
|
||||
class MessageDeleteView(SingleObjectDeleteView):
|
||||
model = Message
|
||||
object_permission = permission_message_delete
|
||||
post_action_redirect = reverse_lazy('motd:message_list')
|
||||
|
||||
@@ -42,10 +43,12 @@ class MessageDeleteView(SingleObjectDeleteView):
|
||||
'title': _('Delete the message: %s?') % self.get_object(),
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
return Message.on_organization.all()
|
||||
|
||||
|
||||
class MessageEditView(SingleObjectEditView):
|
||||
fields = ('label', 'message', 'enabled', 'start_datetime', 'end_datetime')
|
||||
model = Message
|
||||
object_permission = permission_message_edit
|
||||
post_action_redirect = reverse_lazy('motd:message_list')
|
||||
|
||||
@@ -55,9 +58,11 @@ class MessageEditView(SingleObjectEditView):
|
||||
'title': _('Edit message: %s') % self.get_object(),
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
return Message.on_organization.all()
|
||||
|
||||
|
||||
class MessageListView(SingleObjectListView):
|
||||
model = Message
|
||||
object_permission = permission_message_view
|
||||
|
||||
def get_extra_context(self):
|
||||
@@ -65,3 +70,6 @@ class MessageListView(SingleObjectListView):
|
||||
'hide_link': True,
|
||||
'title': _('Messages'),
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
return Message.on_organization.all()
|
||||
|
||||
Reference in New Issue
Block a user