mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Closes #6931: Include applied filters on object list view
This commit is contained in:
parent
6845fb0f00
commit
c7ebad0fbb
@ -5,6 +5,7 @@
|
|||||||
### Enhancements
|
### Enhancements
|
||||||
|
|
||||||
* [#6829](https://github.com/netbox-community/netbox/issues/6829) - Extend GraphQL API to support reverse generic relationships
|
* [#6829](https://github.com/netbox-community/netbox/issues/6829) - Extend GraphQL API to support reverse generic relationships
|
||||||
|
* [#6931](https://github.com/netbox-community/netbox/issues/6931) - Include applied filters on object list view
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
@ -47,9 +47,14 @@
|
|||||||
|
|
||||||
{# Object list #}
|
{# Object list #}
|
||||||
<div class="tab-pane show active" id="object-list" role="tabpanel" aria-labelledby="object-list-tab">
|
<div class="tab-pane show active" id="object-list" role="tabpanel" aria-labelledby="object-list-tab">
|
||||||
{% if table.paginator.num_pages > 1 %}
|
|
||||||
|
|
||||||
{# "Select all" form #}
|
{# Applied filters #}
|
||||||
|
{% if filter_form %}
|
||||||
|
{% applied_filters filter_form request.GET %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# "Select all" form #}
|
||||||
|
{% if table.paginator.num_pages > 1 %}
|
||||||
{% with bulk_edit_url=content_type.model_class|validated_viewname:"bulk_edit" bulk_delete_url=content_type.model_class|validated_viewname:"bulk_delete" %}
|
{% with bulk_edit_url=content_type.model_class|validated_viewname:"bulk_edit" bulk_delete_url=content_type.model_class|validated_viewname:"bulk_delete" %}
|
||||||
<div id="select-all-box" class="d-none card noprint">
|
<div id="select-all-box" class="d-none card noprint">
|
||||||
<form method="post" class="form col-md-12">
|
<form method="post" class="form col-md-12">
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
{% if applied_filters %}
|
||||||
|
<div class="mb-3">
|
||||||
|
{% for filter in applied_filters %}
|
||||||
|
<a href="{{ filter.link_url }}" class="badge rounded-pill bg-primary text-decoration-none me-1">
|
||||||
|
<i class="mdi mdi-close"></i> {{ filter.link_text }}
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
@ -3,6 +3,7 @@ import re
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.forms.models import fields_for_model
|
from django.forms.models import fields_for_model
|
||||||
|
|
||||||
|
from utilities.choices import unpack_grouped_choices
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
from .constants import *
|
from .constants import *
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ __all__ = (
|
|||||||
'expand_alphanumeric_pattern',
|
'expand_alphanumeric_pattern',
|
||||||
'expand_ipaddress_pattern',
|
'expand_ipaddress_pattern',
|
||||||
'form_from_model',
|
'form_from_model',
|
||||||
|
'get_selected_values',
|
||||||
'parse_alphanumeric_range',
|
'parse_alphanumeric_range',
|
||||||
'parse_numeric_range',
|
'parse_numeric_range',
|
||||||
'restrict_form_fields',
|
'restrict_form_fields',
|
||||||
@ -111,6 +113,30 @@ def expand_ipaddress_pattern(string, family):
|
|||||||
yield ''.join([lead, format(i, 'x' if family == 6 else 'd'), remnant])
|
yield ''.join([lead, format(i, 'x' if family == 6 else 'd'), remnant])
|
||||||
|
|
||||||
|
|
||||||
|
def get_selected_values(form, field_name):
|
||||||
|
"""
|
||||||
|
Return the list of selected human-friendly values for a form field
|
||||||
|
"""
|
||||||
|
if not hasattr(form, 'cleaned_data'):
|
||||||
|
form.is_valid()
|
||||||
|
|
||||||
|
# Selection field
|
||||||
|
if hasattr(form.fields[field_name], 'choices'):
|
||||||
|
try:
|
||||||
|
choices = dict(unpack_grouped_choices(form.fields[field_name].choices))
|
||||||
|
return [
|
||||||
|
label for value, label in choices.items() if value in form.cleaned_data[field_name]
|
||||||
|
]
|
||||||
|
except TypeError:
|
||||||
|
# Field uses dynamic choices. Show all that have been populated.
|
||||||
|
return [
|
||||||
|
subwidget.choice_label for subwidget in form[field_name].subwidgets
|
||||||
|
]
|
||||||
|
|
||||||
|
# Non-selection field
|
||||||
|
return [str(form.cleaned_data[field_name])]
|
||||||
|
|
||||||
|
|
||||||
def add_blank_choice(choices):
|
def add_blank_choice(choices):
|
||||||
"""
|
"""
|
||||||
Add a blank choice to the beginning of a choices list.
|
Add a blank choice to the beginning of a choices list.
|
||||||
|
@ -13,7 +13,7 @@ from django.utils.html import strip_tags
|
|||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from markdown import markdown
|
from markdown import markdown
|
||||||
|
|
||||||
from utilities.forms import TableConfigForm
|
from utilities.forms import get_selected_values, TableConfigForm
|
||||||
from utilities.utils import foreground_color
|
from utilities.utils import foreground_color
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
@ -403,3 +403,32 @@ def table_config_form(table, table_name=None):
|
|||||||
'table_name': table_name or table.__class__.__name__,
|
'table_name': table_name or table.__class__.__name__,
|
||||||
'table_config_form': TableConfigForm(table=table),
|
'table_config_form': TableConfigForm(table=table),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@register.inclusion_tag('utilities/templatetags/applied_filters.html')
|
||||||
|
def applied_filters(form, query_params):
|
||||||
|
"""
|
||||||
|
Display the active filters for a given filter form.
|
||||||
|
"""
|
||||||
|
form.is_valid()
|
||||||
|
|
||||||
|
applied_filters = []
|
||||||
|
for filter_name in form.changed_data:
|
||||||
|
if filter_name not in query_params:
|
||||||
|
continue
|
||||||
|
|
||||||
|
bound_field = form.fields[filter_name].get_bound_field(form, filter_name)
|
||||||
|
querydict = query_params.copy()
|
||||||
|
querydict.pop(filter_name)
|
||||||
|
display_value = ', '.join(get_selected_values(form, filter_name))
|
||||||
|
|
||||||
|
applied_filters.append({
|
||||||
|
'name': filter_name,
|
||||||
|
'value': form.cleaned_data[filter_name],
|
||||||
|
'link_url': f'?{querydict.urlencode()}',
|
||||||
|
'link_text': f'{bound_field.label}: {display_value}',
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
'applied_filters': applied_filters,
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user