Repository: bookwyrm-social/bookwyrm

Issue:
Suggesting books to a list: suggested changes in behaviour
I tried suggesting books to a list, and I have a couple of remarks:

## After I submit a suggestion, I need visual feedback that the suggestion is sent

1. I am on a lists page
2. I click the button “Suggest”
3. I wait for the page to load ; the same page is displayed

Should be:

3. The same page is loaded, with a message on top telling me that/if my suggestion has been sent

## If I submit a suggestion from a search result, the new page should display the same search

1. I am on a lists page
2. I enter a search term in the “Search for a book” field, and submit
3. I click on the button “Suggest” in the results
4. I wait for the page to load ; the same search results are not displayed

Should be:

4. I wait for the page to load ; the same search results list is displayed

## If I submit a suggestion, the suggested book still appears in the list

0. (I submitted Book A as a suggestion to the list, it has not been accepted)
1. I am on a lists page
2. In the column on the right side, I look at the list of books that I can suggest
3. Book A is present, even though I just submitted it

Should be:

3a. Book A is present, but the button “Suggest” is not valid
3b. Book A is absent from the list



Some of these (excellent) books have been suggested to a list, but I can't know which ones

![image](https://user-images.githubusercontent.com/1781070/116009686-5bd5d400-a61b-11eb-808e-d4cacf1ee3f4.png)



Discussion:

Resolving patch:
diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py
--- a/bookwyrm/connectors/connector_manager.py
+++ b/bookwyrm/connectors/connector_manager.py
@@ -67,10 +67,12 @@ def search(query, min_confidence=0.1):
     return results
 
 
-def local_search(query, min_confidence=0.1, raw=False):
+def local_search(query, min_confidence=0.1, raw=False, filters=None):
     """only look at local search results"""
     connector = load_connector(models.Connector.objects.get(local=True))
-    return connector.search(query, min_confidence=min_confidence, raw=raw)
+    return connector.search(
+        query, min_confidence=min_confidence, raw=raw, filters=filters
+    )
 
 
 def isbn_local_search(query, raw=False):
diff --git a/bookwyrm/connectors/self_connector.py b/bookwyrm/connectors/self_connector.py
--- a/bookwyrm/connectors/self_connector.py
+++ b/bookwyrm/connectors/self_connector.py
@@ -13,15 +13,16 @@ class Connector(AbstractConnector):
     """instantiate a connector"""
 
     # pylint: disable=arguments-differ
-    def search(self, query, min_confidence=0.1, raw=False):
+    def search(self, query, min_confidence=0.1, raw=False, filters=None):
         """search your local database"""
+        filters = filters or []
         if not query:
             return []
         # first, try searching unqiue identifiers
-        results = search_identifiers(query)
+        results = search_identifiers(query, *filters)
         if not results:
             # then try searching title/author
-            results = search_title_author(query, min_confidence)
+            results = search_title_author(query, min_confidence, *filters)
         search_results = []
         for result in results:
             if raw:
@@ -98,15 +99,15 @@ def expand_book_data(self, book):
         pass
 
 
-def search_identifiers(query):
+def search_identifiers(query, *filters):
     """tries remote_id, isbn; defined as dedupe fields on the model"""
-    filters = [
+    or_filters = [
         {f.name: query}
         for f in models.Edition._meta.get_fields()
         if hasattr(f, "deduplication_field") and f.deduplication_field
     ]
     results = models.Edition.objects.filter(
-        reduce(operator.or_, (Q(**f) for f in filters))
+        *filters, reduce(operator.or_, (Q(**f) for f in or_filters))
     ).distinct()
 
     # when there are multiple editions of the same work, pick the default.
@@ -114,7 +115,7 @@ def search_identifiers(query):
     return results.filter(parent_work__default_edition__id=F("id")) or results
 
 
-def search_title_author(query, min_confidence):
+def search_title_author(query, min_confidence, *filters):
     """searches for title and author"""
     vector = (
         SearchVector("title", weight="A")
@@ -126,7 +127,7 @@ def search_title_author(query, min_confidence):
     results = (
         models.Edition.objects.annotate(search=vector)
         .annotate(rank=SearchRank(vector, query))
-        .filter(rank__gt=min_confidence)
+        .filter(*filters, rank__gt=min_confidence)
         .order_by("-rank")
     )
 
diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py
--- a/bookwyrm/views/list.py
+++ b/bookwyrm/views/list.py
@@ -1,5 +1,6 @@
 """ book list views"""
 from typing import Optional
+from urllib.parse import urlencode
 
 from django.contrib.auth.decorators import login_required
 from django.core.paginator import Paginator
@@ -9,6 +10,7 @@
 from django.http import HttpResponseNotFound, HttpResponseBadRequest, HttpResponse
 from django.shortcuts import get_object_or_404, redirect
 from django.template.response import TemplateResponse
+from django.urls import reverse
 from django.utils.decorators import method_decorator
 from django.views import View
 from django.views.decorators.http import require_POST
@@ -135,7 +137,11 @@ def get(self, request, list_id):
 
         if query and request.user.is_authenticated:
             # search for books
-            suggestions = connector_manager.local_search(query, raw=True)
+            suggestions = connector_manager.local_search(
+                query,
+                raw=True,
+                filters=[~Q(parent_work__editions__in=book_list.books.all())],
+            )
         elif request.user.is_authenticated:
             # just suggest whatever books are nearby
             suggestions = request.user.shelfbook_set.filter(
@@ -263,7 +269,10 @@ def add_book(request):
         # if the book is already on the list, don't flip out
         pass
 
-    return redirect("list", book_list.id)
+    path = reverse("list", args=[book_list.id])
+    params = request.GET.copy()
+    params["updated"] = True
+    return redirect("{:s}?{:s}".format(path, urlencode(params)))
 
 
 @require_POST


Test patch: