Browse Source

Improve warnings when replying to old posts

Previously, the warning would only ever say "over a week old", even when
the topic/comment was much older than that. This adds a new function to
create a vague timedelta description for longer periods, and also
enables the Javascript to use it as well through adding the description
as a data attr on the reply button when a warning is needed, instead of
duplicating the logic in JS.
merge-requests/85/head
Deimos 5 years ago
parent
commit
33124e2be9
  1. 18
      tildes/static/js/behaviors/comment-reply-button.js
  2. 7
      tildes/tildes/jinja.py
  3. 30
      tildes/tildes/lib/datetime.py
  4. 11
      tildes/tildes/templates/macros/comments.jinja2
  5. 4
      tildes/tildes/templates/topic.jinja2
  6. 4
      tildes/tildes/views/topic.py

18
tildes/static/js/behaviors/comment-reply-button.js

@ -79,21 +79,17 @@ $.onmount("[data-js-comment-reply-button]", function() {
} }
} }
var parentCommentTimestamp = new Date(
$parentComment
.find(".comment-posted-time")
.first()
.attr("datetime")
);
// add a warning if the comment being replied to is over a week old
if (Date.now() - parentCommentTimestamp > 1000 * 3600 * 24 * 7) {
// add a warning about the comment's age, if necessary (determined by backend)
var warningAge = $(this).attr("data-js-old-warning-age");
if (warningAge) {
var warningDiv = document.createElement("div"); var warningDiv = document.createElement("div");
warningDiv.classList.add("warning-old-reply"); warningDiv.classList.add("warning-old-reply");
warningDiv.innerHTML = warningDiv.innerHTML =
'<p class="text-warning text-small">The comment you\'re replying to ' + '<p class="text-warning text-small">The comment you\'re replying to ' +
"is over a week old. Replying to old comments is fine as long as " +
"you're contributing to the discussion.</p>";
"is " +
warningAge +
" old. Replying to old comments is fine as long as you're " +
"contributing to the discussion.</p>";
clone.querySelector("form").prepend(warningDiv); clone.querySelector("form").prepend(warningDiv);
} }

7
tildes/tildes/jinja.py

@ -8,7 +8,11 @@ from urllib.parse import quote_plus
from pyramid.config import Configurator from pyramid.config import Configurator
from tildes.lib.datetime import adaptive_date, descriptive_timedelta
from tildes.lib.datetime import (
adaptive_date,
descriptive_timedelta,
vague_timedelta_description,
)
from tildes.models.comment import Comment from tildes.models.comment import Comment
from tildes.models.group import Group from tildes.models.group import Group
from tildes.models.topic import Topic from tildes.models.topic import Topic
@ -46,6 +50,7 @@ def includeme(config: Configurator) -> None:
"adaptive_date": adaptive_date, "adaptive_date": adaptive_date,
"ago": descriptive_timedelta, "ago": descriptive_timedelta,
"quote_plus": do_quote_plus, "quote_plus": do_quote_plus,
"vague_timedelta_description": vague_timedelta_description,
} }
# add custom jinja tests # add custom jinja tests

30
tildes/tildes/lib/datetime.py

@ -137,6 +137,36 @@ def descriptive_timedelta(
return result return result
def vague_timedelta_description(delta: timedelta) -> str:
"""Vaguely describe how long a timedelta refers to, like "over 2 weeks"."""
if delta.days < 1:
raise ValueError("The timedelta must be at least a day.")
day_thresholds = {
"year": 365,
"month": 30,
"week": 7,
"day": 1,
}
for threshold, days in day_thresholds.items():
if delta.days >= days:
largest_threshold = threshold
break
count = str(delta.days // day_thresholds[largest_threshold])
# set the strings we'll output based on count - change count of 1 to "a", otherwise
# pluralize the threshold name (e.g. change "week" to "weeks")
if count == "1":
count = "a"
period = largest_threshold
else:
period = largest_threshold + "s"
return f"over {count} {period}"
def adaptive_date( def adaptive_date(
target: datetime, abbreviate: bool = False, precision: Optional[int] = None target: datetime, abbreviate: bool = False, precision: Optional[int] = None
) -> str: ) -> str:

11
tildes/tildes/templates/macros/comments.jinja2

@ -212,7 +212,16 @@
{% endif %} {% endif %}
{% if request.has_permission('reply', comment) %} {% if request.has_permission('reply', comment) %}
<li><button class="btn-post-action" name="reply" data-js-comment-reply-button>Reply</button></li>
<li>
<button
class="btn-post-action"
name="reply"
data-js-comment-reply-button
{% if comment.age.days >= 7 %}
data-js-old-warning-age="{{ comment.age|vague_timedelta_description }}"
{% endif %}
>Reply</button>
</li>
{% endif %} {% endif %}
</menu> </menu>
{% endif %} {% endif %}

4
tildes/tildes/templates/topic.jinja2

@ -227,9 +227,9 @@
data-js-prevent-double-submit data-js-prevent-double-submit
data-js-confirm-leave-page-unsaved data-js-confirm-leave-page-unsaved
> >
{% if old_topic_warning %}
{% if topic.age.days >= 7 %}
<div class="warning-old-reply"> <div class="warning-old-reply">
<p class="text-warning text-small">This topic is over a week old. Replying to old topics is fine as long as you're contributing to the discussion.</p>
<p class="text-warning text-small">This topic is {{ topic.age|vague_timedelta_description }} old. Replying to old topics is fine as long as you're contributing to the discussion.</p>
</div> </div>
{% endif %} {% endif %}
<input type="hidden" name="csrf_token" value="{{ get_csrf_token() }}"> <input type="hidden" name="csrf_token" value="{{ get_csrf_token() }}">

4
tildes/tildes/views/topic.py

@ -7,7 +7,6 @@ from collections import namedtuple
from decimal import Decimal from decimal import Decimal
from typing import Any, Dict, Optional, Union from typing import Any, Dict, Optional, Union
from datetime import timedelta
from marshmallow import missing, ValidationError from marshmallow import missing, ValidationError
from marshmallow.fields import Boolean, String from marshmallow.fields import Boolean, String
from pyramid.httpexceptions import HTTPFound from pyramid.httpexceptions import HTTPFound
@ -422,8 +421,6 @@ def get_topic(request: Request, comment_order: CommentTreeSortOption) -> dict:
tree.uncollapse_new_comments(topic.last_visit_time) tree.uncollapse_new_comments(topic.last_visit_time)
tree.finalize_collapsing_maximized() tree.finalize_collapsing_maximized()
old_topic_warning = topic.age > timedelta(days=7)
return { return {
"topic": topic, "topic": topic,
"log": log, "log": log,
@ -431,7 +428,6 @@ def get_topic(request: Request, comment_order: CommentTreeSortOption) -> dict:
"comment_order": comment_order, "comment_order": comment_order,
"comment_order_options": CommentTreeSortOption, "comment_order_options": CommentTreeSortOption,
"comment_label_options": CommentLabelOption, "comment_label_options": CommentLabelOption,
"old_topic_warning": old_topic_warning,
} }

Loading…
Cancel
Save