forked from mirrors/bookwyrm
Merge branch 'main' into production
This commit is contained in:
commit
f6026f5ed8
13 changed files with 110 additions and 143 deletions
|
@ -1,13 +1,13 @@
|
||||||
''' functionality outline for a book data connector '''
|
''' functionality outline for a book data connector '''
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from dateutil import parser
|
|
||||||
import pytz
|
import pytz
|
||||||
import requests
|
|
||||||
from requests import HTTPError
|
|
||||||
from urllib3.exceptions import RequestError
|
from urllib3.exceptions import RequestError
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from dateutil import parser
|
||||||
|
import requests
|
||||||
|
from requests import HTTPError
|
||||||
|
|
||||||
from bookwyrm import models
|
from bookwyrm import models
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,8 @@ def shared_inbox(request):
|
||||||
},
|
},
|
||||||
'Update': {
|
'Update': {
|
||||||
'Person': handle_update_user,
|
'Person': handle_update_user,
|
||||||
'Document': handle_update_book,
|
'Edition': handle_update_book,
|
||||||
|
'Work': handle_update_book,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
activity_type = activity['type']
|
activity_type = activity['type']
|
||||||
|
@ -337,7 +338,7 @@ def handle_update_book(activity):
|
||||||
document = activity['object']
|
document = activity['object']
|
||||||
# check if we have their copy and care about their updates
|
# check if we have their copy and care about their updates
|
||||||
book = models.Book.objects.select_subclasses().filter(
|
book = models.Book.objects.select_subclasses().filter(
|
||||||
remote_id=document['url'],
|
remote_id=document['id'],
|
||||||
sync=True,
|
sync=True,
|
||||||
).first()
|
).first()
|
||||||
if not book:
|
if not book:
|
||||||
|
|
|
@ -82,6 +82,17 @@ class UserFollowRequest(UserRelationship):
|
||||||
''' following a user requires manual or automatic confirmation '''
|
''' following a user requires manual or automatic confirmation '''
|
||||||
status = 'follow_request'
|
status = 'follow_request'
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
''' make sure the follow relationship doesn't already exist '''
|
||||||
|
try:
|
||||||
|
UserFollows.objects.get(
|
||||||
|
user_subject=self.user_subject,
|
||||||
|
user_object=self.user_object
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
except UserFollows.DoesNotExist:
|
||||||
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserBlocks(UserRelationship):
|
class UserBlocks(UserRelationship):
|
||||||
''' prevent another user from following you and seeing your posts '''
|
''' prevent another user from following you and seeing your posts '''
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
{% extends 'layout.html' %}
|
|
||||||
{% block content %}
|
|
||||||
<div class="content-container">
|
|
||||||
<h2>Search results</h2>
|
|
||||||
{% for result_set in results %}
|
|
||||||
{% if result_set.results %}
|
|
||||||
<section>
|
|
||||||
{% if not result_set.connector.local %}
|
|
||||||
<h3>
|
|
||||||
Results from <a href="{{ result_set.connector.base_url }}" target="_blank">{% if result_set.connector.name %}{{ result_set.connector.name }}{% else %}{{ result_set.connector.identifier }}{% endif %}</a>
|
|
||||||
</h3>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for result in result_set.results %}
|
|
||||||
<div>
|
|
||||||
<form action="/resolve_book" method="POST">
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="hidden" name="remote_id" value="{{ result.key }}">
|
|
||||||
<button type="submit">{{ result.title }} by {{ result.author }} ({{ result.year }})</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</section>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
|
@ -1,17 +1,18 @@
|
||||||
{% load fr_display %}
|
{% load fr_display %}
|
||||||
|
{% with book.id|uuid as uuid %}
|
||||||
{% with book|book_description as full %}
|
{% with book|book_description as full %}
|
||||||
{% if full %}
|
{% if full %}
|
||||||
{% with full|text_overflow as trimmed %}
|
{% with full|text_overflow as trimmed %}
|
||||||
{% if trimmed != full %}
|
{% if trimmed != full %}
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" name="show-hide-{{ book.id }}" id="show-{{ book.id }}" class="toggle-control" checked>
|
<input type="radio" name="show-hide-{{ book.id }}-{{ uuid }}" id="show-{{ book.id }}-{{ uuid }}" class="toggle-control" checked>
|
||||||
<blockquote class="content toggle-content hidden">{{ trimmed }}
|
<blockquote class="content toggle-content hidden">{{ trimmed }}
|
||||||
<label class="button is-small" for="hide-{{ book.id }}">show more</label></blockquote>
|
<label class="button is-small" for="hide-{{ book.id }}-{{ uuid }}">show more</label></blockquote>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" name="show-hide-{{ book.id }}" id="hide-{{ book.id }}" class="toggle-control">
|
<input type="radio" name="show-hide-{{ book.id }}-{{ uuid }}" id="hide-{{ book.id }}-{{ uuid }}" class="toggle-control">
|
||||||
<blockquote class="content toggle-content hidden">{{ full }}
|
<blockquote class="content toggle-content hidden">{{ full }}
|
||||||
<label class="button is-small" for="show-{{ book.id }}">show less</label></blockquote>
|
<label class="button is-small" for="show-{{ book.id }}-{{ uuid }}">show less</label></blockquote>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<blockquote class="content">{{ full }}
|
<blockquote class="content">{{ full }}
|
||||||
|
@ -20,3 +21,4 @@
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
{% endwith %}
|
||||||
|
|
12
bookwyrm/templates/snippets/book_preview.html
Normal file
12
bookwyrm/templates/snippets/book_preview.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-left">
|
||||||
|
<div>
|
||||||
|
<a href="/book/{{ book.id }}">{% include 'snippets/book_cover.html' with book=book %}</a>
|
||||||
|
{% include 'snippets/shelve_button.html' with book=book %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="media-content">
|
||||||
|
<h3 class="title is-6">{% include 'snippets/book_titleby.html' with book=book %}</h3>
|
||||||
|
{% include 'snippets/book_description.html' with book=book %}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,4 +1,5 @@
|
||||||
{% load fr_display %}
|
{% load fr_display %}
|
||||||
|
{% with activity.id|uuid as uuid %}
|
||||||
<div class="card-footer-item">
|
<div class="card-footer-item">
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<form name="reply" action="/reply" method="post" onsubmit="return reply(event)">
|
<form name="reply" action="/reply" method="post" onsubmit="return reply(event)">
|
||||||
|
@ -7,7 +8,7 @@
|
||||||
<input type="hidden" name="reply_parent" value="{{ activity.id }}">
|
<input type="hidden" name="reply_parent" value="{{ activity.id }}">
|
||||||
<input type="hidden" name="user" value="{{ request.user.id }}">
|
<input type="hidden" name="user" value="{{ request.user.id }}">
|
||||||
<input type="hidden" name="privacy" value="{{ activity.privacy }}">
|
<input type="hidden" name="privacy" value="{{ activity.privacy }}">
|
||||||
<textarea name="content" placeholder="Leave a comment..." id="id_content_{{ activity.id }}" required="true"></textarea>
|
<textarea name="content" placeholder="Leave a comment..." id="id_content_{{ activity.id }}-{{ uuid }}" required="true"></textarea>
|
||||||
<button class="button" type="submit">
|
<button class="button" type="submit">
|
||||||
<span class="icon icon-comment">
|
<span class="icon icon-comment">
|
||||||
<span class="is-sr-only">Comment</span>
|
<span class="is-sr-only">Comment</span>
|
||||||
|
@ -16,7 +17,7 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form name="boost" action="/boost/{{ activity.id }}" method="post" onsubmit="return interact(event)" class="boost-{{ status.id }} {% if request.user|boosted:status %}hidden{% endif %}" data-id="boost-{{ status.id }}">
|
<form name="boost" action="/boost/{{ activity.id }}" method="post" onsubmit="return interact(event)" class="boost-{{ status.id }} {% if request.user|boosted:status %}hidden{% endif %}" data-id="boost-{{ status.id }}-{{ uuid }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button class="button" type="submit">
|
<button class="button" type="submit">
|
||||||
<span class="icon icon-boost">
|
<span class="icon icon-boost">
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<form name="unboost" action="/unboost/{{ activity.id }}" method="post" onsubmit="return interact(event)" class="boost-{{ status.id }} active {% if not request.user|boosted:status %}hidden{% endif %}" data-id="boost-{{ status.id }}">
|
<form name="unboost" action="/unboost/{{ activity.id }}" method="post" onsubmit="return interact(event)" class="boost-{{ status.id }} active {% if not request.user|boosted:status %}hidden{% endif %}" data-id="boost-{{ status.id }}-{{ uuid }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button class="button is-success" type="submit">
|
<button class="button is-success" type="submit">
|
||||||
<span class="icon icon-boost">
|
<span class="icon icon-boost">
|
||||||
|
@ -33,7 +34,7 @@
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form name="favorite" action="/favorite/{{ activity.id }}" method="POST" onsubmit="return interact(event)" class="fav-{{ status.id }} {% if request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}">
|
<form name="favorite" action="/favorite/{{ activity.id }}" method="POST" onsubmit="return interact(event)" class="fav-{{ status.id }} {% if request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button class="button" type="submit">
|
<button class="button" type="submit">
|
||||||
<span class="icon icon-heart">
|
<span class="icon icon-heart">
|
||||||
|
@ -41,7 +42,7 @@
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<form name="unfavorite" action="/unfavorite/{{ activity.id }}" method="POST" onsubmit="return interact(event)" class="fav-{{ status.id }} active {% if not request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}">
|
<form name="unfavorite" action="/unfavorite/{{ activity.id }}" method="POST" onsubmit="return interact(event)" class="fav-{{ status.id }} active {% if not request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button class="button is-success" type="submit">
|
<button class="button is-success" type="submit">
|
||||||
<span class="icon icon-heart">
|
<span class="icon icon-heart">
|
||||||
|
@ -65,3 +66,4 @@
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endwith %}
|
||||||
|
|
|
@ -4,12 +4,25 @@
|
||||||
{% if not status.deleted %}
|
{% if not status.deleted %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<header class="card-header">
|
<header class="card-header">
|
||||||
{% include 'snippets/status_header.html' with status=status %}
|
<div class="card-header-title">
|
||||||
|
<p>
|
||||||
|
{% if status.status_type == 'Boost' %}
|
||||||
|
{% include 'snippets/avatar.html' with user=status.user %}
|
||||||
|
{% include 'snippets/username.html' with user=status.user %}
|
||||||
|
boosted
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{% include 'snippets/status_header.html' with status=status|boosted_status %}
|
||||||
|
{% else %}
|
||||||
|
{% include 'snippets/status_header.html' with status=status %}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
{% if status.status_type == 'Boost' %}
|
{% if status.status_type == 'Boost' %}
|
||||||
{% include 'snippets/status_content.html' with status=status.boosted_status %}
|
{% include 'snippets/status_content.html' with status=status|boosted_status %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% include 'snippets/status_content.html' with status=status %}
|
{% include 'snippets/status_content.html' with status=status %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -17,7 +30,7 @@
|
||||||
|
|
||||||
<footer class="card-footer">
|
<footer class="card-footer">
|
||||||
{% if status.status_type == 'Boost' %}
|
{% if status.status_type == 'Boost' %}
|
||||||
{% include 'snippets/interaction.html' with activity=status.boosted_status %}
|
{% include 'snippets/interaction.html' with activity=status|boosted_status %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% include 'snippets/interaction.html' with activity=status %}
|
{% include 'snippets/interaction.html' with activity=status %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,64 +1,31 @@
|
||||||
{% load fr_display %}
|
{% load fr_display %}
|
||||||
|
<div class="block">
|
||||||
|
{% if status.status_type == 'Review' %}
|
||||||
|
<h3>
|
||||||
|
{% if status.name %}{{ status.name }}<br>{% endif %}
|
||||||
|
{% include 'snippets/stars.html' with rating=status.rating %}
|
||||||
|
</h3>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="media">
|
{% if status.quote %}
|
||||||
{% if not hide_book and status.mention_books.count %}
|
<div class="quote block">
|
||||||
<div class="media-left">
|
<blockquote>{{ status.quote }}</blockquote>
|
||||||
<div class="columns">
|
|
||||||
{% for book in status.mention_books.all|slice:"0:4" %}
|
<p> — {% include 'snippets/book_titleby.html' with book=status.book %}</p>
|
||||||
<div class="column">
|
|
||||||
<a href="/book/{{ book.id }}">{% include 'snippets/book_cover.html' with book=book %}</a>
|
|
||||||
{% if status.mention_books.count > 1 %}
|
|
||||||
<p>{% include 'snippets/book_titleby.html' with book=book %}</p>
|
|
||||||
{% endif %}
|
|
||||||
{% include 'snippets/shelve_button.html' with book=book %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if not hide_book and status.book %}
|
{% if status.content and status.status_type != 'GeneratedNote' and status.status_type != 'Boost' %}
|
||||||
<div class="media-left">
|
<blockquote>{{ status.content | safe }}</blockquote>
|
||||||
<div>
|
|
||||||
<a href="/book/{{ status.book.id }}">{% include 'snippets/book_cover.html' with book=status.book %}</a>
|
|
||||||
{% include 'snippets/shelve_button.html' with book=status.book %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="media-content">
|
|
||||||
{% if status.status_type == 'Review' %}
|
|
||||||
<h3>
|
|
||||||
{% if status.name %}{{ status.name }}<br>{% endif %}
|
|
||||||
{% include 'snippets/stars.html' with rating=status.rating %}
|
|
||||||
</h3>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if status.quote %}
|
|
||||||
<div class="quote block">
|
|
||||||
<blockquote>{{ status.quote }}</blockquote>
|
|
||||||
|
|
||||||
<p> — {% include 'snippets/book_titleby.html' with book=status.book %}</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if status.content and status.status_type != 'GeneratedNote' and status.status_type != 'Boost' %}
|
|
||||||
<blockquote>{{ status.content | safe }}</blockquote>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if status.mention_books.count == 1 and not status.book %}
|
|
||||||
{% include 'snippets/book_description.html' with book=status.mention_books.first %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if not status.content and status.book and not hide_book and status.status_type != 'Boost' %}
|
|
||||||
{% include 'snippets/book_description.html' with book=status.book %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if status.status_type == 'Boost' %}
|
|
||||||
{% include 'snippets/status_content.html' with status=status|boosted_status %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if not max_depth and status.reply_parent or status|replies %}<p><a href="{{ status.remote_id }}">Thread</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if status.book or status.mention_books.count %}
|
||||||
|
<div class="{% if status.status_type != 'GeneratedNote' %}box{% endif %}">
|
||||||
|
{% if status.book %}
|
||||||
|
{% include 'snippets/book_preview.html' with book=status.book %}
|
||||||
|
{% elif status.mention_books.count %}
|
||||||
|
{% include 'snippets/book_preview.html' with book=status.mention_books.first %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
{% load fr_display %}
|
{% load fr_display %}
|
||||||
<div class="card-header-title">
|
{% include 'snippets/avatar.html' with user=status.user %}
|
||||||
<p>
|
{% include 'snippets/username.html' with user=status.user %}
|
||||||
{% include 'snippets/avatar.html' with user=status.user %}
|
|
||||||
|
|
||||||
{% include 'snippets/username.html' with user=status.user %}
|
{% if status.status_type == 'GeneratedNote' %}
|
||||||
{% if status.status_type == 'GeneratedNote' %}
|
{{ status.content | safe }}
|
||||||
{{ status.content | safe }} {% include 'snippets/book_titleby.html' with book=status.mention_books.first %}
|
{% elif status.status_type == 'Review' and not status.name and not status.content%}
|
||||||
{% elif status.status_type == 'Boost' %}
|
rated
|
||||||
boosted {% include 'snippets/avatar.html' with user=status.boosted_status.user %}{% include 'snippets/username.html' with user=status.boosted_status.user possessive=True %} status
|
{% elif status.status_type == 'Review' %}
|
||||||
{% elif status.status_type == 'Review' and not status.name and not status.content%}
|
reviewed
|
||||||
rated <a href="/book/{{ status.book.id }}">{{ status.book.title }}</a>
|
{% elif status.status_type == 'Comment' %}
|
||||||
{% elif status.status_type == 'Review' %}
|
commented on
|
||||||
reviewed <a href="/book/{{ status.book.id }}">{{ status.book.title }}</a>
|
{% elif status.status_type == 'Quotation' %}
|
||||||
{% elif status.status_type == 'Comment' %}
|
quoted
|
||||||
commented on <a href="/book/{{ status.book.id }}">{{ status.book.title }}</a>
|
{% elif status.reply_parent %}
|
||||||
{% elif status.status_type == 'Quotation' %}
|
{% with parent_status=status|parent %}
|
||||||
quoted <a href="/book/{{ status.book.id }}">{{ status.book.title }}</a>
|
replied to {% include 'snippets/username.html' with user=parent_status.user possessive=True %} <a href="{{parent_status.remote_id }}">{% if parent_status.status_type == 'GeneratedNote' %}update{% else %}{{ parent_status.status_type | lower }}{% endif %}</a>
|
||||||
{% elif status.reply_parent %}
|
{% endwith %}
|
||||||
{% with parent_status=status|parent %}
|
{% endif %}
|
||||||
replied to {% include 'snippets/username.html' with user=parent_status.user possessive=True %} <a href="{{parent_status.remote_id }}">{% if parent_status.status_type == 'GeneratedNote' %}update{% else %}{{ parent_status.status_type | lower }}{% endif %}</a>
|
{% if status.book %}
|
||||||
{% endwith %}
|
<a href="/book/{{ status.book.id }}">{{ status.book.title }}</a>
|
||||||
{% endif %}
|
{% elif status.mention_books %}
|
||||||
</p>
|
<a href="/book/{{ status.mention_books.first.id }}">{{ status.mention_books.first.title }}</a>
|
||||||
</div>
|
{% endif %}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
{% extends 'layout.html' %}
|
|
||||||
{% block content %}
|
|
||||||
<div class="block">
|
|
||||||
<h2 class="title">User search results</h2>
|
|
||||||
{% if not results %}
|
|
||||||
<p>No results found for "{{ query }}"</p>
|
|
||||||
{% endif %}
|
|
||||||
{% for result in results %}
|
|
||||||
{{ result }}
|
|
||||||
<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 %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
''' template filters '''
|
''' template filters '''
|
||||||
|
from uuid import uuid4
|
||||||
from django import template
|
from django import template
|
||||||
|
|
||||||
from bookwyrm import models
|
from bookwyrm import models
|
||||||
|
@ -111,7 +112,6 @@ def get_book_description(book):
|
||||||
''' use the work's text if the book doesn't have it '''
|
''' use the work's text if the book doesn't have it '''
|
||||||
return book.description or book.parent_work.description
|
return book.description or book.parent_work.description
|
||||||
|
|
||||||
|
|
||||||
@register.filter(name='text_overflow')
|
@register.filter(name='text_overflow')
|
||||||
def text_overflow(text):
|
def text_overflow(text):
|
||||||
''' dont' let book descriptions run for ages '''
|
''' dont' let book descriptions run for ages '''
|
||||||
|
@ -127,6 +127,11 @@ def text_overflow(text):
|
||||||
return trimmed + '...'
|
return trimmed + '...'
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter(name='uuid')
|
||||||
|
def get_uuid(identifier):
|
||||||
|
return '%s%s' % (identifier, uuid4())
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def shelve_button_identifier(context, book):
|
def shelve_button_identifier(context, book):
|
||||||
''' check what shelf a user has a book on, if any '''
|
''' check what shelf a user has a book on, if any '''
|
||||||
|
|
|
@ -98,7 +98,7 @@ def home_tab(request, tab):
|
||||||
prev_page = '/?page=%d#feed' % (page - 1)
|
prev_page = '/?page=%d#feed' % (page - 1)
|
||||||
data = {
|
data = {
|
||||||
'user': request.user,
|
'user': request.user,
|
||||||
'suggested_books': suggested_books,
|
'suggested_books': set(suggested_books),
|
||||||
'activities': activities,
|
'activities': activities,
|
||||||
'review_form': forms.ReviewForm(),
|
'review_form': forms.ReviewForm(),
|
||||||
'quotation_form': forms.QuotationForm(),
|
'quotation_form': forms.QuotationForm(),
|
||||||
|
|
Loading…
Reference in a new issue