mirror of https://gitlab.com/tildes/tildes.git
Browse Source
Add simple functionality for ignoring topics
Add simple functionality for ignoring topics
This adds a simple Ignore functionality for topics, with the only effect being to exclude ignored topics from listing pages. It also adds a "Your ignored topics" page (linked through the user menu) that lists all of a user's ignored topics, so that they can access them if needed (to be able to un-ignore).merge-requests/88/head
Ivan Fonseca
6 years ago
committed by
Deimos
15 changed files with 287 additions and 6 deletions
-
50tildes/alembic/versions/4e101aae77cd_add_topic_ignores.py
-
1tildes/tildes/database_models.py
-
1tildes/tildes/models/topic/__init__.py
-
12tildes/tildes/models/topic/topic.py
-
38tildes/tildes/models/topic/topic_ignore.py
-
50tildes/tildes/models/topic/topic_query.py
-
2tildes/tildes/request_methods.py
-
1tildes/tildes/resources/topic.py
-
2tildes/tildes/routes.py
-
43tildes/tildes/templates/ignored_topics.jinja2
-
3tildes/tildes/templates/macros/buttons.jinja2
-
5tildes/tildes/templates/macros/user_menu.jinja2
-
4tildes/tildes/templates/topic.jinja2
-
46tildes/tildes/views/api/web/topic.py
-
35tildes/tildes/views/ignored_topics.py
@ -0,0 +1,50 @@ |
|||
"""Add topic_ignores |
|||
|
|||
Revision ID: 4e101aae77cd |
|||
Revises: 4d352e61a468 |
|||
Create Date: 2020-01-07 23:07:51.707034 |
|||
|
|||
""" |
|||
from alembic import op |
|||
import sqlalchemy as sa |
|||
|
|||
|
|||
# revision identifiers, used by Alembic. |
|||
revision = "4e101aae77cd" |
|||
down_revision = "4d352e61a468" |
|||
branch_labels = None |
|||
depends_on = None |
|||
|
|||
|
|||
def upgrade(): |
|||
op.create_table( |
|||
"topic_ignores", |
|||
sa.Column("user_id", sa.Integer(), nullable=False), |
|||
sa.Column("topic_id", sa.Integer(), nullable=False), |
|||
sa.Column( |
|||
"created_time", |
|||
sa.TIMESTAMP(timezone=True), |
|||
server_default=sa.text("NOW()"), |
|||
nullable=False, |
|||
), |
|||
sa.ForeignKeyConstraint( |
|||
["topic_id"], |
|||
["topics.topic_id"], |
|||
name=op.f("fk_topic_ignores_topic_id_topics"), |
|||
), |
|||
sa.ForeignKeyConstraint( |
|||
["user_id"], ["users.user_id"], name=op.f("fk_topic_ignores_user_id_users") |
|||
), |
|||
sa.PrimaryKeyConstraint("user_id", "topic_id", name=op.f("pk_topic_ignores")), |
|||
) |
|||
op.create_index( |
|||
op.f("ix_topic_ignores_created_time"), |
|||
"topic_ignores", |
|||
["created_time"], |
|||
unique=False, |
|||
) |
|||
|
|||
|
|||
def downgrade(): |
|||
op.drop_index(op.f("ix_topic_ignores_created_time"), table_name="topic_ignores") |
|||
op.drop_table("topic_ignores") |
@ -0,0 +1,38 @@ |
|||
"""Contains the TopicIgnore class.""" |
|||
|
|||
from datetime import datetime |
|||
|
|||
from sqlalchemy import Column, ForeignKey, Integer, TIMESTAMP |
|||
from sqlalchemy.orm import relationship |
|||
from sqlalchemy.sql.expression import text |
|||
|
|||
from tildes.models import DatabaseModel |
|||
from tildes.models.topic import Topic |
|||
from tildes.models.user import User |
|||
|
|||
|
|||
class TopicIgnore(DatabaseModel): |
|||
"""Model for an ignored topic.""" |
|||
|
|||
__tablename__ = "topic_ignores" |
|||
|
|||
user_id: int = Column( |
|||
Integer, ForeignKey("users.user_id"), nullable=False, primary_key=True |
|||
) |
|||
topic_id: int = Column( |
|||
Integer, ForeignKey("topics.topic_id"), nullable=False, primary_key=True |
|||
) |
|||
created_time: datetime = Column( |
|||
TIMESTAMP(timezone=True), |
|||
nullable=False, |
|||
index=True, |
|||
server_default=text("NOW()"), |
|||
) |
|||
|
|||
user: User = relationship("User", innerjoin=True) |
|||
topic: Topic = relationship("Topic", innerjoin=True) |
|||
|
|||
def __init__(self, user: User, topic: Topic) -> None: |
|||
"""Ignore a topic.""" |
|||
self.user = user |
|||
self.topic = topic |
@ -0,0 +1,43 @@ |
|||
{% extends 'base_user_menu.jinja2' %} |
|||
|
|||
{% from 'macros/topics.jinja2' import render_topic_for_listing with context %} |
|||
|
|||
{% block title %}Ignored Topics{% endblock %} |
|||
|
|||
{% block main_heading %}Ignored Topics{% endblock %} |
|||
|
|||
{% block content %} |
|||
|
|||
{% if topics %} |
|||
<ol class="post-listing"> |
|||
{% for topic in topics if request.has_permission('view', topic) %} |
|||
<li>{{ render_topic_for_listing(topic, show_group=True) }}</li> |
|||
{% endfor %} |
|||
</ol> |
|||
|
|||
{% if topics.has_prev_page or topics.has_next_page %} |
|||
<div class="pagination"> |
|||
{% if topics.has_prev_page %} |
|||
<a class="page-item btn" |
|||
href="{{ request.current_listing_base_url({'before': topics.prev_page_before_id36}) }}" |
|||
>Prev</a> |
|||
{% endif %} |
|||
|
|||
{% if topics.has_next_page %} |
|||
<a class="page-item btn" |
|||
href="{{ request.current_listing_base_url({'after': topics.next_page_after_id36}) }}" |
|||
>Next</a> |
|||
{% endif %} |
|||
</div> |
|||
{% endif %} |
|||
{% else %} |
|||
<div class="empty"> |
|||
<h2 class="empty-title"> |
|||
{% block empty_message %} |
|||
You haven't ignored any topics |
|||
{% endblock %} |
|||
</h2> |
|||
</div> |
|||
{% endif %} |
|||
|
|||
{% endblock %} |
@ -0,0 +1,35 @@ |
|||
"""Views relating to ignored topics.""" |
|||
|
|||
from typing import Optional, 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.topic import Topic, TopicIgnore |
|||
from tildes.schemas.listing import PaginatedListingSchema |
|||
|
|||
|
|||
@view_config(route_name="ignored_topics", renderer="ignored_topics.jinja2") |
|||
@use_kwargs(PaginatedListingSchema) |
|||
def get_ignored_topics( |
|||
request: Request, after: Optional[str], before: Optional[str], per_page: int, |
|||
) -> dict: |
|||
"""Generate the ignored topics page.""" |
|||
# pylint: disable=unused-argument |
|||
user = request.user |
|||
|
|||
query = request.query(Topic).only_ignored().order_by(desc(TopicIgnore.created_time)) |
|||
|
|||
if before: |
|||
query = query.before_id36(before) |
|||
|
|||
if after: |
|||
query = query.after_id36(after) |
|||
|
|||
query = query.join_all_relationships() |
|||
|
|||
topics = query.all() |
|||
|
|||
return {"user": user, "topics": topics} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue