Browse Source

Display a "content type" for topics in listings

This should be stored in the database so that we can take advantage of
it for searching/filtering, but I want to test it on the live site first
and get input about what other types of content get posted. It'll be
simpler to leave it in code only for that, and I can add it to the
database later.
merge-requests/85/head
Deimos 5 years ago
parent
commit
0820886c14
  1. 7
      tildes/scss/modules/_topic.scss
  2. 21
      tildes/tildes/enums.py
  3. 45
      tildes/tildes/models/topic/topic.py
  4. 4
      tildes/tildes/templates/macros/topics.jinja2

7
tildes/scss/modules/_topic.scss

@ -81,6 +81,13 @@
white-space: nowrap; white-space: nowrap;
} }
// This puts a bullet in front of the topic-content-type only when there's something
// else in front of it (group name and/or tags)
.topic-content-type:not(:first-child)::before {
content: "";
margin-right: 0.4rem;
}
.topic-group { .topic-group {
margin-right: 0.4rem; margin-right: 0.4rem;
} }

21
tildes/tildes/enums.py

@ -115,6 +115,27 @@ class ScraperType(enum.Enum):
YOUTUBE = enum.auto() YOUTUBE = enum.auto()
class TopicContentType(enum.Enum):
"""Enum for the different types of content for topics."""
ARTICLE = enum.auto()
ASK = enum.auto()
IMAGE = enum.auto()
PDF = enum.auto()
TEXT = enum.auto()
TWEET = enum.auto()
VIDEO = enum.auto()
@property
def display_name(self) -> str:
"""Return the content type's name in a format more suitable for display."""
if self.name == "PDF":
return self.name
return self.name.capitalize()
class TopicSortOption(enum.Enum): class TopicSortOption(enum.Enum):
"""Enum for the different methods topics can be sorted by. """Enum for the different methods topics can be sorted by.

45
tildes/tildes/models/topic/topic.py

@ -5,7 +5,9 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from itertools import chain from itertools import chain
from pathlib import PurePosixPath
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, TYPE_CHECKING from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, TYPE_CHECKING
from urllib.parse import urlparse
from pyramid.security import Allow, Authenticated, Deny, DENY_ALL, Everyone from pyramid.security import Allow, Authenticated, Deny, DENY_ALL, Everyone
from sqlalchemy import ( from sqlalchemy import (
@ -24,7 +26,7 @@ from sqlalchemy.orm import deferred, relationship
from sqlalchemy.sql.expression import text from sqlalchemy.sql.expression import text
from titlecase import titlecase from titlecase import titlecase
from tildes.enums import TopicType
from tildes.enums import TopicContentType, TopicType
from tildes.lib.database import TagList from tildes.lib.database import TagList
from tildes.lib.datetime import utc_from_timestamp, utc_now from tildes.lib.datetime import utc_from_timestamp, utc_now
from tildes.lib.id import id_to_id36 from tildes.lib.id import id_to_id36
@ -394,7 +396,46 @@ class Topic(DatabaseModel):
@property @property
def is_spoiler(self) -> bool: def is_spoiler(self) -> bool:
"""Return whether the topic is marked as a spoiler.""" """Return whether the topic is marked as a spoiler."""
return "spoiler" in self.tags
return self.has_tag("spoiler")
def has_tag(self, check_tag: str) -> bool:
"""Return whether the topic has a tag or any sub-tag of it."""
if check_tag in self.tags:
return True
if any(tag.startswith(f"{check_tag}.") for tag in self.tags):
return True
return False
@property
def content_type(self) -> TopicContentType:
"""Return the content's type based on the topic's attributes."""
if self.is_text_type:
if self.has_tag("ask"):
return TopicContentType.ASK
return TopicContentType.TEXT
else:
parsed_url = urlparse(self.link) # type: ignore
url_path = PurePosixPath(parsed_url.path)
if url_path.suffix.lower() == ".pdf":
return TopicContentType.PDF
elif url_path.suffix.lower() in (".gif", ".jpeg", ".jpg", ".png"):
return TopicContentType.IMAGE
# individual sites should be handled in a more general manner; fine for now
if self.link_domain == "youtube.com" and parsed_url.path == "/watch":
return TopicContentType.VIDEO
try:
if self.link_domain == "twitter.com" and url_path.parts[2] == "status":
return TopicContentType.TWEET
except IndexError:
pass
return TopicContentType.ARTICLE
def get_content_metadata(self, key: str) -> Any: def get_content_metadata(self, key: str) -> Any:
"""Get a piece of content metadata "safely". """Get a piece of content metadata "safely".

4
tildes/tildes/templates/macros/topics.jinja2

@ -46,8 +46,10 @@
</ul> </ul>
{% endif %} {% endif %}
<span class="topic-content-type">{{ topic.content_type.display_name }}</span>
{% if topic.content_metadata_for_display %} {% if topic.content_metadata_for_display %}
<span class="topic-content-metadata">{{ topic.content_metadata_for_display }}</span>
<span class="topic-content-metadata">: {{ topic.content_metadata_for_display }}</span>
{% endif %} {% endif %}
{% if topic.unimportant_tags and request.user and request.user.show_tags_in_listings %} {% if topic.unimportant_tags and request.user and request.user.show_tags_in_listings %}

Loading…
Cancel
Save