diff --git a/app/models.py b/app/models.py index b4edcc2..e0bcb2e 100644 --- a/app/models.py +++ b/app/models.py @@ -88,8 +88,11 @@ class User(db.Model, UserMixin): display_name = db.Column(db.String(100), nullable=False, server_default="") # Content - packages = db.relationship("Package", backref="author", lazy="dynamic") - requests = db.relationship("EditRequest", backref="author", lazy="dynamic") + notifications = db.relationship("Notification", primaryjoin="User.id==Notification.user_id") + + # causednotifs = db.relationship("Notification", backref="causer", lazy="dynamic") + packages = db.relationship("Package", backref="author", lazy="dynamic") + requests = db.relationship("EditRequest", backref="author", lazy="dynamic") def __init__(self, username): import datetime @@ -119,6 +122,24 @@ class User(db.Model, UserMixin): else: raise Exception("Permission {} is not related to users".format(perm.name)) + +class Notification(db.Model): + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey("user.id")) + causer_id = db.Column(db.Integer, db.ForeignKey("user.id")) + user = db.relationship("User", foreign_keys=[user_id]) + causer = db.relationship("User", foreign_keys=[causer_id]) + + title = db.Column(db.String(100), nullable=False) + url = db.Column(db.String(200), nullable=True) + + def __init__(self, us, cau, titl, ur): + self.user = us + self.causer = cau + self.title = titl + self.url = ur + + class License(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False, unique=True) diff --git a/app/templates/base.html b/app/templates/base.html index 0ab87b4..cdf1f1f 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -40,6 +40,7 @@ +{% endblock %} diff --git a/app/views/__init__.py b/app/views/__init__.py index dba81ad..22ed5ab 100644 --- a/app/views/__init__.py +++ b/app/views/__init__.py @@ -30,4 +30,4 @@ def home_page(): packages = Package.query.filter_by(approved=True).all() return render_template("index.html", packages=packages) -from . import users, githublogin, packages, sass, tasks, admin +from . import users, githublogin, packages, sass, tasks, admin, notifications diff --git a/app/views/notifications.py b/app/views/notifications.py new file mode 100644 index 0000000..77108d7 --- /dev/null +++ b/app/views/notifications.py @@ -0,0 +1,9 @@ +from flask import * +from flask_user import current_user, login_required +from app import app +from app.models import * + +@app.route("/notifications/") +@login_required +def notifications_page(): + return render_template("notifications/list.html") diff --git a/app/views/packages.py b/app/views/packages.py index 96e50b4..bbebc67 100644 --- a/app/views/packages.py +++ b/app/views/packages.py @@ -96,6 +96,8 @@ def package_page(author, name): if shouldReturnJson(): return jsonify(package.getAsDictionary(app.config["BASE_URL"])) else: + clearNotifications(package.getDetailsURL()) + releases = getReleases(package) requests = [r for r in package.requests if r.status == 0] return render_template("packages/view.html", package=package, releases=releases, requests=requests) @@ -168,7 +170,9 @@ def create_edit_package_page(author=None, name=None): if not package: package = Package() package.author = author - # package.approved = package.checkPerm(current_user, Permission.APPROVE_NEW) + else: + triggerNotif(package.author, current_user, + "{} edited".format(package.title), package.getDetailsURL()) form.populate_obj(package) # copy to row @@ -194,8 +198,10 @@ def approve_package_page(author=None, name=None): else: package.approved = True - db.session.commit() + triggerNotif(package.author, current_user, + "{} approved".format(package.title), package.getDetailsURL()) + db.session.commit() return redirect(package.getDetailsURL()) @@ -222,6 +228,10 @@ def create_screenshot_page(author, name): ss.title = form["title"].data ss.url = uploadedPath db.session.add(ss) + + msg = "{}: Screenshot added {}" \ + .format(package.title, ss.title) + triggerNotif(package.author, current_user, msg, erequest.getURL()) db.session.commit() return redirect(package.getDetailsURL()) @@ -292,6 +302,10 @@ def create_edit_editrequest_page(pauthor, name, id=None): wasChangeMade = True if wasChangeMade: + msg = "{}: Edit request #{} {}" \ + .format(package.title, erequest.id, "created" if id is None else "edited") + triggerNotif(package.author, current_user, msg, erequest.getURL()) + triggerNotif(erequest.author, current_user, msg, erequest.getURL()) db.session.commit() return redirect(erequest.getURL()) else: @@ -311,6 +325,7 @@ def view_editrequest_page(pauthor, name, id): if erequest is None: abort(404) + clearNotifications(erequest.getURL()) return render_template("packages/editrequest_view.html", package=package, request=erequest) @@ -331,6 +346,10 @@ def approve_editrequest_page(pauthor, name, id): else: erequest.status = 1 erequest.applyAll(package) + + msg = "{}: Edit request #{} merged".format(package.title, erequest.id) + triggerNotif(erequest.author, current_user, msg, erequest.getURL()) + triggerNotif(package.author, current_user, msg, erequest.getURL()) db.session.commit() return redirect(package.getDetailsURL()) @@ -351,6 +370,10 @@ def reject_editrequest_page(pauthor, name, id): else: erequest.status = 2 + + msg = "{}: Edit request #{} rejected".format(package.title, erequest.id) + triggerNotif(erequest.author, current_user, msg, erequest.getURL()) + triggerNotif(package.author, current_user, msg, erequest.getURL()) db.session.commit() return redirect(package.getDetailsURL()) @@ -389,6 +412,9 @@ def create_release_page(author, name): db.session.commit() rel.task_id = makeVCSRelease.delay(rel.id, form["vcsLabel"].data).id + + msg = "{}: Release {} created".format(package.title, rel.title) + triggerNotif(package.author, current_user, msg, rel.getEditURL()) db.session.commit() return redirect(url_for("check_task", id=rel.task_id, r=package.getDetailsURL())) @@ -400,6 +426,9 @@ def create_release_page(author, name): rel.title = form["title"].data rel.url = uploadedPath db.session.add(rel) + + msg = "{}: Release {} created".format(package.title, rel.title) + triggerNotif(package.author, current_user, msg, erequest.getURL()) db.session.commit() return redirect(package.getDetailsURL()) @@ -420,6 +449,8 @@ def edit_release_page(author, name, id): if package.name != name or package.author.username != author: abort(404) + clearNotifications(release.getEditURL()) + canEdit = package.checkPerm(current_user, Permission.MAKE_RELEASE) canApprove = package.checkPerm(current_user, Permission.APPROVE_RELEASE) if not (canEdit or canApprove): diff --git a/app/views/utils.py b/app/views/utils.py index f22e874..345d5c1 100644 --- a/app/views/utils.py +++ b/app/views/utils.py @@ -91,3 +91,14 @@ def rank_required(rank): return decorated_function return decorator + +def triggerNotif(owner, causer, title, url): + if owner.rank.atLeast(UserRank.NEW_MEMBER) and owner != causer: + Notification.query.filter_by(user=owner, url=url).delete() + notif = Notification(owner, causer, title, url) + db.session.add(notif) + +def clearNotifications(url): + if current_user.is_authenticated: + Notification.query.filter_by(user=current_user, url=url).delete() + db.session.commit() diff --git a/setup.py b/setup.py index 81ad254..901bbc8 100644 --- a/setup.py +++ b/setup.py @@ -21,12 +21,16 @@ if not os.path.isfile("db.sqlite"): ruben.rank = UserRank.ADMIN db.session.add(ruben) + ez = User("Shara") ez.github_username = "Ezhh" ez.forums_username = "Shara" ez.rank = UserRank.EDITOR db.session.add(ez) + not1 = Notification(ruben, ez, "Awards approved", "/packages/rubenwardy/awards/") + db.session.add(not1) + jeija = User("Jeija") jeija.github_username = "Jeija" db.session.add(jeija)