From 2887cd40077bd780014454f60884b00952d4803f Mon Sep 17 00:00:00 2001 From: delchev Date: Wed, 24 Jun 2026 00:06:12 +0300 Subject: [PATCH 01/22] feat(template): Alpine.js + Harmonia runtime UI template (list + manage) Adds `template-application-ui-harmonia-java`, a parallel runtime UI stack that generates a self-contained Alpine.js + Harmonia SPA (client-routed via Pinecone, no iframes/hubs) from the same `.model` as the Angular template, reusing the Java REST/DAO backend unchanged. - New generation template registered on `platform-templates` (appears in the EDM Generate picker as "Application - UI (Harmonia) - Java"). Composes the reused `template-application-rest-java` sources with a Harmonia UI source set. - View types: read-only `list`, and `manage` (CRUD list + shared create/edit form on a `baseFormPage` with 422 ValidationError -> per-field mapping, relationship dropdowns, client validation, delete-confirm). Other view types stubbed. - Reusable shell adopted from codbex-athena-app: x-h-split layout, sidebar, breadcrumb, responsive drawer, fetch entity client, error/i18n catalog. - Phase 1 embedding: Alpine 3.15.11 + Harmonia 1.24.1 + Lucide served as webjars via application-core (harmonia.version bumped 1.4.2 -> 1.24.1); Pinecone Router vendored (no webjar) under application-core/vendor (license-excluded). The generated index.html references only local assets, no CDN. - HARMONIA_RUNTIME_PLAN.md: research + phasing. IntentSettings: comment noting the intent model recipe names the template explicitly (Angular default today). Verified end-to-end against a live app from a real model (DependsOnIT/edm.model): generation succeeds, the SPA is served at /services/web//, and a CRUD round-trip + relationship dropdowns hit the generated controllers. Co-Authored-By: Claude Opus 4.8 --- HARMONIA_RUNTIME_PLAN.md | 338 ++++++++++++++++++ .../intent/generator/IntentSettings.java | 3 + components/group/group-templates/pom.xml | 4 + components/pom.xml | 6 + .../vendor/pinecone-router.min.js | 4 + .../README.md | 100 ++++++ .../pom.xml | 24 ++ .../project.json | 5 + .../template/template.extension | 5 + .../template/template.js | 62 ++++ .../template/ui/list.js | 40 +++ .../template/ui/manage.js | 60 ++++ .../template/ui/navigation.js | 19 + .../template/ui/shell.js | 88 +++++ .../template/ui/template.js | 44 +++ .../ui/perspective/list/page.js.template | 112 ++++++ .../ui/perspective/list/view.html.template | 92 +++++ .../perspective/manage/form-page.js.template | 152 ++++++++ .../manage/form-view.html.template | 129 +++++++ .../perspective/manage/list-page.js.template | 127 +++++++ .../manage/list-view.html.template | 130 +++++++ .../ui/shell/css/app.css.template | 13 + .../ui/shell/index.html.template | 161 +++++++++ .../ui/shell/js/app.js.template | 6 + .../js/components/layout/appShell.js.template | 103 ++++++ .../components/pages/baseFormPage.js.template | 112 ++++++ .../js/components/pages/basePage.js.template | 22 ++ .../ui/shell/js/config.js.template | 25 ++ .../ui/shell/js/services/api.js.template | 117 ++++++ .../ui/shell/js/services/apiError.js.template | 59 +++ .../js/services/formValidation.js.template | 49 +++ .../ui/shell/notfound.html.template | 12 + .../ui/translations.json.template | 68 ++++ pom.xml | 5 +- 34 files changed, 2295 insertions(+), 1 deletion(-) create mode 100644 HARMONIA_RUNTIME_PLAN.md create mode 100644 components/resources/application-core/src/main/resources/META-INF/dirigible/application-core/vendor/pinecone-router.min.js create mode 100644 components/template/template-application-ui-harmonia-java/README.md create mode 100644 components/template/template-application-ui-harmonia-java/pom.xml create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/project.json create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/template/template.extension create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/template/template.js create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/template/ui/list.js create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/template/ui/manage.js create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/template/ui/navigation.js create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/template/ui/shell.js create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/template/ui/template.js create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/perspective/list/page.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/perspective/list/view.html.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/perspective/manage/form-page.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/perspective/manage/form-view.html.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/perspective/manage/list-page.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/perspective/manage/list-view.html.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/css/app.css.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/index.html.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/js/app.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/js/components/layout/appShell.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/js/components/pages/baseFormPage.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/js/components/pages/basePage.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/js/config.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/js/services/api.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/js/services/apiError.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/js/services/formValidation.js.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/shell/notfound.html.template create mode 100644 components/template/template-application-ui-harmonia-java/src/main/resources/META-INF/dirigible/template-application-ui-harmonia-java/ui/translations.json.template diff --git a/HARMONIA_RUNTIME_PLAN.md b/HARMONIA_RUNTIME_PLAN.md new file mode 100644 index 00000000000..c566239c5c8 --- /dev/null +++ b/HARMONIA_RUNTIME_PLAN.md @@ -0,0 +1,338 @@ +# Dirigible runtime on AlpineJS + Harmonia — research & plan + +Research and implementation plan for a parallel, fully-embedded runtime UI stack. +Framework swap only; behaviour parity. + +## Goal + +Keep the **IDE** (Workbench, Monaco editors, entity/form/intent modelers) on **AngularJS + BlimpKit**. +Move the **runtime** — generated *and* custom apps, plus their **shell/dashboard**, views, forms and +BPM task forms — onto a self-contained **AlpineJS + Harmonia** stack, with SAP-icons replaced by +Harmonia/Unicons, and the whole stack **built into the fat jar** exactly as AngularJS + BlimpKit is +today. No new behaviour — same flows, same REST backend, same artifacts. + +## Verdict + +Feasible, and the architecture already permits it — but it is a large, multi-phase initiative, not a +re-skin. The single biggest lever is that the platform's view↔shell contract is a **framework-agnostic +message protocol** (`postMessage` hubs) plus **JSON / plain-JS registration**. Keep that protocol as +the invariant and you can swap *both ends* (shell and views) to Harmonia while the IDE keeps running on +Angular — and the two stacks can coexist during transition. + +The real work is in three places: (1) reimplementing the runtime **shell/renderers** (the *receiving* +end of the hubs) in Harmonia, (2) a full **view template set** at parity, and (3) a Harmonia **forms** +runtime. Plus embedding + icons + a couple of genuine Harmonia gaps (split panes). + +> **Update after studying the reference implementation.** Two assumptions above are now corrected by a +> working sample (see the new section **"Reference implementation: codbex-athena-app"** below): +> Harmonia **does** ship a split component (`x-h-split`) — the split-pane gap is closed — and a full, +> reusable **Harmonia runtime dashboard/shell already exists** in that repo (sidebar + toolbar + +> breadcrumb + responsive collapse + theming + a `fetch`-based entity client + a 422 error-mapping form +> base). That collapses the single biggest cost (Workstream 3 / Phase 1) from "build from scratch" to +> "adopt and adapt." It also reveals a **different shell architecture** than this plan assumed — a +> single-page, client-side-routed SPA served as a plain Dirigible web resource, **not** the +> iframe-per-view + `postMessage`-hub seam. Read that section before committing to the phasing. + +## Reference implementation: codbex-athena-app + +`github.com/codbex/codbex-athena-app` (the `codbex-athena-app/` project inside it) is a **complete, +working Alpine + Harmonia runtime application** built exactly the way this initiative needs — and per the +direction *its dashboard/shell can be adopted directly*, not re-derived. It is a Dirigible project +(`project.json` with a `guid` + git dependency on `codbex-invoices`; served as a web resource under +`/services/web/codbex-athena-app/`) and it ships, in its own `.claude/skills/`, an 88 KB Harmonia +component reference and an Alpine-architecture guide that together encode the conventions below. Treat +this repo as the canonical pattern source for Workstreams 1–5. + +### What it proves / changes vs. the original plan + +1. **Split panes are NOT a gap.** Harmonia ships `x-h-split` + `x-h-split-panel`, and athena uses it for + the **shell layout itself** — the sidebar/main division is a horizontal split. Real usage from its + `index.html`: + ```html +
+
… sidebar …
+
… main …
+
+ ``` + Documented attributes: `data-orientation="horizontal|vertical"` (h is default), `data-default-size` + (percentages, panels should sum to 100), `data-min` / `data-max` (px clamps), `data-locked="true"` + (non-resizable pane), `data-gutterless="true"` (hide the drag handle), `data-variant="border"`, + `:data-hidden` (collapse a pane reactively). This covers **both** uses the plan flagged — master-detail + views *and* shell layout — so the `platformSplit` port is unnecessary. Decision in Phase 1 is resolved: + use `x-h-split`. + +2. **The runtime dashboard/shell already exists and is reusable.** `js/components/layout/appShell.js` is + a single `Alpine.data('app', …)` component providing everything Workstream 3 lists: sidebar nav + (`x-h-sidebar` + `x-for` over a `nav` array), a top `x-h-toolbar` with `x-h-breadcrumb` trail derived + from the route, a notifications popover, an avatar `x-h-menu` with a light/dark/auto theme submenu, and + **responsive collapse** driven by `Harmonia.getBreakpointListener((isNarrow)=>…, 1024)` that physically + re-parents the sidebar into an `x-h-sheet` drawer below 1024 px. Adopt this file as the starting shell; + the per-app parts that change are just the `nav`, `routeTitles`, and `sections` maps. + +3. **The shell architecture is a client-routed SPA, not the iframe+hub seam.** This is the biggest + architectural divergence from the plan. athena has **no iframes and no `postMessage` hubs**. It is one + HTML page; **Pinecone Router** (v7.5.0, **hash mode**, `basePath: '/services/web/'`) declares + routes as `