mirror of
				https://github.com/sissbruecker/linkding.git
				synced 2025-11-04 04:54:09 +01: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"),
 | 
			
		||||
                "auto_close": "auto_close" in request.GET,
 | 
			
		||||
                "unread": request.user_profile.default_mark_unread,
 | 
			
		||||
                "shared": request.user_profile.default_mark_shared,
 | 
			
		||||
            }
 | 
			
		||||
        if instance is not None and request.method == "GET":
 | 
			
		||||
            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)
 | 
			
		||||
    enable_automatic_html_snapshots = models.BooleanField(default=True, 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(
 | 
			
		||||
        null=False, default=30, validators=[MinValueValidator(10)]
 | 
			
		||||
    )
 | 
			
		||||
@@ -520,6 +521,7 @@ class UserProfileForm(forms.ModelForm):
 | 
			
		||||
            "display_remove_bookmark_action",
 | 
			
		||||
            "permanent_notes",
 | 
			
		||||
            "default_mark_unread",
 | 
			
		||||
            "default_mark_shared",
 | 
			
		||||
            "custom_css",
 | 
			
		||||
            "auto_tagging_rules",
 | 
			
		||||
            "items_per_page",
 | 
			
		||||
 
 | 
			
		||||
@@ -270,6 +270,17 @@ reddit.com/r/Music music reddit</pre>
 | 
			
		||||
            This can be overridden when creating each new bookmark.
 | 
			
		||||
          </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">
 | 
			
		||||
          <details {% if form.custom_css.value %}open{% endif %}>
 | 
			
		||||
            <summary>
 | 
			
		||||
@@ -404,21 +415,25 @@ reddit.com/r/Music music reddit</pre>
 | 
			
		||||
    (function init() {
 | 
			
		||||
      const enableSharing = document.getElementById("{{ form.enable_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 bookmarkDescriptionMaxLines = document.getElementById("{{ form.bookmark_description_max_lines.id_for_label }}");
 | 
			
		||||
 | 
			
		||||
      // Automatically disable public bookmark sharing if bookmark sharing is disabled
 | 
			
		||||
      function updatePublicSharing() {
 | 
			
		||||
      // Automatically disable public bookmark sharing and default shared option if bookmark sharing is disabled
 | 
			
		||||
      function updateSharingOptions() {
 | 
			
		||||
        if (enableSharing.checked) {
 | 
			
		||||
          enablePublicSharing.disabled = false;
 | 
			
		||||
          defaultMarkShared.disabled = false;
 | 
			
		||||
        } else {
 | 
			
		||||
          enablePublicSharing.disabled = true;
 | 
			
		||||
          enablePublicSharing.checked = false;
 | 
			
		||||
          defaultMarkShared.disabled = true;
 | 
			
		||||
          defaultMarkShared.checked = false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      updatePublicSharing();
 | 
			
		||||
      enableSharing.addEventListener("change", updatePublicSharing);
 | 
			
		||||
      updateSharingOptions();
 | 
			
		||||
      enableSharing.addEventListener("change", updateSharingOptions);
 | 
			
		||||
 | 
			
		||||
      // Automatically hide the bookmark description max lines input if the description display is set to inline
 | 
			
		||||
      function updateBookmarkDescriptionMaxLines() {
 | 
			
		||||
 
 | 
			
		||||
@@ -281,3 +281,28 @@ class BookmarkNewViewTestCase(TestCase, BookmarkFactoryMixin):
 | 
			
		||||
            '<input type="checkbox" name="unread" id="id_unread" checked="" aria-describedby="id_unread_help">',
 | 
			
		||||
            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,
 | 
			
		||||
            "permanent_notes": True,
 | 
			
		||||
            "default_mark_unread": True,
 | 
			
		||||
            "default_mark_shared": True,
 | 
			
		||||
            "custom_css": "body { background-color: #000; }",
 | 
			
		||||
            "auto_tagging_rules": "example.com tag",
 | 
			
		||||
            "items_per_page": "10",
 | 
			
		||||
@@ -188,6 +189,9 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            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.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 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_public_sharing).not_to_be_checked()
 | 
			
		||||
            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_label.click()
 | 
			
		||||
            expect(enable_sharing).to_be_checked()
 | 
			
		||||
            expect(enable_public_sharing).not_to_be_checked()
 | 
			
		||||
            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()
 | 
			
		||||
            default_mark_shared_label.click()
 | 
			
		||||
            expect(enable_public_sharing).to_be_checked()
 | 
			
		||||
            expect(enable_public_sharing).to_be_enabled()
 | 
			
		||||
            expect(default_mark_shared).to_be_checked()
 | 
			
		||||
            expect(default_mark_shared).to_be_enabled()
 | 
			
		||||
 | 
			
		||||
            # Disable sharing
 | 
			
		||||
            enable_sharing_label.click()
 | 
			
		||||
            expect(enable_sharing).not_to_be_checked()
 | 
			
		||||
            expect(enable_public_sharing).not_to_be_checked()
 | 
			
		||||
            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):
 | 
			
		||||
        profile = self.get_or_create_test_user().profile
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user