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