Skip to content

Commit

Permalink
Merge pull request #10 from sissbruecker/master
Browse files Browse the repository at this point in the history
sync
  • Loading branch information
krzysztofjeziorny authored Jul 3, 2024
2 parents 3df33c2 + fbc97a3 commit e3d5d5a
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ This section lists community projects around using linkding, in alphabetical ord
- [Linkdy](https://github.com/JGeek00/linkdy): An open source mobile and desktop (not yet) client created with Flutter. Available at the [Google Play Store](https://play.google.com/store/apps/details?id=com.jgeek00.linkdy). By [JGeek00](https://github.com/JGeek00).
- [LinkThing](https://apps.apple.com/us/app/linkthing/id1666031776) An iOS client for linkding. By [amoscardino](https://github.com/amoscardino)
- [Open all links bookmarklet](https://gist.github.com/ukcuddlyguy/336dd7339e6d35fc64a75ccfc9323c66) A browser bookmarklet to open all links on the current Linkding page in new tabs. By [ukcuddlyguy](https://github.com/ukcuddlyguy)
- [Pinkt](https://github.com/fibelatti/pinboard-kotlin) An Android client for linkding. By [fibelatti](https://github.com/fibelatti)
- [Postman collection](https://gist.github.com/gingerbeardman/f0b42502f3bc9344e92ce63afd4360d3) a group of saved request templates for API testing. By [gingerbeardman](https://github.com/gingerbeardman)

## Acknowledgements + Donations
Expand Down
10 changes: 5 additions & 5 deletions bookmarks/api/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,16 @@ def get_queryset(self):
return Bookmark.objects.all().filter(owner=user)

def get_serializer_context(self):
return {"user": self.request.user}
return {"request": self.request, "user": self.request.user}

@action(methods=["get"], detail=False)
def archived(self, request):
user = request.user
search = BookmarkSearch.from_request(request.GET)
query_set = queries.query_archived_bookmarks(user, user.profile, search)
page = self.paginate_queryset(query_set)
serializer = self.get_serializer_class()
data = serializer(page, many=True).data
serializer = self.get_serializer(page, many=True)
data = serializer.data
return self.get_paginated_response(data)

@action(methods=["get"], detail=False)
Expand All @@ -73,8 +73,8 @@ def shared(self, request):
user, request.user_profile, search, public_only
)
page = self.paginate_queryset(query_set)
serializer = self.get_serializer_class()
data = serializer(page, many=True).data
serializer = self.get_serializer(page, many=True)
data = serializer.data
return self.get_paginated_response(data)

@action(methods=["post"], detail=True)
Expand Down
23 changes: 23 additions & 0 deletions bookmarks/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.db.models import prefetch_related_objects
from django.templatetags.static import static
from rest_framework import serializers
from rest_framework.serializers import ListSerializer

Expand Down Expand Up @@ -31,6 +32,8 @@ class Meta:
"website_title",
"website_description",
"web_archive_snapshot_url",
"favicon_url",
"preview_image_url",
"is_archived",
"unread",
"shared",
Expand All @@ -42,6 +45,8 @@ class Meta:
"website_title",
"website_description",
"web_archive_snapshot_url",
"favicon_url",
"preview_image_url",
"date_added",
"date_modified",
]
Expand All @@ -56,6 +61,24 @@ class Meta:
shared = serializers.BooleanField(required=False, default=False)
# Override readonly tag_names property to allow passing a list of tag names to create/update
tag_names = TagListField(required=False, default=[])
favicon_url = serializers.SerializerMethodField()
preview_image_url = serializers.SerializerMethodField()

def get_favicon_url(self, obj: Bookmark):
if not obj.favicon_file:
return None
request = self.context.get("request")
favicon_file_path = static(obj.favicon_file)
favicon_url = request.build_absolute_uri(favicon_file_path)
return favicon_url

def get_preview_image_url(self, obj: Bookmark):
if not obj.preview_image_file:
return None
request = self.context.get("request")
preview_image_file_path = static(obj.preview_image_file)
preview_image_url = request.build_absolute_uri(preview_image_file_path)
return preview_image_url

def create(self, validated_data):
bookmark = Bookmark()
Expand Down
10 changes: 10 additions & 0 deletions bookmarks/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ def setup_numbered_bookmarks(
shared: bool = False,
with_tags: bool = False,
with_web_archive_snapshot_url: bool = False,
with_favicon_file: bool = False,
with_preview_image_file: bool = False,
user: User = None,
):
user = user or self.get_or_create_test_user()
Expand Down Expand Up @@ -118,6 +120,12 @@ def setup_numbered_bookmarks(
web_archive_snapshot_url = ""
if with_web_archive_snapshot_url:
web_archive_snapshot_url = f"https://web.archive.org/web/{i}"
favicon_file = ""
if with_favicon_file:
favicon_file = f"favicon_{i}.png"
preview_image_file = ""
if with_preview_image_file:
preview_image_file = f"preview_image_{i}.png"
bookmark = self.setup_bookmark(
url=url,
title=title,
Expand All @@ -126,6 +134,8 @@ def setup_numbered_bookmarks(
shared=shared,
tags=tags,
web_archive_snapshot_url=web_archive_snapshot_url,
favicon_file=favicon_file,
preview_image_file=preview_image_file,
user=user,
)
bookmarks.append(bookmark)
Expand Down
61 changes: 60 additions & 1 deletion bookmarks/tests/test_bookmarks_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ def assertBookmarkListEqual(self, data_list, bookmarks):
expectation["website_title"] = bookmark.website_title
expectation["website_description"] = bookmark.website_description
expectation["web_archive_snapshot_url"] = bookmark.web_archive_snapshot_url
expectation["favicon_url"] = (
f"http://testserver/static/{bookmark.favicon_file}"
if bookmark.favicon_file
else None
)
expectation["preview_image_url"] = (
f"http://testserver/static/{bookmark.preview_image_file}"
if bookmark.preview_image_file
else None
)
expectation["is_archived"] = bookmark.is_archived
expectation["unread"] = bookmark.unread
expectation["shared"] = bookmark.shared
Expand Down Expand Up @@ -65,7 +75,11 @@ def test_list_bookmarks(self):
def test_list_bookmarks_with_more_details(self):
self.authenticate()
bookmarks = self.setup_numbered_bookmarks(
5, with_tags=True, with_web_archive_snapshot_url=True
5,
with_tags=True,
with_web_archive_snapshot_url=True,
with_favicon_file=True,
with_preview_image_file=True,
)

response = self.get(
Expand Down Expand Up @@ -171,6 +185,23 @@ def test_list_archived_bookmarks_does_not_return_unarchived_bookmarks(self):
)
self.assertBookmarkListEqual(response.data["results"], archived_bookmarks)

def test_list_archived_bookmarks_with_more_details(self):
self.authenticate()
archived_bookmarks = self.setup_numbered_bookmarks(
5,
archived=True,
with_tags=True,
with_web_archive_snapshot_url=True,
with_favicon_file=True,
with_preview_image_file=True,
)

response = self.get(
reverse("bookmarks:bookmark-archived"),
expected_status_code=status.HTTP_200_OK,
)
self.assertBookmarkListEqual(response.data["results"], archived_bookmarks)

def test_list_archived_bookmarks_should_filter_by_query(self):
self.authenticate()
search_value = self.get_random_string()
Expand Down Expand Up @@ -220,6 +251,26 @@ def test_list_shared_bookmarks(self):
)
self.assertBookmarkListEqual(response.data["results"], shared_bookmarks)

def test_list_shared_bookmarks_with_more_details(self):
self.authenticate()

other_user = self.setup_user(enable_sharing=True)
shared_bookmarks = self.setup_numbered_bookmarks(
5,
shared=True,
user=other_user,
with_tags=True,
with_web_archive_snapshot_url=True,
with_favicon_file=True,
with_preview_image_file=True,
)

response = self.get(
reverse("bookmarks:bookmark-shared"),
expected_status_code=status.HTTP_200_OK,
)
self.assertBookmarkListEqual(response.data["results"], shared_bookmarks)

def test_list_only_publicly_shared_bookmarks_when_not_logged_in(self):
user1 = self.setup_user(enable_sharing=True, enable_public_sharing=True)
user2 = self.setup_user(enable_sharing=True)
Expand Down Expand Up @@ -701,6 +752,8 @@ def test_check_returns_bookmark_if_url_is_bookmarked(self):
url="https://example.com",
title="Example title",
description="Example description",
favicon_file="favicon.png",
preview_image_file="preview.png",
)

url = reverse("bookmarks:bookmark-check")
Expand All @@ -715,6 +768,12 @@ def test_check_returns_bookmark_if_url_is_bookmarked(self):
self.assertEqual(bookmark.url, bookmark_data["url"])
self.assertEqual(bookmark.title, bookmark_data["title"])
self.assertEqual(bookmark.description, bookmark_data["description"])
self.assertEqual(
"http://testserver/static/favicon.png", bookmark_data["favicon_url"]
)
self.assertEqual(
"http://testserver/static/preview.png", bookmark_data["preview_image_url"]
)

def test_check_returns_existing_metadata_if_url_is_bookmarked(self):
self.authenticate()
Expand Down
2 changes: 2 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Example response:
"website_title": "Website title",
"website_description": "Website description",
"web_archive_snapshot_url": "https://web.archive.org/web/20200926094623/https://example.com",
"favicon_url": "http://127.0.0.1:8000/static/https_example_com.png",
"preview_image_url": "http://127.0.0.1:8000/static/0ac5c53db923727765216a3a58e70522.jpg",
"is_archived": false,
"unread": false,
"shared": false,
Expand Down

0 comments on commit e3d5d5a

Please sign in to comment.