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) | 
