فهرست منبع

Improve object list layout (#6907)

* Split object list and filters into tabs

* Use object_list template for connections, rack elevations

* Include custom field filters in grouped filter form

* Annotate number of applied filters on tab

* Rearrange table controls
Jeremy Stretch 4 سال پیش
والد
کامیت
939bcfec4b

+ 3 - 0
netbox/dcim/views.py

@@ -2541,6 +2541,7 @@ class ConsoleConnectionsListView(generic.ObjectListView):
     filterset_form = forms.ConsoleConnectionFilterForm
     filterset_form = forms.ConsoleConnectionFilterForm
     table = tables.ConsoleConnectionTable
     table = tables.ConsoleConnectionTable
     template_name = 'dcim/connections_list.html'
     template_name = 'dcim/connections_list.html'
+    action_buttons = ('export',)
 
 
     def extra_context(self):
     def extra_context(self):
         return {
         return {
@@ -2554,6 +2555,7 @@ class PowerConnectionsListView(generic.ObjectListView):
     filterset_form = forms.PowerConnectionFilterForm
     filterset_form = forms.PowerConnectionFilterForm
     table = tables.PowerConnectionTable
     table = tables.PowerConnectionTable
     template_name = 'dcim/connections_list.html'
     template_name = 'dcim/connections_list.html'
+    action_buttons = ('export',)
 
 
     def extra_context(self):
     def extra_context(self):
         return {
         return {
@@ -2567,6 +2569,7 @@ class InterfaceConnectionsListView(generic.ObjectListView):
     filterset_form = forms.InterfaceConnectionFilterForm
     filterset_form = forms.InterfaceConnectionFilterForm
     table = tables.InterfaceConnectionTable
     table = tables.InterfaceConnectionTable
     template_name = 'dcim/connections_list.html'
     template_name = 'dcim/connections_list.html'
+    action_buttons = ('export',)
 
 
     def extra_context(self):
     def extra_context(self):
         return {
         return {

+ 2 - 0
netbox/extras/forms.py

@@ -519,12 +519,14 @@ class CustomFieldModelFilterForm(forms.Form):
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)
 
 
         # Add all applicable CustomFields to the form
         # Add all applicable CustomFields to the form
+        self.custom_field_filters = []
         custom_fields = CustomField.objects.filter(content_types=self.obj_type).exclude(
         custom_fields = CustomField.objects.filter(content_types=self.obj_type).exclude(
             filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED
             filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED
         )
         )
         for cf in custom_fields:
         for cf in custom_fields:
             field_name = 'cf_{}'.format(cf.name)
             field_name = 'cf_{}'.format(cf.name)
             self.fields[field_name] = cf.to_form_field(set_initial=True, enforce_required=False)
             self.fields[field_name] = cf.to_form_field(set_initial=True, enforce_required=False)
+            self.custom_field_filters.append(field_name)
 
 
 
 
 #
 #

+ 25 - 15
netbox/templates/dcim/connections_list.html

@@ -1,24 +1,34 @@
-{% extends 'base/layout.html' %}
+{% extends 'generic/object_list.html' %}
 {% load buttons %}
 {% load buttons %}
+{% load helpers %}
 {% load render_table from django_tables2 %}
 {% load render_table from django_tables2 %}
 
 
 {% block title %}{{ title }}{% endblock %}
 {% block title %}{{ title }}{% endblock %}
 
 
-{% block extra_controls %}{% export_button content_type %}{% endblock %}
+{% block content-wrapper %}
+  <div class="tab-content">
 
 
-{% block content %}
-    <div class="row mb-3">
-        <div class="col col-md-7 col-lg-8 col-xl-9 col-xxl-10">
-            {% include 'inc/table_controls.html' %}
+    {# Conncetions list #}
+    <div class="tab-pane show active" id="object-list" role="tabpanel" aria-labelledby="object-list-tab">
+      {% include 'inc/table_controls.html' %}
 
 
-            <div class="table-responsive">
-                {% render_table table 'inc/table.html' %}
-            </div>
-
-            {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
+      <div class="card">
+        <div class="card-body">
+          <div class="table-responsive">
+            {% render_table table 'inc/table.html' %}
+          </div>
         </div>
         </div>
-        {% if filter_form %}
-            {% include 'inc/filter_list.html' %}
-        {% endif %}
+      </div>
+
+      {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
     </div>
     </div>
-{% endblock %}
+
+    {# Filter form #}
+    {% if filter_form %}
+      <div class="tab-pane show" id="filters-form" role="tabpanel" aria-labelledby="filters-form-tab">
+        {% include 'inc/filter_list.html' %}
+      </div>
+    {% endif %}
+
+  </div>
+{% endblock content-wrapper %}

+ 47 - 38
netbox/templates/dcim/rack_elevation_list.html

@@ -1,4 +1,4 @@
-{% extends 'base/layout.html' %}
+{% extends 'generic/object_list.html' %}
 {% load helpers %}
 {% load helpers %}
 {% load static %}
 {% load static %}
 
 
@@ -22,41 +22,50 @@
     </div>
     </div>
 {% endblock %}
 {% endblock %}
 
 
-{% block content %}
-    <div class="row">
-        <div class="col col-md-7 col-lg-8 col-xl-9 col-xxl-10">
-            {% if page %}
-                <div style="white-space: nowrap; overflow-x: scroll;">
-                    {% for rack in page %}
-                        <div style="display: inline-block; margin-right: 12px; width: 254px">
-                        <div style="margin-left: 30px">
-                            <div class="text-center">
-                                <strong><a href="{% url 'dcim:rack' pk=rack.pk %}">{{ rack.name }}</a></strong>
-                                {% if rack.role %}
-                                    <br /><span class="badge my-3" style="color: {{ rack.role.color|fgcolor }}; background-color: #{{ rack.role.color }}">{{ rack.role }}</span>
-                                {% endif %}
-                                {% if rack.facility_id %}
-                                    <br /><small class="text-muted">{{ rack.facility_id }}</small>
-                                {% endif %}
-                            </div>
-                            {% include 'dcim/inc/rack_elevation.html' with object=rack face=rack_face %}
-                            <div class="clearfix"></div>
-                            <div class="text-center">
-                                <strong><a href="{% url 'dcim:rack' pk=rack.pk %}">{{ rack.name }}</a></strong>
-                                {% if rack.facility_id %}
-                                    <small class="text-muted">({{ rack.facility_id }})</small>
-                                {% endif %}
-                            </div>
-                        </div>
-                        </div>
-                    {% endfor %}
-                </div>
-                <br />
-                {% include 'inc/paginator.html' %}
-            {% else %}
-                <p>No Racks Found</p>
-            {% endif %}
-        </div>
-        {% include 'inc/filter_list.html' %}
+{% block content-wrapper %}
+  <div class="tab-content">
+
+    {# Rack elevations #}
+    <div class="tab-pane show active" id="object-list" role="tabpanel" aria-labelledby="object-list-tab">
+      {% if page %}
+          <div style="white-space: nowrap; overflow-x: scroll;">
+              {% for rack in page %}
+                  <div style="display: inline-block; margin-right: 12px; width: 254px">
+                  <div style="margin-left: 30px">
+                      <div class="text-center">
+                          <strong><a href="{% url 'dcim:rack' pk=rack.pk %}">{{ rack.name }}</a></strong>
+                          {% if rack.role %}
+                              <br /><span class="badge my-3" style="color: {{ rack.role.color|fgcolor }}; background-color: #{{ rack.role.color }}">{{ rack.role }}</span>
+                          {% endif %}
+                          {% if rack.facility_id %}
+                              <br /><small class="text-muted">{{ rack.facility_id }}</small>
+                          {% endif %}
+                      </div>
+                      {% include 'dcim/inc/rack_elevation.html' with object=rack face=rack_face %}
+                      <div class="clearfix"></div>
+                      <div class="text-center">
+                          <strong><a href="{% url 'dcim:rack' pk=rack.pk %}">{{ rack.name }}</a></strong>
+                          {% if rack.facility_id %}
+                              <small class="text-muted">({{ rack.facility_id }})</small>
+                          {% endif %}
+                      </div>
+                  </div>
+                  </div>
+              {% endfor %}
+          </div>
+          <br />
+          {% include 'inc/paginator.html' %}
+      {% else %}
+          <p>No Racks Found</p>
+      {% endif %}
     </div>
     </div>
-{% endblock %}
+
+    {# Filter form #}
+    {% if filter_form %}
+      <div class="tab-pane show" id="filters-form" role="tabpanel" aria-labelledby="filters-form-tab">
+        {% include 'inc/filter_list.html' %}
+      </div>
+    {% endif %}
+
+  </div>
+{% endblock content-wrapper %}

+ 118 - 83
netbox/templates/generic/object_list.html

@@ -4,97 +4,132 @@
 {% load render_table from django_tables2 %}
 {% load render_table from django_tables2 %}
 {% load static %}
 {% load static %}
 
 
-{% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bettertitle }}{% endblock %}
-
 {% block controls %}
 {% block controls %}
-<div class="controls">
-  <div class="control-group">
-    {% block extra_controls %}{% endblock %}
-    {% if permissions.add and 'add' in action_buttons %}
-        {% add_button content_type.model_class|validated_viewname:"add" %}
-    {% endif %}
-    {% if permissions.add and 'import' in action_buttons %}
-        {% import_button content_type.model_class|validated_viewname:"import" %}
-    {% endif %}
-    {% if 'export' in action_buttons %}
-        {% export_button content_type %}
-    {% endif %}
+  <div class="controls">
+    <div class="control-group">
+      {% block extra_controls %}{% endblock %}
+      {% if permissions.add and 'add' in action_buttons %}
+          {% add_button content_type.model_class|validated_viewname:"add" %}
+      {% endif %}
+      {% if permissions.add and 'import' in action_buttons %}
+          {% import_button content_type.model_class|validated_viewname:"import" %}
+      {% endif %}
+      {% if 'export' in action_buttons %}
+          {% export_button content_type %}
+      {% endif %}
+    </div>
   </div>
   </div>
-</div>
 {% endblock controls %}
 {% endblock controls %}
 
 
-{% block content %}
-{% 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" %}
-  <div id="select-all-box" class="d-none card noprint">
-    <form method="post" class="form col-md-12">
-      {% csrf_token %}
-      <div class="card-body">
-        <div class="float-end">
-          {% if bulk_edit_url and permissions.change %}
-            <button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm" disabled>
-              <span class="mdi mdi-pencil" aria-hidden="true"></span> Edit All
-            </button>
-          {% endif %}
-          {% if bulk_delete_url and permissions.delete %}
-            <button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm" disabled>
-              <span class="mdi mdi-trash-can-outline" aria-hidden="true"></span> Delete All
-            </button>
-          {% endif %}
-        </div>
-        <div class="form-check">
-          <input type="checkbox" id="select-all" name="_all" class="form-check-input" />
-          <label for="select-all" class="form-check-label">
-            Select <strong>all {{ table.rows|length }} {{ table.data.verbose_name_plural }}</strong> matching query
-          </label>
-        </div>
-      </div>
-    </form>
-  </div>
-{% endwith %}
-{% endif %}
+{% block tabs %}
+  <ul class="nav nav-tabs px-3">
+    {% block tab_items %}
+      <li class="nav-item" role="presentation">
+        <button class="nav-link active" id="object-list-tab" data-bs-toggle="tab" data-bs-target="#object-list" type="button" role="tab" aria-controls="edit-form" aria-selected="true">
+          {% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bettertitle }}{% endblock %}
+          {% badge table.page.paginator.count %}
+        </button>
+      </li>
+      {% if filter_form %}
+        <li class="nav-item" role="presentation">
+          <button class="nav-link" id="filters-form-tab" data-bs-toggle="tab" data-bs-target="#filters-form" type="button" role="tab" aria-controls="object-list" aria-selected="false">
+            Filters
+            {% if filter_form %}{% badge filter_form.changed_data|length %}{% endif %}
+          </button>
+        </li>
+      {% endif %}
+    {% endblock tab_items %}
+  </ul>
+{% endblock tabs %}
+
+{% block content-wrapper %}
+  <div class="tab-content">
 
 
-{# Object table #}
-<div class="row">
-  <div class="col {% if filter_form %}col-md-7 col-lg-8 col-xl-9 col-xxl-10{% else %}col-12{% endif %}">
-    {# Object list filter, table config #}
-    {% include 'inc/table_controls.html' with table_modal="ObjectTable_config" %}
+    {# Object list #}
+    <div class="tab-pane show active" id="object-list" role="tabpanel" aria-labelledby="object-list-tab">
+      {% 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" %}
-      {% if permissions.change or permissions.delete %}
-        <form method="post" class="form form-horizontal">
-          {% csrf_token %}
-          <input type="hidden" name="return_url" value="{% if return_url %}{{ return_url }}{% else %}{{ request.path }}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}{% endif %}" />
-          <div class="table-responsive">
-            {% render_table table 'inc/table.html' %}
+        {# "Select all" form #}
+        {% 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">
+            <form method="post" class="form col-md-12">
+              {% csrf_token %}
+              <div class="card-body">
+                <div class="float-end">
+                  {% if bulk_edit_url and permissions.change %}
+                    <button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm" disabled>
+                      <span class="mdi mdi-pencil" aria-hidden="true"></span> Edit All
+                    </button>
+                  {% endif %}
+                  {% if bulk_delete_url and permissions.delete %}
+                    <button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm" disabled>
+                      <span class="mdi mdi-trash-can-outline" aria-hidden="true"></span> Delete All
+                    </button>
+                  {% endif %}
+                </div>
+                <div class="form-check">
+                  <input type="checkbox" id="select-all" name="_all" class="form-check-input" />
+                  <label for="select-all" class="form-check-label">
+                    Select <strong>all {{ table.rows|length }} {{ table.data.verbose_name_plural }}</strong> matching query
+                  </label>
+                </div>
+              </div>
+            </form>
           </div>
           </div>
-          <div class="noprint bulk-buttons">
-            <div class="bulk-button-group">
-              {% block bulk_buttons %}{% endblock %}
-              {% if bulk_edit_url and permissions.change %}
-                <button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm">
-                  <i class="mdi mdi-pencil" aria-hidden="true"></i> Edit Selected
-                </button>
-              {% endif %}
-              {% if bulk_delete_url and permissions.delete %}
-                <button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm">
-                  <i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete Selected
-                </button>
-              {% endif %}
+        {% endwith %}
+      {% endif %}
+
+      {# Object table controls #}
+      {% include 'inc/table_controls.html' with table_modal="ObjectTable_config" %}
+
+      <form method="post" class="form form-horizontal">
+        {% csrf_token %}
+        <input type="hidden" name="return_url" value="{% if return_url %}{{ return_url }}{% else %}{{ request.path }}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}{% endif %}" />
+
+        {# Object table #}
+        <div class="card">
+          <div class="card-body">
+            <div class="table-responsive">
+              {% render_table table 'inc/table.html' %}
             </div>
             </div>
           </div>
           </div>
-        </form>
-      {% else %}
-        <div class="table-responsive">
-          {% render_table table 'inc/table.html' %}
         </div>
         </div>
-      {% endif %}
-    {% endwith %}
-    {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
+
+        {# Form buttons #}
+        {% if permissions.change or permissions.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 class="noprint bulk-buttons">
+              <div class="bulk-button-group">
+                {% block bulk_buttons %}{% endblock %}
+                {% if bulk_edit_url and permissions.change %}
+                  <button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm">
+                    <i class="mdi mdi-pencil" aria-hidden="true"></i> Edit Selected
+                  </button>
+                {% endif %}
+                {% if bulk_delete_url and permissions.delete %}
+                  <button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm">
+                    <i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete Selected
+                  </button>
+                {% endif %}
+              </div>
+            </div>
+          {% endwith %}
+        {% endif %}
+
+      </form>
+
+      {# Paginator #}
+      {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
+    </div>
+
+    {# Filter form #}
+    {% if filter_form %}
+      <div class="tab-pane show" id="filters-form" role="tabpanel" aria-labelledby="filters-form-tab">
+        {% include 'inc/filter_list.html' %}
+      </div>
+    {% endif %}
   </div>
   </div>
-  {% if filter_form %}
-    {% include 'inc/filter_list.html' %}
-  {% endif %}
-</div>
-{% table_config_form table table_name="ObjectTable" %}
-{% endblock content %}
+
+  {# Table config form #}
+  {% table_config_form table table_name="ObjectTable" %}
+{% endblock content-wrapper %}

+ 42 - 62
netbox/templates/inc/filter_list.html

@@ -1,65 +1,45 @@
 {% load form_helpers %}
 {% load form_helpers %}
 {% load helpers %}
 {% load helpers %}
 
 
-<div class="col col-md-5 col-lg-4 col-xl-3 col-xxl-2 noprint">
-    <form action="." method="get">
-        <div class="card small">
-            <h5 class="card-header">
-                Field Filters
-            </h5>
-            <div class="card-body overflow-visible d-flex flex-wrap justify-content-between py-3">
-                    {% for field in filter_form.hidden_fields %}
-                        {{ field }}
-                    {% endfor %}
-                    {% if filter_form.field_groups %}
-                        {% for group in filter_form.field_groups %}
-                            <div class="col col-12">
-                                {% for name in group %}
-                                    {% with field=filter_form|get_item:name %}
-                                        {% if field|widget_type == 'checkboxinput' %}
-                                            <div class="form-check mb-3">
-                                                <label class="form-check-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
-                                                {{ field }}
-                                            </div>
-                                        {% else %}
-                                            <div class="mb-3 px-2">
-                                                <label class="form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
-                                                {{ field }}
-                                            </div>
-                                        {% endif %}
-                                    {% endwith %}
-                                {% endfor %}
-                            </div>
-                            {% if forloop.counter != filter_form.field_groups|length %}
-                                <hr class="card-divider mt-0" />
-                            {% endif %}
-                        {% endfor %}
-                    {% else %}
-                        {% for field in filter_form.visible_fields %}
-                            <div class="col col-12">
-                                {% if field|widget_type == 'checkboxinput' %}
-                                    <div class="form-check mb-3">
-                                        <label class="form-check-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
-                                        {{ field }}
-                                    </div>
-                                {% else %}
-                                    <div class="mb-3 px-2">
-                                    <label class="form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
-                                    {{ field }}
-                                    </div>
-                                {% endif %}
-                            </div>
-                        {% endfor %}
-                    {% endif %}
-            </div>
-            <div class="card-footer text-end noprint border-0">
-                <button type="button" class="btn btn-sm btn-outline-danger m-1" data-reset-select>
-                    <i class="mdi mdi-backspace"></i> Reset
-                </button>
-                <button type="submit" class="btn btn-sm btn-primary m-1">
-                    <i class="mdi mdi-filter-variant"></i> Filter
-                </button>
-            </div>
-        </div>
-    </form>
-</div>
+<form action="." method="get">
+  <div class="card">
+    <div class="card-body overflow-visible d-flex flex-wrap justify-content-between py-3">
+          {% for field in filter_form.hidden_fields %}
+              {{ field }}
+          {% endfor %}
+          {% if filter_form.field_groups %}
+              {% for group in filter_form.field_groups %}
+                  <div class="col col-12">
+                      {% for name in group %}
+                          {% with field=filter_form|get_item:name %}
+                              {% render_field field %}
+                          {% endwith %}
+                      {% endfor %}
+                  </div>
+                  <hr class="card-divider mt-0" />
+              {% endfor %}
+              {% for name in filter_form.custom_field_filters %}
+                <div class="col col-12">
+                  {% with field=filter_form|get_item:name %}
+                    {% render_field field %}
+                  {% endwith %}
+                </div>
+              {% endfor %}
+          {% else %}
+              {% for field in filter_form.visible_fields %}
+                  <div class="col col-12">
+                      {% render_field field %}
+                  </div>
+              {% endfor %}
+          {% endif %}
+    </div>
+    <div class="card-footer text-end noprint border-0">
+        <button type="button" class="btn btn-sm btn-outline-danger m-1" data-reset-select>
+            <i class="mdi mdi-backspace"></i> Reset
+        </button>
+        <button type="submit" class="btn btn-sm btn-primary m-1">
+            <i class="mdi mdi-filter-variant"></i> Filter
+        </button>
+    </div>
+  </div>
+</form>

+ 13 - 15
netbox/templates/inc/table_controls.html

@@ -1,19 +1,4 @@
 <div class="row mb-3 justify-content-between">
 <div class="row mb-3 justify-content-between">
-    <div class="col col-md-2 mb-0 d-flex noprint table-controls">
-        {% if request.user.is_authenticated and table_modal %}
-            <div class="input-group input-group-sm">
-                <button
-                    type="button"
-                    data-bs-toggle="modal"
-                    title="Configure Table"
-                    data-bs-target="#{{ table_modal }}"
-                    class="btn btn-sm btn-outline-dark"
-                >
-                    <i class="mdi mdi-cog"></i> Configure Table
-                </button>
-            </div>
-        {% endif %}
-    </div>
     <div class="col col-12 col-lg-4 my-3 my-lg-0 d-flex noprint table-controls">
     <div class="col col-12 col-lg-4 my-3 my-lg-0 d-flex noprint table-controls">
         <div class="input-group input-group-sm">
         <div class="input-group input-group-sm">
             <input
             <input
@@ -24,4 +9,17 @@
             />
             />
         </div>
         </div>
     </div>
     </div>
+    <div class="col col-md-2 mb-0 d-flex justify-content-end noprint table-controls">
+        {% if request.user.is_authenticated and table_modal %}
+            <button
+                type="button"
+                data-bs-toggle="modal"
+                title="Configure Table"
+                data-bs-target="#{{ table_modal }}"
+                class="btn btn-sm btn-outline-dark"
+            >
+                <i class="mdi mdi-cog"></i> Configure Table
+            </button>
+        {% endif %}
+    </div>
 </div>
 </div>