diff --git a/tildes/tildes/__init__.py b/tildes/tildes/__init__.py
index 02df50d..655aee9 100644
--- a/tildes/tildes/__init__.py
+++ b/tildes/tildes/__init__.py
@@ -137,10 +137,11 @@ def current_listing_base_url(
The `query` argument allows adding query variables to the generated url.
"""
- if request.matched_route.name not in ('home', 'group'):
+ if request.matched_route.name not in ('home', 'group', 'user'):
raise AttributeError('Current route is not supported.')
- base_view_vars = ('order', 'period', 'per_page', 'tag', 'unfiltered')
+ base_view_vars = (
+ 'order', 'period', 'per_page', 'tag', 'type', 'unfiltered')
query_vars = {
key: val for key, val in request.GET.copy().items()
if key in base_view_vars
@@ -165,7 +166,7 @@ def current_listing_normal_url(
The `query` argument allows adding query variables to the generated url.
"""
- if request.matched_route.name not in ('home', 'group'):
+ if request.matched_route.name not in ('home', 'group', 'user'):
raise AttributeError('Current route is not supported.')
normal_view_vars = ('order', 'period', 'per_page')
diff --git a/tildes/tildes/models/comment/comment_query.py b/tildes/tildes/models/comment/comment_query.py
index 672367b..fb029f8 100644
--- a/tildes/tildes/models/comment/comment_query.py
+++ b/tildes/tildes/models/comment/comment_query.py
@@ -4,12 +4,12 @@ from typing import Any
from pyramid.request import Request
-from tildes.models import ModelQuery
+from tildes.models.pagination import PaginatedQuery
from .comment import Comment
from .comment_vote import CommentVote
-class CommentQuery(ModelQuery):
+class CommentQuery(PaginatedQuery):
"""Specialized ModelQuery for Comments."""
def __init__(self, request: Request) -> None:
diff --git a/tildes/tildes/templates/macros/user_menu.jinja2 b/tildes/tildes/templates/macros/user_menu.jinja2
index 761a85a..0033ab9 100644
--- a/tildes/tildes/templates/macros/user_menu.jinja2
+++ b/tildes/tildes/templates/macros/user_menu.jinja2
@@ -7,7 +7,7 @@
diff --git a/tildes/tildes/templates/user.jinja2 b/tildes/tildes/templates/user.jinja2
index 1e3a1f1..a043528 100644
--- a/tildes/tildes/templates/user.jinja2
+++ b/tildes/tildes/templates/user.jinja2
@@ -10,13 +10,33 @@
{% endblock %}
-{% block main_heading %}{{ user.username }}'s recent activity{% endblock %}
+{# Only show the heading if they can't see the type tabs #}
+{% block main_heading %}
+ {% if not request.has_permission('view_types', user) %}
+ {{ user.username }}'s recent activity
+ {% endif %}
+{% endblock %}
{% block content %}
+{% if request.has_permission('view_types', user) %}
+
+{% endif %}
-{% if merged_posts %}
+{% if posts %}
- {% for post in merged_posts if request.has_permission('view', post) %}
+ {% for post in posts if request.has_permission('view', post) %}
-
{% if post is topic %}
{{ render_topic_for_listing(post, show_group=True) }}
@@ -27,6 +47,22 @@
{% endfor %}
+
+ {% if post_type and (posts.has_prev_page or posts.has_next_page) %}
+
+ {% endif %}
{% else %}
This user hasn't made any posts
diff --git a/tildes/tildes/views/user.py b/tildes/tildes/views/user.py
index f5ced8a..c7da379 100644
--- a/tildes/tildes/views/user.py
+++ b/tildes/tildes/views/user.py
@@ -1,19 +1,24 @@
"""Views related to a specific user."""
+from typing import List, Union
+
+from marshmallow.fields import String
+from marshmallow.validate import OneOf
from pyramid.request import Request
from pyramid.view import view_config
from sqlalchemy.sql.expression import desc
+from webargs.pyramidparser import use_kwargs
from tildes.models.comment import Comment
from tildes.models.topic import Topic
-from tildes.models.user import UserInviteCode
-
+from tildes.models.user import User, UserInviteCode
+from tildes.schemas.topic_listing import TopicListingSchema
-@view_config(route_name='user', renderer='user.jinja2')
-def get_user(request: Request) -> dict:
- """Generate the main user info page."""
- user = request.context
+def _get_user_recent_activity(
+ request: Request,
+ user: User,
+) -> List[Union[Comment, Topic]]:
page_size = 20
# Since we don't know how many comments or topics will be needed to make
@@ -54,9 +59,56 @@ def get_user(request: Request) -> dict:
)
merged_posts = merged_posts[:page_size]
+ return merged_posts
+
+
+@view_config(route_name='user', renderer='user.jinja2')
+@use_kwargs(TopicListingSchema(only=('after', 'before', 'per_page')))
+@use_kwargs({
+ 'post_type': String(
+ load_from='type',
+ validate=OneOf(('topic', 'comment')),
+ ),
+})
+def get_user(
+ request: Request,
+ after: str,
+ before: str,
+ per_page: int,
+ post_type: str = None,
+) -> dict:
+ """Generate the main user history page."""
+ user = request.context
+
+ if not request.has_permission('view_types', user):
+ post_type = None
+
+ if post_type:
+ if post_type == 'topic':
+ query = request.query(Topic).filter(Topic.user == user)
+ elif post_type == 'comment':
+ query = request.query(Comment).filter(Comment.user == user)
+
+ if before:
+ query = query.before_id36(before)
+
+ if after:
+ query = query.after_id36(after)
+
+ query = query.join_all_relationships()
+
+ # include removed posts if the user's looking at their own page
+ if user == request.user:
+ query = query.include_removed()
+
+ posts = query.get_page(per_page)
+ else:
+ posts = _get_user_recent_activity(request, user)
+
return {
'user': user,
- 'merged_posts': merged_posts,
+ 'posts': posts,
+ 'post_type': post_type,
}