pgkiln 0.84.0 → 0.86.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 (105) hide show
  1. package/db/migrations/155_mail_available.sql +23 -0
  2. package/docs/apex-feature-parity.md +2 -2
  3. package/docs/guide/03-builder.md +14 -5
  4. package/docs/guide/04-pages-and-regions.md +1 -1
  5. package/docs/guide/06-processing.md +7 -3
  6. package/docs/guide/07-dynamic-actions.md +3 -3
  7. package/docs/guide/09-reference.md +1 -0
  8. package/docs/guide/12-development.md +10 -1
  9. package/examples/gallery/README.md +23 -6
  10. package/examples/gallery/gallery.json +4 -0
  11. package/examples/gallery/samples/sample-approvals.sql +102 -11
  12. package/examples/gallery/samples/sample-calendar.sql +40 -5
  13. package/examples/gallery/samples/sample-dynamic-actions.sql +237 -9
  14. package/examples/gallery/samples/sample-grids.sql +35 -3
  15. package/examples/gallery/samples/sample-maps.sql +65 -7
  16. package/examples/gallery/samples/sample-processes.sql +466 -0
  17. package/examples/gallery/samples/sample-validations.sql +407 -0
  18. package/examples/gallery/samples/ux-patterns.sql +154 -14
  19. package/examples/hr/README.md +2 -0
  20. package/examples/hr/hr_80_notifications.sql +125 -0
  21. package/examples/hr/hr_81_vector_search_type.sql +33 -0
  22. package/package.json +1 -1
  23. package/public/app.css +8 -1
  24. package/public/app.js +28 -9
  25. package/src/app.ts +9 -0
  26. package/src/builder/ai-agents.ts +86 -85
  27. package/src/builder/ai-builder.ts +30 -30
  28. package/src/builder/ai.ts +93 -92
  29. package/src/builder/api.ts +47 -47
  30. package/src/builder/app-groups.ts +33 -32
  31. package/src/builder/appfromfile.ts +57 -58
  32. package/src/builder/appsheets.ts +33 -32
  33. package/src/builder/appwizard.ts +65 -65
  34. package/src/builder/arrange.ts +23 -22
  35. package/src/builder/assistant.ts +39 -38
  36. package/src/builder/automations.ts +32 -31
  37. package/src/builder/availability.ts +24 -24
  38. package/src/builder/backups.ts +30 -31
  39. package/src/builder/blueprints.ts +62 -61
  40. package/src/builder/create-page.ts +52 -50
  41. package/src/builder/cross-app.ts +37 -35
  42. package/src/builder/dataload.ts +2 -2
  43. package/src/builder/datasets.ts +107 -106
  44. package/src/builder/dependencies.ts +20 -19
  45. package/src/builder/designer.ts +36 -36
  46. package/src/builder/diagnostics.ts +58 -57
  47. package/src/builder/features.ts +39 -35
  48. package/src/builder/feedback.ts +23 -20
  49. package/src/builder/find-workspace.ts +28 -24
  50. package/src/builder/form-designer.ts +36 -35
  51. package/src/builder/gallery.ts +25 -29
  52. package/src/builder/globalization.ts +50 -49
  53. package/src/builder/i18n/de.ts +3453 -0
  54. package/src/builder/i18n/en.ts +3453 -0
  55. package/src/builder/i18n/es.ts +3453 -0
  56. package/src/builder/i18n/fr.ts +3453 -0
  57. package/src/builder/i18n/it.ts +3453 -0
  58. package/src/builder/i18n/ja.ts +3453 -0
  59. package/src/builder/i18n/ko.ts +3453 -0
  60. package/src/builder/i18n/nl.ts +3453 -0
  61. package/src/builder/i18n/pt.ts +3453 -0
  62. package/src/builder/i18n/zh-cn.ts +3453 -0
  63. package/src/builder/i18n/zh-tw.ts +3453 -0
  64. package/src/builder/i18n.ts +17 -3
  65. package/src/builder/json-sources.ts +63 -62
  66. package/src/builder/layouts.ts +12 -11
  67. package/src/builder/locks.ts +29 -28
  68. package/src/builder/login-page.ts +26 -25
  69. package/src/builder/mail.ts +148 -147
  70. package/src/builder/newapp.ts +15 -12
  71. package/src/builder/plugins.ts +47 -44
  72. package/src/builder/process-jobs.ts +11 -10
  73. package/src/builder/pwa.ts +22 -21
  74. package/src/builder/remote-databases.ts +55 -56
  75. package/src/builder/report-settings.ts +1 -1
  76. package/src/builder/reporter.ts +43 -42
  77. package/src/builder/rest-catalogs.ts +87 -86
  78. package/src/builder/rest.ts +9 -8
  79. package/src/builder/routes.ts +27 -27
  80. package/src/builder/search.ts +14 -13
  81. package/src/builder/static-files.ts +31 -32
  82. package/src/builder/subscriptions.ts +47 -45
  83. package/src/builder/supporting.ts +23 -18
  84. package/src/builder/team.ts +179 -179
  85. package/src/builder/telemetry.ts +59 -62
  86. package/src/builder/templates.ts +66 -65
  87. package/src/builder/themeroller.ts +60 -63
  88. package/src/builder/ui-defaults.ts +21 -20
  89. package/src/builder/ui.ts +2 -1
  90. package/src/builder/upgrade.ts +25 -24
  91. package/src/builder/utilities.ts +48 -47
  92. package/src/builder/vector-providers.ts +67 -66
  93. package/src/builder/websources.ts +43 -42
  94. package/src/builder/wizards.ts +95 -89
  95. package/src/builder/workflow-migrate.ts +30 -31
  96. package/src/builder/workflows.ts +40 -39
  97. package/src/builder/workingcopies.ts +41 -49
  98. package/src/builder/workspace-backups.ts +21 -20
  99. package/src/builder/workspace-mail.ts +17 -16
  100. package/src/builder/workspace-resources.ts +104 -112
  101. package/src/builder/workspace-transfer.ts +34 -26
  102. package/src/runtime/engine.ts +6 -3
  103. package/src/runtime/lists.ts +2 -2
  104. package/src/runtime/push.ts +7 -1
  105. package/src/runtime/regions.ts +9 -4
@@ -0,0 +1,23 @@
1
+ -- 155: meta.mail_available() (sprint 166)
2
+ --
3
+ -- A Send E-Mail process (and meta.send_mail) raises an error when the application has
4
+ -- no mail service, which rolls back the whole submit; until now application code had
5
+ -- no way to ask first (meta.mail_caller is internal). meta.mail_available() answers
6
+ -- whether the current application may send e-mail: it is called from application code
7
+ -- (meta.app_id() set), it has an enabled mail service, and that service has a From
8
+ -- address (the application's own or the service's default). Use it as a process's
9
+ -- condition: condition_type sql, condition_expr meta.mail_available(). It says nothing
10
+ -- about other applications and never raises. Found by the App Gallery's Sample Processes.
11
+
12
+ create function meta.mail_available() returns boolean
13
+ language sql stable security definer set search_path = meta, pg_catalog as $$
14
+ select meta.app_id() is not null and exists (
15
+ select 1
16
+ from meta.mail_service s
17
+ left join meta.app_mail_service x on x.app_id = meta.app_id() and x.service_id = s.id
18
+ where s.id = meta.mail_service_for_app(meta.app_id()) and s.enabled
19
+ and coalesce(x.from_address, nullif(s.settings->>'default_from', '')) is not null)
20
+ $$;
21
+ revoke all on function meta.mail_available() from public;
22
+ grant execute on function meta.mail_available() to public;
23
+ comment on function meta.mail_available() is 'Whether the current application may send e-mail: an enabled mail service with a From address (155)';
@@ -7,7 +7,7 @@ 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-11-06 against **APEX 26.2** (sprint 165: navigation menu badges from SQL, the notification bell and live badges; sprint 162: the SQL Workshop tools and the region and report settings in the eleven builder languages (CD-8); sprint 161: component events of grids, calendars, maps and trees (CD-3); sprint 160: the Workflow Diagram region, an instance's steps with the reached, current and failed ones marked (CD-7); sprint 159: map layers Lines, Polygons and Extruded Polygons with fill and line styles per layer or per row (CD-6); sprint 158: the item types Image Upload, Text Field with autocomplete, Percent Graph and Display Map (CD-5); sprint 157: the process types Close Dialog, Clear Session State, Reset Pagination, User Preferences, Server Side Geocoding, Print Report, Human Task – Create / – Manage and Form – Initialization (CD-4); sprint 156: dynamic action events double click, key down / press, mouse enter / leave, select, resize, scroll, page unload, before refresh and facets change, greater / less and not-in-list conditions, and the actions Cancel Event, Set Style, Collapse / Expand Tree, Show AI Assistant, Trigger Geocoding and Open report dialog (CD-3); sprint 155: APEX's validation types, with an authorization scheme, Always execute and the error's display location (CD-1); sprint 154: one catalogue of server-side condition types for every component, shown in words in the Page Designer (CD-2); sprint 153: Database users in the eleven builder languages (WS-7 leftover); sprint 152: Workspace utilities, the dashboard, Mail queue, Network access, Instance settings and LDAP directories in the eleven builder languages (WS-7 leftover); sprint 151: vector providers with a model in the database, PostgresML (APEX's ONNX models, AP-1 leftover); sprint 150: remote databases, another PostgreSQL database's tables as foreign tables the applications query (REST Enabled SQL, AP-7 leftover); sprint 149: running workflow instances inside parallel branches migrate to a newer version (WS-6 leftover); sprint 148: the AI assistant streams its answers as the model writes them (WS-4 leftover); sprint 147: `pgkiln advise --offline` checks an export's files without a database (AP-10 leftover); sprint 146: the Advisor checks JSON sources' views against their data profile (AP-8 leftover); sprint 145: the texts that offered AI with "Claude or OpenAI" name all four providers: Claude, OpenAI, Gemini and OpenAI-compatible services (AP-11); sprint 144: `pgkiln advise` for CI with text, JSON and SARIF output (APEXlang static analysis / SQLcl CodeScan), security checks in the Advisor, and working copies and locks from the command line and MCP (the Working Copy APIs) (AP-10); sprint 143: the interactive report's 26.2 dialogs: *is one of* / *is not one of* filters with the column's values and counts, *is between* two values (dates with the date picker in the application's format), relative periods on date columns, and the column order by drag and drop or arrow buttons, followed by downloads and the PDF (AP-9); sprint 142: JSON sources with a data profile and updatable views whose arrays are rows, document views of a table with its children (APEX's duality views), JSON path columns in reports (AP-8); sprint 141: static workspace files (`#WORKSPACE_FILES#`), remote servers for REST data sources, catalogs and AI services (an environment variable per environment), and workspace-level web credentials (AP-7); sprint 140: the items Shuttle (ordered), Select One and Select Many, the regions Classic Report (report templates, pagination types), Breadcrumb and Help Text with a page help text, and a [mapping of every APEX item and region type](#item-and-region-types-one-by-one) (AP-4); sprint 139: OpenTelemetry, traces with a span per SQL statement, web call, AI request and tool call, logs, metrics and `/metrics` for Prometheus, browser spans relayed by pgkiln, per workspace off or its own collector (AP-6); sprint 138: an application's Utilities tab with a dashboard, database object dependencies, change history per component, Upgrade application, UI defaults (APEX's Attribute Dictionary), application and page checksums and an icon browser (AP-5); sprint 137: Create page as a grid of page types with previews, the page types interactive report, smart filters, search page, data loading, tree, timeline, media list, content row, comments, dashboard, wizard, unified task list and workflow console, a Feature tab with nine features that install once, and Create page as copy with shared components mapped or copied (AP-3); sprint 136: vector providers (an AI service with an embedding model or a SQL function), `meta.embed`, *Add vector column* in Table Properties with an HNSW index and a queue that keeps embeddings current, search types vector and hybrid (reciprocal rank fusion with full-text) and a Retrieve (RAG) tool for AI agents, all as the app's role through RLS, on pgvector (AP-1); sprint 135: full-text search configurations, APEX's Oracle Text search type on PostgreSQL full-text search with stemming, ranking, highlights, *Did you mean* and *Add full-text search* in Table Properties (AP-2); sprint 134: the builder also in Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어, APEX's ten builder languages plus Nederlands (SEC-5); sprints 121, 123–125: the builder in Deutsch, English, Español, Français, Nederlands and Português, step by step: the frame, sign-in, Workspace home, App Builder, Page Designer menus, the SQL Workshop's home, SQL Worksheet, Object Browser and Table Properties, Shared Components, application settings, users, identity providers, developers and workspaces (WS-7); sprint 122: *Ask in your own words* sets faceted search and smart filter facets, smart filters read a typed phrase (WS-5), and Sample Maps, Sample Approvals, Sample Data Loading and Sample Files in the App Gallery (WS-8); sprint 120: the App Gallery's single-topic sample apps (charts, cards, calendar, interactive grids, dynamic actions, reporting), the UX Pattern Catalog and a Utility Apps tab with Lookup Lists, Release Notes and Announcements (WS-8); sprint 119: data security per table, a roles × columns matrix and masked values per application role in a masking view, the same identity for pages, AI tools, REST, AutoREST and MCP (WS-13); sprint 118: Administration → Mail queue with delivery per hour and per workspace, the slowest provider calls and failures with Retry and Purge, a workspace's own mail service, and workspace network access lists that narrow the installation's allow-list (WS-9); sprint 117: Pillar Light and Pillar Dark navigation appearances with a header strip, clearer navigation tree states, subtle colour utilities, RTL; sprint 116: the comparison moved from 26.1 to 26.2, with a section for the 26.2 workspace items WS-1 … WS-13 and OCI managed identities; the App Builder list with Updated by, working copies and the lock; `pgkiln import --only`, a file-level import; stale rows on facet menus and blueprints fixed; sprint 115: popup LOVs that load on scroll, Wait Popup dynamic actions and dynamic actions on menu entries; sprint 114: Workflow 26.2 with custom task outcomes, task events and notifications, Send E-Mail and draft steps, migrating running instances and the diagram as SVG / PNG; sprint 113: Team Development with issues, labels, milestones, templates, a board and a set-up wizard; sprint 112: AI interactive reports with chips, Undo, computed columns and a phrase parser that needs no AI service; sprint 111: AI Agents with tools as a shared component, a Navigate tool with checksummed URLs, Gemini and OpenAI-compatible services; sprint 110: Data Reporter as a workspace tool with datasets, reporting applications, editors and viewers, published reports with stable URLs and pins; sprint 109: the Workspace home above the App Builder and SQL Workshop, with a summary, top applications, users and developers, and an optional release check; sprint 108: the code editor's syntax colours in the builder's light and dark themes, read-only SQL highlighted, the Data Modeler in dark mode; sprint 107: a transaction mode in the SQL Worksheet with Commit and Rollback; DA-18: JavaScript (MLE) not planned, plv8 where installed; sprint 106: the change log of DDL change sets with Flyway, Liquibase and SQL downloads; sprint 104: RESTful Services modules, templates and handlers with PL/pgSQL and media handlers, privileges, OpenAPI and Try it; sprint 103: Schema Export / Import with pg_dump and pg_restore; sprint 102: the SQL Monitor with live sessions, Top SQL and a statement's plan; sprint 101: Scheduling of pg_cron jobs with a schedule builder, run now and run history; sprint 100: RESTful Services, tables and views published as REST endpoints with paging, filters, keys and OpenAPI; sprint 99: Administration → Database Users for PostgreSQL roles; sprint 98: the Data Modeler with relational diagrams, DDL and a data dictionary; sprint 97: charts of a query in the worksheet, saved charts and their dashboard; sprint 96: the SQL Workshop's Launchpad with pins and tool groups, the builder's search with Ctrl+K; sprint 95: Table Properties: create, edit or copy a table in a form with a DDL preview and Apply in one transaction; sprint 94: an object's menu with Open in a panel, Quick DDL, Add index / trigger / policy and Drop with dependents; sprint 93: worksheets saved as SQL Scripts with tabs and a Files list, Format, Convert case, find and replace, bind and substitution variables; sprint 92: the worksheet's Query Result with sort, value dialog, copy and downloads, plans as a tree with the slowest step and misestimates, SQL History with status, search and run again; sprint 91: the SQL Worksheet like Database Actions' SQL: navigator, Run Statement at the cursor and Run Script with a log per statement, Explain Plan, Autotrace, notices, history, Run as an application role; sprint 90: Comment Out in the page designer, gallery labels in title case; sprint 89: the Object Browser's schema, one row of tabs, blank NULLs, Modify column; sprint 88: home cards with colour bands and round icons, the hero on the page background, a page footer with the version and Back to top; sprint 87: the Create Application wizard reloads the page list for a schema, RLS badges, the alias from the name; sprint 86: the page designer by page number, HTML error pages in the builder; sprint 85: the Form Designer, beyond APEX; sprint 84: the date picker, facet menus; sprint 83: Component Settings and Component Groups; sprint 82: Report Queries; sprint 81: Application Computations and Shortcuts in Shared Components; sprint 80: the master grid's first row selected when the page opens and after a search; grid cells as text with their format mask until edited, with cell navigation by arrow keys, Enter, F2 and Escape; sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; 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).
10
+ Last reviewed: 2026-11-06 against **APEX 26.2** (sprint 164: every App Builder screen in the eleven builder languages (WS-7 leftover); sprint 165: navigation menu badges from SQL, the notification bell and live badges; sprint 162: the SQL Workshop tools and the region and report settings in the eleven builder languages (CD-8); sprint 161: component events of grids, calendars, maps and trees (CD-3); sprint 160: the Workflow Diagram region, an instance's steps with the reached, current and failed ones marked (CD-7); sprint 159: map layers Lines, Polygons and Extruded Polygons with fill and line styles per layer or per row (CD-6); sprint 158: the item types Image Upload, Text Field with autocomplete, Percent Graph and Display Map (CD-5); sprint 157: the process types Close Dialog, Clear Session State, Reset Pagination, User Preferences, Server Side Geocoding, Print Report, Human Task – Create / – Manage and Form – Initialization (CD-4); sprint 156: dynamic action events double click, key down / press, mouse enter / leave, select, resize, scroll, page unload, before refresh and facets change, greater / less and not-in-list conditions, and the actions Cancel Event, Set Style, Collapse / Expand Tree, Show AI Assistant, Trigger Geocoding and Open report dialog (CD-3); sprint 155: APEX's validation types, with an authorization scheme, Always execute and the error's display location (CD-1); sprint 154: one catalogue of server-side condition types for every component, shown in words in the Page Designer (CD-2); sprint 153: Database users in the eleven builder languages (WS-7 leftover); sprint 152: Workspace utilities, the dashboard, Mail queue, Network access, Instance settings and LDAP directories in the eleven builder languages (WS-7 leftover); sprint 151: vector providers with a model in the database, PostgresML (APEX's ONNX models, AP-1 leftover); sprint 150: remote databases, another PostgreSQL database's tables as foreign tables the applications query (REST Enabled SQL, AP-7 leftover); sprint 149: running workflow instances inside parallel branches migrate to a newer version (WS-6 leftover); sprint 148: the AI assistant streams its answers as the model writes them (WS-4 leftover); sprint 147: `pgkiln advise --offline` checks an export's files without a database (AP-10 leftover); sprint 146: the Advisor checks JSON sources' views against their data profile (AP-8 leftover); sprint 145: the texts that offered AI with "Claude or OpenAI" name all four providers: Claude, OpenAI, Gemini and OpenAI-compatible services (AP-11); sprint 144: `pgkiln advise` for CI with text, JSON and SARIF output (APEXlang static analysis / SQLcl CodeScan), security checks in the Advisor, and working copies and locks from the command line and MCP (the Working Copy APIs) (AP-10); sprint 143: the interactive report's 26.2 dialogs: *is one of* / *is not one of* filters with the column's values and counts, *is between* two values (dates with the date picker in the application's format), relative periods on date columns, and the column order by drag and drop or arrow buttons, followed by downloads and the PDF (AP-9); sprint 142: JSON sources with a data profile and updatable views whose arrays are rows, document views of a table with its children (APEX's duality views), JSON path columns in reports (AP-8); sprint 141: static workspace files (`#WORKSPACE_FILES#`), remote servers for REST data sources, catalogs and AI services (an environment variable per environment), and workspace-level web credentials (AP-7); sprint 140: the items Shuttle (ordered), Select One and Select Many, the regions Classic Report (report templates, pagination types), Breadcrumb and Help Text with a page help text, and a [mapping of every APEX item and region type](#item-and-region-types-one-by-one) (AP-4); sprint 139: OpenTelemetry, traces with a span per SQL statement, web call, AI request and tool call, logs, metrics and `/metrics` for Prometheus, browser spans relayed by pgkiln, per workspace off or its own collector (AP-6); sprint 138: an application's Utilities tab with a dashboard, database object dependencies, change history per component, Upgrade application, UI defaults (APEX's Attribute Dictionary), application and page checksums and an icon browser (AP-5); sprint 137: Create page as a grid of page types with previews, the page types interactive report, smart filters, search page, data loading, tree, timeline, media list, content row, comments, dashboard, wizard, unified task list and workflow console, a Feature tab with nine features that install once, and Create page as copy with shared components mapped or copied (AP-3); sprint 136: vector providers (an AI service with an embedding model or a SQL function), `meta.embed`, *Add vector column* in Table Properties with an HNSW index and a queue that keeps embeddings current, search types vector and hybrid (reciprocal rank fusion with full-text) and a Retrieve (RAG) tool for AI agents, all as the app's role through RLS, on pgvector (AP-1); sprint 135: full-text search configurations, APEX's Oracle Text search type on PostgreSQL full-text search with stemming, ranking, highlights, *Did you mean* and *Add full-text search* in Table Properties (AP-2); sprint 134: the builder also in Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어, APEX's ten builder languages plus Nederlands (SEC-5); sprints 121, 123–125: the builder in Deutsch, English, Español, Français, Nederlands and Português, step by step: the frame, sign-in, Workspace home, App Builder, Page Designer menus, the SQL Workshop's home, SQL Worksheet, Object Browser and Table Properties, Shared Components, application settings, users, identity providers, developers and workspaces (WS-7); sprint 122: *Ask in your own words* sets faceted search and smart filter facets, smart filters read a typed phrase (WS-5), and Sample Maps, Sample Approvals, Sample Data Loading and Sample Files in the App Gallery (WS-8); sprint 120: the App Gallery's single-topic sample apps (charts, cards, calendar, interactive grids, dynamic actions, reporting), the UX Pattern Catalog and a Utility Apps tab with Lookup Lists, Release Notes and Announcements (WS-8); sprint 119: data security per table, a roles × columns matrix and masked values per application role in a masking view, the same identity for pages, AI tools, REST, AutoREST and MCP (WS-13); sprint 118: Administration → Mail queue with delivery per hour and per workspace, the slowest provider calls and failures with Retry and Purge, a workspace's own mail service, and workspace network access lists that narrow the installation's allow-list (WS-9); sprint 117: Pillar Light and Pillar Dark navigation appearances with a header strip, clearer navigation tree states, subtle colour utilities, RTL; sprint 116: the comparison moved from 26.1 to 26.2, with a section for the 26.2 workspace items WS-1 … WS-13 and OCI managed identities; the App Builder list with Updated by, working copies and the lock; `pgkiln import --only`, a file-level import; stale rows on facet menus and blueprints fixed; sprint 115: popup LOVs that load on scroll, Wait Popup dynamic actions and dynamic actions on menu entries; sprint 114: Workflow 26.2 with custom task outcomes, task events and notifications, Send E-Mail and draft steps, migrating running instances and the diagram as SVG / PNG; sprint 113: Team Development with issues, labels, milestones, templates, a board and a set-up wizard; sprint 112: AI interactive reports with chips, Undo, computed columns and a phrase parser that needs no AI service; sprint 111: AI Agents with tools as a shared component, a Navigate tool with checksummed URLs, Gemini and OpenAI-compatible services; sprint 110: Data Reporter as a workspace tool with datasets, reporting applications, editors and viewers, published reports with stable URLs and pins; sprint 109: the Workspace home above the App Builder and SQL Workshop, with a summary, top applications, users and developers, and an optional release check; sprint 108: the code editor's syntax colours in the builder's light and dark themes, read-only SQL highlighted, the Data Modeler in dark mode; sprint 107: a transaction mode in the SQL Worksheet with Commit and Rollback; DA-18: JavaScript (MLE) not planned, plv8 where installed; sprint 106: the change log of DDL change sets with Flyway, Liquibase and SQL downloads; sprint 104: RESTful Services modules, templates and handlers with PL/pgSQL and media handlers, privileges, OpenAPI and Try it; sprint 103: Schema Export / Import with pg_dump and pg_restore; sprint 102: the SQL Monitor with live sessions, Top SQL and a statement's plan; sprint 101: Scheduling of pg_cron jobs with a schedule builder, run now and run history; sprint 100: RESTful Services, tables and views published as REST endpoints with paging, filters, keys and OpenAPI; sprint 99: Administration → Database Users for PostgreSQL roles; sprint 98: the Data Modeler with relational diagrams, DDL and a data dictionary; sprint 97: charts of a query in the worksheet, saved charts and their dashboard; sprint 96: the SQL Workshop's Launchpad with pins and tool groups, the builder's search with Ctrl+K; sprint 95: Table Properties: create, edit or copy a table in a form with a DDL preview and Apply in one transaction; sprint 94: an object's menu with Open in a panel, Quick DDL, Add index / trigger / policy and Drop with dependents; sprint 93: worksheets saved as SQL Scripts with tabs and a Files list, Format, Convert case, find and replace, bind and substitution variables; sprint 92: the worksheet's Query Result with sort, value dialog, copy and downloads, plans as a tree with the slowest step and misestimates, SQL History with status, search and run again; sprint 91: the SQL Worksheet like Database Actions' SQL: navigator, Run Statement at the cursor and Run Script with a log per statement, Explain Plan, Autotrace, notices, history, Run as an application role; sprint 90: Comment Out in the page designer, gallery labels in title case; sprint 89: the Object Browser's schema, one row of tabs, blank NULLs, Modify column; sprint 88: home cards with colour bands and round icons, the hero on the page background, a page footer with the version and Back to top; sprint 87: the Create Application wizard reloads the page list for a schema, RLS badges, the alias from the name; sprint 86: the page designer by page number, HTML error pages in the builder; sprint 85: the Form Designer, beyond APEX; sprint 84: the date picker, facet menus; sprint 83: Component Settings and Component Groups; sprint 82: Report Queries; sprint 81: Application Computations and Shortcuts in Shared Components; sprint 80: the master grid's first row selected when the page opens and after a search; grid cells as text with their format mask until edited, with cell navigation by arrow keys, Enter, F2 and Escape; sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; 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
 
@@ -336,7 +336,7 @@ row above where there is one.
336
336
  | WS-4 AI Agents with tools | ✅ | (sprint 111) AI Agents and AI Tools as shared components, a Navigate tool, Gemini and OpenAI-compatible services ([Workflow, automation and AI](#workflow-automation-and-ai)) |
337
337
  | WS-5 AI interactive reports: chips, computed columns | ✅ | (sprint 112) *Ask in your own words* with chips, Undo and computed columns; a phrase parser that needs no AI service; (sprint 122) phrases set faceted search and smart filter facets |
338
338
  | WS-6 Workflow 26.2: outcomes, migrating running instances, drafts, diagram export | ✅ | (sprint 114) Custom task outcomes, task events, Send E-Mail and draft steps, migrating running instances, the diagram as SVG / PNG ([Workflow, automation and AI](#workflow-automation-and-ai)) |
339
- | WS-7 The builder in more languages | ✅ | (sprint 121) The builder in Deutsch, English, Español, Français, Nederlands and Português, and (sprint 134, SEC-5) Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어 with CJK font stacks: links on the sign-in page, a language menu in the status bar, the choice stored per developer (migration 127); builder texts are keyed message files with a coverage check in CI, also for the builder's own JavaScript (sprint 123). Translated (sprints 121, 123–125): the builder's frame, sign-in page, Workspace home, App Builder home, an application's home and tabs, the Page Designer's toolbar, menus, tree and gallery, the SQL Workshop's home and tabs, the SQL Worksheet, Object Browser and Table Properties, Shared Components, an application's settings, Users, identity providers, Developers and Workspaces ([chapter 3](guide/03-builder.md#choosing-the-builder-language)). (sprint 152) Workspace utilities, the dashboard, Mail queue, Network access, Instance settings and LDAP directories; (sprint 153) Database users; (sprint 162, CD-8) every SQL Workshop tool (SQL Monitor, Top SQL, Quick SQL, SQL Scripts, Generate DDL, Schema Comparison, Change Log, Charts, Load / Unload Data, Sample Data, Query Builder, Data Modeler, Utilities, Object Reports, AI, Schema Export / Import, Scheduling with schedules in words, RESTful Services, data security, document views) and the region and report settings. Still English: some App Builder screens (Team Development, mail, datasets, JSON sources, blueprints and a few more) until they move over; messages of checks shared with the command line; by design the property editor's and component forms' field names and help |
339
+ | WS-7 The builder in more languages | ✅ | (sprint 121) The builder in Deutsch, English, Español, Français, Nederlands and Português, and (sprint 134, SEC-5) Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어 with CJK font stacks: links on the sign-in page, a language menu in the status bar, the choice stored per developer (migration 127); builder texts are keyed message files with a coverage check in CI, also for the builder's own JavaScript (sprint 123). Translated (sprints 121, 123–125): the builder's frame, sign-in page, Workspace home, App Builder home, an application's home and tabs, the Page Designer's toolbar, menus, tree and gallery, the SQL Workshop's home and tabs, the SQL Worksheet, Object Browser and Table Properties, Shared Components, an application's settings, Users, identity providers, Developers and Workspaces ([chapter 3](guide/03-builder.md#choosing-the-builder-language)). (sprint 152) Workspace utilities, the dashboard, Mail queue, Network access, Instance settings and LDAP directories; (sprint 153) Database users; (sprint 162, CD-8) every SQL Workshop tool (SQL Monitor, Top SQL, Quick SQL, SQL Scripts, Generate DDL, Schema Comparison, Change Log, Charts, Load / Unload Data, Sample Data, Query Builder, Data Modeler, Utilities, Object Reports, AI, Schema Export / Import, Scheduling with schedules in words, RESTful Services, data security, document views) and the region and report settings; (sprint 164) every other App Builder screen (Team Development, mail services, datasets, REST sources, AI services and agents, blueprints, JSON sources, the wizards, Theme Roller, Form Designer, working copies, locks, automations, workflows, plug-ins, the App Gallery, backups, availability, supporting objects and the rest). Still English: messages of checks shared with the command line (the Advisor, policy checks); by design the property editor's and component forms' field names and help |
340
340
  | WS-8 App Gallery: more sample apps, Utility Apps | ✅ | (sprint 120) Four tabs with counts and a search that also works without JavaScript ([chapter 3](guide/03-builder.md#app-gallery)). *Sample Apps*: HR Demo, Tasks, ten single-topic apps (Sample Charts, Sample Cards, Sample Calendar, Sample Interactive Grids, Sample Dynamic Actions, Sample Reporting; sprint 122: Sample Maps, Sample Approvals, Sample Data Loading, Sample Files) and the **UX Pattern Catalog**, each with its own schema, data, demo account and explanatory texts, installed by administrators from one SQL file in one transaction; *Utility Apps*: Lookup Lists, Release Notes and Announcements as blueprints any developer installs into the workspace. APEX's 27 sample apps include topics pgkiln shows in HR Demo instead (REST, trees, collections); no remote catalogue |
341
341
  | WS-9 Mail queue reporting, workspace SMTP, workspace network ACLs | ✅ | (sprint 118) Administration → Mail queue (per hour and per workspace / application, the slowest provider calls, failures with the provider's answer, Retry and Purge), a workspace's own mail service, and a workspace's network access list that narrows the installation's allow-list for every outgoing call ([Administration](#administration)) |
342
342
  | WS-10 Universal Theme 26.2: Pillar appearances, navigation polish | ✅ | (sprint 117) Theme Roller → Navigation appearance Pillar Light / Pillar Dark per application or style, with a header strip colour for light and dark mode; the current page filled, its parents bold with an accent guide line; `u-color-*-subtle` utilities; a lighter processing indicator; RTL mirrored |
@@ -528,11 +528,20 @@ SQL Monitor, Top SQL, Quick SQL, SQL Scripts, Generate DDL, Schema Comparison, C
528
528
  Data, Sample Data, Query Builder, Data Modeler, Utilities, Object Reports, the SQL Workshop's AI, Schema Export /
529
529
  Import, Scheduling (schedules are described in your language), RESTful Services (modules and AutoREST) and the
530
530
  Object Browser's data security and document view, and the Page Designer's **region and report settings** (cards,
531
- charts, maps, calendars, facets, trees and the other region types, a report's columns). Messages that come from
532
- the database or from checks shared with the command line (a policy check, a REST handler's validation) stay
533
- English. Other builder pages are still in English (they move over screen by screen); so are the
534
- Page Designer's property names and their help (and, the same way, the field names and help of a shared component's
535
- form), the links to this guide, and any SQL the builder generates.
531
+ charts, maps, calendars, facets, trees and the other region types, a report's columns), and (sprint 164) every
532
+ other **App Builder screen**: Team Development, mail services, Data Reporter datasets, REST data sources and
533
+ catalogs, workspace files, remote servers and web credentials, template components, vector providers, AI services,
534
+ the AI assistant and AI agents, blueprints, JSON sources, the REST API page, globalization, remote databases, debug
535
+ messages and the installation log, sign-in settings, the Create Application and create page wizards, Theme Roller,
536
+ features, OpenTelemetry, the Page Designer's layout messages, the Form Designer, utilities, subscriptions, working
537
+ copies, application groups, *Find my workspace* (its mail too, in the language of the page it was asked from),
538
+ static application files, page and application locks with developer comments, automations, workflow versions and
539
+ the migration of running instances, plug-ins, the App Gallery, PWA settings, the builder's search, backups and
540
+ workspace backups, availability, feedback, cross-application reports, workspace export / import, upgrade
541
+ application, page layouts, dependencies, UI defaults and supporting objects. Messages that come from the database
542
+ or from checks shared with the command line (a policy check, the Advisor, a REST handler's validation) stay
543
+ English, and so, by design, do the Page Designer's property names and their help (and, the same way, the field
544
+ names and help of a shared component's form), the links to this guide, and any SQL the builder generates.
536
545
 
537
546
  ## Workspace home
538
547
 
@@ -104,7 +104,7 @@ Region **templates**:
104
104
  |---|---|
105
105
  | `standard` | A card with a header (title and buttons) and a body |
106
106
  | `plain` | No frame and no header: content only (good for KPI cards and intro text) |
107
- | `collapsible` | A standard card whose body can be collapsed by clicking the header |
107
+ | `collapsible` | A standard card whose body can be collapsed by clicking the header; its header buttons stay visible while it is collapsed |
108
108
  | `hero` | A large banner: an icon (`{"icon": "users"}` in the attributes), the title, the text and the buttons (APEX: Hero) |
109
109
  | `title_bar` | The title and buttons on one line over the content, without a card (APEX: Title Bar) |
110
110
  | `buttons_container` | The buttons only (after any text), without a header (APEX: Buttons Container) |
@@ -113,7 +113,7 @@ Plus: every **required** editable item must have a value.
113
113
  | Property | Meaning |
114
114
  |---|---|
115
115
  | `item_name` | The message is shown next to this item (otherwise at the top of the page) |
116
- | `message` | The error message |
116
+ | `message` | The error message; (sprint 166) `&ITEM.` substitutions are filled in with the submitted values (`The name &P3_NAME. is taken.`) |
117
117
  | `when_button` | Only validate for this request. A `DELETE` request runs only the validations with `when_button` `DELETE` (e.g. "approved requests can't be deleted"), not the item checks |
118
118
  | `condition_type`, `condition_expr`, `condition_value` | Only validate when the [server-side condition](#server-side-conditions) holds, e.g. `request_in` `SAVE,CREATE` (sprint 154) |
119
119
  | `authz` | Only validate for users the authorization scheme lets through (sprint 155) |
@@ -154,7 +154,7 @@ two combine well; see error handling below.
154
154
  | `parent_process` | The name of a `chain` process on the page: this process then runs only inside that chain |
155
155
  | `region_id` | The form or grid region, for `form_dml` / `grid_dml` |
156
156
  | `config` | Settings of a `data_load`, `invoke_api`, `download`, `chain`, `workflow`, `send_push` or `plugin` process (JSON) |
157
- | `success_message` | Shown after the redirect; messages of several processes are joined |
157
+ | `success_message` | Shown after the redirect; messages of several processes are joined. (sprint 166) `&ITEM.` substitutions are filled in with the values after the process (`Order &P3_ID. created.`) |
158
158
  | `authz` | Skipped when the user isn't authorized |
159
159
  | `seq` | Order |
160
160
 
@@ -398,6 +398,10 @@ or with an [e-mail template](#e-mail-templates):
398
398
  {"to": "&P5_EMAIL.", "template": "ORDER_SHIPPED", "placeholders": {"NAME": "&P5_NAME.", "ORDER_ID": "&P5_ID."}}
399
399
  ```
400
400
 
401
+ Without a mail service the process raises an error and the submit is rolled back. When the mail is
402
+ optional, give the process the condition `sql` `meta.mail_available()` (sprint 166): it runs only when
403
+ the application has an enabled mail service with a From address.
404
+
401
405
  `to`, `cc`, `bcc` (several addresses separated by commas), `from`, `reply_to`, `subject` and `body`
402
406
  take `&ITEM.` substitutions as they are; in `body_html` the item values are HTML-escaped.
403
407
  `attachments` is a SELECT (binds allowed) with the columns `content` (bytea), `filename` and `mime`,
@@ -448,7 +452,7 @@ the process's attributes (`config`), checked when it is saved and again when it
448
452
  |---|---|---|---|
449
453
  | `close_dialog` | Close Dialog | `{"items": ["P5_ID"]}` | Closes the modal page after the submit (a modal page closes after a submit anyway; this one also hands the items' values to the page below, where items of the same name take them before its [Dialog Closed](07-dynamic-actions.md#dialog-closed) actions run) |
450
454
  | `clear_session_state` | Clear Session State | `{"items": ["P3_NAME"], "pages": [3, 4], "all": false}` | Empties the items, every `P<n>_` item of the pages, or all page and application items |
451
- | `reset_pagination` | Reset Pagination | – | Reports and grids start on their first page after the submit |
455
+ | `reset_pagination` | Reset Pagination | – | An interactive grid saved from a later page starts on its first page again (a report starts on its first page after any submit anyway: its page number is in the URL) |
452
456
  | `user_preferences` | User Preferences | `{"action": "set", "preference": "DEFAULT_DEPT", "item": "P1_DEPT"}`, or `"reset"` | Stores (or removes) a [user preference](#user-preferences); nothing for the public user |
453
457
  | `server_geocoding` | Server Side Geocoding | `{"address_item": "P3_ADDRESS", "coordinates_item": "P3_LOCATION", "country": "nl"}` | The installation's geocoder (`GEOCODER_URL`); the first place's `lat,lng` goes into the coordinates item |
454
458
  | `print_report` | Print Report | `{"document": "EMPLOYEE_SHEET"}` | A [document template](16-files.md#document-templates) or report query, sent as the answer to the submit |
@@ -91,7 +91,7 @@ items, in the browser. A tree of departments that filters an employee report, wi
91
91
  |---|---|---|
92
92
  | `show` / `hide` | browser | Show or hide the affected items/region. **With a condition, the opposite happens when the condition is false**, so one dynamic action gives "show commission only for salesmen". Also applied when the page loads (and already on the server, so there's no flicker) |
93
93
  | `enable` / `disable` | browser | Enable or disable the controls, reversed when the condition is false |
94
- | `set_value` | server | Runs `code` (a SELECT); its first row's columns set the affected items, in order |
94
+ | `set_value` | server | Runs `code` (a SELECT); its first row's columns set the affected items, in order. The affected items must be on the page: a `hidden` item isn't rendered (its value stays on the server, safe from tampering), so set a text or display item, or use a computation |
95
95
  | `execute_sql` | server | Runs `code`; returned columns named like items set those items |
96
96
  | `refresh_region` | server | Re-renders `affected_region_id` with the current session state (e.g. a report filtered by the changed item) |
97
97
  | `refresh_item` | server | Re-renders the affected items (e.g. a list whose LOV depends on another item) |
@@ -119,10 +119,10 @@ items, in the browser. A tree of departments that filters an employee report, wi
119
119
  | `wait_popup` | browser | Shows a modal "please wait" popup with `message` (default *Please wait…*) until `remove_wait_popup` or the next page (APEX: Show Wait Popup); [below](#wait-popup) |
120
120
  | `remove_wait_popup` | browser | Removes the wait popup (APEX: Remove Wait Popup) |
121
121
  | `cancel_event` | browser | Stops the actions after it, and the event's own effect: a button doesn't submit or follow its link, a typed key (`key_down`, `key_press`) stays out of the field, a refresh doesn't happen (APEX: Cancel Event). Sprint 156 |
122
- | `set_style` | browser | Sets CSS properties on the affected items or region: `{"styles": {"color": "#b42318", "font-weight": "bold"}}` in the attributes (APEX: Set Style). Properties from a fixed list (colours, font, text, border, opacity, visibility, padding, margin, width); values without `url()` or `var()`, checked when saved and again before they reach the page |
122
+ | `set_style` | browser | Sets CSS properties on the affected items (their field: input, select list or text area; (sprint 166) before, the item's wrapper) or region: `{"styles": {"color": "#b42318", "font-weight": "bold"}}` in the attributes (APEX: Set Style). Properties from a fixed list (colours, font, text, border, opacity, visibility, padding, margin, width); values without `url()` or `var()`, checked when saved and again before they reach the page |
123
123
  | `collapse_tree` / `expand_tree` | browser | Closes / opens every node of the affected tree region (APEX: Collapse Tree, Expand Tree) |
124
124
  | `show_ai_assistant` | browser | Opens the affected AI assistant region (or the inline dialog it sits in) and puts the cursor in its question (APEX: Show AI Assistant) |
125
- | `trigger_geocoding` | browser | The affected geocoded address item looks its text up, as its *Check address* button does (APEX: Trigger Geocoding) |
125
+ | `trigger_geocoding` | browser | The affected geocoded address item looks its text up, as its *Check address* button does (APEX: Trigger Geocoding); (sprint 166) not when its text is the address just chosen from the list, so a `change` action on the address item itself doesn't reopen it |
126
126
  | `open_report_dialog` | browser | Opens a dialog of the affected interactive report: `code` is `filter`, `columns`, `sort`, `highlight`, `compute`, `aggregate`, `chart`, `group`, `pivot`, `break`, `rows` or `saved` (APEX: Invoke Interactive Report Dialog) |
127
127
 
128
128
  Server-side actions first store `items_to_submit` in session state, run as the application's
@@ -111,6 +111,7 @@ service (an administrator chooses it under Workspace utilities → Mail services
111
111
  | `meta.send_mail_template(p_template, p_placeholders jsonb, p_to, p_cc, p_bcc, p_from, p_reply_to)` | The same with an [e-mail template](06-processing.md#e-mail-templates) and its placeholder values (APEX_MAIL.SEND with `p_template_static_id`) |
112
112
  | `meta.add_mail_attachment(p_mail_id, p_content bytea, p_filename, p_mime)` | Adds a file to a mail queued **in the same transaction** (APEX_MAIL.ADD_ATTACHMENT); at most 20 files and 20 MB per mail, 10 MB per file |
113
113
  | `meta.mail_status(p_mail_id)` | `queued`, `sending`, `sent`, `error` or `cancelled`; NULL for another application's mail |
114
+ | `meta.mail_available()` | (155) Whether the application may send e-mail now: it has an enabled mail service with a From address. Without one, `meta.send_mail` and a Send E-Mail process raise an error (rolling back the submit), so use it as their condition when mail is optional |
114
115
 
115
116
  The mail is sent by the server **after the transaction commits**. Over the application's limit per
116
117
  day `meta.send_mail` raises an error. Application roles can't read the queue; the owner can:
@@ -15,6 +15,7 @@ scripts/migrate.ts migration/seed runner (src/migrate.ts does the work)
15
15
  website/ the website pgkiln.vargar.eu (VitePress): landing page + this guide, synced from docs/ at build time;
16
16
  cd website && npm install && npm run dev; scripts/deploy.sh publishes it (see website/deploy/)
17
17
  scripts/screenshots.ts the README's screenshots in docs/images/ (npm run screenshots, HR example)
18
+ scripts/check-sample.ts (sprint 166) one App Gallery sample: install, sign in as demo, render every page, report errors (--keep)
18
19
  scripts/docker-start.ts container entry point: checks secrets, migrates (locked), sets role and admin passwords, starts the server
19
20
  deploy/ compose.yaml and .env.example for Docker (Dockerfile at the root; chapter 1)
20
21
  bin/pgkiln.js the `pgkiln` command line (runs src/cli/main.ts with tsx)
@@ -344,6 +345,7 @@ src/
344
345
  i18n.ts (sprint 121) the builder's own texts: BUILDER_LANGUAGES, tr(s) / translatorFor(lang) → tx(key, params),
345
346
  tx.rich (markup in a sentence), tx.dyn (keys made at run time), tx.label (known breadcrumb labels),
346
347
  (sprint 162) tx.code (`backticks` become <code>), withTranslator / scopedTx (a request-scoped translator)
348
+ (sprint 164) inRequestScope / setRequestTranslator: scopedTx in every builder handler
347
349
  i18n/ en.ts defines the builder's keys; de, es, fr, it, nl, pt, zh-cn, zh-tw, ja, ko (sprint 134) are Records of the same keys
348
350
  language.ts (migration 127) the status bar's language menu (POST /builder/language), the sign-in page's
349
351
  language links (?lang=, a cookie), meta.developer.language
@@ -650,6 +652,9 @@ test/
650
652
  gallery.test.ts the App Gallery: every starter and utility created from its review and every sample app installed, with all
651
653
  their pages rendering; sample apps (admins), the search, a failing script leaves nothing
652
654
  gallery-samples.ts the gallery's shipped apps for the tests: SAMPLES (schema and role of each script), BLUEPRINTS, drop/install
655
+ sample-coverage.test.ts (sprint 166) every feature in a sample app: each value of the components' catalogues (check constraints
656
+ listed in sample-coverage.sql, and meta.condition_ok's condition types) is used by HR or a gallery
657
+ sample, or exempted there with a reason
653
658
  builder-apex-screens.test.ts sprint 61: sign-in with a workspace, message and banner, utilization, SQL Workshop home, groups, reports
654
659
  workspace-isolation.test.ts isolated workspaces (090): logins, RLS on meta, app_id, roles, SQL Workshop, scripts, imports
655
660
  ai.test.ts AI services: Generate text with AI (text, structured outputs, errors, limits, keys), its dynamic action,
@@ -719,7 +724,11 @@ tx.code('cr.schedule_help'); // (sprint 162) `backticked` pa
719
724
  pass `tx` to each of them: its entry point runs inside `withTranslator(tr(s), () => …)`, and the helpers import
720
725
  `scopedTx as tx`, which takes the translator of the request being rendered from an `AsyncLocalStorage` (so two
721
726
  requests in different languages never mix; `test/builder-i18n.test.ts` renders German and French concurrently).
722
- Outside `withTranslator` it is English.
727
+ (sprint 164) Every `/builder` route runs in a request scope (`inRequestScope` in `app.ts`), and `developer()` sets
728
+ the developer's translator in it once the session is loaded (`setRequestTranslator`), so `scopedTx` works in any
729
+ builder handler and the helpers it calls without `withTranslator`; before sign-in it follows the language cookie
730
+ (`cookieLanguage`). Outside a request (the command line, MCP, background jobs) it is English. Plural counts that
731
+ English writes differently get a separate `_1` key, so the English stays exactly as before.
723
732
 
724
733
  A missing text falls back to English, never to the raw key. Shared helpers that render chrome take the session as
725
734
  an optional last argument (`appHeader(a, 'pages', s)`, `workshopTabs('sql', s)`); `shell()` translates known English
@@ -19,21 +19,38 @@ The builder's **App Gallery** (`/builder/gallery`) lists what `gallery.json` nam
19
19
  |---|---|---|
20
20
  | `sample-charts.sql` | Sample Charts (`/a/sample-charts`) | the 22 chart types, a page per question, a drill-down to a report |
21
21
  | `sample-cards.sql` | Sample Cards | cards with a form, KPI tiles, lists as cards, built-in template components |
22
- | `sample-calendar.sql` | Sample Calendar | month, week, day and list views, create on click, drag and drop through a function |
23
- | `sample-grids.sql` | Sample Interactive Grids | an editable grid, select lists, totals, frozen column, row menu, master-detail, views |
24
- | `sample-dynamic-actions.sql` | Sample Dynamic Actions | show/hide/enable, set value, refresh, messages, wait popup, classes, inline dialog |
22
+ | `sample-calendar.sql` | Sample Calendar | month, week, day and list views, create on click, drag and drop through a function, the calendar's dynamic action events (a chosen day, the view) |
23
+ | `sample-grids.sql` | Sample Interactive Grids | an editable grid, select lists, totals, frozen column, row menu, master-detail, views, a new row's defaults (`grid_row_init`) and a message after saving (`grid_save`) |
24
+ | `sample-dynamic-actions.sql` | Sample Dynamic Actions | show/hide/enable, set value, refresh, messages, wait popup, classes, inline dialog, and every other event (keyboard, mouse, focus, before submit, page unload, resize, scroll, refreshes, a tree, facets) and action (styles, disable, clear, submit, download, print, share, push subscribe, dialogs, trees, report dialogs, the AI assistant) with client-side conditions |
25
25
  | `sample-reporting.sql` | Sample Reporting | interactive report, faceted search, smart filters, a classic report with column options |
26
- | `sample-maps.sql` | Sample Maps | markers and clusters, layers with GeoJSON and a heat map, a map filtering a list by distance, a location item |
27
- | `sample-approvals.sql` | Sample Approvals | a workflow started by a form, an approval task and the task list, the workflow console (accounts demo and approver) |
26
+ | `sample-maps.sql` | Sample Maps | markers and clusters, layers with GeoJSON and a heat map, a map filtering a list by distance, a location item, the map's events (a clicked marker, the zoom), the current position, geocoding an address and the Display Map item |
27
+ | `sample-approvals.sql` | Sample Approvals | a workflow started by a form, an approval task and the task list, the workflow console and diagram, the notification bell (`send_notification`, `meta.notify`), a navigation menu with badges from SQL and live badges, a `timer` dynamic action (accounts demo and approver) |
28
+ | `sample-validations.sql` | Sample Validations | every validation type and error location, every server-side condition type |
29
+ | `sample-processes.sql` | Sample Processes | every process type, page and application computations, branches, application processes and Ajax callbacks, report queries, shortcuts |
28
30
  | `sample-data-loading.sql` | Sample Data Loading | `data_load` processes: by column name and merged, through a data load definition, skipping rows with errors |
29
31
  | `sample-files.sql` | Sample Files | a file in the record's columns, several files in a child table, a photo cropped before upload |
30
- | `ux-patterns.sql` | UX Pattern Catalog | region templates and options, buttons, items and form layouts, content and page patterns |
32
+ | `ux-patterns.sql` | UX Pattern Catalog | region templates and options, buttons and every button position, items (autocomplete, image upload, multiselect, percent graph, URL) and form layouts, content and page patterns, display positions, the minimal and right-side-column page templates, URL and sign-in regions |
31
33
 
32
34
  Each script creates its own schema (`sample_charts`, …), a role (`app_sample_charts`, …) granted to the runtime, the
33
35
  application and one account, **demo** / **demo**. Without the builder:
34
36
  `psql "$DATABASE_URL" -1 -f examples/gallery/samples/sample-charts.sql`. To remove one, delete the application in the
35
37
  App Builder, then `drop schema sample_charts cascade; drop role app_sample_charts;`.
36
38
 
39
+ ## Every feature in a sample app
40
+
41
+ Every catalogued value of the application components (region, item, process, validation and
42
+ computation types, dynamic action events, actions and conditions, server-side condition types,
43
+ button positions, page templates, …) is used by HR or one of these samples: `test/sample-coverage.test.ts`
44
+ fails for a value nobody uses, unless it is exempted there with the reason it can't be shown (an
45
+ authentication scheme that needs an outside service). `test/gallery.test.ts` installs each sample and
46
+ renders every page as its demo account, so what a sample shows also works. A new feature therefore
47
+ comes with a sample that uses it. While you write one:
48
+
49
+ ```bash
50
+ npx tsx scripts/check-sample.ts examples/gallery/samples/sample-processes.sql # install, render every page, remove
51
+ npx tsx scripts/check-sample.ts examples/gallery/samples/sample-processes.sql --keep # and leave it installed
52
+ ```
53
+
37
54
  A sample script follows the pattern of the HR example: plain SQL that inserts `meta.*` rows, using
38
55
  `meta.generate_page()` for wizard-made pages and two temporary helpers (`pg_temp.page_id`, `pg_temp.region_id`).
39
56
  Every page starts with a text that says how it is made.
@@ -20,6 +20,10 @@
20
20
  "description": "Maps of Dutch museums without PostGIS: markers with popups and clustering, several layers (a route and an area as GeoJSON, a heat map you switch on), a map that filters the list beside it by distance, and a form with a location item. Demo account demo / demo."},
21
21
  {"key": "sample-approvals", "title": "Sample Approvals", "alias": "sample-approvals", "icon": "list-checks", "file": "samples/sample-approvals.sql",
22
22
  "description": "Purchase requests that start a workflow: approved by itself below 1,000, otherwise an approval task for the role approver, decided under My tasks; the workflow console with its diagram and history. Demo accounts demo / demo (asks) and approver / approver (decides)."},
23
+ {"key": "sample-validations", "title": "Sample Validations", "alias": "sample-validations", "icon": "shield", "file": "samples/sample-validations.sql",
24
+ "description": "Every validation type with its error shown next to the field, at the top or both, and every server-side condition type deciding whether a region, item, button or process is there, each page saying which one it shows. Demo account demo / demo."},
25
+ {"key": "sample-processes", "title": "Sample Processes", "alias": "sample-processes", "icon": "settings", "file": "samples/sample-processes.sql",
26
+ "description": "What runs when a page is shown and submitted: every process type, page and application computations, branches, application processes and Ajax callbacks, report queries in six formats and shortcuts, each page saying how it is made. Demo account demo / demo."},
23
27
  {"key": "sample-data-loading", "title": "Sample Data Loading", "alias": "sample-data-loading", "icon": "file-up", "file": "samples/sample-data-loading.sql",
24
28
  "description": "Loading CSV, Excel and JSON files into a table from a page: merged by the key, through a data load definition that maps other headings and a date format, and skipping rows with errors. Example files to download included. Demo account demo / demo."},
25
29
  {"key": "sample-files", "title": "Sample Files", "alias": "sample-files", "icon": "files", "file": "samples/sample-files.sql",
@@ -7,7 +7,18 @@
7
7
  -- * from 1,000 it asks for approval: a PURCHASE_APPROVAL task for the
8
8
  -- users with the role approver, decided under My tasks; the task's
9
9
  -- action records the decision on the request
10
- -- * the console lists the workflows with their diagram and history
10
+ -- * the console lists the workflows with their diagram and history; the
11
+ -- request's form draws its workflow (a workflow_diagram region)
12
+ -- * on the request's form the approver claims or releases the task, and
13
+ -- who asked can ask again after a rejection (the declarative process
14
+ -- types human_task_manage and human_task_create)
15
+ -- * the notification bell: a request of 1,000 or more notifies the
16
+ -- approver (a send_notification process), a decision notifies who asked
17
+ -- (meta.notify in the decision); opening one goes to the request
18
+ -- * the navigation menu is a list whose entries have badges from SQL
19
+ -- (your pending requests, the tasks waiting for you), refreshed every
20
+ -- 15 seconds by the live badges; a timer dynamic action refreshes
21
+ -- "Waiting for me"
11
22
  --
12
23
  -- Two accounts: demo / demo asks, approver / approver decides (nobody
13
24
  -- approves their own request).
@@ -50,11 +61,25 @@ create trigger purchase_defaults before insert on sample_approvals.purchase
50
61
  -- the decision, from the approval task's action (by the approver) or the workflow's SQL step
51
62
  -- (which runs as the user who started the workflow, so it says who decided: 'workflow')
52
63
  create function sample_approvals.decide(p_id int, p_outcome text, p_note text, p_by text default null) returns void language plpgsql as $$
64
+ declare
65
+ p sample_approvals.purchase;
53
66
  begin
54
67
  update sample_approvals.purchase
55
68
  set status = case lower(p_outcome) when 'approved' then 'APPROVED' when 'rejected' then 'REJECTED' else status end,
56
69
  decided_by = coalesce(p_by, meta.app_user()), note = nullif(p_note, '')
57
- where id = p_id and status = 'PENDING';
70
+ where id = p_id and status = 'PENDING'
71
+ returning * into p;
72
+ -- the bell of who asked: the decision, opening the request (page 3); a notification
73
+ -- that can't be added (notifications turned off) never stops the decision
74
+ if p.status in ('APPROVED', 'REJECTED') and p.requested_by is not null and meta.app_id() is not null then
75
+ begin
76
+ perform meta.notify(p.requested_by, format('Purchase %s: %s', lower(p.status), p.title),
77
+ coalesce(p.note, format('Decided by %s', p.decided_by)),
78
+ 3, jsonb_build_object('P3_ID', p.id), case p.status when 'APPROVED' then 'check' else 'x' end);
79
+ exception when others then
80
+ raise warning 'sample_approvals.decide: no notification: %', sqlerrm;
81
+ end;
82
+ end if;
58
83
  end
59
84
  $$;
60
85
 
@@ -73,8 +98,8 @@ grant select, insert, update, delete on sample_approvals.purchase to app_sample_
73
98
  grant execute on function sample_approvals.decide(int, text, text, text) to app_sample_approvals;
74
99
 
75
100
  -- 3. The application ----------------------------------------------------------
76
- insert into meta.app (alias, name, home_page, authentication, db_role)
77
- values ('sample-approvals', 'Sample Approvals', 1, 'app_users', 'app_sample_approvals');
101
+ insert into meta.app (alias, name, home_page, authentication, db_role, notifications, live_badges_s, nav_list)
102
+ values ('sample-approvals', 'Sample Approvals', 1, 'app_users', 'app_sample_approvals', true, 15, 'APPROVAL_MENU');
78
103
 
79
104
  insert into meta.app_user (app_id, username, password_hash, roles)
80
105
  select a.id, u.name, meta.hash_password(u.name), u.roles
@@ -116,13 +141,29 @@ insert into meta.process (page_id, seq, name, type, code, when_button)
116
141
  select pg_temp.page_id('sample-approvals', 3), 15, 'Start the approval', 'sql',
117
142
  $c$select meta.start_workflow('PURCHASE', :P3_ID, jsonb_build_object('TITLE', :P3_TITLE, 'AMOUNT', :P3_AMOUNT))$c$, 'CREATE';
118
143
 
119
- insert into meta.nav_entry (app_id, seq, label, icon, target_page)
120
- select a.id, n.seq, n.label, n.icon, n.page
121
- from meta.app a, (values (10, 'Home', 'home', 1), (20, 'Purchases', 'list', 2), (30, 'My tasks', 'check', 4), (40, 'Workflows', 'route', 5)) as n (seq, label, icon, page)
122
- where a.alias = 'sample-approvals';
144
+ -- from 1,000 the approver gets a notification on the bell (the declarative process type
145
+ -- send_notification; an application with several approvers would call meta.notify for each)
146
+ insert into meta.process (page_id, seq, name, type, when_button, condition_type, condition_expr, config)
147
+ select pg_temp.page_id('sample-approvals', 3), 16, 'Tell the approver', 'send_notification', 'CREATE',
148
+ 'sql', ':P3_AMOUNT::numeric >= 1000',
149
+ '{"to": "approver", "title": "Purchase to approve: &P3_TITLE.", "body": "&P3_AMOUNT. from &P3_SUPPLIER., asked by &APP_USER.", "page": 4, "icon": "check"}'::jsonb;
123
150
 
124
151
  insert into meta.list (app_id, name, type, description)
125
- select id, 'APPROVAL_TOPICS', 'static', 'The pages of Sample Approvals' from meta.app where alias = 'sample-approvals';
152
+ select id, l.name, 'static', l.description from meta.app, (values
153
+ ('APPROVAL_TOPICS', 'The pages of Sample Approvals'),
154
+ ('APPROVAL_MENU', 'The navigation menu, with badges from SQL')) as l (name, description)
155
+ where alias = 'sample-approvals';
156
+
157
+ -- the navigation menu (app.nav_list): badges from SQL, refreshed by the live badges
158
+ insert into meta.list_entry (app_id, list_name, seq, label, icon, target_page, badge_query)
159
+ select a.id, 'APPROVAL_MENU', e.seq, e.label, e.icon, e.page, e.badge_query
160
+ from meta.app a, (values
161
+ (10, 'Home', 'home', 1, null),
162
+ (20, 'Purchases', 'list', 2, 'select nullif(count(*), 0) from sample_approvals.purchase where status = ''PENDING'' and requested_by = meta.app_user()'),
163
+ (30, 'My tasks', 'check', 4, 'select nullif(count(*), 0) from meta.tasks where app_id = meta.app_id() and may_act and state in (''unassigned'', ''assigned'')'),
164
+ (40, 'Workflows', 'route', 5, null)
165
+ ) as e (seq, label, icon, page, badge_query)
166
+ where a.alias = 'sample-approvals';
126
167
 
127
168
  insert into meta.list_entry (app_id, list_name, seq, label, icon, target_page, description)
128
169
  select a.id, 'APPROVAL_TOPICS', e.seq, e.label, e.icon, e.page, e.description
@@ -137,11 +178,11 @@ insert into meta.region (page_id, seq, title, type, columns, template, source, c
137
178
  select pg_temp.page_id('sample-approvals', r.page), r.seq, r.title, r.type, 12, r.template, r.source, r.config::jsonb
138
179
  from (values
139
180
  (1, 10, 'Sample Approvals', 'static', 'hero',
140
- '<p>Signed in as <strong>demo</strong>, ask for a purchase under <em>Purchases</em>. Below 1,000 the workflow approves it at once; from 1,000 it creates an approval task for the role <code>approver</code>. Sign in as <strong>approver</strong> / approver and decide under <em>My tasks</em>: the task''s action writes the decision on the request, and the workflow ends.</p>',
181
+ '<p>Signed in as <strong>demo</strong>, ask for a purchase under <em>Purchases</em>. Below 1,000 the workflow approves it at once; from 1,000 it creates an approval task for the role <code>approver</code>. Sign in as <strong>approver</strong> / approver and decide under <em>My tasks</em>: the task''s action writes the decision on the request, and the workflow ends.</p><p>The bell in the header shows notifications: the approver gets one for each request of 1,000 or more (a <code>send_notification</code> process), and who asked gets the decision (<code>meta.notify</code>). The menu''s badges come from SQL and refresh every 15 seconds without a reload: keep both accounts open in two browsers and watch them change.</p>',
141
182
  '{"icon": "check"}'),
142
183
  (1, 20, 'Topics', 'list', 'plain', null, '{"list": "APPROVAL_TOPICS", "template": "cards"}'),
143
184
  (2, 5, 'About this page', 'static', 'plain',
144
- '<p class="lead">The form''s Create button runs the wizard''s row process, then <code>select meta.start_workflow(''PURCHASE'', :P3_ID, …)</code>. A trigger fills in who asked and the status from the session, so the form can''t set them.</p>', '{}'),
185
+ '<p class="lead">The form''s Create button runs the wizard''s row process, then <code>select meta.start_workflow(''PURCHASE'', :P3_ID, …)</code>. A trigger fills in who asked and the status from the session, so the form can''t set them.</p><p>Open a request: below the form a <code>workflow_diagram</code> region draws its workflow, the steps it went through and where it is now. While its approval task is open, the approver gets <strong>Claim task</strong> (and then <strong>Release task</strong>): processes of type <code>human_task_manage</code>. After a rejection, who asked gets <strong>Ask again</strong>: the request, changed or not, is pending again and a process of type <code>human_task_create</code> creates a new <code>PURCHASE_APPROVAL</code> task, outside the workflow, which has ended.</p>', '{}'),
145
186
  (4, 5, 'About this page', 'static', 'plain',
146
187
  '<p class="lead">Regions of type <code>tasks</code>: what waits for the signed-in user (as owner, here the role <code>approver</code>), and what they asked for. Approve and Reject run the task definition''s action with <code>:DETAIL_PK</code>, <code>:OUTCOME</code> and <code>:COMMENT</code>.</p>', '{}'),
147
188
  (4, 10, 'Waiting for me', 'tasks', 'standard', null, '{"empty": "Nothing waits for you. Sign in as approver to decide on requests of 1,000 or more."}'),
@@ -151,3 +192,53 @@ select pg_temp.page_id('sample-approvals', r.page), r.seq, r.title, r.type, 12,
151
192
  (5, 10, 'Workflows I started', 'workflows', 'standard', null, '{"completed": true}'),
152
193
  (5, 20, 'All purchase workflows (approvers)', 'workflows', 'collapsible', null, '{"context": "admin", "completed": true}')
153
194
  ) as r (page, seq, title, type, template, source, config);
195
+
196
+ -- a timer dynamic action: "Waiting for me" refreshes every 30 seconds while the page is visible
197
+ insert into meta.dynamic_action (page_id, seq, name, event, trigger_element, action, affected_region_id)
198
+ select pg_temp.page_id('sample-approvals', 4), 10, 'Refresh what waits', 'timer', '30', 'refresh_region', r.id
199
+ from meta.region r where r.page_id = pg_temp.page_id('sample-approvals', 4) and r.title = 'Waiting for me';
200
+
201
+ -- page 3, the request's form (also the task's details page): its open approval task and its workflow,
202
+ -- computed when the page is shown
203
+ insert into meta.item (page_id, region_id, seq, name, type)
204
+ select r.page_id, r.id, i.seq, i.name, 'hidden'
205
+ from meta.region r, (values (200, 'P3_TASK_ID'), (210, 'P3_WORKFLOW_ID')) as i (seq, name)
206
+ where r.page_id = pg_temp.page_id('sample-approvals', 3) and r.type = 'form';
207
+
208
+ insert into meta.computation (page_id, seq, item_name, point, type, expression)
209
+ values
210
+ (pg_temp.page_id('sample-approvals', 3), 10, 'P3_TASK_ID', 'before_header', 'sql_query',
211
+ $q$select id::text from meta.tasks where app_id = meta.app_id() and definition = 'PURCHASE_APPROVAL' and detail_pk = :P3_ID and state in ('unassigned', 'assigned') order by id desc limit 1$q$),
212
+ (pg_temp.page_id('sample-approvals', 3), 20, 'P3_WORKFLOW_ID', 'before_header', 'sql_query',
213
+ $q$select id::text from meta.workflows where app_id = meta.app_id() and name = 'PURCHASE' and detail_pk = :P3_ID order by id desc limit 1$q$);
214
+
215
+ -- the workflow of the request: a Workflow Diagram region (shown to who started it and its administrators)
216
+ insert into meta.region (page_id, seq, title, type, columns, template, config, condition_type, condition)
217
+ values (pg_temp.page_id('sample-approvals', 3), 20, 'Its workflow', 'workflow_diagram', 12, 'standard',
218
+ '{"instance_item": "P3_WORKFLOW_ID", "empty": "You can''t see this request''s workflow: only who asked and the approvers can."}',
219
+ 'item_not_null', 'P3_WORKFLOW_ID');
220
+
221
+ -- the open task: Claim (a potential owner, while nobody has it) and Release (its owner);
222
+ -- after a rejection who asked can Ask again: the request (as changed on the form) pending again, and a new approval task
223
+ insert into meta.button (page_id, region_id, seq, name, label, action, condition_type, condition)
224
+ select r.page_id, r.id, b.seq, b.name, b.label, 'submit', 'exists', b.cond
225
+ from meta.region r, (values
226
+ (50, 'CLAIM', 'Claim task', $c$select 1 from meta.tasks where id = nullif(:P3_TASK_ID, '')::bigint and may_claim$c$),
227
+ (60, 'RELEASE', 'Release task', $c$select 1 from meta.tasks where id = nullif(:P3_TASK_ID, '')::bigint and may_release$c$),
228
+ (70, 'ASK_AGAIN', 'Ask again', $c$select 1 from sample_approvals.purchase where id = :P3_ID::int and status = 'REJECTED' and requested_by = meta.app_user()$c$)
229
+ ) as b (seq, name, label, cond)
230
+ where r.page_id = pg_temp.page_id('sample-approvals', 3) and r.type = 'form';
231
+
232
+ insert into meta.process (page_id, seq, name, type, code, when_button, config, success_message)
233
+ values
234
+ (pg_temp.page_id('sample-approvals', 3), 30, 'Claim the task', 'human_task_manage', null, 'CLAIM',
235
+ '{"action": "claim", "task": "&P3_TASK_ID."}', 'The task is yours: approve or reject it under My tasks.'),
236
+ (pg_temp.page_id('sample-approvals', 3), 40, 'Release the task', 'human_task_manage', null, 'RELEASE',
237
+ '{"action": "release", "task": "&P3_TASK_ID.", "comment": "Released from the request''s page"}', 'The task is back with every approver.'),
238
+ (pg_temp.page_id('sample-approvals', 3), 50, 'Pending again', 'sql',
239
+ $c$update sample_approvals.purchase
240
+ set title = :P3_TITLE, supplier = :P3_SUPPLIER, amount = :P3_AMOUNT::numeric, status = 'PENDING', decided_by = null, note = null
241
+ where id = :P3_ID::int and status = 'REJECTED' and requested_by = meta.app_user()$c$, 'ASK_AGAIN', '{}', null),
242
+ (pg_temp.page_id('sample-approvals', 3), 51, 'Ask for approval again', 'human_task_create', null, 'ASK_AGAIN',
243
+ '{"definition": "PURCHASE_APPROVAL", "detail_pk": "&P3_ID.", "parameters": {"TITLE": "&P3_TITLE.", "AMOUNT": "&P3_AMOUNT."}, "id_item": "P3_TASK_ID"}',
244
+ 'Asked again: the approvers have a new task.');