diff --git a/viewer/directory.py b/viewer/directory.py index 3788cec..4d15c6e 100644 --- a/viewer/directory.py +++ b/viewer/directory.py @@ -220,7 +220,16 @@ def render_directory(request, path_text, full_path, special=None): # expose which special is active so templates can highlight it context["active_special"] = special # Override breadcrumbs for special galleries to be a single label - context["breadcrumbs"] = [{"label": context["special_name"], "path": None}] + # and make it link to the special gallery root so templates can show + # it as an active, clickable breadcrumb. + from .specials import special_root_url + + context["breadcrumbs"] = [ + { + "label": context["special_name"], + "path": special_root_url(special, query_state), + } + ] # Hide the search box (templates use `is_special` to decide) context["search_text"] = "" context["search_action_url"] = "" diff --git a/viewer/image.py b/viewer/image.py index abe40ee..7741956 100644 --- a/viewer/image.py +++ b/viewer/image.py @@ -185,8 +185,13 @@ def render_image(request, path_text, full_path, special=None): # Breadcrumbs if special is not None: # SPECIAL NAME / IMAGE + from .specials import special_root_url + breadcrumbs = [ - {"label": special_name(special), "path": None}, + { + "label": special_name(special), + "path": special_root_url(special, query_state), + }, {"label": full_path.name, "path": None}, ] else: diff --git a/viewer/test_specials.py b/viewer/test_specials.py new file mode 100644 index 0000000..00ceb5e --- /dev/null +++ b/viewer/test_specials.py @@ -0,0 +1,53 @@ +from pathlib import Path +import tempfile +from django.test import TestCase, override_settings +from django.contrib.auth.models import User +from django.utils import timezone + +from viewer.models import Image as Im + + +class SpecialGalleriesTests(TestCase): + def setUp(self): + # prepare a temporary gallery root and files + self.tmp_gallery = tempfile.TemporaryDirectory() + self.gallery_root = Path(self.tmp_gallery.name) + self.settings_override = override_settings(GALLERY_ROOT=self.gallery_root) + self.settings_override.enable() + + self.user = User.objects.create_user("specuser", "s@example.com", "pw") + + # create files under gallery root + now = timezone.now() + a = self.gallery_root / "a.jpg" + b = self.gallery_root / "b.jpg" + c = self.gallery_root / "c.jpg" + for p in (a, b, c): + p.write_bytes(b"x") + + Im.objects.create( + user=self.user, path=str(a), favorite=True, visits=5, last_visited=now + ) + Im.objects.create( + user=self.user, path=str(b), favorite=False, visits=10, last_visited=now + ) + Im.objects.create( + user=self.user, path=str(c), favorite=True, visits=2, last_visited=now + ) + + def tearDown(self): + self.settings_override.disable() + self.tmp_gallery.cleanup() + + def test_get_special_paths_filters_and_orders(self): + from viewer.specials import get_special_paths + + favs = get_special_paths(self.user, "favorites") + # favorites should include only those marked favorite (a and c) + fav_names = sorted([p.name for p in favs]) + self.assertEqual(fav_names, ["a.jpg", "c.jpg"]) + + most = get_special_paths(self.user, "most-visited") + # most-visited should be ordered descending by visits, expect b.jpg first + self.assertGreaterEqual(len(most), 1) + self.assertEqual(most[0].name, "b.jpg")