Add ability to filter image index by a tag

- Fixed error when searching and filtering by tag at the same time
pull/5679/head
Benedikt Willi 2019-11-12 14:43:09 +01:00 zatwierdzone przez LB
rodzic 749d0172e5
commit 233e7f5189
9 zmienionych plików z 153 dodań i 13 usunięć

Wyświetl plik

@ -17,6 +17,7 @@ Changelog
* Cleaned up Django docs URLs in documentation (Pete Andrew)
* Add StreamFieldPanel to available panel types in documentation (Dan Swain)
* Add {{ block.super }} example to ModelAdmin customisation in documentation (Dan Swain)
* Add ability to filter image index by a tag (Benedikt Willi)
* Fix: Rename documents listing column 'uploaded' to 'created' (LB (Ben Johnston))
* Fix: Submenu items longer then the page height are no longer broken by the submenu footer (Igor van Spengen)
* Fix: Unbundle the l18n library as it was bundled to avoid installation errors which have been resolved (Matt Westcott)

Wyświetl plik

@ -425,6 +425,7 @@ Contributors
* Tim Gates
* Timothy Bautista
* Pete Andrew
* Benedikt Willi
Translators
===========

Wyświetl plik

@ -106,7 +106,7 @@
}
&.bicolor {
border: 0;
border: 1px solid transparent;
padding-left: 3.5em;
&:before {
@ -123,6 +123,10 @@
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
&.button-secondary {
border: 1px solid rgba(0, 0, 0, 0.2);
}
}
&.button-small.bicolor {

Wyświetl plik

@ -29,9 +29,33 @@ a.tag:hover {
.taglist {
font-size: 0.9em;
line-height: 2.4em;
}
h3 {
display: inline;
margin-right: 1em;
.tagfilter {
legend {
@include visuallyvisible;
@include media-breakpoint-up(sm) {
@include column(2);
padding-left: 0;
}
font-weight: 700;
color: #333;
font-size: 1.1em;
display: block;
padding: 0 0 0.8em;
}
a {
font-size: 0.9em;
}
.button.bicolor.icon-cross {
padding-left: 2em;
&:before {
background-color: transparent;
}
}
}

Wyświetl plik

@ -81,10 +81,10 @@
@mixin visuallyvisible {
clip: none;
clip: auto;
height: auto;
width: auto;
margin: auto;
margin: initial;
overflow: visible;
position: initial;
}

Wyświetl plik

@ -26,6 +26,7 @@ Other features
* Cleaned up Django docs URLs in documentation (Pete Andrew)
* Add StreamFieldPanel to available panel types in documentation (Dan Swain)
* Add {{ block.super }} example to ModelAdmin customisation in documentation (Dan Swain)
* Add ability to filter image index by a tag (Benedikt Willi)
Bug fixes

Wyświetl plik

@ -1,4 +1,5 @@
{% extends "wagtailadmin/base.html" %}
{% load wagtailadmin_tags %}
{% load wagtailimages_tags %}
{% load i18n %}
@ -31,13 +32,33 @@
{% endif %}
<div class="nice-padding">
{% if collections %}
<form class="image-search search-bar" action="{% url 'wagtailimages:index' %}" method="GET" novalidate>
<ul class="fields">
<form class="image-search search-bar" action="{% url 'wagtailimages:index' %}" method="GET" novalidate>
<ul class="fields">
{% if collections %}
{% include "wagtailadmin/shared/collection_chooser.html" %}
</ul>
</form>
{% endif %}
{% if current_tag %}
<input type="hidden" name="tag" value="{{ current_tag }}" />
{% endif %}
{% endif %}
{% if popular_tags %}
<li>
<fieldset class="tagfilter">
<legend>{% trans 'Popular Tags:' %}</legend>
{% for tag in popular_tags %}
{% if tag.name != current_tag %}
<a class="button button-small button-secondary bicolor icon icon-tag" href="{% url 'wagtailimages:index' %}{% querystring tag=tag.name %}">{{ tag.name }}</a>
{% else %}
<a class="button button-small bicolor icon icon-tag" href="{% url 'wagtailimages:index' %}{% querystring tag=tag.name %}">{{ tag.name }}</a>
{% endif %}
{% endfor %}
{% if current_tag %}
<a class="button button-small bicolor button-secondary icon icon-cross" href="{% url 'wagtailimages:index' %}{% querystring tag='' %}">{% trans 'Clear choice' %}</a>
{% endif %}
</fieldset>
</li>
{% endif %}
</ul>
</form>
<div id="image-results">
{% include "wagtailimages/images/results.html" %}

Wyświetl plik

@ -50,7 +50,7 @@ class TestImageIndexView(TestCase, WagtailTestUtils):
for i in range(1, 50):
self.image = Image.objects.create(
title="Test image %i" % i,
file=get_test_image_file(),
file=get_test_image_file(size=(1, 1)),
collection=evil_plans_collection
)
@ -87,6 +87,85 @@ class TestImageIndexView(TestCase, WagtailTestUtils):
['Root', 'Evil plans', 'Good plans'])
def test_tags(self):
image_two_tags = Image.objects.create(
title="Test image with two tags",
file=get_test_image_file(),
)
image_two_tags.tags.add("one", "two")
response = self.get()
self.assertEqual(response.status_code, 200)
current_tag = response.context['current_tag']
self.assertIsNone(current_tag)
tags = response.context['popular_tags']
self.assertTrue(
[tag.name for tag in tags] == ["one", "two"]
or [tag.name for tag in tags] == ["two", "one"]
)
def test_tag_filtering(self):
Image.objects.create(
title="Test image with no tags",
file=get_test_image_file(),
)
image_one_tag = Image.objects.create(
title="Test image with one tag",
file=get_test_image_file(),
)
image_one_tag.tags.add("one")
image_two_tags = Image.objects.create(
title="Test image with two tags",
file=get_test_image_file(),
)
image_two_tags.tags.add("one", "two")
# no filtering
response = self.get()
self.assertEqual(response.context['images'].paginator.count, 3)
# filter all images with tag 'one'
response = self.get({'tag': 'one'})
self.assertEqual(response.context['images'].paginator.count, 2)
# filter all images with tag 'two'
response = self.get({'tag': 'two'})
self.assertEqual(response.context['images'].paginator.count, 1)
def test_tag_filtering_preserves_other_params(self):
for i in range(1, 100):
image = Image.objects.create(
title="Test image %i" % i,
file=get_test_image_file(size=(1, 1)),
)
if (i % 2 != 0):
image.tags.add('even')
image.save()
response = self.get({'tag': 'even', 'p': 2})
self.assertEqual(response.status_code, 200)
response_body = response.content.decode('utf8')
# prev link should exist and include tag
self.assertTrue(
"?p=2&amp;tag=even" in response_body
or "?tag=even&amp;p=1" in response_body
)
# next link should exist and include tag
self.assertTrue(
"?p=3&amp;tag=even" in response_body
or "?tag=even&amp;p=3" in response_body
)
class TestImageAddView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()

Wyświetl plik

@ -59,6 +59,14 @@ def index(request):
except (ValueError, Collection.DoesNotExist):
pass
# Filter by tag
current_tag = request.GET.get('tag')
if current_tag:
try:
images = images.filter(tags__name=current_tag)
except (AttributeError):
current_tag = None
paginator = Paginator(images, per_page=INDEX_PAGE_SIZE)
images = paginator.get_page(request.GET.get('p'))
@ -85,6 +93,7 @@ def index(request):
'search_form': form,
'popular_tags': popular_tags_for_model(Image),
'current_tag': current_tag,
'collections': collections,
'current_collection': current_collection,
'user_can_add': permission_policy.user_has_permission(request.user, 'add'),