142 lines
5.5 KiB
Python
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)}
|