Merge branch 'main' into production

This commit is contained in:
Mouse Reeve 2021-03-01 11:44:13 -08:00
commit a1428a6030
130 changed files with 4877 additions and 891 deletions

View file

@ -10,6 +10,7 @@ WORKDIR /app
COPY requirements.txt /app/
RUN pip install -r requirements.txt
RUN apt-get update && apt-get install -y gettext libgettextpo-dev
COPY ./bookwyrm /app
COPY ./celerywyrm /app

View file

@ -30,6 +30,9 @@ Code contributions are gladly welcomed! If you're not sure where to start, take
If you have questions about the project or contributing, you can set up a video call during BookWyrm ["office hours"](https://calendly.com/mouse-reeve/30min).
### Translation
Do you speak a language besides English? BookWyrm needs localization! If you're comfortable using git and want to get into the code, there are [instructions](#workin-with-translations-and-locale-files) on how to create and edit localization files. If you feel more comfortable working in a regular text editor and would prefer not to run the application, get in touch directly and we can figure out a system, like emailing a text file, that works best.
### Financial Support
BookWyrm is an ad-free passion project with no intentions of seeking out venture funding or corporate financial relationships. If you want to help keep the project going, you can donate to the [Patreon](https://www.patreon.com/bookwyrm), or make a one time gift via [PayPal](https://paypal.me/oulipo).
@ -109,6 +112,33 @@ docker-compose up
Once the build is complete, you can access the instance at `localhost:1333`
### Editing static files
If you edit the CSS or JavaScript, you will need to run Django's `collectstatic` command in order for your changes to have effect. You can do this by running:
``` bash
./bw-dev collectstatic
```
### Workin with translations and locale files
Text in the html files are wrapped in translation tags (`{% trans %}` and `{% blocktrans %}`), and Django generates locale files for all the strings in which you can add translations for the text. You can find existing translations in the `locale/` directory.
The application's language is set by a request header sent by your browser to the application, so to change the language of the application, you can change the default language requested by your browser.
#### Adding a locale
To start translation into a language which is currently supported, run the django-admin `makemessages` command with the language code for the language you want to add (like `de` for German, or `en-gb` for British English):
``` bash
./bw-dev makemessages -l <language code>
```
#### Editing a locale
When you have a locale file, open the `django.po` in the directory for the language (for example, if you were adding German, `locale/de/LC_MESSAGES/django.po`. All the the text in the application will be shown in paired strings, with `msgid` as the original text, and `msgstr` as the translation (by default, this is set to an empty string, and will display the original text).
Add you translations to the `msgstr` strings, and when you're ready, compile the locale by running:
``` bash
./bw-dev compilemessages
```
You can add the `-l <language code>` to only compile one language. When you refresh the application, you should see your translations at work.
## Installing in Production
This project is still young and isn't, at the moment, very stable, so please proceed with caution when running in production.

View file

@ -1,121 +1,13 @@
''' handle reading a csv from goodreads '''
import csv
import logging
from bookwyrm.importer import Importer
from bookwyrm import models
from bookwyrm.models import ImportJob, ImportItem
from bookwyrm.tasks import app
# GoodReads is the default importer, thus Importer follows its structure. For a more complete example of overriding see librarything_import.py
logger = logging.getLogger(__name__)
class GoodreadsImporter(Importer):
service = 'GoodReads'
def create_job(user, csv_file, include_reviews, privacy):
''' check over a csv and creates a database entry for the job'''
job = ImportJob.objects.create(
user=user,
include_reviews=include_reviews,
privacy=privacy
)
for index, entry in enumerate(list(csv.DictReader(csv_file))):
if not all(x in entry for x in ('ISBN13', 'Title', 'Author')):
raise ValueError('Author, title, and isbn must be in data.')
ImportItem(job=job, index=index, data=entry).save()
return job
def create_retry_job(user, original_job, items):
''' retry items that didn't import '''
job = ImportJob.objects.create(
user=user,
include_reviews=original_job.include_reviews,
privacy=original_job.privacy,
retry=True
)
for item in items:
ImportItem(job=job, index=item.index, data=item.data).save()
return job
def start_import(job):
''' initalizes a csv import job '''
result = import_data.delay(job.id)
job.task_id = result.id
job.save()
@app.task
def import_data(job_id):
''' does the actual lookup work in a celery task '''
job = ImportJob.objects.get(id=job_id)
try:
for item in job.items.all():
try:
item.resolve()
except Exception as e:# pylint: disable=broad-except
logger.exception(e)
item.fail_reason = 'Error loading book'
item.save()
continue
if item.book:
item.save()
# shelves book and handles reviews
handle_imported_book(
job.user, item, job.include_reviews, job.privacy)
else:
item.fail_reason = 'Could not find a match for book'
item.save()
finally:
job.complete = True
job.save()
def handle_imported_book(user, item, include_reviews, privacy):
''' process a goodreads csv and then post about it '''
if isinstance(item.book, models.Work):
item.book = item.book.default_edition
if not item.book:
return
existing_shelf = models.ShelfBook.objects.filter(
book=item.book, user=user).exists()
# shelve the book if it hasn't been shelved already
if item.shelf and not existing_shelf:
desired_shelf = models.Shelf.objects.get(
identifier=item.shelf,
user=user
)
models.ShelfBook.objects.create(
book=item.book, shelf=desired_shelf, user=user)
for read in item.reads:
# check for an existing readthrough with the same dates
if models.ReadThrough.objects.filter(
user=user, book=item.book,
start_date=read.start_date,
finish_date=read.finish_date
).exists():
continue
read.book = item.book
read.user = user
read.save()
if include_reviews and (item.rating or item.review):
review_title = 'Review of {!r} on Goodreads'.format(
item.book.title,
) if item.review else ''
# we don't know the publication date of the review,
# but "now" is a bad guess
published_date_guess = item.date_read or item.date_added
models.Review.objects.create(
user=user,
book=item.book,
name=review_title,
content=item.review,
rating=item.rating,
published_date=published_date_guess,
privacy=privacy,
)
def parse_fields(self, data):
data.update({'import_source': self.service })
# add missing 'Date Started' field
data.update({'Date Started': None })
return data

135
bookwyrm/importer.py Normal file
View file

@ -0,0 +1,135 @@
''' handle reading a csv from an external service, defaults are from GoodReads '''
import csv
import logging
from bookwyrm import models
from bookwyrm.models import ImportJob, ImportItem
from bookwyrm.tasks import app
logger = logging.getLogger(__name__)
class Importer:
service = 'Unknown'
delimiter = ','
encoding = 'UTF-8'
mandatory_fields = ['Title', 'Author']
def create_job(self, user, csv_file, include_reviews, privacy):
''' check over a csv and creates a database entry for the job'''
job = ImportJob.objects.create(
user=user,
include_reviews=include_reviews,
privacy=privacy
)
for index, entry in enumerate(list(csv.DictReader(csv_file, delimiter=self.delimiter ))):
if not all(x in entry for x in self.mandatory_fields):
raise ValueError('Author and title must be in data.')
entry = self.parse_fields(entry)
self.save_item(job, index, entry)
return job
def save_item(self, job, index, data):
ImportItem(job=job, index=index, data=data).save()
def parse_fields(self, entry):
entry.update({'import_source': self.service })
return entry
def create_retry_job(self, user, original_job, items):
''' retry items that didn't import '''
job = ImportJob.objects.create(
user=user,
include_reviews=original_job.include_reviews,
privacy=original_job.privacy,
retry=True
)
for item in items:
self.save_item(job, item.index, item.data)
return job
def start_import(self, job):
''' initalizes a csv import job '''
result = import_data.delay(self.service, job.id)
job.task_id = result.id
job.save()
@app.task
def import_data(source, job_id):
''' does the actual lookup work in a celery task '''
job = ImportJob.objects.get(id=job_id)
try:
for item in job.items.all():
try:
item.resolve()
except Exception as e:# pylint: disable=broad-except
logger.exception(e)
item.fail_reason = 'Error loading book'
item.save()
continue
if item.book:
item.save()
# shelves book and handles reviews
handle_imported_book(source,
job.user, item, job.include_reviews, job.privacy)
else:
item.fail_reason = 'Could not find a match for book'
item.save()
finally:
job.complete = True
job.save()
def handle_imported_book(source, user, item, include_reviews, privacy):
''' process a csv and then post about it '''
if isinstance(item.book, models.Work):
item.book = item.book.default_edition
if not item.book:
return
existing_shelf = models.ShelfBook.objects.filter(
book=item.book, user=user).exists()
# shelve the book if it hasn't been shelved already
if item.shelf and not existing_shelf:
desired_shelf = models.Shelf.objects.get(
identifier=item.shelf,
user=user
)
models.ShelfBook.objects.create(
book=item.book, shelf=desired_shelf, user=user)
for read in item.reads:
# check for an existing readthrough with the same dates
if models.ReadThrough.objects.filter(
user=user, book=item.book,
start_date=read.start_date,
finish_date=read.finish_date
).exists():
continue
read.book = item.book
read.user = user
read.save()
if include_reviews and (item.rating or item.review):
review_title = 'Review of {!r} on {!r}'.format(
item.book.title,
source,
) if item.review else ''
# we don't know the publication date of the review,
# but "now" is a bad guess
published_date_guess = item.date_read or item.date_added
models.Review.objects.create(
user=user,
book=item.book,
name=review_title,
content=item.review,
rating=item.rating,
published_date=published_date_guess,
privacy=privacy,
)

View file

@ -0,0 +1,42 @@
''' handle reading a csv from librarything '''
import csv
import re
import math
from bookwyrm import models
from bookwyrm.models import ImportItem
from bookwyrm.importer import Importer
class LibrarythingImporter(Importer):
service = 'LibraryThing'
delimiter = '\t'
encoding = 'ISO-8859-1'
# mandatory_fields : fields matching the book title and author
mandatory_fields = ['Title', 'Primary Author']
def parse_fields(self, initial):
data = {}
data['import_source'] = self.service
data['Book Id'] = initial['Book Id']
data['Title'] = initial['Title']
data['Author'] = initial['Primary Author']
data['ISBN13'] = initial['ISBN']
data['My Review'] = initial['Review']
if initial['Rating']:
data['My Rating'] = math.ceil(float(initial['Rating']))
else:
data['My Rating'] = ''
data['Date Added'] = re.sub('\[|\]', '', initial['Entry Date'])
data['Date Started'] = re.sub('\[|\]', '', initial['Date Started'])
data['Date Read'] = re.sub('\[|\]', '', initial['Date Read'])
data['Exclusive Shelf'] = None
if data['Date Read']:
data['Exclusive Shelf'] = "read"
elif data['Date Started']:
data['Exclusive Shelf'] = "reading"
else:
data['Exclusive Shelf'] = "to-read"
return data

View file

@ -97,8 +97,8 @@ class ImportItem(models.Model):
def get_book_from_title_author(self):
''' search by title and author '''
search_term = construct_search_term(
self.data['Title'],
self.data['Author']
self.title,
self.author
)
search_result = connector_manager.first_search_result(
search_term, min_confidence=0.999
@ -149,6 +149,14 @@ class ImportItem(models.Model):
dateutil.parser.parse(self.data['Date Added']))
return None
@property
def date_started(self):
''' when the book was started '''
if "Date Started" in self.data and self.data['Date Started']:
return timezone.make_aware(
dateutil.parser.parse(self.data['Date Started']))
return None
@property
def date_read(self):
''' the date a book was completed '''
@ -160,18 +168,24 @@ class ImportItem(models.Model):
@property
def reads(self):
''' formats a read through dataset for the book in this line '''
if (self.shelf == 'reading'
and self.date_added and not self.date_read):
return [ReadThrough(start_date=self.date_added)]
start_date = self.date_started
# Goodreads special case (no 'date started' field)
if ((self.shelf == 'reading' or (self.shelf == 'read' and self.date_read))
and self.date_added and not start_date):
start_date = self.date_added
if (start_date and start_date is not None and not self.date_read):
return [ReadThrough(start_date=start_date)]
if self.date_read:
return [ReadThrough(
start_date=self.date_added,
start_date=start_date,
finish_date=self.date_read,
)]
return []
def __repr__(self):
return "<GoodreadsItem {!r}>".format(self.data['Title'])
return "<{!r}Item {!r}>".format(self.data['import_source'], self.data['Title'])
def __str__(self):
return "{} by {}".format(self.data['Title'], self.data['Author'])

View file

@ -1,9 +1,10 @@
''' bookwyrm settings and configuration '''
import os
from environs import Env
import requests
from django.utils.translation import gettext_lazy as _
env = Env()
DOMAIN = env('DOMAIN')
@ -27,6 +28,7 @@ EMAIL_USE_TLS = env('EMAIL_USE_TLS', True)
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale'),]
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
@ -58,6 +60,7 @@ INSTALLED_APPS = [
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
@ -135,6 +138,11 @@ AUTH_PASSWORD_VALIDATORS = [
# https://docs.djangoproject.com/en/2.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
LANGUAGES = [
('en-us', _('English')),
('fr-fr', _('French')),
]
TIME_ZONE = 'UTC'

View file

@ -12,9 +12,9 @@ window.onload = function() {
Array.from(document.getElementsByClassName('select-all'))
.forEach(t => t.onclick = selectAll);
// toggle between tabs
Array.from(document.getElementsByClassName('tab-change'))
.forEach(t => t.onclick = tabChange);
// tab groups
Array.from(document.getElementsByClassName('tab-group'))
.forEach(t => new TabGroup(t));
// handle aria settings on menus
Array.from(document.getElementsByClassName('pulldown-menu'))
@ -141,23 +141,6 @@ function selectAll(e) {
.forEach(t => t.checked=true);
}
function tabChange(e) {
var el = e.currentTarget;
var parentElement = el.closest('[role="tablist"]');
parentElement.querySelectorAll('[aria-selected="true"]')
.forEach(t => t.setAttribute("aria-selected", false));
el.setAttribute("aria-selected", true);
parentElement.querySelectorAll('li')
.forEach(t => removeClass(t, 'is-active'));
addClass(el, 'is-active');
var tabId = el.getAttribute('data-tab');
Array.from(document.getElementsByClassName(el.getAttribute('data-category')))
.forEach(t => addRemoveClass(t, 'hidden', t.id != tabId));
}
function toggleMenu(e) {
var el = e.currentTarget;
var expanded = el.getAttribute('aria-expanded') == 'false';
@ -203,3 +186,258 @@ function removeClass(el, className) {
}
el.className = classes.join(' ');
}
/*
* The content below is licensed according to the W3C Software License at
* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
* Heavily modified to web component by Zach Leatherman
* Modified back to vanilla JavaScript with support for Bulma markup and nested tabs by Ned Zimmerman
*/
class TabGroup {
constructor(container) {
this.container = container;
this.tablist = this.container.querySelector('[role="tablist"]');
this.buttons = this.tablist.querySelectorAll('[role="tab"]');
this.panels = this.container.querySelectorAll(':scope > [role="tabpanel"]');
this.delay = this.determineDelay();
if(!this.tablist || !this.buttons.length || !this.panels.length) {
return;
}
this.keys = this.keys();
this.direction = this.direction();
this.initButtons();
this.initPanels();
}
keys() {
return {
end: 35,
home: 36,
left: 37,
up: 38,
right: 39,
down: 40
};
}
// Add or substract depending on key pressed
direction() {
return {
37: -1,
38: -1,
39: 1,
40: 1
};
}
initButtons() {
let count = 0;
for(let button of this.buttons) {
let isSelected = button.getAttribute("aria-selected") === "true";
button.setAttribute("tabindex", isSelected ? "0" : "-1");
button.addEventListener('click', this.clickEventListener.bind(this));
button.addEventListener('keydown', this.keydownEventListener.bind(this));
button.addEventListener('keyup', this.keyupEventListener.bind(this));
button.index = count++;
}
}
initPanels() {
let selectedPanelId = this.tablist.querySelector('[role="tab"][aria-selected="true"]').getAttribute("aria-controls");
for(let panel of this.panels) {
if(panel.getAttribute("id") !== selectedPanelId) {
panel.setAttribute("hidden", "");
}
panel.setAttribute("tabindex", "0");
}
}
clickEventListener(event) {
let button = event.target.closest('a');
event.preventDefault();
this.activateTab(button, false);
}
// Handle keydown on tabs
keydownEventListener(event) {
var key = event.keyCode;
switch (key) {
case this.keys.end:
event.preventDefault();
// Activate last tab
this.activateTab(this.buttons[this.buttons.length - 1]);
break;
case this.keys.home:
event.preventDefault();
// Activate first tab
this.activateTab(this.buttons[0]);
break;
// Up and down are in keydown
// because we need to prevent page scroll >:)
case this.keys.up:
case this.keys.down:
this.determineOrientation(event);
break;
};
}
// Handle keyup on tabs
keyupEventListener(event) {
var key = event.keyCode;
switch (key) {
case this.keys.left:
case this.keys.right:
this.determineOrientation(event);
break;
};
}
// When a tablists aria-orientation is set to vertical,
// only up and down arrow should function.
// In all other cases only left and right arrow function.
determineOrientation(event) {
var key = event.keyCode;
var vertical = this.tablist.getAttribute('aria-orientation') == 'vertical';
var proceed = false;
if (vertical) {
if (key === this.keys.up || key === this.keys.down) {
event.preventDefault();
proceed = true;
};
}
else {
if (key === this.keys.left || key === this.keys.right) {
proceed = true;
};
};
if (proceed) {
this.switchTabOnArrowPress(event);
};
}
// Either focus the next, previous, first, or last tab
// depending on key pressed
switchTabOnArrowPress(event) {
var pressed = event.keyCode;
for (let button of this.buttons) {
button.addEventListener('focus', this.focusEventHandler.bind(this));
};
if (this.direction[pressed]) {
var target = event.target;
if (target.index !== undefined) {
if (this.buttons[target.index + this.direction[pressed]]) {
this.buttons[target.index + this.direction[pressed]].focus();
}
else if (pressed === this.keys.left || pressed === this.keys.up) {
this.focusLastTab();
}
else if (pressed === this.keys.right || pressed == this.keys.down) {
this.focusFirstTab();
}
}
}
}
// Activates any given tab panel
activateTab (tab, setFocus) {
if(tab.getAttribute("role") !== "tab") {
tab = tab.closest('[role="tab"]');
}
setFocus = setFocus || true;
// Deactivate all other tabs
this.deactivateTabs();
// Remove tabindex attribute
tab.removeAttribute('tabindex');
// Set the tab as selected
tab.setAttribute('aria-selected', 'true');
// Give the tab parent an is-active class
tab.parentNode.classList.add('is-active');
// Get the value of aria-controls (which is an ID)
var controls = tab.getAttribute('aria-controls');
// Remove hidden attribute from tab panel to make it visible
document.getElementById(controls).removeAttribute('hidden');
// Set focus when required
if (setFocus) {
tab.focus();
}
}
// Deactivate all tabs and tab panels
deactivateTabs() {
for (let button of this.buttons) {
button.parentNode.classList.remove('is-active');
button.setAttribute('tabindex', '-1');
button.setAttribute('aria-selected', 'false');
button.removeEventListener('focus', this.focusEventHandler.bind(this));
}
for (let panel of this.panels) {
panel.setAttribute('hidden', 'hidden');
}
}
focusFirstTab() {
this.buttons[0].focus();
}
focusLastTab() {
this.buttons[this.buttons.length - 1].focus();
}
// Determine whether there should be a delay
// when user navigates with the arrow keys
determineDelay() {
var hasDelay = this.tablist.hasAttribute('data-delay');
var delay = 0;
if (hasDelay) {
var delayValue = this.tablist.getAttribute('data-delay');
if (delayValue) {
delay = delayValue;
}
else {
// If no value is specified, default to 300ms
delay = 300;
};
};
return delay;
}
focusEventHandler(event) {
var target = event.target;
setTimeout(this.checkTabFocus.bind(this), this.delay, target);
};
// Only activate tab on focus if it still has focus after the delay
checkTabFocus(target) {
let focused = document.activeElement;
if (target === focused) {
this.activateTab(target, false);
}
}
}

View file

@ -1,5 +1,9 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block title %}{{ author.name }}{% endblock %}
{% block content %}
<div class="block">
<div class="columns is-mobile">
@ -9,8 +13,8 @@
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
<div class="column is-narrow">
<a href="{{ author.local_path }}/edit">
<span class="icon icon-pencil" title="Edit Author">
<span class="is-sr-only">Edit Author</span>
<span class="icon icon-pencil" title="{% trans 'Edit Author' %}">
<span class="is-sr-only">{% trans "Edit Author" %}</span>
</span>
</a>
</div>
@ -25,12 +29,12 @@
</p>
{% endif %}
{% if author.wikipedia_link %}
<p><a href="{{ author.wikipedia_link }}" rel=”noopener” target="_blank">Wikipedia</a></p>
<p><a href="{{ author.wikipedia_link }}" rel=”noopener” target="_blank">{% trans "Wikipedia" %}</a></p>
{% endif %}
</div>
<div class="block">
<h3 class="title is-4">Books by {{ author.name }}</h3>
<h3 class="title is-4">{% blocktrans with name=author.name %}Books by {{ name }}{% endblocktrans %}</h3>
{% include 'snippets/book_tiles.html' with books=books %}
</div>
{% endblock %}

View file

@ -1,8 +1,11 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% load humanize %}
{% block content %}
{% block title %}{{ book.title }}{% endblock %}
{% block content %}
<div class="block">
<div class="columns is-mobile">
<div class="column">
@ -23,8 +26,8 @@
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
<div class="column is-narrow">
<a href="{{ book.id }}/edit">
<span class="icon icon-pencil" title="Edit Book">
<span class="is-sr-only">Edit Book</span>
<span class="icon icon-pencil" title="{% trans "Edit Book" %}">
<span class="is-sr-only">{% trans "Edit Book" %}</span>
</span>
</a>
</div>
@ -39,13 +42,13 @@
{% if request.user.is_authenticated and not book.cover %}
<div class="box p-2">
<h3 class="title is-6 mb-1">Add cover</h3>
<h3 class="title is-6 mb-1">{% trans "Add cover" %}</h3>
<form name="add-cover" method="POST" action="/upload-cover/{{ book.id }}" enctype="multipart/form-data">
{% csrf_token %}
<label class="label">
<input type="file" name="cover" accept="image/*" enctype="multipart/form-data" id="id_cover" required>
</label>
<button class="button is-small is-primary" type="submit">Add</button>
<button class="button is-small is-primary" type="submit">{% trans "Add" %}</button>
</form>
</div>
{% endif %}
@ -54,21 +57,21 @@
<dl>
{% if book.isbn_13 %}
<div class="is-flex is-justify-content-space-between">
<dt>ISBN:</dt>
<dt>{% trans "ISBN:" %}</dt>
<dd>{{ book.isbn_13 }}</dd>
</div>
{% endif %}
{% if book.oclc_number %}
<div class="is-flex is-justify-content-space-between">
<dt>OCLC Number:</dt>
<dt>{% trans "OCLC Number:" %}</dt>
<dd>{{ book.oclc_number }}</dd>
</div>
{% endif %}
{% if book.asin %}
<div class="is-flex is-justify-content-space-between">
<dt>ASIN:</dt>
<dt>{% trans "ASIN:" %}</dt>
<dd>{{ book.asin }}</dd>
</div>
{% endif %}
@ -80,7 +83,7 @@
</p>
{% if book.openlibrary_key %}
<p><a href="https://openlibrary.org/books/{{ book.openlibrary_key }}" target="_blank" rel="noopener">View on OpenLibrary</a></p>
<p><a href="https://openlibrary.org/books/{{ book.openlibrary_key }}" target="_blank" rel="noopener">{% trans "View on OpenLibrary" %}</a></p>
{% endif %}
</section>
</div>
@ -92,18 +95,20 @@
{% include 'snippets/trimmed_text.html' with full=book|book_description %}
{% if request.user.is_authenticated and perms.bookwyrm.edit_book and not book|book_description %}
{% include 'snippets/toggle/open_button.html' with text="Add description" controls_text="add-description" controls_uid=book.id focus="id_description" hide_active=True id="hide-description" %}
{% trans 'Add Description' as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text controls_text="add-description" controls_uid=book.id focus="id_description" hide_active=True id="hide-description" %}
<div class="box hidden" id="add-description-{{ book.id }}">
<form name="add-description" method="POST" action="/add-description/{{ book.id }}">
{% csrf_token %}
<p class="fields is-grouped">
<label class="label"for="id_description">Description:</label>
<label class="label"for="id_description">{% trans "Description:" %}</label>
<textarea name="description" cols="None" rows="None" class="textarea" id="id_description"></textarea>
</p>
<div class="field">
<button class="button is-primary" type="submit">Save</button>
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="add-description" controls_uid=book.id hide_inactive=True %}
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="add-description" controls_uid=book.id hide_inactive=True %}
</div>
</form>
</div>
@ -134,23 +139,25 @@
{% if request.user.is_authenticated %}
<section class="block">
<header class="columns">
<h2 class="column title is-5 mb-1">Your reading activity</h2>
<h2 class="column title is-5 mb-1">{% trans "Your reading activity" %}</h2>
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with text="Add read dates" icon="plus" class="is-small" controls_text="add-readthrough" %}
{% trans "Add read dates" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text icon="plus" class="is-small" controls_text="add-readthrough" %}
</div>
</header>
{% if not readthroughs.exists %}
<p>You don't have any reading activity for this book.</p>
<p>{% trans "You don't have any reading activity for this book." %}</p>
{% endif %}
<section class="hidden box" id="add-readthrough">
<form name="add-readthrough" action="/create-readthrough" method="post">
{% include 'snippets/readthrough_form.html' with readthrough=None %}
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit">Create</button>
<button class="button is-primary" type="submit">{% trans "Create" %}</button>
</div>
<div class="control">
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="add-readthrough" %}
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="add-readthrough" %}
</div>
</div>
</form>
@ -168,11 +175,11 @@
<section class="block">
<form name="tag" action="/tag/" method="post">
<label for="tags" class="is-3">Tags</label>
<label for="tags" class="is-3">{% trans "Tags" %}</label>
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}">
<input id="tags" class="input" type="text" name="name">
<button class="button" type="submit">Add tag</button>
<button class="button" type="submit">{% trans "Add tag" %}</button>
</form>
</section>
{% endif %}
@ -189,7 +196,7 @@
<div class="column is-narrow">
{% if book.subjects %}
<section class="content block">
<h2 class="title is-5">Subjects</h2>
<h2 class="title is-5">{% trans "Subjects" %}</h2>
<ul>
{% for subject in book.subjects %}
<li>{{ subject }}</li>
@ -200,7 +207,7 @@
{% if book.subject_places %}
<section class="content block">
<h2 class="title is-5">Places</h2>
<h2 class="title is-5">{% trans "Places" %}</h2>
<ul>
{% for place in book.subject_placess %}
<li>{{ place }}</li>
@ -211,7 +218,7 @@
{% if lists.exists %}
<section class="content block">
<h2 class="title is-5">Lists</h2>
<h2 class="title is-5">{% trans "Lists" %}</h2>
<ul>
{% for list in lists %}
<li><a href="{{ list.local_path }}">{{ list.name }}</a></li>
@ -240,7 +247,7 @@
{% include 'snippets/username.html' with user=rating.user %}
</div>
<div class="field is-grouped mb-0">
<div>rated it</div>
<div>{% trans "rated it" %}</div>
{% include 'snippets/stars.html' with rating=rating.rating %}
</div>
<div>
@ -257,4 +264,3 @@
</div>
{% endblock %}

View file

@ -1,10 +1,12 @@
{% load i18n %}
<section class="card hidden {{ class }}" id="{{ controls_text }}{% if controls_uid %}-{{ controls_uid }}{% endif %}">
<header class="card-header has-background-white-ter">
<h2 class="card-header-title" tabindex="0" id="{{ controls_text }}{% if controls_uid %}-{{ controls_uid }}{% endif %}-header">
{% block header %}{% endblock %}
</h2>
<span class="card-header-icon">
{% include 'snippets/toggle/toggle_button.html' with label="Close" class="delete" nonbutton=True controls_text=controls_text %}
{% trans "Close" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with label=button_text class="delete" nonbutton=True controls_text=controls_text %}
</span>
</header>
<section class="card-content content">

View file

@ -1,22 +1,23 @@
{% extends 'discover/landing_layout.html' %}
{% block panel %}
{% load i18n %}
{% block panel %}
<div class="block columns mt-4">
<nav class="menu column is-one-quarter">
<h2 class="menu-label">About {{ site.name }}</h2>
<h2 class="menu-label">{% blocktrans with site_name=site.name %}About {{ site_name }}{% endblocktrans %}</h2>
<ul class="menu-list">
<li>
<a href="#coc">Code of Conduct</a>
<a href="#coc">{% trans "Code of Conduct" %}</a>
</li>
<li>
<a href="#privacy">Privacy Policy</a>
<a href="#privacy">{% trans "Privacy Policy" %}</a>
</li>
</ul>
</nav>
<div class="column content">
<div class="block" id="coc">
<h2 class="title">Code of Conduct</h2>
<h2 class="title">{% trans "Code of Conduct" %}</h2>
<div class="content">
{{ site.code_of_conduct | safe }}
</div>
@ -25,7 +26,7 @@
<hr aria-hidden="true">
<div class="block" id="privacy">
<h2 class="title">Privacy Policy</h2>
<h2 class="title">{% trans "Privacy Policy" %}</h2>
<div class="content">
{{ site.privacy_policy | safe }}
</div>

View file

@ -1,8 +1,9 @@
{% extends 'discover/landing_layout.html' %}
{% load i18n %}
{% block panel %}
<div class="block is-hidden-tablet">
<h2 class="title has-text-centered">Recent Books</h2>
<h2 class="title has-text-centered">{% trans "Recent Books" %}</h2>
</div>
<section class="tile is-ancestor">

View file

@ -1,21 +0,0 @@
<section class="level is-mobile">
<div class="level-item has-text-centered">
<div>
<p class="title has-text-weight-normal"><span class="icon icon-graphic-paperplane"></span></p>
<p class="heading">Decentralized</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="title has-text-weight-normal"><span class="icon icon-graphic-heart"></span></p>
<p class="heading">Friendly</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="title has-text-weight-normal"><span class="icon icon-graphic-banknote"></span></p>
<p class="heading">Anti-Corporate</p>
</div>
</div>
</section>

View file

@ -1,14 +1,35 @@
{% extends 'layout.html' %}
{% load humanize %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block content %}
{% block title %}{% trans "Welcome" %}{% endblock %}
{% block content %}
<header class="block has-text-centered">
<h1 class="title">{{ site.name }}</h1>
<h2 class="subtitle">{{ site.instance_tagline }}</h2>
</header>
{% include 'discover/icons.html' %}
<section class="level is-mobile">
<div class="level-item has-text-centered">
<div>
<p class="title has-text-weight-normal"><span class="icon icon-graphic-paperplane"></span></p>
<p class="heading">{% trans "Decentralized" %}</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="title has-text-weight-normal"><span class="icon icon-graphic-heart"></span></p>
<p class="heading">{% trans "Friendly" %}</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="title has-text-weight-normal"><span class="icon icon-graphic-banknote"></span></p>
<p class="heading">{% trans "Anti-Corporate" %}</p>
</div>
</div>
</section>
<section class="tile is-ancestor">
<div class="tile is-7 is-parent">
@ -20,37 +41,22 @@
{% if not request.user.is_authenticated %}
<div class="tile is-child box has-background-primary-light content">
{% if site.allow_registration %}
<h2 class="title">Join {{ site.name }}</h2>
<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>
{% else %}
<h2 class="title">This instance is closed</h2>
<h2 class="title">{% trans "This instance is closed" %}</h2>
<p>{{ site.registration_closed_text | safe}}</p>
{% endif %}
</div>
{% else %}
<div class="tile is-child box has-background-white-bis">
<h2 class="title is-4">Your Account</h2>
<div class="media block">
<div class="media-left">
<a href="{{ user.local_path }}">
{% include 'snippets/avatar.html' with user=user large=True %}
</a>
</div>
<div class="media-content">
<p>{% if user.name %}{{ user.name }}{% else %}{{ user.localname }}{% endif %}</p>
<p><a href="{{ user.remote_id }}">{{ user.username }}</a></p>
<p>Joined {{ user.created_date | naturaltime }}</p>
<p>
<a href="{{ user.local_path }}/followers">{{ user.followers.count }} follower{{ user.followers.count | pluralize }}</a>,
<a href="{{ user.local_path }}/following">{{ user.following.count }} following</a>
</p>
</div>
</div>
<h2 class="title is-4">{% trans "Your Account" %}</h2>
{% include 'user/user_preview.html' with user=request.user %}
<div class="box content">
{% if user.summary %}
{{ user.summary | to_markdown | safe }}
{% if request.user.summary %}
{{ request.user.summary | to_markdown | safe }}
{% endif %}
</div>
</div>

View file

@ -1,14 +1,18 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load humanize %}
{% block title %}{% trans "Edit Author" %}: {{ author.name }}{% endblock %}
{% block content %}
<header class="block">
<h1 class="title level-left">
Edit "{{ author.name }}"
</h1>
<div>
<p>Added: {{ author.created_date | naturaltime }}</p>
<p>Updated: {{ author.updated_date | naturaltime }}</p>
<p>Last edited by: <a href="{{ author.last_edited_by.remote_id }}">{{ author.last_edited_by.display_name }}</a></p>
<p>{% trans "Added:" %} {{ author.created_date | naturaltime }}</p>
<p>{% trans "Updated:" %} {{ author.updated_date | naturaltime }}</p>
<p>{% trans "Last edited by:" %} <a href="{{ author.last_edited_by.remote_id }}">{{ author.last_edited_by.display_name }}</a></p>
</div>
</header>
@ -24,45 +28,45 @@
<div class="columns">
<div class="column">
<h2 class="title is-4">Metadata</h2>
<p><label class="label" for="id_name">Name:</label> {{ form.name }}</p>
<h2 class="title is-4">{% trans "Metadata" %}</h2>
<p><label class="label" for="id_name">{% trans "Name:" %}</label> {{ form.name }}</p>
{% for error in form.name.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p><label class="label" for="id_bio">Bio:</label> {{ form.bio }}</p>
<p><label class="label" for="id_bio">{% trans "Bio:" %}</label> {{ form.bio }}</p>
{% for error in form.bio.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p><label class="label" for="id_wikipedia_link">Wikipedia link:</label> {{ form.wikipedia_link }}</p>
<p><label class="label" for="id_wikipedia_link">{% trans "Wikipedia link:" %}</label> {{ form.wikipedia_link }}</p>
{% for error in form.wikipedia_link.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p><label class="label" for="id_born">Birth date:</label> {{ form.born }}</p>
<p><label class="label" for="id_born">{% trans "Birth date:" %}</label> {{ form.born }}</p>
{% for error in form.born.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p><label class="label" for="id_died">Death date:</label> {{ form.died }}</p>
<p><label class="label" for="id_died">{% trans "Death date:" %}</label> {{ form.died }}</p>
{% for error in form.died.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="column">
<h2 class="title is-4">Author Identifiers</h2>
<p><label class="label" for="id_openlibrary_key">Openlibrary key:</label> {{ form.openlibrary_key }}</p>
<h2 class="title is-4">{% trans "Author Identifiers" %}</h2>
<p><label class="label" for="id_openlibrary_key">{% trans "Openlibrary key:" %}</label> {{ form.openlibrary_key }}</p>
{% for error in form.openlibrary_key.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p><label class="label" for="id_librarything_key">Librarything key:</label> {{ form.librarything_key }}</p>
<p><label class="label" for="id_librarything_key">{% trans "Librarything key:" %}</label> {{ form.librarything_key }}</p>
{% for error in form.librarything_key.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p><label class="label" for="id_goodreads_key">Goodreads key:</label> {{ form.goodreads_key }}</p>
<p><label class="label" for="id_goodreads_key">{% trans "Goodreads key:" %}</label> {{ form.goodreads_key }}</p>
{% for error in form.goodreads_key.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
@ -71,10 +75,9 @@
</div>
<div class="block">
<button class="button is-primary" type="submit">Save</button>
<a class="button" href="/author/{{ author.id }}">Cancel</a>
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
<a class="button" href="/author/{{ author.id }}">{% trans "Cancel" %}</a>
</div>
</form>
{% endblock %}

View file

@ -1,14 +1,18 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load humanize %}
{% block title %}{% trans "Edit Book" %}{% endblock %}
{% block content %}
<header class="block">
<h1 class="title level-left">
Edit "{{ book.title }}"
</h1>
<div>
<p>Added: {{ book.created_date | naturaltime }}</p>
<p>Updated: {{ book.updated_date | naturaltime }}</p>
<p>Last edited by: <a href="{{ book.last_edited_by.remote_id }}">{{ book.last_edited_by.display_name }}</a></p>
<p>{% trans "Added:" %} {{ book.created_date | naturaltime }}</p>
<p>{% trans "Updated:" %} {{ book.updated_date | naturaltime }}</p>
<p>{% trans "Last edited by:" %} <a href="{{ book.last_edited_by.remote_id }}">{{ book.last_edited_by.display_name }}</a></p>
</div>
</header>
@ -23,32 +27,32 @@
<input type="hidden" name="last_edited_by" value="{{ request.user.id }}">
<div class="columns">
<div class="column">
<h2 class="title is-4">Metadata</h2>
<p class="fields is-grouped"><label class="label" for="id_title">Title:</label> {{ form.title }} </p>
<h2 class="title is-4">{% trans "Metadata" %}</h2>
<p class="fields is-grouped"><label class="label" for="id_title">{% trans "Title:" %}</label> {{ form.title }} </p>
{% for error in form.title.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_subtitle">Subtitle:</label> {{ form.subtitle }} </p>
<p class="fields is-grouped"><label class="label" for="id_subtitle">{% trans "Subtitle:" %}</label> {{ form.subtitle }} </p>
{% for error in form.subtitle.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_description">Description:</label> {{ form.description }} </p>
<p class="fields is-grouped"><label class="label" for="id_description">{% trans "Description:" %}</label> {{ form.description }} </p>
{% for error in form.description.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_series">Series:</label> {{ form.series }} </p>
<p class="fields is-grouped"><label class="label" for="id_series">{% trans "Series:" %}</label> {{ form.series }} </p>
{% for error in form.series.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_series_number">Series number:</label> {{ form.series_number }} </p>
<p class="fields is-grouped"><label class="label" for="id_series_number">{% trans "Series number:" %}</label> {{ form.series_number }} </p>
{% for error in form.series_number.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_first_published_date">First published date:</label> {{ form.first_published_date }} </p>
<p class="fields is-grouped"><label class="label" for="id_first_published_date">{% trans "First published date:" %}</label> {{ form.first_published_date }} </p>
{% for error in form.first_published_date.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_published_date">Published date:</label> {{ form.published_date }} </p>
<p class="fields is-grouped"><label class="label" for="id_published_date">{% trans "Published date:" %}</label> {{ form.published_date }} </p>
{% for error in form.published_date.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
@ -61,7 +65,7 @@
</div>
<div class="column is-narrow">
<div class="block">
<h2 class="title is-4">Cover</h2>
<h2 class="title is-4">{% trans "Cover" %}</h2>
<p>{{ form.cover }}</p>
{% for error in form.cover.errors %}
<p class="help is-danger">{{ error | escape }}</p>
@ -71,8 +75,8 @@
</div>
<div class="block">
<h2 class="title is-4">Physical Properties</h2>
<p class="fields is-grouped"><label class="label" for="id_physical_format">Format:</label> {{ form.physical_format }} </p>
<h2 class="title is-4">{% trans "Physical Properties" %}</h2>
<p class="fields is-grouped"><label class="label" for="id_physical_format">{% trans "Format:" %}</label> {{ form.physical_format }} </p>
{% for error in form.physical_format.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
@ -80,31 +84,31 @@
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_pages">Pages:</label> {{ form.pages }} </p>
<p class="fields is-grouped"><label class="label" for="id_pages">{% trans "Pages:" %}</label> {{ form.pages }} </p>
{% for error in form.pages.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="block">
<h2 class="title is-4">Book Identifiers</h2>
<p class="fields is-grouped"><label class="label" for="id_isbn_13">ISBN 13:</label> {{ form.isbn_13 }} </p>
<h2 class="title is-4">{% trans "Book Identifiers" %}</h2>
<p class="fields is-grouped"><label class="label" for="id_isbn_13">{% trans "ISBN 13:" %}</label> {{ form.isbn_13 }} </p>
{% for error in form.isbn_13.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_isbn_10">ISBN 10:</label> {{ form.isbn_10 }} </p>
<p class="fields is-grouped"><label class="label" for="id_isbn_10">{% trans "ISBN 10:" %}</label> {{ form.isbn_10 }} </p>
{% for error in form.isbn_10.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_openlibrary_key">Openlibrary key:</label> {{ form.openlibrary_key }} </p>
<p class="fields is-grouped"><label class="label" for="id_openlibrary_key">{% trans "Openlibrary key:" %}</label> {{ form.openlibrary_key }} </p>
{% for error in form.openlibrary_key.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_librarything_key">OCLC Number:</label> {{ form.oclc_number }} </p>
<p class="fields is-grouped"><label class="label" for="id_librarything_key">{% trans "OCLC Number:" %}</label> {{ form.oclc_number }} </p>
{% for error in form.oclc_number.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<p class="fields is-grouped"><label class="label" for="id_asin">ASIN:</label> {{ form.asin }} </p>
<p class="fields is-grouped"><label class="label" for="id_asin">{% trans "ASIN:" %}</label> {{ form.asin }} </p>
{% for error in form.ASIN.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
@ -113,8 +117,8 @@
</div>
<div class="block">
<button class="button is-primary" type="submit">Save</button>
<a class="button" href="/book/{{ book.id }}">Cancel</a>
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
<a class="button" href="/book/{{ book.id }}">{% trans "Cancel" %}</a>
</div>
</form>

View file

@ -1,8 +1,12 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block title %}{% blocktrans with book_title=work.title %}Editions of {{ book_title }}{% endblocktrans %}{% endblock %}
{% block content %}
<div class="block">
<h1 class="title">Editions of <a href="/book/{{ work.id }}">"{{ work.title }}"</a></h1>
<h1 class="title">{% blocktrans with path=work.local_path work_title=work.title %}Editions of <a href="{{ work_path }}">"{{ work_title }}"</a>{% endblocktrans %}</h1>
{% include 'snippets/book_tiles.html' with books=editions %}
</div>

View file

@ -1,10 +1,12 @@
{% extends 'layout.html' %}
{% load i18n %}
{% block title %}{% trans "Oops!" %}{% endblock %}
{% block content %}
<div class="block">
<h1 class="title">Server Error</h1>
<p>Something went wrong! Sorry about that.</p>
<h1 class="title">{% trans "Server Error" %}</h1>
<p>{% trans "Something went wrong! Sorry about that." %}</p>
</div>
{% endblock %}

View file

@ -1,9 +1,16 @@
{% extends 'feed/feed_layout.html' %}
{% load i18n %}
{% block panel %}
<header class="block">
<h1 class="title">Direct Messages{% if partner %} with {% include 'snippets/username.html' with user=partner %}{% endif %}</h1>
{% if partner %}<p class="subtitle"><a href="/direct-messages"><span class="icon icon-arrow-left" aria-hidden="true"></span> All messages</a></p>{% endif %}
<h1 class="title">
{% if partner %}
{% blocktrans with username=partner.display_name path=partner.local_path %}Direct Messages with <a href="{{ path }}">{{ username }}</a>{% endblocktrans %}
{% else %}
{% trans "Direct Messages" %}
{% endif %}
</h1>
{% if partner %}<p class="subtitle"><a href="/direct-messages"><span class="icon icon-arrow-left" aria-hidden="true"></span> {% trans "All messages" %}</a></p>{% endif %}
</header>
<div class="box">
@ -12,7 +19,7 @@
<section class="block">
{% if not activities %}
<p>You have no messages right now.</p>
<p>{% trans "You have no messages right now." %}</p>
{% endif %}
{% for activity in activities %}
<div class="block">

View file

@ -1,18 +1,19 @@
{% extends 'feed/feed_layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block panel %}
<h1 class="title">{{ tab | title }} Timeline</h1>
<h1 class="title">{% blocktrans with tab_title=tab|title %}{{ tab_title }} Timeline{% endblocktrans %}</h1>
<div class="tabs">
<ul>
<li class="{% if tab == 'home' %}is-active{% endif %}">
<a href="/#feed">Home</a>
<a href="/#feed">{% trans "Home" %}</a>
</li>
<li class="{% if tab == 'local' %}is-active{% endif %}">
<a href="/local#feed">Local</a>
<a href="/local#feed">{% trans "Local" %}</a>
</li>
<li class="{% if tab == 'federated' %}is-active{% endif %}">
<a href="/federated#feed">Federated</a>
<a href="/federated#feed">{% trans "Federated" %}</a>
</li>
</ul>
</div>
@ -20,7 +21,7 @@
{# announcements and system messages #}
{% if not goal and tab == 'home' %}
{% now 'Y' as year %}
<section class="block hidden" aria-title="Announcements" data-hide="hide-{{ year }}-reading-goal">
<section class="block hidden" aria-title="{% trans 'Announcements' %}" data-hide="hide-{{ year }}-reading-goal">
{% include 'snippets/goal_card.html' with year=year %}
<hr>
</section>
@ -28,7 +29,7 @@
{# activity feed #}
{% if not activities %}
<p>There aren't any activities right now! Try following a user to get started</p>
<p>{% trans "There aren't any activities right now! Try following a user to get started" %}</p>
{% endif %}
{% for activity in activities %}
<div class="block">

View file

@ -1,14 +1,18 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block content %}
{% block title %}{% trans "Updates" %}{% endblock %}
{% block content %}
<div class="columns">
{% if user.is_authenticated %}
<div class="column is-one-third">
<h2 class="title is-5">Your books</h2>
<h2 class="title is-5">{% trans "Your books" %}</h2>
{% if not suggested_books %}
<p>There are no books here right now! Try searching for a book to get started</p>
<p>{% trans "There are no books here right now! Try searching for a book to get started" %}</p>
{% else %}
<div class="tab-group">
<div class="tabs is-small">
<ul role="tablist">
{% for shelf in suggested_books %}
@ -21,8 +25,8 @@
<div class="tabs is-small is-toggle">
<ul>
{% for book in shelf.books %}
<li class="tab-change{% if shelf_counter == 1 and forloop.first %} is-active{% endif %}" data-tab="book-{{ book.id }}" data-tab="book-{{ book.id }}" role="tab" tabindex="0" aria-selected="{% if shelf_counter == 1 and forloop.first %}true{% else %}false{% endif %}" aria-controls="book-{{ book.id }}" data-category="suggested-tabs">
<a>
<li{% if shelf_counter == 1 and forloop.first %} class="is-active"{% endif %}>
<a href="#book-{{ book.id }}" id="tab-book-{{ book.id }}" role="tab" aria-label="{{ book.title }}" aria-selected="{% if shelf_counter == 1 and forloop.first %}true{% else %}false{% endif %}" aria-controls="book-{{ book.id }}">
{% include 'snippets/book_cover.html' with book=book size="medium" %}
</a>
</li>
@ -38,13 +42,14 @@
{% for shelf in suggested_books %}
{% with shelf_counter=forloop.counter %}
{% for book in shelf.books %}
<div class="suggested-tabs card{% if shelf_counter != 1 or not forloop.first %} hidden{% endif %}" role="tabpanel" id="book-{{ book.id }}">
<div class="suggested-tabs card" role="tabpanel" id="book-{{ book.id }}"{% if shelf_counter != 1 or not forloop.first %} hidden{% endif %} aria-labelledby="tab-book-{{ book.id }}">
<div class="card-header">
<p class="card-header-title">
<span>{% include 'snippets/book_titleby.html' with book=book %}</span>
</p>
<div class="card-header-icon is-hidden-tablet">
{% include 'snippets/toggle/toggle_button.html' with label="close" controls_text="book" controls_uid=book.id class="delete" nonbutton=True pressed=True %}
{% trans "Close" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with label=button_text controls_text="book" controls_uid=book.id class="delete" nonbutton=True pressed=True %}
</div>
</div>
<div class="card-content">
@ -59,12 +64,13 @@
{% endfor %}
{% endwith %}
{% endfor %}
</div>
{% endif %}
{% if goal %}
<section class="section">
<div class="block">
<h3 class="title is-4">{{ goal.year }} Reading Goal</h3>
<h3 class="title is-4">{% blocktrans with yar=goal.year %}{{ year }} Reading Goal{% endblocktrans %}</h3>
{% include 'snippets/goal_progress.html' with goal=goal %}
</div>
</section>

View file

@ -1,9 +1,11 @@
{% extends 'feed/feed_layout.html' %}
{% load i18n %}
{% block panel %}
<header class="block">
<a href="/#feed" class="button" data-back>
<span class="icon icon-arrow-left" aira-hidden="true"></span>
<span>Back</span>
<span>{% trans "Back" %}</span>
</a>
</header>

View file

@ -1,13 +1,15 @@
{% extends 'user/user_layout.html' %}
{% load i18n %}
{% block header %}
<div class="columns is-mobile">
<div class="column">
<h1 class="title">{{ year }} Reading Progress</h1>
<h1 class="title">{% blocktrans %}{{ year }} Reading Progress{% endblocktrans %}</h1>
</div>
{% if is_self and goal %}
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with text="Edit goal" icon="pencil" controls_text="show-edit-goal" focus="edit-form-header" %}
{% trans "Edit Goal" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text icon="pencil" controls_text="show-edit-goal" focus="edit-form-header" %}
</div>
{% endif %}
</div>
@ -21,11 +23,11 @@
<section class="card {% if goal %}hidden{% endif %}" id="show-edit-goal">
<header class="card-header">
<h2 class="card-header-title has-background-primary has-text-white" tabindex="0" id="edit-form-header">
<span class="icon icon-book is-size-3 mr-2" aria-hidden="true"></span> {{ year }} reading goal
<span class="icon icon-book is-size-3 mr-2" aria-hidden="true"></span> {% blocktrans %}{{ year }} Reading Goal{% endblocktrans %}
</h2>
</header>
<section class="card-content content">
<p>Set a goal for how many books you'll finish reading in {{ year }}, and track your progress throughout the year.</p>
<p>{% blocktrans %}Set a goal for how many books you'll finish reading in {{ year }}, and track your progress throughout the year.{% endblocktrans %}</p>
{% include 'snippets/goal_form.html' with goal=goal year=year %}
</section>
@ -34,7 +36,7 @@
{% endif %}
{% if not goal and user != request.user %}
<p>{{ user.display_name }} hasn't set a reading goal for {{ year }}.</p>
<p>{% blocktrans with name=user.display_name %}{{ name }} hasn't set a reading goal for {{ year }}.{% endblocktrans %}</p>
{% endif %}
{% if goal %}
@ -44,7 +46,13 @@
{% if goal.books %}
<section class="content">
<h2>{% if goal.user == request.user %}Your{% else %}{{ goal.user.display_name }}'s{% endif %} {{ year }} Books</h2>
<h2>
{% if goal.user == request.user %}
{% blocktrans %}Your {{ year }} Books{% endblocktrans %}
{% else %}
{% blocktrans with username=goal.user.display_name %}{{ username }}'s {{ year }} Books{% endblocktrans %}
{% endif %}
</h2>
<div class="columns is-multiline">
{% for book in goal.books %}
<div class="column is-narrow">

View file

@ -1,32 +1,51 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load humanize %}
{% block title %}{% trans "Import Books" %}{% endblock %}
{% block content %}
<div class="block">
<h1 class="title">Import Books from GoodReads</h1>
<h1 class="title">{% trans "Import Books" %}</h1>
<form name="import" action="/import" method="post" enctype="multipart/form-data">
{% csrf_token %}
<label class="label" for="source">
<p>{% trans "Data source" %}</p>
<div class="select {{ class }}">
<select name="source" id="source">
<option value="GoodReads" {% if current == 'GoodReads' %}selected{% endif %}>
GoodReads
</option>
<option value="LibraryThing" {% if current == 'LibraryThing' %}selected{% endif %}>
LibraryThing
</option>
</select>
</div>
</label>
<div class="field">
{{ import_form.as_p }}
</div>
<div class="field">
<label class="label">
<input type="checkbox" name="include_reviews" checked> Include reviews
<input type="checkbox" name="include_reviews" checked> {% trans "Include reviews" %}
</label>
</div>
<div class="field">
<label class="label">
<p>Privacy setting for imported reviews:</p>
<p>{% trans "Privacy setting for imported reviews:" %}</p>
{% include 'snippets/privacy_select.html' with no_label=True %}
</label>
</div>
<button class="button is-primary" type="submit">Import</button>
<button class="button is-primary" type="submit">{% trans "Import" %}</button>
</form>
</div>
<div class="content block">
<h2 class="title">Recent Imports</h2>
<h2 class="title">{% trans "Recent Imports" %}</h2>
{% if not jobs %}
<p>No recent imports</p>
<p>{% trans "No recent imports" %}</p>
{% endif %}
<ul>
{% for job in jobs %}

View file

@ -1,34 +1,38 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% load humanize %}
{% block title %}{% trans "Import Status" %}{% endblock %}
{% block content %}
<div class="block">
<h1 class="title">Import Status</h1>
<h1 class="title">{% trans "Import Status" %}</h1>
<p>
Import started: {{ job.created_date | naturaltime }}
{% trans "Import started:" %} {{ job.created_date | naturaltime }}
</p>
{% if job.complete %}
<p>
Import completed: {{ task.date_done | naturaltime }}
{% trans "Import completed:" %} {{ task.date_done | naturaltime }}
</p>
{% elif task.failed %}
<div class="notification is-danger">TASK FAILED</div>
<div class="notification is-danger">{% trans "TASK FAILED" %}</div>
{% endif %}
</div>
<div class="block">
{% if not job.complete %}
Import still in progress.
{% trans "Import still in progress." %}
<p>
(Hit reload to update!)
{% trans "(Hit reload to update!)" %}
</p>
{% endif %}
</div>
{% if failed_items %}
<div class="block">
<h2 class="title is-4">Failed to load</h2>
<h2 class="title is-4">{% trans "Failed to load" %}</h2>
{% if not job.retry %}
<form name="retry" action="/import/{{ job.id }}" method="post">
{% csrf_token %}
@ -52,10 +56,10 @@
<div class="block pt-1 select-all">
<label class="label">
<input type="checkbox" class="checkbox">
Select all
{% trans "Select all" %}
</label>
</div>
<button class="button" type="submit">Retry items</button>
<button class="button" type="submit">{% trans "Retry items" %}</button>
{% else %}
<ul>
{% for item in failed_items %}
@ -77,17 +81,17 @@
{% endif %}
<div class="block">
<h2 class="title is-4">Successfully imported</h2>
<h2 class="title is-4">{% trans "Successfully imported" %}</h2>
<table class="table">
<tr>
<th>
Book
{% trans "Book" %}
</th>
<th>
Title
{% trans "Title" %}
</th>
<th>
Author
{% trans "Author" %}
</th>
<th>
</th>
@ -110,7 +114,7 @@
<td>
{% if item.book %}
<span class="icon icon-check">
<span class="is-sr-only">Imported</span>
<span class="is-sr-only">{% trans "Imported" %}</span>
</span>
{% endif %}
</td>

View file

@ -1,11 +1,15 @@
{% extends 'layout.html' %}
{% load i18n %}
{% block title %}{% trans "Create an Account" %}{% endblock %}
{% block content %}
<div class="columns">
<div class="column">
<div class="block">
{% if valid %}
<h1 class="title">Create an Account</h1>
<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 }}">
@ -14,8 +18,8 @@
</div>
{% else %}
<div class="content">
<h1 class="title">Permission Denied</h1>
<p>Sorry! This invite code is no longer valid.</p>
<h1 class="title">{% trans "Permission Denied" %}</h1>
<p>{% trans "Sorry! This invite code is no longer valid." %}</p>
</div>
{% endif %}
</div>

View file

@ -1,8 +1,9 @@
{% load bookwyrm_tags %}
{% load i18n %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>{% if title %}{{ title }} | {% endif %}{{ site.name }}</title>
<title>{% block title %}BookWyrm{% endblock %} | {{ site.name }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link type="text/css" rel="stylesheet" href="/static/css/bulma.min.css">
<link type="text/css" rel="stylesheet" href="/static/css/format.css">
@ -29,12 +30,12 @@
<form class="navbar-item column" action="/search/">
<div class="field has-addons">
<div class="control">
<input aria-label="Search for a book or user" id="search-input" class="input" type="text" name="q" placeholder="Search for a book or user" value="{{ query }}">
<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 }}">
</div>
<div class="control">
<button class="button" type="submit">
<span class="icon icon-search" title="Search">
<span class="is-sr-only">search</span>
<span class="icon icon-search" title="{% trans 'Search' %}">
<span class="is-sr-only">{% trans "Search" %}</span>
</span>
</button>
</div>
@ -43,8 +44,8 @@
<div role="button" tabindex="0" class="navbar-burger pulldown-menu" data-controls="main-nav" aria-expanded="false">
<div class="navbar-item mt-3">
<div class="icon icon-dots-three-vertical" title="Main navigation menu">
<span class="is-sr-only">Main navigation menu</span>
<div class="icon icon-dots-three-vertical" title="{% trans 'Main navigation menu' %}">
<span class="is-sr-only">{% trans "Main navigation menu" %}</span>
</div>
</div>
</div>
@ -54,13 +55,13 @@
<div class="navbar-start">
{% if request.user.is_authenticated %}
<a href="{% url 'user-shelves' request.user.localname %}" class="navbar-item">
Your shelves
{% trans "Your shelves" %}
</a>
<a href="/#feed" class="navbar-item">
Feed
{% trans "Feed" %}
</a>
<a href="{% url 'lists' %}" class="navbar-item">
Lists
{% trans "Lists" %}
</a>
{% endif %}
</div>
@ -75,22 +76,22 @@
<ul class="navbar-dropdown" id="navbar-dropdown">
<li>
<a href="/direct-messages" class="navbar-item">
Direct messages
{% trans "Direct Messages" %}
</a>
</li>
<li>
<a href="/user/{{request.user.localname}}" class="navbar-item">
Profile
{% trans 'Profile' %}
</a>
</li>
<li>
<a href="/preferences/profile" class="navbar-item">
Settings
{% trans 'Settings' %}
</a>
</li>
<li>
<a href="/import" class="navbar-item">
Import books
{% trans 'Import Books' %}
</a>
</li>
{% if perms.bookwyrm.create_invites or perms.bookwyrm.edit_instance_settings%}
@ -99,21 +100,21 @@
{% if perms.bookwyrm.create_invites %}
<li>
<a href="{% url 'settings-invites' %}" class="navbar-item">
Invites
{% trans 'Invites' %}
</a>
</li>
{% endif %}
{% if perms.bookwyrm.edit_instance_settings %}
<li>
<a href="{% url 'settings-site' %}" class="navbar-item">
Site Configuration
{% trans 'Site Configuration' %}
</a>
</li>
{% endif %}
<hr class="navbar-divider">
<li>
<a href="/logout" class="navbar-item">
Log out
{% trans 'Log out' %}
</a>
</li>
</ul>
@ -121,8 +122,8 @@
<div class="navbar-item">
<a href="/notifications" class="tags has-addons">
<span class="tag is-medium">
<span class="icon icon-bell" title="Notifications">
<span class="is-sr-only">Notifications</span>
<span class="icon icon-bell" title="{% trans 'Notifications' %}">
<span class="is-sr-only">{% trans "Notifications" %}</span>
</span>
</span>
<span class="{% if not request.user|notification_count %}hidden {% endif %}tag is-danger is-medium" data-poll="notifications">
@ -139,16 +140,16 @@
{% csrf_token %}
<div class="columns is-variable is-1">
<div class="column">
<label class="is-sr-only" for="id_localname">Username:</label>
<label class="is-sr-only" for="id_localname">{% trans "Username:" %}</label>
<input type="text" name="localname" maxlength="150" class="input" required="" id="id_localname" placeholder="username">
</div>
<div class="column">
<label class="is-sr-only" for="id_password">Username:</label>
<label class="is-sr-only" for="id_password">{% trans "Username:" %}</label>
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password" placeholder="password">
<p class="help"><a href="/password-reset">Forgot your password?</a></p>
</div>
<div class="column is-narrow">
<button class="button is-primary" type="submit">Log in</button>
<button class="button is-primary" type="submit">{% trans "Log in" %}</button>
</div>
</div>
</form>
@ -179,11 +180,11 @@
<div class="columns">
<div class="column">
<p>
<a href="/about">About this server</a>
<a href="/about">{% trans "About this server" %}</a>
</p>
{% if site.admin_email %}
<p>
<a href="mailto:{{ site.admin_email }}">Contact site admin</a>
<a href="mailto:{{ site.admin_email }}">{% trans "Contact site admin" %}</a>
</p>
{% endif %}
</div>
@ -194,7 +195,7 @@
</div>
{% endif %}
<div class="column">
BookWyrm is open source software. You can contribute or report issues on <a href="https://github.com/mouse-reeve/bookwyrm">GitHub</a>.
{% trans 'BookWyrm is open source software. You can contribute or report issues on <a href="https://github.com/mouse-reeve/bookwyrm">GitHub</a>.' %}
</div>
</div>
</div>

View file

@ -1,7 +1,8 @@
{% extends 'components/inline_form.html' %}
{% load i18n %}
{% block header %}
Create List
{% trans "Create List" %}
{% endblock %}
{% block form %}

View file

@ -1,17 +1,18 @@
{% extends 'lists/list_layout.html' %}
{% load i18n %}
{% block panel %}
<section class="content block">
<h2>Pending Books</h2>
<p><a href="{% url 'list' list.id %}">Go to list</a></p>
<h2>{% trans "Pending Books" %}</h2>
<p><a href="{% url 'list' list.id %}">{% trans "Go to list" %}</a></p>
{% if not pending.exists %}
<p>You're all set!</p>
<p>{% trans "You're all set!" %}</p>
{% else %}
<table class="table is-striped">
<tr>
<th></th>
<th>Book</th>
<th>Suggested by</th>
<th>{% trans "Book" %}</th>
<th>{% trans "Suggested by" %}</th>
<th></th>
</tr>
{% for item in pending %}
@ -31,13 +32,13 @@
{% csrf_token %}
<input type="hidden" name="item" value="{{ item.id }}">
<input type="hidden" name="approved" value="true">
<button class="button">Approve</button>
<button class="button">{% trans "Approve" %}</button>
</form>
<form class="control" method="POST" action="{% url 'list-curate' list.id %}">
{% csrf_token %}
<input type="hidden" name="item" value="{{ item.id }}">
<input type="hidden" name="approved" value="false">
<button class="button is-danger is-light">Discard</button>
<button class="button is-danger is-light">{% trans "Discard" %}</button>
</div>
</form>
</td>

View file

@ -1,7 +1,8 @@
{% extends 'components/inline_form.html' %}
{% load i18n %}
{% block header %}
Edit List
{% trans "Edit List" %}
{% endblock %}
{% block form %}

View file

@ -1,34 +1,35 @@
{% load i18n %}
{% csrf_token %}
<input type="hidden" name="user" value="{{ request.user.id }}">
<div class="columns">
<div class="column">
<div class="field">
<label class="label" for="id_name">Name:</label>
<label class="label" for="id_name">{% trans "Name:" %}</label>
{{ list_form.name }}
</div>
<div class="field">
<label class="label" for="id_description">Description:</label>
<label class="label" for="id_description">{% trans "Description:" %}</label>
{{ list_form.description }}
</div>
</div>
<div class="column">
<fieldset class="field">
<legend class="label">List curation:</legend>
<legend class="label">{% trans "List curation:" %}</legend>
<label class="field">
<input type="radio" name="curation" value="closed"{% if not list or list.curation == 'closed' %} checked{% endif %}> Closed
<p class="help mb-2">Only you can add and remove books to this list</p>
<input type="radio" name="curation" value="closed"{% if not list or list.curation == 'closed' %} checked{% endif %}> {% trans "Closed" %}
<p class="help mb-2">{% trans "Only you can add and remove books to this list" %}</p>
</label>
<label class="field">
<input type="radio" name="curation" value="curated"{% if list.curation == 'curated' %} checked{% endif %}> Curated
<p class="help mb-2">Anyone can suggest books, subject to your approval</p>
<input type="radio" name="curation" value="curated"{% if list.curation == 'curated' %} checked{% endif %}> {% trans "Curated" %}
<p class="help mb-2">{% trans "Anyone can suggest books, subject to your approval" %}</p>
</label>
<label class="field">
<input type="radio" name="curation" value="open"{% if list.curation == 'open' %} checked{% endif %}> Open
<p class="help mb-2">Anyone can add books to this list</p>
<input type="radio" name="curation" value="open"{% if list.curation == 'open' %} checked{% endif %}> {% trans "Open" %}
<p class="help mb-2">{% trans "Anyone can add books to this list" %}</p>
</label>
</fieldset>
</div>
@ -38,7 +39,7 @@
{% include 'snippets/privacy_select.html' with current=list.privacy %}
</div>
<div class="control">
<button type="submit" class="button is-primary">Save</button>
<button type="submit" class="button is-primary">{% trans "Save" %}</button>
</div>
</div>

View file

@ -1,7 +1,8 @@
{% extends 'lists/list_layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block panel %}
{% block panel %}
{% if request.user == list.user and pending_count %}
<div class="block content">
<p>
@ -13,7 +14,7 @@
<div class="columns mt-3">
<section class="column is-three-quarters">
{% if not items.exists %}
<p>This list is currently empty</p>
<p>{% trans "This list is currently empty" %}</p>
{% else %}
<ol>
{% for item in items %}
@ -31,13 +32,13 @@
</div>
<div class="card-footer has-background-white-bis">
<div class="card-footer-item">
<p>Added by {% include 'snippets/username.html' with user=item.user %}</p>
<p>{% trans "Added by" %} {% include 'snippets/username.html' with user=item.user %}</p>
</div>
{% if list.user == request.user or list.curation == 'open' and item.user == request.user %}
<form name="add-book" method="post" action="{% url 'list-remove-book' list.id %}" class="card-footer-item">
{% csrf_token %}
<input type="hidden" name="item" value="{{ item.id }}">
<button type="submit" class="button is-small is-danger">Remove</button>
<button type="submit" class="button is-small is-danger">{% trans "Remove" %}</button>
</form>
{% endif %}
</div>
@ -50,26 +51,29 @@
{% if request.user.is_authenticated and not list.curation == 'closed' or request.user == list.user %}
<section class="column is-one-quarter content">
<h2>{% if list.curation == 'open' or request.user == list.user %}Add{% else %}Suggest{% endif %} Books</h2>
<h2>{% if list.curation == 'open' or request.user == list.user %}{% trans "Add Books" %}{% else %}{% trans "Suggest Books" %}{% endif %}</h2>
<form name="search" action="{% url 'list' list.id %}" method="GET" class="block">
<div class="field has-addons">
<div class="control">
<input aria-label="Search for a book" class="input" type="text" name="q" placeholder="Search for a book" value="{{ query }}">
<input aria-label="{% trans 'Search for a book' %}" class="input" type="text" name="q" placeholder="{% trans 'Search for a book' %}" value="{{ query }}">
</div>
<div class="control">
<button class="button" type="submit">
<span class="icon icon-search" title="Search">
<span class="is-sr-only">search</span>
<span class="icon icon-search" title="{% trans 'Search' %}">
<span class="is-sr-only">{% trans "search" %}</span>
</span>
</button>
</div>
</div>
{% if query %}
<p class="help"><a href="{% url 'list' list.id %}">Clear search</a></p>
<p class="help"><a href="{% url 'list' list.id %}">{% trans "Clear search" %}</a></p>
{% endif %}
</form>
{% if not suggested_books %}
<p>No books found{% if query %} matching the query "{{ query }}"{% endif %}</p>
{% if query %}
<p>{% blocktrans %}No books found matching the query "{{ query }}"{% endblocktrans %}</p>{% else %}
<p>{% trans "No books found" %}</p>
{% endif %}
{% endif %}
{% for book in suggested_books %}
{% if book %}
@ -82,7 +86,7 @@
<form name="add-book" method="post" action="{% url 'list-add-book' list.id %}">
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}">
<button type="submit" class="button is-small is-link">{% if list.curation == 'open' or request.user == list.user %}Add{% else %}Suggest{% endif %}</button>
<button type="submit" class="button is-small is-link">{% if list.curation == 'open' or request.user == list.user %}{% trans "Add" %}{% else %}{% trans "Suggest" %}{% endif %}</button>
</form>
</div>
</div>

View file

@ -1,4 +1,5 @@
{% load bookwyrm_tags %}
{% load i18n %}
<div class="columns is-multiline">
{% for list in lists %}
<div class="column is-one-quarter">
@ -15,7 +16,7 @@
</div>
<div class="card-content is-flex-grow-0">
{% if list.description %}{{ list.description | to_markdown | safe | truncatewords_html:20 }}{% endif %}
<p class="subtitle help">Created {% if list.curation != 'open' %} and curated{% endif %} by {% include 'snippets/username.html' with user=list.user %}</p>
<p class="subtitle help">{% if list.curation != 'open' %}{% trans "Created and curated by" %}{% else %}{% trans "Created by" %}{% endif %} {% include 'snippets/username.html' with user=list.user %}</p>
</div>
</div>
</div>

View file

@ -1,16 +1,21 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block content %}
{% block title %}{{ list.name }}{% endblock %}
{% block content %}
<header class="columns content is-mobile">
<div class="column">
<h1 class="title">{{ list.name }} <span class="subtitle">{% include 'snippets/privacy-icons.html' with item=list %}</span></h1>
<p class="subtitle help">Created {% if list.curation != 'open' %} and curated{% endif %} by {% include 'snippets/username.html' with user=list.user %}</p>
<p class="subtitle help">{% if list.curation != 'open' %}{% trans "Created and curated by" %}{% else %}{% trans "Created by" %} {% include 'snippets/username.html' with user=list.user %}</p>
{% endif %}
{% include 'snippets/trimmed_text.html' with full=list.description %}
</div>
{% if request.user == list.user %}
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with text="Edit list" icon="pencil" controls_text="edit-list" focus="edit-list-header" %}
{% trans "Edit List" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text icon="pencil" controls_text="edit-list" focus="edit-list-header" %}
</div>
{% endif %}
</header>

View file

@ -1,16 +1,21 @@
{% extends 'layout.html' %}
{% load i18n %}
{% block title %}{% trans "Lists" %}{% endblock %}
{% block content %}
<header class="block">
<h1 class="title">Lists</h1>
<h1 class="title">{% trans "Lists" %}</h1>
</header>
{% if request.user.is_authenticated and not lists.has_previous %}
<header class="block columns is-mobile">
<div class="column">
<h2 class="title">Your lists</h2>
<h2 class="title">{% trans "Your lists" %}</h2>
</div>
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with controls_text="create-list" icon="plus" text="Create new list" focus="create-list-header" %}
{% trans "Create List" as button_text %}
{% include 'snippets/toggle/open_button.html' with controls_text="create-list" icon="plus" text=button_text focus="create-list-header" %}
</div>
</header>
@ -32,7 +37,7 @@
{% if lists %}
<section class="block content">
<h2 class="title">Recent Lists</h2>
<h2 class="title">{% trans "Recent Lists" %}</h2>
{% include 'lists/list_items.html' with lists=lists %}
</section>
<div>

View file

@ -1,23 +1,26 @@
{% extends 'layout.html' %}
{% block content %}
{% load i18n %}
{% block title %}{% trans "Login" %}{% endblock %}
{% block content %}
<div class="columns">
<div class="column">
<div class="box">
<h1 class="title">Log in</h1>
<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 %}
<form name="login" method="post" action="/login">
{% csrf_token %}
<div class="field">
<label class="label" for="id_localname">Username:</label>
<label class="label" for="id_localname">{% trans "Username:" %}</label>
<div class="control">
{{ login_form.localname }}
</div>
</div>
<div class="field">
<label class="label" for="id_password">Password:</label>
<label class="label" for="id_password">{% trans "Password:" %}</label>
<div class="control">
{{ login_form.password }}
</div>
@ -27,23 +30,23 @@
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit">Log in</button>
<button class="button is-primary" type="submit">{% trans "Log in" %}</button>
</div>
<div class="control">
<small><a href="/password-reset">Forgot your password?</a></small>
<small><a href="/password-reset">{% trans "Forgot your password?" %}</a></small>
</div>
</div>
</form>
</div>
<div class="box has-background-primary-light">
{% if site.allow_registration %}
<h2 class="title">Create an Account</h2>
<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">This instance is closed</h2>
<p>Contact an administrator to get an invite</p>
<h2 class="title">{% trans "This instance is closed" %}</h2>
<p>{% trans "Contact an administrator to get an invite" %}</p>
{% endif %}
</div>
</div>
@ -53,7 +56,7 @@
{% include 'snippets/about.html' %}
<p class="block">
<a href="/about/">More about this site</a>
<a href="/about/">{% trans "More about this site" %}</a>
</p>
</div>
</div>

View file

@ -1,9 +1,11 @@
{% extends 'layout.html' %}
{% load i18n %}
{% block title %}{% trans "Not Found" %}{% endblock %}
{% block content %}
<div class="block">
<h1 class="title">Not Found</h1>
<p>The page your requested doesn't seem to exist!</p>
<h1 class="title">{% trans "Not Found" %}</h1>
<p>{% trans "The page your requested doesn't seem to exist!" %}</p>
</div>
{% endblock %}

View file

@ -1,13 +1,17 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load humanize %}
{% load bookwyrm_tags %}
{% block title %}{% trans "Notifications" %}{% endblock %}
{% block content %}
<div class="block">
<h1 class="title">Notifications</h1>
<h1 class="title">{% trans "Notifications" %}</h1>
<form name="clear" action="/notifications" method="POST">
{% csrf_token %}
<button class="button is-danger is-light" type="submit" class="secondary">Delete notifications</button>
<button class="button is-danger is-light" type="submit" class="secondary">{% trans "Delete notifications" %}</button>
</form>
</div>
@ -41,32 +45,65 @@
{% include 'snippets/avatar.html' with user=notification.related_user %}
{% include 'snippets/username.html' with user=notification.related_user %}
{% if notification.notification_type == 'FAVORITE' %}
favorited your
<a href="{{ related_status.local_path }}">{{ related_status | status_preview_name|safe }}</a>
{% if related_status.status_type == 'Review' %}
{% blocktrans with book_title=related_status.book.title related_path=related_status.local_path %}favorited your <a href="{{ related_path }}">review of <em>{{ book_title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Comment' %}
{% blocktrans with book_title=related_status.book.title related_path=related_status.local_path %}favorited your <a href="{{ related_path }}">comment on <em>{{ book_title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Quotation' %}
{% blocktrans with book_title=related_status.book.title related_path=related_status.local_path %}favorited your <a href="{{ related_path }}">quote from <em>{{ book_title }}</em></a>{% endblocktrans %}
{% else %}
{% blocktrans with related_path=related_status.local_path %}favorited your <a href="{{ related_path }}">status</a>{% endblocktrans %}
{% endif %}
{% elif notification.notification_type == 'MENTION' %}
mentioned you in a
<a href="{{ related_status.local_path }}">{{ related_status | status_preview_name|safe }}</a>
{% if related_status.status_type == 'Review' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}mentioned you in a <a href="{{ related_path }}">review of <em>{{ book_title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Comment' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}mentioned you in a <a href="{{ related_path }}">comment on <em>{{ book_title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Quotation' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}mentioned you in a <a href="{{ related_path }}">quote from <em>{{ book_title }}</em></a>{% endblocktrans %}
{% else %}
{% blocktrans with related_path=related_status.local_path %}mentioned you in a <a href="{{ related_path }}">status</a>{% endblocktrans %}
{% endif %}
{% elif notification.notification_type == 'REPLY' %}
<a href="{{ related_status.local_path }}">replied</a>
to your
<a href="{{ related_status.reply_parent.local_path }}">{{ related_status | status_preview_name|safe }}</a>
{% if related_status.status_type == 'Review' %}
{% blocktrans with related_path=related_status.local_path parent_path=related_status.reply_parent.local_path book_title=related_status.reply_parent.book.title %}<a href="{{ related_path }}">replied</a> to your <a href="{{ parent_path }}">review of <em>{{ book_title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Comment' %}
{% blocktrans with related_path=related_status.local_path parent_path=related_status.reply_parent.local_path book_title=related_status.reply_parent.book.title %}<a href="{{ related_path }}">replied</a> to your <a href="{{ parent_path }}">comment on <em>{{ book_title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Quotation' %}
{% blocktrans with related_path=related_status.local_path parent_path=related_status.reply_parent.local_path book_title=related_status.reply_parent.book.title %}<a href="{{ related_path }}">replied</a> to your <a href="{{ parent_path }}">quote from <em>{{ book_title }}</em></a>{% endblocktrans %}
{% else %}
{% blocktrans with related_path=related_status.local_path parent_path=related_status.reply_parent.local_path %}<a href="{{ related_path }}">replied</a> to your <a href="{{ parent_path }}">status</a>{% endblocktrans %}
{% endif %}
{% elif notification.notification_type == 'FOLLOW' %}
followed you
{% trans "followed you" %}
{% include 'snippets/follow_button.html' with user=notification.related_user %}
{% elif notification.notification_type == 'FOLLOW_REQUEST' %}
sent you a follow request
{% trans "sent you a follow request" %}
<div class="row shrink">
{% include 'snippets/follow_request_buttons.html' with user=notification.related_user %}
</div>
{% elif notification.notification_type == 'BOOST' %}
boosted your <a href="{{ related_status.local_path }}">{{ related_status | status_preview_name|safe }}</a>
{% if related_status.status_type == 'Review' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">review of <em>{{ book.title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Comment' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">comment on<em>{{ book.title }}</em></a>{% endblocktrans %}
{% elif related_status.status_type == 'Quotation' %}
{% blocktrans with related_path=related_status.local_path book_title=related_status.book.title %}boosted your <a href="{{ related_path }}">quote from <em>{{ book.title }}</em></a>{% endblocktrans %}
{% else %}
{% blocktrans with related_path=related_status.local_path %}boosted your <a href="{{ related_path }}">status</a>{% endblocktrans %}
{% endif %}
{% elif notification.notification_type == 'ADD' %}
{% if notification.related_list_item.approved %}added{% else %}suggested adding{% endif %} {% include 'snippets/book_titleby.html' with book=notification.related_list_item.book %} to your list "<a href="{{ notification.related_list_item.book_list.local_path }}{% if not notification.related_list_item.approved %}/curate{% endif %}">{{ notification.related_list_item.book_list.name }}</a>"
{% if notification.related_list_item.approved %}
{% blocktrans with book_path=notification.related_list_item.book.local_path book_title=notification.related_list_item.book.title list_path=notification.related_list_item.book_list.local_path list_name=notification.related_list_item.book_list.name %} added <em><a href="{{ book_path }}">{{ book_title }}</a></em> to your list "<a href="{{ list_path }}">{{ list_name }}</a>"{% endblocktrans %}
{% else %}
{% blocktrans with book_path=notification.related_list_item.book.local_path book_title=notification.related_list_item.book.title list_path=notification.related_list_item.book_list.local_path list_name=notification.related_list_item.book_list.name %} suggested adding <em><a href="{{ book_path }}">{{ book_title }}</a></em> to your list "<a href="{{ list_path }}/curate">{{ list_name }}</a>"{% endblocktrans %}
{% endif %}
{% endif %}
{% elif notification.related_import %}
your <a href="/import/{{ notification.related_import.id }}">import</a> completed.
{% blocktrans with related_id=notification.related_import.id %} your <a href="/import/{{ related_id }}">import</a> completed.{% endblocktrans %}
{% endif %}
</p>
</div>
@ -98,7 +135,7 @@
{% endfor %}
{% if not notifications %}
<p>You're all caught up!</p>
<p>{% trans "You're all caught up!" %}</p>
{% endif %}
</div>
{% endblock %}

View file

@ -1,30 +1,33 @@
{% extends 'layout.html' %}
{% block content %}
{% load i18n %}
{% block title %}{% trans "Reset Password" %}{% endblock %}
{% block content %}
<div class="columns">
<div class="column">
<div class="block">
<h1 class="title">Reset Password</h1>
<h1 class="title">{% trans "Reset Password" %}</h1>
{% for error in errors %}
<p class="is-danger">{{ error }}</p>
{% endfor %}
<form name="password-reset" method="post" action="/password-reset/{{ code }}">
{% csrf_token %}
<div class="field">
<label class="label" for="id_password">Password:</label>
<label class="label" for="id_password">{% trans "Password:" %}</label>
<div class="control">
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password">
</div>
</div>
<div class="field">
<label class="label" for="id_confirm_password">Confirm password:</label>
<label class="label" for="id_confirm_password">{% trans "Confirm password:" %}</label>
<div class="control">
<input type="password" name="confirm-password" maxlength="128" class="input" required="" id="id_confirm_password">
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit">Confirm</button>
<button class="button is-primary" type="submit">{% trans "Confirm" %}</button>
</div>
</div>
</form>
@ -36,7 +39,6 @@
{% include 'snippets/about.html' %}
</div>
</div>
</div>
{% endblock %}

View file

@ -1,23 +1,26 @@
{% extends 'layout.html' %}
{% block content %}
{% load i18n %}
{% block title %}{% trans "Reset Password" %}{% endblock %}
{% block content %}
<div class="columns is-centered">
<div class="column is-half">
<div class="block">
<h1 class="title">Reset Password</h1>
<h1 class="title">{% trans "Reset Password" %}</h1>
{% if message %}<p>{{ message }}</p>{% endif %}
<p>A link to reset your password will be sent to your email address</p>
<p>{% trans "A link to reset your password will be sent to your email address" %}</p>
<form name="password-reset" method="post" action="/password-reset">
{% csrf_token %}
<div class="field">
<label class="label" for="id_email_register">Email address:</label>
<label class="label" for="id_email_register">{% trans "Email address:" %}</label>
<div class="control">
<input type="email" name="email" maxlength="254" class="input" id="id_email_register">
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-link" type="submit">Reset password</button>
<button class="button is-link" type="submit">{% trans "Reset password" %}</button>
</div>
</div>
</form>

View file

@ -1,12 +1,15 @@
{% extends 'preferences/preferences_layout.html' %}
{% load i18n %}
{% block title %}{% trans "Blocked Users" %}{{ author.name }}{% endblock %}
{% block header %}
Blocked Users
{% trans "Blocked Users" %}
{% endblock %}
{% block panel %}
{% if not request.user.blocks.exists %}
<p>No users currently blocked.</p>
<p>{% trans "No users currently blocked." %}</p>
{% else %}
<ul>
{% for user in request.user.blocks.all %}

View file

@ -1,19 +1,23 @@
{% extends 'preferences/preferences_layout.html' %}
{% load i18n %}
{% block title %}{% trans "Change Password" %}{% endblock %}
{% block header %}
Change Password
{% trans "Change Password" %}
{% endblock %}
{% block panel %}
<form name="edit-profile" action="/change-password/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="block">
<label class="label" for="id_password">New password:</label>
<label class="label" for="id_password">{% trans "New password:" %}</label>
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password">
</div>
<div class="block">
<label class="label" for="id_confirm_password">Confirm password:</label>
<label class="label" for="id_confirm_password">{% trans "Confirm password:" %}</label>
<input type="password" name="confirm-password" maxlength="128" class="input" required="" id="id_confirm_password">
</div>
<button class="button is-primary" type="submit">Change password</button>
<button class="button is-primary" type="submit">{% trans "Change Password" %}</button>
</form>
{% endblock %}

View file

@ -1,6 +1,10 @@
{% extends 'preferences/preferences_layout.html' %}
{% load i18n %}
{% block title %}{% trans "Edit Profile" %}{% endblock %}
{% block header %}
Edit Profile
{% trans "Edit Profile" %}
{% endblock %}
{% block panel %}
@ -10,28 +14,28 @@ Edit Profile
<form name="edit-profile" action="{% url 'prefs-profile' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="block">
<label class="label" for="id_avatar">Avatar:</label>
<label class="label" for="id_avatar">{% trans "Avatar:" %}</label>
{{ form.avatar }}
{% for error in form.avatar.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="block">
<label class="label" for="id_name">Display name:</label>
<label class="label" for="id_name">{% trans "Display name:" %}</label>
{{ form.name }}
{% for error in form.name.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="block">
<label class="label" for="id_summary">Summary:</label>
<label class="label" for="id_summary">{% trans "Summary:" %}</label>
{{ form.summary }}
{% for error in form.summary.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="block">
<label class="label" for="id_email">Email address:</label>
<label class="label" for="id_email">{% trans "Email address:" %}</label>
{{ form.email }}
{% for error in form.email.errors %}
<p class="help is-danger">{{ error | escape }}</p>
@ -39,10 +43,10 @@ Edit Profile
</div>
<div class="block">
<label class="checkbox label" for="id_manually_approves_followers">
Manually approve followers:
{% trans "Manually approve followers:" %}
{{ form.manually_approves_followers }}
</label>
</div>
<button class="button is-primary" type="submit">Save</button>
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
</form>
{% endblock %}

View file

@ -1,4 +1,5 @@
{% extends 'layout.html' %}
{% load i18n %}
{% block content %}
<header class="block column is-offset-one-quarter pl-1">
@ -7,19 +8,19 @@
<div class="block columns">
<nav class="menu column is-one-quarter">
<h2 class="menu-label">Account</h2>
<h2 class="menu-label">{% trans "Account" %}</h2>
<ul class="menu-list">
<li>
<a href="/preferences/profile"{% if '/preferences/profile' in request.path %} class="is-active" aria-selected="true"{% endif %}>Profile</a>
<a href="/preferences/profile"{% if '/preferences/profile' in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Profile" %}</a>
</li>
<li>
<a href="/preferences/password"{% if '/preferences/password' in request.path %} class="is-active" aria-selected="true"{% endif %}>Change password</a>
<a href="/preferences/password"{% if '/preferences/password' in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Change Password" %}</a>
</li>
</ul>
<h2 class="menu-label">Relationships</h2>
<h2 class="menu-label">{% trans "Relationships" %}</h2>
<ul class="menu-list">
<li>
<a href="/preferences/block"{% if '/preferences/block' in request.path %} class="is-active" aria-selected="true"{% endif %}>Blocked users</a>
<a href="/preferences/block"{% if '/preferences/block' in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Blocked Users" %}</a>
</li>
</ul>
</nav>

View file

@ -1,16 +1,20 @@
{% extends 'layout.html' %}
{% load i18n %}
{% block title %}{% trans "Search Results" %}{% endblock %}
{% block content %}
{% with book_results|first as local_results %}
<div class="block">
<h1 class="title">Search Results for "{{ query }}"</h1>
<h1 class="title">{% blocktrans %}Search Results for "{{ query }}"{% endblocktrans %}</h1>
</div>
<div class="block columns">
<div class="column">
<h2 class="title">Matching Books</h2>
<h2 class="title">{% trans "Matching Books" %}</h2>
<section class="block">
{% if not local_results.results %}
<p>No books found for "{{ query }}"</p>
<p>{% blocktrans %}No books found for "{{ query }}"{% endblocktrans %}</p>
{% else %}
<ul>
{% for result in local_results.results %}
@ -26,9 +30,10 @@
{% if book_results|slice:":1" and local_results.results %}
<div class="block">
<p>
Didn't find what you were looking for?
{% trans "Didn't find what you were looking for?" %}
</p>
{% include 'snippets/toggle/open_button.html' with text="Show results from other catalogues" small=True controls_text="more-results" %}
{% trans "Show results from other catalogues" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text small=True controls_text="more-results" %}
</div>
{% endif %}
@ -49,7 +54,7 @@
{% csrf_token %}
<input type="hidden" name="remote_id" value="{{ result.key }}">
<div>{% include 'snippets/search_result_text.html' with result=result link=False %}</div>
<button type="submit" class="button is-small is-link">Import book</button>
<button type="submit" class="button is-small is-link">{% trans "Import book" %}</button>
</form>
</li>
{% endfor %}
@ -59,16 +64,17 @@
{% endfor %}
{% if local_results.results %}
{% include 'snippets/toggle/close_button.html' with text="Hide results from other catalogues" small=True controls_text="more-results" %}
{% trans "Hide results from other catalogues" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text small=True controls_text="more-results" %}
{% endif %}
</div>
{% endif %}
</div>
<div class="column">
<section class="block">
<h2 class="title">Matching Users</h2>
<h2 class="title">{% trans "Matching Users" %}</h2>
{% if not user_results %}
<p>No users found for "{{ query }}"</p>
<p>{% blocktrans %}No users found for "{{ query }}"{% endblocktrans %}</p>
{% endif %}
<ul>
{% for result in user_results %}
@ -81,9 +87,9 @@
</ul>
</section>
<section class="block">
<h2 class="title">Lists</h2>
<h2 class="title">{% trans "Lists" %}</h2>
{% if not list_results %}
<p>No lists found for "{{ query }}"</p>
<p>{% blocktrans %}No lists found for "{{ query }}"{% endblocktrans %}</p>
{% endif %}
{% for result in list_results %}
<div class="block">

View file

@ -1,4 +1,8 @@
{% extends 'layout.html' %}
{% load i18n %}
{% block title %}{% trans "Administration" %}{% endblock %}
{% block content %}
<header class="block column is-offset-one-quarter pl-1">
@ -8,30 +12,30 @@
<div class="block columns">
<nav class="menu column is-one-quarter">
{% if perms.bookwyrm.create_invites %}
<h2 class="menu-label">Manage Users</h2>
<h2 class="menu-label">{% trans "Manage Users" %}</h2>
<ul class="menu-list">
<li>
{% url 'settings-invites' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>Invites</a>
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Invites" %}</a>
</li>
<li>
{% url 'settings-federation' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>Federated Servers</a>
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Federated Servers" %}</a>
</li>
</ul>
{% endif %}
{% if perms.bookwyrm.edit_instance_settings %}
<h2 class="menu-label">Instance Settings</h2>
<h2 class="menu-label">{% trans "Instance Settings" %}</h2>
<ul class="menu-list">
<li>
{% url 'settings-site' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>Site Configuration</a>
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Site Settings" %}</a>
{% if url in request.path %}
<ul class="emnu-list">
<li><a href="{{ url }}#instance-info">Instance Info</a></li>
<li><a href="{{ url }}#images">Images</a></li>
<li><a href="{{ url }}#footer">Footer Content</a></li>
<li><a href="{{ url }}#registration">Registration</a></li>
<li><a href="{{ url }}#instance-info">{% trans "Instance Info" %}</a></li>
<li><a href="{{ url }}#images">{% trans "Images" %}</a></li>
<li><a href="{{ url }}#footer">{% trans "Footer Content" %}</a></li>
<li><a href="{{ url }}#registration">{% trans "Registration" %}</a></li>
</ul>
{% endif %}
</li>

View file

@ -1,13 +1,15 @@
{% extends 'settings/admin_layout.html' %}
{% block header %}Federated Servers{% endblock %}
{% load i18n %}
{% block header %}{% trans "Federated Servers" %}{% endblock %}
{% block panel %}
<table class="table is-striped">
<tr>
<th>Server name</th>
<th>Software</th>
<th>Status</th>
<th>{% trans "Server name" %}</th>
<th>{% trans "Software" %}</th>
<th>{% trans "Status" %}</th>
</tr>
{% for server in servers %}
<tr>

View file

@ -1,41 +1,42 @@
{% extends 'settings/admin_layout.html' %}
{% block header %}Invites{% endblock %}
{% load i18n %}
{% block header %}{% trans "Invites" %}{% endblock %}
{% load humanize %}
{% block panel %}
<section class="block">
<h2 class="title is-4">Generate New Invite</h2>
<h2 class="title is-4">{% trans "Generate New Invite" %}</h2>
<form name="invite" action="{% url 'settings-invites' %}" method="post">
{% csrf_token %}
<div class="field is-grouped">
<div class="control">
<label class="label" for="id_expiry">Expiry:</label>
<label class="label" for="id_expiry">{% trans "Expiry:" %}</label>
<div class="select">
{{ form.expiry }}
</div>
</div>
<div class="control">
<label class="label" for="id_use_limit">Use limit:</label>
<label class="label" for="id_use_limit">{% trans "Use limit:" %}</label>
<div class="select">
{{ form.use_limit }}
</div>
</div>
</div>
<button class="button is-primary" type="submit">Create Invite</button>
<button class="button is-primary" type="submit">{% trans "Create Invite" %}</button>
</form>
</section>
<section class="block">
<table class="table is-striped">
<tr>
<th>Link</th>
<th>Expires</th>
<th>Max uses</th>
<th>Times used</th>
<th>{% trans "Link" %}</th>
<th>{% trans "Expires" %}</th>
<th>{% trans "Max uses" %}</th>
<th>{% trans "Times used" %}</th>
</tr>
{% if not invites %}
<tr><td colspan="4">No active invites</td></tr>
<tr><td colspan="4">{% trans "No active invites" %}</td></tr>
{% endif %}
{% for invite in invites %}
<tr>

View file

@ -1,30 +1,34 @@
{% extends 'settings/admin_layout.html' %}
{% block header %}Site Configuration{% endblock %}
{% load i18n %}
{% block title %}{% trans "Site Settings" %}{% endblock %}
{% block header %}{% trans "Site Settings" %}{% endblock %}
{% block panel %}
<form action="{% url 'settings-site' %}" method="POST" class="content">
{% csrf_token %}
<section class="block" id="instance-info">
<h2 class="title is-4">Instance Info</h2>
<h2 class="title is-4">{% trans "Instance Info" %}</h2>
<div class="control">
<label class="label" for="id_name">Instance Name:</label>
<label class="label" for="id_name">{% trans "Instance Name:" %}</label>
{{ site_form.name }}
</div>
<div class="control">
<label class="label" for="id_instance_tagline">Tagline:</label>
<label class="label" for="id_instance_tagline">{% trans "Tagline:" %}</label>
{{ site_form.instance_tagline }}
</div>
<div class="control">
<label class="label" for="id_instance_description">Instance description:</label>
<label class="label" for="id_instance_description">{% trans "Instance description:" %}</label>
{{ site_form.instance_description }}
</div>
<div class="control">
<label class="label" for="id_code_of_conduct">Code of conduct:</label>
<label class="label" for="id_code_of_conduct">{% trans "Code of conduct:" %}</label>
{{ site_form.code_of_conduct }}
</div>
<div class="control">
<label class="label" for="id_privacy_policy">Privacy Policy:</label>
<label class="label" for="id_privacy_policy">{% trans "Privacy Policy:" %}</label>
{{ site_form.privacy_policy }}
</div>
</section>
@ -32,18 +36,18 @@
<hr aria-hidden="true">
<section class="block" id="images">
<h2 class="title is-4">Images</h2>
<h2 class="title is-4">{% trans "Images" %}</h2>
<div class="field is-grouped">
<div class="control">
<label class="label" for="id_logo">Logo:</label>
<label class="label" for="id_logo">{% trans "Logo:" %}</label>
{{ site_form.logo }}
</div>
<div class="control">
<label class="label" for="id_logo_small">Logo small:</label>
<label class="label" for="id_logo_small">{% trans "Logo small:" %}</label>
{{ site_form.logo_small }}
</div>
<div class="control">
<label class="label" for="id_favicon">Favicon:</label>
<label class="label" for="id_favicon">{% trans "Favicon:" %}</label>
{{ site_form.favicon }}
</div>
</div>
@ -52,17 +56,17 @@
<hr aria-hidden="true">
<section class="block" id="footer">
<h2 class="title is-4">Footer Content</h2>
<h2 class="title is-4">{% trans "Footer Content" %}</h2>
<div class="control">
<label class="label" for="id_support_link">Support link:</label>
<label class="label" for="id_support_link">{% trans "Support link:" %}</label>
<input type="text" name="support_link" maxlength="255" class="input" id="id_support_link" placeholder="https://www.patreon.com/bookwyrm"{% if site.support_link %} value="{{ site.support_link }}"{% endif %}>
</div>
<div class="control">
<label class="label" for="id_support_title">Support title:</label>
<label class="label" for="id_support_title">{% trans "Support title:" %}</label>
<input type="text" name="support_title" maxlength="100" class="input" id="id_support_title" placeholder="Patreon"{% if site.support_title %} value="{{ site.support_title }}"{% endif %}>
</div>
<div class="control">
<label class="label" for="id_admin_email">Admin email:</label>
<label class="label" for="id_admin_email">{% trans "Admin email:" %}</label>
{{ site_form.admin_email }}
</div>
</section>
@ -70,19 +74,19 @@
<hr aria-hidden="true">
<section class="block" id="registration">
<h2 class="title is-4">Registration</h2>
<h2 class="title is-4">{% trans "Registration" %}</h2>
<div class="control">
<label class="label" for="id_allow_registration">Allow registration:
<label class="label" for="id_allow_registration">{% trans "Allow registration:" %}
{{ site_form.allow_registration }}
</div>
<div class="control">
<label class="label" for="id_registration_closed_text">Registration closed text:</label>
<label class="label" for="id_registration_closed_text">{% trans "Registration closed text:" %}</label>
{{ site_form.registration_closed_text }}
</div>
</section>
<footer class="block">
<button class="button is-primary" type="submit">Save Changes</button>
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
</footer>
</form>
{% endblock %}

View file

@ -1,11 +1,12 @@
{% load i18n %}
{% if not user in request.user.blocks.all %}
<form name="blocks" method="post" action="/block/{{ user.id }}">
{% csrf_token %}
<button class="button is-danger is-light is-small {{ class }}" type="submit">Block</button>
<button class="button is-danger is-light is-small {{ class }}" type="submit">{% trans "Block" %}</button>
</form>
{% else %}
<form name="unblocks" method="post" action="/unblock/{{ user.id }}">
{% csrf_token %}
<button class="button is-small {{ class }}" type="submit">Un-block</button>
<button class="button is-small {{ class }}" type="submit">{% trans "Un-block" %}</button>
</form>
{% endif %}

View file

@ -1,7 +1,7 @@
{% load bookwyrm_tags %}
<div class="cover-container is-{{ size }}">
{% if book.cover %}
<img class="book-cover" src="/images/{{ book.cover }}" alt="{{ book.alt_text }}" title="{{ book.alt_text }}">
<img class="book-cover" src="/images/{{ book.cover }}" alt="{{ book.alt_text }}">
{% else %}
<div class="no-cover book-cover">
<img class="book-cover" src="/static/images/no_cover.jpg" alt="No cover">

View file

@ -1,5 +1,7 @@
<a href="/book/{{ book.id }}">{{ book.title }}</a>
{% load i18n %}
{% if book.authors %}
by {% 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 %}
<a href="{{ book.local_path }}">{{ book.title }}</a>
{% endif %}

View file

@ -1,19 +1,20 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% with status.id|uuid as uuid %}
<form name="boost" action="/boost/{{ status.id }}" method="post" class="interaction boost-{{ status.id }}-{{ uuid }} {% if request.user|boosted:status %}hidden{% endif %}" data-id="boost-{{ status.id }}-{{ uuid }}">
{% csrf_token %}
<button class="button is-small" type="submit" {% if not status.boostable %}disabled{% endif %}>
<span class="icon icon-boost" title="Boost status">
<span class="is-sr-only">Boost status</span>
<span class="icon icon-boost" title="{% trans 'Boost status' %}">
<span class="is-sr-only">{% trans "Boost status" %}</span>
</span>
</button>
</form>
<form name="unboost" action="/unboost/{{ status.id }}" method="post" class="interaction boost-{{ status.id }}-{{ uuid }} active {% if not request.user|boosted:status %}hidden{% endif %}" data-id="boost-{{ status.id }}-{{ uuid }}">
{% csrf_token %}
<button class="button is-small is-primary" type="submit">
<span class="icon icon-boost" title="Un-boost status">
<span class="is-sr-only">Un-boost status</span>
<span class="icon icon-boost" title="{% trans 'Un-boost status' %}">
<span class="is-sr-only">{% trans "Un-boost status" %}</span>
</span>
</button>
</form>

View file

@ -1,4 +1,5 @@
{% load i18n %}
<div class="control{% if not parent_status.content_warning %} hidden{% endif %}" id="spoilers-{{ uuid }}">
<label class="is-sr-only" for="id_content_warning-{{ uuid }}">Spoiler alert:</label>
<input type="text" name="content_warning" maxlength="255" class="input" id="id_content_warning-{{ uuid }}" placeholder="Spoilers ahead!"{% if parent_status.content_warning %} value="{{ parent_status.content_warning }}"{% endif %}>
<label class="is-sr-only" for="id_content_warning-{{ uuid }}">{% trans "Spoiler alert:" %}</label>
<input type="text" name="content_warning" maxlength="255" class="input" id="id_content_warning-{{ uuid }}" placeholder="{% trans 'Spoilers ahead!' %}"{% if parent_status.content_warning %} value="{{ parent_status.content_warning }}"{% endif %}>
</div>

View file

@ -1,34 +1,37 @@
{% load humanize %}
{% load i18n %}
{% load bookwyrm_tags %}
<div class="tabs is-boxed">
<ul role="tablist">
<li class="tab-change is-active" data-category="tab-option-{{ book.id }}" role="tab" aria-selected="true" tabindex="0" data-tab="review-{{ book.id }}">
<a>Review</a>
<div class="tab-group">
<div class="tabs is-boxed" role="tablist">
<ul>
<li class="is-active">
<a href="#review-{{ book.id }}" id="tab-review-{{ book.id }}" role="tab" aria-selected="true" aria-controls="review-{{ book.id }}" data-category="tab-option-{{ book.id }}">{% trans "Review" %}</a>
</li>
<li class="tab-change" data-category="tab-option-{{ book.id }}" role="tab" tabindex="0" data-tab="comment-{{ book.id}}">
<a>Comment</a>
<li>
<a href="#comment-{{ book.id}}" id="tab-comment-{{ book.id }}" role="tab" aria-selected="false" aria-controls="comment-{{ book.id}}" data-category="tab-option-{{ book.id }}">{% trans "Comment" %}</a>
</li>
<li class="tab-change" data-category="tab-option-{{ book.id }}" role="tab" tabindex="0" data-tab="quote-{{ book.id }}">
<a>Quote</a>
<li>
<a href="#quote-{{ book.id }}" id="tab-quote-{{ book.id }}" role="tab" aria-selected="false" aria-controls="quote-{{ book.id }}" data-category="tab-option-{{ book.id }}">{% trans "Quote" %}</a>
</li>
</ul>
</div>
<div class="tab-option-{{ book.id }}" id="review-{{ book.id }}">
<div class="tab-option-{{ book.id }}" id="review-{{ book.id }}" role="tabpanel" aria-labelledby="tab-review-{{ book.id }}">
{% with 0|uuid as uuid %}
{% include 'snippets/create_status_form.html' with type='review' %}
{% endwith %}
</div>
<div class="hidden tab-option-{{ book.id }}" id="comment-{{ book.id }}">
<div class="tab-option-{{ book.id }}" id="comment-{{ book.id }}" role="tabpanel" aria-labelledby="tab-comment-{{ book.id }}" hidden>
{% with 0|uuid as uuid %}
{% include 'snippets/create_status_form.html' with type="comment" placeholder="Some thoughts on '"|add:book.title|add:"'" %}
{% endwith %}
</div>
<div class="hidden tab-option-{{ book.id }}" id="quote-{{ book.id }}">
<div class="tab-option-{{ book.id }}" id="quote-{{ book.id }}" role="tabpanel" aria-labelledby="tab-quote-{{ book.id }}" hidden>
{% with 0|uuid as uuid %}
{% include 'snippets/create_status_form.html' with type="quotation" placeholder="An excerpt from '"|add:book.title|add:"'" %}
{% endwith %}
</div>
</div>

View file

@ -1,4 +1,5 @@
{% load bookwyrm_tags %}
{% 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 }}">
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}">
@ -6,7 +7,7 @@
<input type="hidden" name="reply_parent" value="{{ reply_parent.id }}">
{% if type == 'review' %}
<div class="control">
<label class="label" for="id_name_{{ book.id }}_{{ type }}">Title:</label>
<label class="label" for="id_name_{{ book.id }}_{{ type }}">{% trans "Title" %}:</label>
<input type="text" name="name" maxlength="255" class="input" required="" id="id_name_{{ book.id }}_{{ type }}" placeholder="My {{ type }} of '{{ book.title }}'">
</div>
{% endif %}
@ -17,9 +18,9 @@
{% if type == 'review' %}
<fieldset>
<legend class="is-sr-only">Rating</legend>
<legend class="is-sr-only">{% trans "Rating" %}</legend>
<div class="field is-grouped stars form-rate-stars">
<label class="is-sr-only" for="no-rating-{{ book.id }}">No rating</label>
<label class="is-sr-only" for="no-rating-{{ book.id }}">{% trans "No rating" %}</label>
<input class="is-sr-only" type="radio" name="rating" value="" id="no-rating-{{ book.id }}" checked>
{% for i in '12345'|make_list %}
<input class="is-sr-only" id="book{{book.id}}-star-{{ forloop.counter }}" type="radio" name="rating" value="{{ forloop.counter }}">
@ -40,7 +41,7 @@
</div>
{% if type == 'quotation' %}
<div class="control">
<label class="label" for="id_content_quote-{{ book.id }}">Comment:</label>
<label class="label" for="id_content_quote-{{ book.id }}">{% trans "Comment" %}:</label>
{% include 'snippets/content_warning_field.html' with parent_status=status %}
<textarea name="content" class="textarea is-small" id="id_content_quote-{{ book.id }}"></textarea>
</div>
@ -50,19 +51,20 @@
<div class="columns pt-1">
<div class="field has-addons column">
<div class="control">
{% include 'snippets/toggle/toggle_button.html' with text="Include spoiler alert" icon="warning is-size-4" controls_text="spoilers" controls_uid=uuid focus="id_content_warning" checkbox="id_show_spoilers" class="toggle-button" pressed=status.content_warning %}
{% trans "Include spoiler alert" as button_text %}
{% 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=status.content_warning %}
</div>
<div class="control">
{% if type == 'direct' %}
<input type="hidden" name="privacy" value="direct">
<button type="button" class="button" aria-label="Privacy" disabled>Private</button>
<button type="button" class="button" aria-label="Privacy" disabled>{% trans "Private" %}</button>
{% else %}
{% include 'snippets/privacy_select.html' with current=reply_parent.privacy %}
{% endif %}
</div>
</div>
<div class="column is-narrow">
<button class="button is-link" type="submit">Post</button>
<button class="button is-link" type="submit">{% trans "Post" %}</button>
</div>
</div>
</form>

View file

@ -1,8 +1,10 @@
{% extends 'components/modal.html' %}
{% block modal-title %}Delete these read dates?{% endblock %}
{% load i18n %}
{% block modal-title %}{% trans "Delete these read dates?" %}{% endblock %}
{% block modal-body %}
{% if readthrough.progress_updates|length > 0 %}
You are deleting this readthrough and its {{ readthrough.progress_updates|length }} associated progress updates.
{% blocktrans with count=readthrough.progress_updates|length %}You are deleting this readthrough and its {{ count }} associated progress updates.{% endblocktrans %}
{% endif %}
{% endblock %}
{% block modal-footer %}
@ -10,8 +12,9 @@ You are deleting this readthrough and its {{ readthrough.progress_updates|length
{% csrf_token %}
<input type="hidden" name="id" value="{{ readthrough.id }}">
<button class="button is-danger" type="submit">
Delete
{% trans "Delete" %}
</button>
{% include 'snippets/toggle/toggle_button.html' with text="Cancel" controls_text="delete-readthrough" controls_uid=readthrough.id %}
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="delete-readthrough" controls_uid=readthrough.id %}
</form>
{% endblock %}

View file

@ -1,18 +1,19 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% 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 %}hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}">
{% csrf_token %}
<button class="button is-small" type="submit">
<span class="icon icon-heart" title="Like status">
<span class="is-sr-only">Like status</span>
<span class="icon icon-heart" title="{% trans 'Like status' %}">
<span class="is-sr-only">{% trans "Like status" %}</span>
</span>
</button>
</form>
<form name="unfavorite" action="/unfavorite/{{ status.id }}" method="POST" class="interaction fav-{{ status.id }}-{{ uuid }} active {% if not request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}">
{% csrf_token %}
<button class="button is-primary is-small" type="submit">
<span class="icon icon-heart" title="Un-like status">
<span class="is-sr-only">Un-like status</span>
<span class="icon icon-heart" title="{% trans 'Un-like status' %}">
<span class="is-sr-only">{% trans "Un-like status" %}</span>
</span>
</button>
</form>

View file

@ -1,8 +1,9 @@
{% load i18n %}
{% if request.user == user or not request.user.is_authenticated %}
{% elif request.user in user.follower_requests.all %}
<div>
Follow request already sent.
{% trans "Follow request already sent." %}
</div>
{% elif user in request.user.blocks.all %}
@ -15,15 +16,15 @@ Follow request already sent.
{% csrf_token %}
<input type="hidden" name="user" value="{{ user.username }}">
{% if user.manually_approves_followers %}
<button class="button is-small is-link" type="submit">Send follow request</button>
<button class="button is-small is-link" type="submit">{% trans "Send follow request" %}</button>
{% else %}
<button class="button is-small is-link" type="submit">Follow</button>
<button class="button is-small is-link" type="submit">{% trans "Follow" %}</button>
{% endif %}
</form>
<form action="/unfollow/" method="POST" class="interaction follow-{{ user.id }} {% if not request.user in user.followers.all %}hidden{%endif %}" data-id="follow-{{ user.id }}">
{% csrf_token %}
<input type="hidden" name="user" value="{{ user.username }}">
<button class="button is-small is-danger is-light" type="submit">Unfollow</button>
<button class="button is-small is-danger is-light" type="submit">{% trans "Unfollow" %}</button>
</form>
</div>
<div class="control">

View file

@ -1,15 +1,16 @@
{% load i18n %}
{% load bookwyrm_tags %}
{% if request.user|follow_request_exists:user %}
<div class="field is-grouped">
<form action="/accept-follow-request/" method="POST">
{% csrf_token %}
<input type="hidden" name="user" value="{{ user.username }}">
<button class="button is-link is-small" type="submit">Accept</button>
<button class="button is-link is-small" type="submit">{% trans "Accept" %}</button>
</form>
<form action="/delete-follow-request/" method="POST">
{% csrf_token %}
<input type="hidden" name="user" value="{{ user.username }}">
<button class="button is-danger is-light is-small" type="submit" class="warning">Delete</button>
<button class="button is-danger is-light is-small" type="submit" class="warning">{% trans "Delete" %}</button>
</form>
</div>
{% endif %}

View file

@ -1 +1 @@
{% load humanize %}set a goal to read {{ goal.goal | intcomma }} book{{ goal.goal | pluralize }} in {{ goal.year }}
{% load i18n %}{% load humanize %}{% blocktrans count counter=goal.goal with counter=goal.goal year=goal.year %}set a goal to read {{ counter }} book in {{ year }}{% plural %}set a goal to read {{ counter }} books in {{ year }}{% endblocktrans %}

View file

@ -1,15 +1,16 @@
{% extends 'components/card.html' %}
{% load i18n %}
{% block card-header %}
<h3 class="card-header-title has-background-primary has-text-white">
<span class="icon icon-book is-size-3 mr-2" aria-hidden="true"></span> {{ year }} reading goal
<span class="icon icon-book is-size-3 mr-2" aria-hidden="true"></span> {% blocktrans %}{{ year }} Reading Goal{% endblocktrans %}
</h3>
{% endblock %}
{% block card-content %}
<div class="content">
<p>Set a goal for how many books you'll finish reading in {{ year }}, and track your progress throughout the year.</p>
<p>{% blocktrans %}Set a goal for how many books you'll finish reading in {{ year }}, and track your progress throughout the year.{% endblocktrans %}</p>
{% include 'snippets/goal_form.html' %}
</div>
@ -17,7 +18,7 @@
{% block card-footer %}
<div class="card-footer-item is-flex-direction-column">
<button class="button is-danger is-light is-block set-display" data-id="hide-{{ year }}-reading-goal" data-value="true">Dismiss message</button>
<p class="help">You can set or change your reading goal any time from your <a href="{{ request.user.local_path }}">profile page</a></p>
<button class="button is-danger is-light is-block set-display" data-id="hide-{{ year }}-reading-goal" data-value="true">{% trans "Dismiss message" %}</button>
<p class="help">{% blocktrans with path=request.user.local_path %}You can set or change your reading goal any time from your <a href="{{ path }}">profile page</a>{% endblocktrans %}</p>
</div>
{% endblock %}

View file

@ -1,3 +1,4 @@
{% load i18n %}
<form method="post" name="goal" action="{{ request.user.local_path }}/goal/{{ year }}">
{% csrf_token %}
<input type="hidden" name="year" value="{% if goal %}{{ goal.year }}{% else %}{{ year }}{% endif %}">
@ -5,30 +6,31 @@
<div class="columns">
<div class="column">
<label class="label" for="id_goal">Reading goal:</label>
<label class="label" for="id_goal">{% trans "Reading goal:" %}</label>
<div class="field has-addons">
<div class="control">
<input type="number" class="input" name="goal" min="1" id="id_goal" value="{% if goal %}{{ goal.goal }}{% else %}12{% endif %}">
</div>
<p class="button is-static" aria-hidden="true">books</p>
<p class="button is-static" aria-hidden="true">{% trans "books" %}</p>
</div>
</div>
<div class="column">
<label class="label"><p class="mb-2">Goal privacy:</p>
<label class="label"><p class="mb-2">{% trans "Goal privacy:" %}</p>
{% include 'snippets/privacy_select.html' with no_label=True current=goal.privacy %}
</label>
</div>
</div>
<label for="post_status" class="label">
<input type="checkbox" name="post-status" id="post_status" class="checkbox" checked>
Post to feed
{% trans "Post to feed" %}
</label>
<p>
<button type="submit" class="button is-link">Set goal</button>
<button type="submit" class="button is-link">{% trans "Set goal" %}</button>
{% if goal %}
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="show-edit-goal" %}
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="show-edit-goal" %}
{% endif %}
</p>
</form>

View file

@ -1,11 +1,16 @@
{% load i18n %}
{% load humanize %}
<p>
{% if goal.progress_percent >= 100 %}
Success!
{% trans "Success!" %}
{% elif goal.progress_percent %}
{{ goal.progress_percent }}% complete!
{% blocktrans with percent=goal.progress_percent %}{{ percent }}% complete!{% endblocktrans %}
{% endif %}
{% if goal.user == request.user %}
{% blocktrans with read_count=goal.book_count|intcomma goal_count=goal.goal|intcomma path=goal.local_path %}You've read <a href="{{ path }}">{{ read_count }} of {{ goal_count}} books</a>.{% endblocktrans %}
{% else %}
{% blocktrans with username=goal.user.display_name read_count=goal.book_count|intcomma goal_count=goal.goal|intcomma path=goal.local_path %}{{ username }} has read <a href="{{ path }}">{{ read_count }} of {{ goal_count}} books</a>.{% endblocktrans %}
{% endif %}
{% if goal.user == request.user %}You've{% else %}{{ goal.user.display_name }} has{% endif %} read {% if request.path != goal.local_path %}<a href="{{ goal.local_path }}">{% endif %}{{ goal.book_count }} of {{ goal.goal | intcomma }} books{% if request.path != goal.local_path %}</a>{% endif %}.
</p>
<progress class="progress is-large" value="{{ goal.book_count }}" max="{{ goal.goal }}" aria-hidden="true">{{ goal.progress_percent }}%</progress>

View file

@ -1,9 +1,10 @@
{% load i18n %}
<nav class="pagination" role="navigation" aria-label="pagination">
{% if page.has_previous %}
<p class="pagination-previous">
<a href="{{ path }}?page={{ page.previous_page_number }}{{ anchor }}">
<span class="icon icon-arrow-left"></span>
Previous
{% trans "Previous" %}
</a>
</p>
{% endif %}
@ -11,7 +12,7 @@
{% if page.has_next %}
<p class="pagination-next">
<a href="{{ path }}?page={{ page.next_page_number }}{{ anchor }}">
Next
{% trans "Next" %}
<span class="icon icon-arrow-right"></span>
</a>
</p>

View file

@ -1,18 +1,19 @@
{% load i18n %}
{% if item.privacy == 'public' %}
<span class="icon icon-globe" title="Public">
<span class="is-sr-only">Public</span>
<span class="icon icon-globe" title="{% trans 'Public' %}">
<span class="is-sr-only">{% trans "Public" %}</span>
</span>
{% elif item.privacy == 'unlisted' %}
<span class="icon icon-unlock" title="Unlisted">
<span class="is-sr-only">Unlisted</span>
<span class="icon icon-unlock" title="{% trans 'Unlisted' %}">
<span class="is-sr-only">{% trans "Unlisted" %}</span>
</span>
{% elif item.privacy == 'followers' %}
<span class="icon icon-lock" title="Followers-only">
<span class="is-sr-only">Followers-only</span>
<span class="is-sr-only">{% trans "Followers-only" %}</span>
</span>
{% else %}
<span class="icon icon-envelope" title="Private">
<span class="is-sr-only">Private</span>
<span class="icon icon-envelope" title="{% trans 'Private' %}">
<span class="is-sr-only">{% trans "Private" %}</span>
</span>
{% endif %}

View file

@ -1,21 +1,22 @@
{% load i18n %}
{% load bookwyrm_tags %}
<div class="select {{ class }}">
{% with 0|uuid as uuid %}
{% if not no_label %}
<label class="is-sr-only" for="privacy-{{ uuid }}">Post privacy</label>
<label class="is-sr-only" for="privacy-{{ uuid }}">{% trans "Post privacy" %}</label>
{% endif %}
<select name="privacy" id="privacy-{{ uuid }}">
<option value="public" {% if not current or current == 'public' %}selected{% endif %}>
Public
{% trans "Public" %}
</option>
<option value="unlisted" {% if current == 'unlisted' %}selected{% endif %}>
Unlisted
{% trans "Unlisted" %}
</option>
<option value="followers" {% if current == 'followers' %}selected{% endif %}>
Followers
{% trans "Followers" %}
</option>
<option value="direct" {% if current == 'direct' %}selected{% endif %}>
Private
{% trans "Private" %}
</option>
</select>
{% endwith %}

View file

@ -1,8 +1,9 @@
{% load i18n %}
<form class="field is-grouped is-small" action="/edit-readthrough" method="POST">
{% csrf_token %}
<input type="hidden" name="id" value="{{ readthrough.id }}"/>
<div class="field">
<label class="label is-align-self-center mb-0 pr-2" for="progress">Progress:</label>
<label class="label is-align-self-center mb-0 pr-2" for="progress">{% trans "Progress:" %}</label>
<div class="field has-addons mb-0">
<div class="control">
<input
@ -12,16 +13,16 @@
</div>
<div class="control select is-small">
<select name="progress_mode" aria-label="Progress mode">
<option value="PG" {% if readthrough.progress_mode == 'PG' %}selected{% endif %}>pages</option>
<option value="PCT" {% if readthrough.progress_mode == 'PCT' %}selected{% endif %}>percent</option>
<option value="PG" {% if readthrough.progress_mode == 'PG' %}selected{% endif %}>{% trans "pages" %}</option>
<option value="PCT" {% if readthrough.progress_mode == 'PCT' %}selected{% endif %}>{% trans "percent" %}</option>
</select>
</div>
<div class="control">
<button class="button is-small px-2 is-primary" type="submit">Save</button>
<button class="button is-small px-2 is-primary" type="submit">{% trans "Save" %}</button>
</div>
</div>
{% if readthrough.progress_mode == 'PG' and book.pages %}
<p class="help">of {{ book.pages }} pages</p>
<p class="help">{% blocktrans %}of {{ book.pages }} pages{% endblocktrans %}</p>
{% endif %}
</div>
</form>

View file

@ -1,6 +1,7 @@
{% load i18n %}
{% load bookwyrm_tags %}
{% if request.user.is_authenticated %}
<span class="is-sr-only">Leave a rating</span>
<span class="is-sr-only">{% trans "Leave a rating" %}</span>
<div class="block">
<form class="hidden-form" name="rate" action="/post/rating" method="POST">
{% csrf_token %}
@ -10,7 +11,7 @@
<input type="hidden" name="rating" value="{{ forloop.counter }}">
<div class="field is-grouped stars form-rate-stars mb-1 has-text-warning-dark">
<label class="is-sr-only" for="rating-no-rating-{{ book.id }}">No rating</label>
<label class="is-sr-only" for="rating-no-rating-{{ book.id }}">{% trans "No rating" %}</label>
<input class="is-sr-only" type="radio" name="rating" value="" id="rating-no-rating-{{ book.id }}" checked>
{% for i in '12345'|make_list %}
<input class="is-sr-only" id="rating-book{{book.id}}-star-{{ forloop.counter }}" type="radio" name="rating" value="{{ forloop.counter }}" {% if book|user_rating:user == forloop.counter %}checked{% endif %}>
@ -25,7 +26,7 @@
{% include 'snippets/privacy_select.html' with class="is-small" %}
</div>
<div class="control">
<button class="button is-small is-primary" type="submit">Rate</button>
<button class="button is-small is-primary" type="submit">{% trans "Rate" %}</button>
</div>
</div>
</form>

View file

@ -1,16 +1,18 @@
{% load i18n %}
{% load humanize %}
<div class="content block">
<div id="hide-edit-readthrough-{{ readthrough.id }}">
<div class="columns">
<div class="column">
Progress Updates:
{% trans "Progress Updates:" %}
</dl>
<ul>
{% if readthrough.finish_date or readthrough.progress %}
<li>{% if readthrough.finish_date %} {{ readthrough.finish_date | naturalday }}: finished {% else %}{% if readthrough.progress_mode == 'PG' %}on page {{ readthrough.progress }}{% if book.pages %} of {{ book.pages }}{% endif %}
<li>{% if readthrough.finish_date %} {{ readthrough.finish_date | naturalday }}: {% trans "finished" %} {% else %}{% if readthrough.progress_mode == 'PG' %}on page {{ readthrough.progress }}{% if book.pages %} of {{ book.pages }}{% endif %}
{% else %}{{ readthrough.progress }}%{% endif %}{% endif %}
{% if readthrough.progress %}
{% include 'snippets/toggle/toggle_button.html' with text="Show all updates" controls_text="updates" controls_uid=readthrough.id class="is-small" %}
{% trans "Show all updates" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="updates" controls_uid=readthrough.id class="is-small" %}
<ul id="updates-{{ readthrough.id }}" class="hidden">
{% for progress_update in readthrough.progress_updates %}
<li>
@ -25,7 +27,7 @@
<input type="hidden" name="id" value="{{ progress_update.id }}"/>
<button type="submit" class="button is-small" for="delete-progressupdate-{{ progress_update.id }}" role="button" tabindex="0">
<span class="icon icon-x" title="Delete this progress update">
<span class="is-sr-only">Delete this progress update</span>
<span class="is-sr-only">{% trans "Delete this progress update" %}</span>
</span>
</button>
</form>
@ -35,16 +37,18 @@
{% endif %}
</li>
{% endif %}
<li>{{ readthrough.start_date | naturalday }}: started</li>
<li>{{ readthrough.start_date | naturalday }}: {% trans "started" %}</li>
</ul>
</div>
<div class="column is-narrow">
<div class="field has-addons">
<div class="control">
{% include 'snippets/toggle/toggle_button.html' with class="is-small" text="Edit read dates" icon="pencil" controls_text="edit-readthrough" controls_uid=readthrough.id focus="edit-readthrough" %}
{% trans "Edit read dates" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with class="is-small" text=button_text icon="pencil" controls_text="edit-readthrough" controls_uid=readthrough.id focus="edit-readthrough" %}
</div>
<div class="control">
{% include 'snippets/toggle/toggle_button.html' with class="is-small" text="Delete these read dates" icon="x" controls_text="delete-readthrough" controls_uid=readthrough.id focus="modal-title-delete-readthrough" %}
{% trans "Delete these read dates" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with class="is-small" text=button_text icon="x" controls_text="delete-readthrough" controls_uid=readthrough.id focus="modal-title-delete-readthrough" %}
</div>
</div>
</div>
@ -53,12 +57,13 @@
</div>
<div class="box hidden" id="edit-readthrough-{{ readthrough.id }}" tabindex="0">
<h3 class="title is-5">Edit read dates</h3>
<h3 class="title is-5">{% trans "Edit read dates" %}</h3>
<form name="edit-readthrough" action="/edit-readthrough" method="post">
{% include 'snippets/readthrough_form.html' with readthrough=readthrough %}
<div class="field is-grouped">
<button class="button is-primary" type="submit">Save</button>
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="edit-readthrough" controls_uid=readthrough.id %}
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="edit-readthrough" controls_uid=readthrough.id %}
</div>
</form>
</div>

View file

@ -1,16 +1,17 @@
{% load i18n %}
{% csrf_token %}
<input type="hidden" name="id" value="{{ readthrough.id }}">
<input type="hidden" name="book" value="{{ book.id }}">
<div class="field">
<label class="label">
Started reading
{% trans "Started reading" %}
<input type="date" name="start_date" class="input" id="id_start_date-{{ readthrough.id }}" value="{{ readthrough.start_date | date:"Y-m-d" }}">
</label>
</div>
{# Only show progress for editing existing readthroughs #}
{% if readthrough.id and not readthrough.finish_date %}
<label class="label" for="id_progress-{{ readthrough.id }}">
Progress
{% trans "Progress" %}
</label>
<div class="field has-addons">
<div class="control">
@ -18,15 +19,15 @@
</div>
<div class="control select">
<select name="progress_mode" aria-label="Progress mode">
<option value="PG" {% if readthrough.progress_mode == 'PG' %}selected{% endif %}>pages</option>
<option value="PCT" {% if readthrough.progress_mode == 'PCT' %}selected{% endif %}>percent</option>
<option value="PG" {% if readthrough.progress_mode == 'PG' %}selected{% endif %}>{% trans "pages" %}</option>
<option value="PCT" {% if readthrough.progress_mode == 'PCT' %}selected{% endif %}>{% trans "percent" %}</option>
</select>
</div>
</div>
{% endif %}
<div class="field">
<label class="label">
Finished reading
{% trans "Finished reading" %}
<input type="date" name="finish_date" class="input" id="id_finish_date-{{ readthrough.id }}" value="{{ readthrough.finish_date | date:"Y-m-d" }}">
</label>
</div>

View file

@ -1,6 +1,7 @@
{% load i18n %}
{% csrf_token %}
<div class="field">
<label class="label" for="id_localname_register">Username:</label>
<label class="label" for="id_localname_register">{% trans "Username:" %}</label>
<div class="control">
<input type="text" name="localname" maxlength="150" class="input" required="" id="id_localname_register" value="{% if register_form.localname.value %}{{ register_form.localname.value }}{% endif %}">
</div>
@ -9,7 +10,7 @@
{% endfor %}
</div>
<div class="field">
<label class="label" for="id_email_register">Email address:</label>
<label class="label" for="id_email_register">{% trans "Email address:" %}</label>
<div class="control">
<input type="email" name="email" maxlength="254" class="input" id="id_email_register" value="{% if register_form.email.value %}{{ register_form.email.value }}{% endif %}">
{% for error in register_form.email.errors %}
@ -18,7 +19,7 @@
</div>
</div>
<div class="field">
<label class="label" for="id_password_register">Password:</label>
<label class="label" for="id_password_register">{% trans "Password:" %}</label>
<div class="control">
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password_register">
{% for error in register_form.password.errors %}
@ -28,6 +29,6 @@
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit">Sign Up</button>
<button class="button is-primary" type="submit">{% trans "Sign Up" %}</button>
</div>
</div>

View file

@ -1,13 +1,14 @@
{% load i18n %}
{{ obj.user.display_name }}{% if obj.status_type == 'GeneratedNote' %}
{{ obj.content | safe }}
{% elif obj.status_type == 'Review' and not obj.name and not obj.content%}
rated
{% trans "rated" %}
{% elif obj.status_type == 'Review' %}
reviewed
{% trans "reviewed" %}
{% elif obj.status_type == 'Comment' %}
commented on
{% trans "commented on" %}
{% elif obj.status_type == 'Quotation' %}
quoted
{% trans "quoted" %}
{% endif %}
{% if obj.book %}{{ obj.book.title | safe}}
{% elif obj.mention_books %}

View file

@ -1,2 +1,3 @@
{% load i18n %}
<strong>{% if link %}<a href="{{ result.key }}">{{ result.title }}</a>{% else %}{{ result.title }}{% endif %}</strong>
{% if result.author %} by {{ result.author }}{% endif %}{% if result.year %} ({{ result.year }}){% endif %}
{% if result.author %} {% blocktrans with author=result.author %}by {{ author }}{% endblocktrans %}{% endif %}{% if result.year %} ({{ result.year }}){% endif %}

View file

@ -1,39 +1,20 @@
{% load humanize %}
{% load i18n %}
{% load bookwyrm_tags %}
{% if books|length > 0 %}
<div class="table-container">
<table class="table is-striped is-fullwidth">
<tr class="book-preview">
<th>
Cover
</th>
<th>
Title
</th>
<th>
Author
</th>
<th>
Published
</th>
<th>
Shelved
</th>
<th>
Started
</th>
<th>
Finished
</th>
<th>
External links
</th>
{% if ratings %}
<th>
Rating
</th>
{% endif %}
<th>{% trans "Cover" %}</th>
<th>{% trans "Title" %}</th>
<th>{% trans "Author" %}</th>
<th>{% trans "Published" %}</th>
<th>{% trans "Shelved" %}</th>
<th>{% trans "Started" %}</th>
<th>{% trans "Finished" %}</th>
<th>{% trans "External links" %}</th>{% if ratings %}
<th>{% trans "Rating" %}</th>{% endif %}
</tr>
{% for book in books %}
<tr class="book-preview">
@ -60,7 +41,7 @@
{{ read_through.finish_date | naturalday |default_if_none:""}}
</td>
<td>
<a href="https://openlibrary.org/book/{{ book.openlibrary_key }}" target="_blank">OpenLibrary</a>
<a href="https://openlibrary.org/book/{{ book.openlibrary_key }}" target="_blank">{% trans "OpenLibrary" %}</a>
</td>
{% if ratings %}
<td>
@ -77,13 +58,13 @@
</table>
</div>
{% else %}
<p>This shelf is empty.</p>
<p>{% trans "This shelf is empty." %}</p>
{% if shelf.editable %}
<form name="delete-shelf" action="/delete-shelf/{{ shelf.id }}" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ request.user.id }}">
<button class="button is-danger is-light" type="submit">
Delete shelf
{% trans "Delete shelf" %}
</button>
</form>
{% endif %}

View file

@ -1,6 +1,7 @@
{% extends 'components/dropdown.html' %}
{% load i18n %}
{% block dropdown-trigger %}
<span>Change shelf</span>
<span>{% trans "Change shelf" %}</span>
<span class="icon icon-arrow-down" aria-hidden="true"></span>
{% endblock %}
@ -23,7 +24,7 @@
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="shelf" value="{{ current.id }}">
<button class="button is-fullwidth is-small is-danger is-light" type="submit">Unshelve</button>
<button class="button is-fullwidth is-small is-danger is-light" type="submit">{% trans "Unshelve" %}</button>
</form>
</li>
{% endblock %}

View file

@ -1,7 +1,8 @@
{% extends 'components/modal.html' %}
{% load i18n %}
{% block modal-title %}
Finish "<em>{{ book.title }}</em>"
{% blocktrans with book_title=book.title %}Finish "<em>{{ book_title }}</em>"{% endblocktrans %}
{% endblock %}
@ -15,13 +16,13 @@ Finish "<em>{{ book.title }}</em>"
<input type="hidden" name="id" value="{{ readthrough.id }}">
<div class="field">
<label class="label">
Started reading
{% trans "Started reading" %}
<input type="date" name="start_date" class="input" id="finish_id_start_date-{{ uuid }}" value="{{ readthrough.start_date | date:"Y-m-d" }}">
</label>
</div>
<div class="field">
<label class="label">
Finished reading
{% trans "Finished reading" %}
<input type="date" name="finish_date" class="input" id="id_finish_date-{{ uuid }}" value="{% now "Y-m-d" %}">
</label>
</div>
@ -33,13 +34,14 @@ Finish "<em>{{ book.title }}</em>"
<div class="column field">
<label for="post_status-{{ uuid }}">
<input type="checkbox" name="post-status" class="checkbox" id="post_status-{{ uuid }}" checked>
Post to feed
{% trans "Post to feed" %}
</label>
{% include 'snippets/privacy_select.html' %}
</div>
<div class="column">
<button type="submit" class="button is-success">Save</button>
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="finish-reading" controls_uid=uuid %}
<button type="submit" class="button is-success">{% trans "Save" %}</button>
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="finish-reading" controls_uid=uuid %}
</div>
</div>
{% endblock %}

View file

@ -1,7 +1,8 @@
{% extends 'components/dropdown.html' %}
{% load i18n %}
{% block dropdown-trigger %}
<span class="icon icon-arrow-down">
<span class="is-sr-only">More shelves</span>
<span class="is-sr-only">{% trans "More shelves" %}</span>
</span>
{% endblock %}

View file

@ -1,16 +1,20 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% for shelf in shelves %}
{% comparison_bool shelf.identifier active_shelf.shelf.identifier as is_current %}
{% if dropdown %}<li role="menuitem">{% endif %}
<div class="{% if dropdown %}dropdown-item pt-0 pb-0{% elif active_shelf.shelf.identifier|next_shelf != shelf.identifier %}hidden{% endif %}">
{% if shelf.identifier == 'reading' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
{% include 'snippets/toggle/toggle_button.html' with class=class text="Start reading" controls_text="start-reading" controls_uid=button_uuid focus="modal-title-start-reading" disabled=is_current %}
{% trans "Start reading" as button_text %}
{% 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 %}
{% endif %}{% elif shelf.identifier == 'read' and active_shelf.shelf.identifier == 'read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
<button type="button" class="button {{ class }}" disabled><span>Read</span>
<button type="button" class="button {{ class }}" disabled><span>{% trans "Read" %}</span>
{% endif %}{% elif shelf.identifier == 'read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
{% include 'snippets/toggle/toggle_button.html' with class=class text="Finish reading" controls_text="finish-reading" controls_uid=button_uuid focus="modal-title-finish-reading" disabled=is_current %}
{% trans "Finish reading" as button_text %}
{% 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 %}
{% endif %}{% elif shelf.identifier == 'to-read' %}{% if not dropdown or active_shelf.shelf.identifier|next_shelf != shelf.identifier %}
{% include 'snippets/toggle/toggle_button.html' with class=class text="Want to read" controls_text="want-to-read" controls_uid=button_uuid focus="modal-title-want-to-read" disabled=is_current %}
{% trans "Want to read" as button_text %}
{% 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 %}
{% endif %}{% elif shelf.editable %}
<form name="shelve" action="/shelve/" method="post">
{% csrf_token %}

View file

@ -1,7 +1,8 @@
{% extends 'components/modal.html' %}
{% load i18n %}
{% block modal-title %}
Start "<em>{{ book.title }}</em>"
{% blocktrans with book_title=book.title %}Start "<em>{{ book_title }}</em>"{% endblocktrans %}
{% endblock %}
{% block modal-form-open %}
@ -13,7 +14,7 @@ Start "<em>{{ book.title }}</em>"
{% csrf_token %}
<div class="field">
<label class="label">
Started reading
{% trans "Started reading" %}
<input type="date" name="start_date" class="input" id="start_id_start_date-{{ uuid }}" value="{% now "Y-m-d" %}">
</label>
</div>
@ -25,13 +26,14 @@ Start "<em>{{ book.title }}</em>"
<div class="column field">
<label for="post_status_start-{{ uuid }}">
<input type="checkbox" name="post-status" class="checkbox" id="post_status_start-{{ uuid }}" checked>
Post to feed
{% trans "Post to feed" %}
</label>
{% include 'snippets/privacy_select.html' %}
</div>
<div class="column">
<button class="button is-success" type="submit">Save</button>
{% include 'snippets/toggle/toggle_button.html' with text="Cancel" controls_text="start-reading" controls_uid=uuid %}
<button class="button is-success" type="submit">{% trans "Save" %}</button>
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="start-reading" controls_uid=uuid %}
</div>
</div>
{% endblock %}

View file

@ -1,7 +1,8 @@
{% extends 'components/modal.html' %}
{% load i18n %}
{% block modal-title %}
Want to Read "<em>{{ book.title }}</em>"
{% blocktrans with book_title=book.title %}Want to Read "<em>{{ book_title }}</em>"{% endblocktrans %}
{% endblock %}
{% block modal-form-open %}
@ -16,15 +17,16 @@ Want to Read "<em>{{ book.title }}</em>"
<div class="column field">
<label for="post_status_want-{{ uuid }}">
<input type="checkbox" name="post-status" class="checkbox" id="post_status_want-{{ uuid }}" checked>
Post to feed
{% trans "Post to feed" %}
</label>
{% include 'snippets/privacy_select.html' %}
</div>
<div class="column">
<button class="button is-success" type="submit">
<span>Want to read</span>
<span>{% trans "Want to read" %}</span>
</button>
{% include 'snippets/toggle/toggle_button.html' with text="Cancel" controls_text="want-to-read" controls_uid=uuid %}
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="want-to-read" controls_uid=uuid %}
</div>
</div>
{% endblock %}

View file

@ -1,5 +1,6 @@
{% load i18n %}
<p class="stars">
<span class="is-sr-only">{% if rating %}{{ rating|floatformat }} star{{ rating|floatformat | pluralize }}{% else %}No rating{% endif %}</span>
<span class="is-sr-only">{% if rating %}{{ rating|floatformat }} star{{ rating|floatformat | pluralize }}{% else %}{% trans "No rating" %}{% endif %}</span>
{% for i in '12345'|make_list %}
<span class="icon is-small mr-1 icon-star-{% if rating >= forloop.counter %}full{% elif rating|floatformat:0 >= forloop.counter|floatformat:0 %}half{% else %}empty{% endif %}" aria-hidden="true">
</span>

View file

@ -1,9 +1,10 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% if not status.deleted %}
{% if status.status_type == 'Boost' %}
{% include 'snippets/avatar.html' with user=status.user %}
{% include 'snippets/username.html' with user=status.user %}
boosted
{% trans "boosted" %}
{% include 'snippets/status/status_body.html' with status=status|boosted_status %}
{% else %}
{% include 'snippets/status/status_body.html' with status=status %}

View file

@ -1,4 +1,5 @@
{% extends 'components/card.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% load humanize %}
@ -20,7 +21,8 @@
{% if request.user.is_authenticated %}
<div class="field has-addons">
<div class="control">
{% include 'snippets/toggle/toggle_button.html' with controls_text="show-comment" controls_uid=status.id text="Reply" icon="comment" class="is-small toggle-button" focus="id_content_reply" %}
{% trans "Reply" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with controls_text="show-comment" controls_uid=status.id text=button_text icon="comment" class="is-small toggle-button" focus="id_content_reply" %}
</div>
<div class="control">
{% include 'snippets/boost_button.html' with status=status %}
@ -32,16 +34,16 @@
{% else %}
<a href="/login">
<span class="icon icon-comment" title="Reply">
<span class="is-sr-only">Reply</span>
<span class="icon icon-comment" title="{% trans 'Reply' %}">
<span class="is-sr-only">{% trans "Reply" %}</span>
</span>
<span class="icon icon-boost" title="Boost status">
<span class="is-sr-only">Boost status</span>
<span class="icon icon-boost" title="{% trans 'Boost status' %}">
<span class="is-sr-only">{% trans "Boost status" %}</span>
</span>
<span class="icon icon-heart" title="Like status">
<span class="is-sr-only">Like status</span>
<span class="icon icon-heart" title="{% trans 'Like status' %}">
<span class="is-sr-only">{% trans "Like status" %}</span>
</span>
</a>
{% endif %}

View file

@ -1,4 +1,5 @@
{% load bookwyrm_tags %}
{% load i18n %}
<div class="block">
{% if status.status_type == 'Review' %}
<div>
@ -12,13 +13,15 @@
{% if status.content_warning %}
<div>
<p>{{ status.content_warning }}</p>
{% include 'snippets/toggle/open_button.html' with text="show more" class="is-small" controls_text="show-status-cw" controls_uid=status.id %}
{% trans "Show more" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text class="is-small" controls_text="show-status-cw" controls_uid=status.id %}
</div>
{% endif %}
<div{% if status.content_warning %} class="hidden" id="show-status-cw-{{ status.id }}"{% endif %}>
{% if status.content_warning %}
{% include 'snippets/toggle/close_button.html' with text="show less" class="is-small" controls_text="show-status-cw" controls_uid=status.id %}
{% trans "Show less" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text class="is-small" controls_text="show-status-cw" controls_uid=status.id %}
{% endif %}
{% if status.quote %}
@ -38,7 +41,7 @@
{% for attachment in status.attachments.all %}
<div class="column is-narrow">
<figure class="image is-128x128">
<a href="/images/{{ attachment.image }}" target="_blank" aria-label="open image in new window">
<a href="/images/{{ attachment.image }}" target="_blank" aria-label="{% trans 'Open image in new window' %}">
<img src="/images/{{ attachment.image }}"{% if attachment.caption %} alt="{{ attachment.caption }}" title="{{ attachment.caption }}"{% endif %}>
</a>
</figure>

View file

@ -1,17 +1,18 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% include 'snippets/avatar.html' with user=status.user %}
{% include 'snippets/username.html' with user=status.user %}
{% if status.status_type == 'GeneratedNote' %}
{{ status.content | safe }}
{% elif status.status_type == 'Review' and not status.name and not status.content%}
rated
{% trans "rated" %}
{% elif status.status_type == 'Review' %}
reviewed
{% trans "reviewed" %}
{% elif status.status_type == 'Comment' %}
commented on
{% trans "commented on" %}
{% elif status.status_type == 'Quotation' %}
quoted
{% trans "quoted" %}
{% elif status.reply_parent %}
{% with parent_status=status|parent %}
replied to {% include 'snippets/username.html' with user=parent_status.user possessive=True %} <a href="{{parent_status.remote_id }}">{% if parent_status.status_type == 'GeneratedNote' %}update{% else %}{{ parent_status.status_type | lower }}{% endif %}</a>

View file

@ -1,9 +1,10 @@
{% extends 'components/dropdown.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block dropdown-trigger %}
<span class="icon icon-dots-three">
<span class="is-sr-only">More options</span>
<span class="is-sr-only">{% trans "More options" %}</span>
</span>
{% endblock %}
@ -13,13 +14,13 @@
<form class="dropdown-item pt-0 pb-0" name="delete-{{status.id}}" action="/delete-status/{{ status.id }}" method="post">
{% csrf_token %}
<button class="button is-danger is-light is-fullwidth is-small" type="submit">
Delete post
{% trans "Delete post" %}
</button>
</form>
</li>
{% else %}
<li role="menuitem">
<a href="/direct-messages/{{ status.user|username }}" class="button is-fullwidth is-small">Send direct message</a>
<a href="/direct-messages/{{ status.user|username }}" class="button is-fullwidth is-small">{% trans "Send direct message" %}</a>
</li>
<li role="menuitem">
{% include 'snippets/block_button.html' with user=status.user class="is-fullwidth" %}

View file

@ -1,5 +1,6 @@
{% load i18n %}
<form name="switch-edition" action="/switch-edition" method="POST">
{% csrf_token %}
<input type="hidden" name="edition" value="{{ edition.id }}">
<button type="submit" class="button {{ size }}">Switch to this edition</button>
<button type="submit" class="button {{ size }}">{% trans "Switch to this edition" %}</button>
</form>

View file

@ -1,3 +1,4 @@
{% load i18n %}
<div class="control">
<form name="tag" action="/{% if tag.tag.identifier in user_tags %}untag{% else %}tag{% endif %}/" method="post">
{% csrf_token %}
@ -10,11 +11,11 @@
</a>
{% if tag.tag.identifier in user_tags %}
<button class="tag is-delete" type="submit">
<span class="is-sr-only">remove tag</span>
<span class="is-sr-only">{% trans "Remove tag" %}</span>
</button>
{% else %}
<button class="tag" type="submit">+
<span class="is-sr-only">add tag</span>
<span class="is-sr-only">{% trans "Add tag" %}</span>
</button>
{% endif %}
</div>

View file

@ -1,4 +1,6 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% with 0|uuid as uuid %}
{% if full %}
{% with full|to_markdown|safe as full %}
@ -7,12 +9,14 @@
{% if trimmed != full %}
<div id="hide-full-{{ uuid }}">
<div class="content" id="trimmed-{{ uuid }}"><span dir="auto">{{ trimmed }}</span>
{% include 'snippets/toggle/open_button.html' with text="show more" controls_text="full" controls_uid=uuid class="is-small" %}
{% trans "Show more" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text controls_text="full" controls_uid=uuid class="is-small" %}
</div>
</div>
<div id="full-{{ uuid }}" class="hidden">
<div class="content"><span dir="auto">{{ full }}</span>
{% include 'snippets/toggle/close_button.html' with text="show less" controls_text="full" controls_uid=uuid class="is-small" %}
{% trans "Show less" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="full" controls_uid=uuid class="is-small" %}
</div>
</div>
{% else %}

View file

@ -1,15 +1,16 @@
{% extends 'components/dropdown.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block dropdown-trigger %}
<span class="icon icon-dots-three">
<span class="is-sr-only">More options</span>
<span class="is-sr-only">{% trans "More options" %}</span>
</span>
{% endblock %}
{% block dropdown-list %}
<li role="menuitem">
<a href="/direct-messages/{{ user|username }}" class="button is-fullwidth is-small">Send direct message</a>
<a href="/direct-messages/{{ user|username }}" class="button is-fullwidth is-small">{% trans "Send direct message" %}</a>
</li>
<li role="menuitem">
{% include 'snippets/block_button.html' with user=user class="is-fullwidth" %}

View file

@ -1,12 +1,14 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block content %}
{% block title %}{{ tag.name }}{% endblock %}
{% block content %}
<div class="block">
<h1 class="title">Books tagged "{{ tag.name }}"</h1>
<h1 class="title">{% blocktrans %}Books tagged "{{ tag.name }}"{% endblocktrans %}</h1>
{% include 'snippets/book_tiles.html' with books=books.all %}
</div>
{% endblock %}

View file

@ -1,7 +1,8 @@
{% extends 'components/inline_form.html' %}
{% load i18n %}
{% block header %}
Create New Shelf
{% trans "Create New Shelf" %}
{% endblock %}
{% block form %}
@ -9,7 +10,7 @@ Create New Shelf
{% csrf_token %}
<input type="hidden" name="user" value="{{ request.user.id }}">
<div class="field">
<label class="label" for="id_name_create">Name:</label>
<label class="label" for="id_name_create">{% trans "Name:" %}</label>
<input type="text" name="name" maxlength="100" class="input" required="true" id="id_name_create">
</div>
@ -18,7 +19,7 @@ Create New Shelf
{% include 'snippets/privacy_select.html' %}
</div>
<div class="control">
<button class="button is-primary" type="submit">Create shelf</button>
<button class="button is-primary" type="submit">{% trans "Create shelf" %}</button>
</div>
</div>
</form>

View file

@ -1,7 +1,8 @@
{% extends 'components/inline_form.html' %}
{% load i18n %}
{% block header %}
Edit Shelf
{% trans "Edit Shelf" %}
{% endblock %}
{% block form %}
@ -10,7 +11,7 @@ Edit Shelf
<input type="hidden" name="user" value="{{ request.user.id }}">
{% if shelf.editable %}
<div class="field">
<label class="label" for="id_name">Name:</label>
<label class="label" for="id_name">{% trans "Name:" %}</label>
<input type="text" name="name" maxlength="100" class="input" required="true" value="{{ shelf.name }}" id="id_name">
</div>
{% else %}
@ -22,7 +23,7 @@ Edit Shelf
{% include 'snippets/privacy_select.html' with current=shelf.privacy %}
</div>
<div class="control">
<button class="button is-primary" type="submit">Update shelf</button>
<button class="button is-primary" type="submit">{% trans "Update shelf" %}</button>
</div>
</div>
</form>

View file

@ -1,19 +1,16 @@
{% extends 'user/user_layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block header %}
<h1 class="title">
{% if is_self %}Your
{% else %}
{% include 'snippets/username.html' with user=user possessive=True %}
{% endif %}
followers
{% trans "User Profile" %}
</h1>
{% endblock %}
{% block panel %}
<div class="block">
<h2 class="title">Followers</h2>
<h2 class="title">{% trans "Followers" %}</h2>
{% for followers in followers %}
<div class="block columns">
<div class="column">
@ -26,7 +23,7 @@
</div>
{% endfor %}
{% if not followers.count %}
<div>{{ user|username }} has no followers</div>
<div>{% blocktrans with username=user|username %}{{ username }} has no followers{% endblocktrans %}</div>
{% endif %}
</div>
{% endblock %}

View file

@ -1,19 +1,16 @@
{% extends 'user/user_layout.html' %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block header %}
<h1 class="title">
Users following
{% if is_self %}you
{% else %}
{% include 'snippets/username.html' with user=user %}
{% endif %}
{% trans "User Profile" %}
</h1>
{% endblock %}
{% block panel %}
<div class="block">
<h2 class="title">Following</h2>
<h2 class="title">{% trans "Following" %}</h2>
{% for follower in user.following.all %}
<div class="block columns">
<div class="column">
@ -26,7 +23,7 @@
</div>
{% endfor %}
{% if not following.count %}
<div>{{ user|username }} isn't following any users</div>
<div>{% blocktrans with username=user|username %}{{ username }} isn't following any users{% endblocktrans %}</div>
{% endif %}
</div>
{% endblock %}

View file

@ -1,19 +1,21 @@
{% extends 'user/user_layout.html' %}
{% load i18n %}
{% block header %}
<div class="columns is-mobile">
<div class="column">
<h1 class="title">
{% if is_self %}Your
{% if is_self %}
{% trans "Your Lists" %}
{% else %}
{% include 'snippets/username.html' with user=user %}'s
{% blocktrans with username=user.display_name %}Lists: {{ username }}{% endblocktrans %}
{% endif %}
Lists
</h1>
</div>
{% if is_self %}
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with controls_text="create-list" icon="plus" text="Create new list" %}
{% trans "Create new list" as button_text %}
{% include 'snippets/toggle/open_button.html' with controls_text="create-list" icon="plus" text=button_text %}
</div>
{% endif %}
</div>
@ -24,7 +26,7 @@
<section class="block content">
<form name="create-list" method="post" action="{% url 'lists' %}" class="box hidden" id="create-list">
<header class="columns">
<h3 class="title column">Create list</h3>
<h3 class="title column">{% trans "Create list" %}</h3>
<div class="column is-narrow">
{% include 'snippets/toggle/toggle_button.html' with controls_text="create-list" label="close" class="delete" nonbutton=True %}
</div>

View file

@ -1,14 +1,15 @@
{% extends 'user/user_layout.html' %}
{% load bookwyrm_tags %}
{% load i18n %}
{% block header %}
<header class="columns">
<h1 class="title">
{% if is_self %}Your
{% if is_self %}
{% trans "Your Shelves" %}
{% else %}
{% include 'snippets/username.html' with user=user possessive=True %}
{% blocktrans with username=user.display_name %}{{ username }}: Shelves{% endblocktrans %}
{% endif %}
shelves
</h1>
</header>
{% endblock %}
@ -16,11 +17,11 @@
{% block panel %}
<div class="block columns">
<div class="column">
<div class="tabs" role="tablist">
<div class="tabs">
<ul>
{% for shelf_tab in shelves %}
<li class="{% if shelf_tab.identifier == shelf.identifier %}is-active{% endif %}">
<a href="/user/{{ user | username }}/shelf/{{ shelf_tab.identifier }}" role="tab" aria-selected="{% if shelf_tab.identifier == shelf.identifier %}true{% else %}false{% endif %}">{{ shelf_tab.name }}</a>
<a href="/user/{{ user | username }}/shelf/{{ shelf_tab.identifier }}"{% if shelf_tab.identifier == shelf.identifier %} aria-current="page"{% endif %}>{{ shelf_tab.name }}</a>
</li>
{% endfor %}
</ul>
@ -29,7 +30,8 @@
{% if is_self %}
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with text="Create shelf" icon="plus" controls_text="create-shelf-form" focus="create-shelf-form-header" %}
{% trans "Create shelf" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text icon="plus" controls_text="create-shelf-form" focus="create-shelf-form-header" %}
</div>
{% endif %}
</div>
@ -49,7 +51,8 @@
</div>
{% if is_self %}
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with text="Edit shelf" icon="pencil" controls_text="edit-shelf-form" focus="edit-shelf-form-header" %}
{% trans "Edit shelf" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text icon="pencil" controls_text="edit-shelf-form" focus="edit-shelf-form-header" %}
</div>
{% endif %}
</div>

View file

@ -1,15 +1,18 @@
{% extends 'user/user_layout.html' %}
{% load i18n %}
{% block title %}{{ user.name }}{% endblock %}
{% block header %}
<div class="columns is-mobile">
<div class="column">
<h1 class="title">User profile</h1>
<h1 class="title">{% trans "User Profile" %}</h1>
</div>
{% if is_self %}
<div class="column is-narrow">
<a href="/preferences/profile">
<span class="icon icon-pencil" title="Edit profile">
<span class="is-sr-only">Edit profile</span>
<span class="is-sr-only">{% trans "Edit profile" %}</span>
</span>
</a>
</div>
@ -20,12 +23,12 @@
{% block panel %}
{% if user.bookwyrm_user %}
<div class="block">
<h2 class="title">Shelves</h2>
<h2 class="title">{% trans "Shelves" %}</h2>
<div class="columns">
{% for shelf in shelves %}
<div class="column is-narrow">
<h3>{{ shelf.name }}
{% if shelf.size > 3 %}<small>(<a href="{{ shelf.local_path }}">See all {{ shelf.size }}</a>)</small>{% endif %}</h3>
{% if shelf.size > 3 %}<small>(<a href="{{ shelf.local_path }}">{% blocktrans with size=shelf.size %}See all {{ size }}{% endblocktrans %}</a>)</small>{% endif %}</h3>
<div class="is-mobile field is-grouped">
{% for book in shelf.books %}
<div class="control">
@ -38,7 +41,7 @@
</div>
{% endfor %}
</div>
<small><a href="{{ user.local_path }}/shelves">See all {{ shelf_count }} shelves</a></small>
<small><a href="{{ user.local_path }}/shelves">{% blocktrans %}See all {{ shelf_count }} shelves{% endblocktrans %}</a></small>
</div>
{% endif %}
@ -49,16 +52,17 @@
</div>
{% elif user == request.user %}
<div class="block">
<h2 class="title is-4"><a href="{{ user.local_path }}/goal/{% now 'Y' %}">Set a reading goal for {% now 'Y' %}</a></h2>
{% now 'Y' as year %}
<h2 class="title is-4"><a href="{{ user.local_path }}/goal/{{ year }}">{% blocktrans %}Set a reading goal for {{ year }}{% endblocktrans %}</a></h2>
</div>
{% endif %}
<div>
<div class="columns is-mobile">
<h2 class="title column">User Activity</h2>
<h2 class="title column">{% trans "User Activity" %}</h2>
<div class="column is-narrow">
<a class="icon icon-rss" target="_blank" href="{{ user.local_path }}/rss">
<span class="is-sr-only">RSS feed</span>
<span class="is-sr-only">{% trans "RSS feed" %}</span>
</a>
</div>
</div>
@ -69,7 +73,7 @@
{% endfor %}
{% if not activities %}
<div class="block">
<p>No activities yet!</a>
<p>{% trans "No activities yet!" %}</a>
</div>
{% endif %}

Some files were not shown because too many files have changed in this diff Show more