diff options
-rw-r--r-- | apioforum/__init__.py | 1 | ||||
-rw-r--r-- | apioforum/forum.py | 31 | ||||
-rw-r--r-- | apioforum/templates/base.html | 2 | ||||
-rw-r--r-- | apioforum/templates/common.html | 20 | ||||
-rw-r--r-- | apioforum/templates/view_forum.html | 9 | ||||
-rw-r--r-- | apioforum/templates/view_post.html | 2 | ||||
-rw-r--r-- | apioforum/templates/view_thread.html | 3 | ||||
-rw-r--r-- | apioforum/thread.py | 57 |
8 files changed, 101 insertions, 24 deletions
diff --git a/apioforum/__init__.py b/apioforum/__init__.py index 087df81..60777fb 100644 --- a/apioforum/__init__.py +++ b/apioforum/__init__.py @@ -54,6 +54,7 @@ def create_app(): return dict(path_for_next=p) app.jinja_env.globals.update(forum_path=forum.forum_path) + app.jinja_env.globals.update(post_jump=thread.post_jump) from .roles import has_permission, is_bureaucrat, get_user_role app.jinja_env.globals.update( has_permission=has_permission, diff --git a/apioforum/forum.py b/apioforum/forum.py index 2931df9..87d4022 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -13,8 +13,11 @@ from .roles import get_forum_roles,has_permission,is_bureaucrat,get_user_role, p from .permissions import is_admin from sqlite3 import OperationalError import datetime +import math import functools +THREADS_PER_PAGE = 20 + bp = Blueprint("forum", __name__, url_prefix="/") @bp.route("/") @@ -46,7 +49,7 @@ def forum_path(forum_id): ancestors.reverse() return ancestors -def forum_route(relative_path, **kwargs): +def forum_route(relative_path, pagination=False, **kwargs): def decorator(f): path = "/<int:forum_id>" if relative_path != "": @@ -62,6 +65,9 @@ def forum_route(relative_path, **kwargs): abort(404) return f(forum, *args, **kwargs) + if pagination: + wrapper = bp.route(path+"/page/<int:page>", **kwargs)(wrapper) + return decorator def requires_permission(permission, login_required=True): @@ -83,9 +89,12 @@ def requires_bureaucrat(f): return f(forum, *args, **kwargs) return wrapper -@forum_route("") + +@forum_route("",pagination=True) @requires_permission("p_view_forum", login_required=False) -def view_forum(forum): +def view_forum(forum,page=1): + if page < 1: + abort(400) db = get_db() threads = db.execute( """SELECT @@ -100,8 +109,18 @@ def view_forum(forum): INNER JOIN most_recent_posts ON most_recent_posts.thread = threads.id INNER JOIN number_of_posts ON number_of_posts.thread = threads.id WHERE threads.forum = ? - ORDER BY threads.updated DESC; - """,(forum['id'],)).fetchall() + ORDER BY threads.updated DESC + LIMIT ? OFFSET ?; + """,( + forum['id'], + THREADS_PER_PAGE, + (page-1)*THREADS_PER_PAGE, + )).fetchall() + + # XXX: update this when thread filtering happens + num_threads = db.execute("SELECT count(*) AS count FROM threads WHERE threads.forum = ?",(forum['id'],)).fetchone()['count'] + max_pageno = math.ceil(num_threads/THREADS_PER_PAGE) + thread_tags = {} thread_polls = {} @@ -169,6 +188,8 @@ def view_forum(forum): bureaucrats=bureaucrats, thread_polls=thread_polls, avail_tags=avail_tags, + max_pageno=max_pageno, + page=page, ) @forum_route("create_thread",methods=("GET","POST")) diff --git a/apioforum/templates/base.html b/apioforum/templates/base.html index ca1dd87..b97117f 100644 --- a/apioforum/templates/base.html +++ b/apioforum/templates/base.html @@ -10,7 +10,7 @@ <link rel="icon" href="//gh0.pw/favicon.ico"> </head> <body> - <nav id="navbar"> + <nav aria-label="main" id="navbar"> <p style="font-family: monospace;"><b>apio</b><i>forum</i>™</p> <form class="inline-form" action="/search"> <input type="search" placeholder="query" name="q"> diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html index f6b6f29..8eeef70 100644 --- a/apioforum/templates/common.html +++ b/apioforum/templates/common.html @@ -2,10 +2,6 @@ <a href="{{url_for('user.view_user',username=username)}}" class="username">{{username}}</a> {%- endmacro %} -{% macro post_url(post) -%} - {{url_for('thread.view_thread', thread_id=post.thread)}}#post_{{post.id}} -{%- endmacro %} - {% macro disp_post(post, buttons=False, forum=None, footer=None) %} <div class="post {% if post.deleted %}deleted-post{% endif %}" id="post_{{post.id}}"> <div class="post-heading"> @@ -49,7 +45,7 @@ href="{{url_for('thread.view_post',post_id=post.id)}}">src</a> {% endif %} - <a class="post-anchor-link" href="{{post_url(post)}}">#{{post.id}}</a> + <a class="post-anchor-link" href="{{post_jump(post.id)}}">#{{post.id}}</a> </span> </div> <div class="post-content md"> @@ -142,3 +138,17 @@ </desc> </svg> {% endmacro %} + +{% macro pagination_nav(page,max_pageno,view) %} +<nav aria-label="pagination" id="pages"> + {% if page > 1 %} + <a href="{{url_for(view,**kwargs)}}" aria-label="first page"><<</a> + <a href="{{url_for(view,page=page-1,**kwargs)}}" aria-label="previous page"><</a> + {% endif %} + page {{page}} of {{max_pageno}} + {% if page < max_pageno %} {# > #} + <a href="{{url_for(view,page=page+1,**kwargs)}}" aria-label="next page">></a> + <a href="{{url_for(view,page=max_pageno,**kwargs)}}" aria-label="last page">>></a> + {% endif %} +</nav> +{% endmacro %} diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index 0eada1a..75144c8 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% from 'common.html' import ts, tag, disp_user, post_url, forum_breadcrumb, ab, vote_meter %} +{% from 'common.html' import ts, tag, disp_user, post_url, forum_breadcrumb, ab, vote_meter, pagination_nav %} {% block header %} <h1>{% block title %}{{forum.name}}{% endblock %} <span class="thing-id">#{{forum.id}}</span></h1> {% if forum.id != 1 %} @@ -112,7 +112,7 @@ you do not have permission to create threads in this forum {{ ts(thread.mrp_created) }} </span> <span class="thread-preview-post"> - <a href="{{url_for('thread.view_thread',thread_id=thread.id)}}#post_{{thread.mrp_id}}"> + <a href="{{post_jump(thread.mrp_id)}}"> {{ thread.mrp_content[:500]|e }} </a> </span> @@ -120,7 +120,7 @@ you do not have permission to create threads in this forum {% else %} <div class="listing-caption"> <a class="thread-preview-post" - href="{{url_for('thread.view_thread',thread_id=thread.id)}}#post_{{thread.mrp_id}}"> + href="{{post_jump(thread.mrp_id)}}"> latest post </a> </div> @@ -133,6 +133,9 @@ you do not have permission to create threads in this forum </div> {%endfor%} </div> +{{ pagination_nav(page,max_pageno,'forum.view_forum',forum_id=forum.id) }} + + {% else %} <p>you do not have permission to view threads in this forum</p> {% endif %} diff --git a/apioforum/templates/view_post.html b/apioforum/templates/view_post.html index 993c005..fcaf29b 100644 --- a/apioforum/templates/view_post.html +++ b/apioforum/templates/view_post.html @@ -8,5 +8,5 @@ {{disp_post(post,False)}} <p>post source:</p> <textarea readonly class="new-post-box" name="newcontent">{{post.content}}</textarea> -<a href="{{url_for('thread.view_thread',thread_id=post.thread)}}">i am satisfied</a> +<a href="{{post_jump(post.id)}}">i am satisfied</a> {% endblock %} diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index 132fd44..fe22cfc 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -1,4 +1,4 @@ -{% from 'common.html' import disp_post,tag,thread_breadcrumb,vote_meter %} +{% from 'common.html' import disp_post,tag,thread_breadcrumb,vote_meter,pagination_nav %} {% extends 'base.html' %} {% block header %} <h1>{%block title %}{{thread.title}}{% endblock %} <span class="thing-id">#{{thread.id}}</span></h1> @@ -69,6 +69,7 @@ {% endif %} {% endfor %} </div> +{{ pagination_nav(page,max_pageno,'thread.view_thread',thread_id=thread.id) }} {% if g.user and has_permission(thread.forum, g.user, "p_reply_threads") %} <form class="new-post" action="{{url_for('thread.create_post',thread_id=thread.id)}}" method="POST"> <textarea class="new-post-box" placeholder="your post here..." name="content"></textarea> diff --git a/apioforum/thread.py b/apioforum/thread.py index 2fc9dca..f3bcc59 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -1,6 +1,6 @@ # view posts in thread -import itertools +import itertools, math from flask import ( Blueprint, render_template, abort, request, g, redirect, @@ -12,11 +12,41 @@ from .forum import get_avail_tags bp = Blueprint("thread", __name__, url_prefix="/thread") -def post_jump(thread_id, post_id): - return url_for("thread.view_thread",thread_id=thread_id)+"#post_"+str(post_id) +POSTS_PER_PAGE = 20 + +def which_page(post_id,return_thread_id=False): + # on which page lieth the post in question? + # forget not that page numbers employeth a system that has a base of 1. + # the + # we need impart the knowledgf e into ourselves pertaining to the + # number of things + # before the thing + # yes + + db = get_db() + # ASSUMES THAT post ids are consecutive and things + # this is probably a reasonable assumption + + thread_id = db.execute('select thread from posts where id = ?',(post_id,)).fetchone()['thread'] + + number_of_things_before_the_thing = db.execute('select count(*) as c, thread as t from posts where thread = ? and id < ?;',(thread_id,post_id)).fetchone()['c'] + + + page = 1+math.floor(number_of_things_before_the_thing/POSTS_PER_PAGE) + if return_thread_id: + return page, thread_id + else: + return page + +def post_jump(post_id): + page,thread_id=which_page(post_id,True) + return url_for("thread.view_thread",thread_id=thread_id,page=page)+"#post_"+str(post_id) @bp.route("/<int:thread_id>") -def view_thread(thread_id): +@bp.route("/<int:thread_id>/page/<int:page>") +def view_thread(thread_id,page=1): + if page < 1: + abort(400) db = get_db() thread = db.execute("SELECT * FROM threads WHERE id = ?;",(thread_id,)).fetchone() if thread is None: @@ -26,8 +56,17 @@ def view_thread(thread_id): posts = db.execute(""" SELECT * FROM posts WHERE posts.thread = ? - ORDER BY created ASC; - """,(thread_id,)).fetchall() + ORDER BY created ASC + LIMIT ? OFFSET ?; + """,( + thread_id, + POSTS_PER_PAGE, + (page-1)*POSTS_PER_PAGE, + )).fetchall() + + num_posts = db.execute("SELECT count(*) as count FROM posts WHERE posts.thread = ?",(thread_id,)).fetchone()['count'] + max_pageno = math.ceil(num_posts/POSTS_PER_PAGE) + tags = db.execute( """SELECT tags.* FROM tags INNER JOIN thread_tags ON thread_tags.tag = tags.id @@ -72,6 +111,8 @@ def view_thread(thread_id): poll=poll, votes=votes, has_voted=has_voted, + page=page, + max_pageno=max_pageno, ) def register_vote(thread,pollval): @@ -215,7 +256,7 @@ def create_post(thread_id): ) db.commit() flash("post posted postfully") - return redirect(post_jump(thread_id, post_id)) + return redirect(post_jump(post_id)) return redirect(url_for('thread.view_thread',thread_id=thread_id)) @bp.route("/delete_post/<int:post_id>", methods=["GET","POST"]) @@ -287,7 +328,7 @@ def edit_post(post_id): "UPDATE posts SET content = ?, edited = 1, updated = current_timestamp WHERE id = ?",(newcontent,post_id)) db.commit() flash("post edited editiously") - return redirect(post_jump(post['thread'],post_id)) + return redirect(post_jump(post_id)) else: flash(err) return render_template("edit_post.html",post=post) |