pgkiln 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/db/migrations/087_login_page.sql +175 -0
  2. package/db/migrations/088_region_templates.sql +18 -0
  3. package/db/migrations/089_page_groups.sql +330 -0
  4. package/docs/apex-feature-parity.md +22 -20
  5. package/docs/guide/03-builder.md +36 -2
  6. package/docs/guide/04-pages-and-regions.md +42 -3
  7. package/docs/guide/08-security.md +46 -5
  8. package/docs/guide/11-from-apex.md +4 -1
  9. package/docs/guide/12-development.md +7 -1
  10. package/docs/guide/17-mobile.md +3 -1
  11. package/docs/guide/18-cli.md +2 -0
  12. package/docs/guide/20-ai-agents.md +2 -0
  13. package/examples/hr/hr_54_region_templates.sql +67 -0
  14. package/examples/hr/hr_55_page_groups.sql +24 -0
  15. package/package.json +1 -1
  16. package/public/app.css +60 -3
  17. package/public/app.js +89 -3
  18. package/public/builder.css +11 -0
  19. package/public/builder.js +50 -0
  20. package/public/code-editor.css +3 -3
  21. package/public/sw.js +5 -3
  22. package/src/app.ts +2 -0
  23. package/src/appfiles.ts +1 -0
  24. package/src/builder/advisor.ts +14 -0
  25. package/src/builder/components.ts +15 -2
  26. package/src/builder/ddl-tools.ts +114 -0
  27. package/src/builder/designer.ts +29 -3
  28. package/src/builder/forms.ts +6 -4
  29. package/src/builder/login-page.ts +82 -0
  30. package/src/builder/region-help.ts +4 -2
  31. package/src/builder/region-settings.ts +19 -3
  32. package/src/builder/routes.ts +16 -4
  33. package/src/builder/shared.ts +1 -1
  34. package/src/builder/sql.ts +3 -0
  35. package/src/builder/ui.ts +2 -2
  36. package/src/cli/main.ts +45 -0
  37. package/src/cli/mcp.ts +42 -0
  38. package/src/cli/replace.ts +4 -0
  39. package/src/ddl.ts +509 -0
  40. package/src/i18n/ar.ts +17 -0
  41. package/src/i18n/cs.ts +17 -0
  42. package/src/i18n/da.ts +17 -0
  43. package/src/i18n/de.ts +17 -0
  44. package/src/i18n/el.ts +17 -0
  45. package/src/i18n/es.ts +17 -0
  46. package/src/i18n/fi.ts +17 -0
  47. package/src/i18n/fr.ts +17 -0
  48. package/src/i18n/he.ts +17 -0
  49. package/src/i18n/it.ts +17 -0
  50. package/src/i18n/ja.ts +17 -0
  51. package/src/i18n/ko.ts +17 -0
  52. package/src/i18n/nb.ts +17 -0
  53. package/src/i18n/pl.ts +17 -0
  54. package/src/i18n/pt.ts +17 -0
  55. package/src/i18n/ru.ts +17 -0
  56. package/src/i18n/sv.ts +17 -0
  57. package/src/i18n/tr.ts +17 -0
  58. package/src/i18n/uk.ts +17 -0
  59. package/src/i18n/zh.ts +17 -0
  60. package/src/i18n.ts +34 -0
  61. package/src/icons.ts +2 -1
  62. package/src/layout.ts +3 -2
  63. package/src/metadata.ts +10 -4
  64. package/src/runtime/devbar.ts +3 -1
  65. package/src/runtime/display-selector.ts +12 -4
  66. package/src/runtime/grid.ts +170 -26
  67. package/src/runtime/lists.ts +11 -1
  68. package/src/runtime/password-reset.ts +171 -0
  69. package/src/runtime/pwa.ts +7 -10
  70. package/src/runtime/regions.ts +33 -0
  71. package/src/runtime/render.ts +15 -0
  72. package/src/runtime/report-views.ts +4 -2
  73. package/src/runtime/report.ts +36 -22
  74. package/src/runtime/routes.ts +35 -32
  75. package/src/runtime/signin.ts +80 -0
  76. package/src/static-version.ts +34 -0
@@ -7,23 +7,23 @@ open item and open an issue or pull request; see [CONTRIBUTING.md](../CONTRIBUTI
7
7
  Legend: ✅ available · 🟡 partial (see notes) · ❌ not yet · ➖ not planned (a deliberate choice,
8
8
  or better served by the PostgreSQL ecosystem; see the notes and [extensions](guide/15-extensions.md))
9
9
 
10
- Last reviewed: 2026-10-12 (sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
10
+ Last reviewed: 2026-10-12 (sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
11
11
 
12
12
  ## At a glance
13
13
 
14
14
  | Area | ✅ | 🟡 | ❌ | ➖ | In short |
15
15
  |---|---:|---:|---:|---:|---|
16
- | App Builder and development | 16 | 1 | 0 | 0 | Page Designer with drag-and-drop and a code editor, wizards, search, where used, an Advisor, a CLI with one file per component, page locks and comments, supporting objects, working copies with a three-way merge, theme/library/boilerplate apps with subscriptions; App Builder AI (pages, SQL and table descriptions) |
17
- | Regions | 22 | 0 | 1 | 0 | All everyday regions, a search region over search configurations and a URL region; sixteen chart types with drill-down; calendars with week/day/list views and drag and drop; faceted search, smart filters and a region display selector; interactive reports with breaks, aggregates, highlights, compute, group by, pivot, chart view and saved reports; maps (with vector tiles) and trees; template components; row ranges, lazy loading and region caching for large tables |
16
+ | App Builder and development | 17 | 0 | 0 | 0 | Page Designer with drag-and-drop and a code editor, wizards, search, where used, an Advisor, a CLI with one file per component, page locks and comments, supporting objects, working copies with a three-way merge, theme/library/boilerplate apps with subscriptions; App Builder AI (pages, SQL and table descriptions) |
17
+ | Regions | 23 | 0 | 0 | 0 | All everyday regions, a search region over search configurations and a URL region; sixteen chart types with drill-down; calendars with week/day/list views and drag and drop; faceted search, smart filters and a region display selector; interactive reports with breaks, aggregates, highlights, compute, group by, pivot, chart view and saved reports; interactive grids with single row, group by and chart views; maps (with vector tiles) and trees; template components; row ranges, lazy loading and region caching for large tables |
18
18
  | Items | 13 | 0 | 0 | 0 | All common items, file upload (several files per item), rich text and Markdown editors, star rating, combobox, date range, QR code, password reveal, display image and geocoded address |
19
19
  | Logic and processing | 17 | 0 | 0 | 1 | User preferences and application settings; all dynamic action events and actions, Ajax callbacks and an error handling function; Core APEX model complete with computations, conditional branches, build options and menu buttons, download, chain and workflow processes; JavaScript from static application files in dynamic actions; region, item, dynamic action and process plug-ins |
20
- | Security | 21 | 0 | 0 | 0 | A session timeout warning; On par or stricter (CSP without `unsafe-inline`); OIDC, SAML and LDAP; header authentication behind a proxy; database accounts; custom authentication |
21
- | User interface | 11 | 1 | 0 | 0 | Universal Theme-like and responsive; a Theme Roller with style variants and conditional, dynamic styles; about 1,700 icons with Font APEX-like modifiers |
22
- | Globalization | 6 | 1 | 0 | 0 | One translated app like 26.1 with dynamic translations of table values; number format masks and automatic time zone; twenty-two built-in languages |
23
- | Data and integration | 11 | 0 | 1 | 2 | `meta.data_export` and data export downloads (CSV, JSON, XML, HTML, Excel, PDF); e-mail through SMTP (password or OAuth2), Microsoft Graph, Amazon SES and HTTP APIs; REST APIs via PostgREST, REST data sources that write back and synchronise, web credentials with OAuth2 grants, CSV/XLSX/JSON/XML loading with saved definitions and unloading, SQL scripts and Quick SQL, report PDFs and document templates |
20
+ | Security | 22 | 0 | 0 | 0 | An editable login page and Forgot password; a session timeout warning; On par or stricter (CSP without `unsafe-inline`); OIDC, SAML and LDAP; header authentication behind a proxy; database accounts; custom authentication |
21
+ | User interface | 12 | 0 | 0 | 0 | Region templates incl. hero, inline dialog and drawer, wizard and carousel; Universal Theme-like and responsive; a Theme Roller with style variants and conditional, dynamic styles; about 1,700 icons with Font APEX-like modifiers |
22
+ | Globalization | 6 | 0 | 0 | 0 | One translated app like 26.1 with dynamic translations of table values; number format masks and automatic time zone; twenty-two built-in languages |
23
+ | Data and integration | 12 | 0 | 0 | 2 | Generate DDL and schema comparison; `meta.data_export` and data export downloads (CSV, JSON, XML, HTML, Excel, PDF); e-mail through SMTP (password or OAuth2), Microsoft Graph, Amazon SES and HTTP APIs; REST APIs via PostgREST, REST data sources that write back and synchronise, web credentials with OAuth2 grants, CSV/XLSX/JSON/XML loading with saved definitions and unloading, SQL scripts and Quick SQL, report PDFs and document templates |
24
24
  | Workflow, automation and AI | 6 | 0 | 0 | 0 | Scheduled automations with several actions and runs from SQL, approvals, a task list and workflows with parallel branches, versions and invoke-API steps; AI with Claude or OpenAI: *Generate text with AI*, an assistant region with tools, natural-language report filters and blueprints |
25
- | Administration | 7 | 2 | 0 | 0 | Application availability and Run only, automatic backups, user feedback; a developer toolbar with a session state viewer and debug per session; Workspaces that group applications and developers (not a tenant boundary); Top SQL per app; debug messages per request; an install/upgrade log |
26
- | **Total** | **130** | **5** | **2** | **3** | 140 APEX features compared: 93% available, 4% partial |
25
+ | Administration | 8 | 1 | 0 | 0 | Application availability and Run only, automatic backups, user feedback; a developer toolbar with a session state viewer and debug per session; Workspaces that group applications and developers (not a tenant boundary); Top SQL per app; debug messages per request; an install/upgrade log |
26
+ | **Total** | **136** | **1** | **0** | **3** | 140 APEX features compared: 97% available, 1% partial |
27
27
 
28
28
  (Counts are of the rows in the tables below. A review on 2026-10-06 added 18 rows for APEX features that were
29
29
  not compared before, and one on 2026-10-12 added two more (property help, application availability), so the share
@@ -45,7 +45,7 @@ available dropped without anything being removed.)
45
45
  | Static application files | ✅ | Shared Components → **Static application files** ([chapter 3](guide/03-builder.md#static-application-files)): JavaScript, CSS, JSON, images and fonts uploaded or written in the builder, served at `/a/<alias>/static/<name>` with long caching per version, loaded by every page or by one page (APEX's *JavaScript/CSS File URLs*), exported with the application (as files in a directory export). No HTML; the CSP stays `script-src 'self'` |
46
46
  | Supporting objects (install scripts) | ✅ | Install, upgrade and deinstall scripts travel with the export (JSON and directory formats), never run on import; reviewed and run from the builder as the app's role, in one transaction, with a result per statement ([chapter 3](guide/03-builder.md#supporting-objects)) |
47
47
  | Theme, library and boilerplate application types (26.1) | ✅ | An application type in Settings ([chapter 3](guide/03-builder.md#application-types-and-subscriptions)): a **theme** app offers its theme (colours, navigation, Theme Roller styles) and template components, a **library** app its lists of values, authorization schemes, build options, template components and lists; other apps **subscribe** (the component is copied), see whether they are in sync, **refresh** one or all, and the master **publishes** to its subscribers (locked apps skipped). A **boilerplate** app is a *Start from* choice in Create application. Subscriptions are not exported; no subscriptions to pages or plug-ins other than template components |
48
- | Property help in the Page Designer, component reference | 🟡 | Help text under most properties in the Page Designer (175 of 266 fields; the obvious ones such as *Title* and *Sequence* have none), and a guide section per region type, item type and button with the columns its SQL must return ([chapter 4](guide/04-pages-and-regions.md#region-types), [5](guide/05-items.md), [6](guide/06-processing.md#buttons)). (sprint 51) A region's *Attributes (JSON)* help shows its own type's keys with a link to its section of the guide. **Missing:** APEX's Help pane for the *selected* property |
48
+ | Property help in the Page Designer, component reference | ✅ | Help text under most properties in the Page Designer (175 of 266 fields; the obvious ones such as *Title* and *Sequence* have none), and a guide section per region type, item type and button with the columns its SQL must return ([chapter 4](guide/04-pages-and-regions.md#region-types), [5](guide/05-items.md), [6](guide/06-processing.md#buttons)). (sprint 51) A region's *Attributes (JSON)* help shows its own type's keys with a link to its section of the guide. (sprint 59) The **Help pane** under the properties shows the focused property's help, the name it is stored under and the guide section of the component's type |
49
49
  | Advisor | ✅ | Per app: every SQL fragment planned (EXPLAIN, as the app's role, rolled back) for syntax, unknown objects, types and grants; PL/pgSQL blocks compiled; references to missing pages, items, lists of values, schemes and layouts; PL/pgSQL functions with `plpgsql_check` when installed. Plus the security checklist |
50
50
  | Builder search, "where used" | ✅ | Search over every page and component (names, SQL, settings, help); "Used in" under items, pages, lists of values, schemes and report layouts. No search and replace |
51
51
  | AI assistant, pages from natural language, describe tables for LLMs (26.1) | ✅ | **App Builder AI** (administrators choose the builder's AI service): SQL Workshop → AI writes SQL from a question (shown in an editor, never run automatically), explains a query or an error, and describes tables and columns for LLMs (notes, optionally `COMMENT ON`, with AI drafts from names, types and keys only); **Create pages with AI** turns a description into proposed pages that the developer edits and confirms ([chapter 3](guide/03-builder.md)). The model never sees table rows |
@@ -58,7 +58,7 @@ available dropped without anything being removed.)
58
58
  | Classic report | ✅ | `report` with `interactive: false` |
59
59
  | Interactive report | ✅ | Search, column filters, sort, rows per page, control break, aggregates (with subtotals), highlight, saved private and public reports, computed columns, group by, pivot, chart view, row selection into a page item, CSV, Excel (typed cells) and PDF download, print, reset, reflow on phones. a maximum row count (`max_rows`), natural-language control (*Ask in your own words*, 26.1) and row selection that stays across pages. Not possible: flashback queries (PostgreSQL has none; use an audit or temporal table) |
60
60
  | Interactive grid | ✅ | Inline edit, add and delete rows, lists of values, required columns, per-row errors, all-or-nothing save, signed row keys, search and paging; **aggregates** over the whole result (developer and user defined), **frozen columns**, column **reorder/resize/hide** (Actions → Columns, or drag and drop), per-user layouts and **saved grid reports** (private and public), **master-detail** (signed row selection, details refreshed in place), a **row actions menu** (edit, duplicate, delete, links) and **copy/paste** of cell ranges (tab-separated, spreadsheet compatible) ([chapter 4](guide/04-pages-and-regions.md)) |
61
- | Interactive grid views: single row view, chart view, group by | ❌ | The grid shows rows only; the interactive report has chart view and group by |
61
+ | Interactive grid views: single row view, chart view, group by | ✅ | (sprint 54) **Single row view**: one row of the search as a form with first/previous/next/last and *Add row*, from the Actions or row actions menu, saved by the grid's own process with the same checks; **group by** and **chart** set up in the Actions menu over every row of the search, as for the interactive report; `views` limits them; Save comes back to the same search, page and view ([chapter 4](guide/04-pages-and-regions.md#grid-interactive-grid)). No pivot view on grids (the interactive report has one), no editing in the single row view of columns the grid doesn't show |
62
62
  | Form (automatic row processing) | ✅ | Fetch, insert, update, delete, in a page or a modal dialog. Detects rows deleted meanwhile. (sprint 50) **Lost update detection** (APEX: *Prevent Lost Updates* and *Lock Row*): the page carries a checksum of the row's form columns (`meta.row_version`, independent of time zone and date format, as the app's role); *Save* and *Delete* lock the row and refuse when it changed meanwhile; off per form with `{"lost_update": false}` ([chapter 4](guide/04-pages-and-regions.md#form)) |
63
63
  | Charts | ✅ | Bar, column, stacked, line, area, combination (columns + lines), scatter, bubble, donut, pie, gauge, funnel, radar, **Gantt** (start/end, progress, milestones, dependencies, a today line, a time axis from hours to years), **pyramid** (area-proportional segments, or two series back to back) and **polar** (polar area); multi-series, tooltips, data table, palette checked for colour-vision deficiency; drill-down links on chart marks (checksummed, only to pages the user may open). Drawn on the server as SVG without inline styles. **Missing:** other Oracle JET types (e.g. stock, box plot, range), editing a Gantt by drag and drop |
64
64
  | Cards and metric cards (26.1 metric card template) | ✅ | Cards from SQL, with a KPI "metric" style |
@@ -142,6 +142,7 @@ available dropped without anything being removed.)
142
142
  | Session sharing between applications | ✅ | Applications with the same *session sharing group* share a sign-in: the others open without signing in again, each with its own access check and roles; signing out of one signs out of all; idle and maximum times apply ([chapter 8](guide/08-security.md#session-sharing-between-applications)). With OpenID Connect the second sign-in is silent too |
143
143
  | LDAP and SAML authentication | ✅ | LDAP / Active Directory (search + bind, StartTLS/LDAPS, groups → roles) and SAML 2.0 (signed assertions, SP metadata), next to local passwords and OpenID Connect |
144
144
  | Database accounts, HTTP-header authentication | ✅ | HTTP header variable (`header`): the user from a header set by a reverse proxy or SSO gateway, trusted only from proxy addresses in `PGKILN_AUTH_HEADER_PROXIES`, session bound to the header value, optional automatic accounts, sign-out URL; database accounts (`database`): a PostgreSQL login role and its password, checked by PostgreSQL through a short-lived connection, only listed roles or members of a role ([chapter 8](guide/08-security.md)) |
145
+ | Login page (Page Designer), Minimal page template | ✅ | (sprint 55) **Application settings → Login page**: a page of the application (*Create a login page* makes page 9999) that needs no sign-in, with page template *Minimal (no navigation)* and a **Login** region (the sign-in form: identity providers, user name and password, *Keep me signed in*, *Forgot password?*) among any other regions; `/a/<alias>/login` sends visitors there, failed sign-ins come back to it. **Forgot password?** (not built into APEX apps): with an enabled mail service, a single-use link valid for 30 minutes, the same answer whether or not an account exists, limited per address and account ([chapter 8](guide/08-security.md#the-login-page)) |
145
146
  | Custom authentication | ✅ | A PL/pgSQL function or body checks the user name and password as the app's database role, plus post-authentication code; throttling and the activity log as for other types ([chapter 8](guide/08-security.md)) |
146
147
  | Session timeout warning | ✅ | (sprint 52) A dialog before the idle time or the maximum length ends the session (default 2 minutes, per application), with *Stay signed in*; after the end, sign in and come back to the page ([chapter 8](guide/08-security.md#session-timeout-warning)) |
147
148
  | Persistent authentication ("remember me") | ✅ | Per app, 1–365 days; rotating one-time tokens, revoked on sign-out, new password, deactivation or removed access; "Sign out on all devices" |
@@ -151,7 +152,7 @@ available dropped without anything being removed.)
151
152
  | APEX | pgkiln | Notes |
152
153
  |---|---|---|
153
154
  | Universal Theme look and layout | ✅ | Header, side/top navigation, breadcrumbs, 12-column grid, region templates |
154
- | Region templates (Carousel, Hero, Inline Dialog/Popup/Drawer, Wizard Container, Title Bar, Buttons Container, Login) | 🟡 | Standard, plain and collapsible; dialog and drawer **pages**. **Missing:** the other templates, among them inline dialogs and drawers (a region opened on the same page) and a wizard progress bar |
155
+ | Region templates (Carousel, Hero, Inline Dialog/Popup/Drawer, Wizard Container, Title Bar, Buttons Container, Login) | ✅ | Standard, plain and collapsible; (sprint 57) **hero**, **title bar**, **buttons container**, **inline dialog** and **inline drawer** (opened by the dynamic action *Open region* or a link to `#R<id>`), **wizard** with the list template **wizard progress**, and the **carousel** style of the display selector; dialog and drawer **pages**; the login page's **Login** region (sprint 55) ([chapter 4](guide/04-pages-and-regions.md#layout)). An inline popup (anchored to a button) is an inline dialog |
155
156
  | Warn on unsaved changes | ✅ | (sprint 50) A page attribute: the browser asks before the user leaves the page (links, redirect buttons, other forms, closing a dialog, closing or reloading the tab) while an item differs from the value it was shown with, also after a submit that failed; submitting doesn't ask; items opt out with `{"warn_unsaved": false}`; `pgkiln.isChanged()` (APEX: `apex.page.isChanged()`); on for the form pages the wizards make. The interactive grid keeps its own check ([chapter 4](guide/04-pages-and-regions.md#warn-on-unsaved-changes)). No per-button "do not check" |
156
157
  | Responsive: phone, tablet, desktop | ✅ | Tested at 390, 768, 1024 and 1440px on every change (`npm run test:e2e`) |
157
158
  | Modal dialog pages | ✅ | Full screen on phones |
@@ -171,7 +172,6 @@ available dropped without anything being removed.)
171
172
  | Text messages (`APEX_LANG.MESSAGE`, `&APP_TEXT$…`) | ✅ | `meta.message()`, `&APP_TEXT$NAME.`, fallback to the base and primary language |
172
173
  | Language from browser, preference or session | ✅ | Browser, user preference or primary; `?lang=`; right-to-left languages |
173
174
  | Date and timestamp format masks | ✅ | Per app or per language |
174
- | Built-in runtime messages in ~34 languages | 🟡 | Twenty-two: English, Dutch, German, French, Spanish, Italian, Portuguese, Polish, Swedish, Danish, Norwegian, Finnish, Czech, Turkish, Greek, Russian, Ukrainian, Japanese, Chinese (simplified), Korean, Arabic and Hebrew (right to left), each with its date formats and currency; other languages via text messages with the same names |
175
175
  | Dynamic translations (`APEX_LANG.LANG`: translated data values, e.g. list of values entries) | ✅ | (sprint 53) Shared Components → Dynamic translations; `meta.lang(text)` in a query returns the value in the session's language (base language fallback); exported with the application |
176
176
  | Number format masks, automatic time zone | ✅ | Oracle-style number masks (`999G999G990D00`, `FML…`, `0000`, `%`, `S`/`MI`/`PR`, `EEEE`, `X`, `RN`) on report, grid and cards columns, charts and number/display items, in the language's separators with the app's currency; Automatic Time Zone (browser, My account, app or database), `timestamptz` shown in it ([chapter 14](guide/14-globalization.md)) |
177
177
 
@@ -188,7 +188,7 @@ available dropped without anything being removed.)
188
188
  | REST data sources, web credentials (26.1: OAuth refresh tokens, password flow) | ✅ | Shared Components → REST data sources: JSON endpoints with path, query, header and body parameters, a row selector, typed columns and a response cache feed reports, cards, charts, calendars, maps, trees, template components and shared lists of values as SQL over `rest`. **Write-back**: insert, update, delete and fetch operations (path and JSON body templates after the source's URL) used by forms and interactive grids. **Synchronisation** into a local table (merge on key columns with optional delete, replace, append) on demand, on a cron schedule or from SQL (`meta.request_rest_sync`), as the app's role, with a run log. Web credentials: basic, API-key header, bearer and OAuth2 client credentials, password and refresh-token grants (refresh tokens stored encrypted and rotated), secrets encrypted and write-only. Outgoing calls only to an allow-list of hosts, with SSRF checks ([chapter 19](guide/19-rest-data-sources.md)). **Missing:** XML/SOAP, the OAuth2 authorization code flow (consent in the browser) |
189
189
  | Printing, document generator (PDF) | ✅ | **Document templates**: a query (with JSON columns for lines) fills an HTML template with Mustache-style tags, drawn as PDF with a report layout; buttons and links download them. Report PDF with **report layouts** and a print stylesheet on every page. No Word/Excel templates or DOCX/XLSX output |
190
190
  | `APEX_DATA_EXPORT` (a query to CSV, XLSX, PDF, HTML or JSON from PL/SQL) | ✅ | (sprint 53) `meta.data_export(query, format, options)` returns CSV, JSON, XML or HTML as `bytea` with the caller's privileges; the download process's `{"export": …}` sends a query's rows as CSV, JSON, XML, HTML, Excel or PDF |
191
- | SQL Workshop utilities: schema comparison, generate DDL | ❌ | The object browser shows definitions; use `pg_dump --schema-only` or `migra` |
191
+ | SQL Workshop utilities: schema comparison, generate DDL | ✅ | (sprint 56) SQL Workshop → **DDL**: a schema's objects (types, sequences, tables, functions, views, constraints, indexes, triggers, RLS and policies, comments, grants) from the catalog, in an order that runs, unqualified so it also creates them in another schema. **Compare**: two schemas by their DDL (only in one, different, with a diff) and a change script that makes the target like the source (tables column by column; drops commented out for review). Also `pgkiln ddl`, `pgkiln compare` and the MCP tools `generate_ddl`, `compare_schemas` ([chapter 3](guide/03-builder.md#sql-workshop)). Two schemas of the same database only (APEX: also within one workspace) |
192
192
  | Data Reporter: self-service reports for business users (26.1) | ✅ | A **Data Reporter** region ([chapter 4](guide/04-pages-and-regions.md#data_reporter-data-reporter)): the developer offers tables and views with chosen columns, labels and format masks; signed-in users pick columns, filter, group with totals (count, sum, average, minimum, maximum), sort and chart, and save reports privately or shared with the app's users. Runs as the app's role (grants and RLS apply); works without JavaScript and fits phones. One source per report (offer a view to combine tables); no downloads from a reporter yet |
193
193
  | JSON sources, duality views (24.2) | ➖ | PostgreSQL `jsonb` works in any SQL region, form or grid source |
194
194
  | Remote servers / database links | ➖ | `postgres_fdw` or `dblink` |
@@ -212,9 +212,9 @@ available dropped without anything being removed.)
212
212
  | Developer accounts | ✅ | |
213
213
  | Instance administration, install/upgrade logs (26.1) | ✅ | Versioned migrations (`npm run db:migrate`), every run logged; Workspace utilities → **Installation** (administrators): server version, install and upgrade runs with errors, applied migrations, and warnings for migrations the database misses or the server doesn't know ([chapter 3](guide/03-builder.md)). Workspace utilities → **Instance settings**: session length and sign-in throttling (stored in the database, over the environment variables) and an overview of the server's configuration without secrets; a server whose database lacks migrations says so (503) or applies them (`MIGRATE_ON_START`). Other settings stay environment variables |
214
214
  | Debug messages | ✅ | Debug levels 1–9 per app; `meta.debug(level, text)` and `meta.debug_enabled(level)` from application SQL (APEX_DEBUG); timed entries per request (page steps, regions, processes, branches, errors, SQL notices); Activity → **Debug messages** viewer per page view with filters and the slowest step highlighted; retention 1–90 days; password item values are never recorded ([chapter 6](guide/06-processing.md)). (sprint 50) Debug for **one session** from the developer toolbar, the application staying out of debug. **Missing:** debug entries for background jobs and REST requests |
215
- | Developer toolbar, session state viewer | ✅ | (sprint 50) Developers signed in to the builder see a toolbar on the pages of their applications in the same browser: App Builder, the application, **Edit page** (Page Designer), **Session** (the session state viewer: user, roles, session, language, time zone, debug level, this page's items, application items and other pages' items; passwords never shown; clear the page's items) and **Debug** for this session only. A separate random token (cookie path `/a`, HttpOnly) of a live builder session of a developer of the application's workspace ([chapter 3](guide/03-builder.md#developer-toolbar)). **Missing:** Quick Edit (pick a component on the page), Theme Roller from the page |
215
+ | Developer toolbar, session state viewer | ✅ | (sprint 50) Developers signed in to the builder see a toolbar on the pages of their applications in the same browser: App Builder, the application, **Edit page** (Page Designer), **Session** (the session state viewer: user, roles, session, language, time zone, debug level, this page's items, application items and other pages' items; passwords never shown; clear the page's items) **Quick edit** (sprint 59: click a region, item or button to open it in the Page Designer) and **Debug** for this session only. A separate random token (cookie path `/a`, HttpOnly) of a live builder session of a developer of the application's workspace ([chapter 3](guide/03-builder.md#developer-toolbar)). **Missing:** Quick Edit (pick a component on the page), Theme Roller from the page |
216
216
  | Feedback (users send feedback from a page, developers answer) | ✅ | (sprint 51) With *Users can send feedback* on, the navigation bar's **Feedback** link opens a page for a comment, idea or problem about the page (optional rating), with the user's earlier feedback and the developers' answers; developers read, filter, set a status and answer under Application → Feedback ([chapter 3](guide/03-builder.md#feedback)). No screenshots, no e-mail to developers |
217
- | Automatic application backups, page groups | 🟡 | (sprint 51) **Backups**: before every import that replaces an application (CLI, MCP, working copy merge, restore), daily when it changed, and by hand; the newest 25 (configurable) are kept; download and restore from the builder ([chapter 3](guide/03-builder.md#backups)). **Missing:** page groups |
217
+ | Automatic application backups, page groups | ✅ | (sprint 51) **Backups**: before every import that replaces an application (CLI, MCP, working copy merge, restore), daily when it changed, and by hand; the newest 25 (configurable) are kept; download and restore from the builder ([chapter 3](guide/03-builder.md#backups)). (sprint 58) **Page groups**: Shared Components → Page groups, a page's *Page group*, the page list by group with a filter ([chapter 3](guide/03-builder.md#page-groups)) |
218
218
  | Application availability (Available, Developers only, Restricted access, Unavailable; build status *Run only*) | ✅ | (sprint 51) Available, available to developers only (a builder session in the same browser), restricted to named users, or unavailable with a message, for pages, file downloads, REST modules and PostgREST; build status **Run only** refuses builder changes as if the application were locked, while `pgkiln import --replace` still deploys. Installation settings: not exported, kept by an import ([chapter 3](guide/03-builder.md#availability-and-build-status)) |
219
219
  | Monitoring (top SQL) | ✅ | Activity per app; Top SQL per app's database role from `pg_stat_statements` (sortable, resettable) |
220
220
  | Workspaces (multi-tenant) | 🟡 | Workspaces group applications and developers: the builder shows and opens only the applications of a developer's workspaces (administrators: all), a current workspace with a switcher, new and imported applications go into it, administrators add workspaces, choose their developers and move applications ([chapter 3](guide/03-builder.md#workspaces)). **Missing:** isolation between tenants (the SQL Workshop and application code run with installation-wide rights; use separate installations), per-workspace user accounts, schemas and workspace administrators |
@@ -225,8 +225,9 @@ available dropped without anything being removed.)
225
225
  a user name and password only (no OAuth2), so Microsoft 365 after the end of basic authentication
226
226
  needs a relay, and providers such as Amazon SES or Resend only work through their SMTP gateways.
227
227
  pgkiln sends through SMTP with a password or OAuth2, Microsoft Graph, Amazon SES or a provider's
228
- HTTP API, chosen per application (sprint 50; the earlier "no e-mail" decision was reversed). There is
229
- still no built-in "forgot password" link (APEX apps don't have one out of the box either).
228
+ HTTP API, chosen per application (sprint 50; the earlier "no e-mail" decision was reversed). With a
229
+ mail service, applications can offer a built-in *Forgot password?* (sprint 55), which APEX apps
230
+ don't have out of the box.
230
231
  - **PostgREST instead of ORDS**, and no web listener at all: the pgkiln server talks to
231
232
  PostgreSQL directly.
232
233
  - **Row level security instead of VPD**, and one set of policies for the UI and the API.
@@ -288,8 +289,9 @@ report filters, App Builder AI and blueprints.
288
289
  session timeout warning~~ (done in sprint 52).
289
290
  7. ~~Data and settings: user preferences and application settings, `APEX_DATA_EXPORT`, dynamic
290
291
  translations, display image and geocoded address items~~ (done in sprint 53).
291
- 8. The last two ❌ rows: interactive grid views (single row view, chart view, group by), then schema
292
- comparison and DDL generation in SQL Workshop; then the 🟡 rows (region templates first).
292
+ 8. ~~Interactive grid views (single row view, chart view, group by)~~ (done in sprint 54).
293
+ 9. ~~Schema comparison and DDL generation in SQL Workshop~~ (done in sprint 56): no ❌ rows left.
294
+ 10. ~~Region templates~~ (done in sprint 57); ~~page groups~~ (sprint 58); ~~the help pane and Quick edit~~ (sprint 59); then the last 🟡 row: workspace isolation. (2026-10-12, owner: more built-in runtime languages are not planned; the row was removed. Other languages come from an application's own text messages.)
293
295
 
294
296
  Sources: [APEX 26.1 new features](https://docs.oracle.com/en/database/oracle/apex/26.1/htmrn/new-features.html),
295
297
  [What's new in APEX 24.2](https://apex.oracle.com/en/platform/features/whats-new-242/),
@@ -288,6 +288,16 @@ are accepted, whatever the form says.
288
288
  Give a page number, name, mode (normal or modal dialog) and breadcrumb parent, then add
289
289
  components in the page designer.
290
290
 
291
+ ### Page groups
292
+
293
+ **Shared Components → Page groups** (APEX: Page Groups) names groups of pages, e.g. *Employees*,
294
+ *Leave*, *Administration*; each page joins one with its **Page group** property (Page Designer →
295
+ Page → Appearance). The application's page list then has a *Group* column and a filter: all pages,
296
+ one group, or the pages without a group. Renaming a group renames it on its pages, deleting it takes
297
+ them out of it; the Advisor reports a page in a group that doesn't exist. Groups travel with the
298
+ application (export, import, working copies) and change nothing when it runs. The HR example puts
299
+ its pages in four groups.
300
+
291
301
  ## The page designer
292
302
 
293
303
  The page designer has three panes, as in APEX's Page Designer. From 1024 pixels wide they sit
@@ -316,7 +326,9 @@ choosing a component opens the Properties tab.
316
326
  - **Right: the property editor** for the selected component, grouped (Identification, Source,
317
327
  Layout, Security, …) with help text for each property. Type in **Filter** to show only the
318
328
  properties whose name contains the text (Escape clears it); click a group's name to fold it
319
- (remembered on this device).
329
+ (remembered on this device). Under the properties, the **Help** pane (APEX: the Help tab) shows the
330
+ property that has the focus (or the pointer): its help, the name it is stored under in exports and
331
+ application files, and a link to the guide section of the component's type.
320
332
 
321
333
  The toolbar has the page switcher (previous, a list of all pages, next), **Undo** / **Redo** of
322
334
  layout changes, the **Create** menu (region, item, button, dynamic action, computation, validation,
@@ -447,6 +459,7 @@ Toolbar). It isn't shown to anyone else, nor inside dialogs, and it can be folde
447
459
  | **App Builder** | Back to the builder |
448
460
  | **Application *n*** | The application's page in the builder |
449
461
  | **Edit page *n*** | This page in the Page Designer |
462
+ | **Quick edit** | (with JavaScript) Point at a region, item or button of the page (it is outlined) and click it: it opens selected in the Page Designer, in the builder's tab (APEX: Quick Edit). Click the button again or press Esc to stop |
450
463
  | **Session** | The **session state viewer**: the user, roles, session id, language, time zone and debug level; the values of this page's items, the application items and the items of other pages in the session. A password item's value is never shown. *Clear the items of page n* empties this page's items in the session (APEX: Clear Cache) |
451
464
  | **Debug** | Records [debug messages](06-processing.md#debug-messages) for **this session only**, at the chosen level, while the application itself stays out of debug (*Application (n)* when the application has a level of its own). *View debug* opens the recorded requests |
452
465
 
@@ -684,7 +697,9 @@ register at the provider, and has a *Test discovery* button. See
684
697
  only). The state of the [debug messages](06-processing.md#debug-messages) is shown below it,
685
698
  with a link to set their level. **Custom authentication**: the function name, or the function body, and the
686
699
  post-authentication code ([chapter 8](08-security.md#custom-authentication-a-plpgsql-function)).
687
- - **Sign-in methods**: username and password, and/or the identity providers to offer on the login page.
700
+ - **Sign-in methods**: username and password, and/or the identity providers to offer on the login page; the
701
+ application's own **Login page** (*Create a login page* makes one) and **Offer "Forgot password?"** (with a mail
702
+ service), see [chapter 8](08-security.md#the-login-page).
688
703
  - **Theme**: the **base style** (*Iris*, the default for applications created from 0.29 on, or *Standard*, pgkiln's
689
704
  look until 0.28; see [chapter 14](14-globalization.md#base-styles-iris-and-standard)), accent colour, header colour, *side* or *top* navigation (on tablets and phones the
690
705
  menu is always a drawer), a [list](04-pages-and-regions.md#list-lists) as the navigation menu
@@ -949,6 +964,25 @@ may use), a form to **issue a token** for an account, and `curl` examples. See
949
964
  save the definition to rerun it ([chapter 16](16-files.md#sql-workshop--sample-data)).
950
965
  - **AI**: SQL from a question (shown, never run), explanations of queries and errors, and
951
966
  descriptions of tables for models ([App Builder AI](#app-builder-ai)).
967
+ - **DDL** (APEX: Generate DDL): choose a schema and the kinds of objects (types and domains,
968
+ sequences, tables with their constraints and indexes, views and materialized views, functions
969
+ and procedures, triggers, row level security and policies; comments and grants) and get their
970
+ DDL from the database catalog, in an order that runs: types, sequences, PL/pgSQL functions,
971
+ tables, SQL-standard functions, views in dependency order, constraints, foreign keys, indexes,
972
+ triggers, RLS, comments, grants (including `revoke execute … from public` where a function's
973
+ privileges leave PUBLIC out). Names of the schema itself are left unqualified and the script
974
+ starts with `set search_path = <schema>`, so it also creates the same objects in another schema.
975
+ Objects of extensions are left out. Shown in the editor and downloaded as `<schema>.sql`; not run.
976
+ - **Compare** (APEX: Schema Comparison): choose a source and a target schema of this database
977
+ (a development copy and the schema it came from, say). Their objects are compared by their DDL
978
+ (the order of a table's columns is not), and listed as only in the source, only in the target,
979
+ or different, with a diff. The **change script** makes the target like the source: it creates
980
+ what only the source has, changes tables column by column (add, type, default, not null),
981
+ replaces views and functions, drops and creates constraints, indexes, triggers, policies and
982
+ grants that differ, and lists for review what it doesn't change: drops of what only the target
983
+ has (commented out), columns whose identity or generation differs, and types, domains and
984
+ sequences that differ. The same from the command line (`pgkiln ddl`, `pgkiln compare`,
985
+ [chapter 18](18-cli.md)) and for AI agents (`generate_ddl`, `compare_schemas`).
952
986
 
953
987
  Because the SQL Workshop runs as the owner, restrict who gets a developer account.
954
988
 
@@ -33,6 +33,13 @@ JavaScript, like APEX's `apex.page.isChanged()`); without JavaScript there is no
33
33
  - The create page wizards switch it on for the form pages they make; existing pages have it off
34
34
  until you switch it on.
35
35
 
36
+ ### Minimal pages
37
+
38
+ Page template **Minimal (no navigation)** (Page Designer → Page → Appearance; APEX: the page
39
+ template of the same name) shows the page without the header, the navigation menu and the
40
+ navigation bar: the title and the regions only, centred. The application's
41
+ [login page](08-security.md#the-login-page) uses it and gets the sign-in page's backdrop.
42
+
36
43
  ### Dialogs and drawers
37
44
 
38
45
  A modal page (Page Designer → Page → Appearance: *Page mode* Modal dialog) opens over the page that linked to it.
@@ -62,6 +69,18 @@ Region **templates**:
62
69
  | `standard` | A card with a header (title and buttons) and a body |
63
70
  | `plain` | No frame and no header: content only (good for KPI cards and intro text) |
64
71
  | `collapsible` | A standard card whose body can be collapsed by clicking the header |
72
+ | `hero` | A large banner: an icon (`{"icon": "users"}` in the attributes), the title, the text and the buttons (APEX: Hero) |
73
+ | `title_bar` | The title and buttons on one line over the content, without a card (APEX: Title Bar) |
74
+ | `buttons_container` | The buttons only (after any text), without a header (APEX: Buttons Container) |
75
+ | `inline_dialog` | Hidden until opened, then a dialog over the page with a close button; Esc and a click beside it close it too (APEX: Inline Dialog) |
76
+ | `inline_drawer` | The same, as a panel docked to the right edge (APEX: Inline Drawer) |
77
+ | `wizard` | A narrow, centred card for one step of a wizard; a [list](#list-lists) region with template `wizard_progress` above it shows the steps (APEX: Wizard Container) |
78
+
79
+ An inline dialog or drawer opens with the dynamic action **Open region** (and closes with **Close
80
+ region**), e.g. on the click of a button with action *Defined by dynamic action*, or with a link to
81
+ `#R<id>` (which also works without JavaScript). Items in it are part of the page: a submit sends
82
+ them along. The carousel is a style of the [display selector](#display_selector-region-display-selector)
83
+ region (`{"style": "carousel"}`). The HR example's page 44 (*Region templates*) shows them all.
65
84
 
66
85
  Every region also has `seq` (order), `condition` (a SQL boolean expression; the region renders
67
86
  only when true) and `authz` (an authorization scheme).
@@ -116,7 +135,7 @@ database only checks the shape (at most 12 names of lower case letters, digits a
116
135
  | Type | Purpose |
117
136
  |---|---|
118
137
  | [`report`](#report-interactive-report) | Read-only table from a SELECT, with search, filters, sorting, control break, aggregates, highlights, computed columns, group by, pivot and chart views, row selection, saved reports, paging and CSV/Excel/PDF download |
119
- | [`grid`](#grid-interactive-grid) | Editable table on one database table, with aggregates, frozen, movable and resizable columns, saved grid reports, a row actions menu, master-detail and copy/paste of cells |
138
+ | [`grid`](#grid-interactive-grid) | Editable table on one database table, with aggregates, frozen, movable and resizable columns, saved grid reports, a row actions menu, master-detail, copy/paste of cells, and single row, group by and chart views |
120
139
  | [`form`](#form) | Fields for one row of a table, with automatic fetch and save |
121
140
  | [`chart`](#chart) | Bar, column, stacked, line, area, combo, scatter, bubble, donut, pie, gauge, funnel, radar, Gantt, pyramid or polar chart from a SELECT, with drill-down links |
122
141
  | [`cards`](#cards) | Cards or KPI tiles from a SELECT |
@@ -134,6 +153,7 @@ database only checks the shape (at most 12 names of lower case letters, digits a
134
153
  | [`workflows`](06-processing.md#workflows) | Workflow console: the workflows the user started or administers |
135
154
  | [`search`](#search-search-region) | One search field over several sources (search configurations), results grouped per source |
136
155
  | [`url`](#url-url-region) | Another site's page (or a page of this server) in a sandboxed frame |
156
+ | `login` | The sign-in form of the application's own login page (no attributes): identity providers, user name and password, *Keep me signed in*, *Forgot password?*; see [chapter 8](08-security.md#the-login-page) |
137
157
  | [`static`](#static-and-dynamic-content) | Fixed HTML with `&ITEM.` substitutions |
138
158
  | [`dynamic`](#static-and-dynamic-content) | HTML produced by a SELECT |
139
159
 
@@ -354,6 +374,7 @@ Attributes:
354
374
  | `master` | | Makes it (or a report, chart, cards …) a **detail**: `{"item": "P27_DEPTNO", "column": "deptno"}` (below) |
355
375
  | `actions` | `true` | `false` hides the Actions menu (columns, aggregates, saved reports) |
356
376
  | `saved_reports`, `public_reports` | `true`, none | As for reports |
377
+ | `views` | all | The views users may switch to besides the grid: `["row", "group", "chart"]`; `[]` for the grid only |
357
378
 
358
379
  Cell editors follow the column type: number, date, date-time, checkbox (boolean), select list
359
380
  (with `lov`) or text.
@@ -398,6 +419,23 @@ user can only select a row the server showed them; the item is not taken from th
398
419
  submit otherwise. A detail **grid** with `master.column` fills that column with the selected value
399
420
  on its new rows (and never lets users edit it); saving new rows without a selection is refused.
400
421
 
422
+ **Views** (APEX: Single Row View, Group By, Chart). Besides the rows, a grid has three views
423
+ (`r<id>_v=row|group|chart` in the URL, kept in saved grid reports); `views` limits them:
424
+
425
+ - **Single row view**: one row at a time as a form, opened from **Actions → Single row view** or
426
+ a row's ⋮ menu. *First*, *Previous*, *Next* and *Last* move through the rows of the search in
427
+ the grid's order (`r<id>_row=N`, the position from 1); **Add row** opens an empty form
428
+ (`r<id>_row=new`). It edits the same fields as the grid and is saved by the same `grid_dml`
429
+ process, with the same checks (signed keys, required columns, lists of values); the user is
430
+ warned before leaving with unsaved changes. Give the query an `order by` (or sort the grid)
431
+ so that positions stay the same after a save, as for paging.
432
+ - **Group by** and **Chart**: set up in the Actions menu as for an
433
+ [interactive report](#report-interactive-report), over every row of the search. Once
434
+ set up, a switcher above the grid moves between *Grid* and these views.
435
+
436
+ The developer's `hidden` columns can't be grouped, charted or shown in the single row view.
437
+ After **Save** the grid comes back as it was: its search, page, sort and view.
438
+
401
439
  **Copy and paste.** Click a cell and Shift+click another to select a range; Ctrl+C copies it
402
440
  as tab-separated text (which spreadsheets paste as cells). Ctrl+V pastes such text (from a
403
441
  spreadsheet or another grid) from the focused cell on, adding rows when the grid allows inserts;
@@ -779,7 +817,8 @@ region display selector. Regions take part through their own attributes:
779
817
 
780
818
  | Key | Meaning |
781
819
  |---|---|
782
- | `style` | `tabs` (default) or `select` |
820
+ | `style` | `tabs` (default), `select`, or `carousel`: one region at a time with *Previous* and *Next* and a dot per region, without *Show all* (APEX: the Carousel template) |
821
+ | `interval` | A carousel turns to the next region every so many seconds (1 to 120); not while the pointer or the focus is in it, nor for users who prefer reduced motion |
783
822
  | `show_all` | `false` hides the *Show all* tab (default: shown) |
784
823
  | `remember` | `false`: don't remember the chosen tab for the browser session (default: remembered per page) |
785
824
 
@@ -979,7 +1018,7 @@ Attributes (the region's **Settings** in the page designer):
979
1018
  | Key | Meaning |
980
1019
  |---|---|
981
1020
  | `list` | The list's name (upper case) |
982
- | `template` | `links` (default: nested links), `badges` (a row of tiles with the badge as the value), `cards` (a card per entry with its description) or `tabs` (the top-level entries as tabs) |
1021
+ | `template` | `links` (default: nested links), `badges` (a row of tiles with the badge as the value), `cards` (a card per entry with its description), `tabs` (the top-level entries as tabs) or `wizard_progress` (numbered steps: the entry of the current page is the current step, the ones before it are done and link back; APEX: Wizard Progress) |
983
1022
 
984
1023
  The HR example's page 31 (Shortcuts) shows a static list with each template (with a badge from an
985
1024
  item, child entries, a manager-only entry and one of an excluded build option) and a department
@@ -47,11 +47,52 @@ The builder and the runtime cover what APEX offers for its accounts:
47
47
  The `meta.set_password`/`expire`/`unexpire` functions are owner-only. Grant them to an app role if
48
48
  you want to build user administration pages inside an application.
49
49
 
50
- There is no self-service "forgot password" link (APEX apps don't have one out of the box either;
51
- an application can build one with [e-mail](06-processing.md#sending-e-mail) and its own token
52
- table). A user who forgot their password asks an administrator, who
53
- sets a temporary one under **Users → account → Set password**, with *Require change of password
54
- on first use* ticked (the default).
50
+ A user who forgot their password asks an administrator, who sets a temporary one under
51
+ **Users → account → Set password**, with *Require change of password on first use* ticked (the
52
+ default), or uses **Forgot password?** when the application offers it (below).
53
+
54
+ ### Forgot password
55
+
56
+ With **Application settings → Sign-in methods → Offer "Forgot password?"** the sign-in page (the
57
+ built-in one or the application's [own login page](#the-login-page)) has a *Forgot password?* link
58
+ (APEX apps don't have one out of the box). It needs an enabled [mail service](06-processing.md#sending-e-mail)
59
+ with a From address for the application; without one the link isn't shown. It is for passwords
60
+ of the user directory only: not for LDAP, single sign-on, database accounts or custom
61
+ authentication.
62
+
63
+ 1. The user types their user name or e-mail address. The answer is always the same, whether or
64
+ not an account matched, so the page doesn't tell who has an account.
65
+ 2. An active account with a password and an e-mail address that may use the application gets an
66
+ e-mail (in the user's language) with a link to `/a/<alias>/password/reset?token=…`, built from
67
+ `PUBLIC_URL`, never from the request's `Host` header.
68
+ 3. The link works **once**, for **30 minutes**, in this application only. Opening it moves the
69
+ token into the session and out of the address bar; the user chooses a new password (the
70
+ [password policy](#passwords-and-my-account) applies).
71
+ 4. The new password ends every session and *Keep me signed in* token of the account, and makes
72
+ the account's other open links useless.
73
+
74
+ Only a SHA-256 hash of each token is stored (`meta.password_reset`, owner only). Requests are
75
+ limited to 5 per address in 15 minutes and 3 mails per account per hour; they count towards the
76
+ application's daily mail limit and show in the activity log (`password_reset_request`,
77
+ `password_reset`).
78
+
79
+ ### The login page
80
+
81
+ `/a/<alias>/login` shows pgkiln's sign-in page: the application's name, the sign-in methods and,
82
+ when the application has several languages, a language picker. To design your own (APEX: the
83
+ login page, usually page 9999), choose **Application settings → Sign-in methods → Create a login
84
+ page**: it adds page 9999 (or the next free number) that doesn't require authentication, with
85
+ page template *Minimal (no navigation)* and a **Login** region, and makes it the application's
86
+ **Login page**. From then on `/a/<alias>/login` (and every page that needs a signed-in user)
87
+ sends visitors there.
88
+
89
+ Edit it like any page: add static content, images, lists of links or any other region around the
90
+ Login region, which is the sign-in form (identity providers, user name and password, *Keep me
91
+ signed in*, *Forgot password?*). The form still posts to `/a/<alias>/login`, so throttling, the
92
+ CSRF check and every sign-in method work as on the built-in page; a failed sign-in comes back to
93
+ the login page with its message and the user name. A login page that requires authentication,
94
+ or doesn't exist, is ignored (the built-in page shows) and the Advisor reports it; so does a
95
+ login page without a Login region.
55
96
 
56
97
  With single sign-on, password changes happen at the identity provider; My account says so.
57
98
 
@@ -47,6 +47,7 @@ What's missing is listed in the [feature parity matrix](../apex-feature-parity.m
47
47
  | Rich Text Editor, Markdown Editor, Star Rating, Combobox, QR Code | Item types `richtext` (sanitised HTML), `markdown`, `rating`, `combobox` (colon-separated), `qrcode`; plus `daterange` (`from:to`) and `{"reveal": true}` on password items ([chapter 5](05-items.md)) |
48
48
  | Data Generator (sample data for development, 26.1) | SQL Workshop → **Sample Data**: generators proposed per column, foreign keys to existing parent rows, a seed, preview, insert in one transaction (parents first), SQL/CSV download, saved definitions ([chapter 16](16-files.md#sql-workshop--sample-data)) |
49
49
  | Data Workshop (load and unload: CSV, Excel, JSON, XML) / Data Load Definition, *Execute Data Load* process | SQL Workshop → Load Data and **Unload Data** (CSV, JSON, Excel, XML; [chapter 16](16-files.md#sql-workshop--unload-data)); Shared Components → Data load definitions; process type `data_load` with `"definition"` ([chapter 16](16-files.md#data-loading)) |
50
+ | SQL Workshop → Utilities → Generate DDL, Schema Comparison | SQL Workshop → **DDL** and **Compare**: a schema's DDL in an order that runs; two schemas compared by their DDL with a change script; also `pgkiln ddl` and `pgkiln compare` ([chapter 3](03-builder.md#sql-workshop)) |
50
51
  | SQL Workshop → SQL Scripts, Quick SQL, Query Builder | The same names in the SQL Workshop: saved scripts with a result per statement and a run history, shorthand → PostgreSQL DDL, a SELECT built on a canvas of tables, joined by foreign keys or columns you connect, with column functions and grouping ([chapter 3](03-builder.md#sql-workshop)) |
51
52
  | Interactive report *Download → PDF*, printing | Actions → Download PDF, Print ([chapter 16](16-files.md#printing)) |
52
53
  | Pagination *Row Ranges X to Y*, *Maximum Row Count*, region *Lazy Loading*, *Server Cache* | `"pagination": "range"`, `max_rows`, `"lazy": true`, `"cache": {"scope", "seconds"}` ([large tables](04-pages-and-regions.md#large-tables)) |
@@ -97,7 +98,9 @@ in to a second app is then silent via the identity provider's session. See
97
98
  Active Directory** passwords work the same way (groups → roles), and *Keep me signed in* matches
98
99
  APEX's persistent authentication. **Database accounts** sign in with PostgreSQL login roles, and
99
100
  **custom authentication** calls your own PL/pgSQL function (APEX: a custom PL/SQL scheme), see
100
- [chapter 8](08-security.md#custom-authentication-a-plpgsql-function).
101
+ [chapter 8](08-security.md#custom-authentication-a-plpgsql-function). The **login page** (APEX: page 9999 with
102
+ the Login region template) is a page you design in the Page Designer around a **Login** region, and
103
+ **Forgot password?** is built in (APEX apps build their own), see [chapter 8](08-security.md#the-login-page).
101
104
 
102
105
  ## ORDS and PostgREST
103
106
 
@@ -34,6 +34,8 @@ src/
34
34
  app.ts / server.ts Fastify setup / entry point
35
35
  db.ts the two pools, appTx() (SET LOCAL ROLE + pgkiln.* settings, NOTICEs to the debug log), savepoints
36
36
  security.ts URL checksums, password policy, security headers (CSP nonce), throttling limits
37
+ ddl.ts Generate DDL and Schema Comparison: readSchema (catalog → one DDL per object, unqualified), ddlScript (order), compare, changeScript
38
+ static-version.ts the version of app.css, app.js, icons.svg and sw.js (?v= in their URLs, the service worker version): content hash, looked at again when a file changes
37
39
  session.ts sessions (hashed tokens), activity log, login throttling
38
40
  sso.ts OpenID Connect: discovery, sign-in flow, ID token checks, account linking
39
41
  saml.ts SAML 2.0 sign-in (node-saml): AuthnRequest, response checks, SP metadata
@@ -99,6 +101,8 @@ src/
99
101
  icons.ts icon helper (sprite in public/icons.svg)
100
102
  runtime/
101
103
  routes.ts HTTP handlers: show, submit, dynamic actions, cascading lists, login
104
+ signin.ts the sign-in form (built-in page and the login region of an application's own login page), safeNext, passwordResetAvailable
105
+ password-reset.ts Forgot password: request (same answer either way), the link (token into the session), the new password
102
106
  context.ts PageContext, dbg()/timed() debug helpers, bind values, substitutions, public error messages, writeOut (streamed responses with back pressure)
103
107
  authz.ts authorization schemes, conditions, visibility (menu requests count as buttons)
104
108
  engine.ts form fetch, validations, processes (conditions, execution chains, queueing background chains; web requests queued by an sql process are made right after it), application processes
@@ -109,7 +113,7 @@ src/
109
113
  style (user choice, default), themeCss() (only hex values and constants reach the CSS)
110
114
  template-options.ts template options: the fixed CSS class list per region and button, templateClasses() (unknown values ignored)
111
115
  regions.ts region shell + chart (drill-down links, gauge settings)/cards/dynamic dispatch with row limits, lazy placeholder and cache, buttons (menu buttons, badges)
112
- report.ts, report-views.ts (group by, pivot, chart), compute.ts (computed column expressions), grid.ts (aggregates, row actions, Actions menu, layoutFromForm), grid-layout.ts (column layouts: clean, arrange, per user), master-detail.ts (signed master row selection, details), facets.ts, items.ts
116
+ report.ts, report-views.ts (group by, pivot, chart), compute.ts (computed column expressions), grid.ts (aggregates, row actions, Actions menu, single row view, layoutFromForm), grid-layout.ts (column layouts: clean, arrange, per user), master-detail.ts (signed master row selection, details), facets.ts, items.ts
113
117
  (report.ts: paging with row ranges and max_rows, keyset paging (keysetPlan, seekCondition, signed r<id>_k), pagerNav, streamed CSV/Excel downloads with a cursor;
114
118
  items.ts: lovOptions, searchLov/lovLookup for popup LOVs, served by POST /a/:alias/:page/lov/:item/search in routes.ts)
115
119
  region-cache.ts region caching (keys per scope, CSRF placeholder, invalidation on submit) and lazy regions (GET …/region/:id is in routes.ts)
@@ -206,6 +210,8 @@ src/
206
210
  region-settings.ts page designer: settings forms for grid, chart (gauge, drill-down), cards, calendar (views, create, drag and drop), facets, smart filters, display selector, list
207
211
  search.ts app search, "where used" (appEntries, search, whereUsed, usedInPanel)
208
212
  advisor.ts Advisor: EXPLAIN every SQL fragment, reference checks, plpgsql_check
213
+ ddl-tools.ts SQL Workshop → DDL and Compare (src/ddl.ts)
214
+ login-page.ts Application settings → Login page and Forgot password; Create a login page (page 9999)
209
215
  top-sql.ts Top SQL per app role from pg_stat_statements
210
216
  diagnostics.ts Activity → Debug messages (level, list, one request's entries, purge); Workspace utilities →
211
217
  Installation (version, install/upgrade runs, applied and missing migrations; administrators)
@@ -27,7 +27,9 @@ Everything is per application, under its own address: `/a/<alias>/manifest.webma
27
27
  ## Offline
28
28
 
29
29
  - **The app shell** (pgkiln's CSS, script and icons) and an offline page are stored when the app is
30
- installed, so the app always opens.
30
+ installed, so the app always opens. Pages ask for these files with a version in the URL
31
+ (`/static/app.css?v=…`, from the files' contents); when pgkiln is upgraded, or a file changes,
32
+ devices fetch the new one at the next page load.
31
33
  - **Pages** are fetched from the network first. Without a connection, a page the user opened before
32
34
  comes from the device (when *Keep visited pages* is on); otherwise the offline page appears,
33
35
  listing the pages that are on the device.
@@ -37,6 +37,8 @@ any (see [what is not exported](03-builder.md#export-format)).
37
37
  | `pgkiln export <alias> [--format json\|dir\|text] [--out <path>]` | `json` (default): the `pgkiln/2` document with sorted keys, to `--out` or standard output. `dir`: a directory (default `./<alias>`), see below. `text`: the same directory in YAML with the code inline ([text files](#text-files-apexlang)) |
38
38
  | `pgkiln import <path> [--alias <alias>] [--replace] [--check [--force] \| --dry-run]` | Imports a JSON export, an application directory or a `.zip` of one. `--alias` gives the copy another alias. `--replace` updates the application with that alias in place (after a [backup](03-builder.md#backups)). `--check` checks the application before it commits, `--dry-run` only checks ([below](#checking-before-an-import)) |
39
39
  | `pgkiln diff <alias> <path> [--name-only \| --quiet]` | What differs between the application in the database and a directory (or JSON file, or zip) |
40
+ | `pgkiln ddl <schema> [--no-comments] [--no-grants] [--out <file>]` | The DDL of a schema's objects, in an order that runs (as SQL Workshop → DDL, [chapter 3](03-builder.md#sql-workshop)) |
41
+ | `pgkiln compare <source> <target> [--script]` | Compares two schemas: `+` only in the source, `-` only in the target, `~` different; exit code 1 when they differ. `--script` writes the script that makes the target like the source (drops commented out); nothing is run |
40
42
  | `pgkiln mcp` | An MCP server on standard input/output for AI coding agents, see [chapter 20](20-ai-agents.md) |
41
43
  | `pgkiln plugin build <dir> [-o <file>]` | Builds a plug-in file (`pgkiln-plugin/2`) from a source directory, see [plug-ins](04-pages-and-regions.md#plug-ins-with-their-own-code) |
42
44
  | `pgkiln plugin install <file\|dir> --app <alias> [--replace]` | Adds a plug-in (file or source directory) to an application; its install SQL is not run |
@@ -48,6 +48,8 @@ directory the agent started the server in (the project).
48
48
  | `get_page` | every component of one page as YAML, SQL inline | no |
49
49
  | `read_app_files` | component files by path or prefix (`shared/lovs/`, `navigation.yaml`, …) | no |
50
50
  | `describe_schema` | schemas with tables, views and functions; or one table with columns, constraints, indexes, RLS policies and triggers | no |
51
+ | `generate_ddl` | the DDL of a schema's objects, in an order that runs: a start for a migration script | no |
52
+ | `compare_schemas` | the differences between two schemas and a script that makes the target like the source (not run) | no |
51
53
  | `run_query` | one SQL statement, read-only, rows as JSON | no |
52
54
  | `search_docs` | searches this user guide, the parity matrix and SECURITY.md | no |
53
55
  | `recent_errors` | the latest errors and refused requests from the activity log | no |
@@ -0,0 +1,67 @@
1
+ -- =====================================================================
2
+ -- HR example, part 54: region templates (migration 088;
3
+ -- docs/guide/04-pages-and-regions.md "Region templates")
4
+ --
5
+ -- Page 44 "Region templates" (Administration):
6
+ -- - a hero region (an icon, the title, text and a button);
7
+ -- - a title bar with buttons; a buttons container;
8
+ -- - "Leave policy" opens an inline dialog and "Help" an inline drawer
9
+ -- (dynamic actions "Open region"; a link to #R<id> opens them too);
10
+ -- - a carousel (a display selector with style carousel) over three
11
+ -- regions, turning every 8 seconds;
12
+ -- - the steps of onboarding as a wizard progress list above a wizard
13
+ -- region.
14
+ -- =====================================================================
15
+
16
+ insert into meta.page (app_id, page_no, name, title, parent_page)
17
+ select id, 44, 'Region templates', 'Region templates', 1 from meta.app where alias = 'hr';
18
+
19
+ insert into meta.list (app_id, name, type, description)
20
+ select id, 'HR_ONBOARDING_STEPS', 'static', 'The steps of onboarding (a wizard progress list on page 44)' from meta.app where alias = 'hr';
21
+
22
+ insert into meta.list_entry (app_id, list_name, seq, label, target_page)
23
+ select a.id, 'HR_ONBOARDING_STEPS', e.seq, e.label, e.page
24
+ from meta.app a, (values (10, 'Personal details', 44), (20, 'Contract', 3), (30, 'Equipment', 28), (40, 'Done', 1)) as e (seq, label, page)
25
+ where a.alias = 'hr';
26
+
27
+ insert into meta.region (page_id, seq, title, type, columns, template, source, config)
28
+ select p.id, r.seq, r.title, r.type, 12, r.template, r.source, r.config::jsonb
29
+ from meta.page p join meta.app a on a.id = p.app_id, (values
30
+ (10, 'Welcome to HR', 'static', 'hero',
31
+ '<p>Everything about the people in the company: employees, departments, leave and reviews.</p>', '{"icon": "users"}'),
32
+ (20, 'Employees this month', 'static', 'title_bar', '<p class="muted">Hires and departures of the current month.</p>', '{}'),
33
+ (30, 'Actions', 'static', 'buttons_container', null, '{}'),
34
+ (40, 'Leave policy', 'static', 'inline_dialog',
35
+ '<p>Everyone has 25 days of leave a year. Ask your manager at least two weeks ahead; approvals come by e-mail.</p>', '{}'),
36
+ (50, 'Help', 'static', 'inline_drawer',
37
+ '<p>This page shows the region templates: hero, title bar, buttons container, inline dialog and drawer, carousel and wizard.</p>', '{}'),
38
+ (60, 'Highlights', 'display_selector', 'plain', null, '{"style": "carousel", "interval": 8, "show_all": false}'),
39
+ (61, 'New colleagues', 'static', 'standard', '<p>Three people joined the Research department this month.</p>', '{"display_selector": true}'),
40
+ (62, 'Anniversaries', 'static', 'standard', '<p>KING celebrates 45 years with the company.</p>', '{"display_selector": true}'),
41
+ (63, 'Open positions', 'static', 'standard', '<p>Two analysts and a clerk: see the intranet.</p>', '{"display_selector": true}'),
42
+ (70, 'Onboarding steps', 'list', 'plain', null, '{"list": "HR_ONBOARDING_STEPS", "template": "wizard_progress"}'),
43
+ (80, 'Personal details', 'static', 'wizard', '<p>Step 1: check your name, address and bank account in My account.</p>', '{}')
44
+ ) as r (seq, title, type, template, source, config)
45
+ where a.alias = 'hr' and p.page_no = 44;
46
+
47
+ insert into meta.button (page_id, region_id, seq, name, label, action, hot, target_page)
48
+ select p.id, (select r.id from meta.region r where r.page_id = p.id and r.title = b.region), b.seq, b.name, b.label, b.action, b.hot, b.target
49
+ from meta.page p join meta.app a on a.id = p.app_id, (values
50
+ ('Welcome to HR', 10, 'EMPLOYEES', 'See the employees', 'redirect', true, 2),
51
+ ('Employees this month', 20, 'POLICY', 'Leave policy', 'da', false, null),
52
+ ('Actions', 30, 'HELP', 'Help', 'da', false, null)
53
+ ) as b (region, seq, name, label, action, hot, target)
54
+ where a.alias = 'hr' and p.page_no = 44;
55
+
56
+ insert into meta.dynamic_action (page_id, seq, name, event, trigger_element, action, affected_region_id)
57
+ select p.id, d.seq, d.name, 'click', d.button, 'open_region', (select r.id from meta.region r where r.page_id = p.id and r.title = d.region)
58
+ from meta.page p join meta.app a on a.id = p.app_id, (values
59
+ (10, 'Open the leave policy', 'POLICY', 'Leave policy'),
60
+ (20, 'Open the help', 'HELP', 'Help')
61
+ ) as d (seq, name, button, region)
62
+ where a.alias = 'hr' and p.page_no = 44;
63
+
64
+ insert into meta.nav_entry (app_id, parent_id, seq, label, icon, target_page)
65
+ select a.id, n.id, 50, 'Region templates', 'layers', 44
66
+ from meta.app a join meta.nav_entry n on n.app_id = a.id and n.label = 'Administration' and n.parent_id is null
67
+ where a.alias = 'hr';