Allow searching for untagged bookmarks (#226)

Co-authored-by: Sascha Ißbrücker <sascha.issbruecker@gmail.com>
This commit is contained in:
Sascha Ißbrücker 2022-05-21 09:50:51 +02:00 committed by GitHub
parent ebbf0022bc
commit d7f257b3c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 112 additions and 3 deletions

View file

@ -55,6 +55,12 @@ def _base_bookmarks_query(user: User, query_string: str) -> QuerySet:
tags__name__iexact=tag_name
)
# Untagged bookmarks
if query['untagged']:
query_set = query_set.filter(
tags=None
)
# Sort by date added
query_set = query_set.order_by('-date_added')
@ -90,11 +96,15 @@ def _parse_query_string(query_string):
keywords = query_string.strip().split(' ')
keywords = [word for word in keywords if word]
search_terms = [word for word in keywords if word[0] != '#']
search_terms = [word for word in keywords if word[0] != '#' and word[0] != '!']
tag_names = [word[1:] for word in keywords if word[0] == '#']
tag_names = unique(tag_names, str.lower)
# Special search commands
untagged = '!untagged' in keywords
return {
'search_terms': search_terms,
'tag_names': tag_names,
'untagged': untagged,
}

View file

@ -15,3 +15,7 @@
.text-gray-dark {
color: $gray-color-dark;
}
.align-baseline {
align-items: baseline;
}

View file

@ -33,8 +33,10 @@
{# Tag list #}
<section class="content-area column col-4 hide-md">
<div class="content-area-header">
<div class="content-area-header align-baseline">
<h2>Tags</h2>
<div class="spacer"></div>
<a href="?q=!untagged" class="text-gray text-sm">Show Untagged</a>
</div>
{% tag_cloud tags %}
</section>

View file

@ -33,8 +33,10 @@
{# Tag list #}
<section class="content-area column col-4 hide-md">
<div class="content-area-header">
<div class="content-area-header align-baseline">
<h2>Tags</h2>
<div class="spacer"></div>
<a href="?q=!untagged" class="text-gray text-sm">Show Untagged</a>
</div>
{% tag_cloud tags %}
</section>

View file

@ -156,3 +156,8 @@ class BookmarkIndexViewTestCase(TestCase, BookmarkFactoryMixin):
response = self.client.get(reverse('bookmarks:index'))
self.assertVisibleBookmarks(response, visible_bookmarks, '_self')
def test_should_show_link_for_untagged_bookmarks(self):
response = self.client.get(reverse('bookmarks:index'))
self.assertContains(response, '<a href="?q=!untagged" class="text-gray text-sm">Show Untagged</a>')

View file

@ -289,6 +289,60 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
self.assertEqual(bookmark.tag_string, None)
self.assertTrue(bookmark.tag_projection)
def test_query_bookmarks_untagged_should_return_untagged_bookmarks_only(self):
tag = self.setup_tag()
untagged_bookmark = self.setup_bookmark()
self.setup_bookmark(tags=[tag])
self.setup_bookmark(tags=[tag])
query = queries.query_bookmarks(self.user, '!untagged')
self.assertCountEqual(list(query), [untagged_bookmark])
def test_query_bookmarks_untagged_should_be_combinable_with_search_terms(self):
tag = self.setup_tag()
untagged_bookmark = self.setup_bookmark(title='term1')
self.setup_bookmark(title='term2')
self.setup_bookmark(tags=[tag])
query = queries.query_bookmarks(self.user, '!untagged term1')
self.assertCountEqual(list(query), [untagged_bookmark])
def test_query_bookmarks_untagged_should_not_be_combinable_with_tags(self):
tag = self.setup_tag()
self.setup_bookmark()
self.setup_bookmark(tags=[tag])
self.setup_bookmark(tags=[tag])
query = queries.query_bookmarks(self.user, f'!untagged #{tag.name}')
self.assertCountEqual(list(query), [])
def test_query_archived_bookmarks_untagged_should_return_untagged_bookmarks_only(self):
tag = self.setup_tag()
untagged_bookmark = self.setup_bookmark(is_archived=True)
self.setup_bookmark(is_archived=True, tags=[tag])
self.setup_bookmark(is_archived=True, tags=[tag])
query = queries.query_archived_bookmarks(self.user, '!untagged')
self.assertCountEqual(list(query), [untagged_bookmark])
def test_query_archived_bookmarks_untagged_should_be_combinable_with_search_terms(self):
tag = self.setup_tag()
untagged_bookmark = self.setup_bookmark(is_archived=True, title='term1')
self.setup_bookmark(is_archived=True, title='term2')
self.setup_bookmark(is_archived=True, tags=[tag])
query = queries.query_archived_bookmarks(self.user, '!untagged term1')
self.assertCountEqual(list(query), [untagged_bookmark])
def test_query_archived_bookmarks_untagged_should_not_be_combinable_with_tags(self):
tag = self.setup_tag()
self.setup_bookmark(is_archived=True)
self.setup_bookmark(is_archived=True, tags=[tag])
self.setup_bookmark(is_archived=True, tags=[tag])
query = queries.query_archived_bookmarks(self.user, f'!untagged #{tag.name}')
self.assertCountEqual(list(query), [])
def test_query_bookmark_tags_should_return_all_tags_for_empty_query(self):
self.setup_tag_search_data()
@ -460,3 +514,35 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
query = queries.query_archived_bookmark_tags(self.user, '')
self.assertQueryResult(query, [self.get_tags_from_bookmarks(owned_bookmarks)])
def test_query_bookmark_tags_untagged_should_never_return_any_tags(self):
tag = self.setup_tag()
self.setup_bookmark()
self.setup_bookmark(title='term1')
self.setup_bookmark(title='term1', tags=[tag])
self.setup_bookmark(tags=[tag])
query = queries.query_bookmark_tags(self.user, '!untagged')
self.assertCountEqual(list(query), [])
query = queries.query_bookmark_tags(self.user, '!untagged term1')
self.assertCountEqual(list(query), [])
query = queries.query_bookmark_tags(self.user, f'!untagged #{tag.name}')
self.assertCountEqual(list(query), [])
def test_query_archived_bookmark_tags_untagged_should_never_return_any_tags(self):
tag = self.setup_tag()
self.setup_bookmark(is_archived=True)
self.setup_bookmark(is_archived=True, title='term1')
self.setup_bookmark(is_archived=True, title='term1', tags=[tag])
self.setup_bookmark(is_archived=True, tags=[tag])
query = queries.query_archived_bookmark_tags(self.user, '!untagged')
self.assertCountEqual(list(query), [])
query = queries.query_archived_bookmark_tags(self.user, '!untagged term1')
self.assertCountEqual(list(query), [])
query = queries.query_archived_bookmark_tags(self.user, f'!untagged #{tag.name}')
self.assertCountEqual(list(query), [])