Release Notes — v0.2.13 (July 5, 2026)
1. User-Definable Tab Groups (get_tab_groups)
Status: Uncommitted
Detail views now support user-definable top-level tab groups, replacing the hard-coded "Lines"/"Header" tab bar in detail_source_document_partial.html with a fully dynamic system. Any BaseDetailView or BaseSourceDocumentDetailView subclass can define its own tab groups via the get_tab_groups() method.
Usage
class MyDetailView(BaseDetailView):
def get_tab_groups(self):
return [
{'key': 'general', 'name': 'General Info'},
{'key': 'financial', 'name': 'Financial Data'},
{'key': 'notes', 'name': 'Notes'},
]
def detail_ui_view(self):
return [
{'name': 'Basic', 'icon': 'Home', 'headerpostion': 'general', 'Fieldcolumns': [...]},
{'name': 'Amounts', 'icon': 'Currency', 'headerpostion': 'financial', 'Fieldcolumns': [...]},
{'name': 'Remarks', 'icon': 'Pencil', 'headerpostion': 'notes', 'Fieldcolumns': [...]},
]
Backend
enezaframework/views/base.py:- Added
get_tab_groups()method returning[]by default — override in subclasses to define custom tab groups. - Added
get_processed_tab_groups(self, fieldtabs, inlines=None)— distributes fieldtabs (byheaderpostion) and inline objects (bytab_group) into matching groups. Unmatched fieldtabs fall into the first group. - Updated
get_context_data()to computetab_groupsandungrouped_inlinescontext variables. enezaframework/views/basesourcedocument.py:BaseSourceDocumentDetailView.get_tab_groups()returns[{'key': 'lines', 'name': 'Lines'}, {'key': 'header', 'name': 'Header'}]for full backward compatibility.
Templates
core/partials/fieldtabs_accordion.html(new) — Reusable Alpine.js accordion include that renders fieldtabs usingsmart_field. Eliminates ~70 lines of duplicated accordion markup.core/partials/detail_source_document_partial.html— Replaced hard-coded Lines/Header tabs with dynamic{% if tab_groups %}rendering. Tab bar and panes generated from context variable.core/partials/detail_partial.html— Added optional tab group support. Whentab_groupsis present, renders tab bar with accordion panes; otherwise preserves originalmain_object_form.htmlbehavior.core/partials/main_object_form.html— Refactored to usefieldtabs_accordion.htmlinclude.
Backward Compatibility
- Views without
get_tab_groups()(or returning[]) render in accordion-only mode — no tab bar, same behavior as before. BaseSourceDocumentDetailViewretainslines/headertabs viaget_tab_groups()— existingheaderpostion-based code works unchanged.- Fieldtabs without
headerpostionare automatically placed in the first group.
Files changed: 4 backend + 3 templates (2 new, 3 modified).
2. Inline Tab Group Placement (tab_group on Inline Objects)
Status: Uncommitted
Inline related objects can now be assigned to specific tab groups, rendering inside their parent tab pane instead of always at the bottom of the page. Add 'tab_group': 'general' to any inline definition dict.
Usage
def get_inline_related_objects(self):
return [
{
'name': 'images',
'caption': 'Images',
'model': 'EnezaImages',
'relation_name': 'images_content_type',
'tab_group': 'general', # renders inside "General Info" tab
...
},
{
'name': 'document_lines',
'caption': 'Line Items',
'model': 'DocumentLine',
'relation_name': 'lines',
'tab_group': 'items', # renders inside "Line Items" tab
...
},
{
'name': 'audit_log',
'caption': 'Audit Log',
'model': 'AuditLog',
'relation_name': 'audit_logs',
# no tab_group — renders at bottom (ungrouped)
...
},
]
Backend
enezaframework/views/mixins.py:get_inline_fieldtab_config()passes throughtab_groupkey on each inline dict.enezaframework/views/base.py:get_processed_tab_groups()distributes inlines into matching groups alongside fieldtabs.get_context_data()computesungrouped_inlinesfor inlines withouttab_group.
Templates
core/partials/inline_items_section.html(new) — Reusable inline accordion include that renders a list of inline items with expand/collapse accordions and HTMX lazy loading.core/partials/detail_partial.html— Inline objects now render inside their assigned tab panes (grouped) or at page bottom (ungrouped). Tab group Alpine.js scope expanded to cover both form fields and inline sections.core/partials/detail_source_document_partial.html— Same grouped/ungrouped inline pattern.
Backward Compatibility
- Inlines without
tab_grouprender at the bottom as before (viaungrouped_inlinescontext variable). - Views without
get_tab_groups()see all inlines at the bottom (no grouping occurs).
Files changed: 2 backend + 3 templates (1 new, 2 modified).
3. Inline Accordion Toggle Bug Fix
Status: Uncommitted
Fixed a bug where inline accordion sections could not be re-expanded after collapsing when inline_item.active was 1. The toggle logic used hard-coded values (active === 1 ? active = null : active = 2) while the x-show visibility check used {{inline_item.active}}. The toggle could go 1 → null → 2 but never back to 1, trapping the accordion permanently closed.
Fix
All four hard-coded references replaced with {{inline_item.active}}:
| Before | After |
|---|---|
x-data="{ active: 1 }" |
x-data="{ active: {{inline_item.active}} }" |
x-on:click="active === 1 ? active = null : active = 2" |
x-on:click="active === {{inline_item.active}} ? active = null : active = {{inline_item.active}}" |
:class="{ '!text-primary': active === 1 }" |
:class="{ '!text-primary': active === {{inline_item.active}} }" |
:class="{ 'rotate-180': active === 1 }" |
:class="{ 'rotate-180': active === {{inline_item.active}} }" |
Affected Templates
| Template | Context |
|---|---|
core/partials/detail_partial.html |
Main detail view inline accordions |
core/partials/detail_source_document_partial.html |
Source document detail view inline accordions |
core/partials/inline_details_partial.html |
Nested inline detail accordions |
core/partials/inline_update_partial.html |
Nested inline edit accordions |
core/partials/detail_parameter_partial.html |
Parameter detail view inline accordions |
setups/partials/setup_details.html |
Setup detail inline accordions |
setups/partials/setup_create.html |
Setup create inline accordions |
setups/partials/setup_readonly_details.html |
Read-only setup detail inline accordions |
setups/partials/setup_readonly_create.html |
Read-only setup create inline accordions |
journal/partials/journal_batch_detail.html |
Journal batch detail inline accordions |
Files changed: 10 template files.
4. Dark Mode as Default
Status: Uncommitted
The application theme now defaults to dark mode on first visit. The $persist plugin preserves user choices in localStorage, so only first-time visitors see dark by default — users who manually switch to light mode retain their preference.
Changes
enezaframework/static/assets/js/custom.js:$themeConfig.themechanged from'light'to'dark'.vristo-html-template/assets/js/custom.js:$themeConfig.themechanged from'light'to'dark'.isDarkModechanged fromAlpine.$persist(false)toAlpine.$persist(true).- No FOUC (flash of unstyled content) — the
screen_loaderfull-page overlay covers the initial render before Alpine initializes.
Files changed: 2 JS files.
5. Template Code Quality — Reusable Partials
Status: Uncommitted
Two new reusable template partials eliminate significant code duplication across the codebase.
core/partials/fieldtabs_accordion.html
- Renders a list of fieldtabs as Alpine.js accordion sections with expand/collapse toggle, icon, and column-based field layout.
- Used by:
detail_partial.html,detail_source_document_partial.html,main_object_form.html. - Eliminates ~70 lines of duplicated accordion markup per usage.
core/partials/inline_items_section.html
- Renders a list of inline related objects with expand/collapse accordions, HTMX lazy loading, and proper
party_object/objectpk handling. - Used by:
detail_partial.html,detail_source_document_partial.html(both grouped and ungrouped inline sections).
6. Test App — Tab Group Demonstrations
Status: Uncommitted
frameworkapp/views/testviews.py:FrameworkTestDetailView: Addedget_tab_groups()with'general'and'items'groups. Fieldtabs assigned viaheaderpostion. Inline objects assigned viatab_group— Images under "General Info", Lines under "Line Items".- Fixed
'headerpostion '(trailing space) →'headerpostion'on all fieldtab definitions (3 occurrences).
Files changed: 1 file.
7. Version
Already at 0.2.13 in setup.py.
Summary
| Area | Description | Files |
|---|---|---|
| Tab Groups | User-definable top-level tab groups via get_tab_groups(); dynamic tab bar + accordion panes in detail views; fieldtabs_accordion.html reusable include |
7 |
| Inline Tab Placement | Inline objects assignable to tab groups via tab_group key; inline_items_section.html reusable include |
5 |
| Accordion Toggle Fix | Hard-coded inline accordion toggle fixed across 10 templates — re-expanding now works for all inline_item.active values |
10 |
| Dark Mode Default | Theme default changed from light to dark; first-visit dark mode with localStorage persistence | 2 |
| Code Quality | Two reusable partials eliminate ~200 lines of duplicated template code | 2 (new) |
| Test App | Tab group and inline placement demo; headerpostion typo fix |
1 |
Total: 8 backend/template files modified, 2 new template partials, 2 JS files modified, 10 template bugfixes = ~22 files changed.
Note: All changes are uncommitted and untested. The user is solely responsible for testing and validating all outputs before committing or deploying.