Allow users to list their notifications

This is in very early stage, but at least it works.
This commit is contained in:
Gergely Polonkai 2018-07-09 08:32:27 +02:00
parent f1fab33c8d
commit 379a5b1bb0
3 changed files with 116 additions and 9 deletions

View File

@ -288,4 +288,16 @@ class CalendarSocialApp(Flask):
return redirect(url_for('display_profile', username=username)) return redirect(url_for('display_profile', username=username))
@staticmethod
@route('/notifications')
def notifications():
from .models import Notification
if current_user.is_authenticated:
notifs = Notification.query.filter(Notification.profile == current_user.profile)
else:
notifs = []
return render_template('notifications.html', notifs=notifs)
app = CalendarSocialApp(__name__) app = CalendarSocialApp(__name__)

View File

@ -18,6 +18,7 @@
""" """
from datetime import datetime from datetime import datetime
from enum import Enum
from warnings import warn from warnings import warn
from flask_babelex import lazy_gettext from flask_babelex import lazy_gettext
@ -41,6 +42,24 @@ def generate_uuid():
return uuid4().hex return uuid4().hex
def _(translate): # pylint: disable=invalid-name
"""Function to mark strings as translatable
The actual translation will be fetched later in `:meth:AuditLog.get_message`.
"""
return translate
class NotificationAction(Enum):
follow = 1
notification_action_messages = {
NotificationAction.follow: (_('%(actor)s followed you'), _('%(actor)s followed %(item)s'))
}
class SettingsProxy: class SettingsProxy:
"""Proxy object to get settings for a user """Proxy object to get settings for a user
""" """
@ -184,6 +203,15 @@ class Profile(db.Model): # pylint: disable=too-few-public-methods
#: The display name #: The display name
display_name = db.Column(db.Unicode(length=80), nullable=False) display_name = db.Column(db.Unicode(length=80), nullable=False)
@property
def fqdn(self):
ret = ''
if self.user:
return f'@{self.user.username}'
return f'@{self.username}@{self.domain}'
def __repr__(self): def __repr__(self):
if self.user: if self.user:
username = self.user.username username = self.user.username
@ -194,6 +222,16 @@ class Profile(db.Model): # pylint: disable=too-few-public-methods
return f'<Profile {self.id}(@{username}{domain})>' return f'<Profile {self.id}(@{username}{domain})>'
def __str__(self):
ret = ''
if self.display_name:
ret = self.display_name + ' '
ret += f'({self.fqdn})'
return ret
@property @property
def followed_list(self): def followed_list(self):
"""List of profiles this profile is following """List of profiles this profile is following
@ -313,15 +351,6 @@ class UserSetting(db.Model): # pylint: disable=too-few-public-methods
return f'<UserSetting of {self.user}, {self.key}="{self.value}">' return f'<UserSetting of {self.user}, {self.key}="{self.value}">'
def _(translate): # pylint: disable=invalid-name
"""Function to mark strings as translatable
The actual translation will be fetched later in `:meth:AuditLog.get_message`.
"""
return translate
class AuditLog(db.Model): class AuditLog(db.Model):
"""Database model for audit log records """Database model for audit log records
""" """
@ -442,3 +471,62 @@ class UserFollow(db.Model):
#: The timestamp when the follow was accepted #: The timestamp when the follow was accepted
accepted_at = db.Column(db.DateTime(), nullable=True) accepted_at = db.Column(db.DateTime(), nullable=True)
class Notification(db.Model):
"""Database model for notifications
"""
__tablename__ = 'notifications'
# pylint: disable=invalid-name
id = db.Column(db.Integer(), primary_key=True)
#: The recipient of the notification
profile_id = db.Column(db.Integer(), db.ForeignKey('profiles.id'), nullable=False)
profile = db.relationship('Profile',
backref=db.backref('notifications', lazy='dynamic'),
foreign_keys=[profile_id])
#: The profile that generated the notification
actor_id = db.Column(db.Integer(), db.ForeignKey('profiles.id'), nullable=True)
actor = db.relationship('Profile', foreign_keys=[actor_id])
#: The item (e.g. event) that generated the notification
item_id = db.Column(db.Integer(), nullable=True)
#: The type of the item that generated the notification
item_type = db.Column(db.String(length=40))
#: The type of action
action = db.Column(db.Enum(NotificationAction))
#: The timestamp when the notification was created
created_at = db.Column(db.DateTime(), default=datetime.utcnow, nullable=False)
#: The timestamp when the notification was read
read_at = db.Column(db.DateTime(), nullable=True)
@property
def item(self):
item_class = self._decl_class_registry.get(self.item_type)
if item_class is None:
warn(f'Unknown item type {self.item_type}')
return None
return item_class.query.get(self.item_id)
@property
def message(self):
"""Get the translated message for ``key``
"""
from flask_security import current_user
messages = notification_action_messages.get(self.action)
message = messages[0 if self.item == current_user.profile else 1]
return lazy_gettext(message, actor=self.actor, item=self.item)

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% block content %}
{% for notif in notifs %}
{{ notif.message }}<br>
{% endfor %}
{% endblock content %}