SciPost Code Repository

Skip to content
Snippets Groups Projects
models.py 4.78 KiB
Newer Older
__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"


Jorran de Wit's avatar
Jorran de Wit committed
from django.db import models
from django.core.urlresolvers import reverse
Jorran de Wit's avatar
Jorran de Wit committed
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey

from .constants import NOTIFICATION_TYPES
Jorran de Wit's avatar
Jorran de Wit committed
from .managers import NotificationQuerySet


class FakeActors(models.Model):
    """
    This Model acts as a surrogate person that either is unknown, deceased, fake, etc. etc.
    """
    name = models.CharField(max_length=256)

    def __str__(self):
        return self.name


Jorran de Wit's avatar
Jorran de Wit committed
class Notification(models.Model):
    """
    Action model describing the actor acting out a verb (on an optional
    target).
    Nomenclature based on http://activitystrea.ms/specs/atom/1.0/
    Generalized Format::
        <actor> <verb> <time>
        <actor> <verb> <target> <time>
        <actor> <verb> <action_object> <target> <time>
    Examples::
        <justquick> <reached level 60> <1 minute ago>
        <brosner> <commented on> <pinax/pinax> <2 hours ago>
        <washingtontimes> <started follow> <justquick> <8 minutes ago>
        <mitsuhiko> <closed> <issue 70> on <mitsuhiko/flask> <about 2 hours ago>
    Unicode Representation::
        justquick reached level 60 1 minute ago
        mitsuhiko closed issue 70 on mitsuhiko/flask 3 hours ago
    """
    LEVELS = (('success', 'Success'), ('info', 'Info'), ('warning', 'Warning'), ('error', 'Error'))
    level = models.CharField(choices=LEVELS, default='info', max_length=20)

    recipient = models.ForeignKey(settings.AUTH_USER_MODEL, blank=False,
                                  related_name='notifications')
    unread = models.BooleanField(default=True)
Jorran de Wit's avatar
Jorran de Wit committed
    pseudo_unread = models.BooleanField(default=True)  # Used to keep notification-bg "active"
Jorran de Wit's avatar
Jorran de Wit committed

    actor_content_type = models.ForeignKey(ContentType, related_name='notify_actor')
    actor_object_id = models.CharField(max_length=255)
    actor = GenericForeignKey('actor_content_type', 'actor_object_id')

    verb = models.CharField(max_length=255)
    description = models.TextField(blank=True, null=True)

    target_content_type = models.ForeignKey(ContentType, related_name='notify_target',
                                            blank=True, null=True)
    target_object_id = models.CharField(max_length=255, blank=True, null=True)
    target = GenericForeignKey('target_content_type', 'target_object_id')

    action_object_content_type = models.ForeignKey(ContentType, blank=True, null=True,
                                                   related_name='notify_action_object')
    action_object_object_id = models.CharField(max_length=255, blank=True, null=True)
    action_object = GenericForeignKey('action_object_content_type', 'action_object_object_id')

Jorran de Wit's avatar
Jorran de Wit committed
    created = models.DateTimeField(auto_now_add=True)
Jorran de Wit's avatar
Jorran de Wit committed
    url_code = models.CharField(max_length=255)  # Fake

    # This field is for internal use only. It is used to prevent duplicate sending
    # of notifications.
    internal_type = models.CharField(max_length=255, blank=True, choices=NOTIFICATION_TYPES)
Jorran de Wit's avatar
Jorran de Wit committed

    objects = NotificationQuerySet.as_manager()

    class Meta:
        ordering = ('-created', )

Jorran de Wit's avatar
Jorran de Wit committed
        ctx = {
            'actor': self.actor,
            'verb': self.verb,
            'action_object': self.action_object,
            'target': self.target,
            'timesince': self.timesince()
        }
        if self.target:
            if self.action_object:
                return u'%(actor)s %(verb)s %(action_object)s on %(target)s %(timesince)s ago' % ctx
            return u'%(actor)s %(verb)s %(target)s %(timesince)s ago' % ctx
        if self.action_object:
            return u'%(actor)s %(verb)s %(action_object)s %(timesince)s ago' % ctx
        return u'%(actor)s %(verb)s %(timesince)s ago' % ctx

    def get_absolute_url(self):
        return reverse('notifications:forward', args=(self.slug,))

Jorran de Wit's avatar
Jorran de Wit committed
    def timesince(self, now=None):
        """
        Shortcut for the ``django.utils.timesince.timesince`` function of the
        current timestamp.
        """
        from django.utils.timesince import timesince as timesince_
Jorran de Wit's avatar
Jorran de Wit committed
        return timesince_(self.created, now)
Jorran de Wit's avatar
Jorran de Wit committed

    @property
    def slug(self):
        from .utils import id2slug
        return id2slug(self.id)

Jorran de Wit's avatar
Jorran de Wit committed
    def mark_toggle(self):
Jorran de Wit's avatar
Jorran de Wit committed
        if self.pseudo_unread:
            self.mark_as_read()
Jorran de Wit's avatar
Jorran de Wit committed
        else:
            self.mark_as_unread()
Jorran de Wit's avatar
Jorran de Wit committed

Jorran de Wit's avatar
Jorran de Wit committed
    def mark_as_read(self):
Jorran de Wit's avatar
Jorran de Wit committed
        if self.unread or self.pseudo_unread:
            Notification.objects.filter(id=self.id).update(unread=False, pseudo_unread=False)
Jorran de Wit's avatar
Jorran de Wit committed

    def mark_as_unread(self):
Jorran de Wit's avatar
Jorran de Wit committed
        if not self.unread or not self.pseudo_unread:
            Notification.objects.filter(id=self.id).update(unread=True, pseudo_unread=True)