add user posts view
This commit is contained in:
@@ -50,6 +50,10 @@ class Users(Model):
|
|||||||
WHERE users.id = ?"""
|
WHERE users.id = ?"""
|
||||||
return db.fetch_one(q, self.id)
|
return db.fetch_one(q, self.id)
|
||||||
|
|
||||||
|
def get_posts(self, per_page: int, page: int) -> list:
|
||||||
|
q = f'{Posts.FULL_POSTS_QUERY} WHERE posts.user_id = ? ORDER BY posts.created_at DESC LIMIT ? OFFSET ?'
|
||||||
|
return db.query(q, self.id, per_page, (page - 1) * per_page)
|
||||||
|
|
||||||
def get_all_subscriptions(self):
|
def get_all_subscriptions(self):
|
||||||
q = """
|
q = """
|
||||||
SELECT threads.title AS thread_title, threads.slug AS thread_slug
|
SELECT threads.title AS thread_title, threads.slug AS thread_slug
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from flask import Blueprint, redirect, url_for, render_template, request, session
|
from flask import Blueprint, redirect, url_for, render_template, request, session, abort
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -7,9 +7,10 @@ from ..auth import (
|
|||||||
is_logged_in, parse_username, is_password_valid,
|
is_logged_in, parse_username, is_password_valid,
|
||||||
login_required
|
login_required
|
||||||
)
|
)
|
||||||
from ..models import Users
|
from ..models import Users, Posts, Reactions
|
||||||
from ..constants import PermissionLevel
|
from ..constants import PermissionLevel
|
||||||
from secrets import compare_digest as compare_timesafe
|
from secrets import compare_digest as compare_timesafe
|
||||||
|
import math
|
||||||
|
|
||||||
bp = Blueprint('users', __name__, url_prefix='/users/')
|
bp = Blueprint('users', __name__, url_prefix='/users/')
|
||||||
|
|
||||||
@@ -104,6 +105,7 @@ def sign_up_post():
|
|||||||
|
|
||||||
@bp.get('/<username>/')
|
@bp.get('/<username>/')
|
||||||
def user_page(username):
|
def user_page(username):
|
||||||
|
username = username.lower()
|
||||||
target_user = Users.find({'username': username})
|
target_user = Users.find({'username': username})
|
||||||
if not target_user:
|
if not target_user:
|
||||||
abort(404)
|
abort(404)
|
||||||
@@ -111,25 +113,51 @@ def user_page(username):
|
|||||||
|
|
||||||
@bp.get('/<username>/posts/')
|
@bp.get('/<username>/posts/')
|
||||||
def posts(username):
|
def posts(username):
|
||||||
return 'stub'
|
username = username.lower()
|
||||||
|
if username == 'deleteduser':
|
||||||
|
abort(404)
|
||||||
|
target_user = Users.find({'username': username})
|
||||||
|
PER_PAGE = 10
|
||||||
|
posts_count = Posts.count({'user_id': target_user.id})
|
||||||
|
page_count = max(1, math.ceil(posts_count / PER_PAGE))
|
||||||
|
page = 1
|
||||||
|
try:
|
||||||
|
page = max(1, min(int(request.args.get('page', default=1)), page_count))
|
||||||
|
except ValueError:
|
||||||
|
abort(404)
|
||||||
|
posts = target_user.get_posts(PER_PAGE, page)
|
||||||
|
return render_template(
|
||||||
|
'users/posts.html', posts=posts,
|
||||||
|
page=page, page_count=page_count,
|
||||||
|
target_user=target_user, Reactions=Reactions
|
||||||
|
)
|
||||||
|
|
||||||
@bp.get('/<username>/threads/')
|
@bp.get('/<username>/threads/')
|
||||||
def threads(username):
|
def threads(username):
|
||||||
|
username = username.lower()
|
||||||
|
if username == 'deleteduser':
|
||||||
|
abort(404)
|
||||||
return 'stub'
|
return 'stub'
|
||||||
|
|
||||||
@bp.get('/<username>/comments/')
|
@bp.get('/<username>/comments/')
|
||||||
def comments(username):
|
def comments(username):
|
||||||
|
username = username.lower()
|
||||||
|
if username == 'deleteduser':
|
||||||
|
abort(404)
|
||||||
return 'stub'
|
return 'stub'
|
||||||
|
|
||||||
@bp.get('/<username>/settings/')
|
@bp.get('/<username>/settings/')
|
||||||
def settings(username):
|
def settings(username):
|
||||||
|
username = username.lower()
|
||||||
return 'stub'
|
return 'stub'
|
||||||
|
|
||||||
@bp.get('/<username>/inbox/')
|
@bp.get('/<username>/inbox/')
|
||||||
def inbox(username):
|
def inbox(username):
|
||||||
|
username = username.lower()
|
||||||
return 'stub'
|
return 'stub'
|
||||||
|
|
||||||
@bp.get('/<username>/bookmarks/')
|
@bp.get('/<username>/bookmarks/')
|
||||||
def bookmarks(username):
|
def bookmarks(username):
|
||||||
|
username = username.lower()
|
||||||
return 'stub'
|
return 'stub'
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{%- from 'common/icons.html' import icn_info, icn_warn, icn_error, icn_bookmark -%}
|
{%- from 'common/icons.html' import icn_info, icn_warn, icn_error, icn_bookmark -%}
|
||||||
|
|
||||||
{% macro timestamp(unix_ts) -%}
|
{% macro timestamp(unix_ts) -%}
|
||||||
{#<span class="timestamp" data-utc="{{ unix_ts }}">{{ unix_ts | ts_datetime('%Y-%m-%d %H:%M')}} <abbr title="Server Time">ST</abbr></span>#}
|
|
||||||
<time datetime="{{ unix_ts | iso8601 }}">{{ unix_ts | ts_datetime('%Y-%m-%d %H:%M')}} <abbr title="Server Time">ST</abbr></time>
|
<time datetime="{{ unix_ts | iso8601 }}">{{ unix_ts | ts_datetime('%Y-%m-%d %H:%M')}} <abbr title="Server Time">ST</abbr></time>
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
@@ -114,7 +113,7 @@
|
|||||||
{% macro full_post(
|
{% macro full_post(
|
||||||
post, render_sig=true, is_latest=false,
|
post, render_sig=true, is_latest=false,
|
||||||
show_toolbar=true, is_editing=false, thread=none,
|
show_toolbar=true, is_editing=false, thread=none,
|
||||||
show_reactions=true
|
show_reactions=true, show_thread=false
|
||||||
) -%}
|
) -%}
|
||||||
{%- if is_logged_in() -%}
|
{%- if is_logged_in() -%}
|
||||||
{%- set can_delete = post.user_id == get_active_user().id or is_mod() -%}
|
{%- set can_delete = post.user_id == get_active_user().id or is_mod() -%}
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="post-content">
|
<div class="post-content">
|
||||||
<div class="plank even minimal secondary-bg no-shadow post-info">
|
<div class="plank even minimal secondary-bg no-shadow post-info">
|
||||||
|
<span>
|
||||||
<a href="{{get_post_url(post.id, _anchor=true)}}">
|
<a href="{{get_post_url(post.id, _anchor=true)}}">
|
||||||
{%- if post.edited_at <= post.created_at -%}
|
{%- if post.edited_at <= post.created_at -%}
|
||||||
<i>Posted on {{timestamp(post.created_at)}}</i>
|
<i>Posted on {{timestamp(post.created_at)}}</i>
|
||||||
@@ -150,6 +150,10 @@
|
|||||||
<i>Edited on {{timestamp(post.edited_at)}}</i>
|
<i>Edited on {{timestamp(post.edited_at)}}</i>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</a>
|
</a>
|
||||||
|
{%- if show_thread -%}
|
||||||
|
<span> in thread <a href="{{url_for('threads.thread_by_id', thread_id=post.thread_id)}}"> {{post.thread_title}}</a></span>
|
||||||
|
{%- endif -%}
|
||||||
|
</span>
|
||||||
{%- if show_toolbar -%}
|
{%- if show_toolbar -%}
|
||||||
<span class="thread-actions">
|
<span class="thread-actions">
|
||||||
{%- if owns -%}
|
{%- if owns -%}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{% from 'common/macros.html' import infobox with context %}
|
||||||
{% from 'common/macros.html' import subheader %}
|
{% from 'common/macros.html' import subheader %}
|
||||||
{%- extends 'base.html' -%}
|
{%- extends 'base.html' -%}
|
||||||
{%- block title -%}log in{%- endblock -%}
|
{%- block title -%}log in{%- endblock -%}
|
||||||
@@ -7,9 +8,7 @@ Welcome back! No account yet? <a href="{{url_for('users.sign_up')}}">Sign up</a>
|
|||||||
{%- endset -%}
|
{%- endset -%}
|
||||||
{{ subheader('Log in', welcome)}}
|
{{ subheader('Log in', welcome)}}
|
||||||
{%- if request.args.get('error') -%}
|
{%- if request.args.get('error') -%}
|
||||||
<div class="infobox plank critical">
|
{{infobox(request.args.error, InfoboxKind.ERROR)}}
|
||||||
{{request.args.get('error')}}
|
|
||||||
</div>
|
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
<form class="plank primary-bg full-width" method="POST">
|
<form class="plank primary-bg full-width" method="POST">
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
|
|||||||
30
app/templates/users/posts.html
Normal file
30
app/templates/users/posts.html
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{%- from 'common/macros.html' import full_post with context -%}
|
||||||
|
{%- from 'common/macros.html' import subheader, pager -%}
|
||||||
|
{%- extends 'base.html' -%}
|
||||||
|
{%- block title -%}{{ target_user.get_readable_name() }}'s posts{%- endblock -%}
|
||||||
|
{%- block content -%}
|
||||||
|
{%- set td -%}
|
||||||
|
<a href="{{url_for('users.user_page', username=target_user.username)}}">Back to profile</a>
|
||||||
|
{%- if posts -%}
|
||||||
|
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||||
|
<legend>Page</legend>
|
||||||
|
{{- pager(page, page_count) -}}
|
||||||
|
</fieldset>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endset -%}
|
||||||
|
{%- call() subheader("%s's posts" % target_user.get_readable_name(), td) -%}
|
||||||
|
{%- endcall -%}
|
||||||
|
{%- if posts -%}
|
||||||
|
{%- for post in posts -%}
|
||||||
|
<div class="post plank">{{full_post(post, show_toolbar=false, show_thread=true)}}</div>
|
||||||
|
{%- endfor -%}
|
||||||
|
<div class="plank">
|
||||||
|
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||||
|
<legend>Page</legend>
|
||||||
|
{{- pager(page, page_count) -}}
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
{%- else -%}
|
||||||
|
<div class="plank">{{target_user.get_readable_name()}} has no posts.</div>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endblock -%}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{% from 'common/macros.html' import infobox with context %}
|
||||||
{% from 'common/macros.html' import subheader %}
|
{% from 'common/macros.html' import subheader %}
|
||||||
{%- extends 'base.html' -%}
|
{%- extends 'base.html' -%}
|
||||||
{%- block title -%}sign up{%- endblock -%}
|
{%- block title -%}sign up{%- endblock -%}
|
||||||
@@ -7,9 +8,7 @@ Please read the rules etc. stub
|
|||||||
{%- endset -%}
|
{%- endset -%}
|
||||||
{{ subheader('Sign up', welcome)}}
|
{{ subheader('Sign up', welcome)}}
|
||||||
{%- if request.args.get('error') -%}
|
{%- if request.args.get('error') -%}
|
||||||
<div class="infobox plank critical">
|
{{infobox(request.args.error, InfoboxKind.ERROR)}}
|
||||||
{{request.args.get('error')}}
|
|
||||||
</div>
|
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
<form class="plank primary-bg full-width" method="POST">
|
<form class="plank primary-bg full-width" method="POST">
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user