Merge pull request #1078 from bookwyrm-social/templatetags

Refactors templatetags
This commit is contained in:
Mouse Reeve 2021-05-11 16:39:53 -07:00 committed by GitHub
commit 1ea07448c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 243 additions and 302 deletions

View File

@ -1,6 +1,6 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load markdown %}
{% load humanize %} {% load humanize %}
{% block title %}{{ author.name }}{% endblock %} {% block title %}{{ author.name }}{% endblock %}
@ -66,7 +66,7 @@
{% endif %} {% endif %}
<div class="column"> <div class="column">
{% if author.bio %} {% if author.bio %}
{{ author.bio | to_markdown | safe }} {{ author.bio|to_markdown|safe }}
{% endif %} {% endif %}
</div> </div>
</div> </div>

View File

@ -257,7 +257,7 @@
{% include 'snippets/stars.html' with rating=rating.rating %} {% include 'snippets/stars.html' with rating=rating.rating %}
</div> </div>
<div> <div>
<a href="{{ rating.remote_id }}">{{ rating.published_date | naturaltime }}</a> <a href="{{ rating.remote_id }}">{{ rating.published_date|naturaltime }}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
{% block title %}{% blocktrans with book_title=work.title %}Editions of {{ book_title }}{% endblocktrans %}{% endblock %} {% block title %}{% blocktrans with book_title=work.title %}Editions of {{ book_title }}{% endblocktrans %}{% endblock %}

View File

@ -1,5 +1,5 @@
{% spaceless %} {% spaceless %}
{% load bookwyrm_tags %} {% load utilities %}
{% with 0|uuid as uuid %} {% with 0|uuid as uuid %}
<div <div

View File

@ -1,6 +1,6 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% block title %}{% trans "Compose status" %}{% endblock %} {% block title %}{% trans "Compose status" %}{% endblock %}
{% block content %} {% block content %}

View File

@ -1,5 +1,6 @@
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% load markdown %}
{% load humanize %} {% load humanize %}
<div class="card is-stretchable"> <div class="card is-stretchable">
@ -19,7 +20,7 @@
<div> <div>
{% if user.summary %} {% if user.summary %}
{{ user.summary | to_markdown | safe | truncatechars_html:40 }} {{ user.summary|to_markdown|safe|truncatechars_html:40 }}
{% else %}&nbsp;{% endif %} {% else %}&nbsp;{% endif %}
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load markdown %}
{% block title %}{% trans "Welcome" %}{% endblock %} {% block title %}{% trans "Welcome" %}{% endblock %}
@ -49,7 +49,7 @@
{% else %} {% else %}
<h2 class="title">{% trans "This instance is closed" %}</h2> <h2 class="title">{% trans "This instance is closed" %}</h2>
<p>{{ site.registration_closed_text | safe}}</p> <p>{{ site.registration_closed_text|safe}}</p>
{% if site.allow_invite_requests %} {% if site.allow_invite_requests %}
{% if request_received %} {% if request_received %}
@ -64,7 +64,7 @@
<label for="id_request_email" class="label">{% trans "Email address:" %}</label> <label for="id_request_email" class="label">{% trans "Email address:" %}</label>
<input type="email" name="email" maxlength="255" class="input" required="" id="id_request_email"> <input type="email" name="email" maxlength="255" class="input" required="" id="id_request_email">
{% for error in request_form.email.errors %} {% for error in request_form.email.errors %}
<p class="help is-danger">{{ error | escape }}</p> <p class="help is-danger">{{ error|escape }}</p>
{% endfor %} {% endfor %}
</div> </div>
<button type="submit" class="button is-link">{% trans "Submit" %}</button> <button type="submit" class="button is-link">{% trans "Submit" %}</button>
@ -80,7 +80,7 @@
{% include 'user/user_preview.html' with user=request.user %} {% include 'user/user_preview.html' with user=request.user %}
{% if request.user.summary %} {% if request.user.summary %}
<div class="box content"> <div class="box content">
{{ request.user.summary | to_markdown | safe }} {{ request.user.summary|to_markdown|safe }}
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@ -1,5 +1,5 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load markdown %}
{% load i18n %} {% load i18n %}
{% if book %} {% if book %}

View File

@ -1,7 +1,6 @@
{% extends 'feed/feed_layout.html' %} {% extends 'feed/feed_layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
{% load humanize %}
{% block panel %} {% block panel %}
<h1 class="title"> <h1 class="title">

View File

@ -1,6 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
{% block title %}{% trans "Updates" %}{% endblock %} {% block title %}{% trans "Updates" %}{% endblock %}

View File

@ -1,5 +1,5 @@
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% load humanize %} {% load humanize %}
<div class="columns is-mobile scroll-x mb-0"> <div class="columns is-mobile scroll-x mb-0">
{% for user in suggested_users %} {% for user in suggested_users %}

View File

@ -1,4 +1,4 @@
{% load bookwyrm_tags %} {% load status_display %}
<div class="block"> <div class="block">
{% with depth=depth|add:1 %} {% with depth=depth|add:1 %}

View File

@ -1,6 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
{% load humanize %} {% load humanize %}
{% block title %}{% trans "Import Status" %}{% endblock %} {% block title %}{% trans "Import Status" %}{% endblock %}
@ -54,8 +53,8 @@
<input class="checkbox" type="checkbox" name="import_item" value="{{ item.id }}" id="import-item-{{ item.id }}"> <input class="checkbox" type="checkbox" name="import_item" value="{{ item.id }}" id="import-item-{{ item.id }}">
<label for="import-item-{{ item.id }}"> <label for="import-item-{{ item.id }}">
Line {{ item.index }}: Line {{ item.index }}:
<strong>{{ item.data|dict_key:'Title' }}</strong> by <strong>{{ item.data.Title }}</strong> by
{{ item.data|dict_key:'Author' }} {{ item.data.Author }}
</label> </label>
<p> <p>
{{ item.fail_reason }}. {{ item.fail_reason }}.
@ -90,8 +89,8 @@
<li class="pb-1"> <li class="pb-1">
<p> <p>
Line {{ item.index }}: Line {{ item.index }}:
<strong>{{ item.data|dict_key:'Title' }}</strong> by <strong>{{ item.data.Title }}</strong> by
{{ item.data|dict_key:'Author' }} {{ item.data.Author }}
</p> </p>
<p> <p>
{{ item.fail_reason }}. {{ item.fail_reason }}.
@ -130,10 +129,10 @@
{% endif %} {% endif %}
</td> </td>
<td> <td>
{{ item.data|dict_key:'Title' }} {{ item.data.Title }}
</td> </td>
<td> <td>
{{ item.data|dict_key:'Author' }} {{ item.data.Author }}
</td> </td>
<td> <td>
{% if item.book %} {% if item.book %}

View File

@ -1,4 +1,4 @@
{% load bookwyrm_tags %} {% load layout %}
{% load i18n %} {% load i18n %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{% get_lang %}"> <html lang="{% get_lang %}">

View File

@ -1,12 +1,13 @@
{% extends 'lists/list_layout.html' %} {% extends 'lists/list_layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load markdown %}
{% block panel %} {% block panel %}
{% if request.user == list.user and pending_count %} {% if request.user == list.user and pending_count %}
<div class="block content"> <div class="block content">
<p> <p>
<a href="{% url 'list-curate' list.id %}">{{ pending_count }} book{{ pending_count | pluralize }} awaiting your approval</a> <a href="{% url 'list-curate' list.id %}">{{ pending_count }} book{{ pending_count|pluralize }} awaiting your approval</a>
</p> </p>
</div> </div>
{% endif %} {% endif %}

View File

@ -1,4 +1,4 @@
{% load bookwyrm_tags %} {% load markdown %}
<div class="columns is-multiline"> <div class="columns is-multiline">
{% for list in lists %} {% for list in lists %}
<div class="column is-one-quarter"> <div class="column is-one-quarter">

View File

@ -1,6 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
{% block title %}{{ list.name }}{% endblock %} {% block title %}{{ list.name }}{% endblock %}

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load bookwyrm_tags %} {% load utilities %}
{% load i18n %} {% load i18n %}
{% block title %}{% trans "Lists" %}{% endblock %} {% block title %}{% trans "Lists" %}{% endblock %}

View File

@ -1,6 +1,5 @@
{% extends 'settings/admin_layout.html' %} {% extends 'settings/admin_layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
{% load humanize %} {% load humanize %}
{% block title %}{% blocktrans with report_id=report.id username=report.user.username %}Report #{{ report_id }}: {{ username }}{% endblocktrans %}{% endblock %} {% block title %}{% blocktrans with report_id=report.id username=report.user.username %}Report #{{ report_id }}: {{ username }}{% endblocktrans %}{% endblock %}
@ -29,7 +28,7 @@
<a href="{{ comment.user.local_path }}">{{ comment.user.display_name }}</a> <a href="{{ comment.user.local_path }}">{{ comment.user.display_name }}</a>
</div> </div>
<div class="card-footer-item"> <div class="card-footer-item">
{{ comment.created_date | naturaltime }} {{ comment.created_date|naturaltime }}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load humanize %}
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load humanize %}
{% block title %}{% trans "Notifications" %}{% endblock %} {% block title %}{% trans "Notifications" %}{% endblock %}

View File

@ -1,5 +1,4 @@
{% extends 'search/layout.html' %} {% extends 'search/layout.html' %}
{% load bookwyrm_tags %}
{% block panel %} {% block panel %}

View File

@ -1,7 +1,8 @@
{% extends 'settings/admin_layout.html' %} {% extends 'settings/admin_layout.html' %}
{% block title %}{{ server.server_name }}{% endblock %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load markdown %}
{% block title %}{{ server.server_name }}{% endblock %}
{% block header %} {% block header %}
{{ server.server_name }} {{ server.server_name }}

View File

@ -1,3 +1,2 @@
{% load bookwyrm_tags %}
<img class="avatar image {% if large %}is-96x96{% elif medium %}is-48x48{% else %}is-32x32{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}" {% if ariaHide %}aria-hidden="true"{% endif %} alt="{{ user.alt_text }}"> <img class="avatar image {% if large %}is-96x96{% elif medium %}is-48x48{% else %}is-32x32{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}" {% if ariaHide %}aria-hidden="true"{% endif %} alt="{{ user.alt_text }}">

View File

@ -1,6 +1,5 @@
{% spaceless %} {% spaceless %}
{% load bookwyrm_tags %}
{% load i18n %} {% load i18n %}
<figure <figure

View File

@ -1,5 +1,5 @@
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% if book.authors %} {% if book.authors %}
{% blocktrans with path=book.local_path title=book|title %}<a href="{{ path }}">{{ title }}</a> by {% endblocktrans %}{% include 'snippets/authors.html' with book=book %} {% blocktrans with path=book.local_path title=book|title %}<a href="{{ path }}">{{ title }}</a> by {% endblocktrans %}{% include 'snippets/authors.html' with book=book %}
{% else %} {% else %}

View File

@ -1,4 +1,5 @@
{% load bookwyrm_tags %} {% load interaction %}
{% load utilities %}
{% load i18n %} {% load i18n %}
{% with status.id|uuid as uuid %} {% with status.id|uuid as uuid %}

View File

@ -1,6 +1,6 @@
{% load humanize %} {% load humanize %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% with status_type=request.GET.status_type %} {% with status_type=request.GET.status_type %}
<div class="tab-group"> <div class="tab-group">

View File

@ -1,4 +1,7 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load utilities %}
{% load status_display %}
{% load i18n %} {% load i18n %}
<form class="is-flex-grow-1" name="{{ type }}" action="/post/{% if type == 'direct' %}status{% else %}{{ type }}{% endif %}" method="post" id="tab-{{ type }}-{{ book.id }}{{ reply_parent.id }}"> <form class="is-flex-grow-1" name="{{ type }}" action="/post/{% if type == 'direct' %}status{% else %}{{ type }}{% endif %}" method="post" id="tab-{{ type }}-{{ book.id }}{{ reply_parent.id }}">
{% csrf_token %} {% csrf_token %}

View File

@ -1,5 +1,7 @@
{% load bookwyrm_tags %} {% load interaction %}
{% load utilities %}
{% load i18n %} {% load i18n %}
{% with status.id|uuid as uuid %} {% with status.id|uuid as uuid %}
<form name="favorite" action="/favorite/{{ status.id }}" method="POST" class="interaction fav-{{ status.id }}-{{ uuid }} {% if request.user|liked:status %}is-hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}"> <form name="favorite" action="/favorite/{{ status.id }}" method="POST" class="interaction fav-{{ status.id }}-{{ uuid }} {% if request.user|liked:status %}is-hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}">
{% csrf_token %} {% csrf_token %}

View File

@ -1,6 +1,5 @@
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% if request.user in user.follow_requests.all %}
{% if request.user|follow_request_exists:user %}
<div class="field is-grouped"> <div class="field is-grouped">
<form action="/accept-follow-request/" method="POST"> <form action="/accept-follow-request/" method="POST">
{% csrf_token %} {% csrf_token %}

View File

@ -1,6 +1,5 @@
{% spaceless %} {% spaceless %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
<div class=" <div class="
field is-grouped field is-grouped

View File

@ -1,5 +1,5 @@
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
<div class="select {{ class }}"> <div class="select {{ class }}">
{% with 0|uuid as uuid %} {% with 0|uuid as uuid %}
{% if not no_label %} {% if not no_label %}

View File

@ -1,5 +1,6 @@
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% with 0|uuid as report_uuid %} {% with 0|uuid as report_uuid %}
{% trans "Report" as button_text %} {% trans "Report" as button_text %}

View File

@ -1,4 +1,6 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load utilities %}
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
{% with book.id|uuid as uuid %} {% with book.id|uuid as uuid %}

View File

@ -1,5 +1,7 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load utilities %}
{% load i18n %} {% load i18n %}
{% for shelf in shelves %} {% for shelf in shelves %}
{% comparison_bool shelf.identifier active_shelf.shelf.identifier as is_current %} {% comparison_bool shelf.identifier active_shelf.shelf.identifier as is_current %}
{% if dropdown %}<li role="menuitem" class="dropdown-item p-0">{% endif %} {% if dropdown %}<li role="menuitem" class="dropdown-item p-0">{% endif %}

View File

@ -1,4 +1,5 @@
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load markdown %}
{% load i18n %} {% load i18n %}
{% with status_type=status.status_type %} {% with status_type=status.status_type %}

View File

@ -1,6 +1,7 @@
{% spaceless %} {% spaceless %}
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load markdown %}
{% load i18n %} {% load i18n %}
{% if not hide_book %} {% if not hide_book %}

View File

@ -1,7 +1,6 @@
{% extends 'components/card.html' %} {% extends 'components/card.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% load humanize %}
{% block card-header %} {% block card-header %}
<div class="card-header-title has-background-white-ter is-block"> <div class="card-header-title has-background-white-ter is-block">

View File

@ -1,5 +1,6 @@
{% load bookwyrm_tags %} {% load status_display %}
{% load i18n %} {% load i18n %}
{% if not status.deleted %} {% if not status.deleted %}
{% if status.status_type == 'Announce' %} {% if status.status_type == 'Announce' %}
<a href="{{ status.user.local_path }}"> <a href="{{ status.user.local_path }}">

View File

@ -1,4 +1,5 @@
{% load bookwyrm_tags %} {% load utilities %}
{% load status_display %}
{% load i18n %} {% load i18n %}
{% load humanize %} {% load humanize %}
@ -29,7 +30,7 @@
</span> </span>
{% if status.status_type == 'GeneratedNote' %} {% if status.status_type == 'GeneratedNote' %}
{{ status.content | safe }} {{ status.content|safe }}
{% elif status.status_type == 'Rating' %} {% elif status.status_type == 'Rating' %}
{% trans "rated" %} {% trans "rated" %}
{% elif status.status_type == 'Review' %} {% elif status.status_type == 'Review' %}

View File

@ -1,6 +1,6 @@
{% extends 'components/dropdown.html' %} {% extends 'components/dropdown.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% block dropdown-trigger %} {% block dropdown-trigger %}
<span class="icon icon-dots-three m-0-mobile"></span> <span class="icon icon-dots-three m-0-mobile"></span>

View File

@ -1,4 +1,5 @@
{% load bookwyrm_tags %} {% load markdown %}
{% load utilities %}
{% load i18n %} {% load i18n %}
{% with 0|uuid as uuid %} {% with 0|uuid as uuid %}

View File

@ -1,6 +1,6 @@
{% extends 'components/dropdown.html' %} {% extends 'components/dropdown.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% block dropdown-trigger %} {% block dropdown-trigger %}
<span class="icon icon-dots-three"> <span class="icon icon-dots-three">

View File

@ -1,7 +1,8 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load i18n %} {% load i18n %}
{% load humanize %} {% load humanize %}
{% load bookwyrm_tags %} {% load utilities %}
{% load markdown %}
{% block title %}{{ user.display_name }}{% endblock %} {% block title %}{{ user.display_name }}{% endblock %}
@ -23,7 +24,7 @@
{% if user.summary %} {% if user.summary %}
<div class="column box has-background-white-bis content"> <div class="column box has-background-white-bis content">
{{ user.summary | to_markdown | safe }} {{ user.summary|to_markdown|safe }}
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@ -1,6 +1,6 @@
{% extends 'user/layout.html' %} {% extends 'user/layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% block tabs %} {% block tabs %}
{% with user|username as username %} {% with user|username as username %}

View File

@ -1,5 +1,6 @@
{% extends 'user/layout.html' %} {% extends 'user/layout.html' %}
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
{% load utilities %}
{% load humanize %} {% load humanize %}
{% load i18n %} {% load i18n %}
@ -79,7 +80,9 @@
<th>{% trans "Shelved" %}</th> <th>{% trans "Shelved" %}</th>
<th>{% trans "Started" %}</th> <th>{% trans "Started" %}</th>
<th>{% trans "Finished" %}</th> <th>{% trans "Finished" %}</th>
{% if ratings %}<th>{% trans "Rating" %}</th>{% endif %} {% if request.user.is_authenticated %}
<th>{% trans "Rating" %}</th>
{% endif %}
{% if shelf.user == request.user %} {% if shelf.user == request.user %}
<th aria-hidden="true"></th> <th aria-hidden="true"></th>
{% endif %} {% endif %}
@ -99,18 +102,18 @@
{% include 'snippets/authors.html' %} {% include 'snippets/authors.html' %}
</td> </td>
<td data-title="{% trans "Shelved" %}"> <td data-title="{% trans "Shelved" %}">
{{ book.created_date | naturalday }} {{ book.created_date|naturalday }}
</td> </td>
{% latest_read_through book user as read_through %} {% latest_read_through book user as read_through %}
<td data-title="{% trans "Started" %}"> <td data-title="{% trans "Started" %}">
{{ read_through.start_date | naturalday |default_if_none:""}} {{ read_through.start_date|naturalday|default_if_none:""}}
</td> </td>
<td data-title="{% trans "Finished" %}"> <td data-title="{% trans "Finished" %}">
{{ read_through.finish_date | naturalday |default_if_none:""}} {{ read_through.finish_date|naturalday|default_if_none:""}}
</td> </td>
{% if ratings %} {% if request.user.is_authenticated %}
<td data-title="{% trans "Rating" %}"> <td data-title="{% trans "Rating" %}">
{% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %} {% include 'snippets/stars.html' with rating=book.rating %}
</td> </td>
{% endif %} {% endif %}
{% if shelf.user == request.user %} {% if shelf.user == request.user %}

View File

@ -1,6 +1,6 @@
{% extends 'user/layout.html' %} {% extends 'user/layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load utilities %}
{% block title %}{{ user.display_name }}{% endblock %} {% block title %}{{ user.display_name }}{% endblock %}

View File

@ -1,5 +1,6 @@
{% load i18n %} {% load i18n %}
{% load humanize %} {% load humanize %}
{% load utilities %}
{% load bookwyrm_tags %} {% load bookwyrm_tags %}
<div class="media block"> <div class="media block">

View File

@ -1,7 +1,5 @@
{% extends 'settings/admin_layout.html' %} {% extends 'settings/admin_layout.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
{% load humanize %}
{% block title %}{{ user.username }}{% endblock %} {% block title %}{{ user.username }}{% endblock %}
{% block header %}{{ user.username }}{% endblock %} {% block header %}{{ user.username }}{% endblock %}

View File

@ -1,5 +1,5 @@
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %} {% load markdown %}
<div class="block columns"> <div class="block columns">
<div class="column is-flex is-flex-direction-column"> <div class="column is-flex is-flex-direction-column">
<h4 class="title is-4">{% trans "User details" %}</h4> <h4 class="title is-4">{% trans "User details" %}</h4>
@ -7,7 +7,7 @@
{% include 'user/user_preview.html' with user=user %} {% include 'user/user_preview.html' with user=user %}
{% if user.summary %} {% if user.summary %}
<div class="box content has-background-white-ter is-shadowless"> <div class="box content has-background-white-ter is-shadowless">
{{ user.summary | to_markdown | safe }} {{ user.summary|to_markdown|safe }}
</div> </div>
{% endif %} {% endif %}

View File

@ -1,22 +1,15 @@
""" template filters """ """ template filters """
from uuid import uuid4 from django import template
from django import template, utils
from django.db.models import Avg from django.db.models import Avg
from bookwyrm import models, views from bookwyrm import models, views
from bookwyrm.views.status import to_markdown from bookwyrm.views.status import to_markdown
from bookwyrm.templatetags.utilities import get_user_identifier
register = template.Library() register = template.Library()
@register.filter(name="dict_key")
def dict_key(d, k):
"""Returns the given key from a dictionary."""
return d.get(k) or 0
@register.filter(name="rating") @register.filter(name="rating")
def get_rating(book, user): def get_rating(book, user):
"""get the overall rating of a book""" """get the overall rating of a book"""
@ -43,119 +36,12 @@ def get_user_rating(book, user):
return 0 return 0
@register.filter(name="username")
def get_user_identifier(user):
"""use localname for local users, username for remote"""
return user.localname if user.localname else user.username
@register.filter(name="notification_count")
def get_notification_count(user):
"""how many UNREAD notifications are there"""
return user.notification_set.filter(read=False).count()
@register.filter(name="replies")
def get_replies(status):
"""get all direct replies to a status"""
# TODO: this limit could cause problems
return models.Status.objects.filter(
reply_parent=status,
deleted=False,
).select_subclasses()[:10]
@register.filter(name="parent")
def get_parent(status):
"""get the reply parent for a status"""
return (
models.Status.objects.filter(id=status.reply_parent_id)
.select_subclasses()
.get()
)
@register.filter(name="liked")
def get_user_liked(user, status):
"""did the given user fav a status?"""
try:
models.Favorite.objects.get(user=user, status=status)
return True
except models.Favorite.DoesNotExist:
return False
@register.filter(name="boosted")
def get_user_boosted(user, status):
"""did the given user fav a status?"""
return user.id in status.boosters.all().values_list("user", flat=True)
@register.filter(name="follow_request_exists")
def follow_request_exists(user, requester):
"""see if there is a pending follow request for a user"""
try:
models.UserFollowRequest.objects.filter(
user_subject=requester,
user_object=user,
).get()
return True
except models.UserFollowRequest.DoesNotExist:
return False
@register.filter(name="boosted_status")
def get_boosted(boost):
"""load a boosted status. have to do this or it wont get foregin keys"""
return (
models.Status.objects.select_subclasses()
.filter(id=boost.boosted_status.id)
.get()
)
@register.filter(name="book_description") @register.filter(name="book_description")
def get_book_description(book): def get_book_description(book):
"""use the work's text if the book doesn't have it""" """use the work's text if the book doesn't have it"""
return book.description or book.parent_work.description return book.description or book.parent_work.description
@register.filter(name="uuid")
def get_uuid(identifier):
"""for avoiding clashing ids when there are many forms"""
return "%s%s" % (identifier, uuid4())
@register.filter(name="to_markdown")
def get_markdown(content):
"""convert markdown to html"""
if content:
return to_markdown(content)
return None
@register.filter(name="mentions")
def get_mentions(status, user):
"""people to @ in a reply: the parent and all mentions"""
mentions = set([status.user] + list(status.mention_users.all()))
return (
" ".join("@" + get_user_identifier(m) for m in mentions if not m == user) + " "
)
@register.filter(name="status_preview_name")
def get_status_preview_name(obj):
"""text snippet with book context for a status"""
name = obj.__class__.__name__.lower()
if name == "review":
return "%s of <em>%s</em>" % (name, obj.book.title)
if name == "comment":
return "%s on <em>%s</em>" % (name, obj.book.title)
if name == "quotation":
return "%s from <em>%s</em>" % (name, obj.book.title)
return name
@register.filter(name="next_shelf") @register.filter(name="next_shelf")
def get_next_shelf(current_shelf): def get_next_shelf(current_shelf):
"""shelf you'd use to update reading progress""" """shelf you'd use to update reading progress"""
@ -168,17 +54,6 @@ def get_next_shelf(current_shelf):
return "to-read" return "to-read"
@register.filter(name="title")
def get_title(book):
"""display the subtitle if the title is short"""
if not book:
return ""
title = book.title
if len(title) < 6 and book.subtitle:
title = "{:s}: {:s}".format(title, book.subtitle)
return title
@register.simple_tag(takes_context=False) @register.simple_tag(takes_context=False)
def related_status(notification): def related_status(notification):
"""for notifications""" """for notifications"""
@ -212,31 +87,6 @@ def latest_read_through(book, user):
) )
@register.simple_tag(takes_context=False)
def active_read_through(book, user):
"""the most recent read activity"""
return (
models.ReadThrough.objects.filter(
user=user, book=book, finish_date__isnull=True
)
.order_by("-start_date")
.first()
)
@register.simple_tag(takes_context=False)
def comparison_bool(str1, str2):
"""idk why I need to write a tag for this, it reutrns a bool"""
return str1 == str2
@register.simple_tag(takes_context=False)
def get_lang():
"""get current language, strip to the first two letters"""
language = utils.translation.get_language()
return language[0 : language.find("-")]
@register.simple_tag(takes_context=True) @register.simple_tag(takes_context=True)
def mutuals_count(context, user): def mutuals_count(context, user):
"""how many users that you follow, follow them""" """how many users that you follow, follow them"""

View File

@ -0,0 +1,22 @@
""" template filters for status interaction buttons """
from django import template
from bookwyrm import models
register = template.Library()
@register.filter(name="liked")
def get_user_liked(user, status):
"""did the given user fav a status?"""
try:
models.Favorite.objects.get(user=user, status=status)
return True
except models.Favorite.DoesNotExist:
return False
@register.filter(name="boosted")
def get_user_boosted(user, status):
"""did the given user fav a status?"""
return user.id in status.boosters.all().values_list("user", flat=True)

View File

@ -0,0 +1,12 @@
""" template filters used for creating the layout"""
from django import template, utils
register = template.Library()
@register.simple_tag(takes_context=False)
def get_lang():
"""get current language, strip to the first two letters"""
language = utils.translation.get_language()
return language[0 : language.find("-")]

View File

@ -0,0 +1,14 @@
""" template filters """
from django import template
from bookwyrm.views.status import to_markdown
register = template.Library()
@register.filter(name="to_markdown")
def get_markdown(content):
"""convert markdown to html"""
if content:
return to_markdown(content)
return None

View File

@ -0,0 +1,43 @@
""" template filters """
from django import template
from bookwyrm import models
from bookwyrm.templatetags.utilities import get_user_identifier
register = template.Library()
@register.filter(name="mentions")
def get_mentions(status, user):
"""people to @ in a reply: the parent and all mentions"""
mentions = set([status.user] + list(status.mention_users.all()))
return (
" ".join("@" + get_user_identifier(m) for m in mentions if not m == user) + " "
)
@register.filter(name="replies")
def get_replies(status):
"""get all direct replies to a status"""
# TODO: this limit could cause problems
return models.Status.objects.filter(
reply_parent=status,
deleted=False,
).select_subclasses()[:10]
@register.filter(name="parent")
def get_parent(status):
"""get the reply parent for a status"""
return (
models.Status.objects.filter(id=status.reply_parent_id)
.select_subclasses()
.get()
)
@register.filter(name="boosted_status")
def get_boosted(boost):
"""load a boosted status. have to do this or it won't get foreign keys"""
return models.Status.objects.select_subclasses().get(id=boost.boosted_status.id)

View File

@ -0,0 +1,35 @@
""" template filters for really common utilities """
from uuid import uuid4
from django import template
register = template.Library()
@register.filter(name="uuid")
def get_uuid(identifier):
"""for avoiding clashing ids when there are many forms"""
return "%s%s" % (identifier, uuid4())
@register.filter(name="username")
def get_user_identifier(user):
"""use localname for local users, username for remote"""
return user.localname if user.localname else user.username
@register.filter(name="title")
def get_title(book):
"""display the subtitle if the title is short"""
if not book:
return ""
title = book.title
if len(title) < 6 and book.subtitle:
title = "{:s}: {:s}".format(title, book.subtitle)
return title
@register.simple_tag(takes_context=False)
def comparison_bool(str1, str2):
"""idk why I need to write a tag for this, it reutrns a bool"""
return str1 == str2

View File

@ -2,12 +2,17 @@
import re import re
from unittest.mock import patch from unittest.mock import patch
from dateutil.relativedelta import relativedelta
from django.test import TestCase from django.test import TestCase
from django.utils import timezone from django.utils import timezone
from bookwyrm import models from bookwyrm import models
from bookwyrm.templatetags import bookwyrm_tags from bookwyrm.templatetags import (
bookwyrm_tags,
interaction,
markdown,
status_display,
utilities,
)
@patch("bookwyrm.activitystreams.ActivityStream.add_status") @patch("bookwyrm.activitystreams.ActivityStream.add_status")
@ -33,12 +38,6 @@ class TemplateTags(TestCase):
) )
self.book = models.Edition.objects.create(title="Test Book") self.book = models.Edition.objects.create(title="Test Book")
def test_dict_key(self, _):
"""just getting a value out of a dict"""
test_dict = {"a": 1, "b": 3}
self.assertEqual(bookwyrm_tags.dict_key(test_dict, "a"), 1)
self.assertEqual(bookwyrm_tags.dict_key(test_dict, "c"), 0)
def test_get_user_rating(self, _): def test_get_user_rating(self, _):
"""get a user's most recent rating of a book""" """get a user's most recent rating of a book"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
@ -52,27 +51,14 @@ class TemplateTags(TestCase):
def test_get_user_identifer_local(self, _): def test_get_user_identifer_local(self, _):
"""fall back to the simplest uid available""" """fall back to the simplest uid available"""
self.assertNotEqual(self.user.username, self.user.localname) self.assertNotEqual(self.user.username, self.user.localname)
self.assertEqual(bookwyrm_tags.get_user_identifier(self.user), "mouse") self.assertEqual(utilities.get_user_identifier(self.user), "mouse")
def test_get_user_identifer_remote(self, _): def test_get_user_identifer_remote(self, _):
"""for a remote user, should be their full username""" """for a remote user, should be their full username"""
self.assertEqual( self.assertEqual(
bookwyrm_tags.get_user_identifier(self.remote_user), "rat@example.com" utilities.get_user_identifier(self.remote_user), "rat@example.com"
) )
def test_get_notification_count(self, _):
"""just countin'"""
self.assertEqual(bookwyrm_tags.get_notification_count(self.user), 0)
models.Notification.objects.create(user=self.user, notification_type="FAVORITE")
models.Notification.objects.create(user=self.user, notification_type="MENTION")
models.Notification.objects.create(
user=self.remote_user, notification_type="FOLLOW"
)
self.assertEqual(bookwyrm_tags.get_notification_count(self.user), 2)
def test_get_replies(self, _): def test_get_replies(self, _):
"""direct replies to a status""" """direct replies to a status"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
@ -95,7 +81,7 @@ class TemplateTags(TestCase):
deleted_date=timezone.now(), deleted_date=timezone.now(),
) )
replies = bookwyrm_tags.get_replies(parent) replies = status_display.get_replies(parent)
self.assertEqual(len(replies), 2) self.assertEqual(len(replies), 2)
self.assertTrue(first_child in replies) self.assertTrue(first_child in replies)
self.assertTrue(second_child in replies) self.assertTrue(second_child in replies)
@ -111,7 +97,7 @@ class TemplateTags(TestCase):
reply_parent=parent, user=self.user, content="hi" reply_parent=parent, user=self.user, content="hi"
) )
result = bookwyrm_tags.get_parent(child) result = status_display.get_parent(child)
self.assertEqual(result, parent) self.assertEqual(result, parent)
self.assertIsInstance(result, models.Review) self.assertIsInstance(result, models.Review)
@ -119,44 +105,26 @@ class TemplateTags(TestCase):
"""did a user like a status""" """did a user like a status"""
status = models.Review.objects.create(user=self.remote_user, book=self.book) status = models.Review.objects.create(user=self.remote_user, book=self.book)
self.assertFalse(bookwyrm_tags.get_user_liked(self.user, status)) self.assertFalse(interaction.get_user_liked(self.user, status))
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
models.Favorite.objects.create(user=self.user, status=status) models.Favorite.objects.create(user=self.user, status=status)
self.assertTrue(bookwyrm_tags.get_user_liked(self.user, status)) self.assertTrue(interaction.get_user_liked(self.user, status))
def test_get_user_boosted(self, _): def test_get_user_boosted(self, _):
"""did a user boost a status""" """did a user boost a status"""
status = models.Review.objects.create(user=self.remote_user, book=self.book) status = models.Review.objects.create(user=self.remote_user, book=self.book)
self.assertFalse(bookwyrm_tags.get_user_boosted(self.user, status)) self.assertFalse(interaction.get_user_boosted(self.user, status))
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
models.Boost.objects.create(user=self.user, boosted_status=status) models.Boost.objects.create(user=self.user, boosted_status=status)
self.assertTrue(bookwyrm_tags.get_user_boosted(self.user, status)) self.assertTrue(interaction.get_user_boosted(self.user, status))
def test_follow_request_exists(self, _):
"""does a user want to follow"""
self.assertFalse(
bookwyrm_tags.follow_request_exists(self.user, self.remote_user)
)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
models.UserFollowRequest.objects.create(
user_subject=self.user, user_object=self.remote_user
)
self.assertFalse(
bookwyrm_tags.follow_request_exists(self.user, self.remote_user)
)
self.assertTrue(
bookwyrm_tags.follow_request_exists(self.remote_user, self.user)
)
def test_get_boosted(self, _): def test_get_boosted(self, _):
"""load a boosted status""" """load a boosted status"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
status = models.Review.objects.create(user=self.remote_user, book=self.book) status = models.Review.objects.create(user=self.remote_user, book=self.book)
boost = models.Boost.objects.create(user=self.user, boosted_status=status) boost = models.Boost.objects.create(user=self.user, boosted_status=status)
boosted = bookwyrm_tags.get_boosted(boost) boosted = status_display.get_boosted(boost)
self.assertIsInstance(boosted, models.Review) self.assertIsInstance(boosted, models.Review)
self.assertEqual(boosted, status) self.assertEqual(boosted, status)
@ -178,48 +146,23 @@ class TemplateTags(TestCase):
def test_get_uuid(self, _): def test_get_uuid(self, _):
"""uuid functionality""" """uuid functionality"""
uuid = bookwyrm_tags.get_uuid("hi") uuid = utilities.get_uuid("hi")
self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid)) self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid))
def test_get_markdown(self, _): def test_get_markdown(self, _):
"""mardown format data""" """mardown format data"""
result = bookwyrm_tags.get_markdown("_hi_") result = markdown.get_markdown("_hi_")
self.assertEqual(result, "<p><em>hi</em></p>") self.assertEqual(result, "<p><em>hi</em></p>")
result = bookwyrm_tags.get_markdown("<marquee>_hi_</marquee>") result = markdown.get_markdown("<marquee>_hi_</marquee>")
self.assertEqual(result, "<p><em>hi</em></p>") self.assertEqual(result, "<p><em>hi</em></p>")
def test_get_mentions(self, _): def test_get_mentions(self, _):
"""list of people mentioned""" """list of people mentioned"""
status = models.Status.objects.create(content="hi", user=self.remote_user) status = models.Status.objects.create(content="hi", user=self.remote_user)
result = bookwyrm_tags.get_mentions(status, self.user) result = status_display.get_mentions(status, self.user)
self.assertEqual(result, "@rat@example.com ") self.assertEqual(result, "@rat@example.com ")
def test_get_status_preview_name(self, _):
"""status context string"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
status = models.Status.objects.create(content="hi", user=self.user)
result = bookwyrm_tags.get_status_preview_name(status)
self.assertEqual(result, "status")
status = models.Review.objects.create(
content="hi", user=self.user, book=self.book
)
result = bookwyrm_tags.get_status_preview_name(status)
self.assertEqual(result, "review of <em>Test Book</em>")
status = models.Comment.objects.create(
content="hi", user=self.user, book=self.book
)
result = bookwyrm_tags.get_status_preview_name(status)
self.assertEqual(result, "comment on <em>Test Book</em>")
status = models.Quotation.objects.create(
content="hi", user=self.user, book=self.book
)
result = bookwyrm_tags.get_status_preview_name(status)
self.assertEqual(result, "quotation from <em>Test Book</em>")
def test_related_status(self, _): def test_related_status(self, _):
"""gets the subclass model for a notification status""" """gets the subclass model for a notification status"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):

View File

@ -2,6 +2,7 @@
from collections import namedtuple from collections import namedtuple
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import Count, OuterRef, Subquery, F, Q
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.http import HttpResponseBadRequest, HttpResponseNotFound from django.http import HttpResponseBadRequest, HttpResponseNotFound
@ -37,30 +38,41 @@ class Shelf(View):
return HttpResponseNotFound() return HttpResponseNotFound()
if not shelf.visible_to_user(request.user): if not shelf.visible_to_user(request.user):
return HttpResponseNotFound() return HttpResponseNotFound()
books = shelf.books
# this is a constructed "all books" view, with a fake "shelf" obj # this is a constructed "all books" view, with a fake "shelf" obj
else: else:
FakeShelf = namedtuple( FakeShelf = namedtuple(
"Shelf", ("identifier", "name", "user", "books", "privacy") "Shelf", ("identifier", "name", "user", "books", "privacy")
) )
books = models.Edition.objects.filter( books = models.Edition.objects.filter(
# privacy is ensured because the shelves are already filtered above
shelfbook__shelf__in=shelves.all() shelfbook__shelf__in=shelves.all()
).distinct() ).distinct()
shelf = FakeShelf("all", _("All books"), user, books, "public") shelf = FakeShelf("all", _("All books"), user, books, "public")
is_self = request.user == user
if is_api_request(request): if is_api_request(request):
return ActivitypubResponse(shelf.to_activity(**request.GET)) return ActivitypubResponse(shelf.to_activity(**request.GET))
reviews = privacy_filter(
request.user,
models.Review.objects.filter(
user=user,
rating__isnull=False,
book__id=OuterRef("id"),
),
).order_by("-published_date")
books = books.annotate(rating=Subquery(reviews.values("rating")[:1]))
paginated = Paginator( paginated = Paginator(
shelf.books.order_by("-updated_date"), books.order_by("-updated_date"),
PAGE_LENGTH, PAGE_LENGTH,
) )
page = paginated.get_page(request.GET.get("page")) page = paginated.get_page(request.GET.get("page"))
data = { data = {
"user": user, "user": user,
"is_self": is_self, "is_self": request.user == user,
"shelves": shelves.all(), "shelves": shelves.all(),
"shelf": shelf, "shelf": shelf,
"books": page, "books": page,