1
0
Fork 0

Merge branch 'main' into book-format-choices

This commit is contained in:
Mouse Reeve 2021-09-27 10:28:05 -07:00
commit bc87856c2e
199 changed files with 7647 additions and 3289 deletions

View file

@ -325,5 +325,5 @@
{% endblock %}
{% block scripts %}
<script src="{% static "js/vendor/tabs.js" %}"></script>
<script src="{% static "js/vendor/tabs.js" %}?v={{ js_cache }}"></script>
{% endblock %}

View file

@ -0,0 +1,11 @@
{% load i18n %}
{% trans "Help" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text class="ml-3 is-rounded is-small is-white p-0 pb-1" icon="question-circle is-size-6" controls_text=controls_text controls_uid=controls_uid %}
<aside class="tooltip notification is-hidden transition-y is-pulled-left mb-2" id="{{ controls_text }}{% if controls_uid %}-{{ controls_uid }}{% endif %}">
{% trans "Close" as button_text %}
{% include 'snippets/toggle/close_button.html' with label=button_text class="delete" nonbutton=True controls_text=controls_text controls_uid=controls_uid %}
{% block tooltip_content %}{% endblock %}
</aside>

View file

@ -27,7 +27,7 @@
{% if not draft %}
{% include 'snippets/create_status.html' %}
{% else %}
{% include 'snippets/create_status/status.html' %}
{% include 'snippets/create_status/status.html' with no_script=True %}
{% endif %}
</div>
</div>

View file

@ -15,14 +15,15 @@
</p>
</header>
{% with tile_classes="tile is-child box has-background-white-ter is-clipped" %}
<div class="tile is-ancestor">
<div class="tile is-6 is-parent">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/large-book.html' with status=large_activities.0 %}
</div>
</div>
<div class="tile is-6 is-parent">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/large-book.html' with status=large_activities.1 %}
</div>
</div>
@ -31,18 +32,18 @@
<div class="tile is-ancestor">
<div class="tile is-vertical is-6">
<div class="tile is-parent">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/large-book.html' with status=large_activities.2 %}
</div>
</div>
<div class="tile">
<div class="tile is-parent is-6">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/small-book.html' with status=small_activities.0 %}
</div>
</div>
<div class="tile is-parent is-6">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/small-book.html' with status=small_activities.1 %}
</div>
</div>
@ -51,18 +52,18 @@
<div class="tile is-vertical is-6">
<div class="tile">
<div class="tile is-parent is-6">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/small-book.html' with status=small_activities.2 %}
</div>
</div>
<div class="tile is-parent is-6">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/small-book.html' with status=small_activities.3 %}
</div>
</div>
</div>
<div class="tile is-parent">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/large-book.html' with status=large_activities.3 %}
</div>
</div>
@ -71,16 +72,17 @@
<div class="tile is-ancestor">
<div class="tile is-6 is-parent">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/large-book.html' with status=large_activities.4 %}
</div>
</div>
<div class="tile is-6 is-parent">
<div class="tile is-child box has-background-white-ter">
<div class="{{ tile_classes }}">
{% include 'discover/large-book.html' with status=large_activities.5 %}
</div>
</div>
</div>
{% endwith %}
</section>
<div class="block">

View file

@ -14,7 +14,7 @@
</header>
<div class="box">
{% include 'snippets/create_status/status.html' with type="direct" uuid=1 mention=partner %}
{% include 'snippets/create_status/status.html' with type="direct" uuid=1 mention=partner no_script=True %}
</div>
<section class="block">

View file

@ -22,7 +22,7 @@
{% blocktrans with tab_key=tab.key %}load <span data-poll="stream/{{ tab_key }}">0</span> unread status(es){% endblocktrans %}
</a>
{% if request.user.show_goal and not goal and tab.key == streams.first.key %}
{% if request.user.show_goal and not goal and tab.key == 'home' %}
{% now 'Y' as year %}
<section class="block">
{% include 'snippets/goal_card.html' with year=year %}
@ -37,7 +37,7 @@
<div class="block content">
<p>{% trans "There aren't any activities right now! Try following a user to get started" %}</p>
{% if suggested_users %}
{% if request.user.show_suggested_users and suggested_users %}
{# suggested users for when things are very lonely #}
{% include 'feed/suggested_users.html' with suggested_users=suggested_users %}
{% endif %}
@ -46,7 +46,7 @@
{% for activity in activities %}
{% if not activities.number > 1 and forloop.counter0 == 2 and suggested_users %}
{% if request.user.show_suggested_users and not activities.number > 1 and forloop.counter0 == 2 and suggested_users %}
{# suggested users on the first page, two statuses down #}
{% include 'feed/suggested_users.html' with suggested_users=suggested_users %}
{% endif %}

View file

@ -106,5 +106,5 @@
{% endblock %}
{% block scripts %}
<script src="{% static "js/vendor/tabs.js" %}"></script>
<script src="{% static "js/vendor/tabs.js" %}?v={{ js_cache }}"></script>
{% endblock %}

View file

@ -1,6 +1,15 @@
{% load i18n %}
<section class="block">
<h2 class="title is-5">{% trans "Who to follow" %}</h2>
<header class="columns">
<div class="column">
<h2 class="title is-5">{% trans "Who to follow" %}</h2>
</div>
<form class="column is-narrow" action="{% url 'hide-suggestions' %}" method="POST">
{% csrf_token %}
{% trans "Don't show suggested users" as button_text %}
<button type="submit" class="delete" title="{{ button_text }}">{{ button_text }}</button>
</form>
</header>
{% include 'snippets/suggested_users.html' with suggested_users=suggested_users %}
<a class="help" href="{% url 'directory' %}">{% trans "View directory" %} <span class="icon icon-arrow-right"></span></a>
</section>

View file

@ -12,9 +12,14 @@
<div class="columns">
<div class="column is-half">
<label class="label" for="source">
{% trans "Data source:" %}
</label>
<div class="field">
<label class="label is-pulled-left" for="source">
{% trans "Data source:" %}
</label>
{% include 'import/tooltip.html' with controls_text="goodreads-tooltip" %}
</div>
<div class="select block">
<select name="source" id="source">
<option value="GoodReads" {% if current == 'GoodReads' %}selected{% endif %}>

View file

@ -40,7 +40,7 @@
<div class="block">
<h2 class="title is-4">{% trans "Failed to load" %}</h2>
{% if not job.retry %}
<form name="retry" action="/import/{{ job.id }}" method="post">
<form name="retry" action="/import/{{ job.id }}" method="post" class="box">
{% csrf_token %}
{% with failed_count=failed_items|length %}
@ -77,7 +77,7 @@
class="checkbox"
type="checkbox"
data-action="toggle-all"
data-target="failed-imports"
data-target="failed_imports"
/>
{% trans "Select all" %}
</label>
@ -156,5 +156,5 @@
{% endspaceless %}{% endblock %}
{% block scripts %}
<script src="{% static "js/check_all.js" %}"></script>
<script src="{% static "js/check_all.js" %}?v={{ js_cache }}"></script>
{% endblock %}

View file

@ -0,0 +1,8 @@
{% extends 'components/tooltip.html' %}
{% load i18n %}
{% block tooltip_content %}
{% trans 'You can download your GoodReads data from the <a href="https://www.goodreads.com/review/import" target="_blank" rel="noopener">Import/Export page</a> of your GoodReads account.' %}
{% endblock %}

View file

@ -5,11 +5,11 @@
{% block content %}
<h1 class="title">{% trans "Create an Account" %}</h1>
<div class="columns">
<div class="column">
<div class="block">
{% if valid %}
<h1 class="title">{% trans "Create an Account" %}</h1>
<div>
<form name="register" method="post" action="/register">
<input type=hidden name="invite_code" value="{{ invite.code }}">
@ -25,7 +25,7 @@
</div>
</div>
<div class="column">
<div class="block">
<div class="box">
{% include 'snippets/about.html' %}
</div>
</div>

View file

@ -1,4 +1,4 @@
{% extends 'landing/landing_layout.html' %}
{% extends 'landing/layout.html' %}
{% load i18n %}
{% block panel %}

View file

@ -1,4 +1,4 @@
{% extends 'landing/landing_layout.html' %}
{% extends 'landing/layout.html' %}
{% load i18n %}
{% block panel %}

View file

@ -40,38 +40,41 @@
<div class="tile is-5 is-parent">
{% if not request.user.is_authenticated %}
<div class="tile is-child box has-background-primary-light content">
<h2 class="title">
{% if site.allow_registration %}
{% blocktrans with name=site.name %}Join {{ name }}{% endblocktrans %}
{% elif site.allow_invite_requests %}
{% trans "Request an Invitation" %}
{% else %}
{% blocktrans with name=site.name%}{{ name}} registration is closed{% endblocktrans %}
{% endif %}
</h2>
{% if site.allow_registration %}
<h2 class="title">{% blocktrans with name=site.name %}Join {{ name }}{% endblocktrans %}</h2>
<form name="register" method="post" action="/register">
{% include 'snippets/register_form.html' %}
</form>
<form name="register" method="post" action="/register">
{% include 'snippets/register_form.html' %}
</form>
{% elif site.allow_invite_requests %}
{% if request_received %}
<p>
{% trans "Thank you! Your request has been received." %}
</p>
{% else %}
<p>{{ site.invite_request_text }}</p>
<form name="invite-request" action="{% url 'invite-request' %}" method="post">
{% csrf_token %}
<div class="block">
<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">
{% for error in request_form.email.errors %}
<p class="help is-danger">{{ error|escape }}</p>
{% endfor %}
</div>
<button type="submit" class="button is-link">{% trans "Submit" %}</button>
</form>
{% endif %}
{% else %}
<h2 class="title">{% trans "This instance is closed" %}</h2>
<p>{{ site.registration_closed_text|safe}}</p>
{% if site.allow_invite_requests %}
{% if request_received %}
<p>
{% trans "Thank you! Your request has been received." %}
</p>
{% else %}
<h3>{% trans "Request an Invitation" %}</h3>
<form name="invite-request" action="{% url 'invite-request' %}" method="post">
{% csrf_token %}
<div class="block">
<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">
{% for error in request_form.email.errors %}
<p class="help is-danger">{{ error|escape }}</p>
{% endfor %}
</div>
<button type="submit" class="button is-link">{% trans "Submit" %}</button>
</form>
{% endif %}
{% endif %}
<p>{{ site.registration_closed_text|safe}}</p>
{% endif %}
</div>
{% else %}

View file

@ -4,7 +4,7 @@
<!DOCTYPE html>
<html lang="{% get_lang %}">
<head>
<title>{% block title %}BookWyrm{% endblock %} | {{ site.name }}</title>
<title>{% block title %}BookWyrm{% endblock %} - {{ site.name }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{% static "css/vendor/bulma.min.css" %}">
<link rel="stylesheet" href="{% static "css/vendor/icons.css" %}">
@ -17,8 +17,8 @@
{% else %}
<meta name="twitter:card" content="summary">
{% endif %}
<meta name="twitter:title" content="{% if title %}{{ title }} | {% endif %}{{ site.name }}">
<meta name="og:title" content="{% if title %}{{ title }} | {% endif %}{{ site.name }}">
<meta name="twitter:title" content="{% if title %}{{ title }} - {% endif %}{{ site.name }}">
<meta name="og:title" content="{% if title %}{{ title }} - {% endif %}{{ site.name }}">
<meta name="twitter:description" content="{{ site.instance_tagline }}">
<meta name="og:description" content="{{ site.instance_tagline }}">
@ -37,7 +37,12 @@
<form class="navbar-item column" action="/search/">
<div class="field has-addons">
<div class="control">
<input aria-label="{% trans 'Search for a book or user' %}" id="search_input" class="input" type="text" name="q" placeholder="{% trans 'Search for a book or user' %}" value="{{ query }}">
{% if user.is_authenticated %}
{% trans "Search for a book, user, or list" as search_placeholder %}
{% else %}
{% trans "Search for a book" as search_placeholder %}
{% endif %}
<input aria-label="{{ search_placeholder }}" id="search_input" class="input" type="text" name="q" placeholder="{{ search_placeholder }}" value="{{ query }}">
</div>
<div class="control">
<button class="button" type="submit">
@ -121,7 +126,7 @@
{% endif %}
{% if perms.bookwyrm.moderate_user %}
<li>
<a href="{% url 'settings-users' %}" class="navbar-item">
<a href="{% url 'settings-dashboard' %}" class="navbar-item">
{% trans 'Admin' %}
</a>
</li>
@ -210,6 +215,11 @@
</div>
</div>
<div role="region" aria-live="polite" id="live-messages">
<p id="status-success-message" class="live-message is-sr-only is-hidden">{% trans "Successfully posted status" %}</p>
<p id="status-error-message" class="live-message notification is-danger p-3 pr-5 pl-5 is-hidden">{% trans "Error posting status" %}</p>
</div>
<footer class="footer">
<div class="container">
<div class="columns">
@ -249,8 +259,11 @@
<script>
var csrf_token = '{{ csrf_token }}';
</script>
<script src="{% static "js/bookwyrm.js" %}"></script>
<script src="{% static "js/localstorage.js" %}"></script>
<script src="{% static "js/bookwyrm.js" %}?v={{ js_cache }}"></script>
<script src="{% static "js/localstorage.js" %}?v={{ js_cache }}"></script>
<script src="{% static "js/status_cache.js" %}?v={{ js_cache }}"></script>
{% block scripts %}{% endblock %}
</body>
</html>

View file

@ -45,8 +45,10 @@
</div>
</div>
</div>
{% if list.id %}
<div class="column is-narrow">
{% trans "Delete list" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with class="is-danger" text=button_text icon_with_text="x" controls_text="delete_list" controls_uid=list.id focus="modal_title_delete_list" %}
</div>
{% endif %}
</div>

View file

@ -4,69 +4,65 @@
{% block title %}{% trans "Login" %}{% endblock %}
{% block content %}
<div class="columns">
<div class="column">
<div class="box">
<h1 class="title">{% trans "Log in" %}</h1>
{% if login_form.non_field_errors %}
<p class="notification is-danger">{{ login_form.non_field_errors }}</p>
{% endif %}
<h1 class="title">{% trans "Log in" %}</h1>
<div class="columns is-multiline">
<div class="column is-half">
{% if login_form.non_field_errors %}
<p class="notification is-danger">{{ login_form.non_field_errors }}</p>
{% endif %}
{% if show_confirmed_email %}
<p class="notification is-success">{% trans "Success! Email address confirmed." %}</p>
{% endif %}
<form name="login" method="post" action="/login">
{% csrf_token %}
{% if show_confirmed_email %}<input type="hidden" name="first_login" value="true">{% endif %}
<div class="field">
<label class="label" for="id_localname">{% trans "Username:" %}</label>
<div class="control">
{{ login_form.localname }}
</div>
{% if show_confirmed_email %}
<p class="notification is-success">{% trans "Success! Email address confirmed." %}</p>
{% endif %}
<form name="login" method="post" action="/login">
{% csrf_token %}
{% if show_confirmed_email %}<input type="hidden" name="first_login" value="true">{% endif %}
<div class="field">
<label class="label" for="id_localname">{% trans "Username:" %}</label>
<div class="control">
{{ login_form.localname }}
</div>
<div class="field">
<label class="label" for="id_password">{% trans "Password:" %}</label>
<div class="control">
{{ login_form.password }}
</div>
{% for error in login_form.password.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="field">
<label class="label" for="id_password">{% trans "Password:" %}</label>
<div class="control">
{{ login_form.password }}
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit">{% trans "Log in" %}</button>
</div>
<div class="control">
<small><a href="{% url 'password-reset' %}">{% trans "Forgot your password?" %}</a></small>
</div>
{% for error in login_form.password.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit">{% trans "Log in" %}</button>
</div>
</form>
</div>
<div class="control">
<small><a href="{% url 'password-reset' %}">{% trans "Forgot your password?" %}</a></small>
</div>
</div>
</form>
</div>
<div class="column">
{% if site.allow_registration %}
<div class="column is-half">
<div class="box has-background-primary-light">
{% if site.allow_registration %}
<h2 class="title">{% trans "Create an Account" %}</h2>
<form name="register" method="post" action="/register">
{% include 'snippets/register_form.html' %}
</form>
{% else %}
<h2 class="title">{% trans "This instance is closed" %}</h2>
<p>{% trans "Contact an administrator to get an invite" %}</p>
{% endif %}
</div>
</div>
{% endif %}
<div class="column">
<div class="box">
{% include 'snippets/about.html' %}
<p class="block">
<a href="{% url 'about' %}">{% trans "More about this site" %}</a>
</p>
</div>
</div>
</div>
<div class="block">
<div class="box">
{% include 'snippets/about.html' %}
<p class="block">
<a href="{% url 'about' %}">{% trans "More about this site" %}</a>
</p>
</div>
</div>
{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% load humanize %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% block title %}

View file

@ -43,9 +43,19 @@
</div>
<div class="block">
<label class="checkbox label" for="id_show_goal">
{% trans "Show set reading goal prompt in feed:" %}
{% trans "Show reading goal prompt in feed:" %}
{{ form.show_goal }}
</label>
<label class="checkbox label" for="id_show_goal">
{% trans "Show suggested users:" %}
{{ form.show_suggested_users }}
</label>
<label class="checkbox label" for="id_discoverable">
{% trans "Show this account in suggested users:" %}
{{ form.discoverable }}
</label>
{% url 'directory' as path %}
<p class="help">{% blocktrans %}Your account will show up in the <a href="{{ path }}">directory</a>, and may be recommended to other BookWyrm users.{% endblocktrans %}</p>
</div>
<div class="block">
<label class="checkbox label" for="id_manually_approves_followers">
@ -61,14 +71,6 @@
{{ form.default_post_privacy }}
</div>
</div>
<div class="block">
<label class="checkbox label" for="id_discoverable">
{% trans "Show this account in suggested users:" %}
{{ form.discoverable }}
</label>
{% url 'directory' as path %}
<p class="help">{% blocktrans %}Your account will show up in the <a href="{{ path }}">directory</a>, and may be recommended to other BookWyrm users.{% endblocktrans %}</p>
</div>
<div class="block">
<label class="label" for="id_preferred_timezone">{% trans "Preferred Timezone: " %}</label>
<div class="select">

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}{% load humanize %}
{% block title %}{% trans "Announcement" %} - {{ announcement.preview }}{% endblock %}

View file

@ -13,21 +13,21 @@
{% csrf_token %}
<input type="hidden" name="user" value="{{ request.user.id }}">
<p>
<label class="label" for="id_preview">Preview:</label>
<label class="label" for="id_preview">{% trans "Preview:" %}</label>
{{ form.preview }}
{% for error in form.preview.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</p>
<p>
<label class="label" for="id_content">Content:</label>
<label class="label" for="id_content">{% trans "Content:" %}</label>
{{ form.content }}
{% for error in form.content.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</p>
<p>
<label class="label" for="id_event_date">Event date:</label>
<label class="label" for="id_event_date">{% trans "Event date:" %}</label>
<input type="date" name="event_date" value="{{ form.event_date.value|date:'Y-m-d' }}" class="input" id="id_event_date">
{% for error in form.event_date.errors %}
<p class="help is-danger">{{ error | escape }}</p>
@ -37,7 +37,7 @@
<div class="columns">
<div class="column">
<p>
<label class="label" for="id_start_date">Start date:</label>
<label class="label" for="id_start_date">{% trans "Start date:" %}</label>
<input type="date" name="start_date" class="input" value="{{ form.start_date.value|date:'Y-m-d' }}" id="id_start_date">
{% for error in form.start_date.errors %}
<p class="help is-danger">{{ error | escape }}</p>
@ -46,7 +46,7 @@
</div>
<div class="column">
<p>
<label class="label" for="id_end_date">End date:</label>
<label class="label" for="id_end_date">{% trans "End date:" %}</label>
<input type="date" name="end_date" class="input" id="id_end_date" value="{{ form.end_date.value|date:'Y-m-d' }}">
{% for error in form.end_date.errors %}
<p class="help is-danger">{{ error | escape }}</p>
@ -55,7 +55,7 @@
</div>
<div class="column is-narrow">
<p>
<label class="label" for="id_active">Active:</label>
<label class="label" for="id_active">{% trans "Active:" %}</label>
{{ form.active }}
{% for error in form.active.errors %}
<p class="help is-danger">{{ error | escape }}</p>

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}{% load humanize %}
{% block title %}{% trans "Announcements" %}{% endblock %}
@ -14,40 +14,46 @@
{% include 'settings/announcement_form.html' with controls_text="create_announcement" %}
</form>
<table class="table is-striped">
<tr>
<th>
{% url 'settings-announcements' as url %}
{% trans "Date added" as text %}
{% include 'snippets/table-sort-header.html' with field="created_date" sort=sort text=text %}
</th>
<th>
{% trans "Preview" as text %}
{% include 'snippets/table-sort-header.html' with field="preview" sort=sort text=text %}
</th>
<th>
{% trans "Start date" as text %}
{% include 'snippets/table-sort-header.html' with field="start_date" sort=sort text=text %}
</th>
<th>
{% trans "End date" as text %}
{% include 'snippets/table-sort-header.html' with field="end_date" sort=sort text=text %}
</th>
<th>
{% trans "Status" as text %}
{% include 'snippets/table-sort-header.html' with field="active" sort=sort text=text %}
</th>
</tr>
{% for announcement in announcements %}
<tr>
<td>{{ announcement.created_date|naturalday }}</td>
<td><a href="{% url 'settings-announcements' announcement.id %}">{{ announcement.preview }}</a></td>
<td>{{ announcement.start_date|naturaltime|default:'' }}</td>
<td>{{ announcement.end_date|naturaltime|default:'' }}</td>
<td>{% if announcement.active %}{% trans "active" %}{% else %}{% trans "inactive" %}{% endif %}</td>
</tr>
{% endfor %}
</table>
<div class="block">
<table class="table is-striped">
<tr>
<th>
{% url 'settings-announcements' as url %}
{% trans "Date added" as text %}
{% include 'snippets/table-sort-header.html' with field="created_date" sort=sort text=text %}
</th>
<th>
{% trans "Preview" as text %}
{% include 'snippets/table-sort-header.html' with field="preview" sort=sort text=text %}
</th>
<th>
{% trans "Start date" as text %}
{% include 'snippets/table-sort-header.html' with field="start_date" sort=sort text=text %}
</th>
<th>
{% trans "End date" as text %}
{% include 'snippets/table-sort-header.html' with field="end_date" sort=sort text=text %}
</th>
<th>
{% trans "Status" as text %}
{% include 'snippets/table-sort-header.html' with field="active" sort=sort text=text %}
</th>
</tr>
{% for announcement in announcements %}
<tr>
<td>{{ announcement.created_date|naturalday }}</td>
<td><a href="{% url 'settings-announcements' announcement.id %}">{{ announcement.preview }}</a></td>
<td>{{ announcement.start_date|naturaltime|default:'' }}</td>
<td>{{ announcement.end_date|naturaltime|default:'' }}</td>
<td>{% if announcement.active %}{% trans "active" %}{% else %}{% trans "inactive" %}{% endif %}</td>
</tr>
{% endfor %}
</table>
{% if not announcements %}
<p><em>{% trans "No announcements found." %}</em></p>
{% endif %}
</div>
{% include 'snippets/pagination.html' with page=announcements path=request.path %}
{% endblock %}

View file

@ -0,0 +1,120 @@
{% extends 'settings/layout.html' %}
{% load i18n %}
{% load humanize %}
{% load static %}
{% block title %}{% trans "Dashboard" %}{% endblock %}
{% block header %}{% trans "Dashboard" %}{% endblock %}
{% block panel %}
<div class="columns block has-text-centered">
<div class="column is-3">
<div class="notification">
<h3>{% trans "Total users" %}</h3>
<p class="title is-5">{{ users|intcomma }}</p>
</div>
</div>
<div class="column is-3">
<div class="notification">
<h3>{% trans "Active this month" %}</h3>
<p class="title is-5">{{ active_users|intcomma }}</p>
</div>
</div>
<div class="column is-3">
<div class="notification">
<h3>{% trans "Statuses" %}</h3>
<p class="title is-5">{{ statuses|intcomma }}</p>
</div>
</div>
<div class="column is-3">
<div class="notification">
<h3>{% trans "Works" %}</h3>
<p class="title is-5">{{ works|intcomma }}</p>
</div>
</div>
</div>
<div class="columns block is-multiline">
{% if reports %}
<div class="column">
<a href="{% url 'settings-reports' %}" class="notification is-warning is-block">
{% blocktrans trimmed count counter=reports with display_count=reports|intcomma %}
{{ display_count }} open report
{% plural %}
{{ display_count }} open reports
{% endblocktrans %}
</a>
</div>
{% endif %}
{% if not site.allow_registration and site.allow_invite_requests and invite_requests %}
<div class="column">
<a href="{% url 'settings-invite-requests' %}" class="notification is-block is-success is-light">
{% blocktrans trimmed count counter=invite_requests with display_count=invite_requests|intcomma %}
{{ display_count }} invite request
{% plural %}
{{ display_count }} invite requests
{% endblocktrans %}
</a>
</div>
{% endif %}
</div>
<div class="block content">
<h2>{% trans "Instance Activity" %}</h2>
<form method="get" action="{% url 'settings-dashboard' %}" class="notification has-background-white-bis">
<div class="is-flex is-align-items-flex-end">
<div class="ml-1 mr-1">
<label class="label">
{% trans "Start date:" %}
<input class="input" type="date" name="start" value="{{ start }}">
</label>
</div>
<div class="ml-1 mr-1">
<label class="label">
{% trans "End date:" %}
<input class="input" type="date" name="end" value="{{ end }}">
</label>
</div>
<div class="ml-1 mr-1">
<label class="label">
{% trans "Interval:" %}
<div class="select">
<select name="days">
<option value="1" {% if interval == 1 %}selected{% endif %}>{% trans "Days" %}</option>
<option value="7" {% if interval == 7 %}selected{% endif %}>{% trans "Weeks" %}</option>
</select>
</div>
</label>
</div>
<div class="ml-1 mr-1">
<button class="button is-link" type="submit">{% trans "Submit" %}</button>
</div>
</div>
</form>
<div class="columns">
<div class="column">
<h3>{% trans "User signup activity" %}</h3>
<div class="box">
<canvas id="user_stats"></canvas>
</div>
</div>
<div class="column">
<h3>{% trans "Status activity" %}</h3>
<div class="box">
<canvas id="status_stats"></canvas>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.5.1/dist/chart.min.js"></script>
{% include 'settings/dashboard_user_chart.html' %}
{% include 'settings/dashboard_status_chart.html' %}
{% endblock %}

View file

@ -0,0 +1,26 @@
{% load i18n %}
<script>
const status_labels = [{% for label in status_stats.labels %}"{{ label }}",{% endfor %}];
const status_data = {
labels: status_labels,
datasets: [{
label: '{% trans "Statuses posted" %}',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: {{ status_stats.total }},
}]
};
// === include 'setup' then 'config' above ===
const status_config = {
type: 'bar',
data: status_data,
options: {}
};
var statusStats = new Chart(
document.getElementById('status_stats'),
status_config
);
</script>

View file

@ -0,0 +1,29 @@
{% load i18n %}
<script>
const labels = [{% for label in user_stats.labels %}"{{ label }}",{% endfor %}];
const data = {
labels: labels,
datasets: [{
label: '{% trans "Total" %}',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: {{ user_stats.total }},
}, {
label: '{% trans "Active this month" %}',
backgroundColor: 'rgb(75, 192, 192)',
borderColor: 'rgb(75, 192, 192)',
data: {{ user_stats.active }},
}]
};
const config = {
type: 'line',
data: data,
options: {}
};
var userStats = new Chart(
document.getElementById('user_stats'),
config
);
</script>

View file

@ -0,0 +1,30 @@
{% extends 'components/inline_form.html' %}
{% load i18n %}
{% block header %}
{% trans "Add domain" %}
{% endblock %}
{% block form %}
<form name="add-domain" method="post" action="{% url 'settings-email-blocks' %}">
{% csrf_token %}
<label class="label" for="id_domain">{% trans "Domain:" %}</label>
<div class="field has-addons">
<div class="control">
<div class="button is-disabled">@</div>
</div>
<div class="control">
{{ form.domain }}
</div>
</div>
{% for error in form.domain.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<div class="field">
<div class="control">
<button type="submit" class="button is-primary">{% trans "Add" %}</button>
</div>
</div>
</form>
{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% block title %}{% trans "Add instance" %}{% endblock %}

View file

@ -0,0 +1,61 @@
{% extends 'settings/layout.html' %}
{% load i18n %}
{% load humanize %}
{% block title %}{% trans "Email Blocklist" %}{% endblock %}
{% block header %}{% trans "Email Blocklist" %}{% endblock %}
{% block edit-button %}
{% trans "Add domain" as button_text %}
{% include 'snippets/toggle/open_button.html' with controls_text="add_domain" icon_with_text="plus" text=button_text focus="add_domain_header" %}
{% endblock %}
{% block panel %}
{% include 'settings/domain_form.html' with controls_text="add_domain" class="block" %}
<p class="notification block">
{% trans "When someone tries to register with an email from this domain, no account will be created. The registration process will appear to have worked." %}
</p>
<table class="table is-striped is-fullwidth">
<tr>
{% url 'settings-federation' as url %}
<th>
{% trans "Domain" %}
</th>
<th>{% trans "Users" %}</th>
<th>
{% trans "Options" %}
</th>
</tr>
{% for domain in domains %}
<tr>
<td>{{ domain.domain }}</td>
<td>
<a href="{% url 'settings-users' %}?email=@{{ domain.domain }}">
{% with user_count=domain.users.count %}
{% blocktrans trimmed count conter=user_count with display_count=user_count|intcomma %}
{{ display_count }} user
{% plural %}
{{ display_count }} users
{% endblocktrans %}
{% endwith %}
</a>
</td>
<td>
<form name="remove-{{ domain.id }}" action="{% url 'settings-email-blocks-delete' domain.id %}" method="post">
{% csrf_token %}
{% trans "Delete" as button_text %}
<button class="button" type="submit">
<span class="icon icon-x" title="{{ button_text }}" aria-hidden="true"></span>
<span class="is-hidden-mobile">{{ button_text }}</span>
</button>
</form>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% load markdown %}
@ -29,7 +29,7 @@
</div>
<div class="is-flex">
<dt>{% trans "Status:" %}</dt>
<dd>{{ server.status }}</dd>
<dd>{{ server.get_status_display }}</dd>
</div>
</dl>
</div>

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% block title %}{% trans "Federated Instances" %}{% endblock %}
@ -12,6 +12,19 @@
{% endblock %}
{% block panel %}
<div class="tabs">
<ul>
{% url 'settings-federation' status='federated' as url %}
<li {% if request.path in url %}class="is-active" aria-current="page"{% endif %}>
<a href="{{ url }}">{% trans "Federated" %}</a>
</li>
{% url 'settings-federation' status='blocked' as url %}
<li {% if url in request.path %}class="is-active" aria-current="page"{% endif %}>
<a href="{{ url }}">{% trans "Blocked" %}</a>
</li>
</ul>
</div>
<table class="table is-striped">
<tr>
{% url 'settings-federation' as url %}
@ -20,21 +33,30 @@
{% include 'snippets/table-sort-header.html' with field="server_name" sort=sort text=text %}
</th>
<th>
{% trans "Date federated" as text %}
{% trans "Date added" as text %}
{% include 'snippets/table-sort-header.html' with field="created_date" sort=sort text=text %}
</th>
<th>
{% trans "Software" as text %}
{% include 'snippets/table-sort-header.html' with field="application_type" sort=sort text=text %}
</th>
<th>
{% trans "Users" %}
</th>
<th>{% trans "Status" %}</th>
</tr>
{% for server in servers %}
<tr>
<td><a href="{% url 'settings-federated-server' server.id %}">{{ server.server_name }}</a></td>
<td>{{ server.created_date }}</td>
<td>{{ server.application_type }} ({{ server.application_version }})</td>
<td>{{ server.status }}</td>
<td>
{% if server.application_type %}
{{ server.application_type }}
{% if server.application_version %}({{ server.application_version }}){% endif %}
{% endif %}
</td>
<td>{{ server.user_set.count }}</td>
<td>{{ server.get_status_display }}</td>
</tr>
{% endfor %}
</table>

View file

@ -0,0 +1,36 @@
{% extends 'components/inline_form.html' %}
{% load i18n %}
{% block header %}
{% trans "Add IP address" %}
{% endblock %}
{% block form %}
<form name="add-address" method="post" action="{% url 'settings-ip-blocks' %}">
<div class="block">
{% trans "Use IP address blocks with caution, and consider using blocks only temporarily, as IP addresses are often shared or change hands. If you block your own IP, you will not be able to access this page." %}
</div>
{% csrf_token %}
<div class="field">
<label class="label" for="id_address">
{% trans "IP Address:" %}
</label>
</div>
<div class="field">
<input type="text" name="address" maxlength="255" class="input" required="" id="id_address" placeholder="190.0.2.0/24">
</div>
{% for error in form.address.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<div class="field">
<div class="control">
<button type="submit" class="button is-primary">{% trans "Add" %}</button>
</div>
</div>
</form>
{% endblock %}

View file

@ -0,0 +1,47 @@
{% extends 'settings/layout.html' %}
{% load i18n %}
{% load humanize %}
{% block title %}{% trans "IP Address Blocklist" %}{% endblock %}
{% block header %}{% trans "IP Address Blocklist" %}{% endblock %}
{% block edit-button %}
{% trans "Add IP address" as button_text %}
{% include 'snippets/toggle/open_button.html' with controls_text="add_address" icon_with_text="plus" text=button_text focus="add_address_header" %}
{% endblock %}
{% block panel %}
{% include 'settings/ip_address_form.html' with controls_text="add_address" class="block" %}
<p class="notification block">
{% trans "Any traffic from this IP address will get a 404 response when trying to access any part of the application." %}
</p>
<table class="table is-striped is-fullwidth">
<tr>
<th>
{% trans "Address" %}
</th>
<th>
{% trans "Options" %}
</th>
</tr>
{% for address in addresses %}
<tr>
<td>{{ address.address }}</td>
<td>
<form name="remove-{{ address.id }}" action="{% url 'settings-ip-blocks-delete' address.id %}" method="post">
{% csrf_token %}
{% trans "Delete" as button_text %}
<button class="button" type="submit">
<span class="icon icon-x" title="{{ button_text }}" aria-hidden="true"></span>
<span class="is-hidden-mobile">{{ button_text }}</span>
</button>
</form>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View file

@ -0,0 +1,8 @@
{% extends 'components/tooltip.html' %}
{% load i18n %}
{% block tooltip_content %}
{% trans "You can block IP ranges using CIDR syntax." %}
{% endblock %}

View file

@ -18,6 +18,13 @@
<div class="block columns">
<nav class="menu column is-one-quarter">
<h2 class="menu-label">
{% url 'settings-dashboard' as url %}
<a
href="{{ url }}"
{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}
>{% trans "Dashboard" %}</a>
</h2>
{% if perms.bookwyrm.create_invites %}
<h2 class="menu-label">{% trans "Manage Users" %}</h2>
<ul class="menu-list">
@ -32,12 +39,6 @@
{% url 'settings-invites' as alt_url %}
<a href="{{ url }}"{% if url in request.path or request.path in alt_url %} class="is-active" aria-selected="true"{% endif %}>{% trans "Invites" %}</a>
</li>
{% if perms.bookwyrm.moderate_user %}
<li>
{% url 'settings-reports' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Reports" %}</a>
</li>
{% endif %}
{% if perms.bookwyrm.control_federation %}
<li>
{% url 'settings-federation' as url %}
@ -46,6 +47,23 @@
{% endif %}
</ul>
{% endif %}
{% if perms.bookwyrm.moderate_user %}
<h2 class="menu-label">{% trans "Moderation" %}</h2>
<ul class="menu-list">
<li>
{% url 'settings-reports' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Reports" %}</a>
</li>
<li>
{% url 'settings-email-blocks' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Email Blocklist" %}</a>
</li>
<li>
{% url 'settings-ip-blocks' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "IP Address Blocklist" %}</a>
</li>
</ul>
{% endif %}
{% if perms.bookwyrm.edit_instance_settings %}
<h2 class="menu-label">{% trans "Instance Settings" %}</h2>
<ul class="menu-list">

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% load humanize %}
{% block header %}{% trans "Invite Requests" %}{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% block header %}{% trans "Invites" %}{% endblock %}
{% load humanize %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% block title %}{% trans "Add instance" %}{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% block title %}{% trans "Site Settings" %}{% endblock %}
@ -23,6 +23,11 @@
<label class="label" for="id_instance_description">{% trans "Instance description:" %}</label>
{{ site_form.instance_description }}
</div>
<div class="field">
<label class="label mb-0" for="id_short_description">{% trans "Short description:" %}</label>
<p class="help">{% trans "Used when the instance is previewed on joinbookwyrm.com. Does not support html or markdown." %}</p>
{{ site_form.instance_short_description }}
</div>
<div class="field">
<label class="label" for="id_code_of_conduct">{% trans "Code of conduct:" %}</label>
{{ site_form.code_of_conduct }}
@ -102,6 +107,13 @@
<label class="label" for="id_registration_closed_text">{% trans "Registration closed text:" %}</label>
{{ site_form.registration_closed_text }}
</div>
<div class="field">
<label class="label" for="id_invite_request_text">{% trans "Invite request text:" %}</label>
{{ site_form.invite_request_text }}
{% for error in site_form.invite_request_text.errors %}
<p class="help is-danger">{{ error|escape }}</p>
{% endfor %}
</div>
</section>
<footer class="block">

View file

@ -35,11 +35,16 @@ uuid: a unique identifier used to make html "id" attributes unique and clarify j
size="3"
value="{% firstof draft.progress readthrough.progress '' %}"
id="progress_{{ uuid }}"
data-cache-draft="id_progress_comment_{{ book.id }}"
>
</div>
<div class="control">
<div class="select">
<select name="progress_mode" aria-label="Progress mode">
<select
name="progress_mode"
aria-label="Progress mode"
data-cache-draft="id_progress_mode_comment_{{ book.id }}"
>
<option
value="PG"
{% if draft.progress_mode == 'PG' or readthrough.progress_mode == 'PG' %}selected{% endif %}

View file

@ -10,7 +10,8 @@ draft: an existing Status object that is providing default values for input fiel
{% endcomment %}
<textarea
name="content"
class="textarea"
class="textarea save-draft"
data-cache-draft="id_content_{{ type }}_{{ book.id }}{{ reply_parent.id }}"
id="id_content_{{ type }}_{{ book.id }}{{ reply_parent.id }}"
placeholder="{{ placeholder }}"
aria-label="{% if reply_parent %}{% trans 'Reply' %}{% else %}{% trans 'Content' %}{% endif %}"

View file

@ -1,12 +1,22 @@
{% load i18n %}
<div class="control{% if not parent_status.content_warning and not draft.content_warning %} is-hidden{% endif %}" id="spoilers_{{ uuid }}">
<label class="is-sr-only" for="id_content_warning_{{ uuid }}">{% trans "Spoiler alert:" %}</label>
<div
class="field{% if not reply_parent.content_warning and not draft.content_warning %} is-hidden{% endif %}"
id="spoilers_{{ uuid }}{{ local_uuid }}"
>
<label
class="label"
for="id_content_warning_{{ uuid }}{{ local_uuid }}"
>
{% trans "Content warning:" %}
</label>
<input
type="text"
name="content_warning"
maxlength="255"
class="input"
id="id_content_warning_{{ uuid }}"
id="id_content_warning_{{ uuid }}{{ local_uuid }}"
placeholder="{% trans 'Spoilers ahead!' %}"
value="{% firstof draft.content_warning parent_status.content_warning '' %}">
value="{% firstof draft.content_warning reply_parent.content_warning '' %}"
data-cache-draft="id_content_warning_{{ book.id }}_{{ type }}"
>
</div>

View file

@ -1,8 +1,17 @@
{% load i18n %}
<div class="control">
<input type="checkbox" class="is-hidden" name="sensitive" id="id_show_spoilers_{{ uuid }}" {% if draft.content_warning or status.content_warning %}checked{% endif %} aria-hidden="true">
<input
type="checkbox"
class="is-hidden"
name="sensitive"
id="id_show_spoilers_{{ uuid }}{{ local_uuid }}"
{% if draft.content_warning or status.content_warning %}checked{% endif %}
aria-hidden="true"
data-cache-draft="id_sensitive_{{ book.id }}_{{ type }}{{ reply_parent.id }}"
>
{% trans "Include spoiler alert" as button_text %}
{% firstof draft.content_warning status.content_warning as pressed %}
{% include 'snippets/toggle/toggle_button.html' with text=button_text icon="warning is-size-4" controls_text="spoilers" controls_uid=uuid focus="id_content_warning" checkbox="id_show_spoilers" class="toggle-button" pressed=pressed %}
{% firstof local_uuid '' as local_uuid %}
{% include 'snippets/toggle/toggle_button.html' with text=button_text icon="warning is-size-4" controls_text="spoilers" controls_uid=uuid|add:local_uuid focus="id_content_warning" checkbox="id_show_spoilers" class="toggle-button" pressed=pressed %}
</div>

View file

@ -14,7 +14,13 @@ reply_parent: the Status object this post will be in reply to, if applicable
{% block form_open %}
{# default form tag syntax, can be overriddden #}
<form class="is-flex-grow-1" name="{{ type }}" action="/post/{{ type }}" method="post" id="tab_{{ type }}_{{ book.id }}{{ reply_parent.id }}">
<form
class="is-flex-grow-1{% if not no_script %} submit-status{% endif %}"
name="{{ type }}"
action="/post/{{ type }}"
method="post"
id="tab_{{ type }}_{{ book.id }}{{ reply_parent.id }}"
>
{% endblock %}
{% csrf_token %}
@ -25,23 +31,19 @@ reply_parent: the Status object this post will be in reply to, if applicable
<input type="hidden" name="reply_parent" value="{% firstof draft.reply_parent.id reply_parent.id %}">
{% endblock %}
{% include "snippets/create_status/content_warning_field.html" %}
{# fields that go between the content warnings and the content field (ie, quote) #}
{% block pre_content_additions %}{% endblock %}
<label class="label" for="id_content_{{ type }}_{{ book.id }}{{ reply_parent.id }}">
{% block content_label %}
{% trans "Comment:" %}
{% endblock %}
</label>
<div class="field">
<div class="control">
{% include "snippets/create_status/content_warning_field.html" %}
</div>
{# fields that go between the content warnings and the content field (ie, quote) #}
{% block pre_content_additions %}{% endblock %}
<label class="label" for="id_content_{{ type }}_{{ book.id }}{{ reply_parent.id }}">
{% block content_label %}
{% trans "Comment:" %}
{% endblock %}
</label>
<div class="control">
{% include "snippets/create_status/content_field.html" with placeholder=placeholder %}
</div>
{% include "snippets/create_status/content_field.html" with placeholder=placeholder %}
</div>
{# additional fields that go after the content block (ie, progress) #}

View file

@ -16,7 +16,10 @@
</div>
</div>
<div class="column is-narrow">
<button class="button is-link" type="submit">{% trans "Post" %}</button>
<button class="button is-link" type="submit">
<span class="icon icon-spinner" aria-hidden="true"></span>
<span>{% trans "Post" %}</span>
</button>
</div>
</div>

View file

@ -24,6 +24,7 @@ uuid: a unique identifier used to make html "id" attributes unique and clarify j
id="id_quote_{{ book.id }}_{{ type }}"
placeholder="{% blocktrans with book_title=book.title %}An excerpt from '{{ book_title }}'{% endblocktrans %}"
required
data-cache-draft="id_quote_{{ book.id }}_{{ type }}"
>{{ draft.quote|default:'' }}</textarea>
</div>
</div>
@ -32,7 +33,11 @@ uuid: a unique identifier used to make html "id" attributes unique and clarify j
<div class="field has-addons mb-0">
<div class="control">
<div class="select">
<select name="position_mode" aria-label="Position mode">
<select
name="position_mode"
aria-label="Position mode"
data-cache-draft="id_position_mode_{{ book.id }}_{{ type }}"
>
<option
value="PG"
{% if draft.position_mode == 'PG' or not draft %}selected{% endif %}
@ -58,6 +63,7 @@ uuid: a unique identifier used to make html "id" attributes unique and clarify j
size="3"
value="{% firstof draft.position '' %}"
id="position_{{ uuid }}"
data-cache-draft="id_position_{{ book.id }}_{{ type }}"
>
</div>
</div>

View file

@ -15,7 +15,17 @@ uuid: a unique identifier used to make html "id" attributes unique and clarify j
<div class="field">
<label class="label" for="id_name_{{ book.id }}">{% trans "Title:" %}</label>
<div class="control">
<input type="text" name="name" maxlength="255" class="input" required="" id="id_name_{{ book.id }}" placeholder="{% blocktrans with book_title=book.title %}Your review of '{{ book_title }}'{% endblocktrans %}" value="{% firstof draft.name ''%}">
<input
type="text"
name="name"
maxlength="255"
class="input"
required=""
id="id_name_{{ book.id }}"
placeholder="{% blocktrans with book_title=book.title %}Your review of '{{ book_title }}'{% endblocktrans %}"
value="{% firstof draft.name ''%}"
data-cache-draft="id_name_{{ book.id }}_{{ type }}"
>
</div>
</div>

View file

@ -1,5 +1,6 @@
{% spaceless %}
{% load i18n %}
{% load stars %}
<div class="
field is-grouped
@ -20,6 +21,24 @@
</label>
{% for i in '12345'|make_list %}
<label
class="is-sr-only"
for="{{ type|slugify }}_book{{ book.id }}_star_{{ forloop.counter0 }}_half"
>
{% blocktranslate trimmed count rating=forloop.counter0 with half_rating=forloop.counter0|half_star %}
{{ half_rating }} star
{% plural %}
{{ half_rating }} stars
{% endblocktranslate %}
</label>
<input
id="{{ type|slugify }}_book{{ book.id }}_star_{{ forloop.counter0 }}_half"
class="is-sr-only half"
type="radio"
name="rating"
value="{{ forloop.counter0 }}.5"
{% if default_rating == forloop.counter %}checked{% endif %}
/>
<input
id="{{ type|slugify }}_book{{ book.id }}_star_{{ forloop.counter }}"
class="is-sr-only"
@ -39,6 +58,7 @@
{% endif %}
"
for="{{ type|slugify }}_book{{ book.id }}_star_{{ forloop.counter }}"
data-for-half="{{ type|slugify }}_book{{ book.id }}_star_{{ forloop.counter0 }}_half"
>
<span class="is-sr-only">
{% blocktranslate trimmed count rating=forloop.counter %}

View file

@ -1,5 +1,5 @@
{% load i18n %}
<form method="post" name="goal" action="{{ request.user.local_path }}/goal/{{ year }}">
<form method="post" name="goal" action="{% url 'user-goal' request.user.localname year %}">
{% csrf_token %}
<input type="hidden" name="year" value="{% if goal %}{{ goal.year }}{% else %}{{ year }}{% endif %}">
<input type="hidden" name="user" value="{{ request.user.id }}">

View file

@ -9,7 +9,7 @@ Finish "<em>{{ book_title }}</em>"
{% endblock %}
{% block modal-form-open %}
<form name="finish-reading" action="{% url 'reading-status' 'finish' book.id %}" method="post">
<form name="finish-reading" action="{% url 'reading-status' 'finish' book.id %}" method="post" class="submit-status">
{% csrf_token %}
<input type="hidden" name="reading_status" value="read">
{% endblock %}

View file

@ -12,4 +12,5 @@
<input type="hidden" name="user" value="{{ request.user.id }}">
<input type="hidden" name="mention_books" value="{{ book.id }}">
<input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="id" value="{{ readthrough.id }}">
{% endblock %}

View file

@ -6,7 +6,7 @@
{% endblock %}
{% block modal-form-open %}
<form action="{% url 'edit-readthrough' %}" method="POST">
<form action="{% url 'edit-readthrough' %}" method="POST" class="submit-status">
{% endblock %}
{% block modal-body %}
@ -23,7 +23,8 @@
min="0"
name="progress"
size="3"
value="{{ readthrough.progress|default:'' }}">
value="{{ readthrough.progress|default:'' }}"
>
</div>
<div class="control select">
<select name="progress_mode" aria-label="Progress mode">

View file

@ -9,7 +9,7 @@ Start "<em>{{ book_title }}</em>"
{% endblock %}
{% block modal-form-open %}
<form name="start-reading" action="{% url 'reading-status' 'start' book.id %}" method="post">
<form name="start-reading" action="{% url 'reading-status' 'start' book.id %}" method="post" class="submit-status">
<input type="hidden" name="reading_status" value="reading">
{% csrf_token %}
{% endblock %}

View file

@ -9,7 +9,7 @@ Want to Read "<em>{{ book_title }}</em>"
{% endblock %}
{% block modal-form-open %}
<form name="shelve" action="{% url 'reading-status' 'want' book.id %}" method="post">
<form name="shelve" action="{% url 'reading-status' 'want' book.id %}" method="post" class="submit-status">
<input type="hidden" name="reading_status" value="to-read">
{% csrf_token %}
{% endblock %}

View file

@ -6,7 +6,7 @@
{% with book.id|uuid as uuid %}
{% active_shelf book as active_shelf %}
{% latest_read_through book request.user as readthrough %}
<div class="field has-addons mb-0">
<div class="field has-addons mb-0" data-shelve-button-book="{{ book.id }}">
{% if switch_mode and active_shelf.book != book %}
<div class="control">
{% include 'snippets/switch_edition_button.html' with edition=book size='is-small' %}

View file

@ -7,5 +7,5 @@
{% endblock %}
{% block dropdown-list %}
{% include 'snippets/shelve_button/shelve_button_options.html' with active_shelf=active_shelf shelves=user_shelves dropdown=True class="shelf-option is-fullwidth is-small is-radiusless is-white" %}
{% include 'snippets/shelve_button/shelve_button_dropdown_options.html' with active_shelf=active_shelf shelves=user_shelves dropdown=True class="shelf-option is-fullwidth is-small is-radiusless is-white" %}
{% endblock %}

View file

@ -0,0 +1,69 @@
{% load bookwyrm_tags %}
{% load utilities %}
{% load i18n %}
{% with next_shelf_identifier=active_shelf.shelf.identifier|next_shelf %}
{% for shelf in shelves %}
{% comparison_bool shelf.identifier active_shelf.shelf.identifier as is_current %}
<li role="menuitem" class="dropdown-item p-0">
<div
class="{% if next_shelf_identifier == shelf.identifier %}is-hidden{% endif %}"
data-shelf-dropdown-identifier="{{ shelf.identifier }}"
data-shelf-next="{{ shelf.identifier|next_shelf }}"
>
{% if shelf.identifier == 'reading' %}
{% trans "Start reading" as button_text %}
{% url 'reading-status' 'start' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="start_reading" controls_uid=button_uuid focus="modal_title_start_reading" disabled=is_current fallback_url=fallback_url %}
{% elif shelf.identifier == 'read' %}
{% trans "Read" as button_text %}
{% url 'reading-status' 'finish' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="finish_reading" controls_uid=button_uuid focus="modal_title_finish_reading" disabled=is_current fallback_url=fallback_url %}
{% elif shelf.identifier == 'to-read' %}
{% trans "Want to read" as button_text %}
{% url 'reading-status' 'want' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="want_to_read" controls_uid=button_uuid focus="modal_title_want_to_read" disabled=is_current fallback_url=fallback_url %}
{% elif shelf.editable %}
<form name="shelve" action="/shelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
<button class="button {{ class }}" name="shelf" type="submit" value="{{ shelf.identifier }}" {% if shelf in book.shelf_set.all %} disabled {% endif %}>
<span>{{ shelf.name }}</span>
</button>
</form>
{% endif %}
</div>
</li>
{% endfor %}
{% if readthrough and active_shelf.shelf.identifier != 'read' %}
<li role="menuitem" class="dropdown-item p-0" data-extra-options>
{% trans "Update progress" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="progress_update" controls_uid=button_uuid focus="modal_title_progress_update" %}
</li>
{% endif %}
{% if active_shelf.shelf %}
<li role="menuitem" class="dropdown-item p-0" data-extra-options>
<form name="shelve" action="/unshelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
<input type="hidden" name="shelf" value="{{ active_shelf.shelf.id }}">
<button class="button is-fullwidth is-small{% if dropdown %} is-radiusless{% endif %} is-danger is-light" type="submit">
{% blocktrans with name=active_shelf.shelf.name %}Remove from {{ name }}{% endblocktrans %}
</button>
</form>
</li>
{% endif %}
{% endwith %}

View file

@ -2,33 +2,43 @@
{% load utilities %}
{% load i18n %}
{% for shelf in shelves %}
{% comparison_bool shelf.identifier active_shelf.shelf.identifier as is_current %}
{% if dropdown %}<li role="menuitem" class="dropdown-item p-0">{% endif %}
<div class="{% if not dropdown and active_shelf.shelf.identifier|next_shelf != shelf.identifier %}is-hidden{% endif %}">
{% if shelf.identifier == 'reading' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
{% with next_shelf_identifier=active_shelf.shelf.identifier|next_shelf %}
{% trans "Start reading" as button_text %}
{% url 'reading-status' 'start' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="start_reading" controls_uid=button_uuid focus="modal_title_start_reading" disabled=is_current fallback_url=fallback_url %}
{% endif %}{% elif shelf.identifier == 'read' and active_shelf.shelf.identifier == 'read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
<div
class="{% if next_shelf_identifier != 'complete' %}is-hidden{% endif %}"
data-shelf-identifier="complete"
>
<button type="button" class="button {{ class }}" disabled>
<span>{% trans "Read" %}</span>
</button>
{% endif %}{% elif shelf.identifier == 'read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
</div>
{% trans "Finish reading" as button_text %}
{% url 'reading-status' 'finish' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="finish_reading" controls_uid=button_uuid focus="modal_title_finish_reading" disabled=is_current fallback_url=fallback_url %}
{% for shelf in shelves %}
<div
class="{% if next_shelf_identifier != shelf.identifier %}is-hidden{% endif %}"
data-shelf-identifier="{{ shelf.identifier }}"
data-shelf-next="{{ shelf.identifier|next_shelf }}"
>
{% if shelf.identifier == 'reading' %}
{% endif %}{% elif shelf.identifier == 'to-read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
{% trans "Start reading" as button_text %}
{% url 'reading-status' 'start' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="start_reading" controls_uid=button_uuid focus="modal_title_start_reading" fallback_url=fallback_url %}
{% trans "Want to read" as button_text %}
{% url 'reading-status' 'want' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="want_to_read" controls_uid=button_uuid focus="modal_title_want_to_read" disabled=is_current fallback_url=fallback_url %}
{% elif shelf.identifier == 'read' %}
{% trans "Finish reading" as button_text %}
{% url 'reading-status' 'finish' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="finish_reading" controls_uid=button_uuid focus="modal_title_finish_reading" fallback_url=fallback_url %}
{% elif shelf.identifier == 'to-read' %}
{% trans "Want to read" as button_text %}
{% url 'reading-status' 'want' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="want_to_read" controls_uid=button_uuid focus="modal_title_want_to_read" fallback_url=fallback_url %}
{% elif shelf.editable %}
{% endif %}{% elif shelf.editable %}
<form name="shelve" action="/shelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
@ -36,30 +46,9 @@
<span>{{ shelf.name }}</span>
</button>
</form>
{% endif %}
</div>
{% if dropdown %}</li>{% endif %}
{% endfor %}
{% if dropdown %}
{% if readthrough and active_shelf.shelf.identifier != 'read' %}
<li role="menuitem" class="dropdown-item p-0">
{% trans "Update progress" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="progress_update" controls_uid=button_uuid focus="modal_title_progress_update" %}
</li>
{% endif %}
{% if active_shelf.shelf %}
<li role="menuitem" class="dropdown-item p-0">
<form name="shelve" action="/unshelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
<input type="hidden" name="shelf" value="{{ active_shelf.shelf.id }}">
<button class="button is-fullwidth is-small{% if dropdown %} is-radiusless{% endif %} is-danger is-light" type="submit">
{% blocktrans with name=active_shelf.shelf.name %}Remove from {{ name }}{% endblocktrans %}
</button>
</form>
</li>
{% endif %}
{% endif %}
{% endwith %}

View file

@ -67,12 +67,18 @@
{% endif %}
{% if status.content_warning %}
<div>
<p>{{ status.content_warning }}</p>
<div class="notification p-2 is-clearfix is-warning is-light">
<p class="is-pulled-left is-flex">
{% trans "Content warning" as text %}
<span class="icon icon-warning" title="{{ text }}">
<span class="is-sr-only">{{ text }}</span>
</span>
{{ status.content_warning }}
</p>
{% trans "Show more" as button_text %}
{% trans "Show status" as button_text %}
{% with text=button_text class="is-small" controls_text="show_status_cw" controls_uid=status.id %}
{% with text=button_text class="is-small is-pulled-right" icon_with_text="arrow-down" controls_text="show_status_cw" controls_uid=status.id %}
{% include 'snippets/toggle/open_button.html' %}
{% endwith %}
</div>
@ -84,17 +90,9 @@
class="is-hidden"
{% endif %}
>
{% if status.content_warning %}
{% trans "Show less" as button_text %}
{% with text=button_text class="is-small" controls_text="show_status_cw" controls_uid=status.id %}
{% include 'snippets/toggle/close_button.html' %}
{% endwith %}
{% endif %}
{% if status.quote %}
<div class="quote block">
<blockquote dir="auto" class="content mb-2">{{ status.quote|safe }}</blockquote>
<blockquote dir="auto" class="content mb-2 preserve-whitespace">{{ status.quote|safe }}</blockquote>
<p>
&mdash; {% include 'snippets/book_titleby.html' with book=status.book %}
@ -141,6 +139,14 @@
</div>
</div>
{% endif %}
{% if status.content_warning %}
{% trans "Hide status" as button_text %}
{% with text=button_text class="is-small" controls_text="show_status_cw" controls_uid=status.id icon_with_text="arrow-up" %}
{% include 'snippets/toggle/close_button.html' %}
{% endwith %}
{% endif %}
</div>
</article>
</div>

View file

@ -66,7 +66,7 @@
{% block card-bonus %}
{% if request.user.is_authenticated and not moderation_mode %}
{% with status.id|uuid as uuid %}
<section class="is-hidden" id="show_comment_{{ status.id }}">
<section class="reply-panel is-hidden" id="show_comment_{{ status.id }}">
<div class="card-footer">
<div class="card-footer-item">
{% include 'snippets/create_status/status.html' with type="reply" reply_parent=status book=None %}

View file

@ -10,7 +10,7 @@
{% if not no_trim and trimmed != full %}
<div id="hide_full_{{ uuid }}">
<div class="content" id="trimmed_{{ uuid }}">
<div dir="auto">{{ trimmed }}</div>
<div dir="auto" class="preserve-whitespace">{{ trimmed }}</div>
<div>
{% if not hide_more %}
@ -25,6 +25,7 @@
<div class="content">
<div
dir="auto"
class="preserve-whitespace"
{% if itemprop %}itemprop="{{ itemprop }}"{% endif %}
>
{{ full }}
@ -41,6 +42,7 @@
<div class="content">
<div
dir="auto"
class="preserve-whitespace"
{% if itemprop %}itemprop="{{ itemprop }}"{% endif %}
>
{{ full }}

View file

@ -0,0 +1,25 @@
{% extends "components/inline_form.html" %}
{% load i18n %}
{% block header %}
{% trans "Permanently delete user" %}
{% endblock %}
{% block form %}
<form name="delete-user" action="{% url 'settings-delete-user' user.id %}" method="post">
{% csrf_token %}
<p>
{% blocktrans trimmed with username=user.localname %}
Are you sure you want to delete <strong>{{ username}}</strong>'s account? This action cannot be undone. To proceed, please enter your password to confirm deletion.
{% endblocktrans %}
</p>
<div class="field">
<label class="label" for="id_password">{% trans "Your password:" %}</label>
<input class="input {% if form.password.errors %}is-danger{% endif %}" type="password" name="password" id="id_password" required>
{% for error in form.password.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<button type="submit" class="button is-danger">{% trans "Delete Account" %}</button>
</form>
{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% block title %}{{ user.username }}{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'settings/admin_layout.html' %}
{% extends 'settings/layout.html' %}
{% load i18n %}
{% block title %}{% trans "Users" %}{% endblock %}

View file

@ -27,7 +27,7 @@
<p class="notification is-warning">
{% trans "Inactive" %}
{% if user.deactivation_reason %}
({{ user.deactivation_reason }})
<span class="help">({% trans user.get_deactivation_reason_display %})</span>
{% endif %}
</p>
{% endif %}

View file

@ -1,6 +1,6 @@
{% load i18n %}
<div class="block content">
{% if not user.is_active and user.deactivation_reason == "self_deletion" %}
{% if not user.is_active and user.deactivation_reason == "self_deletion" or user.deactivation_reason == "moderator_deletion" %}
<div class="notification is-danger">
{% trans "Permanently deleted" %}
</div>
@ -8,19 +8,38 @@
<h3>{% trans "Actions" %}</h3>
<div class="is-flex">
{% if user.is_active %}
<p class="mr-1">
<a class="button" href="{% url 'direct-messages-user' user.username %}">{% trans "Send direct message" %}</a>
</p>
<form name="suspend" method="post" action="{% url 'settings-report-suspend' user.id %}">
{% endif %}
{% if user.is_active or user.deactivation_reason == "pending" %}
<form name="suspend" method="post" action="{% url 'settings-report-suspend' user.id %}" class="mr-1">
{% csrf_token %}
{% if user.is_active %}
<button type="submit" class="button is-danger is-light">{% trans "Suspend user" %}</button>
{% else %}
<button class="button">{% trans "Un-suspend user" %}</button>
{% endif %}
</form>
{% else %}
<form name="unsuspend" method="post" action="{% url 'settings-report-unsuspend' user.id %}" class="mr-1">
{% csrf_token %}
<button class="button">{% trans "Un-suspend user" %}</button>
</form>
{% endif %}
{% if user.local %}
<div>
{% trans "Permanently delete user" as button_text %}
{% include "snippets/toggle/open_button.html" with controls_text="delete_user" text=button_text class="is-danger is-light" %}
</div>
{% endif %}
</div>
{% if user.local %}
<div>
{% include "user_admin/delete_user_form.html" with controls_text="delete_user" class="mt-2 mb-2" %}
</div>
{% endif %}
{% if user.local %}
<div>
<form name="permission" method="post" action="{% url 'settings-user' user.id %}">