Add option to collapse side panel (#975)

This commit is contained in:
Sascha Ißbrücker
2025-02-02 11:28:35 +01:00
committed by GitHub
parent 17442eeb9a
commit 0d4c47eb81
11 changed files with 131 additions and 15 deletions

View File

@@ -0,0 +1,48 @@
from django.urls import reverse
from playwright.sync_api import sync_playwright, expect
from bookmarks.e2e.helpers import LinkdingE2ETestCase
class CollapseSidePanelE2ETestCase(LinkdingE2ETestCase):
def setUp(self) -> None:
super().setUp()
def assertSidePanelIsVisible(self):
expect(self.page.locator(".bookmarks-page .side-panel")).to_be_visible()
expect(
self.page.locator(".bookmarks-page [ld-tag-modal-trigger]")
).not_to_be_visible()
def assertSidePanelIsHidden(self):
expect(self.page.locator(".bookmarks-page .side-panel")).not_to_be_visible()
expect(
self.page.locator(".bookmarks-page [ld-tag-modal-trigger]")
).to_be_visible()
def test_side_panel_should_be_visible_by_default(self):
with sync_playwright() as p:
self.open(reverse("bookmarks:index"), p)
self.assertSidePanelIsVisible()
self.page.goto(self.live_server_url + reverse("bookmarks:archived"))
self.assertSidePanelIsVisible()
self.page.goto(self.live_server_url + reverse("bookmarks:shared"))
self.assertSidePanelIsVisible()
def test_side_panel_should_be_hidden_when_collapsed(self):
user = self.get_or_create_test_user()
user.profile.collapse_side_panel = True
user.profile.save()
with sync_playwright() as p:
self.open(reverse("bookmarks:index"), p)
self.assertSidePanelIsHidden()
self.page.goto(self.live_server_url + reverse("bookmarks:archived"))
self.assertSidePanelIsHidden()
self.page.goto(self.live_server_url + reverse("bookmarks:shared"))
self.assertSidePanelIsHidden()

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.1.5 on 2025-02-02 09:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookmarks", "0042_userprofile_custom_css_hash"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="collapse_side_panel",
field=models.BooleanField(default=False),
),
]

View File

@@ -440,6 +440,7 @@ class UserProfile(models.Model):
null=False, default=30, validators=[MinValueValidator(10)]
)
sticky_pagination = models.BooleanField(default=False, null=False)
collapse_side_panel = models.BooleanField(default=False, null=False)
def save(self, *args, **kwargs):
if self.custom_css:
@@ -479,6 +480,7 @@ class UserProfileForm(forms.ModelForm):
"auto_tagging_rules",
"items_per_page",
"sticky_pagination",
"collapse_side_panel",
]

View File

@@ -36,7 +36,6 @@
}
}
& .sections section {
margin-top: var(--unit-4);
}

View File

@@ -10,8 +10,38 @@
}
/* Bookmark page grid */
.bookmarks-page.grid {
grid-gap: var(--unit-9);
.bookmarks-page {
&.grid {
grid-gap: var(--unit-9);
}
[ld-tag-modal-trigger] {
display: none;
}
@media (max-width: 840px) {
section.side-panel {
display: none;
}
[ld-tag-modal-trigger] {
display: inline-block;
}
}
&.collapse-side-panel {
section.main {
grid-column: span var(--grid-columns);
}
section.side-panel {
display: none;
}
[ld-tag-modal-trigger] {
display: inline-block;
}
}
}
/* Bookmark area header controls */

View File

@@ -4,16 +4,17 @@
{% load bookmarks %}
{% block content %}
<div ld-bulk-edit class="bookmarks-page grid columns-md-1">
<div ld-bulk-edit
class="bookmarks-page grid columns-md-1 {% if bookmark_list.collapse_side_panel %}collapse-side-panel{% endif %}">
{# Bookmark list #}
<section class="content-area col-2">
<section class="main content-area col-2">
<div class="content-area-header mb-0">
<h2>Archived bookmarks</h2>
<div class="header-controls">
{% bookmark_search bookmark_list.search mode='archived' %}
{% include 'bookmarks/bulk_edit/toggle.html' %}
<button ld-tag-modal-trigger class="btn ml-2 show-md">Tags
<button ld-tag-modal-trigger class="btn ml-2">Tags
</button>
</div>
</div>
@@ -31,7 +32,7 @@
</section>
{# Tag cloud #}
<section class="content-area col-1 hide-md">
<section class="side-panel content-area col-1">
<div class="content-area-header">
<h2>Tags</h2>
</div>

View File

@@ -4,16 +4,17 @@
{% load bookmarks %}
{% block content %}
<div ld-bulk-edit class="bookmarks-page grid columns-md-1">
<div ld-bulk-edit
class="bookmarks-page grid columns-md-1 {% if bookmark_list.collapse_side_panel %}collapse-side-panel{% endif %}">
{# Bookmark list #}
<section class="content-area col-2">
<section class="main content-area col-2">
<div class="content-area-header mb-0">
<h2>Bookmarks</h2>
<div class="header-controls">
{% bookmark_search bookmark_list.search %}
{% include 'bookmarks/bulk_edit/toggle.html' %}
<button ld-tag-modal-trigger class="btn ml-2 show-md">Tags</button>
<button ld-tag-modal-trigger class="btn ml-2">Tags</button>
</div>
</div>
@@ -30,7 +31,7 @@
</section>
{# Tag cloud #}
<section class="content-area col-1 hide-md">
<section class="side-panel content-area col-1">
<div class="content-area-header">
<h2>Tags</h2>
</div>

View File

@@ -4,15 +4,16 @@
{% load bookmarks %}
{% block content %}
<div class="bookmarks-page grid columns-md-1">
<div
class="bookmarks-page grid columns-md-1 {% if bookmark_list.collapse_side_panel %}collapse-side-panel{% endif %}">
{# Bookmark list #}
<section class="content-area col-2">
<section class="main content-area col-2">
<div class="content-area-header">
<h2>Shared bookmarks</h2>
<div class="header-controls">
{% bookmark_search bookmark_list.search mode='shared' %}
<button ld-tag-modal-trigger class="btn ml-2 show-md">Tags
<button ld-tag-modal-trigger class="btn ml-2">Tags
</button>
</div>
</div>
@@ -28,7 +29,7 @@
</section>
{# Filters #}
<section class="content-area col-1 hide-md">
<section class="side-panel content-area col-1">
<div class="content-area-header">
<h2>User</h2>
</div>

View File

@@ -124,6 +124,16 @@
visible without having to scroll to the end of the page first.
</div>
</div>
<div class="form-group">
<label for="{{ form.collapse_side_panel.id_for_label }}" class="form-checkbox">
{{ form.collapse_side_panel }}
<i class="form-icon"></i> Collapse tags
</label>
<div class="form-input-hint">
When enabled, the tags side panel will be collapsed by default to give more space to the bookmark list.
Instead, the tags can be shown in a modal dialog by clicking the tags button in the bookmark list header.
</div>
</div>
<div class="form-group">
<label for="{{ form.tag_search.id_for_label }}" class="form-label">Tag search</label>
{{ form.tag_search|add_class:"form-select width-25 width-sm-100" }}

View File

@@ -47,6 +47,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
"auto_tagging_rules": "",
"items_per_page": "30",
"sticky_pagination": False,
"collapse_side_panel": False,
}
return {**form_data, **overrides}
@@ -117,6 +118,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
"auto_tagging_rules": "example.com tag",
"items_per_page": "10",
"sticky_pagination": True,
"collapse_side_panel": True,
}
response = self.client.post(
reverse("bookmarks:settings.update"), form_data, follow=True
@@ -194,6 +196,9 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
self.assertEqual(
self.user.profile.sticky_pagination, form_data["sticky_pagination"]
)
self.assertEqual(
self.user.profile.collapse_side_panel, form_data["collapse_side_panel"]
)
self.assertSuccessMessage(html, "Profile updated")

View File

@@ -208,6 +208,7 @@ class BookmarkListContext:
self.show_favicons = user_profile.enable_favicons
self.show_preview_images = user_profile.enable_preview_images
self.show_notes = user_profile.permanent_notes
self.collapse_side_panel = user_profile.collapse_side_panel
@staticmethod
def generate_return_url(search: BookmarkSearch, base_url: str, page: int = None):