diff options
-rw-r--r-- | apioforum/db.py | 9 | ||||
-rw-r--r-- | apioforum/forum.py | 22 | ||||
-rw-r--r-- | apioforum/read.py | 12 | ||||
-rw-r--r-- | apioforum/static/style.css | 12 | ||||
-rw-r--r-- | apioforum/templates/view_forum.html | 4 | ||||
-rw-r--r-- | apioforum/thread.py | 7 |
6 files changed, 64 insertions, 2 deletions
diff --git a/apioforum/db.py b/apioforum/db.py index 24146e2..2d06a13 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -233,6 +233,15 @@ CREATE VIEW public_posts AS JOIN forum_thread_of_post h ON p.id=h.p_id JOIN public_forums b ON b.id=h.f_id; """, +""" +CREATE TABLE read ( + user NOT NULL REFERENCES users(username), + forum REFERENCES forums(id), + thread REFERENCES threads(id), + time TIMESTAMP NOT NULL +); +ALTER TABLE forums ADD COLUMN updated TIMESTAMP; +""", ] diff --git a/apioforum/forum.py b/apioforum/forum.py index 988c9a5..289cc40 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -11,6 +11,7 @@ from .db import get_db from .mdrender import render from .roles import get_forum_roles,has_permission,is_bureaucrat,get_user_role, permissions as role_permissions from .permissions import is_admin +from . import read from sqlite3 import OperationalError import datetime import math @@ -89,6 +90,18 @@ def requires_bureaucrat(f): return f(forum, *args, **kwargs) return wrapper +def set_updated(forum_id): + db = get_db() + ancestors = db.execute(""" + WITH RECURSIVE fs AS + (SELECT * FROM forums WHERE id = ? + UNION ALL + SELECT forums.* FROM forums, fs WHERE fs.parent=forums.id) + SELECT * FROM fs; + """,(forum_id,)).fetchall() + for f in ancestors: + db.execute("UPDATE forums SET updated = current_timestamp WHERE id = ?;", (f['id'],)) + db.commit() @forum_route("",pagination=True) @requires_permission("p_view_forum", login_required=False) @@ -218,6 +231,13 @@ def view_forum(forum,page=1): WHERE role = 'bureaucrat' AND forum = ? """,(forum['id'],)).fetchall() bureaucrats = [b[0] for b in bureaucrats] + + + if g.user != None: + db.execute("DELETE FROM read WHERE user = ? AND forum = ?;", (g.user, forum['id'])) + db.execute("INSERT INTO read (user,forum,time) VALUES (?,?,current_timestamp);", (g.user, forum['id'])) + db.commit() + return render_template("view_forum.html", forum=forum, @@ -231,6 +251,7 @@ def view_forum(forum,page=1): page=page, current_sortby=sortby, tagfilter_tag=tagfilter_tag, + is_read=read.is_read, ) @forum_route("create_thread",methods=("GET","POST")) @@ -266,6 +287,7 @@ def create_thread(forum): (thread_id,g.user,content) ) db.commit() + set_updated(forum['id']) from . import webhooks thread = db.execute("select * from threads where id = ?",(thread_id,)).fetchone() diff --git a/apioforum/read.py b/apioforum/read.py new file mode 100644 index 0000000..289b40e --- /dev/null +++ b/apioforum/read.py @@ -0,0 +1,12 @@ +from flask import g +from .db import get_db + +def is_read(type, id): + if g.user == None: + return False + db = get_db() + read = db.execute("SELECT * FROM read WHERE user = ? AND " + type + " = ?;", (g.user, id)).fetchone() + if read == None: + return False + updated = db.execute("SELECT * FROM " + type + "s WHERE id = ?;", (id,)).fetchone()['updated'] + return updated == None or read['time'] >= updated diff --git a/apioforum/static/style.css b/apioforum/static/style.css index 3d6ec22..c77ec69 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -7,6 +7,7 @@ body { font-family: sans-serif; word-wrap: break-word; } --gray: darkgray; --light-colour: white; --username-colour: hsl(0, 0%, 25%); + --read-colour: hsl(0, 0%, 30%); --red: red; --yellow: yellow; --blue: blue; @@ -211,6 +212,16 @@ nav#pages .pageno { align-self: center; } flex-grow: 1; } +.listing-title a { + text-decoration: none; + color: var(--read-colour); +} + +.unread .listing-title a { + text-decoration: underline; + color: var(--dark-colour); +} + .thread-listing-tags { display: flex; align-items: center; @@ -359,6 +370,7 @@ textarea { --gray: lightgray; --light-colour: black; --username-colour: hsl(0, 0%, 80%); + --read-colour: hsl(0, 0%, 70%); --yellow: rgb(212, 173, 0); --blue: rgb(78, 89, 255); --visited: rgb(173, 110, 209); diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index b6b336f..d37a018 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -49,7 +49,7 @@ <div class="forum-list"> {% for subforum in subforums %} <div class="listing"> - <div class="listing-main"> + <div class="listing-main {% if not is_read('forum', subforum.id) %}unread{% endif %}"> <div class="listing-title"> <a href="{{url_for('forum.view_forum',forum_id=subforum.id)}}"> {{- subforum.name -}} @@ -130,7 +130,7 @@ you do not have permission to create threads in this forum <div class="thread-list"> {%for thread in threads%} <div class="listing"> - <div class="listing-main"> + <div class="listing-main {%if not is_read('thread', thread.id)%}unread{% endif %}"> <div class="listing-title"> <a href="{{url_for('thread.view_thread',thread_id=thread.id)}}"> <abbr title="{{ thread.title }}" style="text-decoration:none">{{- thread.title -}}</abbr> diff --git a/apioforum/thread.py b/apioforum/thread.py index 83b1adc..656d43d 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -9,6 +9,7 @@ from flask import ( from .db import get_db from .roles import has_permission from . import webhooks +from . import forum from .forum import get_avail_tags bp = Blueprint("thread", __name__, url_prefix="/thread") @@ -103,6 +104,11 @@ def view_thread(thread_id,page=1): else: v = db.execute("SELECT * FROM votes WHERE poll = ? AND user = ? AND current AND NOT is_retraction;",(poll['id'],g.user)).fetchone() has_voted = v is not None + + if g.user != None: + db.execute("DELETE FROM read WHERE user = ? AND thread = ?;", (g.user, thread_id)) + db.execute("INSERT INTO read (user,thread,time) VALUES (?,?,current_timestamp);", (g.user, thread_id)) + db.commit() return render_template( "view_thread.html", @@ -256,6 +262,7 @@ def create_post(thread_id): (thread_id,) ) db.commit() + forum.set_updated(thread['forum']) post = db.execute("select * from posts where id = ?",(post_id,)).fetchone() webhooks.do_webhooks_post(thread['forum'],post) flash("post posted postfully") |