From 53590c7544f15d5b8afa3e5e27e47b51a6ed7904 Mon Sep 17 00:00:00 2001 From: raven Date: Sun, 1 Nov 2026 23:29:08 -0600 Subject: add support for "wiki page" thread type a thread has a type, which may be "thread" or "wiki page." if the type is wiki page, then its first post becomes editable by other people. additionally, each edit is now tracked in the database. --- apioforum/db.py | 25 ++++++++++ apioforum/forum.py | 23 +++++++-- apioforum/roles.py | 1 + apioforum/static/style.css | 4 ++ apioforum/templates/common.html | 29 ++++++----- apioforum/templates/config_thread.html | 19 ++++---- apioforum/templates/edit_permissions.html | 2 + apioforum/templates/edit_post.html | 8 +++- apioforum/templates/view_thread.html | 80 ++++++++++++++++++------------- apioforum/thread.py | 33 ++++++++++++- 10 files changed, 165 insertions(+), 59 deletions(-) diff --git a/apioforum/db.py b/apioforum/db.py index ead4e5a..9dcf1ee 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -261,6 +261,31 @@ ALTER TABLE users ADD COLUMN banreason TEXT; """ ALTER TABLE threads ADD COLUMN locked INT NOT NULL DEFAULT 0; """, +""" +ALTER TABLE threads ADD COLUMN type TEXT NOT NULL DEFAULT "thread"; +ALTER TABLE posts ADD COLUMN wiki INT NOT NULL DEFAULT 0; +ALTER TABLE posts ADD COLUMN updated_by_others INT NOT NULL DEFAULT 0; +CREATE TABLE revisions ( + post NOT NULL REFERENCES posts(id), + id INTEGER PRIMARY KEY, + author NOT NULL REFERENCES users(username), + content TEXT NOT NULL, + time TIMESTAMP, + comment TEXT +); +CREATE TABLE wiki_pages ( + path TEXT NOT NULL, + forum NOT NULL REFERENCES forums(id), + thread REFERENCES threads(id), + type TEXT NOT NULL DEFAULT "page", + PRIMARY KEY (path, forum) +); +ALTER TABLE role_config ADD COLUMN p_edit_wiki INT NOT NULL DEFAULT 1 +""", +""" +INSERT INTO revisions (post, author, content, time) + SELECT id, author, content, updated FROM posts; +""", ] diff --git a/apioforum/forum.py b/apioforum/forum.py index a955ed5..b731a24 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -280,9 +280,17 @@ def create_thread(forum): if forum is None: flash("that forum doesn't exist") return redirect(url_for('index')) + + if "type" in request.args: + thread_type = request.args["type"] + else: + thread_type = "thread" + thread_type = thread_type.replace('_', " ") + if thread_type != "thread" and thread_type != "wiki page": + abort(404) if g.user is None: - flash("you need to be logged in to create a thread") + flash("you need to be logged in to create a " + thread_type) return redirect(url_for('index')) if request.method == "POST": @@ -298,15 +306,21 @@ def create_thread(forum): lock = int(request.form.get('lock','0')) cur = db.cursor() cur.execute( - """INSERT INTO threads (title,creator,created,updated,forum,locked) - VALUES (?,?,current_timestamp,current_timestamp,?,?);""", - (title,g.user,forum['id'],lock) + """INSERT INTO threads (title,creator,created,updated,forum,locked,type) + VALUES (?,?,current_timestamp,current_timestamp,?,?,?);""", + (title,g.user,forum['id'],lock,thread_type) ) thread_id = cur.lastrowid cur.execute( "INSERT INTO posts (thread,created,author,content) VALUES (?,current_timestamp,?,?);", (thread_id,g.user,content) ) + db.execute(""" + INSERT INTO revisions (post,author,content,time,comment) + VALUES (?,?,?,current_timestamp,?); + """, (cur.lastrowid,g.user,content,"(created)")) + if thread_type == "wiki page": + db.execute("UPDATE posts SET wiki = 1 WHERE id = ?;", (cur.lastrowid,)) thread = {'id': thread_id, 'forum': forum['id']} apply_selected_tags(thread, request.form) db.commit() @@ -321,6 +335,7 @@ def create_thread(forum): return render_template("config_thread.html", forum=forum, + thread_type=thread_type, avail_tags=get_avail_tags(forum['id'])) @forum_route("roles",methods=("GET","POST")) diff --git a/apioforum/roles.py b/apioforum/roles.py index 42ce21c..e2428af 100644 --- a/apioforum/roles.py +++ b/apioforum/roles.py @@ -10,6 +10,7 @@ permissions = [ "p_view_threads", "p_vote", "p_create_polls", + "p_edit_wiki", "p_approve", "p_create_subforum", "p_view_forum" diff --git a/apioforum/static/style.css b/apioforum/static/style.css index 573411c..8a30355 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -527,3 +527,7 @@ sitelen { src: local(nasin-nanpa), url("nasin-nanpa.otf") format("opentype"); } +.wiki-body { + margin-bottom: 5px; +} + diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html index 20bc00b..1177405 100644 --- a/apioforum/templates/common.html +++ b/apioforum/templates/common.html @@ -20,12 +20,13 @@ {{disp_user(post.author)}} - {% set role = get_user_role(forum, post.author) %} - {% if role != "other" %} - - ({{ role }}) - - {% endif %} + {%- set role = get_user_role(forum, post.author) -%} + {%- if role != "other" %} + ({{ role }}) + {%- endif -%} + {%- if post.updated_by_others == 1 -%} + , et al. + {%- endif %} {{ts(post.created)}} @@ -35,7 +36,11 @@ {% if buttons %} - {% if post.author == g.user %} + {% if post.author == g.user or ( + post.wiki == 1 and + has_permission(forum, g.user, "p_edit_wiki") + and not thread_info(post.thread).locked == 1) + %} edit {% endif %} @@ -173,12 +178,12 @@ {% endmacro %} -{% macro pagination_nav(page,max_pageno,view,bottom=False) %} +{% macro pagination_nav(page,max_pageno,view,bottom=False,fragment="") %}