Add option for list filter quick remove. #183
* add option for list filter quick remove * move transform from css to python * make template tag more resilient for unusual filters * fix tests * rename field, move rendering to template, change style * fix testsmaster
parent
de2979219e
commit
f8ace75f36
|
|
@ -163,8 +163,10 @@ class ThemeAdmin(admin.ModelAdmin):
|
||||||
{
|
{
|
||||||
"classes": ("wide",),
|
"classes": ("wide",),
|
||||||
"fields": (
|
"fields": (
|
||||||
|
"list_filter_highlight",
|
||||||
"list_filter_dropdown",
|
"list_filter_dropdown",
|
||||||
"list_filter_sticky",
|
"list_filter_sticky",
|
||||||
|
"list_filter_removal_links",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 4.0.7 on 2022-10-10 21:46
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('admin_interface', '0026_theme_list_filter_highlight'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='theme',
|
||||||
|
name='list_filter_removal_links',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='quick remove links for active filters at top of sidebar'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -340,6 +340,10 @@ class Theme(models.Model):
|
||||||
list_filter_sticky = models.BooleanField(
|
list_filter_sticky = models.BooleanField(
|
||||||
default=True, verbose_name=_("sticky position")
|
default=True, verbose_name=_("sticky position")
|
||||||
)
|
)
|
||||||
|
list_filter_removal_links = models.BooleanField(
|
||||||
|
default=False, verbose_name=_(
|
||||||
|
"quick remove links for active filters at top of sidebar")
|
||||||
|
)
|
||||||
|
|
||||||
foldable_apps = models.BooleanField(default=True, verbose_name=_("foldable apps"))
|
foldable_apps = models.BooleanField(default=True, verbose_name=_("foldable apps"))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -376,12 +376,24 @@
|
||||||
border-radius: var(--admin-interface-module-border-radius);
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter .changelist-filter-clear a {
|
||||||
|
font-size: 13px;
|
||||||
|
margin: .3em 0;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter .changelist-filter-clear a:focus,
|
||||||
|
.admin-interface .module.filtered #changelist-filter .changelist-filter-clear a:hover,
|
||||||
.admin-interface .module.filtered #changelist-filter #changelist-filter-clear a:focus,
|
.admin-interface .module.filtered #changelist-filter #changelist-filter-clear a:focus,
|
||||||
.admin-interface .module.filtered #changelist-filter #changelist-filter-clear a:hover {
|
.admin-interface .module.filtered #changelist-filter #changelist-filter-clear a:hover {
|
||||||
color: #666;
|
color: #666;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter .changelist-filter-clear a span {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.admin-interface .module.filtered #changelist-filter li a:focus,
|
.admin-interface .module.filtered #changelist-filter li a:focus,
|
||||||
.admin-interface .module.filtered #changelist-filter li a:hover {
|
.admin-interface .module.filtered #changelist-filter li a:hover {
|
||||||
color: #666;
|
color: #666;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{% extends "admin/change_list.html" %}
|
||||||
|
{% load i18n admin_list admin_interface_tags %}
|
||||||
|
{# copied from django 4.0.7 #}
|
||||||
|
|
||||||
|
{% block filters %}
|
||||||
|
{% if cl.has_filters %}
|
||||||
|
<div id="changelist-filter">
|
||||||
|
<h2>{% translate 'Filter' %}</h2>
|
||||||
|
{% if cl.has_active_filters %}
|
||||||
|
{% get_admin_interface_setting "list_filter_removal_links" as list_filter_removal_links %}
|
||||||
|
{% if list_filter_removal_links %}
|
||||||
|
{% for spec in cl.filter_specs %}{% admin_interface_filter_removal_link cl spec %}{% endfor %}
|
||||||
|
<h3 id="changelist-filter-clear">
|
||||||
|
<a href="{{ cl.clear_all_filters_qs }}">{% translate "Clear all filters" %} ✖</a>
|
||||||
|
</h3>
|
||||||
|
{% else %}
|
||||||
|
<h3 id="changelist-filter-clear">
|
||||||
|
<a href="{{ cl.clear_all_filters_qs }}">✖ {% translate "Clear all filters" %}</a>
|
||||||
|
</h3>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{% load admin_interface_tags %}
|
||||||
|
{% if spec.lookup_val or spec.value %}
|
||||||
|
<div class="changelist-filter-clear"><a href="{% admin_interface_clear_filter_qs cl spec %}">
|
||||||
|
{{ title|capfirst }}: <span>{{ selected_value }}</span> ✖
|
||||||
|
</a></div>
|
||||||
|
{% endif %}
|
||||||
|
|
@ -6,6 +6,7 @@ import re
|
||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.template.loader import get_template
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
|
|
||||||
from admin_interface.cache import get_cached_active_theme, set_cached_active_theme
|
from admin_interface.cache import get_cached_active_theme, set_cached_active_theme
|
||||||
|
|
@ -65,8 +66,8 @@ def get_admin_interface_languages(context):
|
||||||
return langs_data
|
return langs_data
|
||||||
|
|
||||||
|
|
||||||
@simple_tag(takes_context=True)
|
@simple_tag()
|
||||||
def get_admin_interface_theme(context):
|
def get_admin_interface_theme():
|
||||||
theme = get_cached_active_theme()
|
theme = get_cached_active_theme()
|
||||||
if not theme:
|
if not theme:
|
||||||
theme = Theme.get_active_theme()
|
theme = Theme.get_active_theme()
|
||||||
|
|
@ -74,6 +75,12 @@ def get_admin_interface_theme(context):
|
||||||
return theme
|
return theme
|
||||||
|
|
||||||
|
|
||||||
|
@simple_tag()
|
||||||
|
def get_admin_interface_setting(setting):
|
||||||
|
theme = get_admin_interface_theme()
|
||||||
|
return getattr(theme, setting)
|
||||||
|
|
||||||
|
|
||||||
@simple_tag(takes_context=False)
|
@simple_tag(takes_context=False)
|
||||||
def get_admin_interface_version():
|
def get_admin_interface_version():
|
||||||
return __version__
|
return __version__
|
||||||
|
|
@ -88,3 +95,27 @@ def hash_string(text):
|
||||||
@simple_tag(takes_context=False)
|
@simple_tag(takes_context=False)
|
||||||
def get_admin_interface_nocache():
|
def get_admin_interface_nocache():
|
||||||
return hash_string(__version__)
|
return hash_string(__version__)
|
||||||
|
|
||||||
|
|
||||||
|
@simple_tag()
|
||||||
|
def admin_interface_clear_filter_qs(changelist, list_filter):
|
||||||
|
return changelist.get_query_string(remove=list_filter.expected_parameters())
|
||||||
|
|
||||||
|
|
||||||
|
@simple_tag()
|
||||||
|
def admin_interface_filter_removal_link(changelist, list_filter):
|
||||||
|
tpl = get_template('admin_interface/list_filter_removal_link.html')
|
||||||
|
title = list_filter.title
|
||||||
|
|
||||||
|
choices = [c for c in list_filter.choices(changelist) if c['selected']]
|
||||||
|
try:
|
||||||
|
value = choices[0]['display']
|
||||||
|
except (IndexError, KeyError):
|
||||||
|
value = '...'
|
||||||
|
|
||||||
|
return tpl.render({
|
||||||
|
'cl': changelist,
|
||||||
|
'spec': list_filter,
|
||||||
|
'selected_value': value,
|
||||||
|
'title': title,
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -102,20 +102,7 @@ class AdminInterfaceTemplateTagsTestCase(TestCase):
|
||||||
def test_get_theme(self):
|
def test_get_theme(self):
|
||||||
Theme.objects.all().delete()
|
Theme.objects.all().delete()
|
||||||
context = Context({})
|
context = Context({})
|
||||||
theme = templatetags.get_admin_interface_theme(context)
|
theme = templatetags.get_admin_interface_theme()
|
||||||
self.assertEqual(theme.name, "Django")
|
|
||||||
rendered = self.__render_template(
|
|
||||||
"{% load admin_interface_tags %}"
|
|
||||||
"{% get_admin_interface_theme as theme %}"
|
|
||||||
"{{ theme.name }}",
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
self.assertEqual(rendered, "Django")
|
|
||||||
|
|
||||||
def test_get_theme_with_request(self):
|
|
||||||
Theme.objects.all().delete()
|
|
||||||
context = Context({"request": self.request_factory.get("/")})
|
|
||||||
theme = templatetags.get_admin_interface_theme(context)
|
|
||||||
self.assertEqual(theme.name, "Django")
|
self.assertEqual(theme.name, "Django")
|
||||||
rendered = self.__render_template(
|
rendered = self.__render_template(
|
||||||
"{% load admin_interface_tags %}"
|
"{% load admin_interface_tags %}"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue