mirror of
https://github.com/sissbruecker/linkding.git
synced 2025-09-09 02:36:43 +02:00
Add option to mark bookmarks as shared by default (#1170)
* Add option to mark bookmarks as shared by default * add migration
This commit is contained in:
@@ -50,6 +50,7 @@ class BookmarkForm(forms.ModelForm):
|
|||||||
"tag_string": request.GET.get("tags"),
|
"tag_string": request.GET.get("tags"),
|
||||||
"auto_close": "auto_close" in request.GET,
|
"auto_close": "auto_close" in request.GET,
|
||||||
"unread": request.user_profile.default_mark_unread,
|
"unread": request.user_profile.default_mark_unread,
|
||||||
|
"shared": request.user_profile.default_mark_shared,
|
||||||
}
|
}
|
||||||
if instance is not None and request.method == "GET":
|
if instance is not None and request.method == "GET":
|
||||||
initial = {"tag_string": build_tag_string(instance.tag_names, " ")}
|
initial = {"tag_string": build_tag_string(instance.tag_names, " ")}
|
||||||
|
18
bookmarks/migrations/0048_userprofile_default_mark_shared.py
Normal file
18
bookmarks/migrations/0048_userprofile_default_mark_shared.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.2.3 on 2025-08-22 17:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookmarks", "0047_populate_url_normalized_field"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="userprofile",
|
||||||
|
name="default_mark_shared",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
@@ -479,6 +479,7 @@ class UserProfile(models.Model):
|
|||||||
search_preferences = models.JSONField(default=dict, null=False)
|
search_preferences = models.JSONField(default=dict, null=False)
|
||||||
enable_automatic_html_snapshots = models.BooleanField(default=True, null=False)
|
enable_automatic_html_snapshots = models.BooleanField(default=True, null=False)
|
||||||
default_mark_unread = models.BooleanField(default=False, null=False)
|
default_mark_unread = models.BooleanField(default=False, null=False)
|
||||||
|
default_mark_shared = models.BooleanField(default=False, null=False)
|
||||||
items_per_page = models.IntegerField(
|
items_per_page = models.IntegerField(
|
||||||
null=False, default=30, validators=[MinValueValidator(10)]
|
null=False, default=30, validators=[MinValueValidator(10)]
|
||||||
)
|
)
|
||||||
@@ -520,6 +521,7 @@ class UserProfileForm(forms.ModelForm):
|
|||||||
"display_remove_bookmark_action",
|
"display_remove_bookmark_action",
|
||||||
"permanent_notes",
|
"permanent_notes",
|
||||||
"default_mark_unread",
|
"default_mark_unread",
|
||||||
|
"default_mark_shared",
|
||||||
"custom_css",
|
"custom_css",
|
||||||
"auto_tagging_rules",
|
"auto_tagging_rules",
|
||||||
"items_per_page",
|
"items_per_page",
|
||||||
|
@@ -270,6 +270,17 @@ reddit.com/r/Music music reddit</pre>
|
|||||||
This can be overridden when creating each new bookmark.
|
This can be overridden when creating each new bookmark.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="{{ form.default_mark_shared.id_for_label }}" class="form-checkbox">
|
||||||
|
{{ form.default_mark_shared }}
|
||||||
|
<i class="form-icon"></i> Create bookmarks as shared by default
|
||||||
|
</label>
|
||||||
|
<div class="form-input-hint">
|
||||||
|
Sets the default state for the "Share" option when creating a new bookmark.
|
||||||
|
Setting this option will make all new bookmarks default to shared.
|
||||||
|
This can be overridden when creating each new bookmark.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<details {% if form.custom_css.value %}open{% endif %}>
|
<details {% if form.custom_css.value %}open{% endif %}>
|
||||||
<summary>
|
<summary>
|
||||||
@@ -404,21 +415,25 @@ reddit.com/r/Music music reddit</pre>
|
|||||||
(function init() {
|
(function init() {
|
||||||
const enableSharing = document.getElementById("{{ form.enable_sharing.id_for_label }}");
|
const enableSharing = document.getElementById("{{ form.enable_sharing.id_for_label }}");
|
||||||
const enablePublicSharing = document.getElementById("{{ form.enable_public_sharing.id_for_label }}");
|
const enablePublicSharing = document.getElementById("{{ form.enable_public_sharing.id_for_label }}");
|
||||||
|
const defaultMarkShared = document.getElementById("{{ form.default_mark_shared.id_for_label }}");
|
||||||
const bookmarkDescriptionDisplay = document.getElementById("{{ form.bookmark_description_display.id_for_label }}");
|
const bookmarkDescriptionDisplay = document.getElementById("{{ form.bookmark_description_display.id_for_label }}");
|
||||||
const bookmarkDescriptionMaxLines = document.getElementById("{{ form.bookmark_description_max_lines.id_for_label }}");
|
const bookmarkDescriptionMaxLines = document.getElementById("{{ form.bookmark_description_max_lines.id_for_label }}");
|
||||||
|
|
||||||
// Automatically disable public bookmark sharing if bookmark sharing is disabled
|
// Automatically disable public bookmark sharing and default shared option if bookmark sharing is disabled
|
||||||
function updatePublicSharing() {
|
function updateSharingOptions() {
|
||||||
if (enableSharing.checked) {
|
if (enableSharing.checked) {
|
||||||
enablePublicSharing.disabled = false;
|
enablePublicSharing.disabled = false;
|
||||||
|
defaultMarkShared.disabled = false;
|
||||||
} else {
|
} else {
|
||||||
enablePublicSharing.disabled = true;
|
enablePublicSharing.disabled = true;
|
||||||
enablePublicSharing.checked = false;
|
enablePublicSharing.checked = false;
|
||||||
|
defaultMarkShared.disabled = true;
|
||||||
|
defaultMarkShared.checked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePublicSharing();
|
updateSharingOptions();
|
||||||
enableSharing.addEventListener("change", updatePublicSharing);
|
enableSharing.addEventListener("change", updateSharingOptions);
|
||||||
|
|
||||||
// Automatically hide the bookmark description max lines input if the description display is set to inline
|
// Automatically hide the bookmark description max lines input if the description display is set to inline
|
||||||
function updateBookmarkDescriptionMaxLines() {
|
function updateBookmarkDescriptionMaxLines() {
|
||||||
|
@@ -281,3 +281,28 @@ class BookmarkNewViewTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
'<input type="checkbox" name="unread" id="id_unread" checked="" aria-describedby="id_unread_help">',
|
'<input type="checkbox" name="unread" id="id_unread" checked="" aria-describedby="id_unread_help">',
|
||||||
html,
|
html,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_should_not_check_shared_by_default(self):
|
||||||
|
self.user.profile.enable_sharing = True
|
||||||
|
self.user.profile.save()
|
||||||
|
|
||||||
|
response = self.client.get(reverse("linkding:bookmarks.new"))
|
||||||
|
html = response.content.decode()
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
'<input type="checkbox" name="shared" id="id_shared" aria-describedby="id_shared_help">',
|
||||||
|
html,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_should_check_shared_when_configured_in_profile(self):
|
||||||
|
self.user.profile.enable_sharing = True
|
||||||
|
self.user.profile.default_mark_shared = True
|
||||||
|
self.user.profile.save()
|
||||||
|
|
||||||
|
response = self.client.get(reverse("linkding:bookmarks.new"))
|
||||||
|
html = response.content.decode()
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
'<input type="checkbox" name="shared" id="id_shared" checked="" aria-describedby="id_shared_help">',
|
||||||
|
html,
|
||||||
|
)
|
||||||
|
@@ -115,6 +115,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
"display_remove_bookmark_action": False,
|
"display_remove_bookmark_action": False,
|
||||||
"permanent_notes": True,
|
"permanent_notes": True,
|
||||||
"default_mark_unread": True,
|
"default_mark_unread": True,
|
||||||
|
"default_mark_shared": True,
|
||||||
"custom_css": "body { background-color: #000; }",
|
"custom_css": "body { background-color: #000; }",
|
||||||
"auto_tagging_rules": "example.com tag",
|
"auto_tagging_rules": "example.com tag",
|
||||||
"items_per_page": "10",
|
"items_per_page": "10",
|
||||||
@@ -188,6 +189,9 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.user.profile.default_mark_unread, form_data["default_mark_unread"]
|
self.user.profile.default_mark_unread, form_data["default_mark_unread"]
|
||||||
)
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
self.user.profile.default_mark_shared, form_data["default_mark_shared"]
|
||||||
|
)
|
||||||
self.assertEqual(self.user.profile.custom_css, form_data["custom_css"])
|
self.assertEqual(self.user.profile.custom_css, form_data["custom_css"])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.user.profile.auto_tagging_rules, form_data["auto_tagging_rules"]
|
self.user.profile.auto_tagging_rules, form_data["auto_tagging_rules"]
|
||||||
|
@@ -18,28 +18,43 @@ class SettingsGeneralE2ETestCase(LinkdingE2ETestCase):
|
|||||||
enable_public_sharing_label = page.get_by_text(
|
enable_public_sharing_label = page.get_by_text(
|
||||||
"Enable public bookmark sharing"
|
"Enable public bookmark sharing"
|
||||||
)
|
)
|
||||||
|
default_mark_shared = page.get_by_label(
|
||||||
|
"Create bookmarks as shared by default"
|
||||||
|
)
|
||||||
|
default_mark_shared_label = page.get_by_text(
|
||||||
|
"Create bookmarks as shared by default"
|
||||||
|
)
|
||||||
|
|
||||||
# Public sharing is disabled by default
|
# Public sharing and default shared are disabled by default
|
||||||
expect(enable_sharing).not_to_be_checked()
|
expect(enable_sharing).not_to_be_checked()
|
||||||
expect(enable_public_sharing).not_to_be_checked()
|
expect(enable_public_sharing).not_to_be_checked()
|
||||||
expect(enable_public_sharing).to_be_disabled()
|
expect(enable_public_sharing).to_be_disabled()
|
||||||
|
expect(default_mark_shared).not_to_be_checked()
|
||||||
|
expect(default_mark_shared).to_be_disabled()
|
||||||
|
|
||||||
# Enable sharing
|
# Enable sharing
|
||||||
enable_sharing_label.click()
|
enable_sharing_label.click()
|
||||||
expect(enable_sharing).to_be_checked()
|
expect(enable_sharing).to_be_checked()
|
||||||
expect(enable_public_sharing).not_to_be_checked()
|
expect(enable_public_sharing).not_to_be_checked()
|
||||||
expect(enable_public_sharing).to_be_enabled()
|
expect(enable_public_sharing).to_be_enabled()
|
||||||
|
expect(default_mark_shared).not_to_be_checked()
|
||||||
|
expect(default_mark_shared).to_be_enabled()
|
||||||
|
|
||||||
# Enable public sharing
|
# Enable public sharing and default shared
|
||||||
enable_public_sharing_label.click()
|
enable_public_sharing_label.click()
|
||||||
|
default_mark_shared_label.click()
|
||||||
expect(enable_public_sharing).to_be_checked()
|
expect(enable_public_sharing).to_be_checked()
|
||||||
expect(enable_public_sharing).to_be_enabled()
|
expect(enable_public_sharing).to_be_enabled()
|
||||||
|
expect(default_mark_shared).to_be_checked()
|
||||||
|
expect(default_mark_shared).to_be_enabled()
|
||||||
|
|
||||||
# Disable sharing
|
# Disable sharing
|
||||||
enable_sharing_label.click()
|
enable_sharing_label.click()
|
||||||
expect(enable_sharing).not_to_be_checked()
|
expect(enable_sharing).not_to_be_checked()
|
||||||
expect(enable_public_sharing).not_to_be_checked()
|
expect(enable_public_sharing).not_to_be_checked()
|
||||||
expect(enable_public_sharing).to_be_disabled()
|
expect(enable_public_sharing).to_be_disabled()
|
||||||
|
expect(default_mark_shared).not_to_be_checked()
|
||||||
|
expect(default_mark_shared).to_be_disabled()
|
||||||
|
|
||||||
def test_should_not_show_bookmark_description_max_lines_when_display_inline(self):
|
def test_should_not_show_bookmark_description_max_lines_when_display_inline(self):
|
||||||
profile = self.get_or_create_test_user().profile
|
profile = self.get_or_create_test_user().profile
|
||||||
|
Reference in New Issue
Block a user