Merge branch 'main' into production

This commit is contained in:
Mouse Reeve 2021-05-05 08:39:21 -07:00
commit 0ff7c84a14
29 changed files with 137 additions and 85 deletions

View file

@ -39,3 +39,6 @@
</div>
{% endblock %}
{% block scripts %}
{% include 'snippets/datepicker_js.html' %}
{% endblock %}

View file

@ -333,4 +333,5 @@
{% block scripts %}
<script src="/static/js/vendor/tabs.js"></script>
{% include 'snippets/datepicker_js.html' %}
{% endblock %}

View file

@ -133,7 +133,11 @@
<p class="mb-2">
<label class="label" for="id_first_published_date">{% trans "First published date:" %}</label>
<input type="date" name="first_published_date" class="input" id="id_first_published_date"{% if form.first_published_date.value %} value="{{ form.first_published_date.value|date:'Y-m-d' }}"{% endif %}>
<duet-date-picker
identifier="id_first_published_date"
name="first_published_date"
{% if form.first_published_date.value %}value="{{ form.first_published_date.value|date:'Y-m-d' }}"{% endif %}
></duet-date-picker>
</p>
{% for error in form.first_published_date.errors %}
<p class="help is-danger">{{ error | escape }}</p>
@ -141,7 +145,11 @@
<p class="mb-2">
<label class="label" for="id_published_date">{% trans "Published date:" %}</label>
<input type="date" name="published_date" class="input" id="id_published_date"{% if form.published_date.value %} value="{{ form.published_date.value|date:'Y-m-d'}}"{% endif %}>
<duet-date-picker
identifier="id_published_date"
name="published_date"
{% if form.published_date.value %}value="{{ form.published_date.value|date:'Y-m-d' }}"{% endif %}
></duet-date-picker>
</p>
{% for error in form.published_date.errors %}
<p class="help is-danger">{{ error | escape }}</p>
@ -239,9 +247,13 @@
{% if not confirm_mode %}
<div class="block">
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
<a class="button" href="/book/{{ book.id }}">{% trans "Cancel" %}</a>
<a class="button" href="{{ book.local_path}}">{% trans "Cancel" %}</a>
</div>
{% endif %}
</form>
{% endblock %}
{% block scripts %}
{% include 'snippets/datepicker_js.html' %}
{% endblock %}

View file

@ -15,14 +15,14 @@
{% for book in editions %}
<div class="columns is-gapless mb-6">
<div class="column is-cover">
<a href="/book/{{ book.id }}">
<a href="{{ book.local_path }}">
{% include 'snippets/book_cover.html' with book=book cover_class='is-w-m is-h-m align to-l-mobile' %}
</a>
</div>
<div class="column my-3-mobile ml-3-tablet mr-auto">
<h2 class="title is-5 mb-1">
<a href="/book/{{ book.id }}" class="has-text-black">
<a href="{{ book.local_path }}" class="has-text-black">
{{ book.title }}
</a>
</h2>
@ -51,3 +51,7 @@
{% include 'snippets/pagination.html' with page=editions path=request.path %}
</div>
{% endblock %}
{% block scripts %}
{% include 'snippets/datepicker_js.html' %}
{% endblock %}

View file

@ -17,7 +17,7 @@
<div class="column mt-3-mobile ml-3-tablet">
<h3 class="title is-5">
<a href="/book/{{ book.id }}">{{ book.title }}</a>
<a href="{{ book.local_path }}">{{ book.title }}</a>
</h3>
{% if book.authors %}

View file

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

View file

@ -76,8 +76,12 @@
<div class="block">
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
<a class="button" href="/author/{{ author.id }}">{% trans "Cancel" %}</a>
<a class="button" href="{{ author.local_path }}">{% trans "Cancel" %}</a>
</div>
</form>
{% endblock %}
{% block scripts %}
{% include 'snippets/datepicker_js.html' %}
{% endblock %}

View file

@ -10,7 +10,7 @@
{% trans "Direct Messages" %}
{% endif %}
</h1>
{% if partner %}<p class="subtitle"><a href="/direct-messages"><span class="icon icon-arrow-left" aria-hidden="true"></span> {% trans "All messages" %}</a></p>{% endif %}
{% if partner %}<p class="subtitle"><a href="{% url 'direct-messages' %}"><span class="icon icon-arrow-left" aria-hidden="true"></span> {% trans "All messages" %}</a></p>{% endif %}
</header>
<div class="box">

View file

@ -105,4 +105,5 @@
{% block scripts %}
<script src="/static/js/vendor/tabs.js"></script>
{% include 'snippets/datepicker_js.html' %}
{% endblock %}

View file

@ -64,3 +64,7 @@
</form>
{% endblock %}
{% block scripts %}
{% include 'snippets/datepicker_js.html' %}
{% endblock %}

View file

@ -56,7 +56,7 @@
{% endif %}
<ul>
{% for job in jobs %}
<li><a href="/import/{{ job.id }}">{{ job.created_date | naturaltime }}</a></li>
<li><a href="{% url 'import-status' job.id %}">{{ job.created_date | naturaltime }}</a></li>
{% endfor %}
</ul>
</div>

View file

@ -124,7 +124,7 @@
<tr>
<td>
{% if item.book %}
<a href="/book/{{ item.book.id }}">
<a href="{{ item.book.local_path }}">
{% include 'snippets/book_cover.html' with book=item.book cover_class='is-h-s' %}
</a>
{% endif %}

View file

@ -94,12 +94,12 @@
</a>
</li>
<li>
<a href="/import" class="navbar-item">
<a href="{% url 'import' %}" class="navbar-item">
{% trans 'Import Books' %}
</a>
</li>
<li>
<a href="/preferences/profile" class="navbar-item">
<a href="{% url 'prefs-profile' %}" class="navbar-item">
{% trans 'Settings' %}
</a>
</li>
@ -122,14 +122,14 @@
{% endif %}
<li class="navbar-divider" role="presentation"></li>
<li>
<a href="/logout" class="navbar-item">
<a href="{% url 'logout' %}" class="navbar-item">
{% trans 'Log out' %}
</a>
</li>
</ul>
</div>
<div class="navbar-item">
<a href="/notifications" class="tags has-addons">
<a href="{% url 'notifications' %}" class="tags has-addons">
<span class="tag is-medium">
<span class="icon icon-bell" title="{% trans 'Notifications' %}">
<span class="is-sr-only">{% trans "Notifications" %}</span>
@ -158,7 +158,7 @@
<div class="column">
<label class="is-sr-only" for="id_password">{% trans "Username:" %}</label>
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password" placeholder="{% trans 'password' %}">
<p class="help"><a href="/password-reset">{% trans "Forgot your password?" %}</a></p>
<p class="help"><a href="{% url 'password-reset' %}">{% trans "Forgot your password?" %}</a></p>
</div>
<div class="column is-narrow">
<button class="button is-primary" type="submit">{% trans "Log in" %}</button>
@ -195,7 +195,7 @@
<div class="columns">
<div class="column is-one-fifth">
<p>
<a href="/about">{% trans "About this server" %}</a>
<a href="{% url 'about' %}">{% trans "About this server" %}</a>
</p>
{% if site.admin_email %}
<p>

View file

@ -33,7 +33,7 @@
<button class="button is-primary" type="submit">{% trans "Log in" %}</button>
</div>
<div class="control">
<small><a href="/password-reset">{% trans "Forgot your password?" %}</a></small>
<small><a href="{% url 'password-reset' %}">{% trans "Forgot your password?" %}</a></small>
</div>
</div>
</form>
@ -56,7 +56,7 @@
{% include 'snippets/about.html' %}
<p class="block">
<a href="/about/">{% trans "More about this site" %}</a>
<a href="{% url 'about' %}">{% trans "More about this site" %}</a>
</p>
</div>
</div>

View file

@ -107,7 +107,8 @@
{% endif %}
{% endif %}
{% elif notification.related_import %}
{% blocktrans with related_id=notification.related_import.id %}Your <a href="/import/{{ related_id }}">import</a> completed.{% endblocktrans %}
{% url 'import-status' notification.related_import.id as url %}
{% blocktrans %}Your <a href="{{ url }}">import</a> completed.{% endblocktrans %}
{% elif notification.related_report %}
{% url 'settings-report' notification.related_report.id as path %}
{% blocktrans with related_id=path %}A new <a href="{{ path }}">report</a> needs moderation.{% endblocktrans %}

View file

@ -11,16 +11,19 @@
<h2 class="menu-label">{% trans "Account" %}</h2>
<ul class="menu-list">
<li>
<a href="/preferences/profile"{% if '/preferences/profile' in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Profile" %}</a>
{% url 'prefs-profile' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Profile" %}</a>
</li>
<li>
<a href="/preferences/password"{% if '/preferences/password' in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Change Password" %}</a>
{% url 'prefs-password' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Change Password" %}</a>
</li>
</ul>
<h2 class="menu-label">{% trans "Relationships" %}</h2>
<ul class="menu-list">
<li>
<a href="/preferences/block"{% if '/preferences/block' in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Blocked Users" %}</a>
{% url 'prefs-block' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Blocked Users" %}</a>
</li>
</ul>
</nav>

View file

@ -5,7 +5,7 @@
{% endcomment %}
{% for author in book.authors.all %}
<a
href="/author/{{ author.id }}"
href="{{ author.local_path }}"
class="author"
itemprop="author"
itemscope

View file

@ -3,7 +3,7 @@
<div class="column is-narrow">
<div class="box is-flex is-flex-direction-column is-align-items-center">
<div class="mb-3">
<a href="/book/{{ book.id }}">
<a href="{{ book.local_path }}">
{% include 'snippets/book_cover.html' with book=book cover_class='is-w-l-mobile is-h-l-mobile is-w-l-tablet is-h-xl-tablet' %}
</a>
</div>

View file

@ -0,0 +1,3 @@
<script type="module" src="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.3.0/dist/duet/duet.esm.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.3.0/dist/duet/duet.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.3.0/dist/duet/themes/default.css" />

View file

@ -5,7 +5,11 @@
<div class="field">
<label class="label">
{% trans "Started reading" %}
<input type="date" name="start_date" class="input" id="id_start_date-{{ readthrough.id }}" value="{{ readthrough.start_date | date:"Y-m-d" }}">
<duet-date-picker
identifier="id_start_date-{{ readthrough.id }}"
name="start_date"
value="{{ readthrough.start_date | date:'Y-m-d' }}">
</duet-date-picker>
</label>
</div>
{# Only show progress for editing existing readthroughs #}
@ -28,6 +32,10 @@
<div class="field">
<label class="label">
{% trans "Finished reading" %}
<input type="date" name="finish_date" class="input" id="id_finish_date-{{ readthrough.id }}" value="{{ readthrough.finish_date | date:"Y-m-d" }}">
<duet-date-picker
identifier="id_finish_date-{{ readthrough.id }}"
name="finish_date"
value="{{ readthrough.finish_date | date:'Y-m-d' }}">
</duet-date-picker>
</label>
</div>

View file

@ -17,13 +17,21 @@
<div class="field">
<label class="label">
{% trans "Started reading" %}
<input type="date" name="start_date" class="input" id="finish_id_start_date-{{ uuid }}" value="{{ readthrough.start_date | date:"Y-m-d" }}">
<duet-date-picker
identifier="id_start_date-{{ uuid }}"
name="start_date"
value="{{ readthrough.start_date | date:'Y-m-d' }}"
></duet-date-picker>
</label>
</div>
<div class="field">
<label class="label">
{% trans "Finished reading" %}
<input type="date" name="finish_date" class="input" id="id_finish_date-{{ uuid }}" value="{% now "Y-m-d" %}">
<duet-date-picker
identifier="id_finish_date-{{ uuid }}"
name="finish_date"
value="{{ readthrough.finish_date | date:'Y-m-d' }}"
></duet-date-picker>
</label>
</div>
</section>

View file

@ -15,7 +15,11 @@
<div class="field">
<label class="label">
{% trans "Started reading" %}
<input type="date" name="start_date" class="input" id="start_id_start_date-{{ uuid }}" value="{% now "Y-m-d" %}">
<duet-date-picker
identifier="start_id_start_date-{{ uuid }}"
name="start_date"
value="{% now "Y-m-d" %}"
></duet-date-picker>
</label>
</div>
</section>

View file

@ -44,7 +44,7 @@
{% else %}
<div class="card-footer-item">
<a href="/login">
<a href="{% url 'login' %}">
<span class="icon icon-comment is-small" title="{% trans 'Reply' %}">
<span class="is-sr-only">{% trans "Reply" %}</span>
</span>

View file

@ -47,7 +47,7 @@
{% if status.book %}
{% if status.status_type == 'GeneratedNote' or status.status_type == 'Rating' %}
<a href="/book/{{ status.book.id }}">{{ status.book|title }}</a>{% if status.status_type == 'Rating' %}: {% include 'snippets/stars.html' with rating=status.rating %}
<a href="{{ status.book.local_path }}">{{ status.book|title }}</a>{% if status.status_type == 'Rating' %}: {% include 'snippets/stars.html' with rating=status.rating %}
<span
itemprop="reviewRating"
itemscope
@ -58,7 +58,7 @@
{% if status.book %}
{% if status.status_type == 'GeneratedNote' or status.status_type == 'Rating' %}
<a href="/book/{{ status.book.id }}">{{ status.book|title }}</a>{% if status.status_type == 'Rating' %}:
<a href="{{ status.book.local_path }}">{{ status.book|title }}</a>{% if status.status_type == 'Rating' %}:
<span
itemprop="reviewRating"
itemscope
@ -76,7 +76,7 @@
{% include 'snippets/book_titleby.html' with book=status.book %}
{% endif %}
{% elif status.mention_books %}
<a href="/book/{{ status.mention_books.first.id }}">
<a href="{{ status.mention_books.first.local_path }}">
{{ status.mention_books.first.title }}
</a>
{% endif %}
@ -86,7 +86,7 @@
{% include 'snippets/book_titleby.html' with book=status.book %}
{% endif %}
{% elif status.mention_books %}
<a href="/book/{{ status.mention_books.first.id }}">{{ status.mention_books.first|title }}</a>
<a href="{{ status.mention_books.first.local_path }}">{{ status.mention_books.first|title }}</a>
{% endif %}
</h3>

View file

@ -10,7 +10,7 @@
{% block dropdown-list %}
<li role="menuitem">
<a href="/direct-messages/{{ user|username }}" class="button is-fullwidth is-small">{% trans "Send direct message" %}</a>
<a href="{% url 'direct-messages-user' user|username %}" class="button is-fullwidth is-small">{% trans "Send direct message" %}</a>
</li>
<li role="menuitem">
{% include 'snippets/report_button.html' with user=user class="is-fullwidth" %}

View file

@ -81,3 +81,8 @@
{% block panel %}{% endblock %}
{% endblock %}
{% block scripts %}
{% include 'snippets/datepicker_js.html' %}
{% endblock %}

View file

@ -35,29 +35,49 @@ class InboxAdd(TestCase):
work = models.Work.objects.create(title="work title")
self.book = models.Edition.objects.create(
title="Test",
remote_id="https://bookwyrm.social/book/37292",
remote_id="https://example.com/book/37292",
parent_work=work,
)
models.SiteSettings.objects.create()
@responses.activate
def test_handle_add_book_to_shelf(self):
"""shelving a book"""
shelf = models.Shelf.objects.create(user=self.remote_user, name="Test Shelf")
shelf.remote_id = "https://bookwyrm.social/user/mouse/shelf/to-read"
shelf.remote_id = "https://example.com/user/rat/shelf/to-read"
shelf.save()
responses.add(
responses.GET,
"https://example.com/user/rat/shelf/to-read",
json={
"id": shelf.remote_id,
"type": "Shelf",
"totalItems": 1,
"first": "https://example.com/shelf/22?page=1",
"last": "https://example.com/shelf/22?page=1",
"name": "Test Shelf",
"owner": self.remote_user.remote_id,
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"cc": ["https://example.com/user/rat/followers"],
"summary": "summary text",
"curation": "curated",
"@context": "https://www.w3.org/ns/activitystreams",
},
)
activity = {
"id": "https://bookwyrm.social/shelfbook/6189#add",
"id": "https://example.com/shelfbook/6189#add",
"type": "Add",
"actor": "https://example.com/users/rat",
"object": {
"actor": self.remote_user.remote_id,
"type": "ShelfItem",
"book": self.book.remote_id,
"id": "https://bookwyrm.social/shelfbook/6189",
"id": "https://example.com/shelfbook/6189",
},
"target": "https://bookwyrm.social/user/mouse/shelf/to-read",
"target": "https://example.com/user/rat/shelf/to-read",
"@context": "https://www.w3.org/ns/activitystreams",
}
views.inbox.activity_task(activity)
@ -68,7 +88,7 @@ class InboxAdd(TestCase):
"""listing a book"""
responses.add(
responses.GET,
"https://bookwyrm.social/user/mouse/list/to-read",
"https://example.com/user/mouse/list/to-read",
json={
"id": "https://example.com/list/22",
"type": "BookList",
@ -86,17 +106,17 @@ class InboxAdd(TestCase):
)
activity = {
"id": "https://bookwyrm.social/listbook/6189#add",
"id": "https://example.com/listbook/6189#add",
"type": "Add",
"actor": "https://example.com/users/rat",
"object": {
"actor": self.remote_user.remote_id,
"type": "ListItem",
"book": self.book.remote_id,
"id": "https://bookwyrm.social/listbook/6189",
"id": "https://example.com/listbook/6189",
"order": 1,
},
"target": "https://bookwyrm.social/user/mouse/list/to-read",
"target": "https://example.com/user/mouse/list/to-read",
"@context": "https://www.w3.org/ns/activitystreams",
}
views.inbox.activity_task(activity)
@ -105,4 +125,4 @@ class InboxAdd(TestCase):
listitem = models.ListItem.objects.get()
self.assertEqual(booklist.name, "Test List")
self.assertEqual(booklist.books.first(), self.book)
self.assertEqual(listitem.remote_id, "https://bookwyrm.social/listbook/6189")
self.assertEqual(listitem.remote_id, "https://example.com/listbook/6189")

View file

@ -47,39 +47,6 @@ class BookViews(TestCase):
)
models.SiteSettings.objects.create()
def test_date_regression(self):
"""ensure that creating a new book actually saves the published date fields
this was initially a regression due to using a custom date picker tag
"""
first_published_date = "2021-04-20"
published_date = "2022-04-20"
self.local_user.groups.add(self.group)
view = views.EditBook.as_view()
form = forms.EditionForm(
{
"title": "New Title",
"last_edited_by": self.local_user.id,
"first_published_date": first_published_date,
"published_date": published_date,
}
)
request = self.factory.post("", form.data)
request.user = self.local_user
with patch("bookwyrm.connectors.connector_manager.local_search"):
result = view(request)
result.render()
self.assertContains(
result,
f'<input type="date" name="first_published_date" class="input" id="id_first_published_date" value="{first_published_date}">',
)
self.assertContains(
result,
f'<input type="date" name="published_date" class="input" id="id_published_date" value="{published_date}">',
)
def test_book_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.Book.as_view()

View file

@ -45,8 +45,12 @@ urlpatterns = [
# authentication
re_path(r"^login/?$", views.Login.as_view(), name="login"),
re_path(r"^register/?$", views.Register.as_view()),
re_path(r"^logout/?$", views.Logout.as_view()),
re_path(r"^password-reset/?$", views.PasswordResetRequest.as_view()),
re_path(r"^logout/?$", views.Logout.as_view(), name="logout"),
re_path(
r"^password-reset/?$",
views.PasswordResetRequest.as_view(),
name="password-reset",
),
re_path(
r"^password-reset/(?P<code>[A-Za-z0-9]+)/?$", views.PasswordReset.as_view()
),
@ -134,7 +138,7 @@ urlpatterns = [
re_path(r"^about/?$", views.About.as_view(), name="about"),
path("", views.Home.as_view(), name="landing"),
re_path(r"^discover/?$", views.Discover.as_view()),
re_path(r"^notifications/?$", views.Notifications.as_view()),
re_path(r"^notifications/?$", views.Notifications.as_view(), name="notifications"),
re_path(r"^directory/?", views.Directory.as_view(), name="directory"),
# Get started
re_path(
@ -165,8 +169,8 @@ urlpatterns = [
# search
re_path(r"^search/?$", views.Search.as_view(), name="search"),
# imports
re_path(r"^import/?$", views.Import.as_view()),
re_path(r"^import/(\d+)/?$", views.ImportStatus.as_view()),
re_path(r"^import/?$", views.Import.as_view(), name="import"),
re_path(r"^import/(\d+)/?$", views.ImportStatus.as_view(), name="import-status"),
# users
re_path(r"%s/?$" % user_path, views.User.as_view(), name="user-feed"),
re_path(r"%s\.json$" % user_path, views.User.as_view()),
@ -229,7 +233,7 @@ urlpatterns = [
views.ChangePassword.as_view(),
name="prefs-password",
),
re_path(r"^preferences/block/?$", views.Block.as_view()),
re_path(r"^preferences/block/?$", views.Block.as_view(), name="prefs-block"),
re_path(r"^block/(?P<user_id>\d+)/?$", views.Block.as_view()),
re_path(r"^unblock/(?P<user_id>\d+)/?$", views.unblock),
# statuses