1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

: Enable dynamic tables for object list views

This commit is contained in:
jeremystretch
2021-12-13 16:51:59 -05:00
parent c50dc1eb35
commit 91f33d3289
7 changed files with 107 additions and 4 deletions

@ -23,6 +23,7 @@ from utilities.exceptions import AbortTransaction, PermissionsViolation
from utilities.forms import (
BootstrapMixin, BulkRenameForm, ConfirmationForm, CSVDataField, CSVFileField, ImportForm, restrict_form_fields,
)
from utilities.htmx import is_htmx
from utilities.permissions import get_permission_for_model
from utilities.tables import paginate_table
from utilities.utils import normalize_querydict, prepare_cloned_fields
@ -185,6 +186,12 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
table = self.get_table(request, permissions)
paginate_table(table, request)
# If this is an HTMX request, return only the rendered table HTML
if is_htmx(request):
return render(request, 'htmx/table.html', {
'table': table,
})
context = {
'content_type': content_type,
'table': table,

@ -160,6 +160,9 @@
})();
</script>
{# TODO: Package HTMX JS locally #}
<script src="https://unpkg.com/htmx.org@1.6.1"></script>
{# Page layout #}
{% block layout %}{% endblock %}

@ -95,10 +95,11 @@
{# Object table #}
<div class="card">
<div class="card-body">
<div class="card-body" id="object_list">
<div class="table-responsive">
{% render_table table 'inc/table.html' %}
{% render_table table 'inc/table_htmx.html' %}
</div>
{% include 'inc/paginator_htmx.html' with paginator=table.paginator page=table.page %}
</div>
</div>
@ -125,8 +126,6 @@
</form>
{# Paginator #}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
</div>
{# Filter form #}

@ -0,0 +1,5 @@
{# Render an HTML table element #}
{% load render_table from django_tables2 %}
{% render_table table 'inc/table_htmx.html' %}
{% include 'inc/paginator_htmx.html' with paginator=table.paginator page=table.page %}

@ -0,0 +1,43 @@
{% load helpers %}
<div class="row">
<div class="col col-md-6 mb-0">
{% if paginator.num_pages > 1 %}
<div class="btn-group btn-group-sm" role="group" aria-label="Pages">
{% if page.has_previous %}
<a href="#" hx-get="{% querystring request page=page.previous_page_number %}" hx-target="#object_list" class="btn btn-outline-secondary">
<i class="mdi mdi-chevron-double-left"></i>
</a>
{% endif %}
{% for p in page.smart_pages %}
{% if p %}
<a href="#" hx-get="{% querystring request page=p %}" hx-target="#object_list" class="btn btn-outline-secondary{% if page.number == p %} active{% endif %}">
{{ p }}
</a>
{% else %}
<button type="button" class="btn btn-outline-secondary" disabled>
<span>&hellip;</span>
</button>
{% endif %}
{% endfor %}
{% if page.has_next %}
<a href="#" hx-get="{% querystring request page=page.next_page_number %}" hx-target="#object_list" class="btn btn-outline-secondary">
<i class="mdi mdi-chevron-double-right"></i>
</a>
{% endif %}
</div>
{% endif %}
</div>
<div class="col col-md-6 mb-0 text-end">
<div class="dropdown dropup">
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
Per Page
</button>
<ul class="dropdown-menu">
{% for n in page.paginator.get_page_lengths %}
<li><a class="dropdown-item" href="#" hx-get="{% querystring request per_page=n %}" hx-target="#object_list">{{ n }}</a></li>
{% endfor %}
</ul>
</div>
</div>
</div>

@ -0,0 +1,41 @@
{% load django_tables2 %}
<table{% if table.attrs %} {{ table.attrs.as_html }}{% endif %}>
{% if table.show_header %}
<thead>
<tr>
{% for column in table.columns %}
{% if column.orderable %}
<th {{ column.attrs.th.as_html }}><a href="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}" hx-get="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}" hx-target="#object_list">{{ column.header }}</a></th>
{% else %}
<th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
{% endif %}
{% endfor %}
</tr>
</thead>
{% endif %}
<tbody>
{% for row in table.page.object_list|default:table.rows %}
<tr {{ row.attrs.as_html }}>
{% for column, cell in row.items %}
<td {{ column.attrs.td.as_html }}>{{ cell }}</td>
{% endfor %}
</tr>
{% empty %}
{% if table.empty_text %}
<tr>
<td colspan="{{ table.columns|length }}" class="text-center text-muted">&mdash; {{ table.empty_text }} &mdash;</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
{% if table.has_footer %}
<tfoot>
<tr>
{% for column in table.columns %}
<td>{{ column.footer }}</td>
{% endfor %}
</tr>
</tfoot>
{% endif %}
</table>

5
netbox/utilities/htmx.py Normal file

@ -0,0 +1,5 @@
def is_htmx(request):
"""
Returns True if the request was made by HTMX; False otherwise.
"""
return 'Hx-Request' in request.headers