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

Enable tabbed group fields in fieldsets

This commit is contained in:
Jeremy Stretch
2024-03-12 17:02:26 -04:00
parent f585c36d86
commit 4c7b6fcec0
6 changed files with 92 additions and 121 deletions

View File

@@ -1,10 +1,43 @@
import random
import string
from functools import cached_property
__all__ = (
'FieldGroup',
'InlineFields',
'TabbedFieldGroups',
)
class InlineFields:
class FieldGroup:
def __init__(self, *field_names, label=None):
def __init__(self, label, *field_names):
self.field_names = field_names
self.label = label
class InlineFields(FieldGroup):
pass
class TabbedFieldGroups:
def __init__(self, *groups):
self.groups = [
FieldGroup(*group) for group in groups
]
# Initialize a random ID for the group (for tab selection)
self.id = ''.join(
random.choice(string.ascii_lowercase + string.digits) for _ in range(8)
)
@cached_property
def tabs(self):
return [
{
'id': f'{self.id}_{i}',
'title': group.label,
'fields': group.field_names,
} for i, group in enumerate(self.groups, start=1)
]

View File

@@ -7,9 +7,11 @@
</div>
{% endif %}
{% for layout, title, items in rows %}
{% if layout == 'field' %}
{# Single form field #}
{% render_field items.0 %}
{% elif layout == 'inline' %}
{# Multiple form fields on the same line #}
<div class="row mb-3">
@@ -21,6 +23,30 @@
</div>
{% endfor %}
</div>
{% elif layout == 'tabs' %}
{# Tabbed groups of fields #}
<div class="row offset-sm-3">
<ul class="nav nav-pills mb-1" role="tablist">
{% for tab in items %}
<li role="presentation" class="nav-item">
<button role="tab" type="button" id="{{ tab.id }}_tab" data-bs-toggle="tab" aria-controls="{{ tab.id }}" data-bs-target="#{{ tab.id }}" class="nav-link {% if tab.active %}active{% endif %}">
{% trans tab.title %}
</button>
</li>
{% endfor %}
</ul>
</div>
<div class="tab-content p-0 border-0">
{% for tab in items %}
<div class="tab-pane {% if tab.active %}active{% endif %}" id="{{ tab.id }}" role="tabpanel" aria-labeled-by="{{ tab.id }}_tab">
{% for field in tab.fields %}
{% render_field field %}
{% endfor %}
</div>
{% endfor %}
</div>
{% endif %}
{% endfor %}
</div>

View File

@@ -1,6 +1,6 @@
from django import template
from utilities.forms.rendering import InlineFields
from utilities.forms.rendering import InlineFields, TabbedFieldGroups
__all__ = (
'getfield',
@@ -58,6 +58,21 @@ def render_fieldset(form, fieldset, heading=None):
rows.append(
('inline', item.label, [form[name] for name in item.field_names])
)
elif type(item) is TabbedFieldGroups:
tabs = [
{
'id': tab['id'],
'title': tab['title'],
'active': bool(form.initial.get(tab['fields'][0], False)),
'fields': [form[name] for name in tab['fields']]
} for tab in item.tabs
]
# If none of the tabs has been marked as active, activate the first one
if not any(tab['active'] for tab in tabs):
tabs[0]['active'] = True
rows.append(
('tabs', None, tabs)
)
else:
rows.append(
('field', None, [form[item]])