Fixes pagination of local search results

This commit is contained in:
Mouse Reeve 2022-08-04 11:42:03 -07:00
parent 3270d0a7d4
commit 06d1936ac9
3 changed files with 72 additions and 64 deletions

View file

@ -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 %}

View file

@ -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 %}

View file

@ -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):