Merge 1c995fa5f9
into 815cab5c9a
This commit is contained in:
commit
9834bd4f55
|
@ -40,6 +40,7 @@ class BaseTable(tables.Table):
|
|||
:param user: Personalize table display for the given user (optional). Has no effect if AnonymousUser is passed.
|
||||
"""
|
||||
exempt_columns = ()
|
||||
filterset_form = None
|
||||
|
||||
class Meta:
|
||||
attrs = {
|
||||
|
|
|
@ -161,6 +161,18 @@ class ObjectListView(BaseMultiObjectView, ActionsMixin, TableMixin):
|
|||
# Render the objects table
|
||||
table = self.get_table(self.queryset, request, has_bulk_actions)
|
||||
|
||||
# Check for filterset_form on this view, if a form exists
|
||||
# * Apply to context for use by the filter form tab and initialize the form
|
||||
# * Apply to the table for use by the table and initialize a separate instance of the form for use by the table
|
||||
# column filters
|
||||
# * Otherwise set to None
|
||||
if self.filterset_form:
|
||||
filterset_form = self.filterset_form(request.GET)
|
||||
table.filterset_form = self.filterset_form(request.GET)
|
||||
else:
|
||||
filterset_form = None
|
||||
table.filterset_form = None
|
||||
|
||||
# If this is an HTMX request, return only the rendered table HTML
|
||||
if htmx_partial(request):
|
||||
if not request.htmx.target:
|
||||
|
@ -169,14 +181,16 @@ class ObjectListView(BaseMultiObjectView, ActionsMixin, TableMixin):
|
|||
if 'pk' in table.base_columns:
|
||||
table.columns.hide('pk')
|
||||
return render(request, 'htmx/table.html', {
|
||||
'model': model,
|
||||
'table': table,
|
||||
'filter_form': filterset_form,
|
||||
})
|
||||
|
||||
context = {
|
||||
'model': model,
|
||||
'table': table,
|
||||
'actions': actions,
|
||||
'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None,
|
||||
'filter_form': filterset_form,
|
||||
'prerequisite_model': get_prerequisite_model(self.queryset),
|
||||
**self.get_extra_context(request),
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -28,3 +28,20 @@ span.color-label {
|
|||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// Override bootstrap "dropdown" positioning and display for column filters
|
||||
.column-filter {
|
||||
position: static;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
// Override mdi font-size to adjust filter icon size
|
||||
.column-filter.dropdown > .dropdown-toggle > .mdi-filter-settings {
|
||||
font-size: .625rem;
|
||||
}
|
||||
|
||||
.column-filter.dropdown > .dropdown-menu {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.column-filter.dropdown-toggle:after { content: none }
|
|
@ -63,9 +63,7 @@ Context:
|
|||
<div class="tab-pane show active" id="object-list" role="tabpanel" aria-labelledby="object-list-tab">
|
||||
|
||||
{# Applied filters #}
|
||||
{% if filter_form %}
|
||||
{% applied_filters model filter_form request.GET %}
|
||||
{% endif %}
|
||||
{% include 'inc/applied_filters_pane.html' %}
|
||||
|
||||
{# Object table controls #}
|
||||
{% include 'inc/table_controls_htmx.html' with table_modal="ObjectTable_config" %}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
{% load helpers %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{# Applied filters #}
|
||||
{% include 'inc/applied_filters_pane.html' %}
|
||||
|
||||
{% with preferences|get_key:"pagination.placement" as paginator_placement %}
|
||||
{% if paginator_placement == 'top' or paginator_placement == 'both' %}
|
||||
{% include 'inc/paginator.html' with htmx=True table=table paginator=table.paginator page=table.page %}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{% load helpers %}
|
||||
|
||||
<div id="applied_filters_pane" hx-swap-oob="true">
|
||||
{# Applied filters #}
|
||||
{% if filter_form %}
|
||||
{% applied_filters model filter_form request.GET %}
|
||||
{% endif %}
|
||||
</div>
|
|
@ -5,7 +5,7 @@
|
|||
<div class="col-auto d-print-none">
|
||||
<div class="input-group input-group-flat me-2 quicksearch" hx-disinherit="hx-select hx-swap">
|
||||
<input type="search" results="5" name="q" id="quicksearch" class="form-control px-2 py-1" placeholder="Quick search"
|
||||
hx-get="{{ request.full_path }}" hx-target="#object_list" hx-trigger="keyup changed delay:500ms, search" />
|
||||
hx-get="" hx-target="#object_list" hx-trigger="keyup changed delay:500ms, search" />
|
||||
<span class="input-group-text py-1">
|
||||
<a href="#" id="quicksearch_clear" class="d-none text-secondary"><i class="mdi mdi-close-circle"></i></a>
|
||||
</span>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{% load form_helpers %}
|
||||
{% if form_field %}
|
||||
<div class="column-filter dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown" data-bs-auto-close="outside"><i class="mdi mdi-filter-settings"></i></a>
|
||||
<div class="dropdown-menu">
|
||||
<div class="px-3 py-3">
|
||||
{% render_table_filter_field form_field table=table request=request %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
|
@ -1,4 +1,5 @@
|
|||
{% load django_tables2 %}
|
||||
{% load form_helpers %}
|
||||
<table{% if table.attrs %} {{ table.attrs.as_html }}{% endif %} hx-disinherit="hx-target hx-select hx-swap">
|
||||
{% if table.show_header %}
|
||||
<thead
|
||||
|
@ -14,11 +15,16 @@
|
|||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring table.prefixed_order_by_field='' %}"
|
||||
class="text-danger"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
><i class="mdi mdi-close"></i></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if table.filterset_form %}
|
||||
{% include 'inc/table_header_filter_dropdown.html' with form_field=table.filterset_form|get_filter_field:column.name %}
|
||||
{% endif %}
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}"
|
||||
hx-get="{{ table.htmx_url }}{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
>{{ column.header }}</a>
|
||||
</th>
|
||||
{% else %}
|
||||
|
|
|
@ -6,6 +6,7 @@ from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, T
|
|||
|
||||
__all__ = (
|
||||
'getfield',
|
||||
'get_filter_field',
|
||||
'render_custom_fields',
|
||||
'render_errors',
|
||||
'render_field',
|
||||
|
@ -13,6 +14,7 @@ __all__ = (
|
|||
'widget_type',
|
||||
)
|
||||
|
||||
from utilities.templatetags.helpers import querystring
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
@ -32,6 +34,11 @@ def getfield(form, fieldname):
|
|||
return None
|
||||
|
||||
|
||||
@register.filter()
|
||||
def get_filter_field(form, fieldname):
|
||||
return getfield(form, f'{fieldname}') or getfield(form, f'{fieldname}_id')
|
||||
|
||||
|
||||
@register.filter(name='widget_type')
|
||||
def widget_type(field):
|
||||
"""
|
||||
|
@ -120,6 +127,7 @@ def render_field(field, bulk_nullable=False, label=None):
|
|||
"""
|
||||
Render a single form field from template
|
||||
"""
|
||||
|
||||
return {
|
||||
'field': field,
|
||||
'label': label or field.label,
|
||||
|
@ -127,6 +135,39 @@ def render_field(field, bulk_nullable=False, label=None):
|
|||
}
|
||||
|
||||
|
||||
@register.inclusion_tag('form_helpers/render_field.html')
|
||||
def render_table_filter_field(field, table, request):
|
||||
"""
|
||||
Render a single form field for table column filters from template
|
||||
"""
|
||||
url = ""
|
||||
|
||||
# Handle filter forms
|
||||
if table:
|
||||
# Build kwargs for querystring function
|
||||
kwargs = {field.name: None}
|
||||
# Build request url
|
||||
if request and table.htmx_url:
|
||||
url = table.htmx_url + querystring(request, **kwargs)
|
||||
elif request:
|
||||
url = querystring(request, **kwargs)
|
||||
|
||||
# Set HTMX args
|
||||
if hasattr(field.field, 'widget'):
|
||||
field.field.widget.attrs.update({
|
||||
'id': f'table_filter_id_{field.name}',
|
||||
'hx-get': url if url else '#',
|
||||
'hx-push-url': "true",
|
||||
'hx-trigger': 'hidden.bs.dropdown from:closest .dropdown'
|
||||
})
|
||||
|
||||
return {
|
||||
'field': field,
|
||||
'label': None,
|
||||
'bulk_nullable': False,
|
||||
}
|
||||
|
||||
|
||||
@register.inclusion_tag('form_helpers/render_custom_fields.html')
|
||||
def render_custom_fields(form):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue