Skip to content

Commit

Permalink
feat: fieldset as tabs (#249)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasvinclav authored Jan 14, 2024
1 parent 06efaa5 commit b412b20
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 6 deletions.
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ Did you decide to start using Unfold but you don't have time to make the switch
- **WYSIWYG:** built-in support for WYSIWYG (Trix)
- **Custom filters:** widgets for filtering number & datetime values
- **Dashboard:** custom components for rapid dashboard development
- **Tabs:** define custom tab navigations for models
- **Model tabs:** define custom tab navigations for models
- **Fieldset tabs:** merge several fielsets into tabs in change form
- **Colors:** possibility to override default color scheme
- **Third party packages:** default support for multiple popular applications
- **Environment label**: distinguish between environments by displaying a label
Expand All @@ -50,6 +51,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
- [Numeric filters](#numeric-filters)
- [Date/time filters](#datetime-filters)
- [Display decorator](#display-decorator)
- [Change form tabs](#change-form-tabs)
- [Third party packages](#third-party-packages)
- [django-celery-beat](#django-celery-beat)
- [django-guardian](#django-guardian)
Expand Down Expand Up @@ -582,6 +584,55 @@ class UserAdmin(ModelAdmin):
return "First main heading", "Smaller additional description", "AB"
```

## Change form tabs

When the change form contains a lot of fieldsets, sometimes it is better to group them into tabs so it will not be needed to scroll. To mark a fieldset for tab navigation it is required to add a `tab` CSS class to the fieldset. Once the fieldset contains `tab` class it will be recognized in a template and grouped into tab navigation. Each tab must contain its name. If the name is not available, it will be not included in the tab navigation.

```python
# admin.py

from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from unfold.admin import ModelAdmin

from .models import MyModel


@admin.register(MyModel)
class MyModelAdmin(ModelAdmin):
fieldsets = (
(
None,
{
"fields": [
"field_1",
"field_2",
],
},
),
(
_("Tab 1"),
{
"classes": ["tab"],
"fields": [
"field_3",
"field_4",
],
},
),
(
_("Tab 2"),
{
"classes": ["tab"],
"fields": [
"field_5",
"field_6",
],
},
),
)
```

## Third party packages

### django-celery-beat
Expand Down
6 changes: 5 additions & 1 deletion src/unfold/templates/admin/change_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,12 @@

{% block field_sets %}
{% for fieldset in adminform %}
{% include 'admin/includes/fieldset.html' %}
{% if "tab" not in fieldset.classes %}
{% include 'admin/includes/fieldset.html' %}
{% endif %}
{% endfor %}

{% include "unfold/helpers/fieldsets_tabs.html" %}
{% endblock %}

{% block after_field_sets %}{% endblock %}
Expand Down
6 changes: 3 additions & 3 deletions src/unfold/templates/admin/includes/fieldset.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{% load unfold %}

<fieldset class="module {{ fieldset.classes }}">
{% if fieldset.name %}
<h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-md text-gray-900 text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-gray-200">
<fieldset class="module{% if fieldset.classes %} {{ fieldset.classes }}{% endif %}">
{% if fieldset.name and "tab" not in fieldset.classes %}
<h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-md text-gray-700 text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-gray-200">
{{ fieldset.name }}
</h2>
{% endif %}
Expand Down
26 changes: 26 additions & 0 deletions src/unfold/templates/unfold/helpers/fieldsets_tabs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{% load unfold %}

{% with tabs=adminform|tabs %}
{% if tabs %}
<div x-data="{openTab: null}">
<ul class="bg-gray-100 border border-transparent flex gap-10 mb-6 px-4 py-3 rounded-md text-gray-400 text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-gray-400">
{% for fieldset in tabs %}
<li>
<a class="cursor-pointer font-semibold hover:text-gray-700 dark:hover:text-white"
x-on:click="openTab = '{{ fieldset.name|slugify }}'"
x-bind:class="openTab == '{{ fieldset.name|slugify }}'{% if forloop.first %} || openTab == null{% endif %} ? 'text-gray-700 dark:text-white' : ''">
{{ fieldset.name }}
</a>
</li>
{% endfor %}
</ul>

{% for fieldset in tabs %}
<div class="tab-wrapper{% if fieldset.name %} fieldset-{{ fieldset.name|slugify }}{% endif %}"
x-show="openTab == '{{ fieldset.name|slugify }}'{% if forloop.first %} || openTab == null{% endif %}">
{% include 'admin/includes/fieldset.html' %}
</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
14 changes: 13 additions & 1 deletion src/unfold/templatetags/unfold.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Any, Dict, Mapping, Optional, Union
from typing import Any, Dict, List, Mapping, Optional, Union

from django import template
from django.contrib.admin.helpers import AdminForm, Fieldset
from django.forms import Field
from django.template import Library, Node, RequestContext, TemplateSyntaxError
from django.template.base import NodeList, Parser, Token, token_kwargs
Expand Down Expand Up @@ -42,6 +43,17 @@ def index(indexable: Mapping[int, Any], i: int) -> Any:
return indexable[i]


@register.filter
def tabs(adminform: AdminForm) -> List[Fieldset]:
result = []

for fieldset in adminform:
if "tab" in fieldset.classes and fieldset.name:
result.append(fieldset)

return result


class CaptureNode(Node):
def __init__(self, nodelist: NodeList, varname: str, silent: bool) -> None:
self.nodelist = nodelist
Expand Down

0 comments on commit b412b20

Please sign in to comment.