combo/combo/apps/notifications/models.py

142 lines
5.5 KiB
Python

# combo - content management system
# Copyright (C) 2014-2016 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.conf import settings
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.timezone import now, localtime, timedelta
from django.db.models import Q
from combo.data.models import CellBase
from combo.data.library import register_cell_class
class NotificationManager(models.Manager):
def filter_by_id(self, id):
try:
int(id)
except (ValueError, TypeError):
search_id = Q(external_id=id)
else:
search_id = Q(pk=id) | Q(external_id=id)
return self.filter(search_id)
class Notification(models.Model):
objects = NotificationManager()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
summary = models.CharField(_('Label'), max_length=140)
body = models.TextField(_('Body'), default='', blank=True)
url = models.URLField(_('URL'), default='', blank=True)
origin = models.CharField(_('Origin'), max_length=100, blank=True)
start_timestamp = models.DateTimeField(_('Start date and time'))
end_timestamp = models.DateTimeField(_('End date and time'))
acked = models.BooleanField(_('Acked'), default=False)
external_id = models.SlugField(_('External identifier'), null=True)
class Meta:
verbose_name = _('Notification')
def __unicode__(self):
return self.summary
def public_id(self):
return self.external_id or str(self.pk)
@classmethod
def notify(cls, user, summary, id=None, body=None, url=None, origin=None,
start_timestamp=None, duration=None, end_timestamp=None):
'''
Create a new notification:
Notification.notify(user, 'summary') -> id
Create a notification with a duration of one day:
Notification.notify(user, 'summary', duration=3600*24)
Renew an existing notification, or create a new one, with an external_id:
Notification.notify(user, 'summary', id='id')
'''
created = False
# get ...
notification = Notification.objects.filter_by_id(id).filter(user=user).first() if id else None
if not notification: # ... or create
notification = Notification(user=user, summary=summary,
body=body or '', url=url or '',
external_id=id)
created = True
notification.summary = summary
notification.body = body or ''
notification.url = url or ''
notification.origin = origin or ''
notification.start_timestamp = start_timestamp or now()
if duration:
if not isinstance(duration, timedelta):
duration = timedelta(seconds=duration)
notification.end_timestamp = notification.start_timestamp + duration
else:
notification.end_timestamp = end_timestamp or notification.start_timestamp + timedelta(3)
notification.save()
if notification.external_id is None:
notification_id = '%s' % notification.pk
else:
notification_id = notification.external_id
return notification_id, created
@classmethod
def ack(cls, user, id):
Notification.objects.filter_by_id(id).filter(user=user).update(acked=True)
@classmethod
def forget(cls, user, id):
past = now() - timedelta(seconds=5)
Notification.objects.filter_by_id(id).filter(user=user).update(end_timestamp=past,
acked=True)
@register_cell_class
class NotificationsCell(CellBase):
user_dependant = True
ajax_refresh = 120
class Meta:
verbose_name = _('User Notifications')
def is_visible(self, user=None):
if user is None or not user.is_authenticated():
return False
return super(NotificationsCell, self).is_visible(user)
def get_cell_extra_context(self, context):
extra_context = super(NotificationsCell, self).get_cell_extra_context(context)
user = getattr(context.get('request'), 'user', None)
if user and user.is_authenticated():
extra_context['notifications'] = Notification.objects.filter(user=user,
start_timestamp__lte=now(), end_timestamp__gt=now()).order_by('-start_timestamp')
extra_context['new_notifications'] = extra_context['notifications'].filter(acked=False)
return extra_context
def get_badge(self, context):
user = getattr(context.get('request'), 'user', None)
if not user or not user.is_authenticated():
return
notifs = Notification.objects.filter(user=user, start_timestamp__lte=now(),
end_timestamp__gt=now())
new = notifs.filter(acked=False).count()
if not new:
return
return {'badge': str(new)}