mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Fixes #2921: Replace tags filter with Select2 widget
This commit is contained in:
parent
b7e78028ce
commit
834fd408bd
@ -6,6 +6,7 @@
|
|||||||
* [#2050](https://github.com/netbox-community/netbox/issues/2050) - Preview image attachments when hovering the link
|
* [#2050](https://github.com/netbox-community/netbox/issues/2050) - Preview image attachments when hovering the link
|
||||||
* [#2113](https://github.com/netbox-community/netbox/issues/2113) - Allow NAPALM driver settings to be changed with request headers
|
* [#2113](https://github.com/netbox-community/netbox/issues/2113) - Allow NAPALM driver settings to be changed with request headers
|
||||||
* [#2589](https://github.com/netbox-community/netbox/issues/2589) - Toggle for showing available prefixes/ip addresses
|
* [#2589](https://github.com/netbox-community/netbox/issues/2589) - Toggle for showing available prefixes/ip addresses
|
||||||
|
* [#2921](https://github.com/netbox-community/netbox/issues/2921) - Replace tags filter with Select2 widget
|
||||||
* [#3009](https://github.com/netbox-community/netbox/issues/3009) - Search by description when assigning IP address
|
* [#3009](https://github.com/netbox-community/netbox/issues/3009) - Search by description when assigning IP address
|
||||||
* [#3090](https://github.com/netbox-community/netbox/issues/3090) - Add filter field for device interfaces
|
* [#3090](https://github.com/netbox-community/netbox/issues/3090) - Add filter field for device interfaces
|
||||||
* [#3187](https://github.com/netbox-community/netbox/issues/3187) - Add rack selection field to rack elevations
|
* [#3187](https://github.com/netbox-community/netbox/issues/3187) - Add rack selection field to rack elevations
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
{% load helpers %}
|
|
||||||
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<span class="fa fa-tags" aria-hidden="true"></span>
|
|
||||||
<strong>Tags</strong>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body text-center">
|
|
||||||
{% for tag in tags %}
|
|
||||||
<a href="{% querystring request tag=tag.slug %}" class="btn btn-sm {% if tag.slug in request.GET.tag %}btn-primary{% else %}btn-link{% endif %}">{{ tag }} <span class="badge">{{ tag.count }}</span></a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -17,7 +17,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<strong><i class="fa fa-bar-chart"></i> Statistics</strong>
|
<strong><i class="fa fa-bar-chart"></i> Statistics</strong>
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 noprint">
|
<div class="col-md-3 noprint">
|
||||||
{% include 'inc/search_panel.html' %}
|
{% include 'inc/search_panel.html' %}
|
||||||
{% include 'inc/tags_panel.html' %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.db import transaction, IntegrityError
|
from django.db import transaction, IntegrityError
|
||||||
from django.db.models import Count, ProtectedError
|
from django.db.models import Count, ProtectedError
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.forms import CharField, Form, ModelMultipleChoiceField, MultipleHiddenInput, Textarea
|
from django.forms import CharField, Form, ModelMultipleChoiceField, MultipleChoiceField, MultipleHiddenInput, Textarea
|
||||||
from django.http import HttpResponse, HttpResponseServerError
|
from django.http import HttpResponse, HttpResponseServerError
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
@ -24,7 +24,7 @@ from django_tables2 import RequestConfig
|
|||||||
|
|
||||||
from extras.models import CustomField, CustomFieldValue, ExportTemplate
|
from extras.models import CustomField, CustomFieldValue, ExportTemplate
|
||||||
from extras.querysets import CustomFieldQueryset
|
from extras.querysets import CustomFieldQueryset
|
||||||
from utilities.forms import BootstrapMixin, CSVDataField
|
from utilities.forms import BootstrapMixin, CSVDataField, StaticSelect2Multiple
|
||||||
from utilities.utils import csv_format
|
from utilities.utils import csv_format
|
||||||
from .error_handlers import handle_protectederror
|
from .error_handlers import handle_protectederror
|
||||||
from .forms import ConfirmationForm
|
from .forms import ConfirmationForm
|
||||||
@ -94,6 +94,7 @@ class ObjectListView(View):
|
|||||||
|
|
||||||
model = self.queryset.model
|
model = self.queryset.model
|
||||||
content_type = ContentType.objects.get_for_model(model)
|
content_type = ContentType.objects.get_for_model(model)
|
||||||
|
filter_form = self.filter_form(request.GET, label_suffix='') if self.filter_form else None
|
||||||
|
|
||||||
if self.filter:
|
if self.filter:
|
||||||
self.queryset = self.filter(request.GET, self.queryset).qs
|
self.queryset = self.filter(request.GET, self.queryset).qs
|
||||||
@ -142,11 +143,17 @@ class ObjectListView(View):
|
|||||||
if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
|
if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
|
||||||
table.columns.show('pk')
|
table.columns.show('pk')
|
||||||
|
|
||||||
# Construct queryset for tags list
|
# Add the tags filter field to the from if the model has tags
|
||||||
if hasattr(model, 'tags'):
|
if hasattr(model, 'tags') and filter_form:
|
||||||
tags = model.tags.annotate(count=Count('extras_taggeditem_items')).order_by('name')
|
tags = model.tags.annotate(count=Count('extras_taggeditem_items')).order_by('name')
|
||||||
else:
|
choices = [(str(tag.slug), '{} ({})'.format(tag.name, tag.count)) for tag in tags]
|
||||||
tags = None
|
|
||||||
|
filter_form.fields['tag'] = MultipleChoiceField(
|
||||||
|
label='Tags',
|
||||||
|
choices=choices,
|
||||||
|
required=False,
|
||||||
|
widget=StaticSelect2Multiple(),
|
||||||
|
)
|
||||||
|
|
||||||
# Apply the request context
|
# Apply the request context
|
||||||
paginate = {
|
paginate = {
|
||||||
@ -159,8 +166,7 @@ class ObjectListView(View):
|
|||||||
'content_type': content_type,
|
'content_type': content_type,
|
||||||
'table': table,
|
'table': table,
|
||||||
'permissions': permissions,
|
'permissions': permissions,
|
||||||
'filter_form': self.filter_form(request.GET, label_suffix='') if self.filter_form else None,
|
'filter_form': filter_form,
|
||||||
'tags': tags,
|
|
||||||
}
|
}
|
||||||
context.update(self.extra_context())
|
context.update(self.extra_context())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user