diff --git a/viewer/directory.py b/viewer/directory.py index b1b34eb..e13f02c 100644 --- a/viewer/directory.py +++ b/viewer/directory.py @@ -169,6 +169,9 @@ def render_directory(request, path_text, full_path): "search_action_url": gallery_url( Path(path_text) if path_text != "" else None, True, search_action_query ), + "clear_search_url": gallery_url( + Path(path_text) if path_text != "" else None, True, None + ), } # sort_label depends on SORT_LABELS in common; import lazily to avoid circulars diff --git a/viewer/templates/gallery_view.html b/viewer/templates/gallery_view.html index e8186df..090152e 100644 --- a/viewer/templates/gallery_view.html +++ b/viewer/templates/gallery_view.html @@ -33,6 +33,11 @@
+ {% if search_text %} + + + + {% endif %}
diff --git a/viewer/test.py b/viewer/test.py index 583cb40..55d2ef3 100644 --- a/viewer/test.py +++ b/viewer/test.py @@ -235,6 +235,26 @@ class GalleryViewTests(GalleryBaseTests): self.assertIn("sort=recent", url) self.assertIn("theme=light", url) + def test_clear_search_url_present_and_clears_query(self): + # When a search is active the context should provide a URL that + # clears the search (no query parameters) for the current path. + response = self.client.get("/gallery/?search=match&sort=recent&theme=light") + self.assertEqual(response.status_code, 200) + + clear_url = response.context.get("clear_search_url") + # For the root path the clear URL should be the gallery root without query + self.assertEqual(clear_url, "/gallery/") + + def test_clear_search_url_uses_nested_path(self): + # Ensure clear_search_url respects nested paths (clears search but preserves path) + response = self.client.get( + "/gallery/sub_a/?search=match&sort=recent&theme=light" + ) + self.assertEqual(response.status_code, 200) + + clear_url = response.context.get("clear_search_url") + self.assertTrue(clear_url.find("/gallery/sub_a/") == 0) + def test_search_action_url_uses_nested_path(self): response = self.client.get("/gallery/sub_a/?sort=recent&theme=light") self.assertEqual(response.status_code, 200) @@ -445,6 +465,17 @@ class GalleryTemplateTests(GalleryBaseTests): self.assertIn("Most visited", body) self.assertIn("Recently visited", body) + def test_clear_search_button_shown_when_searching(self): + # The template should render a clear-search button when a search is active + resp = self.client.get("/gallery/?search=match") + body = resp.content.decode("utf-8") + self.assertIn('aria-label="Clear search"', body) + + # And it should not be present when there's no search + resp2 = self.client.get("/gallery/") + body2 = resp2.content.decode("utf-8") + self.assertNotIn('aria-label="Clear search"', body2) + def test_template_shows_fallback_icon_for_empty_subdir(self): response = self.client.get("/gallery/") self.assertEqual(response.status_code, 200)