Add bundles for organizing bookmarks (#1097)

* add bundle model and query logic

* cleanup tests

* add basic form

* add success message

* Add form tests

* Add bundle list view

* fix edit view

* Add remove button

* Add basic preview logic

* Make pagination use absolute URLs

* Hide bookmark edits when rendering preview

* Render bookmark list in preview

* Reorder bundles

* Show bundles in bookmark view

* Make bookmark search respect selected bundle

* UI tweaks

* Fix bookmark scope

* Improve bundle preview

* Skip preview if form is submitted

* Show correct preview after invalid form submission

* Add option to hide bundles

* Merge new migrations

* Add tests for bundle menu

* Improve check for preview being removed
This commit is contained in:
Sascha Ißbrücker
2025-06-19 16:47:29 +02:00
committed by GitHub
parent 8be72a5d1f
commit 1672dc0152
59 changed files with 2290 additions and 267 deletions

View File

@@ -10,7 +10,7 @@ from django.urls import reverse
from django.utils import timezone, formats
from bookmarks.middlewares import LinkdingMiddleware
from bookmarks.models import Bookmark, UserProfile, User
from bookmarks.models import Bookmark, BookmarkSearch, UserProfile, User
from bookmarks.tests.helpers import BookmarkFactoryMixin, HtmlTestMixin
from bookmarks.views import contexts
@@ -46,7 +46,6 @@ class BookmarkListTemplateTest(TestCase, BookmarkFactoryMixin, HtmlTestMixin):
title="View snapshot on the Internet Archive Wayback Machine" target="{link_target}" rel="noopener">
{label_content}
</a>
<span>|</span>
""",
html,
)
@@ -266,6 +265,7 @@ class BookmarkListTemplateTest(TestCase, BookmarkFactoryMixin, HtmlTestMixin):
contexts.BookmarkListContext
] = contexts.ActiveBookmarkListContext,
user: User | AnonymousUser = None,
is_preview: bool = False,
) -> str:
rf = RequestFactory()
request = rf.get(url)
@@ -273,7 +273,10 @@ class BookmarkListTemplateTest(TestCase, BookmarkFactoryMixin, HtmlTestMixin):
middleware = LinkdingMiddleware(lambda r: HttpResponse())
middleware(request)
bookmark_list_context = context_type(request)
search = BookmarkSearch.from_request(request, request.GET)
bookmark_list_context = context_type(request, search)
if is_preview:
bookmark_list_context.is_preview = True
context = RequestContext(request, {"bookmark_list": bookmark_list_context})
template = Template("{% include 'bookmarks/bookmark_list.html' %}")
@@ -1047,3 +1050,21 @@ class BookmarkListTemplateTest(TestCase, BookmarkFactoryMixin, HtmlTestMixin):
soup = self.make_soup(html)
bookmarks = soup.select("li[ld-bookmark-item]")
self.assertEqual(10, len(bookmarks))
def test_no_actions_rendered_when_is_preview(self):
bookmark = self.setup_bookmark()
bookmark.date_added = timezone.now() - relativedelta(days=8)
bookmark.web_archive_snapshot_url = "https://example.com"
bookmark.save()
html = self.render_template(is_preview=True)
# Verify no actions are rendered
self.assertNoViewLink(html, bookmark)
self.assertNoBookmarkActions(html, bookmark)
self.assertMarkAsReadButton(html, bookmark, count=0)
self.assertUnshareButton(html, bookmark, count=0)
self.assertNotesToggle(html, count=0)
# But date should still be rendered
self.assertWebArchiveLink(html, "1 week ago", bookmark.web_archive_snapshot_url)