Update the Message of the day (motd) app to support organizations.

This commit is contained in:
Roberto Rosario
2016-05-30 17:51:24 -04:00
parent e943588ba2
commit aca93a0deb
12 changed files with 199 additions and 27 deletions

View File

@@ -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}
)

View File

@@ -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',

View File

@@ -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
),
),
]

View File

@@ -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
),
),
]

View 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'
),
),
]

View File

@@ -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')

View File

@@ -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()}

View 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'

View File

@@ -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)

View 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
)

View File

@@ -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'

View File

@@ -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()