pgkiln 0.45.0 → 0.46.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.
- package/db/migrations/106_form_designer.sql +102 -0
- package/db/migrations/107_app_version.sql +9 -0
- package/docs/apex-feature-parity.md +6 -3
- package/docs/guide/03-builder.md +36 -12
- package/docs/guide/04-pages-and-regions.md +74 -2
- package/docs/guide/05-items.md +14 -2
- package/docs/guide/09-reference.md +1 -1
- package/docs/guide/11-from-apex.md +2 -1
- package/docs/guide/12-development.md +6 -1
- package/examples/hr/hr_61_form_designer.sql +80 -0
- package/package.json +1 -1
- package/public/app.css +62 -2
- package/public/app.js +244 -35
- package/public/builder.css +21 -1
- package/public/builder.js +67 -0
- package/public/sw.js +2 -1
- package/src/app.ts +9 -1
- package/src/builder/appwizard.ts +22 -6
- package/src/builder/arrange.ts +33 -12
- package/src/builder/code-editor.ts +1 -1
- package/src/builder/components.ts +1 -1
- package/src/builder/designer.ts +44 -17
- package/src/builder/errors.ts +65 -0
- package/src/builder/form-designer.ts +229 -0
- package/src/builder/locks.ts +6 -0
- package/src/builder/newapp.ts +2 -1
- package/src/builder/object-browser.ts +81 -18
- package/src/builder/region-help.ts +2 -0
- package/src/builder/region-settings.ts +2 -0
- package/src/builder/reporter.ts +1 -1
- package/src/builder/routes.ts +7 -5
- package/src/builder/search.ts +3 -3
- package/src/builder/shared.ts +2 -2
- package/src/builder/ui.ts +2 -0
- package/src/cli/replace.ts +10 -0
- package/src/i18n/ar.ts +62 -0
- package/src/i18n/cs.ts +62 -0
- package/src/i18n/da.ts +62 -0
- package/src/i18n/de.ts +62 -0
- package/src/i18n/el.ts +62 -0
- package/src/i18n/es.ts +62 -0
- package/src/i18n/fi.ts +62 -0
- package/src/i18n/fr.ts +62 -0
- package/src/i18n/he.ts +62 -0
- package/src/i18n/it.ts +62 -0
- package/src/i18n/ja.ts +62 -0
- package/src/i18n/ko.ts +62 -0
- package/src/i18n/nb.ts +62 -0
- package/src/i18n/pl.ts +62 -0
- package/src/i18n/pt.ts +62 -0
- package/src/i18n/ru.ts +62 -0
- package/src/i18n/sv.ts +62 -0
- package/src/i18n/tr.ts +62 -0
- package/src/i18n/uk.ts +62 -0
- package/src/i18n/zh.ts +62 -0
- package/src/i18n.ts +124 -0
- package/src/metadata.ts +4 -2
- package/src/runtime/devbar.ts +1 -1
- package/src/runtime/facet-state.ts +10 -5
- package/src/runtime/facets.ts +29 -5
- package/src/runtime/form-designer.ts +676 -0
- package/src/runtime/grid.ts +15 -8
- package/src/runtime/items.ts +33 -21
- package/src/runtime/lists.ts +1 -1
- package/src/runtime/pdf.ts +2 -1
- package/src/runtime/regions.ts +4 -0
- package/src/runtime/render.ts +7 -3
- package/src/runtime/report.ts +2 -2
- package/src/runtime/routes.ts +3 -1
- package/src/runtime/smart-filters.ts +2 -1
- package/src/runtime/tasks.ts +6 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
-- ---------------------------------------------------------------------
|
|
2
|
+
-- 106: Form Designer: the application's administrators build their own
|
|
3
|
+
-- data entry forms in the running application.
|
|
4
|
+
--
|
|
5
|
+
-- The developer places a region of type 'form_designer' and lists in its
|
|
6
|
+
-- settings (config.sources) the tables and views it offers: the columns
|
|
7
|
+
-- forms may show and change, the column that identifies a row, and what
|
|
8
|
+
-- forms on it may do at most (add, change, delete rows). Who may design
|
|
9
|
+
-- forms is an authorization scheme (config.design_authz); without one
|
|
10
|
+
-- nobody can. Those settings are part of the region, so they travel with
|
|
11
|
+
-- the application export.
|
|
12
|
+
--
|
|
13
|
+
-- A user form is a definition (source, fields with labels, help, required,
|
|
14
|
+
-- display and default, the columns of its row list, the actions it allows)
|
|
15
|
+
-- under a name, kept per region; published forms are used by everyone who
|
|
16
|
+
-- can see the region, drafts only by designers. User forms are data of the
|
|
17
|
+
-- installation (like meta.data_report): not part of the application export,
|
|
18
|
+
-- kept when an application is replaced. Applications reach the table only
|
|
19
|
+
-- through meta.user_forms and the two functions; the runtime checks every
|
|
20
|
+
-- definition against the region's offered columns before it renders or
|
|
21
|
+
-- saves, and reads and writes rows as the application's database role, so
|
|
22
|
+
-- grants and row level security apply.
|
|
23
|
+
-- ---------------------------------------------------------------------
|
|
24
|
+
alter table meta.region drop constraint region_type_check;
|
|
25
|
+
alter table meta.region add constraint region_type_check
|
|
26
|
+
check (type in ('report', 'form', 'chart', 'cards', 'static', 'grid', 'calendar', 'dynamic', 'facets', 'tasks', 'workflows', 'map', 'tree',
|
|
27
|
+
'template_component', 'smart_filters', 'display_selector', 'list', 'data_reporter', 'ai_assistant', 'plugin', 'url', 'search',
|
|
28
|
+
'login', 'form_designer'));
|
|
29
|
+
|
|
30
|
+
create table meta.user_form (
|
|
31
|
+
id serial primary key,
|
|
32
|
+
app_id int not null references meta.app on delete cascade,
|
|
33
|
+
region_id int not null references meta.region on delete cascade,
|
|
34
|
+
name text not null check (length(btrim(name)) between 1 and 80),
|
|
35
|
+
description text check (length(description) <= 500),
|
|
36
|
+
published boolean not null default false,
|
|
37
|
+
definition jsonb not null check (jsonb_typeof(definition) = 'object' and length(definition::text) <= 32000),
|
|
38
|
+
created_by text not null,
|
|
39
|
+
updated_by text not null,
|
|
40
|
+
created_at timestamptz not null default now(),
|
|
41
|
+
updated_at timestamptz not null default now(),
|
|
42
|
+
unique (region_id, name)
|
|
43
|
+
);
|
|
44
|
+
create index user_form_app_idx on meta.user_form (app_id);
|
|
45
|
+
revoke all on meta.user_form from public;
|
|
46
|
+
|
|
47
|
+
create view meta.user_forms with (security_barrier) as
|
|
48
|
+
select id, region_id, name, description, published, definition, created_by, updated_by, created_at, updated_at
|
|
49
|
+
from meta.user_form
|
|
50
|
+
where app_id = meta.app_id();
|
|
51
|
+
grant select on meta.user_forms to public;
|
|
52
|
+
|
|
53
|
+
-- Save a form of a Form Designer region of the current application: a new
|
|
54
|
+
-- one (p_id null) or an existing one (p_id). Returns its id. Whether the
|
|
55
|
+
-- user may design forms (the region's authorization scheme) is checked by
|
|
56
|
+
-- the runtime before it calls this.
|
|
57
|
+
create function meta.save_user_form(p_region int, p_id int, p_name text, p_description text, p_definition jsonb, p_published boolean default false)
|
|
58
|
+
returns int
|
|
59
|
+
language plpgsql security definer set search_path = meta, pg_catalog as $$
|
|
60
|
+
declare
|
|
61
|
+
v_user text := meta.app_user();
|
|
62
|
+
v_app int := meta.app_id();
|
|
63
|
+
v_id int;
|
|
64
|
+
begin
|
|
65
|
+
if v_user is null or v_user = 'nobody' then
|
|
66
|
+
raise exception 'sign in to design forms';
|
|
67
|
+
end if;
|
|
68
|
+
if not exists (select 1 from region r join page p on p.id = r.page_id where r.id = p_region and p.app_id = v_app and r.type = 'form_designer') then
|
|
69
|
+
raise exception 'unknown form designer region %', p_region;
|
|
70
|
+
end if;
|
|
71
|
+
begin
|
|
72
|
+
if p_id is null then
|
|
73
|
+
insert into user_form (app_id, region_id, name, description, published, definition, created_by, updated_by)
|
|
74
|
+
values (v_app, p_region, btrim(p_name), nullif(btrim(p_description), ''), coalesce(p_published, false), p_definition, v_user, v_user)
|
|
75
|
+
returning id into v_id;
|
|
76
|
+
else
|
|
77
|
+
update user_form
|
|
78
|
+
set name = btrim(p_name), description = nullif(btrim(p_description), ''), published = coalesce(p_published, false),
|
|
79
|
+
definition = p_definition, updated_by = v_user, updated_at = now()
|
|
80
|
+
where id = p_id and app_id = v_app and region_id = p_region
|
|
81
|
+
returning id into v_id;
|
|
82
|
+
if v_id is null then
|
|
83
|
+
raise exception 'form % does not exist', p_id;
|
|
84
|
+
end if;
|
|
85
|
+
end if;
|
|
86
|
+
exception when unique_violation then
|
|
87
|
+
raise exception 'There is already a form named "%".', btrim(p_name) using errcode = 'P0001';
|
|
88
|
+
end;
|
|
89
|
+
return v_id;
|
|
90
|
+
end
|
|
91
|
+
$$;
|
|
92
|
+
|
|
93
|
+
-- Delete a form of a Form Designer region of the current application.
|
|
94
|
+
create function meta.delete_user_form(p_region int, p_id int) returns boolean
|
|
95
|
+
language sql security definer set search_path = meta, pg_catalog as $$
|
|
96
|
+
with d as (delete from user_form where id = p_id and region_id = p_region and app_id = meta.app_id()
|
|
97
|
+
and meta.app_user() is not null and meta.app_user() <> 'nobody' returning 1)
|
|
98
|
+
select exists (select 1 from d)
|
|
99
|
+
$$;
|
|
100
|
+
|
|
101
|
+
revoke all on function meta.save_user_form(int, int, text, text, jsonb, boolean), meta.delete_user_form(int, int) from public;
|
|
102
|
+
grant execute on function meta.save_user_form(int, int, text, text, jsonb, boolean), meta.delete_user_form(int, int) to public;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- ---------------------------------------------------------------------
|
|
2
|
+
-- 107: an application's version (APEX: Application Definition → Version,
|
|
3
|
+
-- "Release 1.0"), shown in the footer of its pages with "Back to top".
|
|
4
|
+
-- New applications start with 'Release 1.0'; existing ones have none (no
|
|
5
|
+
-- version in the footer) until a developer sets one in Settings. It travels
|
|
6
|
+
-- with the export like the other columns of meta.app.
|
|
7
|
+
-- ---------------------------------------------------------------------
|
|
8
|
+
alter table meta.app add column version text check (length(version) <= 40);
|
|
9
|
+
comment on column meta.app.version is 'The application''s version, e.g. Release 1.0: shown in its pages'' footer (107)';
|
|
@@ -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-10-15 (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-10-15 (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
|
|
|
@@ -38,7 +38,7 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
38
38
|
| App Builder: create, edit, delete, run apps | ✅ | Builder at `/builder` |
|
|
39
39
|
| Create application wizard | ✅ | Blank app with its own database role and schema, started from a **boilerplate application** if wanted; **from a file**: CSV/TSV/XLSX/JSON/XML, where an Excel workbook with several sheets (or JSON with several arrays) becomes several tables, with a preview to include or leave out each sheet, edit table/column names, types and primary keys, and **foreign keys proposed** from matching columns; **from pasted data** (CSV/TSV text); **from existing tables** (pick the tables and views of a schema). Each gives a report and form per table, navigation and an optional dashboard (a chart per table), plus an optional faceted search for a single table, all created in one transaction. (sprint 73) **One page like APEX's**: name, icon and description, appearance (theme style, side or top menu, accent), a **page type per table** (interactive report with form, faceted search, cards, calendar, master detail, interactive grid, report, none; large tables proposed as a grid), **features** (About page, access control roles, activity reporting, feedback, theme style selection, PWA, push), settings (alias, authentication, first user, language) and a boilerplate under Advanced; a progress message, then straight to the new application. (sprint 71) The generated pages read like APEX's: human labels (abbreviations, run-together words, column and table comments), plural page and menu names with singular form titles, foreign keys shown by the parent's name in reports, `bytea` columns as one file item with their name/mime/size/updated columns, number format masks, a pencil per report row, the Dashboard after Home with *(none)* and top-N charts, and a Home page with a hero and a card per page. **Missing:** blueprints (26.1) |
|
|
40
40
|
| Create page wizards | ✅ | Report and form, interactive grid, form, cards, calendar, chart, map, faceted search and master-detail (stacked grids) from any table or view, with defaults from the catalog (columns, key, dates, positions, foreign keys), an optional modal form page and a navigation entry; also from SQL (`meta.generate_page`). No side-by-side or drill-down master-detail, no wizard for smart filters or trees |
|
|
41
|
-
| Page Designer | ✅ | IDE-style window (dark or light): component tree, a layout canvas with drag and drop (with keyboard and button alternatives) and a gallery of regions, items and buttons, a filterable property editor; undo/redo; panes become tabs on phones. Settings forms for report, grid, chart, cards, calendar, faceted search, smart filters, display selector, map, tree and template component regions. A code editor for SQL, PL/pgSQL, JSON and HTML with highlighting and autocomplete of tables, columns and `:ITEM` binds (no extra libraries). Drag and drop needs a mouse; on touch screens the Arrange buttons move components. (sprint 77) The layout draws the page template's display positions (banner, breadcrumb bar, left/right column, body, footer) as drop zones and a region's button positions; the rendering tree groups by position and has a context menu (create in or below, Duplicate, Copy to other page, expand/collapse all, delete); the property editor has Common / All, Go to group and a Template Options dialog; a page number in the toolbar. No nested regions (APEX's sub regions) and no Comment Out |
|
|
41
|
+
| Page Designer | ✅ | IDE-style window (dark or light): component tree, a layout canvas with drag and drop (with keyboard and button alternatives) and a gallery of regions, items and buttons, a filterable property editor; undo/redo; panes become tabs on phones. Settings forms for report, grid, chart, cards, calendar, faceted search, smart filters, display selector, map, tree and template component regions. A code editor for SQL, PL/pgSQL, JSON and HTML with highlighting and autocomplete of tables, columns and `:ITEM` binds (no extra libraries). Drag and drop needs a mouse; on touch screens the Arrange buttons move components. (sprint 77) The layout draws the page template's display positions (banner, breadcrumb bar, left/right column, body, footer) as drop zones and a region's button positions; the rendering tree groups by position and has a context menu (create in or below, Duplicate, Copy to other page, expand/collapse all, (sprint 90) Comment out with a COMMENTED_OUT build option, delete; no Create Sub Region: no nested regions); the property editor has Common / All, Go to group and a Template Options dialog; a page number in the toolbar. No nested regions (APEX's sub regions) and no Comment Out |
|
|
42
42
|
| Shared components | ✅ | (sprint 74) A grid of ten groups with counts like APEX's, a searchable, sortable list per type with Create, and Settings-backed types linking to their Settings tab ([mapping below](#shared-components-apex-links-and-pgkiln)). Navigation menu, **lists** (static entries with nesting, badges, conditions, authorization and build options, or a query; for list regions, the navigation menu and the navigation bar), authorization schemes, build options, lists of values, application items and processes, access control, globalization, template components and plug-ins, web credentials, REST data sources, data load definitions, supporting objects |
|
|
43
43
|
| Export / import | ✅ | `meta.export_app()` / `meta.import_app()`: portable JSON, also in the builder (new applications; `pgkiln import --replace` and the MCP `import_app` update one in place, live for every user at the commit). (sprint 51) **Checked imports**: `pgkiln import --check` (`--dry-run`, `--force`), the MCP import (by default) and the builder's import run the Advisor inside the import's transaction (SQL planned as the application's role: missing tables, columns, functions, types, grants; references) and refuse on errors, so nothing changes; APEX doesn't check. The version an import replaces is [backed up](guide/03-builder.md#backups) first ([chapter 18](guide/18-cli.md#checking-before-an-import)) |
|
|
44
44
|
| APEXlang: human-readable, diffable app files; static IDs (26.1) | ✅ | `pgkiln export --format dir`: one JSON file per component with sorted keys, SQL and HTML in sibling files, references by static id instead of database ids; `pgkiln import --replace` updates an app in place, `pgkiln diff` compares ([chapter 18](guide/18-cli.md)). (0.31) **`--format text`**: the same files as YAML (a strict subset any YAML tool reads) with the SQL and templates inline, read back losslessly ([text files](guide/18-cli.md#text-files-apexlang)); regions have a stored **Static ID** (exported as their key, rendered as `data-static-id`), other components are named by their stored names. The syntax is YAML rather than APEXlang's own, so APEXlang files don't import |
|
|
@@ -176,7 +176,7 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
176
176
|
| Translated applications (26.1: text-message-based translation of one app) | ✅ | One app with translations, like 26.1; XLIFF 1.2 and CSV export/import, coverage per language |
|
|
177
177
|
| Text messages (`APEX_LANG.MESSAGE`, `&APP_TEXT$…`) | ✅ | `meta.message()`, `&APP_TEXT$NAME.`, fallback to the base and primary language |
|
|
178
178
|
| Language from browser, preference or session | ✅ | Browser, user preference or primary; `?lang=`; right-to-left languages |
|
|
179
|
-
| Date and timestamp format masks | ✅ | Per app or per language; (sprint 76) date items show and read the application's date format (or their own) with a calendar button |
|
|
179
|
+
| Date and timestamp format masks | ✅ | Per app or per language; (sprint 76) date items show and read the application's date format (or their own) with a calendar button; (sprint 84) pgkiln's date picker (keyboard, week start, Today, Clear) for date items, date ranges, grid date cells and facet date ranges; timestamps keep the browser's field |
|
|
180
180
|
| 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 |
|
|
181
181
|
| 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)) |
|
|
182
182
|
|
|
@@ -269,6 +269,9 @@ Small but real differences, for teams comparing the two:
|
|
|
269
269
|
- An import can be checked before it commits (`pgkiln import --check`): SQL that names a missing
|
|
270
270
|
table or column refuses the deployment instead of failing at run time.
|
|
271
271
|
- E-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs, not only SMTP with a password.
|
|
272
|
+
- (sprint 85) A **Form Designer** region ([chapter 4](guide/04-pages-and-regions.md#form_designer-form-designer)): the
|
|
273
|
+
application's administrators build and publish data entry forms in the running application, on the tables and
|
|
274
|
+
columns the developer offers, with grants, row level security and lost update detection applying.
|
|
272
275
|
|
|
273
276
|
## Roadmap (proposed priority)
|
|
274
277
|
|
package/docs/guide/03-builder.md
CHANGED
|
@@ -199,6 +199,11 @@ Every builder page has the same frame, modelled on an IDE:
|
|
|
199
199
|
|
|
200
200
|
On phones the rail gets narrower and the breadcrumb shows only the current page.
|
|
201
201
|
|
|
202
|
+
(sprint 86) An address under `/builder` that leads nowhere (a deleted application or page, a typo, an
|
|
203
|
+
application of a workspace you are not a member of) shows a **Page not found** page in the builder's
|
|
204
|
+
theme with a link to the App Builder home; a server error shows **Something went wrong** (the error
|
|
205
|
+
is in the server log, not on the page). Scripts get the plain answers they always got.
|
|
206
|
+
|
|
202
207
|
## App Builder home
|
|
203
208
|
|
|
204
209
|
The home page is laid out like APEX's App Builder:
|
|
@@ -251,15 +256,15 @@ start from a file, pasted data, a blueprint or the App Gallery instead. Then:
|
|
|
251
256
|
|
|
252
257
|
| Section | Field | Meaning |
|
|
253
258
|
|---|---|---|
|
|
254
|
-
| Data | Pages on the tables of | The parsing schema: an existing schema (
|
|
259
|
+
| Data | Pages on the tables of | The parsing schema: an existing schema, or a new, empty one named after the alias. (sprint 87) Choosing a schema lists its tables under Pages at once, with the name and alias proposed for it (unless you already typed them); without JavaScript, *Show its tables* does it |
|
|
255
260
|
| Application | Name | Display name, shown in the header. Proposed from the schema and selected when you click it, so typing replaces it |
|
|
256
261
|
| | Description, Icon | Shown on the home page's hero and the About page |
|
|
257
262
|
| Appearance | Theme style, Navigation, Accent colour | Iris, Lavender or Standard; a side or top menu; an own accent colour |
|
|
258
|
-
| Pages | a page type per table | *Interactive report with form*, *Faceted search*, *Cards*, *Calendar* (a table with a date column), *Master detail* (a table another table refers to), *Interactive grid*, *Report* or *No page*. Tables with a single-column primary key get a modal form with their report, faceted search, cards and calendar; views and tables without such a key can't have a form or a grid. Proposed: a report with form, an interactive grid for a table of more than 100,000 rows, a report for a view. *Dashboard*: a chart per table |
|
|
263
|
+
| Pages | a page type per table | *Interactive report with form*, *Faceted search*, *Cards*, *Calendar* (a table with a date column), *Master detail* (a table another table refers to), *Interactive grid*, *Report* or *No page*. Tables with a single-column primary key get a modal form with their report, faceted search, cards and calendar; views and tables without such a key can't have a form or a grid. Proposed: a report with form, an interactive grid for a table of more than 100,000 rows, a report for a view. (sprint 87) A table with [row level security](08-security.md) shows *RLS · n* (its number of policies), or *RLS, no policies* in red: the application's role would see no rows. *Dashboard*: a chart per table |
|
|
259
264
|
| Features | | *About page* (in a Help menu), *Access control* (authorization schemes `CONTRIBUTOR` and `READER` next to `ADMIN`, for the roles admin, contributor and reader), *Activity reporting* (page 9010 for administrators: page views per day and the latest activity, from `meta.app_activity`), *Feedback*, *Theme style selection* (users may choose light or dark), *Install as an app* (PWA) and *Push notifications* (needs `PGKILN_SECRET_KEY`) |
|
|
260
|
-
| Settings | Alias | Lowercase URL name: `inventory` gives `/a/inventory` |
|
|
265
|
+
| Settings | Alias | Lowercase URL name: `inventory` gives `/a/inventory`. (sprint 87) It follows the name as you type it (*Café Orders* → `cafe-orders`) until you change it yourself |
|
|
261
266
|
| | Authentication | *App users* (a login page and a user list), *HTTP header* (a trusted reverse proxy names the user, see [chapter 8](08-security.md#http-header-authentication-reverse-proxy)), *Database accounts* (PostgreSQL login roles and their passwords, see [chapter 8](08-security.md#database-accounts-postgresql-roles)), *Custom* (your own PL/pgSQL function, see [chapter 8](08-security.md#custom-authentication-a-plpgsql-function)) or *None* (a public app) |
|
|
262
|
-
| | First user / Password | The first user; they get the `admin` role. An existing account is reused (its password isn't changed) |
|
|
267
|
+
| | First user / Password | The first user; they get the `admin` role. An existing account is reused (its password isn't changed). (sprint 87) Hidden while Authentication is *None* |
|
|
263
268
|
| | Language | The application's primary language |
|
|
264
269
|
| Advanced | Start from | Shown when there are **boilerplate** applications (Settings → Application type): their pages, shared components and settings are copied into the new application, which keeps its own name, alias, role and authentication ([application types](#application-types-and-subscriptions)) |
|
|
265
270
|
|
|
@@ -268,7 +273,9 @@ Creating the app also:
|
|
|
268
273
|
- creates the database role `app_<alias>` with `SELECT/INSERT/UPDATE/DELETE` on all tables,
|
|
269
274
|
`USAGE` on sequences and `EXECUTE` on functions in the schema, plus **default privileges**,
|
|
270
275
|
so tables you create later (as the owner, e.g. in the SQL Workshop) are usable by the app straight away;
|
|
271
|
-
- creates page 1 *Home*, a navigation entry, and an authorization scheme `ADMIN` (role `admin`);
|
|
276
|
+
- creates page 1 *Home*, a navigation entry, and an authorization scheme `ADMIN` (role `admin`); (sprint 88) the home
|
|
277
|
+
page is a hero with the name and icon on the page background and a card per page, each with a colour band and its
|
|
278
|
+
icon in a round badge; the version is *Release 1.0*;
|
|
272
279
|
- shows a progress message while it works and then opens the new application's page in the builder,
|
|
273
280
|
with what was created (and anything left out) as a message.
|
|
274
281
|
|
|
@@ -539,6 +546,11 @@ its pages in four groups.
|
|
|
539
546
|
|
|
540
547
|
## The page designer
|
|
541
548
|
|
|
549
|
+
(sprint 86) A page's address in the page designer is its application's id and its number:
|
|
550
|
+
`/builder/apps/<app id>/pages/<page number>`, with `?c=region-<id>` (and so on) for the selected
|
|
551
|
+
component, so a link names the page you mean. The older `/builder/pages/<internal id>` still works:
|
|
552
|
+
a browser that opens it is sent to the page's number.
|
|
553
|
+
|
|
542
554
|
The page designer has three panes, as in APEX's Page Designer. From 1024 pixels wide they sit
|
|
543
555
|
side by side; on phones and portrait tablets they are tabs (**Tree**, **Layout**, **Properties**):
|
|
544
556
|
choosing a component opens the Properties tab.
|
|
@@ -567,8 +579,12 @@ choosing a component opens the Properties tab.
|
|
|
567
579
|
*Create dynamic action*, *Create region below*, **Duplicate** (a copy right after it; a region comes with its
|
|
568
580
|
items and buttons, names get `_2`), **Copy to other page…** (to the end of a page of the same application; items
|
|
569
581
|
named `P<n>_` get that page's number, a region's buttons and items come along, references in SQL are not changed),
|
|
570
|
-
*Expand all below*, *Collapse all below
|
|
571
|
-
|
|
582
|
+
*Expand all below*, *Collapse all below*, (sprint 90) **Comment out** and *Delete*. The arrow keys move through the
|
|
583
|
+
menu, Escape closes it. **Comment out** (APEX's) leaves a component (a region, item, button, dynamic action,
|
|
584
|
+
validation, process, computation or branch) out of the page without deleting it: it gets the
|
|
585
|
+
[build option](#shared-components) `COMMENTED_OUT`, made with the status *Exclude* when first needed, and is struck
|
|
586
|
+
through in the tree; **Uncomment** takes it off again (another build option of the component is left alone).
|
|
587
|
+
APEX's *Create Sub Region* is not there: pgkiln has no nested regions.
|
|
572
588
|
- **Middle: the Layout**: the page template's display positions as labelled zones (Banner, Breadcrumb bar,
|
|
573
589
|
the side column of a side-column template beside the Body, Footer), each with its regions on the 12-column
|
|
574
590
|
grid, each region with its items and its buttons in their button positions, as they will be placed on the page; under it a **gallery** of region types, item types
|
|
@@ -692,6 +708,7 @@ out, other keys are kept, columns the query no longer returns stay listed so you
|
|
|
692
708
|
| `ai_assistant` | The AI service (those the application may use), system prompt, welcome text, placeholder, error message, tool rounds per question, questions per conversation, public or not, and the context queries and tools as JSON (checked when saving: query shapes, parameter types, REST data sources and authorization schemes that exist) ([AI assistant](04-pages-and-regions.md#ai_assistant-ai-assistant)) |
|
|
693
709
|
| `report` (also) | *Ask in your own words (AI)*: the AI service and placeholder of the [natural-language filters](04-pages-and-regions.md#natural-language-filters-ask-in-your-own-words) |
|
|
694
710
|
| `data_reporter` | Data sources (a table or view each: static id, label, description, offered columns with labels and format masks), who may share reports, rows per page ([Data Reporter](04-pages-and-regions.md#data_reporter-data-reporter)) |
|
|
711
|
+
| `form_designer` | Who may design forms (an authorization scheme), data sources (a table or view each: static id, label, description, key column, may add / change / delete rows, offered columns with labels and lists of values), rows per page ([Form Designer](04-pages-and-regions.md#form_designer-form-designer)) |
|
|
695
712
|
|
|
696
713
|
Links, lists of values and the facets' report are checked when saving: a form can only point to
|
|
697
714
|
pages and shared lists of values of the same application, and to report regions on the same page.
|
|
@@ -1011,7 +1028,9 @@ on Definition (`?tab=…` opens another). *Save settings* saves the first five t
|
|
|
1011
1028
|
you were on. The Security tab shows only the fields of the chosen authentication type (HTTP header, database
|
|
1012
1029
|
accounts or custom).
|
|
1013
1030
|
|
|
1014
|
-
- **Application**: name, alias, home page.
|
|
1031
|
+
- **Application**: name, alias, home page, and (sprint 88) the **version** (APEX: Version, e.g. *Release 1.0*): shown
|
|
1032
|
+
at the bottom of the application's pages, next to *Back to top*. New applications start at *Release 1.0*; empty: no
|
|
1033
|
+
version in the footer.
|
|
1015
1034
|
- **Security**: authentication (*App users*, *HTTP header*, *Database accounts*, *Custom* or
|
|
1016
1035
|
*None*), the database role, and **debug mode** (shows full database errors to users; development
|
|
1017
1036
|
only). The state of the [debug messages](06-processing.md#debug-messages) is shown below it,
|
|
@@ -1241,17 +1260,22 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
|
|
|
1241
1260
|
statements are allowed; the result of the last one is shown (up to 500 rows). Press
|
|
1242
1261
|
**Ctrl/Cmd + Enter** to run. The [code editor](#the-code-editor) suggests every schema, table,
|
|
1243
1262
|
column and function the owner sees.
|
|
1244
|
-
- **Object Browser** (APEX's): the **schema** in the header
|
|
1263
|
+
- **Object Browser** (APEX's): the **schema** in the header and a tree with a
|
|
1245
1264
|
folder per object type (tables, views, materialized views, indexes, sequences, types, functions, procedures,
|
|
1246
1265
|
triggers) and a **filter** by name. pgkiln's own schemas (`meta`, `pgkiln_plugins`) and objects that belong to an
|
|
1247
1266
|
extension show only with **Show system objects**. **Create** (and the tiles shown when nothing is selected) opens
|
|
1248
1267
|
SQL Commands with a CREATE TABLE, VIEW, FUNCTION, SEQUENCE or INDEX statement to fill in. A table opens in tabs:
|
|
1249
|
-
**Columns** (with comments; *Add*, *Rename* and *Drop column* write
|
|
1250
|
-
review and run: nothing changes until you press Run), **Data** (25
|
|
1268
|
+
**Columns** (with comments; the toolbar's *Add*, *Modify* (type, nulls, default), *Rename* and *Drop column* write
|
|
1269
|
+
the ALTER TABLE statement into SQL Commands to review and run: nothing changes until you press Run), **Data** (25
|
|
1270
|
+
rows a page; NULL is a blank cell), **Indexes**, **Constraints**
|
|
1251
1271
|
(primary key, foreign keys with the table they refer to, unique, check), **Triggers**, **Grants**, **Row level
|
|
1252
1272
|
security** (on or off, the policies), **Dependencies** (views and foreign keys that use it, and what it uses),
|
|
1253
1273
|
**Statistics** (rows, sizes, analyze and vacuum times) and **DDL**. A view has the same tabs where they apply; a
|
|
1254
|
-
function or procedure shows its source, a trigger, index, sequence or type its definition.
|
|
1274
|
+
function or procedure shows its source, a trigger, index, sequence or type its definition. (sprint 89) The tabs stay
|
|
1275
|
+
on one row: Columns, Data, Indexes, Constraints and DDL (and the current one), the others under **More**. The
|
|
1276
|
+
schema shown is the one you chose last (remembered for the session), else the session's schema of SQL Commands,
|
|
1277
|
+
else the **parsing schema** of the application changed last in your workspace (the schema its database role
|
|
1278
|
+
uses).
|
|
1255
1279
|
- **SQL Scripts**: saved scripts, shared by the developers of the workspace. Create one in the editor, upload a
|
|
1256
1280
|
`.sql` file (UTF-8, up to 5 MB) or save one from Quick SQL; download it again as `.sql`. **Run**
|
|
1257
1281
|
splits the script into statements at semicolons (outside strings, comments, quoted identifiers,
|
|
@@ -819,7 +819,9 @@ Counts take the search and all *other* facets into account. Three kinds of facet
|
|
|
819
819
|
|
|
820
820
|
- **checkbox** (the default): the most frequent values of a column, each with a checkbox; after the seventh
|
|
821
821
|
the rest sit under *Show all (n)* (open when one of them is chosen), and a boolean's values read *Yes* and
|
|
822
|
-
*No*.
|
|
822
|
+
*No*. Its ⋮ menu (APEX: the facet's menu) has *Clear* (when values are chosen) and *Sort by count* (the
|
|
823
|
+
default) or *Sort by name*; the order is a URL parameter (`r<report id>_fo_<column>=name`) that Apply and
|
|
824
|
+
Reset keep. With
|
|
823
825
|
`"exclude": true` the facet gets an *Exclude the selected values* switch: the chosen values are
|
|
824
826
|
then left out instead (rows where the column is empty stay).
|
|
825
827
|
- **range**: a number or date column in ranges, as radio buttons ("Any", then each range). A
|
|
@@ -1127,7 +1129,7 @@ Attributes (the region's **Settings** in the page designer):
|
|
|
1127
1129
|
| Key | Meaning |
|
|
1128
1130
|
|---|---|
|
|
1129
1131
|
| `list` | The list's name (upper case) |
|
|
1130
|
-
| `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) |
|
|
1132
|
+
| `template` | `links` (default: nested links), `badges` (a row of tiles with the badge as the value), `cards` (a card per entry with its description; (sprint 88) a colour band and the icon in a round badge, in the chart palette's order), `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) |
|
|
1131
1133
|
|
|
1132
1134
|
The HR example's page 31 (Shortcuts) shows a static list with each template (with a badge from an
|
|
1133
1135
|
item, child entries, a manager-only entry and one of an excluded build option) and a department
|
|
@@ -1198,6 +1200,76 @@ region when an application is replaced. The HR example's page 36 (*My reports*)
|
|
|
1198
1200
|
(a view without the user name and photo columns) and leave requests (row level security: an
|
|
1199
1201
|
employee sees only their own), with King's shared report *Salary by department*.
|
|
1200
1202
|
|
|
1203
|
+
### `form_designer` (Form Designer)
|
|
1204
|
+
|
|
1205
|
+
A **Form Designer** region (sprint 85; pgkiln's own, APEX has no counterpart) lets the application's
|
|
1206
|
+
administrators build their own data entry forms in the running application, without a developer
|
|
1207
|
+
and without a new release. Like the [Data Reporter](#data_reporter-data-reporter), the developer
|
|
1208
|
+
decides *what* may be edited; the administrators decide *how* the forms look and who uses them.
|
|
1209
|
+
|
|
1210
|
+
**The developer** places the region (page designer gallery: *Form Designer*) and, in its
|
|
1211
|
+
**Settings**, chooses **who may design forms** (an [authorization scheme](08-security.md); without
|
|
1212
|
+
one nobody can) and adds **data sources**: a table or view each (pgkiln's own `meta` schema and the
|
|
1213
|
+
system schemas are never offered), with a static id, a label and a description. Per source:
|
|
1214
|
+
|
|
1215
|
+
- the **columns** forms may show and change, with a label and, for a select list or radio group,
|
|
1216
|
+
a **list of values**: a shared one of the application (`LOV:NAME`) or `STATIC:Display;value,…`
|
|
1217
|
+
(never SQL: designers can't write queries);
|
|
1218
|
+
- the **key column** that identifies a row (the primary key of a new table; choose one for a view),
|
|
1219
|
+
needed to change and delete rows;
|
|
1220
|
+
- what forms on it **may** do at most: **add**, **change** and **delete** rows.
|
|
1221
|
+
|
|
1222
|
+
A new source offers all its columns except binary and JSON ones, allows adding and (with a key)
|
|
1223
|
+
changing rows, never deleting. Untick generated keys and audit columns; the builder warns when the
|
|
1224
|
+
application's database role lacks a privilege a source needs.
|
|
1225
|
+
|
|
1226
|
+
**Designers** (users that pass the scheme) see *New form* and a *Design form* link under each
|
|
1227
|
+
form. The designer is a plain form (it works without JavaScript): a name, a description, what
|
|
1228
|
+
users may do (within what the source allows) and a row per offered column: *On the form*,
|
|
1229
|
+
*Order*, *Label*, *Help text*, *Required*, *Display* (a field by the column's type; a text area for
|
|
1230
|
+
text; a select list or radio group for a column with a list of values) and a *Default* for new
|
|
1231
|
+
rows, and *In the list* for the columns of the form's list of rows. A form is a **draft** until
|
|
1232
|
+
*Published* is ticked: only designers see drafts.
|
|
1233
|
+
|
|
1234
|
+
**Users** see the published forms as cards. A form with list columns opens on its rows (newest
|
|
1235
|
+
first, paged, `page_size`) with *Add* and an *Edit* link per row; a form without list columns
|
|
1236
|
+
only adds rows: it opens on an empty form, and after *Save* on the next empty one. Fields follow
|
|
1237
|
+
the column's type: a number field, the [date picker](05-items.md#the-date-picker) in the
|
|
1238
|
+
application's date format for dates, the browser's date and time field for timestamps, a
|
|
1239
|
+
checkbox for booleans.
|
|
1240
|
+
|
|
1241
|
+
How it stays safe:
|
|
1242
|
+
|
|
1243
|
+
- rows are read and written as the **application's database role**: grants and [row level
|
|
1244
|
+
security](08-security.md) apply (in the HR example an employee changes only their own meetings);
|
|
1245
|
+
- a form's definition is checked against the region's settings before it renders or saves: only
|
|
1246
|
+
offered columns that exist and can be read, displays the column's type allows, actions the
|
|
1247
|
+
source allows; anything else is dropped. Only the form's fields are written; identifiers are
|
|
1248
|
+
only the developer's schema, table and column names, always quoted; values and row keys are
|
|
1249
|
+
always parameters; a value of a list of values must be in the list;
|
|
1250
|
+
- **lost updates** are refused: a row changed since its form was opened is not overwritten (the
|
|
1251
|
+
user sees what they typed, with a message);
|
|
1252
|
+
- forms are stored in `meta.user_form`, reached by applications only through the view
|
|
1253
|
+
`meta.user_forms` (the forms of the application) and the functions `meta.save_user_form` /
|
|
1254
|
+
`meta.delete_user_form`; saving rows and forms needs the CSRF token and a region the user can
|
|
1255
|
+
see, designing also the region's authorization scheme. Every saved, changed or deleted row and
|
|
1256
|
+
form is in the activity log (event `form_designer`).
|
|
1257
|
+
|
|
1258
|
+
Attributes (written by the region's **Settings**):
|
|
1259
|
+
|
|
1260
|
+
| Key | Default | Meaning |
|
|
1261
|
+
|---|---|---|
|
|
1262
|
+
| `sources` | | `[{"id": "orders", "label": "Orders", "description": "…", "schema": "sales", "table": "orders", "key": "id", "columns": [{"name": "customer", "label": "Customer"}, {"name": "status", "lov": "LOV:ORDER_STATUS"}], "insert": true, "update": true, "delete": false}]` |
|
|
1263
|
+
| `design_authz` | | The authorization scheme designers pass; none: nobody designs |
|
|
1264
|
+
| `page_size` | `25` | Rows per page of a form's list (5 to 200) |
|
|
1265
|
+
| `empty` | `No data found.` | Text when a form's list has no rows |
|
|
1266
|
+
|
|
1267
|
+
The sources travel with the application export (they are the region's attributes); the forms are
|
|
1268
|
+
data of the installation, like Data Reporter reports: not exported, and they stay with their
|
|
1269
|
+
region when an application is replaced. The HR example's page 45 (*Forms*, under Administration)
|
|
1270
|
+
offers departments, meetings and employees (changing only) to administrators, with the published
|
|
1271
|
+
forms *Departments* and *Book a meeting*.
|
|
1272
|
+
|
|
1201
1273
|
### `ai_assistant` (AI assistant)
|
|
1202
1274
|
|
|
1203
1275
|
An **AI assistant** region (APEX: AI Assistant, AI agents and tools) is a chat with an
|
package/docs/guide/05-items.md
CHANGED
|
@@ -11,7 +11,7 @@ page, optionally inside a region. Name them `P<page>_<NAME>` (uppercase letters,
|
|
|
11
11
|
| `text` | text field | text |
|
|
12
12
|
| `textarea` | multi-line text (always full width) | text |
|
|
13
13
|
| `number` | number field (numeric keyboard on phones) | e.g. `1250.50` |
|
|
14
|
-
| `date` |
|
|
14
|
+
| `date` | a text field in the item's date format mask, else the application's date format, else `YYYY-MM-DD`, with pgkiln's [date picker](#the-date-picker) (sprint 84; was the browser's); typed dates are read back in the format | `YYYY-MM-DD` |
|
|
15
15
|
| `datetime` | date-time picker | `YYYY-MM-DDTHH:MM` |
|
|
16
16
|
| `email`, `tel`, `url` | typed fields with the matching phone keyboard | text |
|
|
17
17
|
| `password` | password field; never shown back, empty = unchanged | text |
|
|
@@ -31,7 +31,7 @@ page, optionally inside a region. Name them `P<page>_<NAME>` (uppercase letters,
|
|
|
31
31
|
| `markdown` | Markdown textarea with a toolbar; shown formatted when read-only | the Markdown text |
|
|
32
32
|
| `rating` | star rating (radio buttons drawn as stars) | `1` … `max` (default 5) |
|
|
33
33
|
| `combobox` | free text with suggestions from the list of values; several values become tags | **colon-separated** values, e.g. `SQL:Sales` |
|
|
34
|
-
| `daterange` | two date
|
|
34
|
+
| `daterange` | two date fields, *From* and *To*, in the date format with the date picker (the picker keeps *From* on or before *To*) | `from:to`, e.g. `2026-01-01:2026-06-30` |
|
|
35
35
|
| `qrcode` | display only: the value as a QR code (SVG drawn on the server) | whatever was set |
|
|
36
36
|
| `image` | display only: a picture from a URL in the value, or a BLOB from a query ([Display image](#display-image-and-geocoded-address)) | a URL, or nothing |
|
|
37
37
|
| `address` | a text field with *Check address*: the installation's geocoder offers matching addresses ([Geocoded address](#display-image-and-geocoded-address)) | the address as text |
|
|
@@ -51,6 +51,18 @@ where hiredate between nullif(split_part(:P20_PERIOD, ':', 1), '')::date
|
|
|
51
51
|
and coalesce(nullif(split_part(:P20_PERIOD, ':', 2), '')::date, 'infinity')
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
|
|
55
|
+
### The date picker
|
|
56
|
+
|
|
57
|
+
(sprint 84; APEX: the date picker) A date item, a date range item, an interactive grid's date cell and a
|
|
58
|
+
faceted search's own date range and the task list's vacation rule are text in the date format: the item's date format mask, else the
|
|
59
|
+
application's date format (Settings → Globalization), else `YYYY-MM-DD`. The calendar button next to the
|
|
60
|
+
field (or Alt+↓ in it) opens a month of days under it: the chosen day marked, today outlined, the week
|
|
61
|
+
starting on the language's first day. Arrow keys move a day or a week, Page Up and Page Down a month
|
|
62
|
+
(with Shift a year), Home and End to the week's first and last day, Enter or Space choose, Escape
|
|
63
|
+
closes; *Today* and *Clear* below. Typed dates are read back in the format (and `YYYY-MM-DD` always
|
|
64
|
+
works), so the field works without JavaScript. Timestamp items and grid timestamp cells still use the
|
|
65
|
+
browser's date and time field.
|
|
54
66
|
## Properties
|
|
55
67
|
|
|
56
68
|
| Property | Meaning |
|
|
@@ -427,7 +427,7 @@ navigation entries and application processes have the same `build_option` column
|
|
|
427
427
|
| Column | Description |
|
|
428
428
|
|---|---|
|
|
429
429
|
| `page_id`, `seq`, `title` | |
|
|
430
|
-
| `type` | `report`, `grid`, `form`, `chart`, `cards`, `calendar`, `facets`, `smart_filters`, `display_selector`, `map`, `tree`, `template_component`, `list`, `data_reporter`, `ai_assistant`, `tasks`, `workflows`, `static`, `dynamic` |
|
|
430
|
+
| `type` | `report`, `grid`, `form`, `chart`, `cards`, `calendar`, `facets`, `smart_filters`, `display_selector`, `map`, `tree`, `template_component`, `list`, `data_reporter`, `form_designer`, `ai_assistant`, `tasks`, `workflows`, `static`, `dynamic` |
|
|
431
431
|
| `source` | SELECT (or HTML for `static`) |
|
|
432
432
|
| `table_name`, `pk_column` | For `form` and `grid` |
|
|
433
433
|
| `pk_item` | For `form`: the item holding the key |
|
|
@@ -169,7 +169,8 @@ Tips:
|
|
|
169
169
|
together.
|
|
170
170
|
- **Errors are hidden by default**: unexpected errors show a reference number unless the app is in
|
|
171
171
|
debug mode.
|
|
172
|
-
- **Dates**: date items
|
|
172
|
+
- **Dates**: date items, date ranges, grid date cells and facet ranges are text in the application's date format
|
|
173
|
+
(else ISO, `2026-10-01`) with pgkiln's date picker; format masks
|
|
173
174
|
apply to report, grid and cards columns and to number and display items
|
|
174
175
|
([number formats](14-globalization.md#number-formats)).
|
|
175
176
|
- **Modal pages** open over the calling page, and close and refresh it after a successful submit,
|
|
@@ -154,6 +154,8 @@ src/
|
|
|
154
154
|
tasks.ts task list region and task actions (approvals); (094) the vacation rule panel and route
|
|
155
155
|
data-reporter.ts Data Reporter region (migration 057): sources from the region's config, checkDef (offered columns, whitelists),
|
|
156
156
|
reportQuery/chartQuery, the list and editor (GET form), save/delete routes (meta.save_data_report)
|
|
157
|
+
form-designer.ts Form Designer region (migration 106): sources from the region's config, checkFormDef (offered columns, displays,
|
|
158
|
+
actions), forms as cards, a form's rows, a row's form (lost update hash), the designer; row/design/delete routes
|
|
157
159
|
workflows.ts workflow console region and its actions
|
|
158
160
|
ai.ts Generate text with AI: the ai_generate process (config checks, &ITEM. as delimited escaped data,
|
|
159
161
|
schemas from items, answers into items), aiInputs/aiOutputs for its dynamic action (route in routes.ts)
|
|
@@ -209,7 +211,9 @@ src/
|
|
|
209
211
|
mail.ts Workspace utilities → Mail services (administrators: providers, write-only secret, allowed senders,
|
|
210
212
|
applications with From and daily limit, test) and Applications → Activity → Mail (retry, cancel)
|
|
211
213
|
shared.ts Shared Components and access control
|
|
212
|
-
designer.ts page designer: component tree (with computations and branches), layout canvas and gallery, property editor, toolbar
|
|
214
|
+
designer.ts page designer: component tree (with computations and branches), layout canvas and gallery, property editor, toolbar;
|
|
215
|
+
(sprint 86) GET /builder/apps/:app/pages/:no, /builder/pages/:id redirects browsers there (designerUrl in ui.ts)
|
|
216
|
+
errors.ts (sprint 86) the builder's HTML 404 and 500 pages for browsers (wantsHtml, a not-found handler and an onSend hook)
|
|
213
217
|
arrange.ts page designer layout changes: move, column span, create from the gallery, undo / redo
|
|
214
218
|
sql.ts SQL Workshop: the home and SQL commands (templates and drafts to review)
|
|
215
219
|
object-browser.ts (sprint 75) the Object Browser: objects by type, system objects hidden, a table in tabs, column actions as SQL to review
|
|
@@ -241,6 +245,7 @@ src/
|
|
|
241
245
|
themeroller.ts Settings → Theme Roller: style variants (add, edit, rename, delete), default style, users may choose
|
|
242
246
|
subscriptions.ts Shared Components → Subscriptions: subscribe, refresh, unsubscribe, subscribers and publish; the note under a component
|
|
243
247
|
reporter.ts page designer: Data Reporter settings (sources: table or view, offered columns, labels, masks; sharing)
|
|
248
|
+
form-designer.ts page designer: Form Designer settings (designers' scheme; sources: key, actions, offered columns, labels, lists of values)
|
|
244
249
|
workingcopies.ts Working copies: list and create, compare with differences, merge or refresh with conflict choices, delete
|
|
245
250
|
rest.ts REST module endpoints list and curl example (Shared Components)
|
|
246
251
|
workflows.ts workflow versions, diagram and instances (Shared Components)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- HR example, part 61: a Form Designer (docs/guide/04-pages-and-regions.md,
|
|
3
|
+
-- "Form Designer")
|
|
4
|
+
--
|
|
5
|
+
-- Page 45 "Forms": the application's administrators (authorization scheme
|
|
6
|
+
-- ADMIN) build data entry forms on three tables the developer offers in the
|
|
7
|
+
-- region's settings, and publish them for every employee:
|
|
8
|
+
-- - "Departments": hr.dept, add and change rows;
|
|
9
|
+
-- - "Meetings": hr.meeting, add, change and delete rows; its row level
|
|
10
|
+
-- security still applies (an employee changes only their own meetings);
|
|
11
|
+
-- - "Employees": hr.emp, change rows only, with the job and department
|
|
12
|
+
-- as lists of values.
|
|
13
|
+
-- Two published forms are there to start from: "Departments" (a list of
|
|
14
|
+
-- departments with Add and Edit) and "Book a meeting" (no list: the form
|
|
15
|
+
-- only adds rows). Forms are installation data: not part of the export.
|
|
16
|
+
-- =====================================================================
|
|
17
|
+
|
|
18
|
+
insert into meta.page (app_id, page_no, name, title, parent_page)
|
|
19
|
+
select id, 45, 'Forms', 'Forms', 1 from meta.app where alias = 'hr';
|
|
20
|
+
|
|
21
|
+
insert into meta.region (page_id, seq, title, type, columns, template, config)
|
|
22
|
+
select p.id, 10, 'Form Designer', 'form_designer', 12, 'standard', $j${
|
|
23
|
+
"design_authz": "ADMIN",
|
|
24
|
+
"page_size": 15,
|
|
25
|
+
"sources": [
|
|
26
|
+
{"id": "departments", "label": "Departments", "description": "Department names and locations.",
|
|
27
|
+
"schema": "hr", "table": "dept", "key": "deptno", "insert": true, "update": true, "delete": false,
|
|
28
|
+
"columns": [{"name": "dname", "label": "Department"}, {"name": "loc", "label": "Location"}]},
|
|
29
|
+
{"id": "meetings", "label": "Meetings", "description": "Meetings in the planner; employees change only their own.",
|
|
30
|
+
"schema": "hr", "table": "meeting", "key": "id", "insert": true, "update": true, "delete": true,
|
|
31
|
+
"columns": [{"name": "title", "label": "Title"}, {"name": "starts_at", "label": "Starts"}, {"name": "ends_at", "label": "Ends"}, {"name": "private", "label": "Private"}]},
|
|
32
|
+
{"id": "employees", "label": "Employees", "description": "Job, department and salary of employees.",
|
|
33
|
+
"schema": "hr", "table": "emp", "key": "empno", "insert": false, "update": true, "delete": false,
|
|
34
|
+
"columns": [{"name": "ename", "label": "Name"}, {"name": "job", "label": "Job", "lov": "LOV:JOBS"}, {"name": "deptno", "label": "Department", "lov": "LOV:DEPARTMENTS"},
|
|
35
|
+
{"name": "hiredate", "label": "Hire date"}, {"name": "sal", "label": "Salary"}]}
|
|
36
|
+
]}$j$::jsonb
|
|
37
|
+
from meta.page p join meta.app a on a.id = p.app_id
|
|
38
|
+
where a.alias = 'hr' and p.page_no = 45;
|
|
39
|
+
|
|
40
|
+
-- two published forms to start from (forms are installation data: not part of the export)
|
|
41
|
+
insert into meta.user_form (app_id, region_id, name, description, published, definition, created_by, updated_by)
|
|
42
|
+
select a.id, r.id, f.name, f.description, true, f.definition, 'king', 'king'
|
|
43
|
+
from meta.app a join meta.page p on p.app_id = a.id and p.page_no = 45 join meta.region r on r.page_id = p.id and r.type = 'form_designer',
|
|
44
|
+
(values
|
|
45
|
+
('Departments', 'Add a department or change its name and location.',
|
|
46
|
+
'{"source": "departments",
|
|
47
|
+
"fields": [{"column": "dname", "label": "", "help": "", "required": true, "display": "auto", "default": ""},
|
|
48
|
+
{"column": "loc", "label": "", "help": "The city.", "required": false, "display": "auto", "default": ""}],
|
|
49
|
+
"list": ["dname", "loc"], "actions": {"insert": true, "update": true, "delete": false}}'::jsonb),
|
|
50
|
+
('Book a meeting', 'Put a meeting in the planner.',
|
|
51
|
+
'{"source": "meetings",
|
|
52
|
+
"fields": [{"column": "title", "label": "What", "help": "", "required": true, "display": "auto", "default": ""},
|
|
53
|
+
{"column": "starts_at", "label": "", "help": "", "required": true, "display": "auto", "default": ""},
|
|
54
|
+
{"column": "ends_at", "label": "", "help": "Leave empty for a meeting without an end.", "required": false, "display": "auto", "default": ""},
|
|
55
|
+
{"column": "private", "label": "Only visible to me", "help": "", "required": false, "display": "auto", "default": "false"}],
|
|
56
|
+
"list": [], "actions": {"insert": true, "update": false, "delete": false}}'::jsonb)
|
|
57
|
+
) as f (name, description, definition)
|
|
58
|
+
where a.alias = 'hr';
|
|
59
|
+
|
|
60
|
+
insert into meta.nav_entry (app_id, parent_id, seq, label, icon, target_page)
|
|
61
|
+
select a.id, n.id, 60, 'Forms', 'file', 45
|
|
62
|
+
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
|
|
63
|
+
where a.alias = 'hr';
|
|
64
|
+
|
|
65
|
+
insert into meta.translation (app_id, language, source, target)
|
|
66
|
+
select a.id, 'nl', t.source, t.target
|
|
67
|
+
from meta.app a, (values
|
|
68
|
+
('Forms', 'Formulieren'),
|
|
69
|
+
('Form Designer', 'Formulierbouwer'),
|
|
70
|
+
('Department names and locations.', 'Namen en vestigingsplaatsen van afdelingen.'),
|
|
71
|
+
('Meetings', 'Vergaderingen'),
|
|
72
|
+
('Meetings in the planner; employees change only their own.', 'Vergaderingen in de planner; medewerkers wijzigen alleen hun eigen.'),
|
|
73
|
+
('Job, department and salary of employees.', 'Functie, afdeling en salaris van medewerkers.'),
|
|
74
|
+
('Title', 'Titel'),
|
|
75
|
+
('Starts', 'Begint'),
|
|
76
|
+
('Ends', 'Eindigt'),
|
|
77
|
+
('Private', 'Privé')
|
|
78
|
+
) as t (source, target)
|
|
79
|
+
where a.alias = 'hr'
|
|
80
|
+
on conflict do nothing;
|