Ajout des notifications
This commit is contained in:
parent
0c7c408e40
commit
15a4d38ea0
|
@ -26,8 +26,9 @@ from app import models # IDK why this is here, but it works
|
|||
from app.models.comment import Comment
|
||||
from app.models.thread import Thread
|
||||
from app.models.forum import Forum
|
||||
from app.models.notification import Notification
|
||||
from app.routes import index, search, users # To load routes at initialization
|
||||
from app.routes.account import login, account
|
||||
from app.routes.account import login, account, notification
|
||||
from app.routes.admin import index, groups, account, trophies
|
||||
from app.utils import pluralize # To use pluralize into the templates
|
||||
from app.utils import is_title
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
shoutbox-kick shoutbox-ban
|
||||
unlimited-pms footer-statistics community-login
|
||||
access-admin-panel edit-account delete-account edit-trophies
|
||||
delete_notification
|
||||
-
|
||||
name: Modérateur
|
||||
css: "color: green"
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
from app import db
|
||||
from datetime import datetime
|
||||
|
||||
class Notification(db.Model):
|
||||
""" A long-term `flash` notification. It is deleted when watched """
|
||||
__tablename__ = 'notification'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
||||
text = db.Column(db.UnicodeText)
|
||||
href = db.Column(db.UnicodeText)
|
||||
date = db.Column(db.DateTime, default=datetime.now())
|
||||
|
||||
owner_id = db.Column(db.Integer, db.ForeignKey('member.id'), nullable=False)
|
||||
|
||||
def __init__(self, owner_id, text, href=None):
|
||||
""" Check weather or not the id is valid before creating the notif! """
|
||||
self.text = text
|
||||
self.href = href
|
||||
self.owner_id = owner_id
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Notification to {self.owner.name}: {self.text} ({self.href})>'
|
|
@ -5,7 +5,9 @@ from flask_login import UserMixin
|
|||
from app.models.privs import SpecialPrivilege, Group, GroupMember, \
|
||||
GroupPrivilege
|
||||
from app.models.trophies import Trophy, TrophyMember
|
||||
from app.models.notification import Notification
|
||||
import app.utils.unicode_names as unicode_names
|
||||
from app.utils.notify import notify
|
||||
from config import V5Config
|
||||
|
||||
import werkzeug.security
|
||||
|
@ -96,6 +98,7 @@ class Member(User):
|
|||
newsletter = db.Column(db.Boolean, default=False)
|
||||
|
||||
# Relations
|
||||
notifications = db.relationship('Notification', backref="owner", lazy=True)
|
||||
trophies = db.relationship('Trophy', secondary=TrophyMember,
|
||||
back_populates='owners')
|
||||
|
||||
|
@ -207,6 +210,14 @@ class Member(User):
|
|||
return werkzeug.security.check_password_hash(self.password_hash,
|
||||
password)
|
||||
|
||||
def notify(self, message, href=None):
|
||||
""" Notify a user with a message.
|
||||
An hyperlink can be added to redirect to the notification source """
|
||||
|
||||
n = Notification(self.id, message, href=href)
|
||||
db.session.add(n)
|
||||
db.session.commit()
|
||||
|
||||
def add_trophy(self, t):
|
||||
"""
|
||||
Add a trophy to the current user. Check whether the request sender has
|
||||
|
@ -218,8 +229,7 @@ class Member(User):
|
|||
t = Trophy.query.filter_by(name=t).first()
|
||||
if t not in self.trophies:
|
||||
self.trophies.append(t)
|
||||
# TODO: implement the notification system
|
||||
# self.notify(f"Vous venez de débloquer le trophée '{t.name}'")
|
||||
self.notify(f"Vous avez débloqué le trophée '{t.name}'")
|
||||
|
||||
def del_trophy(self, t):
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
from flask import redirect, url_for, request, flash
|
||||
from flask_login import login_required, current_user
|
||||
from app import app, db
|
||||
from app.models.notification import Notification
|
||||
from app.utils.render import render
|
||||
|
||||
|
||||
@app.route('/notifications', methods=['GET'])
|
||||
@login_required
|
||||
def list_notifications():
|
||||
notifications = current_user.notifications
|
||||
return render('account/notifications.html', notifications=notifications)
|
||||
|
||||
|
||||
@app.route('/notifications/delete/<id>', methods=['GET'])
|
||||
@login_required
|
||||
def delete_notification(id=None):
|
||||
if type(id) == int:
|
||||
notification = Notification.query.get(id)
|
||||
if notification:
|
||||
# Only current user or admin can delete notifications
|
||||
if notification.owner_id == current_user.id:
|
||||
db.session.delete(notification)
|
||||
db.session.commit()
|
||||
return redirect(url_for('list_notifications'))
|
||||
elif 'delete_notification' in current_user.privs:
|
||||
db.session.delete(notification)
|
||||
db.session.commit()
|
||||
# TODO: change this redirection
|
||||
return redirect(url_for('list_notifications'))
|
||||
else:
|
||||
abort(403)
|
||||
abort(404)
|
||||
elif id == "all":
|
||||
for n in current_user.notifications:
|
||||
db.session.delete(n)
|
||||
db.session.commit()
|
||||
return redirect(url_for('list_notifications'))
|
||||
# TODO: add something to allow an admin to delete all notifs for a user
|
||||
# with a GET parameter
|
||||
else:
|
||||
abort(404)
|
|
@ -1,4 +1,5 @@
|
|||
from flask import flash, redirect, url_for
|
||||
from flask_login import current_user
|
||||
from wtforms import BooleanField
|
||||
from app.utils.priv_required import priv_required
|
||||
from app.models.users import Member
|
||||
|
@ -6,6 +7,7 @@ from app.models.trophies import Trophy
|
|||
from app.forms.account import AdminUpdateAccountForm, AdminDeleteAccountForm, \
|
||||
AdminAccountEditTrophyForm
|
||||
from app.utils.render import render
|
||||
from app.utils.notify import notify
|
||||
from app import app, db
|
||||
|
||||
|
||||
|
@ -47,6 +49,7 @@ def adm_edit_account(user_id):
|
|||
db.session.merge(user)
|
||||
db.session.commit()
|
||||
# TODO: send an email to member saying his account has been modified
|
||||
user.notify(f"Vos informations personnelles ont été modifiées par {current_user.name}.")
|
||||
flash('Modifications effectuées', 'ok')
|
||||
else:
|
||||
flash('Erreur lors de la modification', 'error')
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
{% extends "base/base.html" %}
|
||||
|
||||
{% block title %}
|
||||
<h1>Notifications</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
{% if notifications %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Notification</th>
|
||||
<th><a href="{{ url_for('delete_notification', id='all') }}">Tout supprimer</a></th>
|
||||
</tr>
|
||||
{% for n in notifications %}
|
||||
<tr>
|
||||
<td>{{ n.date.strftime('Le %Y-%m-%d à %H:%M') }}</td>
|
||||
<td>
|
||||
{% if n.href %}<a href="{{ n.href }}">{% endif %}
|
||||
{{ n.text }}
|
||||
{% if n.href %}</a>{% endif %}
|
||||
</td>
|
||||
<td><a href="{{ url_for('delete_notification', id=n.id)}}">Supprimer</a>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
Aucune notification.
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -6,7 +6,7 @@
|
|||
<a href="{{ url_for('user', username=current_user.name) }}">
|
||||
{{ current_user.name }}</a>
|
||||
</h2>
|
||||
<a href="#">
|
||||
<a href="{{ url_for('list_notifications') }}">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path fill="#ffffff" d="M20,2A2,2 0 0,1 22,4V16A2,2 0 0,1 20,18H6L2,22V4C2,2.89 2.9,2 4,2H20M4,4V17.17L5.17,16H20V4H4M6,7H18V9H6V7M6,11H15V13H6V11Z"></path>
|
||||
</svg>Notifications
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
from app import db
|
||||
from app.models.notification import Notification
|
||||
# from app.models.users import Member
|
||||
|
||||
def notify(user, message, href=None):
|
||||
""" Notify a user (by id, name or object reference) with a message.
|
||||
An hyperlink can be added to redirect to the notification source """
|
||||
|
||||
# Cuz' duck typing is quite cool
|
||||
# TODO: maybe abort if no user is found
|
||||
if type(user) == str:
|
||||
user = Member.query.filter_by(name=user).first()
|
||||
if isinstance(user, Member):
|
||||
user = user.id
|
||||
if user and Member.query.get(user):
|
||||
n = Notification(user, message, href=href)
|
||||
db.session.add(n)
|
||||
db.session.commit()
|
||||
else:
|
||||
print("User not found")
|
|
@ -0,0 +1,36 @@
|
|||
"""Ajout des notifications
|
||||
|
||||
Revision ID: ebca7362eb22
|
||||
Revises: e3b140752719
|
||||
Create Date: 2019-09-01 11:36:25.962212
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'ebca7362eb22'
|
||||
down_revision = 'e3b140752719'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('notification',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('text', sa.UnicodeText(), nullable=True),
|
||||
sa.Column('href', sa.UnicodeText(), nullable=True),
|
||||
sa.Column('date', sa.DateTime(), nullable=True),
|
||||
sa.Column('owner_id', sa.Integer(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['owner_id'], ['member.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('notification')
|
||||
# ### end Alembic commands ###
|
Loading…
Reference in New Issue