mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2025-02-18 12:05:18 +00:00
Fixes pagination of local search results
This commit is contained in:
parent
3270d0a7d4
commit
06d1936ac9
3 changed files with 72 additions and 64 deletions
|
@ -3,10 +3,9 @@
|
||||||
|
|
||||||
{% block panel %}
|
{% block panel %}
|
||||||
|
|
||||||
{% if results %}
|
{% if results or remote_results %}
|
||||||
{% with results|first as local_results %}
|
|
||||||
<ul class="block">
|
<ul class="block">
|
||||||
{% for result in local_results.results %}
|
{% for result in results %}
|
||||||
<li class="pd-4 mb-5 local-book-search-result" id="tour-local-book-search-result">
|
<li class="pd-4 mb-5 local-book-search-result" id="tour-local-book-search-result">
|
||||||
<div class="columns is-mobile is-gapless mb-0">
|
<div class="columns is-mobile is-gapless mb-0">
|
||||||
<div class="column is-cover">
|
<div class="column is-cover">
|
||||||
|
@ -29,16 +28,12 @@
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endwith %}
|
|
||||||
|
|
||||||
<div class="block">
|
<div class="block">
|
||||||
{% for result_set in results|slice:"1:" %}
|
{% for result_set in remote_results %}
|
||||||
{% if result_set.results %}
|
{% if result_set.results %}
|
||||||
<section class="mb-5">
|
<section class="mb-5">
|
||||||
{% if not result_set.connector.local %}
|
|
||||||
<details class="details-panel box" open>
|
<details class="details-panel box" open>
|
||||||
{% endif %}
|
|
||||||
{% if not result_set.connector.local %}
|
|
||||||
<summary class="is-flex is-align-items-center is-flex-wrap-wrap is-gap-2 remote-book-search-result" id="tour-remote-search-result">
|
<summary class="is-flex is-align-items-center is-flex-wrap-wrap is-gap-2 remote-book-search-result" id="tour-remote-search-result">
|
||||||
<span class="mb-0 title is-5">
|
<span class="mb-0 title is-5">
|
||||||
{% trans 'Results from' %}
|
{% trans 'Results from' %}
|
||||||
|
@ -47,7 +42,6 @@
|
||||||
|
|
||||||
<span class="details-close icon icon-x" aria-hidden="true"></span>
|
<span class="details-close icon icon-x" aria-hidden="true"></span>
|
||||||
</summary>
|
</summary>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
<div class="is-flex is-flex-direction-row-reverse">
|
<div class="is-flex is-flex-direction-row-reverse">
|
||||||
|
@ -88,17 +82,15 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if not result_set.connector.local %}
|
|
||||||
</details>
|
</details>
|
||||||
{% endif %}
|
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block search_footer %}
|
||||||
<p class="block">
|
<p class="block">
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
{% if not remote %}
|
{% if not remote %}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load humanize %}
|
||||||
|
|
||||||
{% block title %}{% trans "Search" %}{% endblock %}
|
{% block title %}{% trans "Search" %}{% endblock %}
|
||||||
|
|
||||||
|
@ -53,17 +54,24 @@
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<section class="block" id="search-results-block">
|
<section class="block" id="search-results-block">
|
||||||
|
<p class="block">
|
||||||
{% if not results %}
|
{% if not results %}
|
||||||
<p>
|
|
||||||
<em>{% blocktrans %}No results found for "{{ query }}"{% endblocktrans %}</em>
|
<em>{% blocktrans %}No results found for "{{ query }}"{% endblocktrans %}</em>
|
||||||
</p>
|
{% else %}
|
||||||
|
<em>{% blocktrans trimmed count counter=results.paginator.count with result_count=results.paginator.count|intcomma %}
|
||||||
|
{{ result_count }} result found
|
||||||
|
{% plural %}
|
||||||
|
{{ result_count }} results found
|
||||||
|
{% endblocktrans %}</em>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</p>
|
||||||
{% block panel %}
|
{% block panel %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
<div>
|
<div class="block">
|
||||||
{% include 'snippets/pagination.html' with page=results path=request.path %}
|
{% include 'snippets/pagination.html' with page=results path=request.path %}
|
||||||
</div>
|
</div>
|
||||||
|
{% block search_footer %}{% endblock %}
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -23,22 +23,11 @@ class Search(View):
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
"""that search bar up top"""
|
"""that search bar up top"""
|
||||||
query = request.GET.get("q")
|
|
||||||
# check if query is isbn
|
|
||||||
query = isbn_check(query)
|
|
||||||
min_confidence = request.GET.get("min_confidence", 0)
|
|
||||||
search_type = request.GET.get("type")
|
|
||||||
search_remote = (
|
|
||||||
request.GET.get("remote", False) and request.user.is_authenticated
|
|
||||||
)
|
|
||||||
|
|
||||||
if is_api_request(request):
|
if is_api_request(request):
|
||||||
# only return local book results via json so we don't cascade
|
return api_book_search(request)
|
||||||
book_results = search(query, min_confidence=min_confidence)
|
|
||||||
return JsonResponse(
|
|
||||||
[format_search_result(r) for r in book_results], safe=False
|
|
||||||
)
|
|
||||||
|
|
||||||
|
query = request.GET.get("q")
|
||||||
|
search_type = request.GET.get("type")
|
||||||
if query and not search_type:
|
if query and not search_type:
|
||||||
search_type = "user" if "@" in query else "book"
|
search_type = "user" if "@" in query else "book"
|
||||||
|
|
||||||
|
@ -50,49 +39,64 @@ class Search(View):
|
||||||
if not search_type in endpoints:
|
if not search_type in endpoints:
|
||||||
search_type = "book"
|
search_type = "book"
|
||||||
|
|
||||||
data = {
|
return endpoints[search_type](request)
|
||||||
"query": query or "",
|
|
||||||
"type": search_type,
|
|
||||||
"remote": search_remote,
|
def api_book_search(request):
|
||||||
}
|
"""Return books via API response"""
|
||||||
if query:
|
query = request.GET.get("q")
|
||||||
results, search_remote = endpoints[search_type](
|
query = isbn_check(query)
|
||||||
query, request.user, min_confidence, search_remote
|
min_confidence = request.GET.get("min_confidence", 0)
|
||||||
|
# only return local book results via json so we don't cascade
|
||||||
|
book_results = search(query, min_confidence=min_confidence)
|
||||||
|
return JsonResponse(
|
||||||
|
[format_search_result(r) for r in book_results], safe=False
|
||||||
)
|
)
|
||||||
if results:
|
|
||||||
paginated = Paginator(results, PAGE_LENGTH).get_page(
|
def book_search(request):
|
||||||
|
"""the real business is elsewhere"""
|
||||||
|
query = request.GET.get("q")
|
||||||
|
# check if query is isbn
|
||||||
|
query = isbn_check(query)
|
||||||
|
min_confidence = request.GET.get("min_confidence", 0)
|
||||||
|
search_remote = (
|
||||||
|
request.GET.get("remote", False) and request.user.is_authenticated
|
||||||
|
)
|
||||||
|
|
||||||
|
# try a local-only search
|
||||||
|
local_results = search(query, min_confidence=min_confidence)
|
||||||
|
paginated = Paginator(local_results, PAGE_LENGTH).get_page(
|
||||||
request.GET.get("page")
|
request.GET.get("page")
|
||||||
)
|
)
|
||||||
data["results"] = paginated
|
data = {
|
||||||
data["remote"] = search_remote
|
"query": query,
|
||||||
|
"results": paginated,
|
||||||
return TemplateResponse(request, f"search/{search_type}.html", data)
|
"type": "book",
|
||||||
|
"remote": search_remote
|
||||||
|
}
|
||||||
|
# if a logged in user requested remote results or got no local results, try remote
|
||||||
|
if request.user.is_authenticated and (not local_results or search_remote):
|
||||||
|
data["remote_results"] = connector_manager.search(
|
||||||
|
query, min_confidence=min_confidence
|
||||||
|
)
|
||||||
|
return TemplateResponse(request, "search/book.html", data)
|
||||||
|
|
||||||
|
|
||||||
def book_search(query, user, min_confidence, search_remote=False):
|
def user_search(request):
|
||||||
"""the real business is elsewhere"""
|
|
||||||
# try a local-only search
|
|
||||||
results = [{"results": search(query, min_confidence=min_confidence)}]
|
|
||||||
if not user.is_authenticated or (results[0]["results"] and not search_remote):
|
|
||||||
return results, False
|
|
||||||
|
|
||||||
# if there were no local results, or the request was for remote, search all sources
|
|
||||||
results += connector_manager.search(query, min_confidence=min_confidence)
|
|
||||||
return results, True
|
|
||||||
|
|
||||||
|
|
||||||
def user_search(query, viewer, *_):
|
|
||||||
"""cool kids members only user search"""
|
"""cool kids members only user search"""
|
||||||
|
viewer = request.user
|
||||||
|
query = request.GET.get("q")
|
||||||
|
data = {"type": "user", "query": query}
|
||||||
# logged out viewers can't search users
|
# logged out viewers can't search users
|
||||||
if not viewer.is_authenticated:
|
if not viewer.is_authenticated:
|
||||||
return models.User.objects.none(), None
|
return TemplateResponse(request, "search/user.html", data)
|
||||||
|
|
||||||
# use webfinger for mastodon style account@domain.com username to load the user if
|
# use webfinger for mastodon style account@domain.com username to load the user if
|
||||||
# they don't exist locally (handle_remote_webfinger will check the db)
|
# they don't exist locally (handle_remote_webfinger will check the db)
|
||||||
if re.match(regex.FULL_USERNAME, query):
|
if re.match(regex.FULL_USERNAME, query):
|
||||||
handle_remote_webfinger(query)
|
handle_remote_webfinger(query)
|
||||||
|
|
||||||
return (
|
data["results"] = (
|
||||||
models.User.viewer_aware_objects(viewer)
|
models.User.viewer_aware_objects(viewer)
|
||||||
.annotate(
|
.annotate(
|
||||||
similarity=Greatest(
|
similarity=Greatest(
|
||||||
|
@ -104,14 +108,17 @@ def user_search(query, viewer, *_):
|
||||||
similarity__gt=0.5,
|
similarity__gt=0.5,
|
||||||
)
|
)
|
||||||
.order_by("-similarity")
|
.order_by("-similarity")
|
||||||
), None
|
)
|
||||||
|
return TemplateResponse(request, "search/user.html", data)
|
||||||
|
|
||||||
|
|
||||||
def list_search(query, viewer, *_):
|
def list_search(request):
|
||||||
"""any relevent lists?"""
|
"""any relevent lists?"""
|
||||||
return (
|
query = request.GET.get("q")
|
||||||
|
data = {"query": query, "type": "list"}
|
||||||
|
data["results"] = (
|
||||||
models.List.privacy_filter(
|
models.List.privacy_filter(
|
||||||
viewer,
|
request.user,
|
||||||
privacy_levels=["public", "followers"],
|
privacy_levels=["public", "followers"],
|
||||||
)
|
)
|
||||||
.annotate(
|
.annotate(
|
||||||
|
@ -124,7 +131,8 @@ def list_search(query, viewer, *_):
|
||||||
similarity__gt=0.1,
|
similarity__gt=0.1,
|
||||||
)
|
)
|
||||||
.order_by("-similarity")
|
.order_by("-similarity")
|
||||||
), None
|
)
|
||||||
|
return TemplateResponse(request, "search/list.html", data)
|
||||||
|
|
||||||
|
|
||||||
def isbn_check(query):
|
def isbn_check(query):
|
||||||
|
|
Loading…
Reference in a new issue