diff --git a/docs/admin-ui-architecture-diagram.png b/docs/admin-ui-architecture-diagram.png new file mode 100644 index 0000000000..bb66252629 Binary files /dev/null and b/docs/admin-ui-architecture-diagram.png differ diff --git a/docs/admin-ui-architecture.md b/docs/admin-ui-architecture.md new file mode 100644 index 0000000000..3137042006 --- /dev/null +++ b/docs/admin-ui-architecture.md @@ -0,0 +1,1412 @@ +# Broadleaf Commerce Admin UI Architecture + +> **Document Version:** 1.0 +> **Date:** April 2026 +> **Purpose:** Comprehensive audit of the current admin UI architecture to guide future rewrite efforts. +> **Scope:** Open Admin Platform front-end — JavaScript, templates, CSS, and their server-side integration points. + +--- + +## Table of Contents + +1. [Executive Summary](#1-executive-summary) +2. [Technology Stack](#2-technology-stack) +3. [High-Level Architecture](#3-high-level-architecture) +4. [JavaScript Component Inventory](#4-javascript-component-inventory) + - 4.1 [Script Loading Order](#41-script-loading-order) + - 4.2 [Core Files](#42-core-files) + - 4.3 [UI Layer](#43-ui-layer) + - 4.4 [Component Layer](#44-component-layer) + - 4.5 [Vendor Libraries](#45-vendor-libraries) + - 4.6 [Library Plugins](#46-library-plugins) + - 4.7 [Redactor Plugins](#47-redactor-plugins) +5. [BLCAdmin Namespace API](#5-blcadmin-namespace-api) + - 5.1 [Global Object Structure](#51-global-object-structure) + - 5.2 [Modal Management](#52-modal-management) + - 5.3 [Handler Registration System](#53-handler-registration-system) + - 5.4 [Field Initialization](#54-field-initialization) + - 5.5 [Selectize Integration](#55-selectize-integration) + - 5.6 [Event System and Callbacks](#56-event-system-and-callbacks) +6. [BLC Global Utilities](#6-blc-global-utilities) +7. [jQuery Plugins and Libraries Catalog](#7-jquery-plugins-and-libraries-catalog) + - 7.1 [jQuery Versions](#71-jquery-versions) + - 7.2 [Foundation 3](#72-foundation-3) + - 7.3 [Redactor Rich Text Editor](#73-redactor-rich-text-editor) + - 7.4 [Selectize](#74-selectize) + - 7.5 [DataTables](#75-datatables) + - 7.6 [Other Vendor Libraries](#76-other-vendor-libraries) + - 7.7 [jQuery Plugins (lib/plugins)](#77-jquery-plugins-libplugins) +8. [Thymeleaf Template Map](#8-thymeleaf-template-map) + - 8.1 [Template Hierarchy](#81-template-hierarchy) + - 8.2 [Layout Templates](#82-layout-templates) + - 8.3 [Component Templates](#83-component-templates) + - 8.4 [Field Type Templates](#84-field-type-templates) + - 8.5 [View Templates](#85-view-templates) + - 8.6 [Modal Templates](#86-modal-templates) + - 8.7 [Login and Utility Templates](#87-login-and-utility-templates) +9. [AJAX Endpoints and Server-Side Controllers](#9-ajax-endpoints-and-server-side-controllers) + - 9.1 [AdminBasicEntityController](#91-adminbasicentitycontroller) + - 9.2 [Request/Response Flow](#92-requestresponse-flow) +10. [Critical Admin Features](#10-critical-admin-features) + - 10.1 [Entity CRUD Operations](#101-entity-crud-operations) + - 10.2 [ListGrid (Data Tables)](#102-listgrid-data-tables) + - 10.3 [Rule Builder](#103-rule-builder) + - 10.4 [Filter Builder](#104-filter-builder) + - 10.5 [Asset Management](#105-asset-management) + - 10.6 [Translations](#106-translations) + - 10.7 [Session Management](#107-session-management) +11. [Dependency Graph](#11-dependency-graph) +12. [Interaction Patterns](#12-interaction-patterns) +13. [Risks and Technical Debt](#13-risks-and-technical-debt) +14. [Framework Replacement Recommendations](#14-framework-replacement-recommendations) + +--- + +## 1. Executive Summary + +The Broadleaf Commerce admin UI is a server-rendered, metadata-driven application built on **Thymeleaf** templates and a large jQuery-based JavaScript layer. The front-end centers on a single global namespace — `BLCAdmin` — that orchestrates modal management, form handling, field initialization, and AJAX communication. All UI is auto-generated from JPA entity metadata through the **Open Admin Platform**, meaning the same JS/template code renders every entity type in the system. + +### Key Statistics + +| Metric | Count | +|--------|-------| +| JavaScript files (admin directory) | **96** | +| Thymeleaf HTML templates | **120** | +| Field type templates (edit + filter) | **50** | +| Lines of custom admin JS (components + core) | **~9,300** | +| Lines of vendor/library JS | **~75,000+** | +| jQuery version | **3.5.1** (two copies) | +| CSS framework | **Foundation 3** (12 plugins) | +| Rich text editor | **Redactor** (6 custom plugins) | + +### Architecture at a Glance + +![Admin UI Architecture Diagram](admin-ui-architecture-diagram.png) + +
+Text version of the architecture diagram + +``` +┌──────────────────────────────────────────────────────────────────┐ +│ Browser (Client) │ +│ │ +│ ┌────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ +│ │ Foundation 3│ │ jQuery 3.5 │ │ Vendor Libs │ │ +│ │ (CSS + JS) │ │ │ │ Selectize, Redactor, │ │ +│ │ │ │ │ │ DataTables, QueryBuilder, │ │ +│ └──────┬──────┘ └──────┬───────┘ │ Spectrum, Moment, etc. │ │ +│ │ │ └───────────┬──────────────┘ │ +│ └────────┬───────┘ │ │ +│ ▼ │ │ +│ ┌───────────────────────────────────────────────┴──────────────┐│ +│ │ BLCAdmin Namespace ││ +│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ ││ +│ │ │ Modals │ │ Handlers │ │ Fields │ │ Components │ ││ +│ │ │ (stack) │ │ (chain) │ │ (init) │ │ entityForm │ ││ +│ │ │ │ │ │ │ │ │ listGrid │ ││ +│ │ │ │ │ │ │ │ │ ruleBuilder │ ││ +│ │ │ │ │ │ │ │ │ filterBuilder │ ││ +│ │ └──────────┘ └──────────┘ └──────────┘ └────────────────┘ ││ +│ └──────────────────────────┬───────────────────────────────────┘│ +│ │ BLC.ajax() │ +│ ▼ │ +└─────────────────────────────┬────────────────────────────────────┘ + │ HTTP (HTML fragments / JSON) + ▼ +┌──────────────────────────────────────────────────────────────────┐ +│ Spring MVC Server │ +│ │ +│ ┌──────────────────────────────────────────────────────────────┐│ +│ │ AdminBasicEntityController (/{sectionKey}) ││ +│ │ viewEntityList · viewEntityForm · addEntity · saveEntity ││ +│ │ removeEntity · showAddCollectionItem · updateCollectionItem││ +│ │ getCollectionFieldRecords · viewEntityListSelectize ││ +│ └──────────────────────────┬───────────────────────────────────┘│ +│ │ │ +│ ┌──────────────────────────▼───────────────────────────────────┐│ +│ │ Thymeleaf Template Engine ││ +│ │ fullPageLayout → head + leftNav + header + content + footer ││ +│ │ modalContainer → entityAdd / entityEdit / adornedSelect ││ +│ │ components: entityForm · listGrid · ruleBuilder · fields/* ││ +│ └──────────────────────────────────────────────────────────────┘│ +│ │ +│ ┌──────────────────────────────────────────────────────────────┐│ +│ │ Open Admin Platform (Metadata) ││ +│ │ ClassMetadata → EntityForm → ListGrid → Field → FieldGroup ││ +│ │ PersistencePackageRequest → DynamicResultSet ││ +│ └──────────────────────────────────────────────────────────────┘│ +└──────────────────────────────────────────────────────────────────┘ +``` + +
+ +--- + +## 2. Technology Stack + +| Layer | Technology | Version | Notes | +|-------|-----------|---------|-------| +| **CSS Framework** | Foundation 3 | 3.x | jQuery-based, 12 component plugins | +| **JS Library** | jQuery | 3.5.1 | Two identical copies (lib + vendor) | +| **JS UI** | jQuery UI | 1.13.3 | Date/time pickers, sortable, draggable | +| **Rich Text** | Redactor | (bundled) | 9,642 lines; 6 custom plugins | +| **Dropdowns** | Selectize.js | (bundled) | 3,685 lines; async search, custom plugins | +| **Data Tables** | jQuery DataTables | 1.13.1 | 15,605 lines; used for some grids | +| **Query Builder** | jQuery QueryBuilder | (bundled) | 4,082 lines; rule/filter building | +| **Color Picker** | Spectrum.js | (bundled) | 2,341 lines | +| **Typeahead** | Bloodhound + Typeahead | (bundled) | 2,450 lines | +| **Date/Time** | jQuery DateTimePicker | (bundled) | 1,870 lines | +| **Templates** | doT.js | (bundled) | Client-side micro-templates | +| **Moment** | Moment.js + locales | (bundled) | Date formatting/parsing | +| **Templating** | Thymeleaf | 3.x | Server-side HTML generation | +| **Backend** | Spring MVC | 6.x | Jakarta EE / Spring Boot | +| **Build** | Maven + BLC Bundle Tag | — | CSS/JS bundling via custom Thymeleaf dialect | +| **Modernizr** | Modernizr | 3.6.0 | Feature detection | + +--- + +## 3. High-Level Architecture + +### 3.1 Metadata-Driven UI + +The admin UI is fundamentally **metadata-driven**. Entity classes are annotated with `@AdminPresentation*` annotations, and the Open Admin Platform reads these at runtime to produce `ClassMetadata` objects. The controller layer converts metadata into `EntityForm` and `ListGrid` DTOs, which Thymeleaf templates render into HTML. + +**Flow:** + +``` +JPA Entity Annotations + │ + ▼ +ClassMetadata (server) + │ + ▼ +EntityForm / ListGrid DTOs + │ + ▼ +Thymeleaf templates (server-side HTML) + │ + ▼ +Browser receives HTML fragment + │ + ▼ +BLCAdmin.initializeFields() runs on new DOM + │ + ▼ +Selectize, Redactor, DatePicker, etc. attach to fields +``` + +### 3.2 Page Lifecycle + +1. **Full page load** — `fullPageLayout.html` renders with ``, left navigation, header, content area, and footer. +2. **Footer** loads three JS bundles in order: `adminlib.js` (vendor), `admin.js` (app), `admin-init.js` (bootstrap). +3. **`blc-admin-init.js`** initializes Foundation plugins, then calls `BLCAdmin.initializeFields()`. +4. **Subsequent interactions** use `BLC.ajax()` to fetch HTML fragments from the server, insert them into the DOM (often inside modals), and re-run `BLCAdmin.initializeFields()` on the new content. + +### 3.3 Module System + +There is **no module system** (no AMD, CommonJS, or ES modules). All files are concatenated into bundles by the `` Thymeleaf tag at build time. Every file either: +- Extends the `BLCAdmin` global via an IIFE: `(function($, BLCAdmin) { ... })(jQuery, BLCAdmin);` +- Attaches jQuery event handlers via `$(document).ready()` or delegated `$('body').on(...)`. + +--- + +## 4. JavaScript Component Inventory + +### 4.1 Script Loading Order + +The footer (`layout/partials/footer.html`) defines three bundles loaded in strict order: + +**Bundle 1: `adminlib.js`** — Vendor libraries (loaded first, provides jQuery plugins) +``` +jquery-3.5.1.js (loaded separately via +``` + +The `lib/` copy appears to be a legacy artifact. **Recommendation:** Remove the duplicate. + +### 7.2 Foundation 3 + +Foundation 3 is the CSS grid and component framework. The following jQuery plugins are initialized in `blc-admin-init.js`: + +| Component | Initialized | Actually Used | +|-----------|-------------|---------------| +| `foundationAlerts` | Yes | Yes — dismissable notifications | +| `foundationButtons` | Yes | Yes — button groups | +| `foundationAccordion` | Yes | Yes — collapsible sections | +| `foundationNavigation` | Yes | Yes — dropdown menus | +| `foundationTopBar` | Yes | Limited — top bar structure | +| `foundationMediaQueryViewer` | Yes | Development only | +| `foundationTabs` | Yes | **Yes — primary tab navigation** with field init callback | +| `foundationTooltips` | Yes | Yes — field help tooltips | +| `foundationMagellan` | Yes | Minimal usage | +| `foundationClearing` | Yes | Yes — image galleries | +| `foundationForms` | Not explicitly | CSS form styling | +| `foundationJoyride` | Not explicitly | Not observed in use | +| `foundationOrbit` | Not explicitly | Not observed in use | + +**Foundation tab callback (critical):** +```javascript +$.fn.foundationTabs({ + deep_linking: false, + callback: function() { + BLCAdmin.initializeFields(BLCAdmin.getActiveTab()); + BLCAdmin.updateFields(BLCAdmin.getActiveTab()); + } +}); +``` + +### 7.3 Redactor Rich Text Editor + +**Core:** `lib/redactor.js` (9,642 lines) + +**Configuration (from `blc-admin.js` initialization):** +```javascript +$el.redactor({ + plugins: ['fontcolor', 'fontfamily', 'fontsize', 'table', 'video', 'selectasset'], + replaceDivs: false, + pastePlainText: true, + deniedTags: ['html', 'head', 'body', 'meta', 'applet', 'style'], + minHeight: 140, + tabIndex: 1, + buttons: [ + 'html', 'formatting', 'bold', 'italic', 'underline', 'deleted', + 'unorderedlist', 'orderedlist', 'outdent', 'indent', + 'image', 'video', 'file', 'table', 'link', 'alignment', 'horizontalrule' + ] +}); +``` + +**Custom plugins:** + +| Plugin | Function | +|--------|----------| +| `fontcolor` | Adds text color and highlight color buttons to toolbar | +| `fontfamily` | Adds font family dropdown (Arial, Georgia, Impact, Courier, Trebuchet) | +| `fontsize` | Adds font size dropdown (10px through 30px) | +| `selectasset` | Adds "Select Asset" button — opens BLC asset selector modal to insert images | +| `table` | Full table editing — insert table, add/delete rows/columns | +| `video` | Video embed — pastes iframe/embed code from URL input | + +### 7.4 Selectize + +**Core:** `vendor/selectize.js` (3,685 lines) + +**Used for:** +- Enum dropdowns (single and multi-select) +- Foreign key lookups (async search via `/{sectionKey}/selectize`) +- Rule builder field selection +- Filter builder value selection + +**Custom Selectize plugins:** +- `selectize-silent-remove.js` — Removes items without triggering change events +- `clear_on_type` — Clears current selection when user starts typing +- `enter_key_blur` — Blurs selectize on Enter key press + +### 7.5 DataTables + +**Core:** `vendor/jquery.dataTables-1.13.1.js` (15,605 lines) + +DataTables is included but the primary data table implementation is the **custom ListGrid** system. DataTables may be used for specific grids that need its advanced features. The custom ListGrid provides: +- AJAX-loaded records with custom pagination +- Server-side filtering and sorting +- Inline editing +- Row selection (single and multi) +- Sub-collection management +- Toolbar actions + +### 7.6 Other Vendor Libraries + +| Library | File | Lines | Purpose | +|---------|------|-------|---------| +| **Spectrum** | `lib/plugins/spectrum.js` | 2,341 | Color picker widget for color-type fields | +| **Typeahead/Bloodhound** | `lib/plugins/typeahead.bundle.js` | 2,450 | Typeahead search for to-one lookups | +| **doT.js** | `vendor/doT.js` | 157 | Client-side micro-templating | +| **jQuery QueryBuilder** | `vendor/query-builder.js` | 4,082 | Base query builder widget used by rule/filter builders | +| **Moment.js** | `vendor/moment-with-locales.min.js` | 24 (min) | Date parsing and formatting with locale support | +| **Moment Duration Format** | `vendor/moment-duration-format.js` | 499 | Duration formatting extension | +| **jQuery Fluidbox** | `vendor/jquery.fluidbox.js` | 546 | Image lightbox/zoom overlay | +| **jQuery Remodal** | `vendor/jquery.remodal.js` | 333 | Alternative modal dialog library | +| **jQuery Confirm** | `vendor/jquery-confirm.min.js` | 45 (min) | Confirmation dialog boxes | +| **jQuery Easing** | `vendor/jquery.easing.1.3.js` | 204 | Animation easing equations | +| **jQuery ExtendExt** | `vendor/jquery.extendext.js` | 125 | Extended jQuery.extend (used by QueryBuilder) | +| **jQuery ScrollIntoView** | `vendor/jquery.scrollintoview.js` | 209 | Smooth scroll to element | +| **jQuery DateTimePicker** | `vendor/jquery.datetimepicker.js` | 1,851 | Combined date/time picker | +| **Picker.js** | `vendor/picker.js` / `picker.date.js` / `picker.time.js` | 3,424 | Date/time picker components | + +### 7.7 jQuery Plugins (lib/plugins) + +| Plugin | Lines | Purpose | +|--------|-------|---------| +| `blc-admin-query-builder.js` | 250 | BLC wrapper around jQuery QueryBuilder — adds Selectize integration, custom validation, BLC-specific options | +| `blc-admin-filter-builder.js` | 181 | BLC wrapper for filter builder — handles filter-specific QueryBuilder configuration | +| `bootstrap.js` | 254 | Bootstrap 2 JavaScript — provides modal, tooltip, dropdown, alert components (subset used alongside Foundation) | +| `jquery.fileupload.js` | 1,201 | jQuery File Upload — core upload engine | +| `jquery.fileupload-ui.js` | 807 | File Upload UI — progress bars, cancel buttons | +| `jquery.fileupload-fp.js` | 227 | File Upload file processing — image resize, validation | +| `jquery.iframe-transport.js` | 185 | Iframe-based upload fallback for legacy browsers | +| `jquery.mCustomScrollbar.js` | 941 | Custom scrollbar replacement for listgrid containers | +| `jquery.ba-dotimeout.js` | 233 | Debounce and throttle — used for search input delay, resize handling | +| `jquery.autosize.js` | 233 | Auto-resize textareas based on content | +| `jquery.cookie.js` | 63 | Cookie management — used for session and preference storage | +| `jquery.event.move.js` | 584 | Pointer event normalization — touch and mouse | +| `jquery.event.swipe.js` | 130 | Swipe gesture detection | +| `jquery.placeholder.js` | 157 | Placeholder attribute polyfill for older browsers | +| `jquery.mousewheel.js` | 83 | Mouse wheel event normalization | +| `jquery.ui.widget.js` | 530 | jQuery UI Widget factory (standalone) | + +--- + +## 8. Thymeleaf Template Map + +### 8.1 Template Hierarchy + +``` +fullPageLayout.html +├── layout/partials/head.html (CSS bundles, meta tags) +├── layout/partials/leftNav.html (primary navigation) +├── layout/partials/header.html (top bar, search, user menu) +│ ├── layout/partials/breadcrumb.html +│ ├── layout/partials/entityTitle.html +│ ├── layout/partials/headerFlash.html +│ ├── layout/partials/headerDetailedMsg.html +│ ├── layout/partials/stickyHeader.html +│ └── layout/partials/sandboxRibbon.html +├── layout/partials/secondLeftNav.html (secondary navigation) +├── ${templateName} (dynamic content — see views/) +├── layout/partials/footer.html (JS bundles) +│ ├── layout/partials/preFooterContent.html +│ └── layout/partials/postFooterContent.html +└── layout/partials/preHeadContent.html + └── layout/partials/postHeadContent.html + +modalContainer.html (modal wrapper) +├── ${templateName} (modal content — see views/modal/) +└── (inherits JS from parent page) + +loginLayout.html +├── layout/partials/loginHead.html +└── login/*.html +``` + +### 8.2 Layout Templates + +| Template | Purpose | +|----------|---------| +| `layout/fullPageLayout.html` | Master page layout. Includes head, left nav, header, content area, footer. Handles RTL languages. | +| `layout/loginLayout.html` | Login page layout. Minimal chrome, login-specific head. | +| `layout/partials/head.html` | `` section. CSS bundle (`admin.css`), meta tags, favicon. | +| `layout/partials/footer.html` | JS bundles (`adminlib.js`, `admin.js`, `admin-init.js`). Contains the admin user hidden input. | +| `layout/partials/leftNav.html` | Primary left navigation. Admin sections organized by module. | +| `layout/partials/secondLeftNav.html` | Secondary navigation panel (slide-in). | +| `layout/partials/header.html` | Top header bar with breadcrumb, entity title, actions. | +| `layout/partials/breadcrumb.html` | Breadcrumb navigation trail. | +| `layout/partials/entityTitle.html` | Current entity name/title display. | +| `layout/partials/stickyHeader.html` | Sticky header with save/action buttons. | +| `layout/partials/headerFlash.html` | Flash message bar (success/error after redirect). | +| `layout/partials/headerDetailedMsg.html` | Detailed message panel. | +| `layout/partials/sandboxRibbon.html` | Sandbox environment indicator ribbon. | +| `layout/partials/additionalHeaderMenu.html` | Extension point for header menu items. | +| `layout/partials/preHeadContent.html` | Extension point before ``. | +| `layout/partials/postHeadContent.html` | Extension point after head content. | +| `layout/partials/preFooterContent.html` | Extension point before footer scripts. | +| `layout/partials/postFooterContent.html` | Extension point after footer scripts. | + +### 8.3 Component Templates + +| Template | Purpose | +|----------|---------| +| `components/entityForm.html` | **Core entity form.** Renders tabs, field groups, fields, action buttons, sub-collections. The most complex template. | +| `components/partials/entityFormFields.html` | Renders individual fields within a field group. Selects field template based on `field.fieldType`. | +| `components/partials/entityFormGroups.html` | Renders field groups within a tab. | +| `components/listGrid.html` | **Data table.** Renders table headers, body rows, toolbar, pagination controls. | +| `components/partials/listGridHeaderFilter.html` | Filter inputs in listgrid column headers. | +| `components/partials/listGridIcon.html` | Row status icons. | +| `components/listGridToolbar.html` | ListGrid action toolbar (add, reorder, etc.). | +| `components/listGridModalActions.html` | Modal-specific listgrid actions. | +| `components/ruleBuilder.html` | Rule builder widget. Renders jQuery QueryBuilder container with field definitions. | +| `components/searchFields.html` | Search input above main listgrid. | +| `components/emptyMainListGrid.html` | Empty state for listgrids with no records. | +| `components/dynamicForm.html` | Dynamic form rendering for runtime-generated forms. | +| `components/selectizeCollection.html` | Selectize-based collection management. | +| `components/selectizeLabelBar.html` | Label/tag bar for selectize multi-select. | +| `components/standaloneField.html` | Standalone field rendering outside entity form context. | +| `components/fieldTooltip.html` | Field help tooltip rendering. | +| `components/fieldTranslation.html` | Translation indicator and link for translatable fields. | +| `components/mediaGrid.html` | Media/image grid display. | +| `components/mediaListGrid.html` | Media items in listgrid format. | + +### 8.4 Field Type Templates + +Each field type has an **edit** template and a **filter** template: + +**Edit templates (`fields/`):** + +| Template | Field Type | Description | +|----------|-----------|-------------| +| `string.html` | STRING | Text input | +| `text.html` | TEXT | Textarea | +| `integer.html` | INTEGER | Numeric input | +| `decimal.html` | DECIMAL | Decimal input | +| `money.html` | MONEY | Currency input with formatting | +| `boolean.html` | BOOLEAN | Radio buttons (Yes/No) | +| `date.html` | DATE | Date picker | +| `color.html` | COLOR | Spectrum color picker | +| `code.html` | CODE | Code editor (ACE) | +| `html.html` | HTML | Redactor rich text editor | +| `html_basic.html` | HTML_BASIC | Basic HTML textarea | +| `id.html` | ID | Read-only ID display | +| `hidden.html` | HIDDEN | Hidden input | +| `hidden_boolean.html` | HIDDEN_BOOLEAN | Hidden boolean | +| `password.html` | PASSWORD | Password input | +| `readonly.html` | READONLY | Read-only text display | +| `description.html` | DESCRIPTION | Description/help text | +| `foreign_key.html` | FOREIGN_KEY | Selectize lookup | +| `additional_foreign_key.html` | ADDITIONAL_FOREIGN_KEY | Foreign key with display value | +| `asset_lookup.html` | ASSET_LOOKUP | Asset selector with preview | +| `asset_url.html` | ASSET_URL | Asset URL with preview | +| `media.html` | MEDIA | Media item with upload | +| `broadleaf_enumeration.html` | BROADLEAF_ENUMERATION | Selectize enum dropdown | +| `explicit_enumeration.html` | EXPLICIT_ENUMERATION | Selectize explicit enum | +| `data_driven_enumeration.html` | DATA_DRIVEN_ENUMERATION | Selectize data-driven enum | +| `combo_field.html` | COMBO_FIELD | Combined field types | +| `generated_url.html` | GENERATED_URL | Auto-generated URL field | +| `generated_field_value.html` | GENERATED_FIELD_VALUE | Auto-generated value field | +| `rule_simple.html` | RULE_SIMPLE | Simple rule builder | +| `rule_simple_time.html` | RULE_SIMPLE_TIME | Time-based rule builder | +| `rule_with_quantity.html` | RULE_WITH_QUANTITY | Quantity-match rule builder | +| `boolean_link.html` | BOOLEAN_LINK | Boolean displayed as link | + +**Filter templates (`fields/filter/`):** +Each edit template above has a corresponding filter variant in `fields/filter/` that renders the field as a filter input for listgrid header filtering. Filter variants include: +`string`, `text`, `integer`, `decimal`, `money`, `boolean`, `date`, `color`, `code`, `html`, `html_basic`, `id`, `hidden`, `password`, `readonly`, `description`, `foreign_key`, `additional_foreign_key`, `asset_lookup`, `asset_url`, `broadleaf_enumeration`, `explicit_enumeration`, `data_driven_enumeration`, `combo_field`. + +### 8.5 View Templates + +| Template | Purpose | +|----------|---------| +| `views/entityList.html` | Main entity list view. Renders search fields and listgrid, or empty state. | +| `views/entityEdit.html` | Entity edit view. Renders entity form with optional AJAX update mode. Includes CSRF and state version tokens. | +| `views/entityEditWithActions.html` | Entity edit with action buttons (save, delete, etc.). | +| `views/entityListWithUploadForm.html` | Entity list with embedded file upload form. | +| `views/collectionListGrid.html` | Sub-collection listgrid within an entity form. | +| `views/dynamicFormPartial.html` | Partial for dynamically loaded form content. | +| `views/fullListGrid.html` | Full-page listgrid (no entity form wrapper). | +| `views/standaloneListGrid.html` | Standalone listgrid component. | + +### 8.6 Modal Templates + +| Template | Purpose | +|----------|---------| +| `views/modal/entityAdd.html` | **Add new entity** modal. Form with all applicable fields. | +| `views/modal/entityTypeSelection.html` | Polymorphic entity type selector before add. | +| `views/modal/entityView.html` | Read-only entity view modal. | +| `views/modal/simpleAddEntity.html` | Simple (basic collection) add modal. | +| `views/modal/simpleEditEntity.html` | Simple collection edit modal. | +| `views/modal/simpleSelectEntity.html` | Simple entity selection modal with listgrid. | +| `views/modal/adornedSelectEntity.html` | Adorned target entity selector. ListGrid for selecting related entity. | +| `views/modal/adornedEditEntity.html` | Adorned target edit form. Edit join table data after selection. | +| `views/modal/mapAddEntity.html` | Map collection add modal. Key-value pair entry. | +| `views/modal/mapEditEntity.html` | Map collection edit modal. | +| `views/modal/selectAsset.html` | Asset library browser and selector. | +| `views/modal/translationListGrid.html` | Translation list for a field across locales. | +| `views/modal/translationAdd.html` | Add/edit translation for a specific locale. | +| `views/modal/categoryTreeModal.html` | Category tree browser for hierarchical selection. | + +### 8.7 Login and Utility Templates + +| Template | Purpose | +|----------|---------| +| `login/login.html` | Login form. | +| `login/forgotPassword.html` | Password reset request form. | +| `login/forgotUsername.html` | Username recovery form. | +| `login/resetPassword.html` | Password reset form (with token). | +| `login/changePasswordPopup.html` | Password change popup for forced resets. | +| `login/termsAndConditions.html` | Terms and conditions acceptance. | +| `login/loginDialogFooter.html` | Login page footer content. | +| `modules/defaultContainer.html` | Default page container (full-page layout). | +| `modules/emptyContainer.html` | Empty container for AJAX fragment responses. | +| `modules/modalContainer.html` | Modal wrapper container. | +| `noAccess.html` | Access denied page. | +| `sc_conflict.html` | Stale state conflict resolution page. | +| `utility/error.html` | Error display page. | + +--- + +## 9. AJAX Endpoints and Server-Side Controllers + +### 9.1 AdminBasicEntityController + +The primary controller handling all entity CRUD operations. Mapped to `/{sectionKey}` where `sectionKey` identifies the entity type (e.g., `product`, `category`, `offer`). + +| Endpoint | Method | Returns | Purpose | +|----------|--------|---------|---------| +| `/{sectionKey}` | GET | HTML (full page) | Entity list view | +| `/{sectionKey}/selectize` | GET | JSON | Selectize dropdown data | +| `/{sectionKey}/add` | GET | HTML (modal) | Add entity form | +| `/{sectionKey}/add` | POST | HTML/redirect | Create entity | +| `/{sectionKey}/{id}` | GET | HTML (full page) | Entity edit view | +| `/{sectionKey}/{id}` | POST | HTML/redirect | Update entity | +| `/{sectionKey}/{id}/delete` | POST | redirect | Delete entity | +| `/{sectionKey}/{id}/duplicate` | POST | redirect | Duplicate entity | +| `/{sectionKey}/{id}/{tabName}` | GET | HTML (fragment) | Single tab content | +| `/{sectionKey}/{id}/{collectionField}/add` | GET | HTML (modal) | Add collection item form | +| `/{sectionKey}/{id}/{collectionField}/add` | POST | HTML/JSON | Create collection item | +| `/{sectionKey}/{id}/{collectionField}/selectize` | GET | JSON | Collection selectize data | +| `/{sectionKey}/{id}/{collectionField}/{collectionId}` | GET | HTML (modal) | View/edit collection item | +| `/{sectionKey}/{id}/{collectionField}/{collectionId}` | POST | HTML/JSON | Update collection item | +| `/{sectionKey}/{id}/{collectionField}/{collectionId}/delete` | POST | HTML/JSON | Delete collection item | +| `/{sectionKey}/{id}/{collectionField}/details` | GET | HTML (fragment) | Collection listgrid records | +| `/{sectionKey}/{id}/saveEntityJson` | POST | JSON | Save with JSON response (dirty list) | + +### 9.2 Request/Response Flow + +**Standard page load:** +``` +Browser GET /{sectionKey}/{id} + → AdminBasicEntityController.viewEntityForm() + → service.getClassMetadata(ppr) // Get entity metadata + → service.getRecord(ppr) // Get entity data + → formService.populateEntityForm(cmd, entity, entityForm) + → model.addAttribute("entityForm", entityForm) + → model.addAttribute("viewType", "views/entityEdit") + → return DEFAULT_CONTAINER_VIEW // "modules/defaultContainer" + → Thymeleaf renders fullPageLayout.html + → includes views/entityEdit.html + → includes components/entityForm.html + → iterates tabs → field groups → fields + → includes fields/{fieldType}.html for each field + → includes components/listGrid.html for sub-collections +``` + +**AJAX collection load:** +``` +Browser GET /{sectionKey}/{id}/{collectionField}/details + → AdminBasicEntityController.getCollectionFieldRecords() + → formService.buildCollectionListGrid(...) + → return "views/collectionListGrid" + → Thymeleaf renders listGrid fragment + → Browser inserts HTML into existing page + → BLCAdmin.initializeFields($newContent) +``` + +**Modal entity add:** +``` +Browser GET /{sectionKey}/add + → AdminBasicEntityController.viewAddEntityForm() + → formService.createEntityForm(cmd) + → model.addAttribute("viewType", "modal/entityAdd") + → return MODAL_CONTAINER_VIEW // "modules/modalContainer" + → Thymeleaf renders modalContainer.html + → includes views/modal/entityAdd.html + → Browser shows as modal via BLCAdmin.showModal() + → BLCAdmin.initializeFields($modal) +``` + +--- + +## 10. Critical Admin Features + +### 10.1 Entity CRUD Operations + +**Supporting files:** `entityForm.js`, `entityForm-status.js`, `entityForm-generatedUrl.js`, `entityForm-generatedFieldValue.js`, `blc-admin.js` +**Templates:** `entityForm.html`, `entityEdit.html`, `entityList.html`, `modal/entityAdd.html` + +The entity form system handles: +- **Create:** Modal form → POST to `/{sectionKey}/add` → redirect to edit view +- **Read:** Full-page form with tabs, field groups, and sub-collections +- **Update:** Form submission via `BLC.ajax()` → JSON response with dirty field list → selective DOM update +- **Delete:** Confirmation dialog → POST to `/{sectionKey}/{id}/delete` → redirect to list + +**Key features:** +- Sticky header with save button that tracks form dirty state +- Tab-based field grouping with lazy initialization +- Automatic URL generation from name fields +- Unsaved change detection with revert capability +- Field-level validation with error display +- CSRF and stale state protection + +### 10.2 ListGrid (Data Tables) + +**Supporting files:** `listGrid.js`, `listGrid-paginate.js`, `listGrid-filter.js` +**Templates:** `listGrid.html`, `listGridToolbar.html`, `listGridHeaderFilter.html`, `collectionListGrid.html` + +The custom ListGrid provides: +- **Pagination:** Scroll-based lazy loading with range caching. Records fetched in pages via AJAX. +- **Filtering:** Per-column filter inputs in headers. Supports text, date, enum, boolean, and foreign key filters. +- **Sorting:** Click column headers to toggle ASC/DESC/NONE. Server-side sorting. +- **Row selection:** Single-select and multi-select modes for relationship management. +- **Inline editing:** Direct value editing within grid cells. +- **Toolbar actions:** Add, reorder, remove buttons. Custom action support. +- **Sub-collection management:** Nested grids within entity forms for one-to-many and many-to-many relationships. +- **Row reordering:** Drag-and-drop reordering for ordered collections. + +### 10.3 Rule Builder + +**Supporting files:** `ruleBuilder-v2.js`, `ruleBuilder-operators-v2.js`, `ruleBuilder-options.js`, `blc-admin-query-builder.js` +**Templates:** `ruleBuilder.html`, `rule_simple.html`, `rule_simple_time.html`, `rule_with_quantity.html` + +Three rule types: +- **RULE_SIMPLE:** Basic conditional rules (e.g., customer segment rules) +- **RULE_SIMPLE_TIME:** Time-based rules (e.g., promotion date ranges) +- **RULE_WITH_QUANTITY:** Quantity-match rules (e.g., "buy X get Y" promotions) + +Features: +- Dynamic field loading from server (enum options generated at runtime) +- Per-type operator sets (string: contains/starts-with/etc., numeric: >/`. No minification, tree-shaking, or static analysis. | +| **Global namespace pollution** | Medium | `BLCAdmin`, `BLC`, `BLCAdmin.*` all on `window`. Name collisions possible with extensions. | +| **No TypeScript** | Low | No type safety. All 9,300+ lines of custom JS are untyped. | +| **No automated JS tests** | Low | No unit or integration tests for front-end code. | + +### 13.2 Maintenance Concerns + +- **Monolithic `blc-admin.js`** (1,665 lines) — combines modal management, field initialization, selectize setup, redactor setup, and utility functions in one file. +- **Tight coupling** — `entityForm-status.js` has intimate knowledge of Redactor, Selectize, QueryBuilder, and Spectrum internals for revert operations. +- **Duplicated libraries** — jQuery, Modernizr, jquery.remodal, jquery.datetimepicker each appear in multiple locations. +- **Server-side rendering dependency** — Every UI change requires server-side template modification. No way to iterate on front-end independently. +- **No CSS preprocessing** — Plain CSS files bundled at runtime. No SASS/LESS/PostCSS. + +--- + +## 14. Framework Replacement Recommendations + +### 14.1 Evaluation Criteria + +| Criterion | Weight | Rationale | +|-----------|--------|-----------| +| **Metadata-driven rendering** | Critical | The admin auto-generates UI from entity metadata. The replacement must support dynamic form/table generation from schemas. | +| **Component architecture** | High | Must replace 15+ tightly coupled JS files with isolated, testable components. | +| **AJAX/SPA capability** | High | Current pattern is AJAX fragments. Modern framework should support full SPA or hybrid SSR+SPA. | +| **Rich form support** | High | 30+ field types, nested modals, rule builders, file uploads. | +| **Incremental adoption** | High | Cannot rewrite everything at once. Must support coexistence with existing Thymeleaf pages. | +| **Java/Spring integration** | Medium | Backend is Spring MVC. Framework should work with existing REST endpoints. | +| **Team skill availability** | Medium | Framework should have broad adoption and hiring pool. | + +### 14.2 Recommended Approach: React + +**Primary recommendation: React with TypeScript** + +| Factor | Assessment | +|--------|------------| +| **Metadata-driven forms** | Excellent — React JSON Schema Form, Formik, or custom renderers can generate forms from metadata. | +| **Component model** | Excellent — Each field type, listgrid, rule builder, modal becomes an isolated component. | +| **State management** | Excellent — Redux/Zustand replaces the global `BLCAdmin` namespace with predictable state. | +| **Rich text** | Excellent — TipTap, Slate, or Draft.js replace Redactor. | +| **Dropdowns** | Excellent — React Select replaces Selectize with better async search. | +| **Data tables** | Excellent — TanStack Table (React Table) provides headless table with pagination, sorting, filtering. | +| **TypeScript** | Excellent — Full type safety for the 30+ field types and metadata DTOs. | +| **Incremental migration** | Good — Can embed React components in existing Thymeleaf pages via mount points. | +| **Spring integration** | Good — Backend exposes JSON APIs consumed by React. Existing controller methods can be refactored to return JSON. | +| **Ecosystem** | Excellent — Largest ecosystem for admin UI libraries. | + +### 14.3 Alternative: Vue.js + +Vue would also work well and may be preferred if the team has Vue experience: + +| Factor | Assessment | +|--------|------------| +| **Incremental adoption** | Excellent — Vue is designed for progressive adoption. Can mount onto existing pages. | +| **Learning curve** | Lower than React for jQuery developers. Template syntax is more familiar. | +| **Ecosystem** | Good — Vuetify, PrimeVue for component libraries. | + +### 14.4 Migration Strategy + +**Phase 1: API Layer** +- Refactor `AdminBasicEntityController` to return JSON alongside HTML (content negotiation). +- Add REST endpoints for metadata, entity CRUD, collection operations. + +**Phase 2: Component Library** +- Build React/Vue components for each field type (30+ components). +- Build ListGrid, RuleBuilder, FilterBuilder, Modal components. +- Each component is independently testable. + +**Phase 3: Page-by-Page Migration** +- Replace one Thymeleaf view at a time with a React/Vue SPA page. +- Use iframe or micro-frontend pattern for coexistence. +- Start with the simplest views (entity list) and work toward complex ones (entity edit with sub-collections and rule builders). + +**Phase 4: Remove Legacy** +- Once all views are migrated, remove Thymeleaf templates and jQuery code. +- Remove Foundation 3, Redactor, Selectize, and all legacy vendor libraries. + +### 14.5 Key Libraries to Replace + +| Current | Replacement (React) | Replacement (Vue) | +|---------|---------------------|-------------------| +| jQuery 3.5.1 | Not needed (React handles DOM) | Not needed (Vue handles DOM) | +| Foundation 3 | Tailwind CSS or MUI | Tailwind CSS or Vuetify | +| Redactor | TipTap or Slate | TipTap | +| Selectize | React Select | Vue Select | +| jQuery DataTables / ListGrid | TanStack Table | TanStack Table | +| jQuery QueryBuilder | react-querybuilder | vue-query-builder | +| Spectrum | react-colorful | @simonwep/pickr | +| jQuery DateTimePicker | date-fns + react-datepicker | v-calendar | +| jQuery File Upload | react-dropzone | vue-filepond | +| Bloodhound/Typeahead | Built into React Select async | Built into Vue Select async | +| Bootstrap 2 modals | Headless UI / Radix | Headless UI | +| Moment.js | date-fns or dayjs | date-fns or dayjs | + +--- + +*End of document. This audit was conducted by analyzing the source code of the `admin/broadleaf-open-admin-platform` module. No code was modified during this process.*