special-gallery: scope image prev/next/back to special galleries; add tests
This commit is contained in:
@@ -64,15 +64,15 @@ def append_query(url, query_dict):
|
|||||||
return url + "?" + urlencode(query_dict)
|
return url + "?" + urlencode(query_dict)
|
||||||
|
|
||||||
|
|
||||||
def gallery_url(path_obj=None, is_dir=False, query_dict=None):
|
def gallery_url(path_obj=None, is_dir=False, query_dict=None, special=None):
|
||||||
if query_dict is None:
|
if query_dict is None:
|
||||||
query_dict = {}
|
query_dict = {}
|
||||||
|
|
||||||
if path_obj is None:
|
if path_obj is None:
|
||||||
base_url = "/gallery/"
|
base_url = f"/gallery/{special}/" if special is not None else "/gallery/"
|
||||||
else:
|
else:
|
||||||
path_text = str(path_obj).replace("\\", "/")
|
path_text = str(path_obj).replace("\\", "/")
|
||||||
base_url = "/gallery/" + path_text
|
base_url = (f"/gallery/{special}/" if special is not None else "/gallery/") + path_text
|
||||||
|
|
||||||
if is_dir and not base_url.endswith("/"):
|
if is_dir and not base_url.endswith("/"):
|
||||||
base_url += "/"
|
base_url += "/"
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ def render_directory(request, path_text, full_path, special=None):
|
|||||||
image_data = []
|
image_data = []
|
||||||
for image in images:
|
for image in images:
|
||||||
rel_path = image.relative_to(settings.GALLERY_ROOT)
|
rel_path = image.relative_to(settings.GALLERY_ROOT)
|
||||||
image_url = gallery_url(rel_path, False, query_state)
|
image_url = gallery_url(rel_path, False, query_state, special)
|
||||||
|
|
||||||
thumbnail = None
|
thumbnail = None
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -115,10 +115,21 @@ def render_image(request, path_text, full_path, special=None):
|
|||||||
next_url = None
|
next_url = None
|
||||||
if prev_path is not None:
|
if prev_path is not None:
|
||||||
rel = prev_path.relative_to(settings.GALLERY_ROOT)
|
rel = prev_path.relative_to(settings.GALLERY_ROOT)
|
||||||
|
# When viewing from a special gallery, route prev/next through the
|
||||||
|
# special gallery URL so subsequent navigation preserves the special
|
||||||
|
# gallery context. Otherwise use the normal gallery URL for the file.
|
||||||
|
if special is not None:
|
||||||
|
rel_text = str(rel).replace("\\", "/")
|
||||||
|
prev_url = append_query(f"/gallery/{special}/{rel_text}/", query_state)
|
||||||
|
else:
|
||||||
prev_url = gallery_url(rel, False, query_state)
|
prev_url = gallery_url(rel, False, query_state)
|
||||||
|
|
||||||
if next_path is not None:
|
if next_path is not None:
|
||||||
rel = next_path.relative_to(settings.GALLERY_ROOT)
|
rel = next_path.relative_to(settings.GALLERY_ROOT)
|
||||||
|
if special is not None:
|
||||||
|
rel_text = str(rel).replace("\\", "/")
|
||||||
|
next_url = append_query(f"/gallery/{special}/{rel_text}/", query_state)
|
||||||
|
else:
|
||||||
next_url = gallery_url(rel, False, query_state)
|
next_url = gallery_url(rel, False, query_state)
|
||||||
|
|
||||||
# Back (directory) and Home (root) links and thumbnails
|
# Back (directory) and Home (root) links and thumbnails
|
||||||
|
|||||||
@@ -49,9 +49,11 @@
|
|||||||
<a href="/gallery/most-visited/" class="sidebar-link {% if active_special == 'most-visited' %}active-sort{% endif %}">Most visited</a>
|
<a href="/gallery/most-visited/" class="sidebar-link {% if active_special == 'most-visited' %}active-sort{% endif %}">Most visited</a>
|
||||||
<a href="/gallery/recent/" class="sidebar-link {% if active_special == 'recent' %}active-sort{% endif %}">Recently visited</a>
|
<a href="/gallery/recent/" class="sidebar-link {% if active_special == 'recent' %}active-sort{% endif %}">Recently visited</a>
|
||||||
|
|
||||||
{% if path != '' %}
|
{% if path != '' or is_special %}
|
||||||
<hr>
|
<hr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if path != '' %}
|
||||||
<a href="{{ back_url }}" class="subdir-item">
|
<a href="{{ back_url }}" class="subdir-item">
|
||||||
{% if back_thumb %}
|
{% if back_thumb %}
|
||||||
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
||||||
@@ -60,7 +62,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if path != '' or is_special %}
|
||||||
<a href="{{ home_url }}" class="subdir-item">
|
<a href="{{ home_url }}" class="subdir-item">
|
||||||
{% if home_thumb %}
|
{% if home_thumb %}
|
||||||
<img src="{{ home_thumb }}" class="subdir-thumb" alt="home thumb">
|
<img src="{{ home_thumb }}" class="subdir-thumb" alt="home thumb">
|
||||||
@@ -125,13 +129,15 @@
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<a href="/gallery/favorites/" class="sidebar-link">Favorites</a>
|
<a href="/gallery/favorites/" class="sidebar-link {% if active_special == 'favorites' %}active-sort{% endif %}">Favorites</a>
|
||||||
<a href="/gallery/most-visited/" class="sidebar-link">Most visited</a>
|
<a href="/gallery/most-visited/" class="sidebar-link {% if active_special == 'most-visited' %}active-sort{% endif %}">Most visited</a>
|
||||||
<a href="/gallery/recent/" class="sidebar-link">Recently visited</a>
|
<a href="/gallery/recent/" class="sidebar-link {% if active_special == 'recent' %}active-sort{% endif %}">Recently visited</a>
|
||||||
|
|
||||||
|
{% if path != '' or is_special %}
|
||||||
|
<hr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if path != '' %}
|
{% if path != '' %}
|
||||||
<hr>
|
|
||||||
|
|
||||||
<a href="{{ back_url }}" class="subdir-item">
|
<a href="{{ back_url }}" class="subdir-item">
|
||||||
{% if back_thumb %}
|
{% if back_thumb %}
|
||||||
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
||||||
@@ -140,7 +146,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if path != '' or is_special %}
|
||||||
<a href="{{ home_url }}" class="subdir-item">
|
<a href="{{ home_url }}" class="subdir-item">
|
||||||
{% if home_thumb %}
|
{% if home_thumb %}
|
||||||
<img src="{{ home_thumb }}" class="subdir-thumb" alt="home thumb">
|
<img src="{{ home_thumb }}" class="subdir-thumb" alt="home thumb">
|
||||||
@@ -265,13 +273,15 @@
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<a href="#" class="sidebar-link">Favorites</a>
|
<a href="/gallery/favorites/" class="sidebar-link {% if active_special == 'favorites' %}active-sort{% endif %}">Favorites</a>
|
||||||
<a href="#" class="sidebar-link">Most visited</a>
|
<a href="/gallery/most-visited/" class="sidebar-link {% if active_special == 'most-visited' %}active-sort{% endif %}">Most visited</a>
|
||||||
<a href="#" class="sidebar-link">Recently visited</a>
|
<a href="/gallery/recent/" class="sidebar-link {% if active_special == 'recent' %}active-sort{% endif %}">Recently visited</a>
|
||||||
|
|
||||||
|
{% if path != '' or is_special %}
|
||||||
|
<hr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if path != '' %}
|
{% if path != '' %}
|
||||||
<hr>
|
|
||||||
|
|
||||||
<a href="{{ back_url }}" class="subdir-item">
|
<a href="{{ back_url }}" class="subdir-item">
|
||||||
{% if back_thumb %}
|
{% if back_thumb %}
|
||||||
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
||||||
@@ -280,7 +290,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if path != '' or is_special %}
|
||||||
<a href="{{ home_url }}" class="subdir-item">
|
<a href="{{ home_url }}" class="subdir-item">
|
||||||
{% if home_thumb %}
|
{% if home_thumb %}
|
||||||
<img src="{{ home_thumb }}" class="subdir-thumb" alt="home thumb">
|
<img src="{{ home_thumb }}" class="subdir-thumb" alt="home thumb">
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="sidebar-scroll flex-grow-1">
|
<div class="sidebar-scroll flex-grow-1">
|
||||||
|
{% if not is_special or is_special and 'favorites' in breadcrumbs.0.path %}
|
||||||
{% if prev_url %}
|
{% if prev_url %}
|
||||||
<a href="{{ prev_url }}" class="subdir-item">
|
<a href="{{ prev_url }}" class="subdir-item">
|
||||||
{% if prev_thumb %}
|
{% if prev_thumb %}
|
||||||
@@ -67,7 +68,18 @@
|
|||||||
<span>Next</span>
|
<span>Next</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if is_special %}
|
||||||
|
<a href="{{ breadcrumbs.0.path }}" class="subdir-item">
|
||||||
|
{% if back_thumb %}
|
||||||
|
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
||||||
|
{% else %}
|
||||||
|
<span class="subdir-fallback"><i class="fa-solid fa-image"></i></span>
|
||||||
|
{% endif %}
|
||||||
|
<span>Back</span>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
<a href="{{ back_url }}" class="subdir-item">
|
<a href="{{ back_url }}" class="subdir-item">
|
||||||
{% if back_thumb %}
|
{% if back_thumb %}
|
||||||
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
||||||
@@ -76,6 +88,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<a href="{{ home_url }}" class="subdir-item">
|
<a href="{{ home_url }}" class="subdir-item">
|
||||||
{% if home_thumb %}
|
{% if home_thumb %}
|
||||||
@@ -221,6 +234,16 @@
|
|||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if is_special %}
|
||||||
|
<a href="{{ breadcrumbs.0.path }}" class="subdir-item">
|
||||||
|
{% if back_thumb %}
|
||||||
|
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
||||||
|
{% else %}
|
||||||
|
<span class="subdir-fallback"><i class="fa-solid fa-image"></i></span>
|
||||||
|
{% endif %}
|
||||||
|
<span>Back</span>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
<a href="{{ back_url }}" class="subdir-item">
|
<a href="{{ back_url }}" class="subdir-item">
|
||||||
{% if back_thumb %}
|
{% if back_thumb %}
|
||||||
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
<img src="{{ back_thumb }}" class="subdir-thumb" alt="back thumb">
|
||||||
@@ -229,6 +252,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<a href="{{ home_url }}" class="subdir-item">
|
<a href="{{ home_url }}" class="subdir-item">
|
||||||
{% if home_thumb %}
|
{% if home_thumb %}
|
||||||
|
|||||||
@@ -91,6 +91,41 @@ class SpecialGalleriesTests(TestCase):
|
|||||||
# Next should be c.jpg (since favorites are a.jpg and c.jpg sorted)
|
# Next should be c.jpg (since favorites are a.jpg and c.jpg sorted)
|
||||||
self.assertIn("c.jpg", ctx.get("next"))
|
self.assertIn("c.jpg", ctx.get("next"))
|
||||||
|
|
||||||
|
def test_favorites_image_view_prev_next_urls_and_back_link(self):
|
||||||
|
# Image view under favorites should produce prev/next URLs scoped to favorites
|
||||||
|
resp = self.client.get("/gallery/favorites/a.jpg/")
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
ctx = resp.context
|
||||||
|
self.assertTrue(ctx.get("is_special"))
|
||||||
|
|
||||||
|
crumbs = ctx.get("breadcrumbs")
|
||||||
|
# back link for template should point to the special root
|
||||||
|
self.assertTrue(crumbs[0]["path"].startswith("/gallery/favorites/"))
|
||||||
|
|
||||||
|
# prev_url should be None for first favorite; next_url should be inside favorites
|
||||||
|
self.assertIsNone(ctx.get("prev_url"))
|
||||||
|
next_url = ctx.get("next_url")
|
||||||
|
self.assertIsNotNone(next_url)
|
||||||
|
self.assertTrue(next_url.startswith("/gallery/favorites/"))
|
||||||
|
self.assertIn("c.jpg", next_url)
|
||||||
|
|
||||||
|
def test_most_visited_image_view_prev_next_urls(self):
|
||||||
|
# most-visited image view should scope prev/next URLs to the most-visited gallery
|
||||||
|
resp = self.client.get("/gallery/most-visited/b.jpg/")
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
ctx = resp.context
|
||||||
|
self.assertTrue(ctx.get("is_special"))
|
||||||
|
|
||||||
|
crumbs = ctx.get("breadcrumbs")
|
||||||
|
self.assertTrue(crumbs[0]["path"].startswith("/gallery/most-visited/"))
|
||||||
|
|
||||||
|
# b.jpg is the top most-visited image in fixtures => prev_url None, next_url points to a.jpg
|
||||||
|
self.assertIsNone(ctx.get("prev_url"))
|
||||||
|
next_url = ctx.get("next_url")
|
||||||
|
self.assertIsNotNone(next_url)
|
||||||
|
self.assertTrue(next_url.startswith("/gallery/most-visited/"))
|
||||||
|
self.assertIn("a.jpg", next_url)
|
||||||
|
|
||||||
def test_most_visited_and_recent_directory_views(self):
|
def test_most_visited_and_recent_directory_views(self):
|
||||||
# most-visited should list images ordered by visits desc
|
# most-visited should list images ordered by visits desc
|
||||||
resp = self.client.get("/gallery/most-visited/")
|
resp = self.client.get("/gallery/most-visited/")
|
||||||
|
|||||||
Reference in New Issue
Block a user