Merge branch 'upstream' into tab-keyboard-accessibility

This commit is contained in:
Ned Zimmerman
2021-02-27 11:53:27 -04:00
218 changed files with 7197 additions and 3530 deletions

View File

@ -1,16 +0,0 @@
{% extends 'layout.html' %}
{% block content %}
<div class="columns">
<div class="column block">
{% include 'snippets/about.html' %}
</div>
<div class="column block">
<h2 class="title">Code of Conduct</h2>
<div class="content">
{{ site.code_of_conduct | safe }}
</div>
</div>
</div>
{% endblock %}

View File

@ -2,7 +2,7 @@
{% load bookwyrm_tags %}
{% block content %}
<div class="block">
<div class="columns">
<div class="columns is-mobile">
<div class="column">
<h1 class="title">{{ author.name }}</h1>
</div>

View File

@ -4,7 +4,7 @@
{% block content %}
<div class="block">
<div class="columns">
<div class="columns is-mobile">
<div class="column">
<h1 class="title">
{{ book.title }}{% if book.subtitle %}:
@ -35,33 +35,17 @@
<div class="column is-narrow">
{% include 'snippets/book_cover.html' with book=book size=large %}
{% include 'snippets/rate_action.html' with user=request.user book=book %}
{% include 'snippets/shelve_button.html' %}
{% include 'snippets/shelve_button/shelve_button.html' %}
{% if request.user.is_authenticated and not book.cover %}
<div class="box p-2">
<h3 class="title is-6 mb-1">Add cover</h3>
<form name="add-cover" method="POST" action="/upload-cover/{{ book.id }}" enctype="multipart/form-data">
{% csrf_token %}
<div class="field has-addons">
<div class="control">
<div class="file is-small mb-1">
<label class="file-label">
<input class="file-input" type="file" name="cover" accept="image/*" enctype="multipart/form-data" id="id_cover" required>
<span class="file-cta">
<span class="file-icon">
<i class="fas fa-upload"></i>
</span>
<span class="file-label">
Choose file...
</span>
</span>
</label>
</div>
</div>
<div class="control">
<button class="button is-small is-primary" type="submit">Add</button>
</div>
</div>
<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>
</form>
</div>
{% endif %}
@ -103,7 +87,7 @@
<div class="column">
<div class="block">
<h3 class="field is-grouped">{% include 'snippets/stars.html' with rating=rating %} ({{ review_count }} review{{ reviews|length|pluralize }})</h3>
<h3 class="field is-grouped">{% include 'snippets/stars.html' with rating=rating %} ({{ review_count }} review{{ review_count|pluralize }})</h3>
{% include 'snippets/trimmed_text.html' with full=book|book_description %}
@ -147,7 +131,7 @@
{% endfor %}
</div>
{% if readthroughs.exists %}
{% if request.user.is_authenticated %}
<section class="block">
<header class="columns">
<h2 class="column title is-5 mb-1">Your reading activity</h2>
@ -155,6 +139,9 @@
{% include 'snippets/toggle/open_button.html' with text="Add read dates" 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>
{% 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 %}
@ -221,6 +208,17 @@
</ul>
</section>
{% endif %}
{% if lists.exists %}
<section class="content block">
<h2 class="title is-5">Lists</h2>
<ul>
{% for list in lists %}
<li><a href="{{ list.local_path }}">{{ list.name }}</a></li>
{% endfor %}
</ul>
</section>
{% endif %}
</div>
</div>
</div>
@ -228,7 +226,7 @@
<div class="block" id="reviews">
{% for review in reviews %}
<div class="block">
{% include 'snippets/status.html' with status=review hide_book=True depth=1 %}
{% include 'snippets/status/status.html' with status=review hide_book=True depth=1 %}
</div>
{% endfor %}

View File

@ -0,0 +1,13 @@
<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 %}
</span>
</header>
<section class="card-content content">
{% block form %}{% endblock %}
</section>
</section>

View File

@ -8,15 +8,17 @@
{% include 'snippets/toggle/toggle_button.html' with label="close" class="delete" nonbutton=True %}
</header>
{% block modal-form-open %}{% endblock %}
{% if not no_body %}
<section class="modal-card-body">
{% block modal-body %}{% endblock %}
</section>
{% endif %}
<footer class="modal-card-foot">
{% block modal-footer %}{% endblock %}
</footer>
{% block modal-form-close %}{% endblock %}
</div>
<label class="modal-close is-large" for="{{ controls_text }}-{{ readthrough.id }}" aria-label="close"></label>
<label class="modal-close is-large" for="{{ controls_text }}-{{ controls_uid }}" aria-label="close"></label>
{% include 'snippets/toggle/toggle_button.html' with label="close" class="modal-close is-large" nonbutton=True %}
</div>

View File

@ -1,19 +0,0 @@
{% extends 'layout.html' %}
{% block content %}
<div class="block">
<h1 class="title">Direct Messages</h1>
{% if not activities %}
<p>You have no messages right now.</p>
{% endif %}
{% for activity in activities %}
<div class="block">
{% include 'snippets/status.html' with status=activity %}
</div>
{% endfor %}
{% include 'snippets/pagination.html' with page=activities path="direct-messages" %}
</div>
{% endblock %}

View File

@ -0,0 +1,22 @@
{% extends 'layout.html' %}
{% 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="block">
{% include 'snippets/about.html' %}
</section>
<div class="block">
<h2 class="title">Code of Conduct</h2>
<div class="content">
{{ site.code_of_conduct | safe }}
</div>
</div>
{% endblock %}

View File

@ -1,11 +1,14 @@
{% extends 'layout.html' %}
{% block content %}
{% if not request.user.is_authenticated %}
<div class="block">
<h1 class="title has-text-centered">{{ site.name }}: {{ site.instance_tagline }}</h1>
</div>
<header class="block has-text-centered">
<h1 class="title">{{ site.name }}</h1>
<h2 class="subtitle">{{ site.instance_tagline }}</h2>
</header>
{% include 'discover/icons.html' %}
{% if not request.user.is_authenticated %}
<section class="tile is-ancestor">
<div class="tile is-7 is-parent">
<div class="tile is-child box">
@ -26,10 +29,7 @@
</div>
</div>
</section>
{% else %}
<div class="block">
<h1 class="title has-text-centered">Discover</h1>
</div>
{% endif %}
<div class="block is-hidden-tablet">
@ -40,18 +40,18 @@
<div class="tile is-vertical">
<div class="tile is-parent">
<div class="tile is-child box has-background-white-ter">
{% include 'snippets/discover/large-book.html' with book=books.0 %}
{% include 'discover/large-book.html' with book=books.0 %}
</div>
</div>
<div class="tile">
<div class="tile is-parent is-6">
<div class="tile is-child box has-background-white-ter">
{% include 'snippets/discover/small-book.html' with book=books.1 %}
{% include 'discover/small-book.html' with book=books.1 %}
</div>
</div>
<div class="tile is-parent is-6">
<div class="tile is-child box has-background-white-ter">
{% include 'snippets/discover/small-book.html' with book=books.2 %}
{% include 'discover/small-book.html' with book=books.2 %}
</div>
</div>
</div>
@ -60,18 +60,18 @@
<div class="tile">
<div class="tile is-parent is-6">
<div class="tile is-child box has-background-white-ter">
{% include 'snippets/discover/small-book.html' with book=books.3 %}
{% include 'discover/small-book.html' with book=books.3 %}
</div>
</div>
<div class="tile is-parent is-6">
<div class="tile is-child box has-background-white-ter">
{% include 'snippets/discover/small-book.html' with book=books.4 %}
{% include 'discover/small-book.html' with book=books.4 %}
</div>
</div>
</div>
<div class="tile is-parent">
<div class="tile is-child box has-background-white-ter">
{% include 'snippets/discover/large-book.html' with book=books.5 %}
{% include 'discover/large-book.html' with book=books.5 %}
</div>
</div>
</div>

View File

@ -0,0 +1,21 @@
<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

@ -2,8 +2,8 @@
{% if book %}
<div class="columns">
<div class="column is-narrow">
{% include 'snippets/book_cover.html' with book=book size="large" %}
{% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %}
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book size="large" %}</a>
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
</div>
<div class="column">
<h3 class="title is-5"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>

View File

@ -1,9 +1,7 @@
{% load bookwyrm_tags %}
{% if book %}
{% include 'snippets/book_cover.html' with book=book %}
{% if ratings %}
{% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %}
{% endif %}
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book %}</a>
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
<h3 class="title is-6"><a href="/book/{{ book.id }}">{{ book.title }}</a></h3>
{% if book.authors %}

View File

@ -62,7 +62,7 @@
<div class="column is-narrow">
<div class="block">
<h2 class="title is-4">Cover</h2>
<p>{{ form.cover }} </p>
<p>{{ form.cover }}</p>
{% for error in form.cover.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}

View File

@ -1,66 +0,0 @@
{% extends 'layout.html' %}
{% block content %}
<div class="block columns">
<div class="column is-half">
<h1 class="title">Profile</h1>
{% if form.non_field_errors %}
<p class="notification is-danger">{{ form.non_field_errors }}</p>
{% endif %}
<form name="edit-profile" action="/edit-profile/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="block">
<label class="label" for="id_avatar">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>
{{ 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>
{{ 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>
{{ form.email }}
{% for error in form.email.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="block">
<label class="checkbox label" for="id_manually_approves_followers">
Manually approve followers:
{{ form.manually_approves_followers }}
</label>
</div>
<button class="button is-primary" type="submit">Save</button>
</form>
</div>
<div class="column is-half">
<div class="block">
<h2 class="title">Change password</h2>
<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>
<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>
<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>
</form>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,26 @@
{% extends 'feed/feed_layout.html' %}
{% 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 %}
</header>
<div class="box">
{% include 'snippets/create_status_form.html' with type="direct" uuid=1 mentions=partner %}
</div>
<section class="block">
{% if not activities %}
<p>You have no messages right now.</p>
{% endif %}
{% for activity in activities %}
<div class="block">
{% include 'snippets/status/status.html' with status=activity %}
</div>
{% endfor %}
{% include 'snippets/pagination.html' with page=activities path="direct-messages" %}
</section>
{% endblock %}

View File

@ -0,0 +1,39 @@
{% extends 'feed/feed_layout.html' %}
{% load bookwyrm_tags %}
{% block panel %}
<h1 class="title">{{ tab | title }} Timeline</h1>
<div class="tabs">
<ul>
<li class="{% if tab == 'home' %}is-active{% endif %}">
<a href="/#feed">Home</a>
</li>
<li class="{% if tab == 'local' %}is-active{% endif %}">
<a href="/local#feed">Local</a>
</li>
<li class="{% if tab == 'federated' %}is-active{% endif %}">
<a href="/federated#feed">Federated</a>
</li>
</ul>
</div>
{# 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">
{% include 'snippets/goal_card.html' with year=year %}
<hr>
</section>
{% endif %}
{# activity feed #}
{% if not activities %}
<p>There aren't any activities right now! Try following a user to get started</p>
{% endif %}
{% for activity in activities %}
<div class="block">
{% include 'snippets/status/status.html' with status=activity %}
</div>
{% endfor %}
{% endblock %}

View File

@ -3,6 +3,7 @@
{% block content %}
<div class="columns">
{% if user.is_authenticated %}
<div class="column is-one-third">
<h2 class="title is-5">Your books</h2>
{% if not suggested_books %}
@ -48,12 +49,12 @@
</div>
</div>
<div class="card-content">
{% include 'snippets/shelve_button.html' with book=book %}
{% active_shelf book as active_shelf %}
{% if active_shelf.shelf.identifier == 'reading' and book.latest_readthrough %}
{% include 'snippets/progress_update.html' with readthrough=book.latest_readthrough %}
{% endif %}
{% include 'snippets/create_status.html' with book=book %}
{% include 'snippets/shelve_button/shelve_button.html' with book=book %}
{% active_shelf book as active_shelf %}
{% if active_shelf.shelf.identifier == 'reading' and book.latest_readthrough %}
{% include 'snippets/progress_update.html' with readthrough=book.latest_readthrough %}
{% endif %}
{% include 'snippets/create_status.html' with book=book %}
</div>
</div>
{% endfor %}
@ -71,43 +72,15 @@
</section>
{% endif %}
</div>
{% endif %}
<div class="column is-two-thirds" id="feed">
<h1 class="title">{{ tab | title }} Timeline</h1>
<div class="tabs">
<ul>
<li class="{% if tab == 'home' %}is-active{% endif %}">
<a href="/#feed">Home</a>
</li>
<li class="{% if tab == 'local' %}is-active{% endif %}">
<a href="/local#feed">Local</a>
</li>
<li class="{% if tab == 'federated' %}is-active{% endif %}">
<a href="/federated#feed">Federated</a>
</li>
</ul>
</div>
{% block panel %}{% endblock %}
{# 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">
{% include 'snippets/goal_card.html' with year=year %}
<hr>
</section>
{% if activities %}
{% include 'snippets/pagination.html' with page=activities path=path anchor="#feed" %}
{% endif %}
{# activity feed #}
{% if not activities %}
<p>There aren't any activities right now! Try following a user to get started</p>
{% endif %}
{% for activity in activities %}
<div class="block">
{% include 'snippets/status.html' with status=activity %}
</div>
{% endfor %}
{% include 'snippets/pagination.html' with page=activities path='/'|add:tab anchor="#feed" %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,13 @@
{% extends 'feed/feed_layout.html' %}
{% 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>
</a>
</header>
{% include 'feed/thread.html' with status=status depth=0 max_depth=6 is_root=True direction=0 %}
{% endblock %}

View File

@ -4,16 +4,16 @@
{% with depth=depth|add:1 %}
{% if depth <= max_depth and status.reply_parent and direction <= 0 %}
{% with direction=-1 %}
{% include 'snippets/thread.html' with status=status|parent is_root=False %}
{% include 'feed/thread.html' with status=status|parent is_root=False %}
{% endwith %}
{% endif %}
{% include 'snippets/status.html' with status=status main=is_root %}
{% include 'snippets/status/status.html' with status=status main=is_root %}
{% if depth <= max_depth and direction >= 0 %}
{% for reply in status|replies %}
{% with direction=1 %}
{% include 'snippets/thread.html' with status=reply is_root=False %}
{% include 'feed/thread.html' with status=reply is_root=False %}
{% endwith %}
{% endfor %}
{% endif %}

View File

@ -1,38 +0,0 @@
{% extends 'layout.html' %}
{% load bookwyrm_tags %}
{% block content %}
<div class="block">
<h1 class="title">
{% if is_self %}Your
{% else %}
{% include 'snippets/username.html' with user=user possessive=True %}
{% endif %}
followers
</h1>
</div>
{% include 'snippets/user_header.html' with user=user %}
<div class="block">
<h2 class="title">Followers</h2>
{% for followers in followers %}
<div class="block">
<div class="field is-grouped">
<div class="control">
{% include 'snippets/avatar.html' with user=followers %}
</div>
<div class="control">
{% include 'snippets/username.html' with user=followers show_full=True %}
</div>
<div class="control">
{% include 'snippets/follow_button.html' with user=followers %}
</div>
</div>
</div>
{% endfor %}
{% if not followers.count %}
<div>{{ user|username }} has no followers</div>
{% endif %}
</div>
{% endblock %}

View File

@ -1,38 +0,0 @@
{% extends 'layout.html' %}
{% load bookwyrm_tags %}
{% block content %}
<div class="block">
<h1 class="title">
Users following
{% if is_self %}you
{% else %}
{% include 'snippets/username.html' with user=user %}
{% endif %}
</h1>
</div>
{% include 'snippets/user_header.html' with user=user %}
<div class="block">
<h2 class="title">Following</h2>
{% for follower in user.following.all %}
<div class="block">
<div class="field is-grouped">
<div class="control">
{% include 'snippets/avatar.html' with user=follower %}
</div>
<div class="control">
{% include 'snippets/username.html' with user=follower show_full=True %}
</div>
<div class="control">
{% include 'snippets/follow_button.html' with user=follower %}
</div>
</div>
</div>
{% endfor %}
{% if not following.count %}
<div>{{ user|username }} isn't following any users</div>
{% endif %}
</div>
{% endblock %}

View File

@ -1,13 +1,22 @@
{% extends 'layout.html' %}
{% block content %}
{% extends 'user/user_layout.html' %}
{% block header %}
<div class="columns is-mobile">
<div class="column">
<h1 class="title">{{ year }} Reading Progress</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" %}
</div>
{% endif %}
</div>
{% endblock %}
{% block panel %}
<section class="block">
<h1 class="title">{{ year }} Reading Progress</h1>
{% if user == request.user %}
<div class="block">
{% if goal %}
{% include 'snippets/toggle/open_button.html' with text="Edit goal" controls_text="show-edit-goal" focus="edit-form-header" %}
{% endif %}
{% now 'Y' as year %}
<section class="card {% if goal %}hidden{% endif %}" id="show-edit-goal">
<header class="card-header">
@ -34,14 +43,14 @@
</section>
{% if goal.books %}
<section>
<h2 class="title">{% if goal.user == request.user %}Your{% else %}{{ goal.user.display_name }}'s{% endif %} {{ year }} Books</h2>
<section class="content">
<h2>{% if goal.user == request.user %}Your{% else %}{{ goal.user.display_name }}'s{% endif %} {{ year }} Books</h2>
<div class="columns is-multiline">
{% for book in goal.books %}
<div class="column is-narrow">
<div class="box">
<a href="{{ book.book.local_path }}">
{% include 'snippets/discover/small-book.html' with book=book.book rating=goal.ratings %}
{% include 'discover/small-book.html' with book=book.book rating=goal.ratings %}
</a>
</div>
</div>

View File

@ -53,12 +53,15 @@
<div class="navbar-menu" id="main-nav">
<div class="navbar-start">
{% if request.user.is_authenticated %}
<a href="/user/{{ request.user.localname }}/shelves" class="navbar-item">
<a href="{% url 'user-shelves' request.user.localname %}" class="navbar-item">
Your shelves
</a>
<a href="/#feed" class="navbar-item">
Feed
</a>
<a href="{% url 'lists' %}" class="navbar-item">
Lists
</a>
{% endif %}
</div>
@ -81,7 +84,7 @@
</a>
</li>
<li>
<a href="/edit-profile" class="navbar-item">
<a href="/preferences/profile" class="navbar-item">
Settings
</a>
</li>
@ -90,13 +93,23 @@
Import books
</a>
</li>
{% if perms.bookwyrm.create_invites or perms.bookwyrm.edit_instance_settings%}
<hr class="navbar-divider">
{% endif %}
{% if perms.bookwyrm.create_invites %}
<li>
<a href="/invite" class="navbar-item">
<a href="{% url 'settings-invites' %}" class="navbar-item">
Invites
</a>
</li>
{% endif %}
{% if perms.bookwyrm.edit_instance_settings %}
<li>
<a href="{% url 'settings-site' %}" class="navbar-item">
Site Configuration
</a>
</li>
{% endif %}
<hr class="navbar-divider">
<li>
<a href="/logout" class="navbar-item">

View File

@ -0,0 +1,11 @@
{% extends 'components/inline_form.html' %}
{% block header %}
Create List
{% endblock %}
{% block form %}
<form name="create-list" method="post" action="{% url 'lists' %}">
{% include 'lists/form.html' %}
</form>
{% endblock %}

View File

@ -0,0 +1,49 @@
{% extends 'lists/list_layout.html' %}
{% block panel %}
<section class="content block">
<h2>Pending Books</h2>
<p><a href="{% url 'list' list.id %}">Go to list</a></p>
{% if not pending.exists %}
<p>You're all set!</p>
{% else %}
<table class="table is-striped">
<tr>
<th></th>
<th>Book</th>
<th>Suggested by</th>
<th></th>
</tr>
{% for item in pending %}
<tr>
<td>
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=item.book size="small" %}</a>
</td>
<td>
{% include 'snippets/book_titleby.html' with book=item.book %}
</td>
<td>
{% include 'snippets/username.html' with user=item.user %}
</td>
<td>
<div class="field has-addons">
<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="true">
<button class="button">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>
</div>
</form>
</td>
</tr>
{% endfor %}
</table>
{% endif %}
</section>
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'components/inline_form.html' %}
{% block header %}
Edit List
{% endblock %}
{% block form %}
<form name="edit-list" method="post" action="{% url 'list' list.id %}">
{% include 'lists/form.html' %}
</form>
{% endblock %}

View File

@ -0,0 +1,44 @@
{% 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>
{{ list_form.name }}
</div>
<div class="field">
<label class="label" for="id_description">Description:</label>
{{ list_form.description }}
</div>
</div>
<div class="column">
<fieldset class="field">
<legend class="label">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>
</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>
</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>
</label>
</fieldset>
</div>
</div>
<div class="field has-addons">
<div class="control">
{% include 'snippets/privacy_select.html' with current=list.privacy %}
</div>
<div class="control">
<button type="submit" class="button is-primary">Save</button>
</div>
</div>

View File

@ -0,0 +1,94 @@
{% extends 'lists/list_layout.html' %}
{% load bookwyrm_tags %}
{% block panel %}
{% if request.user == list.user and pending_count %}
<div class="block content">
<p>
<a href="{% url 'list-curate' list.id %}">{{ pending_count }} book{{ pending_count | pluralize }} awaiting your approval</a>
</p>
</div>
{% endif %}
<div class="columns mt-3">
<section class="column is-three-quarters">
{% if not items.exists %}
<p>This list is currently empty</p>
{% else %}
<ol>
{% for item in items %}
<li class="block pb-3">
<div class="card">
<div class="card-content columns p-0 mb-0 is-mobile">
<div class="column is-narrow pt-0 pb-0">
<a href="{{ item.book.local_path }}">{% include 'snippets/book_cover.html' with book=item.book size="medium" %}</a>
</div>
<div class="column is-flex-direction-column is-align-items-self-start">
<span>{% include 'snippets/book_titleby.html' with book=item.book %}</span>
{% include 'snippets/stars.html' with rating=item.book|rating:request.user %}
{% include 'snippets/shelve_button/shelve_button.html' with book=item.book %}
</div>
</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>
</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>
</form>
{% endif %}
</div>
</div>
</li>
{% endfor %}
</ol>
{% endif %}
</section>
{% 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>
<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 }}">
</div>
<div class="control">
<button class="button" type="submit">
<span class="icon icon-search" title="Search">
<span class="is-sr-only">search</span>
</span>
</button>
</div>
</div>
{% if query %}
<p class="help"><a href="{% url 'list' list.id %}">Clear search</a></p>
{% endif %}
</form>
{% if not suggested_books %}
<p>No books found{% if query %} matching the query "{{ query }}"{% endif %}</p>
{% endif %}
{% for book in suggested_books %}
{% if book %}
<div class="block columns is-mobile">
<div class="column is-narrow">
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book size="small" %}</a>
</div>
<div class="column">
<p>{% include 'snippets/book_titleby.html' with book=book %}</p>
<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>
</form>
</div>
</div>
{% endif %}
{% endfor %}
</section>
{% endif %}
</div>
{% endblock %}

View File

@ -0,0 +1,23 @@
{% load bookwyrm_tags %}
<div class="columns is-multiline">
{% for list in lists %}
<div class="column is-one-quarter">
<div class="card">
<header class="card-header">
<h4 class="card-header-title">
<a href="{{ list.local_path }}">{{ list.name }}</a> <span class="subtitle">{% include 'snippets/privacy-icons.html' with item=list %}</span>
</h4>
</header>
<div class="card-image is-flex is-clipped">
{% for book in list.listitem_set.all|slice:5 %}
<a href="{{ book.book.local_path }}">{% include 'snippets/book_cover.html' with book=book.book size="small" %}</a>
{% endfor %}
</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>
</div>
</div>
</div>
{% endfor %}
</div>

View File

@ -0,0 +1,24 @@
{% extends 'layout.html' %}
{% load bookwyrm_tags %}
{% 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>
{% 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" %}
</div>
{% endif %}
</header>
<div class="block">
{% include 'lists/edit_form.html' with controls_text="edit-list" %}
</div>
{% block panel %}{% endblock %}
{% endblock %}

View File

@ -0,0 +1,43 @@
{% extends 'layout.html' %}
{% block content %}
<header class="block">
<h1 class="title">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>
</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" %}
</div>
</header>
<div class="block">
{% include 'lists/create_form.html' with controls_text="create-list" %}
</div>
<section class="block content">
{% if request.user.list_set.exists %}
{% include 'lists/list_items.html' with lists=request.user.list_set.all|slice:4 %}
{% endif %}
{% if request.user.list_set.count > 4 %}
<a href="{% url 'user-lists' request.user.localname %}">See all {{ request.user.list_set.count}} lists</a>
{% endif %}
</section>
{% endif %}
{% if lists %}
<section class="block content">
<h2 class="title">Recent Lists</h2>
{% include 'lists/list_items.html' with lists=lists %}
</section>
<div>
{% include 'snippets/pagination.html' with page=lists path=path %}
</div>
{% endif %}
{% endblock %}

View File

@ -29,6 +29,8 @@
<span class="icon icon-heart"></span>
{% elif notification.notification_type == 'IMPORT' %}
<span class="icon icon-list"></span>
{% elif notification.notification_type == 'ADD' %}
<span class="icon icon-plus"></span>
{% endif %}
</div>
<div class="column">
@ -36,33 +38,34 @@
<p>
{# DESCRIPTION #}
{% if notification.related_user %}
{% 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>
{% 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>
{% elif notification.notification_type == 'MENTION' %}
mentioned you in a
<a href="{{ related_status.local_path }}">{{ related_status | status_preview_name|safe }}</a>
{% elif notification.notification_type == 'MENTION' %}
mentioned you in a
<a href="{{ related_status.local_path }}">{{ related_status | status_preview_name|safe }}</a>
{% 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>
{% elif notification.notification_type == 'FOLLOW' %}
followed you
{% include 'snippets/follow_button.html' with user=notification.related_user %}
{% elif notification.notification_type == 'FOLLOW_REQUEST' %}
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>
{% endif %}
{% else %}
{% 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>
{% elif notification.notification_type == 'FOLLOW' %}
followed you
{% include 'snippets/follow_button.html' with user=notification.related_user %}
{% elif notification.notification_type == 'FOLLOW_REQUEST' %}
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>
{% 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>"
{% endif %}
{% elif notification.related_import %}
your <a href="/import/{{ notification.related_import.id }}">import</a> completed.
{% endif %}
</p>

View File

@ -0,0 +1,24 @@
{% extends 'preferences/preferences_layout.html' %}
{% block header %}
Blocked Users
{% endblock %}
{% block panel %}
{% if not request.user.blocks.exists %}
<p>No users currently blocked.</p>
{% else %}
<ul>
{% for user in request.user.blocks.all %}
<li class="is-flex">
<p>
{% include 'snippets/avatar.html' with user=user %} {% include 'snippets/username.html' with user=user %}
</p>
<p class="mr-2">
{% include 'snippets/block_button.html' with user=user %}
</p>
</li>
{% endfor %}
</ul>
{% endif %}
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends 'preferences/preferences_layout.html' %}
{% block header %}
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>
<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>
<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>
</form>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends 'preferences/preferences_layout.html' %}
{% block header %}
Edit Profile
{% endblock %}
{% block panel %}
{% if form.non_field_errors %}
<p class="notification is-danger">{{ form.non_field_errors }}</p>
{% endif %}
<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>
{{ 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>
{{ 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>
{{ 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>
{{ form.email }}
{% for error in form.email.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="block">
<label class="checkbox label" for="id_manually_approves_followers">
Manually approve followers:
{{ form.manually_approves_followers }}
</label>
</div>
<button class="button is-primary" type="submit">Save</button>
</form>
{% endblock %}

View File

@ -0,0 +1,31 @@
{% extends 'layout.html' %}
{% block content %}
<header class="block column is-offset-one-quarter pl-1">
<h1 class="title">{% block header %}{% endblock %}</h1>
</header>
<div class="block columns">
<nav class="menu column is-one-quarter">
<h2 class="menu-label">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>
</li>
<li>
<a href="/preferences/password"{% if '/preferences/password' in request.path %} class="is-active" aria-selected="true"{% endif %}>Change password</a>
</li>
</ul>
<h2 class="menu-label">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>
</li>
</ul>
</nav>
<div class="column content">
{% block panel %}{% endblock %}
</div>
</div>
{% endblock %}

View File

@ -22,7 +22,8 @@
{% endif %}
</section>
{% if book_results|slice:":1" and local_results.results and request.user.is_authenticated %}
{% if request.user.is_authenticated %}
{% if book_results|slice:":1" and local_results.results %}
<div class="block">
<p>
Didn't find what you were looking for?
@ -61,19 +62,39 @@
{% include 'snippets/toggle/close_button.html' with text="Hide results from other catalogues" small=True controls_text="more-results" %}
{% endif %}
</div>
{% endif %}
</div>
<div class="column">
<h2 class="title">Matching Users</h2>
{% if not user_results %}
<p>No users found for "{{ query }}"</p>
{% endif %}
{% for result in user_results %}
<div class="block">
{% include 'snippets/avatar.html' with user=result %}</h2>
{% include 'snippets/username.html' with user=result show_full=True %}</h2>
{% include 'snippets/follow_button.html' with user=result %}
</div>
{% endfor %}
<section class="block">
<h2 class="title">Matching Users</h2>
{% if not user_results %}
<p>No users found for "{{ query }}"</p>
{% endif %}
<ul>
{% for result in user_results %}
<li class="block">
{% include 'snippets/avatar.html' with user=result %}</h2>
{% include 'snippets/username.html' with user=result show_full=True %}</h2>
{% include 'snippets/follow_button.html' with user=result %}
</li>
{% endfor %}
</ul>
</section>
<section class="block">
<h2 class="title">Lists</h2>
{% if not list_results %}
<p>No lists found for "{{ query }}"</p>
{% endif %}
{% for result in list_results %}
<div class="block">
<ul>
<li>
<a href="{% url 'list' result.id %}">{{ result.name }}</a>
</li>
</ul>
</div>
{% endfor %}
</section>
</div>
</div>
{% endwith %}

View File

@ -0,0 +1,46 @@
{% extends 'layout.html' %}
{% block content %}
<header class="block column is-offset-one-quarter pl-1">
<h1 class="title">{% block header %}{% endblock %}</h1>
</header>
<div class="block columns">
<nav class="menu column is-one-quarter">
{% if perms.bookwyrm.create_invites %}
<h2 class="menu-label">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>
</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>
</li>
</ul>
{% endif %}
{% if perms.bookwyrm.edit_instance_settings %}
<h2 class="menu-label">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>
{% 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>
</ul>
{% endif %}
</li>
</ul>
{% endif %}
</nav>
<div class="column content">
{% block panel %}{% endblock %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,21 @@
{% extends 'settings/admin_layout.html' %}
{% block header %}Federated Servers{% endblock %}
{% block panel %}
<table class="table is-striped">
<tr>
<th>Server name</th>
<th>Software</th>
<th>Status</th>
</tr>
{% for server in servers %}
<tr>
<td>{{ server.server_name }}</td>
<td>{{ server.application_type }} ({{ server.application_version }})</td>
<td>{{ server.status }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,8 +1,32 @@
{% extends 'layout.html' %}
{% extends 'settings/admin_layout.html' %}
{% block header %}Invites{% endblock %}
{% load humanize %}
{% block content %}
<div class="block">
<h1 class="title">Invites</h1>
{% block panel %}
<section class="block">
<h2 class="title is-4">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>
<div class="select">
{{ form.expiry }}
</div>
</div>
<div class="control">
<label class="label" for="id_use_limit">Use limit:</label>
<div class="select">
{{ form.use_limit }}
</div>
</div>
</div>
<button class="button is-primary" type="submit">Create Invite</button>
</form>
</section>
<section class="block">
<table class="table is-striped">
<tr>
<th>Link</th>
@ -22,29 +46,6 @@
</tr>
{% endfor %}
</table>
</div>
<div class="block">
<h2 class="title is-4">Generate New Invite</h2>
<form name="invite" action="/invite/" method="post">
{% csrf_token %}
<div class="field is-grouped">
<div class="control">
<label class="label" for="id_expiry">Expiry:</label>
<div class="select">
{{ form.expiry }}
</div>
</div>
<div class="control">
<label class="label" for="id_use_limit">Use limit:</label>
<div class="select">
{{ form.use_limit }}
</div>
</div>
</div>
<button class="button is-primary" type="submit">Create Invite</button>
</form>
</div>
{% include 'snippets/pagination.html' with page=invites path=request.path %}
</section>
{% endblock %}

View File

@ -0,0 +1,84 @@
{% extends 'settings/admin_layout.html' %}
{% block header %}Site Configuration{% 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>
<div class="control">
<label class="label" for="id_name">Instance Name:</label>
{{ site_form.name }}
</div>
<div class="control">
<label class="label" for="id_instance_tagline">Tagline:</label>
{{ site_form.instance_tagline }}
</div>
<div class="control">
<label class="label" for="id_instance_description">Instance description:</label>
{{ site_form.instance_description }}
</div>
<div class="control">
<label class="label" for="id_code_of_conduct">Code of conduct:</label>
{{ site_form.code_of_conduct }}
</div>
</section>
<hr aria-hidden="true">
<section class="block" id="images">
<h2 class="title is-4">Images</h2>
<div class="field is-grouped">
<div class="control">
<label class="label" for="id_logo">Logo:</label>
{{ site_form.logo }}
</div>
<div class="control">
<label class="label" for="id_logo_small">Logo small:</label>
{{ site_form.logo_small }}
</div>
<div class="control">
<label class="label" for="id_favicon">Favicon:</label>
{{ site_form.favicon }}
</div>
</div>
</section>
<hr aria-hidden="true">
<section class="block" id="footer">
<h2 class="title is-4">Footer Content</h2>
<div class="control">
<label class="label" for="id_support_link">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>
<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>
{{ site_form.admin_email }}
</div>
</section>
<hr aria-hidden="true">
<section class="block" id="registration">
<h2 class="title is-4">Registration</h2>
<div class="control">
<label class="label" for="id_allow_registration">Allow registration:
{{ site_form.allow_registration }}
</div>
<div class="control">
<label class="label" for="id_registration_closed_text">Registration closed text:</label>
{{ site_form.registration_closed_text }}
</div>
</section>
<footer class="block">
<button class="button is-primary" type="submit">Save Changes</button>
</footer>
</form>
{% endblock %}

View File

@ -1,106 +0,0 @@
{% extends 'layout.html' %}
{% load bookwyrm_tags %}
{% block content %}
<div class="columns">
<div class="column">
<h1 class="title">
{% if is_self %}Your
{% else %}
{% include 'snippets/username.html' with user=user possessive=True %}
{% endif %}
shelves
</h1>
</div>
</div>
{% include 'snippets/user_header.html' with user=user %}
<div class="block columns">
<div class="column">
<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 }}"{% if shelf_tab.identifier == shelf.identifier %} aria-current="page"{% endif %}>{{ shelf_tab.name }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
{% if is_self %}
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with text="Create shelf" icon="plus" class="is-clickable" controls_text="create-shelf-form" %}
</div>
{% endif %}
</div>
<div class="hidden box mb-5" id="create-shelf-form">
<h2 class="title is-4">Create new shelf</h2>
<form name="create-shelf" action="/create-shelf/" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ request.user.id }}">
<div class="field">
<label class="label" for="id_name_create">Name:</label>
<input type="text" name="name" maxlength="100" class="input" required="true" id="id_name_create">
</div>
<label class="label">
<p>Shelf privacy:</p>
{% include 'snippets/privacy_select.html' with no_label=True %}
</label>
<div class="field is-grouped">
<button class="button is-primary" type="submit">Create shelf</button>
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="create-shelf-form" %}
</div>
</form>
</div>
<div class="block columns">
<div class="column">
<h2 class="title is-3">
{{ shelf.name }}
<span class="subtitle">
{% include 'snippets/privacy-icons.html' with item=shelf %}
</span>
</h2>
</div>
{% if is_self %}
<div class="column is-narrow">
{% include 'snippets/toggle/open_button.html' with text="Edit shelf" icon="pencil" class="is-clickable" controls_text="edit-shelf-form" %}
</div>
{% endif %}
</div>
<div class="hidden box mb-5" id="edit-shelf-form">
<h2 class="title is-4">Edit shelf</h2>
<form name="create-shelf" action="{{ shelf.local_path }}" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ request.user.id }}">
{% if shelf.editable %}
<div class="field">
<label class="label" for="id_name">Name:</label>
<input type="text" name="name" maxlength="100" class="input" required="true" value="{{ shelf.name }}" id="id_name">
</div>
{% else %}
<input type="hidden" name="name" required="true" value="{{ shelf.name }}">
{% endif %}
<label class="label">
<p>Shelf privacy:</p>
{% include 'snippets/privacy_select.html' with no_label=True current=shelf.privacy %}
</label>
<div class="field is-grouped">
<button class="button is-primary" type="submit">Update shelf</button>
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="edit-shelf-form" %}
</div>
</form>
</div>
<div class="block">
<div>
{% include 'snippets/shelf.html' with shelf=shelf books=books ratings=ratings %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,11 @@
{% 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>
</form>
{% else %}
<form name="unblocks" method="post" action="/unblock/{{ user.id }}">
{% csrf_token %}
<button class="button is-small {{ class }}" type="submit">Un-block</button>
</form>
{% endif %}

View File

@ -5,7 +5,7 @@
<a href="/book/{{ book.id }}">
{% include 'snippets/book_cover.html' with book=book %}
</a>
{% include 'snippets/shelve_button.html' with book=book switch_mode=True %}
{% include 'snippets/shelve_button/shelve_button.html' with book=book switch_mode=True %}
</div>
</div>
{% endfor %}

View File

@ -11,7 +11,7 @@
</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-success" type="submit">
<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>

View File

@ -1,5 +1,5 @@
{% load bookwyrm_tags %}
<form class="is-flex-grow-1" name="{{ type }}" action="/post/{{ type }}" method="post" id="tab-{{ type }}-{{ book.id }}{{ reply_parent.id }}">
<form class="is-flex-grow-1" 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 }}">
<input type="hidden" name="user" value="{{ request.user.id }}">
@ -11,7 +11,7 @@
</div>
{% endif %}
<div class="control">
{% if not type == 'reply' %}
{% if type != 'reply' and type != 'direct' %}
<label class="label" for="id_{% if type == 'quotation' %}quote{% else %}content{% endif %}_{{ book.id }}_{{ type }}">{{ type|title }}:</label>
{% endif %}
@ -35,7 +35,7 @@
<textarea name="quote" class="textarea" id="id_quote_{{ book.id }}_{{ type }}" placeholder="{{ placeholder }}" required></textarea>
{% else %}
{% include 'snippets/content_warning_field.html' with parent_status=status %}
<textarea name="content" class="textarea" id="id_content_{{ type }}-{{ book.id }}{{reply_parent.id}}" placeholder="{{ placeholder }}" {% if type == 'reply' %} aria-label="Reply"{% endif %} required>{% if reply_parent %}{{ reply_parent|mentions:request.user }}{% endif %}</textarea>
<textarea name="content" class="textarea" id="id_content_{{ type }}-{{ book.id }}{{reply_parent.id}}" placeholder="{{ placeholder }}" {% if type == 'reply' %} aria-label="Reply"{% endif %} required>{% if reply_parent %}{{ reply_parent|mentions:request.user }}{% endif %}{% if mentions %}@{{ mentions|username }} {% endif %}</textarea>
{% endif %}
</div>
{% if type == 'quotation' %}
@ -53,7 +53,12 @@
{% 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 %}
</div>
<div class="control">
{% include 'snippets/privacy_select.html' with current=reply_parent.privacy%}
{% if type == 'direct' %}
<input type="hidden" name="privacy" value="direct">
<button type="button" class="button" aria-label="Privacy" disabled>Private</button>
{% else %}
{% include 'snippets/privacy_select.html' with current=reply_parent.privacy %}
{% endif %}
</div>
</div>
<div class="column is-narrow">

View File

@ -1,4 +1,4 @@
{% extends 'snippets/components/modal.html' %}
{% extends 'components/modal.html' %}
{% block modal-title %}Delete these read dates?{% endblock %}
{% block modal-body %}
{% if readthrough.progress_updates|length > 0 %}

View File

@ -10,7 +10,7 @@
</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-success is-small" type="submit">
<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>

View File

@ -5,20 +5,29 @@
Follow request already sent.
</div>
{% elif user in request.user.blocks.all %}
{% include 'snippets/block_button.html' %}
{% else %}
<form action="/follow/" method="POST" class="interaction follow-{{ user.id }} {% if request.user in user.followers.all %}hidden{%endif %}" data-id="follow-{{ user.id }}">
{% 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>
{% else %}
<button class="button is-small is-link" type="submit">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>
</form>
<div class="field has-addons">
<div class="control">
<form action="/follow/" method="POST" class="interaction follow-{{ user.id }} {% if request.user in user.followers.all %}hidden{%endif %}" data-id="follow-{{ user.id }}">
{% 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>
{% else %}
<button class="button is-small is-link" type="submit">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>
</form>
</div>
<div class="control">
{% include 'snippets/user_options.html' with user=user class="is-small" %}
</div>
</div>
{% endif %}

View File

@ -0,0 +1 @@
{% load humanize %}set a goal to read {{ goal.goal | intcomma }} book{{ goal.goal | pluralize }} in {{ goal.year }}

View File

@ -1,4 +1,4 @@
{% extends 'snippets/components/card.html' %}
{% extends 'components/card.html' %}
{% block card-header %}
<h3 class="card-header-title has-background-primary has-text-white">

View File

@ -1,10 +1,11 @@
{% load humanize %}
<p>
{% if goal.progress_percent >= 100 %}
Success!
{% elif goal.progress_percent %}
{{ goal.progress_percent }}% complete!
{% 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 }} books{% if request.path != goal.local_path %}</a>{% 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,18 +1,18 @@
{% if item.privacy == 'public' %}
<span class="icon icon-globe" title="Public post">
<span class="is-sr-only">Public post</span>
<span class="icon icon-globe" title="Public">
<span class="is-sr-only">Public</span>
</span>
{% elif item.privacy == 'unlisted' %}
<span class="icon icon-unlock" title="Unlisted post">
<span class="is-sr-only">Unlisted post</span>
<span class="icon icon-unlock" title="Unlisted">
<span class="is-sr-only">Unlisted</span>
</span>
{% elif item.privacy == 'followers' %}
<span class="icon icon-lock" title="Followers-only post">
<span class="is-sr-only">Followers-only post</span>
<span class="icon icon-lock" title="Followers-only">
<span class="is-sr-only">Followers-only</span>
</span>
{% else %}
<span class="icon icon-envelope" title="Private post">
<span class="is-sr-only">Private post</span>
<span class="icon icon-envelope" title="Private">
<span class="is-sr-only">Private</span>
</span>
{% endif %}

View File

@ -9,11 +9,11 @@
<input type="hidden" name="privacy" value="public">
<input type="hidden" name="rating" value="{{ forloop.counter }}">
<div class="field is-grouped stars form-rate-stars mb-1">
<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>
<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|rating:user == forloop.counter %}checked{% endif %}>
<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 %}>
<label class="icon icon-star-empty" for="rating-book{{book.id}}-star-{{ forloop.counter }}">
<span class="is-sr-only">{{ forloop.counter }} star{{ forloop.counter | pluralize }}</span>
</label>

View File

@ -6,10 +6,11 @@
Progress Updates:
</dl>
<ul>
{% if readthrough.progress %}
{% 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 %}
{% else %}{{ readthrough.progress }}%{% endif %}{% endif %}
{% include 'snippets/toggle/toggle_button.html' with text="Show all updates" controls_text="updates" controls_uid=readthrough.id class="is-small" %}
{% if readthrough.progress %}
{% include 'snippets/toggle/toggle_button.html' with text="Show all updates" 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>
@ -31,6 +32,7 @@
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endif %}
<li>{{ readthrough.start_date | naturalday }}: started</li>

View File

@ -0,0 +1 @@
{{ obj.pure_content | safe }}

View File

@ -0,0 +1,15 @@
{{ 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
{% elif obj.status_type == 'Review' %}
reviewed
{% elif obj.status_type == 'Comment' %}
commented on
{% elif obj.status_type == 'Quotation' %}
quoted
{% endif %}
{% if obj.book %}{{ obj.book.title | safe}}
{% elif obj.mention_books %}
{{ obj.mention_books.first.title }}
{% endif %}

View File

@ -1,6 +1,7 @@
{% load humanize %}
{% load bookwyrm_tags %}
{% if books|length > 0 %}
<div class="table-container">
<table class="table is-striped is-fullwidth">
<tr class="book-preview">
@ -37,10 +38,10 @@
{% for book in books %}
<tr class="book-preview">
<td>
{% include 'snippets/book_cover.html' with book=book size="small" %}
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book size="small" %}</a>
</td>
<td>
<a href="/book/{{ book.id }}">{{ book.title }}</a>
<a href="{{ book.local_path }}">{{ book.title }}</a>
</td>
<td>
{{ book.authors.first.name }}
@ -74,6 +75,7 @@
</tr>
{% endfor %}
</table>
</div>
{% else %}
<p>This shelf is empty.</p>
{% if shelf.editable %}

View File

@ -1,4 +1,4 @@
{% extends 'snippets/components/dropdown.html' %}
{% extends 'components/dropdown.html' %}
{% block dropdown-trigger %}
<span>Change shelf</span>
<span class="icon icon-arrow-down" aria-hidden="true"></span>

View File

@ -1,40 +0,0 @@
{% load bookwyrm_tags %}
{% if request.user.is_authenticated %}
{% with book.id|uuid as uuid %}
{% active_shelf book as active_shelf %}
<div class="field has-addons">
{% if switch_mode and active_shelf.book != book %}
<div class="control">
{% include 'snippets/switch_edition_button.html' with edition=book size='is-small' %}
</div>
{% else %}
<div class="control">
{% if active_shelf.shelf.identifier == 'read' %}
<button class="button is-small" disabled>
<span>Read</span> <span class="icon icon-check"></span>
</button>
{% elif active_shelf.shelf.identifier == 'reading' %}
{% include 'snippets/toggle/toggle_button.html' with class="is-small" text="I'm done!" controls_text="finish-reading" controls_uid=uuid focus="modal-title-finish-reading" %}
{% elif active_shelf.shelf.identifier == 'to-read' %}
{% include 'snippets/toggle/toggle_button.html' with class="is-small" text="Start reading" controls_text="start-reading" controls_uid=uuid focus="modal-title-start-reading" %}
{% else %}
<form name="shelve" action="/shelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
<input type="hidden" name="shelf" value="to-read">
<button class="button is-small" type="submit">Want to read</button>
</form>
{% endif %}
</div>
{% include 'snippets/shelve_button_dropdown.html' with class="is-small" button_uuid=uuid%}
{% endif %}
</div>
{% include 'snippets/start_reading_modal.html' with book=active_shelf.book controls_text="start-reading" controls_uid=uuid %}
{% latest_read_through book request.user as readthrough %}
{% include 'snippets/finish_reading_modal.html' with book=active_shelf.book controls_text="finish-reading" controls_uid=uuid readthrough=readthrough %}
{% endwith %}
{% endif %}

View File

@ -1,4 +1,4 @@
{% extends 'snippets/components/modal.html' %}
{% extends 'components/modal.html' %}
{% block modal-title %}
Finish "<em>{{ book.title }}</em>"

View File

@ -0,0 +1,27 @@
{% load bookwyrm_tags %}
{% if request.user.is_authenticated %}
{% with book.id|uuid as uuid %}
{% active_shelf book as active_shelf %}
<div class="field has-addons">
{% if switch_mode and active_shelf.book != book %}
<div class="control">
{% include 'snippets/switch_edition_button.html' with edition=book size='is-small' %}
</div>
{% else %}
<div class="control">
{% include 'snippets/shelve_button/shelve_button_options.html' with class="shelf-option is-small" shelves=request.user.shelf_set.all active_shelf=active_shelf button_uuid=uuid %}
</div>
{% include 'snippets/shelve_button/shelve_button_dropdown.html' with class="is-small" button_uuid=uuid%}
{% endif %}
</div>
{% include 'snippets/shelve_button/want_to_read_modal.html' with book=active_shelf.book controls_text="want-to-read" controls_uid=uuid no_body=True %}
{% include 'snippets/shelve_button/start_reading_modal.html' with book=active_shelf.book controls_text="start-reading" controls_uid=uuid %}
{% latest_read_through book request.user as readthrough %}
{% include 'snippets/shelve_button/finish_reading_modal.html' with book=active_shelf.book controls_text="finish-reading" controls_uid=uuid readthrough=readthrough %}
{% endwith %}
{% endif %}

View File

@ -0,0 +1,10 @@
{% extends 'components/dropdown.html' %}
{% block dropdown-trigger %}
<span class="icon icon-arrow-down">
<span class="is-sr-only">More shelves</span>
</span>
{% endblock %}
{% block dropdown-list %}
{% include 'snippets/shelve_button/shelve_button_options.html' with active_shelf=active_shelf shelves=request.user.shelf_set.all dropdown=True class="shelf-option is-fullwidth is-small" %}
{% endblock %}

View File

@ -0,0 +1,25 @@
{% load bookwyrm_tags %}
{% 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 %}
{% 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>
{% 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 %}
{% 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 %}
{% endif %}{% elif shelf.editable %}
<form name="shelve" action="/shelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
<button class="button {{ class }}" name="shelf" type="submit" value="{{ shelf.identifier }}" {% if shelf in book.shelf_set.all %} disabled {% endif %}>
<span>{{ shelf.name }}</span>
</button>
</form>
{% endif %}
</div>
{% if dropdown %}</li>{% endif %}
{% endfor %}

View File

@ -1,4 +1,4 @@
{% extends 'snippets/components/modal.html' %}
{% extends 'components/modal.html' %}
{% block modal-title %}
Start "<em>{{ book.title }}</em>"

View File

@ -0,0 +1,31 @@
{% extends 'components/modal.html' %}
{% block modal-title %}
Want to Read "<em>{{ book.title }}</em>"
{% endblock %}
{% block modal-form-open %}
<form name="shelve" action="/shelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
<input type="hidden" name="shelf" value="to-read">
{% endblock %}
{% block modal-footer %}
<div class="columns">
<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
</label>
{% include 'snippets/privacy_select.html' %}
</div>
<div class="column">
<button class="button is-success" type="submit">
<span>Want to read</span>
</button>
{% include 'snippets/toggle/toggle_button.html' with text="Cancel" controls_text="want-to-read" controls_uid=uuid %}
</div>
</div>
{% endblock %}
{% block modal-form-close %}</form>{% endblock %}

View File

@ -1,28 +0,0 @@
{% extends 'snippets/components/dropdown.html' %}
{% block dropdown-trigger %}
<span class="icon icon-arrow-down">
<span class="is-sr-only">More shelves</span>
</span>
{% endblock %}
{% block dropdown-list %}
{% for shelf in request.user.shelf_set.all %}
<li role="menuitem">
{% if active_shelf.shelf.identifier != 'reading' and shelf.identifier == 'reading' %}
<div class="dropdown-item pt-0 pb-0">
{% include 'snippets/toggle/toggle_button.html' with class="is-fullwidth is-small" text="Start reading" controls_text="start-reading" controls_uid=button_uuid focus="modal-title-start-reading" %}
</div>
{% else %}
<form class="dropdown-item pt-0 pb-0" name="shelve" action="/shelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}">
<button class="button is-fullwidth is-small" name="shelf" type="submit" value="{{ shelf.identifier }}" {% if shelf in book.shelf_set.all %} disabled {% endif %}>
<span>{{ shelf.name }}</span>
{% if shelf in book.shelf_set.all %}<span class="icon icon-check"></span>{% endif %}
</button>
</form>
{% endif %}
</li>
{% endfor %}
{% endblock %}

View File

@ -1,8 +1,7 @@
<div class="stars">
<p class="stars">
<span class="is-sr-only">{% if rating %}{{ rating|floatformat }} star{{ rating|floatformat | pluralize }}{% else %}No rating{% endif %}</span>
{% for i in '12345'|make_list %}
<span class="icon icon-star-{% if rating >= forloop.counter %}full{% elif rating|floatformat:0 >= forloop.counter|floatformat:0 %}half{% else %}empty{% endif %}">
<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>
{% endfor %}
</div>
</p>

View File

@ -2,8 +2,9 @@
<div class="columns">
<div class="column is-narrow">
<div>
<a href="/book/{{ book.id }}">{% include 'snippets/book_cover.html' with book=book %}</a>
{% include 'snippets/shelve_button.html' with book=book %}
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book %}</a>
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
{% include 'snippets/shelve_button/shelve_button.html' with book=book %}
</div>
</div>
<div class="column">

View File

@ -4,8 +4,8 @@
{% include 'snippets/avatar.html' with user=status.user %}
{% include 'snippets/username.html' with user=status.user %}
boosted
{% include 'snippets/status_body.html' with status=status|boosted_status %}
{% include 'snippets/status/status_body.html' with status=status|boosted_status %}
{% else %}
{% include 'snippets/status_body.html' with status=status %}
{% include 'snippets/status/status_body.html' with status=status %}
{% endif %}
{% endif %}

View File

@ -1,17 +1,17 @@
{% extends 'snippets/components/card.html' %}
{% extends 'components/card.html' %}
{% load bookwyrm_tags %}
{% load humanize %}
{% block card-header %}
<h3 class="card-header-title has-background-white-ter is-block">
{% include 'snippets/status_header.html' with status=status %}
{% include 'snippets/status/status_header.html' with status=status %}
</h3>
{% endblock %}
{% block card-content %}
{% include 'snippets/status_content.html' with status=status %}
{% include 'snippets/status/status_content.html' with status=status %}
{% endblock %}
@ -20,7 +20,7 @@
{% 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" focus="id_content_reply" %}
{% 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" %}
</div>
<div class="control">
{% include 'snippets/boost_button.html' with status=status %}
@ -54,11 +54,9 @@
<div class="card-footer-item">
<a href="{{ status.remote_id }}">{{ status.published_date | post_date }}</a>
</div>
{% if status.user == request.user %}
<div class="card-footer-item">
{% include 'snippets/status_options.html' with class="is-small" right=True %}
{% include 'snippets/status/status_options.html' with class="is-small" right=True %}
</div>
{% endif %}
{% endblock %}

View File

@ -54,9 +54,9 @@
{% if status.book or status.mention_books.count %}
<div class="{% if status.status_type != 'GeneratedNote' %}box has-background-white-bis{% endif %}">
{% if status.book %}
{% include 'snippets/book_preview.html' with book=status.book %}
{% include 'snippets/status/book_preview.html' with book=status.book %}
{% elif status.mention_books.count %}
{% include 'snippets/book_preview.html' with book=status.mention_books.first %}
{% include 'snippets/status/book_preview.html' with book=status.mention_books.first %}
{% endif %}
</div>
{% endif %}

View File

@ -1,4 +1,5 @@
{% extends 'snippets/components/dropdown.html' %}
{% extends 'components/dropdown.html' %}
{% load bookwyrm_tags %}
{% block dropdown-trigger %}
<span class="icon icon-dots-three">
@ -7,6 +8,7 @@
{% endblock %}
{% block dropdown-list %}
{% if status.user == request.user %}
<li role="menuitem">
<form class="dropdown-item pt-0 pb-0" name="delete-{{status.id}}" action="/delete-status/{{ status.id }}" method="post">
{% csrf_token %}
@ -15,4 +17,12 @@
</button>
</form>
</li>
{% else %}
<li role="menuitem">
<a href="/direct-messages/{{ status.user|username }}" class="button is-fullwidth is-small">Send direct message</a>
</li>
<li role="menuitem">
{% include 'snippets/block_button.html' with user=status.user class="is-fullwidth" %}
</li>
{% endif %}
{% endblock %}

View File

@ -6,6 +6,7 @@
{% if checkbox %}data-controls-checkbox="{{ checkbox }}{% if controls_uid %}-{{ controls_uid }}{% endif %}"{% endif %}
{% if label %}aria-label="{{ label }}"{% endif %}
aria-pressed="{% if pressed %}true{% else %}false{% endif %}"
{% if disabled %}disabled{% endif %}
>
{% if icon %}
@ -13,6 +14,6 @@
<span class="is-sr-only">{{ text }}</span>
</span>
{% else %}
{{ text }}
<span>{{ text }}</span>
{% endif %}
</button>

View File

@ -1,24 +1,26 @@
{% load bookwyrm_tags %}
{% with 0|uuid as uuid %}
{% if full %}
{% with full|to_markdown|safe as full %}
{% with full|to_markdown|safe|truncatewords_html:60 as trimmed %}
{% if trimmed != full %}
<div id="hide-full-{{ uuid }}">
<blockquote class="content" id="trimmed-{{ uuid }}"><span dir="auto">{{ trimmed }}</span>
<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" %}
</blockquote>
</div>
</div>
<div id="full-{{ uuid }}" class="hidden">
<blockquote class="content"><span dir="auto">{{ full | to_markdown | safe }}</span>
<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" %}
</blockquote>
</div>
</div>
{% else %}
<blockquote class="content"><span dir="auto">{{ full | to_markdown | safe }}</span></blockquote>
<div class="content"><span dir="auto">{{ full }}</span></div>
{% endif %}
{% endwith %}
{% endwith %}
{% endif %}
{% endwith %}

View File

@ -0,0 +1,17 @@
{% extends 'components/dropdown.html' %}
{% load bookwyrm_tags %}
{% block dropdown-trigger %}
<span class="icon icon-dots-three">
<span class="is-sr-only">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>
</li>
<li role="menuitem">
{% include 'snippets/block_button.html' with user=user class="is-fullwidth" %}
</li>
{% endblock %}

View File

@ -1,9 +0,0 @@
{% extends 'layout.html' %}
{% block content %}
<div class="block">
{% include 'snippets/thread.html' with status=status depth=0 max_depth=6 is_root=True direction=0 %}
</div>
{% endblock %}

View File

@ -0,0 +1,26 @@
{% extends 'components/inline_form.html' %}
{% block header %}
Create New Shelf
{% endblock %}
{% block form %}
<form name="create-shelf" action="{% url 'shelf-create' %}" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ request.user.id }}">
<div class="field">
<label class="label" for="id_name_create">Name:</label>
<input type="text" name="name" maxlength="100" class="input" required="true" id="id_name_create">
</div>
<div class="field has-addons">
<div class="control">
{% include 'snippets/privacy_select.html' %}
</div>
<div class="control">
<button class="button is-primary" type="submit">Create shelf</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,31 @@
{% extends 'components/inline_form.html' %}
{% block header %}
Edit Shelf
{% endblock %}
{% block form %}
<form name="edit-shelf" action="{{ shelf.local_path }}" method="post">
{% csrf_token %}
<input type="hidden" name="user" value="{{ request.user.id }}">
{% if shelf.editable %}
<div class="field">
<label class="label" for="id_name">Name:</label>
<input type="text" name="name" maxlength="100" class="input" required="true" value="{{ shelf.name }}" id="id_name">
</div>
{% else %}
<input type="hidden" name="name" required="true" value="{{ shelf.name }}">
{% endif %}
<div class="field has-addons">
<div class="control">
{% include 'snippets/privacy_select.html' with current=shelf.privacy %}
</div>
<div class="control">
<button class="button is-primary" type="submit">Update shelf</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,32 @@
{% extends 'user/user_layout.html' %}
{% load bookwyrm_tags %}
{% block header %}
<h1 class="title">
{% if is_self %}Your
{% else %}
{% include 'snippets/username.html' with user=user possessive=True %}
{% endif %}
followers
</h1>
{% endblock %}
{% block panel %}
<div class="block">
<h2 class="title">Followers</h2>
{% for followers in followers %}
<div class="block columns">
<div class="column">
{% include 'snippets/avatar.html' with user=followers %}
{% include 'snippets/username.html' with user=followers show_full=True %}
</div>
<div class="column is-narrow">
{% include 'snippets/follow_button.html' with user=followers %}
</div>
</div>
{% endfor %}
{% if not followers.count %}
<div>{{ user|username }} has no followers</div>
{% endif %}
</div>
{% endblock %}

View File

@ -0,0 +1,32 @@
{% extends 'user/user_layout.html' %}
{% load bookwyrm_tags %}
{% block header %}
<h1 class="title">
Users following
{% if is_self %}you
{% else %}
{% include 'snippets/username.html' with user=user %}
{% endif %}
</h1>
{% endblock %}
{% block panel %}
<div class="block">
<h2 class="title">Following</h2>
{% for follower in user.following.all %}
<div class="block columns">
<div class="column">
{% include 'snippets/avatar.html' with user=follower %}
{% include 'snippets/username.html' with user=follower show_full=True %}
</div>
<div class="column">
{% include 'snippets/follow_button.html' with user=follower %}
</div>
</div>
{% endfor %}
{% if not following.count %}
<div>{{ user|username }} isn't following any users</div>
{% endif %}
</div>
{% endblock %}

View File

@ -0,0 +1,40 @@
{% extends 'user/user_layout.html' %}
{% block header %}
<div class="columns is-mobile">
<div class="column">
<h1 class="title">
{% if is_self %}Your
{% else %}
{% include 'snippets/username.html' with user=user %}'s
{% 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" %}
</div>
{% endif %}
</div>
{% endblock %}
{% block panel %}
<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>
<div class="column is-narrow">
{% include 'snippets/toggle/toggle_button.html' with controls_text="create-list" label="close" class="delete" nonbutton=True %}
</div>
</header>
{% include 'lists/form.html' %}
</form>
{% include 'lists/list_items.html' with lists=lists %}
</section>
<div>
{% include 'snippets/pagination.html' with page=lists path=path %}
</div>
{% endblock %}

View File

@ -0,0 +1,66 @@
{% extends 'user/user_layout.html' %}
{% load bookwyrm_tags %}
{% block header %}
<header class="columns">
<h1 class="title">
{% if is_self %}Your
{% else %}
{% include 'snippets/username.html' with user=user possessive=True %}
{% endif %}
shelves
</h1>
</header>
{% endblock %}
{% block panel %}
<div class="block columns">
<div class="column">
<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 }}"{% if shelf_tab.identifier == shelf.identifier %} aria-current="page"{% endif %}>{{ shelf_tab.name }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
{% 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" %}
</div>
{% endif %}
</div>
<div class="block">
{% include 'user/create_shelf_form.html' with controls_text='create-shelf-form' %}
</div>
<div class="block columns is-mobile">
<div class="column">
<h2 class="title is-3">
{{ shelf.name }}
<span class="subtitle">
{% include 'snippets/privacy-icons.html' with item=shelf %}
</span>
</h2>
</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" %}
</div>
{% endif %}
</div>
<div class="block">
{% include 'user/edit_shelf_form.html' with controls_text="edit-shelf-form" %}
</div>
<div class="block">
<div>
{% include 'snippets/shelf.html' with shelf=shelf books=books ratings=ratings %}
</div>
</div>
{% endblock %}

View File

@ -1,13 +1,13 @@
{% extends 'layout.html' %}
{% block content %}
{% extends 'user/user_layout.html' %}
<div class="columns">
{% block header %}
<div class="columns is-mobile">
<div class="column">
<h1 class="title">User profile</h1>
</div>
{% if is_self %}
<div class="column is-narrow">
<a href="/edit-profile">
<a href="/preferences/profile">
<span class="icon icon-pencil" title="Edit profile">
<span class="is-sr-only">Edit profile</span>
</span>
@ -15,9 +15,10 @@
</div>
{% endif %}
</div>
{% endblock %}
{% include 'snippets/user_header.html' with user=user %}
{% block panel %}
{% if user.bookwyrm_user %}
<div class="block">
<h2 class="title">Shelves</h2>
<div class="columns">
@ -39,6 +40,7 @@
</div>
<small><a href="{{ user.local_path }}/shelves">See all {{ shelf_count }} shelves</a></small>
</div>
{% endif %}
{% if goal %}
<div class="block">
@ -52,12 +54,17 @@
{% endif %}
<div>
<div class="block">
<h2 class="title">User Activity</h2>
<div class="columns is-mobile">
<h2 class="title column">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>
</a>
</div>
</div>
{% for activity in activities %}
<div class="block" id="feed">
{% include 'snippets/status.html' with status=activity %}
{% include 'snippets/status/status.html' with status=activity %}
</div>
{% endfor %}
{% if not activities %}

View File

@ -1,5 +1,13 @@
{% extends 'layout.html' %}
{% load humanize %}
{% load bookwyrm_tags %}
{% block content %}
<header class="block">
{% block header %}{% endblock %}
</header>
{# user bio #}
<div class="block">
<div class="columns">
<div class="column is-narrow">
@ -34,7 +42,7 @@
{% endif %}
</div>
</div>
{% if not is_self %}
{% if not is_self and request.user.is_authenticated %}
{% include 'snippets/follow_button.html' with user=user %}
{% endif %}
@ -52,4 +60,38 @@
</div>
{% endif %}
</div>
{% with user|username as username %}
{% if 'user/'|add:username|add:'/shelf' not in request.path and 'user/'|add:username|add:'/shelves' not in request.path %}
<nav class="tabs">
<ul>
{% url 'user-feed' user|username as url %}
<li{% if url == request.path or url == request.path|add:'/' %} class="is-active"{% endif %}>
<a href="{{ url }}">Activity</a>
</li>
{% if is_self or user.goal.exists %}
{% now 'Y' as year %}
{% url 'user-goal' user|username year as url %}
<li{% if url in request.path %} class="is-active"{% endif %}>
<a href="{{ url }}">Reading Goal</a>
</li>
{% endif %}
{% if is_self or user.lists.exists %}
{% url 'user-lists' user|username as url %}
<li{% if url in request.path %} class="is-active"{% endif %}>
<a href="{{ url }}">Lists</a>
</li>
{% endif %}
{% if user.shelf_set.exists %}
{% url 'user-shelves' user|username as url %}
<li{% if url in request.path %} class="is-active"{% endif %}>
<a href="{{ url }}">Shelves</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% endwith %}
{% block panel %}{% endblock %}
{% endblock %}