From 072f5da86d9c48dcbb6ffe0181f30ba102389f81 Mon Sep 17 00:00:00 2001 From: ajbt200128 Date: Thu, 31 Oct 2019 21:09:32 -0400 Subject: [PATCH] Add page listing topics/comments you've voted on --- tildes/tildes/models/comment/comment_query.py | 18 ++++++- tildes/tildes/models/topic/topic_query.py | 18 ++++++- tildes/tildes/request_methods.py | 1 + tildes/tildes/routes.py | 1 + tildes/tildes/templates/bookmarks.jinja2 | 2 + .../tildes/templates/macros/user_menu.jinja2 | 5 ++ tildes/tildes/templates/votes.jinja2 | 13 +++++ tildes/tildes/views/votes.py | 49 +++++++++++++++++++ 8 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 tildes/tildes/templates/votes.jinja2 create mode 100644 tildes/tildes/views/votes.py diff --git a/tildes/tildes/models/comment/comment_query.py b/tildes/tildes/models/comment/comment_query.py index ff5b01b..4bd8c7b 100644 --- a/tildes/tildes/models/comment/comment_query.py +++ b/tildes/tildes/models/comment/comment_query.py @@ -7,6 +7,7 @@ from typing import Any from pyramid.request import Request from sqlalchemy import func +from sqlalchemy.orm import aliased from sqlalchemy.sql.expression import and_ from tildes.enums import CommentSortOption @@ -29,6 +30,7 @@ class CommentQuery(PaginatedQuery): super().__init__(Comment, request) self._only_bookmarked = False + self._only_user_voted = False def _attach_extra_data(self) -> "CommentQuery": """Attach the extra user data to the query.""" @@ -41,7 +43,7 @@ class CommentQuery(PaginatedQuery): def _attach_vote_data(self) -> "CommentQuery": """Add a subquery to include whether the user has voted.""" vote_subquery = ( - self.request.query(CommentVote) + self.request.query(aliased(CommentVote)) .filter( CommentVote.comment_id == Comment.comment_id, CommentVote.user_id == self.request.user.user_id, @@ -49,7 +51,14 @@ class CommentQuery(PaginatedQuery): .exists() .label("user_voted") ) - return self.add_columns(vote_subquery) + + query = self.add_columns(vote_subquery) + + if self._only_user_voted: + query = query.add_columns(CommentVote.created_time) + query = query.filter(vote_subquery) + + return query def _attach_bookmark_data(self) -> "CommentQuery": """Join the data related to whether the user has bookmarked the comment.""" @@ -104,3 +113,8 @@ class CommentQuery(PaginatedQuery): """Restrict the comments to ones that the user has bookmarked (generative).""" self._only_bookmarked = True return self + + def only_user_voted(self) -> "CommentQuery": + """Restrict the comments to ones that the user has voted on (generative).""" + self._only_user_voted = True + return self diff --git a/tildes/tildes/models/topic/topic_query.py b/tildes/tildes/models/topic/topic_query.py index 1f0bea6..c135c54 100644 --- a/tildes/tildes/models/topic/topic_query.py +++ b/tildes/tildes/models/topic/topic_query.py @@ -8,6 +8,7 @@ from typing import Any, Sequence from pyramid.request import Request from sqlalchemy import func from sqlalchemy.sql.expression import and_, null +from sqlalchemy.orm import aliased from tildes.enums import TopicSortOption from tildes.lib.datetime import SimpleHoursPeriod, utc_now @@ -34,6 +35,7 @@ class TopicQuery(PaginatedQuery): super().__init__(Topic, request) self._only_bookmarked = False + self._only_user_voted = False def _attach_extra_data(self) -> "TopicQuery": """Attach the extra user data to the query.""" @@ -46,7 +48,7 @@ class TopicQuery(PaginatedQuery): def _attach_vote_data(self) -> "TopicQuery": """Add a subquery to include whether the user has voted.""" vote_subquery = ( - self.request.query(TopicVote) + self.request.query(aliased(TopicVote)) .filter( TopicVote.topic_id == Topic.topic_id, TopicVote.user == self.request.user, @@ -54,7 +56,14 @@ class TopicQuery(PaginatedQuery): .exists() .label("user_voted") ) - return self.add_columns(vote_subquery) + + query = self.add_columns(vote_subquery) + + if self._only_user_voted: + query = query.filter(vote_subquery) + query = query.add_columns(TopicVote.created_time) + + return query def _attach_bookmark_data(self) -> "TopicQuery": """Join the data related to whether the user has bookmarked the topic.""" @@ -181,3 +190,8 @@ class TopicQuery(PaginatedQuery): """Restrict the topics to ones that the user has bookmarked (generative).""" self._only_bookmarked = True return self + + def only_user_voted(self) -> "TopicQuery": + """Restrict the topics to ones that the user has voted on (generative).""" + self._only_user_voted = True + return self diff --git a/tildes/tildes/request_methods.py b/tildes/tildes/request_methods.py index 19f672d..b2594ca 100644 --- a/tildes/tildes/request_methods.py +++ b/tildes/tildes/request_methods.py @@ -153,6 +153,7 @@ def current_listing_normal_url( """ normal_vars_by_route: Dict[str, Tuple[str, ...]] = { "bookmarks": ("order", "period", "per_page"), + "votes": ("order", "period", "per_page"), "group": ("order", "period", "per_page"), "group_search": ("order", "period", "per_page", "q"), "home": ("order", "period", "per_page"), diff --git a/tildes/tildes/routes.py b/tildes/tildes/routes.py index 2e045df..85aed87 100644 --- a/tildes/tildes/routes.py +++ b/tildes/tildes/routes.py @@ -106,6 +106,7 @@ def includeme(config: Configurator) -> None: ) config.add_route("bookmarks", "/bookmarks", factory=LoggedInFactory) + config.add_route("votes", "/votes", factory=LoggedInFactory) config.add_route("invite", "/invite", factory=LoggedInFactory) diff --git a/tildes/tildes/templates/bookmarks.jinja2 b/tildes/tildes/templates/bookmarks.jinja2 index af645df..1dafa2e 100644 --- a/tildes/tildes/templates/bookmarks.jinja2 +++ b/tildes/tildes/templates/bookmarks.jinja2 @@ -53,11 +53,13 @@ {% else %}

+ {% block empty_message %} {% if post_type == 'topic' %} You haven't bookmarked any topics {% elif post_type == 'comment' %} You haven't bookmarked any comments {% endif %} + {% endblock %}

{% endif %} diff --git a/tildes/tildes/templates/macros/user_menu.jinja2 b/tildes/tildes/templates/macros/user_menu.jinja2 index ed1c96e..68000e5 100644 --- a/tildes/tildes/templates/macros/user_menu.jinja2 +++ b/tildes/tildes/templates/macros/user_menu.jinja2 @@ -13,6 +13,11 @@ Your posts +
  • Notifications
  • diff --git a/tildes/tildes/templates/votes.jinja2 b/tildes/tildes/templates/votes.jinja2 new file mode 100644 index 0000000..f043b82 --- /dev/null +++ b/tildes/tildes/templates/votes.jinja2 @@ -0,0 +1,13 @@ +{% extends 'bookmarks.jinja2' %} + +{% block title %}Votes{% endblock %} + +{% block main_heading %}Votes{% endblock %} + +{% block empty_message %} + {% if post_type == 'topic' %} + You haven't voted on any topics + {% elif post_type == 'comment' %} + You haven't voted on any comments + {% endif %} +{% endblock %} diff --git a/tildes/tildes/views/votes.py b/tildes/tildes/views/votes.py new file mode 100644 index 0000000..7221499 --- /dev/null +++ b/tildes/tildes/views/votes.py @@ -0,0 +1,49 @@ +"""Views relating to voted posts.""" + +from typing import Type, Union + +from pyramid.request import Request +from pyramid.view import view_config +from sqlalchemy.sql import desc +from webargs.pyramidparser import use_kwargs + +from tildes.models.comment import Comment, CommentVote +from tildes.models.topic import Topic, TopicVote +from tildes.schemas.fields import PostType +from tildes.schemas.listing import PaginatedListingSchema + + +@view_config(route_name="votes", renderer="votes.jinja2") +@use_kwargs(PaginatedListingSchema) +@use_kwargs({"post_type": PostType(load_from="type", missing="topic")}) +def get_voted_posts( + request: Request, after: str, before: str, per_page: int, post_type: str +) -> dict: + """Generate the voted posts page.""" + # pylint: disable=unused-argument + user = request.user + + vote_cls: Union[Type[CommentVote], Type[TopicVote]] + + if post_type == "comment": + post_cls = Comment + vote_cls = CommentVote + elif post_type == "topic": + post_cls = Topic + vote_cls = TopicVote + + query = ( + request.query(post_cls).only_user_voted().order_by(desc(vote_cls.created_time)) + ) + + if before: + query = query.before_id36(before) + + if after: + query = query.after_id36(after) + + query = query.join_all_relationships() + + posts = query.all() + + return {"user": user, "posts": posts, "post_type": post_type}