Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.31.0 #9

Merged
merged 6 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

## v1.31.0 (16/06/2024)

### What's Changed
* Add support for bookmark thumbnails by @vslinko in https://github.com/sissbruecker/linkding/pull/721
* Automatically add tags to bookmarks based on URL pattern by @vslinko in https://github.com/sissbruecker/linkding/pull/736
* Load bookmark thumbnails after import by @vslinko in https://github.com/sissbruecker/linkding/pull/724
* Load missing thumbnails after enabling the feature by @sissbruecker in https://github.com/sissbruecker/linkding/pull/725
* Thumbnails lazy loading by @vslinko in https://github.com/sissbruecker/linkding/pull/734
* Add option for disabling tag grouping by @vslinko in https://github.com/sissbruecker/linkding/pull/735
* Preview auto tags in bookmark form by @sissbruecker in https://github.com/sissbruecker/linkding/pull/737
* Hide tooltip on mobile by @vslinko in https://github.com/sissbruecker/linkding/pull/733
* Bump requests from 2.31.0 to 2.32.0 by @dependabot in https://github.com/sissbruecker/linkding/pull/740

### New Contributors
* @vslinko made their first contribution in https://github.com/sissbruecker/linkding/pull/721

**Full Changelog**: https://github.com/sissbruecker/linkding/compare/v1.30.0...v1.31.0

---

## v1.30.0 (20/04/2024)

### What's Changed
Expand Down
13 changes: 12 additions & 1 deletion bookmarks/api/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
UserProfileSerializer,
)
from bookmarks.models import Bookmark, BookmarkSearch, Tag, User
from bookmarks.services import auto_tagging
from bookmarks.services.bookmarks import (
archive_bookmark,
unarchive_bookmark,
Expand Down Expand Up @@ -107,8 +108,18 @@ def check(self, request):
else:
metadata = website_loader.load_website_metadata(url)

# Return tags that would be automatically applied to the bookmark
profile = request.user.profile
auto_tags = []
if profile.auto_tagging_rules:
auto_tags = auto_tagging.get_tags(profile.auto_tagging_rules, url)

return Response(
{"bookmark": existing_bookmark_data, "metadata": metadata.to_dict()},
{
"bookmark": existing_bookmark_data,
"metadata": metadata.to_dict(),
"auto_tags": auto_tags,
},
status=status.HTTP_200_OK,
)

Expand Down
22 changes: 22 additions & 0 deletions bookmarks/e2e/e2e_test_bookmark_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,25 @@ def test_enter_url_of_existing_bookmark_should_show_notes(self):

page.get_by_label("URL").fill(bookmark.url)
expect(details).to_have_attribute("open", value="")

def test_create_should_preview_auto_tags(self):
profile = self.get_or_create_test_user().profile
profile.auto_tagging_rules = "github.com dev github"
profile.save()

with sync_playwright() as p:
# Open page with URL that should have auto tags
browser = self.setup_browser(p)
page = browser.new_page()
url = self.live_server_url + reverse("bookmarks:new")
url += f"?url=https%3A%2F%2Fgithub.com%2Fsissbruecker%2Flinkding"
page.goto(url)

auto_tags_hint = page.locator(".form-input-hint.auto-tags")
expect(auto_tags_hint).to_be_visible()
expect(auto_tags_hint).to_have_text("Auto tags: dev github")

# Change to URL without auto tags
page.get_by_label("URL").fill("https://example.com")

expect(auto_tags_hint).to_be_hidden()
13 changes: 13 additions & 0 deletions bookmarks/management/commands/full_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ def handle(self, *args, **options):
file_path = os.path.join(root, file)
zip_file.write(file_path, os.path.join("favicons", file))

# Backup the previews folder
if not os.path.exists(os.path.join("data", "previews")):
self.stdout.write(
self.style.WARNING("No previews folder found. Skipping...")
)
else:
self.stdout.write("Backup bookmark previews...")
previews_folder = os.path.join("data", "previews")
for root, _, files in os.walk(previews_folder):
for file in files:
file_path = os.path.join(root, file)
zip_file.write(file_path, os.path.join("previews", file))

self.stdout.write(self.style.SUCCESS(f"Backup created at {backup_file}"))

def backup_database(self, backup_db_file):
Expand Down
9 changes: 4 additions & 5 deletions bookmarks/styles/bookmark-form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@
.form-input-hint.bookmark-exists {
display: none;
color: $warning-color;
}

a {
color: $warning-color;
text-decoration: underline;
font-weight: bold;
}
.form-input-hint.auto-tags {
display: none;
color: $success-color;
}

details.notes textarea {
Expand Down
18 changes: 15 additions & 3 deletions bookmarks/templates/bookmarks/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
<label for="{{ form.tag_string.id_for_label }}" class="form-label">Tags</label>
{{ form.tag_string|add_class:"form-input"|attr:"ld-tag-autocomplete"|attr:"autocomplete:off"|attr:"autocapitalize:off" }}
<div class="form-input-hint">
Enter any number of tags separated by space and <strong>without</strong> the hash (#). If a tag does not
exist it will be
automatically created.
Enter any number of tags separated by space and <strong>without</strong> the hash (#).
If a tag does not exist it will be automatically created.
</div>
<div class="form-input-hint auto-tags"></div>
{{ form.tag_string.errors }}
</div>
<div class="form-group has-icon-right">
Expand Down Expand Up @@ -197,6 +197,18 @@
} else {
bookmarkExistsHint.style['display'] = 'none';
}

// Preview auto tags
const autoTags = data.auto_tags;
const autoTagsHint = document.querySelector('.form-input-hint.auto-tags');

if (autoTags.length > 0) {
autoTags.sort();
autoTagsHint.style['display'] = 'block';
autoTagsHint.innerHTML = `Auto tags: ${autoTags.join(" ")}`;
} else {
autoTagsHint.style['display'] = 'none';
}
});
}

Expand Down
28 changes: 28 additions & 0 deletions bookmarks/tests/test_bookmarks_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,34 @@ def test_check_returns_existing_metadata_if_url_is_bookmarked(self):
self.assertEqual(bookmark.website_description, metadata["description"])
self.assertIsNone(metadata["preview_image"])

def test_check_returns_no_auto_tags_if_none_configured(self):
self.authenticate()

url = reverse("bookmarks:bookmark-check")
check_url = urllib.parse.quote_plus("https://example.com")
response = self.get(
f"{url}?url={check_url}", expected_status_code=status.HTTP_200_OK
)
auto_tags = response.data["auto_tags"]

self.assertCountEqual(auto_tags, [])

def test_check_returns_matching_auto_tags(self):
self.authenticate()

profile = self.get_or_create_test_user().profile
profile.auto_tagging_rules = "example.com tag1 tag2"
profile.save()

url = reverse("bookmarks:bookmark-check")
check_url = urllib.parse.quote_plus("https://example.com")
response = self.get(
f"{url}?url={check_url}", expected_status_code=status.HTTP_200_OK
)
auto_tags = response.data["auto_tags"]

self.assertCountEqual(auto_tags, ["tag1", "tag2"])

def test_can_only_access_own_bookmarks(self):
self.authenticate()
self.setup_bookmark()
Expand Down
5 changes: 3 additions & 2 deletions docs/backup.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ The data folder contains the following contents that are relevant for backups:
- `db.sqlite3` - the SQLite database
- `assets` - folder that contains HTML snapshots of bookmarks
- `favicons` - folder that contains downloaded favicons
- `previews` - folder that contains downloaded preview images

The following sections explain how to back up the individual contents.

## Full backup

linkding provides a CLI command to create a full backup of the data folder. This creates a zip file that contains backups of the database, assets, and favicons.
linkding provides a CLI command to create a full backup of the data folder. This creates a zip file that contains backups of the database, assets, favicons, and preview images.

> [!NOTE]
> This method assumes that you are using the default SQLite database.
Expand Down Expand Up @@ -90,7 +91,7 @@ This is the least technical option to back up bookmarks, but has several limitat
- It only exports your own bookmarks, not those of other users.
- It does not export URLs of snapshots on the Internet Archive Wayback machine.
- It does not export HTML snapshots of bookmarks. Even if you backup and restore the assets folder, the bookmarks will not be linked to the snapshots anymore.
- It does not export favicons.
- It does not export favicons or preview images.

Only use this method if you are fine with the above limitations.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "linkding",
"version": "1.30.1",
"version": "1.31.0",
"description": "",
"main": "index.js",
"scripts": {
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pyopenssl==24.1.0
# via josepy
python-dateutil==2.9.0.post0
# via -r requirements.in
pytz==2023.3.post1
# via djangorestframework
requests==2.32.3
# via
# -r requirements.in
Expand Down
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.30.0
1.31.0
Loading