Browse Source

Hide tags in listings by default + layout updates

Topic tags are no longer shown in listing pages by default (except
"important" ones such as "nsfw" and "spoiler"), and the layout and
emphasis on them has been adjusted in multiple other ways as well. A
preference to continue showing them in listings has been added, and this
preference is enabled by default for all users with the "topic.tag"
permission (ability to tag any users' topics).

Other changes:

* The tagging field is collapsed by default when posting a new topic. If
  a user expands it and enters tags, it will be shown expanded in the
  future. It will also be expanded by default after the user
  adds/changes tags on a topic, and will also be set automatically for
  users that have shown an interest in tagging recently (by submitting a
  topic with tags or changing tags).
* "Content metadata" such as word count and duration is now shown next
  to the group name (where tags were previously), instead of after the
  title.
* Topic icons (favicons) are now shown next to the domain name, instead
  of before the title. Blank icons no longer have a dashed border and
  are now just an empty space.
* When on a topic's comments page, tags are now shown in the main
  content area, below the "byline" information about who posted the
  topic and when, instead of in the sidebar.
* Other minor layout changes to adjust for tags, as well as prepare for
  some other upcoming changes like adding "actions" to topics in
  listings.
merge-requests/85/head
Deimos 5 years ago
parent
commit
bc6fc08a53
  1. 72
      tildes/alembic/versions/d56e71257a86_add_tag_related_user_settings.py
  2. 1
      tildes/scripts/generate_site_icons_css.py
  3. 36
      tildes/scss/modules/_topic.scss
  4. 12
      tildes/scss/themes/_theme_base.scss
  5. 16
      tildes/tildes/models/topic/topic.py
  6. 6
      tildes/tildes/models/user/user.py
  7. 8
      tildes/tildes/templates/includes/new_topic_form.jinja2
  8. 11
      tildes/tildes/templates/includes/topic_tags.jinja2
  9. 3
      tildes/tildes/templates/intercooler/topic_tags_edit.jinja2
  10. 2
      tildes/tildes/templates/macros/forms.jinja2
  11. 36
      tildes/tildes/templates/macros/topics.jinja2
  12. 21
      tildes/tildes/templates/settings.jinja2
  13. 6
      tildes/tildes/templates/topic.jinja2
  14. 5
      tildes/tildes/views/api/web/topic.py
  15. 16
      tildes/tildes/views/api/web/user.py
  16. 5
      tildes/tildes/views/topic.py

72
tildes/alembic/versions/d56e71257a86_add_tag_related_user_settings.py

@ -0,0 +1,72 @@
"""Add tag-related user settings
Revision ID: d56e71257a86
Revises: a195ddbb4be6
Create Date: 2019-09-27 23:53:34.287619
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "d56e71257a86"
down_revision = "a195ddbb4be6"
branch_labels = None
depends_on = None
def upgrade():
op.add_column(
"users",
sa.Column(
"show_tags_in_listings",
sa.Boolean(),
server_default="false",
nullable=False,
),
)
op.add_column(
"users",
sa.Column(
"show_tags_on_new_topic",
sa.Boolean(),
server_default="false",
nullable=False,
),
)
# enable the new settings for any users that have the "topic.tag" permission
op.execute(
"""
UPDATE users
SET show_tags_in_listings = true, show_tags_on_new_topic = true
WHERE permissions ? 'topic.tag'
"""
)
# show tagging on new topics for any users that have changed tags recently or posted
# a topic that has tags and wasn't re-tagged by another user
op.execute(
"""
UPDATE users
SET show_tags_on_new_topic = true
WHERE user_id IN (
SELECT DISTINCT(user_id) FROM log_topics WHERE event_type = 'TOPIC_TAG'
) OR user_id IN (
SELECT DISTINCT(user_id) FROM topics
WHERE tags != '{}' AND created_time > NOW() - INTERVAL '30 days'
AND NOT EXISTS (
SELECT * FROM log_topics
WHERE topic_id = topics.topic_id
AND event_type = 'TOPIC_TAG'
AND user_id != topics.user_id
)
)
"""
)
def downgrade():
op.drop_column("users", "show_tags_on_new_topic")
op.drop_column("users", "show_tags_in_listings")

1
tildes/scripts/generate_site_icons_css.py

@ -15,7 +15,6 @@ OUTPUT_FILE = "/opt/tildes/static/css/site-icons.css"
CSS_RULE = """
.topic-icon-{domain} {{
background-image: url('/images/site-icons/{filename}');
border: 0;
}}
"""

36
tildes/scss/modules/_topic.scss

@ -15,7 +15,7 @@
grid-template-areas:
"title voting"
"metadata voting"
"info info";
"info voting";
grid-template-columns: 1fr auto;
grid-gap: 0.2rem;
@ -42,8 +42,6 @@
header {
grid-area: title;
display: flex;
min-height: 1rem;
}
.topic-metadata {
@ -91,9 +89,7 @@
width: 16px;
height: 16px;
flex-shrink: 0;
margin-top: 2px;
margin-right: 0.2rem;
border: 1px dashed;
background-size: 16px 16px;
}
@ -115,9 +111,16 @@
.topic-metadata {
display: flex;
flex-wrap: wrap;
align-items: baseline;
max-height: 4rem;
overflow: hidden;
// when users enable showing tags in listings, force them to wrap to a new line
.topic-tags:last-child {
width: 100%;
margin-top: 0.2rem;
}
}
.topic-tags {
@ -137,6 +140,8 @@
font-weight: normal;
// make the voting button wider on large screens
min-width: 2rem;
@media (min-width: $size-sm) {
min-width: 3rem;
}
@ -210,10 +215,6 @@
display: grid;
grid-template-columns: 1fr 1.5fr 0.7fr;
@media (min-width: $size-sm) {
grid-template-columns: 1fr 1.2fr 1fr;
}
grid-column-gap: 0.4rem;
max-width: 32rem;
@ -229,6 +230,8 @@
}
.topic-info-source {
display: flex;
align-items: center;
overflow: hidden;
text-overflow: ellipsis;
}
@ -244,6 +247,19 @@
font-size: 0.6rem;
}
.topic-full-tags {
margin-bottom: 0.4rem;
font-size: 0.6rem;
a {
text-decoration: underline;
&:hover {
text-decoration: none;
}
}
}
.topic-full-link {
display: flex;
word-break: break-all;
@ -287,7 +303,7 @@
"title voting"
"metadata voting"
"content voting"
"info info";
"info voting";
}
}

12
tildes/scss/themes/_theme_base.scss

@ -545,20 +545,16 @@
}
}
.topic-content-metadata {
.topic-full-byline {
color: map-get($theme, "foreground-secondary");
}
.topic-full-byline {
.topic-full-tags {
color: map-get($theme, "foreground-secondary");
}
.topic-icon {
border-color: map-get($theme, "link");
a {
color: map-get($theme, "foreground-secondary");
}
.topic-info {
color: map-get($theme, "foreground-middle");
}
.topic-info-comments-new {

16
tildes/tildes/models/topic/topic.py

@ -68,6 +68,8 @@ class Topic(DatabaseModel):
- deleted_time will be set when is_deleted is set to true
"""
# pylint: disable=too-many-public-methods
schema_class = TopicSchema
__tablename__ = "topics"
@ -178,6 +180,17 @@ class Topic(DatabaseModel):
def tags(self, new_tags: List[str]) -> None:
self._tags = new_tags
@property
def important_tags(self) -> List[str]:
"""Return only the topic's "important" tags."""
return [tag for tag in self.tags if tag in SPECIAL_TAGS]
@property
def unimportant_tags(self) -> List[str]:
"""Return only the topic's tags that *aren't* considered "important"."""
important_tags = set(self.important_tags)
return [tag for tag in self.tags if tag not in important_tags]
def __repr__(self) -> str:
"""Display the topic's title and ID as its repr format."""
return f'<Topic "{self.title}" ({self.topic_id})>'
@ -447,7 +460,8 @@ class Topic(DatabaseModel):
if published_timestamp:
published = utc_from_timestamp(published_timestamp)
if self.created_time - published > timedelta(days=3):
metadata_strings.append(published.strftime("%b %-d %Y"))
date_str = published.strftime("%b %-d %Y")
metadata_strings.append(f"published {date_str}")
return ", ".join(metadata_strings)

6
tildes/tildes/models/user/user.py

@ -107,6 +107,12 @@ class User(DatabaseModel):
)
open_new_tab_text: bool = Column(Boolean, nullable=False, server_default="false")
theme_default: str = Column(Text)
show_tags_in_listings: bool = Column(
Boolean, nullable=False, server_default="false"
)
show_tags_on_new_topic: bool = Column(
Boolean, nullable=False, server_default="false"
)
is_deleted: bool = Column(
Boolean, nullable=False, server_default="false", index=True
)

8
tildes/tildes/templates/includes/new_topic_form.jinja2

@ -46,7 +46,15 @@
</div>
</fieldset>
{# Hide the tag-adding form in a <details> unless it should be shown for this user #}
{% if request.user.show_tags_on_new_topic %}
{{ topic_tagging(autocomplete_options=group.common_topic_tags, value=tags) }}
{% else %}
<details>
<summary>Add tags (optional)</summary>
{{ topic_tagging(autocomplete_options=group.common_topic_tags, value=tags) }}
</details>
{% endif %}
<div class="form-buttons">
<button type="submit" class="btn btn-primary">Post topic</button>

11
tildes/tildes/templates/includes/topic_tags.jinja2

@ -1,12 +1,9 @@
{# Copyright (c) 2018 Tildes contributors <code@tildes.net> #}
{# SPDX-License-Identifier: AGPL-3.0-or-later #}
{% from 'macros/topics.jinja2' import topic_tag %}
<ul class="topic-tags">
<div class="topic-full-tags">{% if topic.tags %}Tags:{% endif %}
{% for tag in topic.tags %}
{{ topic_tag(tag, "/~"~topic.group.path~"?tag="~tag.replace(' ', '_')) }}
{% else %}
<li class="label label-topic-tag">No tags</li>
<a href="/~{{ topic.group.path }}?tag={{ tag.replace(" ", "_") }}">{{ tag }}</a>
{%- if not loop.last %},{% endif %}
{% endfor %}
</ul>
</div>

3
tildes/tildes/templates/intercooler/topic_tags_edit.jinja2

@ -9,7 +9,8 @@
'ic_topic_tags',
topic_id36=topic.topic_id36,
) }}"
data-ic-target="#sidebar .topic-tags"
data-ic-target=".topic-full-tags"
data-ic-replace-target="true"
data-js-remove-on-success
>
<input type="hidden" name="conflict_check" id="conflict_check" value="{{ topic.tags|join(",") }}">

2
tildes/tildes/templates/macros/forms.jinja2

@ -35,7 +35,7 @@
{% macro topic_tagging(value=None, auto_focus=False, autocomplete_options=None) %}
<div class="form-autocomplete form-group" data-js-autocomplete-container data-js-ctrl-enter-submit-form>
<label class="form-label" for="tags">
<span>Tags (optional, comma-separated)</span>
<span>Tags (comma-separated)</span>
<a href="https://docs.tildes.net/instructions/posting-on-tildes#tagging-topics" target="_blank" tabindex="-1">Tagging help</a>
</label>
<div class="form-autocomplete-input form-input">

36
tildes/tildes/templates/macros/topics.jinja2

@ -11,11 +11,6 @@
data-topic-posted-by="{{ topic.user.username }}"
>
<header>
{% if topic.is_link_type %}
<div class="topic-icon topic-icon-{{ topic.link_domain.replace('.', '_') }}"></div>
{% endif %}
<div>
<h1 class="topic-title">
{% if topic.is_text_type %}
<a
@ -32,10 +27,6 @@
>{{ topic.title }}</a>
{% endif %}
</h1>
{% if topic.content_metadata_for_display %}
<span class="topic-content-metadata">({{ topic.content_metadata_for_display }})</span>
{% endif %}
</div>
</header>
<div class="topic-metadata">
@ -43,9 +34,25 @@
<span class="topic-group">{{ group_linked(topic.group.path) }}</span>
{% endif %}
{% if topic.tags %}
{% if topic.important_tags %}
<ul class="topic-tags">
{% for tag in topic.important_tags %}
{% if request.matched_route.name in ('home', 'group') %}
{{ topic_tag(tag, request.current_listing_normal_url({'tag': tag.replace(' ', '_')})) }}
{% else %}
{{ topic_tag(tag, request.route_url('home', _query=[('tag', tag.replace(' ', '_'))])) }}
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% if topic.content_metadata_for_display %}
<span class="topic-content-metadata">{{ topic.content_metadata_for_display }}</span>
{% endif %}
{% if topic.unimportant_tags and request.user and request.user.show_tags_in_listings %}
<ul class="topic-tags">
{% for tag in topic.tags %}
{% for tag in topic.unimportant_tags %}
{% if request.matched_route.name in ('home', 'group') %}
{{ topic_tag(tag, request.current_listing_normal_url({'tag': tag.replace(' ', '_')})) }}
{% else %}
@ -85,7 +92,12 @@
{% if topic.is_user_treated_as_source %}
aria-label="Posted by">{{ username_linked(topic.user.username) }}
{% else %}
aria-label="Link source">{{ topic.link_source }}
aria-label="Link source">
{% if topic.is_link_type %}
<div class="topic-icon topic-icon-{{ topic.link_domain.replace('.', '_') }}"></div>
{% endif %}
{{ topic.link_source }}
{% endif %}
</div>

21
tildes/tildes/templates/settings.jinja2

@ -37,6 +37,27 @@
</form>
</li>
<li>
<form
name="show-tags-in-listings"
autocomplete="off"
data-ic-patch-to="{{ request.route_url('ic_user', username=request.user.username) }}"
>
<div class="form-group">
<label class="form-checkbox">
<input
type="checkbox"
id="show_tags_in_listings"
name="show_tags_in_listings"
data-js-autosubmit-on-change
{% if request.user.show_tags_in_listings %}checked{% endif %}
>
<i class="form-icon"></i> Show topic tags in listing pages (home page, groups, etc.)
</label>
</div>
</form>
</li>
<li>
<form
name="interact-mark-notifications-read"

6
tildes/tildes/templates/topic.jinja2

@ -48,6 +48,7 @@
</span>
{% endif %}
</div>
{% include "includes/topic_tags.jinja2" %}
</header>
{% if topic.is_deleted %}
@ -258,11 +259,6 @@
>
</dd>
<dt>Tags</dt>
<dd>
{% include 'includes/topic_tags.jinja2' %}
</dd>
<dt>Comments</dt>
{% if topic.num_comments > 0 %}
<dd>

5
tildes/tildes/views/api/web/topic.py

@ -204,6 +204,11 @@ def put_tag_topic(request: Request, tags: str, conflict_check: str) -> dict:
)
)
# show the tag field by default in the future when the tagger is posting a new topic
if not request.user.show_tags_on_new_topic:
request.user.show_tags_on_new_topic = True
request.db_session.add(request.user)
return {"topic": topic}

16
tildes/tildes/views/api/web/user.py

@ -144,6 +144,22 @@ def post_disable_two_factor(request: Request, code: str) -> Response:
return {}
@ic_view_config(
route_name="user",
request_method="PATCH",
request_param="ic-trigger-name=show-tags-in-listings",
permission="change_show_tags_in_listings_setting",
)
def patch_change_show_tags_in_listings(request: Request) -> Response:
"""Change the user's "show tags in listings" setting."""
user = request.context
show_tags = bool(request.params.get("show_tags_in_listings"))
user.show_tags_in_listings = show_tags
return IC_NOOP
@ic_view_config(
route_name="user",
request_method="PATCH",

5
tildes/tildes/views/topic.py

@ -124,6 +124,11 @@ def post_group_topics(
request.db_session.add(LogTopic(LogEventType.TOPIC_POST, request, new_topic))
# if the user added tags to the topic, show the field by default in the future
if tags and not request.user.show_tags_on_new_topic:
request.user.show_tags_on_new_topic = True
request.db_session.add(request.user)
# flush the changes to the database so the new topic's ID is generated
request.db_session.flush()

Loading…
Cancel
Save