mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-27 03:51:08 +00:00
Merge branch 'main' into group-list-button
Hopefully fixes failing tests!
This commit is contained in:
commit
2153afe743
40 changed files with 549 additions and 301 deletions
19
bookwyrm/migrations/0122_alter_annualgoal_year.py
Normal file
19
bookwyrm/migrations/0122_alter_annualgoal_year.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 3.2.5 on 2022-01-04 18:59
|
||||||
|
|
||||||
|
import bookwyrm.models.user
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0121_user_summary_keys"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="annualgoal",
|
||||||
|
name="year",
|
||||||
|
field=models.IntegerField(default=bookwyrm.models.user.get_current_year),
|
||||||
|
),
|
||||||
|
]
|
|
@ -415,12 +415,17 @@ class KeyPair(ActivitypubMixin, BookWyrmModel):
|
||||||
return activity_object
|
return activity_object
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_year():
|
||||||
|
"""sets default year for annual goal to this year"""
|
||||||
|
return timezone.now().year
|
||||||
|
|
||||||
|
|
||||||
class AnnualGoal(BookWyrmModel):
|
class AnnualGoal(BookWyrmModel):
|
||||||
"""set a goal for how many books you read in a year"""
|
"""set a goal for how many books you read in a year"""
|
||||||
|
|
||||||
user = models.ForeignKey("User", on_delete=models.PROTECT)
|
user = models.ForeignKey("User", on_delete=models.PROTECT)
|
||||||
goal = models.IntegerField(validators=[MinValueValidator(1)])
|
goal = models.IntegerField(validators=[MinValueValidator(1)])
|
||||||
year = models.IntegerField(default=timezone.now().year)
|
year = models.IntegerField(default=get_current_year)
|
||||||
privacy = models.CharField(
|
privacy = models.CharField(
|
||||||
max_length=255, default="public", choices=fields.PrivacyLevels.choices
|
max_length=255, default="public", choices=fields.PrivacyLevels.choices
|
||||||
)
|
)
|
||||||
|
|
|
@ -135,6 +135,18 @@ button::-moz-focus-inner {
|
||||||
border-bottom: 1px solid #ededed;
|
border-bottom: 1px solid #ededed;
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-flex-direction-row-mobile {
|
||||||
|
flex-direction: row !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-flex-direction-column-mobile {
|
||||||
|
flex-direction: column !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag.is-small {
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button.is-transparent {
|
.button.is-transparent {
|
||||||
|
@ -215,7 +227,7 @@ input[type=file]::file-selector-button:hover {
|
||||||
/** General `details` element styles
|
/** General `details` element styles
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
summary {
|
details summary {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,22 +235,22 @@ summary::-webkit-details-marker {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary::marker {
|
details summary::marker {
|
||||||
content: none;
|
content: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-pinned-button summary {
|
details.detail-pinned-button summary {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-pinned-button form {
|
details.detail-pinned-button form {
|
||||||
float: left;
|
float: left;
|
||||||
width: -webkit-fill-available;
|
width: 100%;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Details dropdown
|
/** Dropdown w/ Details element
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
details.dropdown[open] summary.dropdown-trigger::before {
|
details.dropdown[open] summary.dropdown-trigger::before {
|
||||||
|
@ -250,11 +262,11 @@ details.dropdown[open] summary.dropdown-trigger::before {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
details .dropdown-menu {
|
details.dropdown .dropdown-menu {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
details .dropdown-menu button {
|
details.dropdown .dropdown-menu button {
|
||||||
/* Fix weird Safari defaults */
|
/* Fix weird Safari defaults */
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
@ -289,6 +301,46 @@ details.dropdown .dropdown-menu a:focus-visible {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Details panel
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
details.details-panel {
|
||||||
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: box-shadow 0.2s ease;
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
details[open].details-panel,
|
||||||
|
details.details-panel:hover {
|
||||||
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
details.details-panel summary {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
details.details-panel summary .details-close {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
details[open].details-panel summary .details-close {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 769px) {
|
||||||
|
.details-panel .filters-field:not(:last-child) {
|
||||||
|
border-right: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
padding-top: 0.25rem;
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Shelving
|
/** Shelving
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
@ -1149,3 +1201,93 @@ ol.ordered-list li::before {
|
||||||
margin-bottom: 0.75rem !important;
|
margin-bottom: 0.75rem !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Gaps (for Flexbox and Grid)
|
||||||
|
*
|
||||||
|
* Those are supplementary rules to Bulma’s. They follow the same conventions.
|
||||||
|
* Add those you’ll need.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
.is-gap-0 {
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-gap-1 {
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-gap-2 {
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-gap-3 {
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-gap-4 {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-gap-5 {
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-gap-6 {
|
||||||
|
gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-row-gap-0 {
|
||||||
|
row-gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-row-gap-1 {
|
||||||
|
row-gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-row-gap-2 {
|
||||||
|
row-gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-row-gap-3 {
|
||||||
|
row-gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-row-gap-4 {
|
||||||
|
row-gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-row-gap-5 {
|
||||||
|
row-gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-row-gap-6 {
|
||||||
|
row-gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-column-gap-0 {
|
||||||
|
column-gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-column-gap-1 {
|
||||||
|
column-gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-column-gap-2 {
|
||||||
|
column-gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-column-gap-3 {
|
||||||
|
column-gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-column-gap-4 {
|
||||||
|
column-gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-column-gap-5 {
|
||||||
|
column-gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-column-gap-6 {
|
||||||
|
column-gap: 3rem;
|
||||||
|
}
|
||||||
|
|
4
bookwyrm/static/css/vendor/icons.css
vendored
4
bookwyrm/static/css/vendor/icons.css
vendored
|
@ -25,6 +25,10 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon.is-small {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-book:before {
|
.icon-book:before {
|
||||||
content: "\e901";
|
content: "\e901";
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ let BookWyrm = new (class {
|
||||||
document
|
document
|
||||||
.querySelectorAll("[data-duplicate]")
|
.querySelectorAll("[data-duplicate]")
|
||||||
.forEach((node) => node.addEventListener("click", this.duplicateInput.bind(this)));
|
.forEach((node) => node.addEventListener("click", this.duplicateInput.bind(this)));
|
||||||
|
|
||||||
document
|
document
|
||||||
.querySelectorAll("details.dropdown")
|
.querySelectorAll("details.dropdown")
|
||||||
.forEach((node) =>
|
.forEach((node) =>
|
||||||
|
@ -60,6 +61,9 @@ let BookWyrm = new (class {
|
||||||
.querySelectorAll('input[type="file"]')
|
.querySelectorAll('input[type="file"]')
|
||||||
.forEach(bookwyrm.disableIfTooLarge.bind(bookwyrm));
|
.forEach(bookwyrm.disableIfTooLarge.bind(bookwyrm));
|
||||||
document.querySelectorAll("[data-copytext]").forEach(bookwyrm.copyText.bind(bookwyrm));
|
document.querySelectorAll("[data-copytext]").forEach(bookwyrm.copyText.bind(bookwyrm));
|
||||||
|
document
|
||||||
|
.querySelectorAll(".modal.is-active")
|
||||||
|
.forEach(bookwyrm.handleActiveModal.bind(bookwyrm));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +409,7 @@ let BookWyrm = new (class {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the modal component.
|
* Handle the modal component with a button trigger.
|
||||||
*
|
*
|
||||||
* @param {Event} event - Event fired by an element
|
* @param {Event} event - Event fired by an element
|
||||||
* with the `data-modal-open` attribute
|
* with the `data-modal-open` attribute
|
||||||
|
@ -416,6 +420,7 @@ let BookWyrm = new (class {
|
||||||
* for information about using the modal.
|
* for information about using the modal.
|
||||||
*/
|
*/
|
||||||
handleModalButton(event) {
|
handleModalButton(event) {
|
||||||
|
const { handleFocusTrap } = this;
|
||||||
const modalButton = event.currentTarget;
|
const modalButton = event.currentTarget;
|
||||||
const targetModalId = modalButton.dataset.modalOpen;
|
const targetModalId = modalButton.dataset.modalOpen;
|
||||||
const htmlElement = document.querySelector("html");
|
const htmlElement = document.querySelector("html");
|
||||||
|
@ -427,6 +432,8 @@ let BookWyrm = new (class {
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
function handleModalOpen(modalElement) {
|
function handleModalOpen(modalElement) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
htmlElement.classList.add("is-clipped");
|
htmlElement.classList.add("is-clipped");
|
||||||
modalElement.classList.add("is-active");
|
modalElement.classList.add("is-active");
|
||||||
modalElement.getElementsByClassName("modal-card")[0].focus();
|
modalElement.getElementsByClassName("modal-card")[0].focus();
|
||||||
|
@ -455,42 +462,48 @@ let BookWyrm = new (class {
|
||||||
modalButton.focus();
|
modalButton.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFocusTrap(event) {
|
|
||||||
if (event.key !== "Tab") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const focusableEls = event.currentTarget.querySelectorAll(
|
|
||||||
[
|
|
||||||
"a[href]:not([disabled])",
|
|
||||||
"button:not([disabled])",
|
|
||||||
"textarea:not([disabled])",
|
|
||||||
'input:not([type="hidden"]):not([disabled])',
|
|
||||||
"select:not([disabled])",
|
|
||||||
"details:not([disabled])",
|
|
||||||
'[tabindex]:not([tabindex="-1"]):not([disabled])',
|
|
||||||
].join(",")
|
|
||||||
);
|
|
||||||
const firstFocusableEl = focusableEls[0];
|
|
||||||
const lastFocusableEl = focusableEls[focusableEls.length - 1];
|
|
||||||
|
|
||||||
if (event.shiftKey) {
|
|
||||||
/* Shift + tab */ if (document.activeElement === firstFocusableEl) {
|
|
||||||
lastFocusableEl.focus();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
} /* Tab */ else {
|
|
||||||
if (document.activeElement === lastFocusableEl) {
|
|
||||||
firstFocusableEl.focus();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open modal
|
// Open modal
|
||||||
handleModalOpen(modal);
|
handleModalOpen(modal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the modal component when opened at page load.
|
||||||
|
*
|
||||||
|
* @param {Element} modalElement - Active modal element
|
||||||
|
* @return {undefined}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
handleActiveModal(modalElement) {
|
||||||
|
if (!modalElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { handleFocusTrap } = this;
|
||||||
|
|
||||||
|
modalElement.getElementsByClassName("modal-card")[0].focus();
|
||||||
|
|
||||||
|
const closeButtons = modalElement.querySelectorAll("[data-modal-close]");
|
||||||
|
|
||||||
|
closeButtons.forEach((button) => {
|
||||||
|
button.addEventListener("click", function () {
|
||||||
|
handleModalClose(modalElement);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keydown", function (event) {
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
handleModalClose(modalElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
modalElement.addEventListener("keydown", handleFocusTrap);
|
||||||
|
|
||||||
|
function handleModalClose(modalElement) {
|
||||||
|
modalElement.removeEventListener("keydown", handleFocusTrap);
|
||||||
|
history.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display pop up window.
|
* Display pop up window.
|
||||||
*
|
*
|
||||||
|
|
|
@ -192,6 +192,31 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if goal_status and goal_status.percent >= 100 %}
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column has-text-centered">
|
||||||
|
<h2 class="title is-3 is-serif">
|
||||||
|
{% with goal=goal_status.goal goal_percent=goal_status.percent %}
|
||||||
|
{% blocktrans trimmed count counter=goal %}
|
||||||
|
{{ display_name }} set a goal of reading {{ goal }} book in {{ year }},<br />
|
||||||
|
and achieved {{ goal_percent }}% of that goal
|
||||||
|
{% plural %}
|
||||||
|
{{ display_name }} set a goal of reading {{ goal }} books in {{ year }},<br />
|
||||||
|
and achieved {{ goal_percent }}% of that goal
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% endwith %}
|
||||||
|
</h2>
|
||||||
|
<p class="subtitle is-5">{% trans "Way to go!" %}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column is-one-fifth is-offset-two-fifths">
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if ratings_total > 0 %}
|
{% if ratings_total > 0 %}
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column has-text-centered">
|
<div class="column has-text-centered">
|
||||||
|
|
|
@ -92,10 +92,11 @@
|
||||||
{% trans "View on OpenLibrary" %}
|
{% trans "View on OpenLibrary" %}
|
||||||
</a>
|
</a>
|
||||||
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
|
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
|
||||||
{% with controls_text="ol_sync" controls_uid=author.id %}
|
<button class="button is-small" type="button" data-modal-open="openlibrary_sync">
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text focus="modal_title_ol_sync" class="is-small" icon_with_text="download" %}
|
<span class="icon icon-download" title="{{ button_text }}"></span>
|
||||||
{% include "author/sync_modal.html" with source="openlibrary.org" source_name="OpenLibrary" %}
|
<span class="is-sr-only-mobile">{{ button_text }}</span>
|
||||||
{% endwith %}
|
</button>
|
||||||
|
{% include "author/sync_modal.html" with source="openlibrary.org" source_name="OpenLibrary" id="openlibrary_sync" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -107,10 +108,11 @@
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
|
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
|
||||||
{% with controls_text="iv_sync" controls_uid=author.id %}
|
<button class="button is-small" type="button" data-modal-open="inventaire_sync">
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text focus="modal_title_iv_sync" class="is-small" icon_with_text="download" %}
|
<span class="icon icon-download" title="{{ button_text }}"></span>
|
||||||
{% include "author/sync_modal.html" with source="inventaire.io" source_name="Inventaire" %}
|
<span class="is-sr-only-mobile">{{ button_text }}</span>
|
||||||
{% endwith %}
|
</button>
|
||||||
|
{% include "author/sync_modal.html" with source="inventaire.io" source_name="Inventaire" id="inventaire_sync" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -19,12 +19,8 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-footer %}
|
{% block modal-footer %}
|
||||||
<button class="button is-primary" type="submit">
|
<button class="button is-primary" type="submit">{% trans "Confirm" %}</button>
|
||||||
<span>{% trans "Confirm" %}</span>
|
<button type="button" class="button" data-modal-close>{% trans "Cancel" %}</button>
|
||||||
</button>
|
|
||||||
|
|
||||||
{% trans "Cancel" as button_text %}
|
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-form-close %}</form>{% endblock %}
|
{% block modal-form-close %}</form>{% endblock %}
|
||||||
|
|
|
@ -63,7 +63,11 @@
|
||||||
<div class="column is-one-fifth">
|
<div class="column is-one-fifth">
|
||||||
{% if not book.cover %}
|
{% if not book.cover %}
|
||||||
{% if user_authenticated %}
|
{% if user_authenticated %}
|
||||||
<button type="button" data-controls="add_cover_{{ book.id }}" data-focus-target="modal_title_add_cover_{{ book.id }}" aria-pressed="false" class="cover-container no-cover is-h-m-mobile">
|
<button
|
||||||
|
type="button"
|
||||||
|
class="cover-container no-cover is-h-m-mobile"
|
||||||
|
data-modal-open="add_cover_{{ book.id }}"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
class="book-cover"
|
class="book-cover"
|
||||||
src="{% static "images/no_cover.jpg" %}"
|
src="{% static "images/no_cover.jpg" %}"
|
||||||
|
@ -78,7 +82,8 @@
|
||||||
{% trans "Click to add cover" %}
|
{% trans "Click to add cover" %}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
{% include 'book/cover_add_modal.html' with book=book controls_text="add_cover" controls_uid=book.id %}
|
{% join "add_cover" book.id as modal_id %}
|
||||||
|
{% include 'book/cover_add_modal.html' with id=modal_id %}
|
||||||
{% if request.GET.cover_error %}
|
{% if request.GET.cover_error %}
|
||||||
<p class="help is-danger">{% trans "Failed to load cover" %}</p>
|
<p class="help is-danger">{% trans "Failed to load cover" %}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -117,23 +122,30 @@
|
||||||
{% trans "Load data" as button_text %}
|
{% trans "Load data" as button_text %}
|
||||||
{% if book.openlibrary_key %}
|
{% if book.openlibrary_key %}
|
||||||
<p>
|
<p>
|
||||||
<a href="{{ book.openlibrary_link }}" target="_blank" rel="noopener">{% trans "View on OpenLibrary" %}</a>
|
<a href="{{ book.openlibrary_link }}" target="_blank" rel="noopener">
|
||||||
|
{% trans "View on OpenLibrary" %}
|
||||||
|
</a>
|
||||||
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
|
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
|
||||||
{% with controls_text="ol_sync" controls_uid=book.id %}
|
<button class="button is-small" type="button" data-modal-open="openlibrary_sync">
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text focus="modal_title_ol_sync" class="is-small" icon_with_text="download" %}
|
<span class="icon icon-download" title="{{ button_text }}"></span>
|
||||||
{% include "book/sync_modal.html" with source="openlibrary.org" source_name="OpenLibrary" %}
|
<span class="is-sr-only-mobile">{{ button_text }}</span>
|
||||||
{% endwith %}
|
</button>
|
||||||
|
{% include "book/sync_modal.html" with source="openlibrary.org" source_name="OpenLibrary" id="openlibrary_sync" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if book.inventaire_id %}
|
{% if book.inventaire_id %}
|
||||||
<p>
|
<p>
|
||||||
<a href="{{ book.inventaire_link }}" target="_blank" rel="noopener">{% trans "View on Inventaire" %}</a>
|
<a href="{{ book.inventaire_link }}" target="_blank" rel="noopener">
|
||||||
|
{% trans "View on Inventaire" %}
|
||||||
|
</a>
|
||||||
|
|
||||||
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
|
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
|
||||||
{% with controls_text="iv_sync" controls_uid=book.id %}
|
<button class="button is-small" type="button" data-modal-open="inventaire_sync">
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text focus="modal_title_iv_sync" class="is-small" icon_with_text="download" %}
|
<span class="icon icon-download" title="{{ button_text }}"></span>
|
||||||
{% include "book/sync_modal.html" with source="inventaire.io" source_name="Inventaire" %}
|
<span class="is-sr-only-mobile">{{ button_text }}</span>
|
||||||
{% endwith %}
|
</button>
|
||||||
|
{% include "book/sync_modal.html" with source="inventaire.io" source_name="Inventaire" id="inventaire_sync" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -29,8 +29,7 @@
|
||||||
|
|
||||||
{% block modal-footer %}
|
{% block modal-footer %}
|
||||||
<button class="button is-primary" type="submit">{% trans "Add" %}</button>
|
<button class="button is-primary" type="submit">{% trans "Add" %}</button>
|
||||||
{% trans "Cancel" as button_text %}
|
<button type="button" class="button" data-modal-close>{% trans "Cancel" %}</button>
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block modal-form-close %}</form>{% endblock %}
|
|
||||||
|
|
||||||
|
{% block modal-form-close %}</form>{% endblock %}
|
||||||
|
|
|
@ -2,11 +2,17 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block modal-title %}{% trans "Delete these read dates?" %}{% endblock %}
|
{% block modal-title %}{% trans "Delete these read dates?" %}{% endblock %}
|
||||||
|
|
||||||
{% block modal-body %}
|
{% block modal-body %}
|
||||||
{% if readthrough.progress_updates|length > 0 %}
|
{% if readthrough.progress_updates|length > 0 %}
|
||||||
{% blocktrans with count=readthrough.progress_updates|length %}You are deleting this readthrough and its {{ count }} associated progress updates.{% endblocktrans %}
|
{% blocktrans trimmed with count=readthrough.progress_updates|length %}
|
||||||
|
You are deleting this readthrough and its {{ count }} associated progress updates.
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% else %}
|
||||||
|
{% trans "This action cannot be un-done" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-footer %}
|
{% block modal-footer %}
|
||||||
<form name="delete-readthrough-{{ readthrough.id }}" action="/delete-readthrough" method="POST">
|
<form name="delete-readthrough-{{ readthrough.id }}" action="/delete-readthrough" method="POST">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
@ -14,7 +20,6 @@
|
||||||
<button class="button is-danger" type="submit">
|
<button class="button is-danger" type="submit">
|
||||||
{% trans "Delete" %}
|
{% trans "Delete" %}
|
||||||
</button>
|
</button>
|
||||||
{% trans "Cancel" as button_text %}
|
<button type="button" class="button" data-modal-close>{% trans "Cancel" %}</button>
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="delete_readthrough" controls_uid=readthrough.id %}
|
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,6 +1,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
{% load tz %}
|
{% load tz %}
|
||||||
|
{% load utilities %}
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div id="hide_edit_readthrough_{{ readthrough.id }}" class="box is-shadowless has-background-white-bis">
|
<div id="hide_edit_readthrough_{{ readthrough.id }}" class="box is-shadowless has-background-white-bis">
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
|
@ -10,14 +11,14 @@
|
||||||
{% if readthrough.finish_date or readthrough.progress %}
|
{% if readthrough.finish_date or readthrough.progress %}
|
||||||
<li>
|
<li>
|
||||||
{% if readthrough.finish_date %}
|
{% if readthrough.finish_date %}
|
||||||
{{ readthrough.finish_date | localtime | naturalday }}: {% trans "finished" %}
|
{{ readthrough.finish_date | localtime | naturalday }}: {% trans "finished" %}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
{% if readthrough.progress_mode == 'PG' %}
|
{% if readthrough.progress_mode == 'PG' %}
|
||||||
{% include 'snippets/page_text.html' with page=readthrough.progress total_pages=book.pages %}
|
{% include 'snippets/page_text.html' with page=readthrough.progress total_pages=book.pages %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ readthrough.progress }}%
|
{{ readthrough.progress }}%
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if readthrough.progress %}
|
{% if readthrough.progress %}
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if readthrough.start_date %}
|
{% if readthrough.start_date %}
|
||||||
<li>{{ readthrough.start_date | localtime | naturalday }}: {% trans "started" %}</li>
|
<li>{{ readthrough.start_date | localtime | naturalday }}: {% trans "started" %}</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -60,7 +62,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
{% trans "Delete these read dates" as button_text %}
|
{% 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" %}
|
<button class="button is-small" type="button" data-modal-open="delete_readthrough_{{ readthrough.id }}">
|
||||||
|
<span class="icon icon-x" title="{{ button_text }}">
|
||||||
|
<span class="is-sr-only">{{ button_text }}</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -79,4 +85,5 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% include 'snippets/delete_readthrough_modal.html' with controls_text="delete_readthrough" controls_uid=readthrough.id no_body=True %}
|
{% join "delete_readthrough" readthrough.id as modal_id %}
|
||||||
|
{% include 'book/delete_readthrough_modal.html' with id=modal_id %}
|
||||||
|
|
|
@ -19,12 +19,8 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-footer %}
|
{% block modal-footer %}
|
||||||
<button class="button is-primary" type="submit">
|
<button class="button is-primary" type="submit">{% trans "Confirm" %}</button>
|
||||||
<span>{% trans "Confirm" %}</span>
|
<button type="button" class="button" data-modal-close>{% trans "Cancel" %}</button>
|
||||||
</button>
|
|
||||||
|
|
||||||
{% trans "Cancel" as button_text %}
|
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-form-close %}</form>{% endblock %}
|
{% block modal-form-close %}</form>{% endblock %}
|
||||||
|
|
|
@ -1,40 +1,33 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div
|
|
||||||
role="dialog"
|
<div class="modal {% if active %}is-active{% endif %}" id="{{ id }}">
|
||||||
class="modal {% if active %}is-active{% else %}is-hidden{% endif %}"
|
<div class="modal-background" data-modal-close></div>
|
||||||
id="{{ controls_text }}_{{ controls_uid }}"
|
<div class="modal-card" role="dialog" aria-modal="true" tabindex="-1" aria-described-by="{{ id }}_header">
|
||||||
aria-labelledby="modal_card_title_{{ controls_text }}_{{ controls_uid }}"
|
<header class="modal-card-head">
|
||||||
aria-modal="true"
|
<h2 class="modal-card-title mb-0" id="{{ id }}_header">
|
||||||
>
|
|
||||||
{# @todo Implement focus traps to prevent tabbing out of the modal. #}
|
|
||||||
<div class="modal-background"></div>
|
|
||||||
{% trans "Close" as label %}
|
|
||||||
<div class="modal-card">
|
|
||||||
<header class="modal-card-head" tabindex="0" id="modal_title_{{ controls_text }}_{{ controls_uid }}">
|
|
||||||
<h2 class="modal-card-title is-flex-shrink-1" id="modal_card_title_{{ controls_text }}_{{ controls_uid }}">
|
|
||||||
{% block modal-title %}{% endblock %}
|
{% block modal-title %}{% endblock %}
|
||||||
</h2>
|
</h2>
|
||||||
{% if static %}
|
<button
|
||||||
<a href="/" class="delete">{{ label }}</a>
|
type="button"
|
||||||
{% else %}
|
class="delete"
|
||||||
{% include 'snippets/toggle/toggle_button.html' with label=label class="delete" nonbutton=True %}
|
aria-label="{% trans 'Close' %}"
|
||||||
{% endif %}
|
data-modal-close
|
||||||
|
></button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{% block modal-form-open %}{% endblock %}
|
{% block modal-form-open %}{% endblock %}
|
||||||
{% if not no_body %}
|
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
{% block modal-body %}{% endblock %}
|
{% block modal-body %}{% endblock %}
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
|
||||||
<footer class="modal-card-foot">
|
<footer class="modal-card-foot">
|
||||||
{% block modal-footer %}{% endblock %}
|
{% block modal-footer %}{% endblock %}
|
||||||
</footer>
|
</footer>
|
||||||
{% block modal-form-close %}{% endblock %}
|
{% block modal-form-close %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
{% if static %}
|
<button
|
||||||
<a href="/" class="modal-close is-large">{{ label }}</a>
|
type="button"
|
||||||
{% else %}
|
class="modal-close is-large"
|
||||||
{% include 'snippets/toggle/toggle_button.html' with label=label class="modal-close is-large" nonbutton=True %}
|
aria-label="{% trans 'Close' %}"
|
||||||
{% endif %}
|
data-modal-close
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
<div class="modal" id="{{ id }}">
|
|
||||||
<div class="modal-background" data-modal-close></div>
|
|
||||||
<div class="modal-card is-thin" role="dialog" aria-modal="true" tabindex="-1">
|
|
||||||
<header class="modal-card-head">
|
|
||||||
<h2 class="modal-card-title mb-0">
|
|
||||||
{% block modal-title %}{% endblock %}
|
|
||||||
</h2>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="delete"
|
|
||||||
aria-label="{% trans 'Close' %}"
|
|
||||||
data-modal-close
|
|
||||||
></button>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<section class="modal-card-body">
|
|
||||||
{% block modal-body %}{% endblock %}
|
|
||||||
</section>
|
|
||||||
<footer class="modal-card-foot">
|
|
||||||
{% block modal-footer %}{% endblock %}
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="modal-close is-large"
|
|
||||||
aria-label="{% trans 'Close' %}"
|
|
||||||
data-modal-close
|
|
||||||
></button>
|
|
||||||
</div>
|
|
|
@ -6,57 +6,22 @@
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
{{ tab.name }}
|
{{ tab.name }}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="block is-clipped">
|
|
||||||
<div class="is-pulled-left">
|
|
||||||
<div class="tabs">
|
|
||||||
<ul>
|
|
||||||
{% for stream in streams %}
|
|
||||||
<li class="{% if tab.key == stream.key %}is-active{% endif %}"{% if tab.key == stream.key %} aria-current="page"{% endif %}>
|
|
||||||
<a href="/{{ stream.key }}#feed">{{ stream.shortname }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# feed settings #}
|
<div class="tabs">
|
||||||
<details class="detail-pinned-button" {% if settings_saved %}open{% endif %}>
|
<ul>
|
||||||
<summary class="control">
|
{% for stream in streams %}
|
||||||
<span class="button">
|
<li class="{% if tab.key == stream.key %}is-active{% endif %}"{% if tab.key == stream.key %} aria-current="page"{% endif %}>
|
||||||
<span class="icon icon-dots-three m-0-mobile" aria-hidden="true"></span>
|
<a href="/{{ stream.key }}#feed">{{ stream.shortname }}</a>
|
||||||
<span class="is-sr-only-mobile">{{ _("Feed settings") }}</span>
|
</li>
|
||||||
</span>
|
{% endfor %}
|
||||||
</summary>
|
</ul>
|
||||||
<form class="notification level is-align-items-flex-end" method="post" action="/{{ tab.key }}#feed">
|
|
||||||
{% csrf_token %}
|
|
||||||
|
|
||||||
<div class="level-left">
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<span class="is-flex is-align-items-baseline">
|
|
||||||
<label class="label mt-2 mb-1">Status types</label>
|
|
||||||
{% if settings_saved %}
|
|
||||||
<span class="tag is-success is-light ml-2">{{ _("Saved!") }}</span>
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
|
||||||
{% for name, value in feed_status_types_options %}
|
|
||||||
<label class="mr-2">
|
|
||||||
<input type="checkbox" name="feed_status_types" value="{{ name }}" {% if name in user.feed_status_types %}checked=""{% endif %}/>
|
|
||||||
{{ value }}
|
|
||||||
</label>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="level-right control">
|
|
||||||
<button class="button is-small is-primary is-outlined" type="submit">
|
|
||||||
{{ _("Save settings") }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</details>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# feed settings #}
|
||||||
|
{% with "/"|add:tab.key|add:"#feed" as action %}
|
||||||
|
{% include 'feed/feed_filters.html' with size="small" method="post" action=action %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
{# announcements and system messages #}
|
{# announcements and system messages #}
|
||||||
{% if not activities.number > 1 %}
|
{% if not activities.number > 1 %}
|
||||||
<a href="{{ request.path }}" class="transition-y is-hidden notification is-primary is-block" data-poll-wrapper>
|
<a href="{{ request.path }}" class="transition-y is-hidden notification is-primary is-block" data-poll-wrapper>
|
||||||
|
|
5
bookwyrm/templates/feed/feed_filters.html
Normal file
5
bookwyrm/templates/feed/feed_filters.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends 'snippets/filters_panel/filters_panel.html' %}
|
||||||
|
|
||||||
|
{% block filter_fields %}
|
||||||
|
{% include 'feed/status_types_filter.html' %}
|
||||||
|
{% endblock %}
|
16
bookwyrm/templates/feed/status_types_filter.html
Normal file
16
bookwyrm/templates/feed/status_types_filter.html
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{% extends 'snippets/filters_panel/filter_field.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block filter %}
|
||||||
|
<label class="label mt-2 mb-1">Status types</label>
|
||||||
|
|
||||||
|
<div class="is-flex is-flex-direction-row is-flex-direction-column-mobile">
|
||||||
|
{% for name, value in feed_status_types_options %}
|
||||||
|
<label class="mr-2">
|
||||||
|
<input type="checkbox" name="feed_status_types" value="{{ name }}" {% if name in user.feed_status_types %}checked=""{% endif %}/>
|
||||||
|
{{ value }}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -14,8 +14,7 @@
|
||||||
<button class="button is-danger" type="submit">
|
<button class="button is-danger" type="submit">
|
||||||
{% trans "Delete" %}
|
{% trans "Delete" %}
|
||||||
</button>
|
</button>
|
||||||
{% trans "Cancel" as button_text %}
|
<button type="button" class="button" data-modal-close>{% trans "Cancel" %}</button>
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="delete_group" controls_uid=group.id %}
|
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -9,5 +9,5 @@
|
||||||
<form name="edit-group" method="post" action="{% url 'group' group.id %}">
|
<form name="edit-group" method="post" action="{% url 'group' group.id %}">
|
||||||
{% include 'groups/form.html' %}
|
{% include 'groups/form.html' %}
|
||||||
</form>
|
</form>
|
||||||
{% include "groups/delete_group_modal.html" with controls_text="delete_group" controls_uid=group.id %}
|
{% include "groups/delete_group_modal.html" with id="delete_group" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -14,21 +14,20 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="columns is-mobile">
|
<div class="is-flex">
|
||||||
<div class="column">
|
|
||||||
<div class="field has-addons">
|
|
||||||
<div class="control">
|
|
||||||
{% include 'snippets/privacy_select_no_followers.html' with current=group.privacy %}
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
|
||||||
<button type="submit" class="button is-primary">{% trans "Save" %}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% if group.id %}
|
{% if group.id %}
|
||||||
<div class="column is-narrow">
|
<div class="is-flex-grow-1">
|
||||||
{% trans "Delete group" as button_text %}
|
<button type="button" data-modal-open="delete_group" class="button is-danger">
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class="is-danger" text=button_text icon_with_text="x" controls_text="delete_group" controls_uid=group.id focus="modal_title_delete_group" %}
|
{% trans "Delete group" %}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="field has-addons">
|
||||||
|
<div class="control">
|
||||||
|
{% include 'snippets/privacy_select_no_followers.html' with current=group.privacy %}
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<button type="submit" class="button is-primary">{% trans "Save" %}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends 'components/new_modal.html' %}
|
{% extends 'components/modal.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block modal-title %}{% trans "Delete this list?" %}{% endblock %}
|
{% block modal-title %}{% trans "Delete this list?" %}{% endblock %}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<ul class="block">
|
<ul class="block">
|
||||||
{% for result in local_results.results %}
|
{% for result in local_results.results %}
|
||||||
<li class="pd-4 mb-5">
|
<li class="pd-4 mb-5">
|
||||||
<div class="columns is-mobile is-gapless">
|
<div class="columns is-mobile is-gapless mb-0">
|
||||||
<div class="column is-cover">
|
<div class="column is-cover">
|
||||||
{% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' %}
|
{% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,34 +34,28 @@
|
||||||
<div class="block">
|
<div class="block">
|
||||||
{% for result_set in results|slice:"1:" %}
|
{% for result_set in results|slice:"1:" %}
|
||||||
{% if result_set.results %}
|
{% if result_set.results %}
|
||||||
<section class="box has-background-white-bis">
|
<section class="mb-5">
|
||||||
{% if not result_set.connector.local %}
|
{% if not result_set.connector.local %}
|
||||||
<header class="columns is-mobile">
|
<details class="details-panel box" {% if forloop.first %}open{% endif %}>
|
||||||
<div class="column">
|
{% endif %}
|
||||||
<h3 class="title is-5">
|
{% if not result_set.connector.local %}
|
||||||
|
<summary class="is-flex is-align-items-center is-flex-wrap-wrap is-gap-2">
|
||||||
|
<span class="mb-0 title is-5">
|
||||||
{% trans 'Results from' %}
|
{% trans 'Results from' %}
|
||||||
<a href="{{ result_set.connector.base_url }}" target="_blank">{{ result_set.connector.name|default:result_set.connector.identifier }}</a>
|
<a href="{{ result_set.connector.base_url }}" target="_blank">{{ result_set.connector.name|default:result_set.connector.identifier }}</a>
|
||||||
</h3>
|
</span>
|
||||||
</div>
|
|
||||||
<div class="column is-narrow">
|
|
||||||
{% trans "Open" as button_text %}
|
|
||||||
{% include 'snippets/toggle/open_button.html' with text=button_text controls_text="more_results_panel" controls_uid=result_set.connector.identifier class="is-small" icon_with_text="arrow-down" pressed=forloop.first %}
|
|
||||||
{% trans "Close" as button_text %}
|
|
||||||
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="more_results_panel" controls_uid=result_set.connector.identifier class="is-small" icon_with_text="arrow-up" pressed=forloop.first %}
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="box has-background-white is-shadowless{% if not forloop.first %} is-hidden{% endif %}" id="more_results_panel_{{ result_set.connector.identifier }}">
|
<span class="details-close icon icon-x" aria-hidden></span>
|
||||||
|
</summary>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="mt-5">
|
||||||
<div class="is-flex is-flex-direction-row-reverse">
|
<div class="is-flex is-flex-direction-row-reverse">
|
||||||
<div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="is-flex-grow-1">
|
<ul class="is-flex-grow-1">
|
||||||
{% for result in result_set.results %}
|
{% for result in result_set.results %}
|
||||||
<li class="mb-5">
|
<li class="{% if not forloop.last %}mb-5{% endif %}">
|
||||||
<div class="columns is-mobile is-gapless">
|
<div class="columns is-mobile is-gapless">
|
||||||
<div class="columns is-mobile is-gapless">
|
<div class="column is-1 is-cover">
|
||||||
{% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' external_path=True %}
|
{% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' external_path=True %}
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-10 ml-3">
|
<div class="column is-10 ml-3">
|
||||||
|
@ -92,6 +86,9 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if not result_set.connector.local %}
|
||||||
|
</details>
|
||||||
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<div class="column is-flex">
|
<div class="filters-field column">
|
||||||
<div class="box is-flex-grow-1">
|
{% block filter %}
|
||||||
{% block filter %}
|
{% endblock %}
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,28 +1,47 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="notification content">
|
<details class="details-panel box is-size-{{ size|default:'normal' }}" {% if filters_applied %}open{% endif %}>
|
||||||
<h2 class="columns is-mobile mb-0">
|
<summary class="is-flex is-align-items-center is-flex-wrap-wrap is-gap-2">
|
||||||
<span class="column pb-0">Filters</span>
|
<span class="mb-0 title {% if size == 'small' %}is-6{% else %}is-5{% endif %} is-flex-shrink-0">
|
||||||
|
{% trans "Filters" %}
|
||||||
|
|
||||||
<span class="column is-narrow pb-0">
|
|
||||||
{% trans "Show filters" as text %}
|
|
||||||
{% include 'snippets/toggle/open_button.html' with text=text controls_text="filters" icon_with_text="arrow-down" class="is-small" focus="filters" %}
|
|
||||||
{% trans "Hide filters" as text %}
|
|
||||||
{% include 'snippets/toggle/close_button.html' with text=text controls_text="filters" icon_with_text="arrow-up" class="is-small" %}
|
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
|
||||||
|
|
||||||
<form class="is-hidden mt-3" id="filters" method="get" action="{{ request.path }}" tabindex="0">
|
{% if filters_applied %}
|
||||||
{% if sort %}
|
<span class="tag is-success is-light ml-2 mb-0 is-{{ size|default:'normal' }}">
|
||||||
<input type="hidden" name="sort" value="{{ sort }}">
|
{{ _("Filters are applied") }}
|
||||||
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="columns">
|
|
||||||
{% block filter_fields %}
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
<button class="button is-primary">{% trans "Apply filters" %}</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% if request.GET %}
|
{% if request.GET %}
|
||||||
<a class="help" href="{{ request.path }}">{% trans "Clear filters" %}</a>
|
<span class="mb-0 tags has-addons">
|
||||||
{% endif %}
|
<span class="mb-0 tag is-success is-light is-{{ size|default:'normal' }}">
|
||||||
</div>
|
{% trans "Filters are applied" %}
|
||||||
|
</span>
|
||||||
|
<a class="mb-0 tag is-success is-{{ size|default:'normal' }}" href="{{ request.path }}">
|
||||||
|
{% trans "Clear filters" %}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<span class="details-close icon icon-x is-{{ size|default:'normal' }}" aria-hidden></span>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="mt-3">
|
||||||
|
<form id="filters" method="{{ method|default:'get' }}" action="{{ action|default:request.path }}">
|
||||||
|
{% if method == 'post' %}
|
||||||
|
{% csrf_token %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if sort %}
|
||||||
|
<input type="hidden" name="sort" value="{{ sort }}">
|
||||||
|
{% endif %}
|
||||||
|
<div class="mt-3 columns filters-fields is-align-items-stretch">
|
||||||
|
{% block filter_fields %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button is-primary is-small">
|
||||||
|
{% trans "Apply filters" %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
type="number"
|
type="number"
|
||||||
name="progress"
|
name="progress"
|
||||||
class="input"
|
class="input"
|
||||||
id="id_progress_{{ readthrough.id }}{{ controls_uid }}"
|
id="{{ field_id }}"
|
||||||
value="{{ readthrough.progress }}"
|
value="{{ readthrough.progress }}"
|
||||||
{% if progress_required %}required{% endif %}
|
{% if progress_required %}required{% endif %}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends 'snippets/reading_modals/layout.html' %}
|
{% extends 'snippets/reading_modals/layout.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load utilities %}
|
||||||
|
|
||||||
{% block modal-title %}
|
{% block modal-title %}
|
||||||
{% trans "Update progress" %}
|
{% trans "Update progress" %}
|
||||||
|
@ -12,8 +13,9 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block reading-dates %}
|
{% block reading-dates %}
|
||||||
<label for="id_progress_{{ readthrough.id }}{{ controls_uid }}" class="label">{% trans "Progress:" %}</label>
|
{% join "id_progress" uuid as field_id %}
|
||||||
{% include "snippets/progress_field.html" with progress_required=True %}
|
<label for="{{ field_id }}" class="label">{% trans "Progress:" %}</label>
|
||||||
|
{% include "snippets/progress_field.html" with progress_required=True id=field_id %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block form %}
|
{% block form %}
|
||||||
|
|
|
@ -11,7 +11,7 @@ Start "<em>{{ book_title }}</em>"
|
||||||
{% block modal-form-open %}
|
{% block modal-form-open %}
|
||||||
<form name="start-reading-{{ uuid }}" action="{% url 'reading-status' 'start' book.id %}" method="post" {% if not refresh %}class="submit-status"{% endif %}>
|
<form name="start-reading-{{ uuid }}" action="{% url 'reading-status' 'start' book.id %}" method="post" {% if not refresh %}class="submit-status"{% endif %}>
|
||||||
<input type="hidden" name="reading_status" value="reading">
|
<input type="hidden" name="reading_status" value="reading">
|
||||||
<input type="hidden" name="shelf" value="{{ move_from }}">
|
<input type="hidden" name="shelf" value="{{ move_from }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load utilities %}
|
||||||
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="id" value="{{ readthrough.id }}">
|
<input type="hidden" name="id" value="{{ readthrough.id }}">
|
||||||
<input type="hidden" name="book" value="{{ book.id }}">
|
<input type="hidden" name="book" value="{{ book.id }}">
|
||||||
|
@ -10,10 +12,11 @@
|
||||||
</div>
|
</div>
|
||||||
{# Only show progress for editing existing readthroughs #}
|
{# Only show progress for editing existing readthroughs #}
|
||||||
{% if readthrough.id and not readthrough.finish_date %}
|
{% if readthrough.id and not readthrough.finish_date %}
|
||||||
<label class="label" for="id_progress_{{ readthrough.id }}{{ controls_uid }}">
|
{% join "id_progress" readthrough.id as field_id %}
|
||||||
|
<label class="label" for="{{ field_id }}">
|
||||||
{% trans "Progress" %}
|
{% trans "Progress" %}
|
||||||
</label>
|
</label>
|
||||||
{% include "snippets/progress_field.html" %}
|
{% include "snippets/progress_field.html" with id=field_id %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label" for="id_finish_date_{{ readthrough.id }}">
|
<label class="label" for="id_finish_date_{{ readthrough.id }}">
|
||||||
|
|
|
@ -3,9 +3,15 @@
|
||||||
|
|
||||||
{% with 0|uuid as report_uuid %}
|
{% with 0|uuid as report_uuid %}
|
||||||
|
|
||||||
{% trans "Report" as button_text %}
|
{% join "report" report_uuid as modal_id %}
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class="is-danger is-light is-small is-fullwidth" text=button_text controls_text="report" controls_uid=report_uuid focus="modal_title_report" disabled=is_current %}
|
<button
|
||||||
|
class="button is-small is-danger is-light is-fullwidth"
|
||||||
{% include 'snippets/report_modal.html' with user=user reporter=request.user controls_text="report" controls_uid=report_uuid %}
|
type="button"
|
||||||
|
data-modal-open="{{ modal_id }}"
|
||||||
|
{% if is_current %}disabled{% endif %}
|
||||||
|
>
|
||||||
|
{% trans "Report" %}
|
||||||
|
</button>
|
||||||
|
{% include 'snippets/report_modal.html' with user=user reporter=request.user id=modal_id %}
|
||||||
|
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
|
@ -21,8 +21,12 @@
|
||||||
|
|
||||||
<section class="content">
|
<section class="content">
|
||||||
<p>{% blocktrans with site_name=site.name %}This report will be sent to {{ site_name }}'s moderators for review.{% endblocktrans %}</p>
|
<p>{% blocktrans with site_name=site.name %}This report will be sent to {{ site_name }}'s moderators for review.{% endblocktrans %}</p>
|
||||||
<label class="label" for="id_{{ controls_uid }}_report_note">{% trans "More info about this report:" %}</label>
|
<div class="control">
|
||||||
<textarea class="textarea" name="note" id="id_{{ controls_uid }}_report_note"></textarea>
|
<label class="label" for="id_{{ controls_uid }}_report_note">
|
||||||
|
{% trans "More info about this report:" %}
|
||||||
|
</label>
|
||||||
|
<textarea class="textarea" name="note" id="id_{{ controls_uid }}_report_note"></textarea>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -31,9 +35,9 @@
|
||||||
{% block modal-footer %}
|
{% block modal-footer %}
|
||||||
|
|
||||||
<button class="button is-success" type="submit">{% trans "Submit" %}</button>
|
<button class="button is-success" type="submit">{% trans "Submit" %}</button>
|
||||||
{% trans "Cancel" as button_text %}
|
<button type="button" class="button" data-modal-close>{% trans "Cancel" %}</button>
|
||||||
{% include 'snippets/toggle/toggle_button.html' with text=button_text controls_text="report" controls_uid=report_uuid class="" %}
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-form-close %}</form>{% endblock %}
|
{% block modal-form-close %}</form>{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -88,11 +88,14 @@
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% include 'snippets/reading_modals/want_to_read_modal.html' with book=active_shelf.book controls_text="want_to_read" controls_uid=uuid move_from=current.id refresh=True class="" %}
|
{% join "want_to_read" uuid as modal_id %}
|
||||||
|
{% include 'snippets/reading_modals/want_to_read_modal.html' with book=active_shelf.book id=modal_id move_from=current.id refresh=True class="" %}
|
||||||
|
|
||||||
{% include 'snippets/reading_modals/start_reading_modal.html' with book=active_shelf.book controls_text="start_reading" controls_uid=uuid move_from=current.id refresh=True class="" %}
|
{% join "start_reading" uuid as modal_id %}
|
||||||
|
{% include 'snippets/reading_modals/start_reading_modal.html' with book=active_shelf.book id=modal_id move_from=current.id refresh=True class="" %}
|
||||||
|
|
||||||
{% include 'snippets/reading_modals/finish_reading_modal.html' with book=active_shelf.book controls_text="finish_reading" controls_uid=uuid move_from=current.id readthrough=readthrough refresh=True class="" %}
|
{% join "finish_reading" uuid as modal_id %}
|
||||||
|
{% include 'snippets/reading_modals/finish_reading_modal.html' with book=active_shelf.book id=modal_id move_from=current.id readthrough=readthrough refresh=True class="" %}
|
||||||
|
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
10
bookwyrm/templates/snippets/shelve_button/modal_button.html
Normal file
10
bookwyrm/templates/snippets/shelve_button/modal_button.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{% load utilities %}
|
||||||
|
<form name="fallback_form_{{ 0|uuid }}" method="GET" action="{{ fallback_url }}" autocomplete="off">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="button {{ class }}"
|
||||||
|
data-modal-open="{{ modal_id }}"
|
||||||
|
>
|
||||||
|
{{ button_text }}
|
||||||
|
</button>
|
||||||
|
</form>
|
|
@ -6,7 +6,7 @@
|
||||||
{% with book.id|uuid as uuid %}
|
{% with book.id|uuid as uuid %}
|
||||||
{% active_shelf book as active_shelf %}
|
{% active_shelf book as active_shelf %}
|
||||||
{% latest_read_through book request.user as readthrough %}
|
{% latest_read_through book request.user as readthrough %}
|
||||||
<div class="field has-addons mb-0" data-shelve-button-book="{{ book.id }}">
|
<div class="field has-addons mb-0 has-text-weight-normal" data-shelve-button-book="{{ book.id }}">
|
||||||
{% if switch_mode and active_shelf.book != book %}
|
{% if switch_mode and active_shelf.book != book %}
|
||||||
<div class="control">
|
<div class="control">
|
||||||
{% include 'snippets/switch_edition_button.html' with edition=book size='is-small' %}
|
{% include 'snippets/switch_edition_button.html' with edition=book size='is-small' %}
|
||||||
|
@ -19,13 +19,17 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% include 'snippets/reading_modals/want_to_read_modal.html' with book=active_shelf.book controls_text="want_to_read" controls_uid=uuid %}
|
{% join "want_to_read" uuid as modal_id %}
|
||||||
|
{% include 'snippets/reading_modals/want_to_read_modal.html' with book=active_shelf.book id=modal_id class="" %}
|
||||||
|
|
||||||
{% include 'snippets/reading_modals/start_reading_modal.html' with book=active_shelf.book controls_text="start_reading" controls_uid=uuid %}
|
{% join "start_reading" uuid as modal_id %}
|
||||||
|
{% include 'snippets/reading_modals/start_reading_modal.html' with book=active_shelf.book id=modal_id class="" %}
|
||||||
|
|
||||||
{% include 'snippets/reading_modals/finish_reading_modal.html' with book=active_shelf.book controls_text="finish_reading" controls_uid=uuid readthrough=readthrough %}
|
{% join "finish_reading" uuid as modal_id %}
|
||||||
|
{% include 'snippets/reading_modals/finish_reading_modal.html' with book=active_shelf.book id=modal_id readthrough=readthrough class="" %}
|
||||||
|
|
||||||
{% include 'snippets/reading_modals/progress_update_modal.html' with book=active_shelf.book controls_text="progress_update" controls_uid=uuid readthrough=readthrough %}
|
{% join "progress_update" uuid as modal_id %}
|
||||||
|
{% include 'snippets/reading_modals/progress_update_modal.html' with book=active_shelf.book id=modal_id readthrough=readthrough class="" %}
|
||||||
|
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -16,19 +16,22 @@
|
||||||
|
|
||||||
{% trans "Start reading" as button_text %}
|
{% trans "Start reading" as button_text %}
|
||||||
{% url 'reading-status' 'start' book.id as fallback_url %}
|
{% url 'reading-status' 'start' book.id as fallback_url %}
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="start_reading" controls_uid=button_uuid focus="modal_title_start_reading" disabled=is_current fallback_url=fallback_url %}
|
{% join "start_reading" button_uuid as modal_id %}
|
||||||
|
{% include 'snippets/shelve_button/modal_button.html' with class=class fallback_url=fallback_url %}
|
||||||
|
|
||||||
{% elif shelf.identifier == 'read' %}
|
{% elif shelf.identifier == 'read' %}
|
||||||
|
|
||||||
{% trans "Read" as button_text %}
|
{% trans "Read" as button_text %}
|
||||||
{% url 'reading-status' 'finish' book.id as fallback_url %}
|
{% url 'reading-status' 'finish' book.id as fallback_url %}
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="finish_reading" controls_uid=button_uuid focus="modal_title_finish_reading" disabled=is_current fallback_url=fallback_url %}
|
{% join "finish_reading" button_uuid as modal_id %}
|
||||||
|
{% include 'snippets/shelve_button/modal_button.html' with class=class fallback_url=fallback_url %}
|
||||||
|
|
||||||
{% elif shelf.identifier == 'to-read' %}
|
{% elif shelf.identifier == 'to-read' %}
|
||||||
|
|
||||||
{% trans "Want to read" as button_text %}
|
{% trans "Want to read" as button_text %}
|
||||||
{% url 'reading-status' 'want' book.id as fallback_url %}
|
{% url 'reading-status' 'want' book.id as fallback_url %}
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="want_to_read" controls_uid=button_uuid focus="modal_title_want_to_read" disabled=is_current fallback_url=fallback_url %}
|
{% join "want_to_read" button_uuid as modal_id %}
|
||||||
|
{% include 'snippets/shelve_button/modal_button.html' with class=class fallback_url=fallback_url %}
|
||||||
|
|
||||||
{% elif shelf.editable %}
|
{% elif shelf.editable %}
|
||||||
|
|
||||||
|
@ -47,8 +50,9 @@
|
||||||
|
|
||||||
{% if readthrough and active_shelf.shelf.identifier != 'read' %}
|
{% if readthrough and active_shelf.shelf.identifier != 'read' %}
|
||||||
<li role="menuitem" class="dropdown-item p-0" data-extra-options>
|
<li role="menuitem" class="dropdown-item p-0" data-extra-options>
|
||||||
{% trans "Update progress" as button_text %}
|
<button type="submit" class="button {{ class }}" data-modal-open="progress_update_{{ button_uuid }}">
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="progress_update" controls_uid=button_uuid focus="modal_title_progress_update" %}
|
{% trans "Update progress" %}
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -23,19 +23,22 @@
|
||||||
|
|
||||||
{% trans "Start reading" as button_text %}
|
{% trans "Start reading" as button_text %}
|
||||||
{% url 'reading-status' 'start' book.id as fallback_url %}
|
{% url 'reading-status' 'start' book.id as fallback_url %}
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="start_reading" controls_uid=button_uuid focus="modal_title_start_reading" fallback_url=fallback_url %}
|
{% join "start_reading" button_uuid as modal_id %}
|
||||||
|
{% include 'snippets/shelve_button/modal_button.html' with class=class fallback_url=fallback_url %}
|
||||||
|
|
||||||
{% elif shelf.identifier == 'read' %}
|
{% elif shelf.identifier == 'read' %}
|
||||||
|
|
||||||
{% trans "Finish reading" as button_text %}
|
{% trans "Finish reading" as button_text %}
|
||||||
{% url 'reading-status' 'finish' book.id as fallback_url %}
|
{% url 'reading-status' 'finish' book.id as fallback_url %}
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="finish_reading" controls_uid=button_uuid focus="modal_title_finish_reading" fallback_url=fallback_url %}
|
{% join "finish_reading" button_uuid as modal_id %}
|
||||||
|
{% include 'snippets/shelve_button/modal_button.html' with class=class fallback_url=fallback_url %}
|
||||||
|
|
||||||
{% elif shelf.identifier == 'to-read' %}
|
{% elif shelf.identifier == 'to-read' %}
|
||||||
|
|
||||||
{% trans "Want to read" as button_text %}
|
{% trans "Want to read" as button_text %}
|
||||||
{% url 'reading-status' 'want' book.id as fallback_url %}
|
{% url 'reading-status' 'want' book.id as fallback_url %}
|
||||||
{% include 'snippets/toggle/toggle_button.html' with class=class text=button_text controls_text="want_to_read" controls_uid=button_uuid focus="modal_title_want_to_read" fallback_url=fallback_url %}
|
{% join "want_to_read" button_uuid as modal_id %}
|
||||||
|
{% include 'snippets/shelve_button/modal_button.html' with class=class fallback_url=fallback_url %}
|
||||||
|
|
||||||
{% elif shelf.editable %}
|
{% elif shelf.editable %}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,12 @@ def get_uuid(identifier):
|
||||||
return f"{identifier}{uuid4()}"
|
return f"{identifier}{uuid4()}"
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=False)
|
||||||
|
def join(*args):
|
||||||
|
"""concatenate an arbitary set of values"""
|
||||||
|
return "_".join(str(a) for a in args)
|
||||||
|
|
||||||
|
|
||||||
@register.filter(name="username")
|
@register.filter(name="username")
|
||||||
def get_user_identifier(user):
|
def get_user_identifier(user):
|
||||||
"""use localname for local users, username for remote"""
|
"""use localname for local users, username for remote"""
|
||||||
|
|
|
@ -483,7 +483,6 @@ class ModelFields(TestCase):
|
||||||
|
|
||||||
instance.set_field_from_activity(book, mock_activity)
|
instance.set_field_from_activity(book, mock_activity)
|
||||||
self.assertIsNotNone(book.cover.name)
|
self.assertIsNotNone(book.cover.name)
|
||||||
self.assertEqual(book.cover.size, 43200)
|
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
def test_image_field_set_field_from_activity_no_overwrite_no_cover(self, *_):
|
def test_image_field_set_field_from_activity_no_overwrite_no_cover(self, *_):
|
||||||
|
@ -510,7 +509,6 @@ class ModelFields(TestCase):
|
||||||
|
|
||||||
instance.set_field_from_activity(book, mock_activity, overwrite=False)
|
instance.set_field_from_activity(book, mock_activity, overwrite=False)
|
||||||
self.assertIsNotNone(book.cover.name)
|
self.assertIsNotNone(book.cover.name)
|
||||||
self.assertEqual(book.cover.size, 43200)
|
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
def test_image_field_set_field_from_activity_no_overwrite_with_cover(self, *_):
|
def test_image_field_set_field_from_activity_no_overwrite_with_cover(self, *_):
|
||||||
|
@ -539,14 +537,15 @@ class ModelFields(TestCase):
|
||||||
)
|
)
|
||||||
book = Edition.objects.create(title="hello")
|
book = Edition.objects.create(title="hello")
|
||||||
book.cover.save("test.jpg", ContentFile(output.getvalue()))
|
book.cover.save("test.jpg", ContentFile(output.getvalue()))
|
||||||
self.assertEqual(book.cover.size, 2136)
|
cover_size = book.cover.size
|
||||||
|
self.assertIsNotNone(cover_size)
|
||||||
|
|
||||||
MockActivity = namedtuple("MockActivity", ("cover"))
|
MockActivity = namedtuple("MockActivity", ("cover"))
|
||||||
mock_activity = MockActivity("http://www.example.com/image.jpg")
|
mock_activity = MockActivity("http://www.example.com/image.jpg")
|
||||||
|
|
||||||
instance.set_field_from_activity(book, mock_activity, overwrite=False)
|
instance.set_field_from_activity(book, mock_activity, overwrite=False)
|
||||||
# same cover as before
|
# same cover as before
|
||||||
self.assertEqual(book.cover.size, 2136)
|
self.assertEqual(book.cover.size, cover_size)
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
def test_image_field_set_field_from_activity_with_overwrite_with_cover(self, *_):
|
def test_image_field_set_field_from_activity_with_overwrite_with_cover(self, *_):
|
||||||
|
@ -559,7 +558,8 @@ class ModelFields(TestCase):
|
||||||
image.save(output, format=image.format)
|
image.save(output, format=image.format)
|
||||||
book = Edition.objects.create(title="hello")
|
book = Edition.objects.create(title="hello")
|
||||||
book.cover.save("test.jpg", ContentFile(output.getvalue()))
|
book.cover.save("test.jpg", ContentFile(output.getvalue()))
|
||||||
self.assertEqual(book.cover.size, 2136)
|
cover_size = book.cover.size
|
||||||
|
self.assertIsNotNone(cover_size)
|
||||||
|
|
||||||
another_image_file = pathlib.Path(__file__).parent.joinpath(
|
another_image_file = pathlib.Path(__file__).parent.joinpath(
|
||||||
"../../static/images/logo.png"
|
"../../static/images/logo.png"
|
||||||
|
@ -583,7 +583,7 @@ class ModelFields(TestCase):
|
||||||
instance.set_field_from_activity(book, mock_activity, overwrite=True)
|
instance.set_field_from_activity(book, mock_activity, overwrite=True)
|
||||||
# new cover
|
# new cover
|
||||||
self.assertIsNotNone(book.cover.name)
|
self.assertIsNotNone(book.cover.name)
|
||||||
self.assertEqual(book.cover.size, 376800)
|
self.assertNotEqual(book.cover.size, cover_size)
|
||||||
|
|
||||||
def test_datetime_field(self, *_):
|
def test_datetime_field(self, *_):
|
||||||
"""this one is pretty simple, it just has to use isoformat"""
|
"""this one is pretty simple, it just has to use isoformat"""
|
||||||
|
|
|
@ -24,7 +24,7 @@ LAST_DAY = 15
|
||||||
class AnnualSummary(View):
|
class AnnualSummary(View):
|
||||||
"""display a summary of the year for the current user"""
|
"""display a summary of the year for the current user"""
|
||||||
|
|
||||||
def get(self, request, username, year):
|
def get(self, request, username, year): # pylint: disable=too-many-locals
|
||||||
"""get response"""
|
"""get response"""
|
||||||
|
|
||||||
user = get_user_from_username(request.user, username)
|
user = get_user_from_username(request.user, username)
|
||||||
|
@ -79,6 +79,9 @@ class AnnualSummary(View):
|
||||||
)
|
)
|
||||||
ratings_stats = ratings.aggregate(Avg("rating"))
|
ratings_stats = ratings.aggregate(Avg("rating"))
|
||||||
|
|
||||||
|
# annual goal status
|
||||||
|
goal_status = get_goal_status(user, year)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"summary_user": user,
|
"summary_user": user,
|
||||||
"year": year,
|
"year": year,
|
||||||
|
@ -101,6 +104,7 @@ class AnnualSummary(View):
|
||||||
review.book.id for review in ratings.filter(rating=5)
|
review.book.id for review in ratings.filter(rating=5)
|
||||||
],
|
],
|
||||||
"paginated_years": paginated_years,
|
"paginated_years": paginated_years,
|
||||||
|
"goal_status": goal_status,
|
||||||
}
|
}
|
||||||
|
|
||||||
return TemplateResponse(request, "annual_summary/layout.html", data)
|
return TemplateResponse(request, "annual_summary/layout.html", data)
|
||||||
|
@ -208,3 +212,17 @@ def get_books_from_shelfbooks(books_ids):
|
||||||
books = models.Edition.objects.filter(id__in=books_ids).order_by(ordered)
|
books = models.Edition.objects.filter(id__in=books_ids).order_by(ordered)
|
||||||
|
|
||||||
return books
|
return books
|
||||||
|
|
||||||
|
|
||||||
|
def get_goal_status(user, year):
|
||||||
|
"""return a dict with the year's goal status"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
goal = models.AnnualGoal.objects.get(user=user, year=year)
|
||||||
|
except models.AnnualGoal.DoesNotExist:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if goal.privacy != "public":
|
||||||
|
return None
|
||||||
|
|
||||||
|
return dict(**goal.progress, **{"goal": goal.goal})
|
||||||
|
|
|
@ -26,15 +26,15 @@ class Feed(View):
|
||||||
|
|
||||||
def post(self, request, tab):
|
def post(self, request, tab):
|
||||||
"""save feed settings form, with a silent validation fail"""
|
"""save feed settings form, with a silent validation fail"""
|
||||||
settings_saved = False
|
filters_applied = False
|
||||||
form = forms.FeedStatusTypesForm(request.POST, instance=request.user)
|
form = forms.FeedStatusTypesForm(request.POST, instance=request.user)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
form.save()
|
form.save()
|
||||||
settings_saved = True
|
filters_applied = True
|
||||||
|
|
||||||
return self.get(request, tab, settings_saved)
|
return self.get(request, tab, filters_applied)
|
||||||
|
|
||||||
def get(self, request, tab, settings_saved=False):
|
def get(self, request, tab, filters_applied=False):
|
||||||
"""user's homepage with activity feed"""
|
"""user's homepage with activity feed"""
|
||||||
tab = [s for s in STREAMS if s["key"] == tab]
|
tab = [s for s in STREAMS if s["key"] == tab]
|
||||||
tab = tab[0] if tab else STREAMS[0]
|
tab = tab[0] if tab else STREAMS[0]
|
||||||
|
@ -61,7 +61,7 @@ class Feed(View):
|
||||||
"goal_form": forms.GoalForm(),
|
"goal_form": forms.GoalForm(),
|
||||||
"feed_status_types_options": FeedFilterChoices,
|
"feed_status_types_options": FeedFilterChoices,
|
||||||
"allowed_status_types": request.user.feed_status_types,
|
"allowed_status_types": request.user.feed_status_types,
|
||||||
"settings_saved": settings_saved,
|
"filters_applied": filters_applied,
|
||||||
"path": f"/{tab['key']}",
|
"path": f"/{tab['key']}",
|
||||||
"annual_summary_year": get_annual_summary_year(),
|
"annual_summary_year": get_annual_summary_year(),
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue