pgkiln 0.50.0 → 0.51.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/SECURITY.md +2 -0
- package/db/migrations/119_workspace_home.sql +30 -0
- package/db/migrations/120_datasets.sql +87 -0
- package/docs/apex-feature-parity.md +5 -4
- package/docs/guide/01-installation.md +2 -0
- package/docs/guide/03-builder.md +91 -5
- package/docs/guide/04-pages-and-regions.md +25 -1
- package/docs/guide/12-development.md +26 -3
- package/examples/hr/hr_63_datasets.sql +29 -0
- package/package.json +1 -1
- package/public/app.css +6 -0
- package/public/builder.css +34 -0
- package/src/app.ts +5 -1
- package/src/builder/datasets.ts +472 -0
- package/src/builder/home.ts +12 -7
- package/src/builder/instance.ts +2 -0
- package/src/builder/reporter.ts +52 -3
- package/src/builder/routes.ts +3 -3
- package/src/builder/subscriptions.ts +1 -0
- package/src/builder/ui.ts +7 -5
- package/src/builder/workspace-home.ts +283 -0
- package/src/builder/workspaces.ts +7 -4
- package/src/datasets.ts +367 -0
- package/src/i18n/ar.ts +16 -0
- package/src/i18n/cs.ts +16 -0
- package/src/i18n/da.ts +16 -0
- package/src/i18n/de.ts +16 -0
- package/src/i18n/el.ts +16 -0
- package/src/i18n/es.ts +16 -0
- package/src/i18n/fi.ts +16 -0
- package/src/i18n/fr.ts +16 -0
- package/src/i18n/he.ts +16 -0
- package/src/i18n/it.ts +16 -0
- package/src/i18n/ja.ts +16 -0
- package/src/i18n/ko.ts +16 -0
- package/src/i18n/nb.ts +16 -0
- package/src/i18n/pl.ts +16 -0
- package/src/i18n/pt.ts +16 -0
- package/src/i18n/ru.ts +16 -0
- package/src/i18n/sv.ts +16 -0
- package/src/i18n/tr.ts +16 -0
- package/src/i18n/uk.ts +16 -0
- package/src/i18n/zh.ts +16 -0
- package/src/i18n.ts +32 -0
- package/src/instance.ts +1 -0
- package/src/release-check.ts +139 -0
- package/src/reporting-app.ts +101 -0
- package/src/runtime/data-reporter.ts +199 -32
- package/src/session.ts +2 -0
- package/src/subscriptions.ts +2 -1
- package/src/workspace-export.ts +24 -4
package/SECURITY.md
CHANGED
|
@@ -97,6 +97,8 @@ first version (MVP). Every finding below has a regression test in
|
|
|
97
97
|
| Files | Uploads are size- and type-checked and stored per session (`meta.temp_files` shows only the session's own files). A posted text value can't point a file item at another file, and a "remove file" value only removes files of the form's own record. Downloads need a checksum bound to user, page, item and record, check page access and read as the app's role (RLS applies). They are sent as attachments with `nosniff` and a sandboxing CSP; only PNG, JPEG, GIF, WebP and PDF are shown inline. |
|
|
98
98
|
| Data loading and PDFs | The `data_load` process loads as the app's role (grants, RLS, triggers apply) and shows only data errors and `RAISE` messages per row. Report PDFs run the report's own query with the same page, region and row checks as the screen. |
|
|
99
99
|
| SQL Worksheet transactions (sprint 107) | A worksheet's open transaction is held in server memory under the caller's builder session id plus the tab key and checked against the workspace: every lookup starts from the caller's own session, so another developer or another sign-in never reaches it. Its connection is a plain client built from the workspace's developer login (or the *Run as* application's), never returned to a pool, and closed at the end, so `SET ROLE` reaches only roles that login has and nothing leaks into the builder's pools; *Run as* can't change while it is open. Rolled back on idle timeout, sign-out, session expiry, workspace switch, tab close and server stop, with `idle_in_transaction_session_timeout` as a backstop; at most `WORKSHEET_TXN_MAX_PER_DEVELOPER` per developer and `WORKSHEET_TXN_MAX` per server, each one database connection outside the pools. CSRF and a developer sign-in on every endpoint. |
|
|
100
|
+
| Release check (sprint 109) | Off by default (`PGKILN_RELEASE_CHECK`, or Instance settings for administrators). When on, the server sends one GET to GitHub's releases API at most once a day per process, with a 5-second timeout and a 1 MB limit, and sends nothing about the installation; only a semver version and an https link are kept from the answer, and they are escaped on the Workspace home. Pages never wait for it. |
|
|
101
|
+
| Data Reporter datasets and reporting applications (sprint 110) | Datasets are managed by the workspace's developers with CSRF on every POST; their schema must be one the workspace's SQL Workshop connection may use (never pgkiln's own or the system's), and tables, columns, joins and filters are checked against the catalog. The runtime builds a dataset's SELECT with quoted identifiers, literal values and whitelisted operators, and runs reports as the application's role. A reporting application's role gets SELECT only on the datasets' tables and views, so RLS applies; viewers never reach the report editor (report parameters in the URL are ignored), and only `admin_authz` users unpublish or delete others' reports. Dataset files are checked like a saved dataset before import. |
|
|
100
102
|
|
|
101
103
|
## Findings of the MVP review and their fixes
|
|
102
104
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-- ---------------------------------------------------------------------
|
|
2
|
+
-- 119: the Workspace home (sprint 109, WS-1; APEX: the workspace home
|
|
3
|
+
-- page). The builder opens /builder/home after signing in: tool cards, the
|
|
4
|
+
-- workspace's top applications and users by page views over a reporting
|
|
5
|
+
-- timeframe, a summary of counts, the workspace message and a system
|
|
6
|
+
-- message.
|
|
7
|
+
--
|
|
8
|
+
-- meta.developer.home_timeframe: the reporting timeframe each developer
|
|
9
|
+
-- chose for Top applications and Top users (hour, day or week); null is
|
|
10
|
+
-- the default (day). A developer account is installation data: not
|
|
11
|
+
-- exported with an application or a workspace.
|
|
12
|
+
--
|
|
13
|
+
-- meta.workspace.builder_home: what an old /builder link opens in this
|
|
14
|
+
-- workspace (a workspace preference): null or 'apps' = the App Builder (as
|
|
15
|
+
-- before; the App Builder is also at /builder/apps), 'home' = a redirect to
|
|
16
|
+
-- the Workspace home. Travels in a workspace export's settings.
|
|
17
|
+
--
|
|
18
|
+
-- The "new version available" check is an instance setting
|
|
19
|
+
-- (meta.setting 'release_check' = 'on' / 'off'; else the environment
|
|
20
|
+
-- variable PGKILN_RELEASE_CHECK; off by default): no table needed.
|
|
21
|
+
-- ---------------------------------------------------------------------
|
|
22
|
+
alter table meta.developer
|
|
23
|
+
add column home_timeframe text check (home_timeframe in ('hour', 'day', 'week'));
|
|
24
|
+
comment on column meta.developer.home_timeframe is
|
|
25
|
+
'The reporting timeframe of the developer''s Workspace home (119): hour, day or week; null = day.';
|
|
26
|
+
|
|
27
|
+
alter table meta.workspace
|
|
28
|
+
add column builder_home text check (builder_home in ('apps', 'home'));
|
|
29
|
+
comment on column meta.workspace.builder_home is
|
|
30
|
+
'What /builder opens in this workspace (119): null or apps = the App Builder, home = the Workspace home.';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- 120: Data Reporter datasets (APEX 26.1: Data Reporter → Datasets)
|
|
3
|
+
--
|
|
4
|
+
-- A dataset is a reusable, trusted view of a workspace's data for business
|
|
5
|
+
-- users: tables and views of one schema, joined (the joins proposed from
|
|
6
|
+
-- foreign keys), the columns users may see with labels, format masks and
|
|
7
|
+
-- descriptions, and an optional row filter. Developers define datasets in
|
|
8
|
+
-- the builder (Data Reporter); a Data Reporter region offers a dataset as a
|
|
9
|
+
-- source with {"id": "...", "dataset": "<name>"} in config.sources, and
|
|
10
|
+
-- the runtime builds the dataset's SELECT from the definition (identifiers
|
|
11
|
+
-- quoted, values as literals, operators from a whitelist) and runs reports
|
|
12
|
+
-- on it as the application's database role, so grants and row level
|
|
13
|
+
-- security apply.
|
|
14
|
+
--
|
|
15
|
+
-- tables [{"alias": "t1", "table": "emp"},
|
|
16
|
+
-- {"alias": "t2", "table": "dept",
|
|
17
|
+
-- "join": {"to": "t1", "type": "left", "on": [{"column": "deptno", "ref": "deptno"}]}}]
|
|
18
|
+
-- columns [{"name": "ename", "table": "t1", "column": "ename", "label": "Name",
|
|
19
|
+
-- "format": "FML999G990D00", "description": "..."}]
|
|
20
|
+
-- filters [{"table": "t1", "column": "active", "op": "eq", "value": "true"}]
|
|
21
|
+
--
|
|
22
|
+
-- Per workspace, like the SQL Workshop's saved work. Installation data:
|
|
23
|
+
-- not part of an application's export (the builder's Data Reporter exports
|
|
24
|
+
-- and imports datasets as JSON files). The builder writes it as the owner;
|
|
25
|
+
-- the runtime reads it through its own login, and row level security shows
|
|
26
|
+
-- an isolated workspace's login its own workspace's datasets only.
|
|
27
|
+
-- =====================================================================
|
|
28
|
+
create table meta.dataset (
|
|
29
|
+
id bigint generated always as identity primary key,
|
|
30
|
+
workspace_id int not null default 1 references meta.workspace on delete cascade,
|
|
31
|
+
name text not null check (name ~ '^[a-z][a-z0-9_]{0,39}$'),
|
|
32
|
+
label text not null check (length(btrim(label)) between 1 and 80),
|
|
33
|
+
description text check (length(description) <= 500),
|
|
34
|
+
schema_name text not null check (length(schema_name) between 1 and 63 and schema_name !~* '^(pg_.*|information_schema|meta)$'),
|
|
35
|
+
tables jsonb not null check (jsonb_typeof(tables) = 'array' and jsonb_array_length(tables) between 1 and 10),
|
|
36
|
+
columns jsonb not null default '[]' check (jsonb_typeof(columns) = 'array' and jsonb_array_length(columns) <= 200),
|
|
37
|
+
filters jsonb not null default '[]' check (jsonb_typeof(filters) = 'array' and jsonb_array_length(filters) <= 5),
|
|
38
|
+
created_by text not null,
|
|
39
|
+
created_at timestamptz not null default now(),
|
|
40
|
+
updated_by text,
|
|
41
|
+
updated_at timestamptz not null default now(),
|
|
42
|
+
unique (workspace_id, name)
|
|
43
|
+
);
|
|
44
|
+
revoke all on meta.dataset from public;
|
|
45
|
+
grant select on meta.dataset to pgkiln_runtime;
|
|
46
|
+
comment on table meta.dataset is 'Data Reporter datasets per workspace (120): joined tables and views, offered columns, a row filter; installation data, not exported';
|
|
47
|
+
|
|
48
|
+
-- May this login see a workspace's datasets? An isolated workspace's login: its own only;
|
|
49
|
+
-- other logins: those of workspaces that are not isolated.
|
|
50
|
+
create function meta.dataset_visible(p_workspace int) returns boolean
|
|
51
|
+
language sql stable security definer set search_path = meta, pg_catalog as $$
|
|
52
|
+
select case when meta.login_workspace() is not null then p_workspace = meta.login_workspace()
|
|
53
|
+
else not coalesce((select w.isolated from meta.workspace w where w.id = p_workspace), false) end
|
|
54
|
+
$$;
|
|
55
|
+
|
|
56
|
+
-- The workspace whose datasets an application's Data Reporter offers (refused for an
|
|
57
|
+
-- application the login may not see).
|
|
58
|
+
create function meta.dataset_workspace(p_app_id int) returns int
|
|
59
|
+
language sql stable security definer set search_path = meta, pg_catalog as $$
|
|
60
|
+
select meta.app_workspace(meta.checked_app(p_app_id))
|
|
61
|
+
$$;
|
|
62
|
+
|
|
63
|
+
revoke all on function meta.dataset_visible(int), meta.dataset_workspace(int) from public;
|
|
64
|
+
grant execute on function meta.dataset_visible(int), meta.dataset_workspace(int) to pgkiln_runtime;
|
|
65
|
+
|
|
66
|
+
-- (090) an isolated workspace's logins see their own workspace's datasets only
|
|
67
|
+
alter table meta.dataset enable row level security;
|
|
68
|
+
create policy workspace on meta.dataset
|
|
69
|
+
using ((select meta.isolation_off()) or meta.dataset_visible(workspace_id));
|
|
70
|
+
|
|
71
|
+
-- ---------------------------------------------------------------------
|
|
72
|
+
-- Reporting applications: an application generated by the builder's Data
|
|
73
|
+
-- Reporter on one or more datasets (a Data Reporter region is its engine;
|
|
74
|
+
-- roles viewer, editor and administrator). The type is part of the
|
|
75
|
+
-- definition and travels with the export.
|
|
76
|
+
-- ---------------------------------------------------------------------
|
|
77
|
+
alter table meta.app drop constraint app_app_type_check;
|
|
78
|
+
alter table meta.app add constraint app_app_type_check
|
|
79
|
+
check (app_type in ('standard', 'theme', 'library', 'boilerplate', 'reporting'));
|
|
80
|
+
comment on column meta.app.app_type is 'standard, theme, library (components offered to other apps), boilerplate (a starting point for new apps) or reporting (120: generated on Data Reporter datasets)';
|
|
81
|
+
|
|
82
|
+
-- The number of reporting applications of a workspace (the workspace home's summary).
|
|
83
|
+
create function meta.reporting_app_count(p_workspace int) returns int
|
|
84
|
+
language sql stable security definer set search_path = meta, pg_catalog as $$
|
|
85
|
+
select count(*)::int from meta.app a where a.app_type = 'reporting' and meta.app_workspace(a.id) = p_workspace
|
|
86
|
+
$$;
|
|
87
|
+
revoke all on function meta.reporting_app_count(int) from public;
|
|
@@ -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-18 (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-10-19 (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
|
|
|
@@ -22,8 +22,8 @@ Last reviewed: 2026-10-18 (sprint 108: the code editor's syntax colours in the b
|
|
|
22
22
|
| Globalization | 6 | 0 | 0 | 0 | One translated app like 26.1 with dynamic translations of table values; number format masks and automatic time zone; twenty-two built-in languages |
|
|
23
23
|
| Data and integration | 13 | 0 | 0 | 2 | REST source catalogs from OpenAPI documents; Generate DDL and schema comparison; `meta.data_export` and data export downloads (CSV, JSON, XML, HTML, Excel, PDF); e-mail through SMTP (password or OAuth2), Microsoft Graph, Amazon SES and HTTP APIs; REST APIs via PostgREST, REST data sources that write back and synchronise, web credentials with OAuth2 grants, CSV/XLSX/JSON/XML loading with saved definitions and unloading, SQL scripts and Quick SQL, report PDFs and document templates |
|
|
24
24
|
| Workflow, automation and AI | 6 | 0 | 0 | 0 | Scheduled automations with several actions and runs from SQL, approvals, a task list and workflows with parallel branches, versions and invoke-API steps; AI with Claude or OpenAI: *Generate text with AI*, an assistant region with tools, natural-language report filters and blueprints |
|
|
25
|
-
| Administration |
|
|
26
|
-
| **Total** | **
|
|
25
|
+
| Administration | 12 | 0 | 0 | 0 | An APEX-like sign-in with a workspace and a Workspace home; a workspace's components exported and imported as one file; workspace message, environment banner and utilization; isolated workspaces with their own database logins and roles, and workspace administrators; application availability and Run only, automatic backups, user feedback; a developer toolbar with a session state viewer and debug per session; Top SQL per app; debug messages per request; an install/upgrade log |
|
|
26
|
+
| **Total** | **144** | **0** | **0** | **3** | 147 APEX features compared: 98% available, none partial or missing |
|
|
27
27
|
|
|
28
28
|
(Counts are of the rows in the tables below. A review on 2026-10-06 added 18 rows for APEX features that were
|
|
29
29
|
not compared before, one on 2026-10-12 added two more (property help, application availability), and one on
|
|
@@ -194,7 +194,7 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
194
194
|
| Printing, document generator (PDF) | ✅ | **Document templates**: a query (with JSON columns for lines) fills an HTML template with Mustache-style tags, drawn as PDF with a report layout; buttons and links download them. (sprint 82) **Report queries**: a named query as PDF, Excel, CSV, JSON, XML or HTML. Report PDF with **report layouts** and a print stylesheet on every page. No Word/Excel templates or DOCX/XLSX output |
|
|
195
195
|
| `APEX_DATA_EXPORT` (a query to CSV, XLSX, PDF, HTML or JSON from PL/SQL) | ✅ | (sprint 53) `meta.data_export(query, format, options)` returns CSV, JSON, XML or HTML as `bytea` with the caller's privileges; the download process's `{"export": …}` sends a query's rows as CSV, JSON, XML, HTML, Excel or PDF |
|
|
196
196
|
| SQL Workshop utilities: schema comparison, generate DDL | ✅ | (sprint 56) SQL Workshop → **DDL**: a schema's objects (types, sequences, tables, functions, views, constraints, indexes, triggers, RLS and policies, comments, grants) from the catalog, in an order that runs, unqualified so it also creates them in another schema. **Compare**: two schemas by their DDL (only in one, different, with a diff) and a change script that makes the target like the source (tables column by column; drops commented out for review). Also `pgkiln ddl`, `pgkiln compare` and the MCP tools `generate_ddl`, `compare_schemas` ([chapter 3](guide/03-builder.md#sql-workshop)). Two schemas of the same database only (APEX: also within one workspace) |
|
|
197
|
-
| Data Reporter: self-service reports for business users (26.1) | ✅ | A **Data Reporter** region ([chapter 4](guide/04-pages-and-regions.md#data_reporter-data-reporter)): the developer offers tables and views with chosen columns, labels and format masks; signed-in users pick columns, filter, group with totals (count, sum, average, minimum, maximum), sort and chart, and save reports privately or shared with the app's users. Runs as the app's role (grants and RLS apply); works without JavaScript and fits phones. (sprint 68) A **welcome page** like 26.1's: a greeting (the developer's own, or pgkiln's), the sources as cards that start a report, the user's reports latest first, shared ones, and a search. One source per report (offer a view to combine tables); no downloads from a reporter yet |
|
|
197
|
+
| Data Reporter: self-service reports for business users (26.1) | ✅ | A **Data Reporter** region ([chapter 4](guide/04-pages-and-regions.md#data_reporter-data-reporter)): the developer offers tables and views with chosen columns, labels and format masks; signed-in users pick columns, filter, group with totals (count, sum, average, minimum, maximum), sort and chart, and save reports privately or shared with the app's users. Runs as the app's role (grants and RLS apply); works without JavaScript and fits phones. (sprint 68) A **welcome page** like 26.1's: a greeting (the developer's own, or pgkiln's), the sources as cards that start a report, the user's reports latest first, shared ones, and a search. One source per report (offer a view to combine tables); no downloads from a reporter yet (sprint 110) **A workspace tool too**: App Builder → **Data Reporter** ([chapter 3](guide/03-builder.md#data-reporter-datasets-and-reporting-applications)) keeps **datasets** (tables and views of one schema with joins proposed from foreign keys, offered columns with labels, masks and descriptions, a row filter; files and the workspace export) and makes a **reporting application** on them in two clicks: viewers open published reports by a stable URL and pin them, editors build and publish, administrators moderate; every report runs as the application's SELECT-only role through RLS. |
|
|
198
198
|
| REST Source Catalogs (Workspace Utilities) | ✅ | (sprint 67) Workspace utilities → **REST Source Catalogs**: a workspace's web services with a base URL and services, from an **OpenAPI 3 / Swagger 2.0** document (file, pasted or read from a URL on the allow-list), a catalog file or by hand: parameters (under the service's own names), row selector, typed columns and write-back operations from the response schemas and collection/item paths, with notes on what can't be used. An application's *REST data sources → From a REST source catalog* makes a data source from a service, with its own web credential ([chapter 19](guide/19-rest-data-sources.md#rest-source-catalogs)). **Missing:** YAML documents (convert to JSON), APEX's built-in catalogs (e.g. Oracle Fusion) |
|
|
199
199
|
| JSON sources, duality views (24.2) | ➖ | PostgreSQL `jsonb` works in any SQL region, form or grid source |
|
|
200
200
|
| Remote servers / database links | ➖ | `postgres_fdw` or `dblink` |
|
|
@@ -216,6 +216,7 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
216
216
|
| APEX | pgkiln | Notes |
|
|
217
217
|
|---|---|---|
|
|
218
218
|
| Developer accounts, workspace sign-in | ✅ | (sprint 61) The builder's sign-in page like APEX's: workspace (optional; it becomes the current one, a wrong one answers like a wrong password), username, password with a Show button, *Remember workspace and username*, a link to Administration. (sprint 68) **Find my workspace**: developers' e-mail addresses, and a mail with their workspaces through the builder's mail service (the same answer for every address, limited per address and IP). **Missing:** the sign-in page's language links (the builder is in English only) |
|
|
219
|
+
| Workspace home (tool cards, top apps and users, summary, workspace and system message) | ✅ | (sprint 109) `/builder/home` opens after sign-in ([chapter 3](guide/03-builder.md#workspace-home)): App Builder, SQL Workshop, Data Reporter and App Gallery cards; the workspace message edited in place; a Summary of applications, tables, developers and reporting applications; top applications, users and developers over an hour, a day or a week; a system message with the server's version and, with the optional release check (`PGKILN_RELEASE_CHECK`, off by default), *pgkiln X is available*. The App Builder moved to `/builder/apps`; `/builder` opens either, per workspace. |
|
|
219
220
|
| Workspace message, environment banner, workspace utilization, preferences and extension links (Manage Service) | ✅ | (sprint 61) An **Administration** menu in the icon rail; administrators and workspace administrators set a **workspace message** (on the App Builder home) and an **environment banner** (a coloured label on every builder page of the workspace), and see **workspace utilization** (applications, pages, page views, users, static files, schema storage) ([chapter 3](guide/03-builder.md#workspace-message-and-environment-banner)). (sprint 62) **Workspace preferences**: the SQL Workshop and the applications' RESTful services (REST modules) on or off per workspace; **extension links** in an Extensions menu of the rail ([chapter 3](guide/03-builder.md#workspace-preferences)). **Missing:** the account login controls of APEX's preferences (pgkiln's password policy and sign-in throttling are installation-wide) |
|
|
220
221
|
| Instance administration, install/upgrade logs (26.1) | ✅ | Versioned migrations (`npm run db:migrate`), every run logged; Workspace utilities → **Installation** (administrators): server version, install and upgrade runs with errors, applied migrations, and warnings for migrations the database misses or the server doesn't know ([chapter 3](guide/03-builder.md)). Workspace utilities → **Instance settings**: session length and sign-in throttling (stored in the database, over the environment variables) and an overview of the server's configuration without secrets; a server whose database lacks migrations says so (503) or applies them (`MIGRATE_ON_START`). Other settings stay environment variables |
|
|
221
222
|
| Debug messages | ✅ | Debug levels 1–9 per app; `meta.debug(level, text)` and `meta.debug_enabled(level)` from application SQL (APEX_DEBUG); timed entries per request (page steps, regions, processes, branches, errors, SQL notices); Activity → **Debug messages** viewer per page view with filters and the slowest step highlighted; retention 1–90 days; password item values are never recorded ([chapter 6](guide/06-processing.md)). (sprint 50) Debug for **one session** from the developer toolbar, the application staying out of debug. **Missing:** debug entries for background jobs and REST requests |
|
|
@@ -191,6 +191,8 @@ which is read at startup; real environment variables take precedence.
|
|
|
191
191
|
| `PGKILN_REST_MAX_BYTES` | `5000000` | Largest web service response read (also after decompression) |
|
|
192
192
|
| `MIGRATE_ON_START` | `false` | `true` applies missing migrations when the server starts. Without it, a server whose database lacks migrations answers every request with 503 and names the missing files until they are applied (`npm run db:migrate` or `pgkiln migrate`; no restart needed) |
|
|
193
193
|
| `LOG_LEVEL` | `info` | `fatal`, `error`, `warn`, `info`, `debug`, `trace` |
|
|
194
|
+
| `PGKILN_RELEASE_CHECK` | `off` | `on`: the server asks GitHub once a day for a newer pgkiln release and the [Workspace home](03-builder.md#the-release-check) announces it. Administrators can also set it in the builder (Instance settings → *New versions*), which wins over the variable. Keep it off where the server may not reach the internet |
|
|
195
|
+
| `PGKILN_RELEASE_URL` | GitHub's releases API | For tests and mirrors only: the address of a JSON document like GitHub's `releases/latest` |
|
|
194
196
|
|
|
195
197
|
## npm scripts
|
|
196
198
|
|
package/docs/guide/03-builder.md
CHANGED
|
@@ -6,7 +6,7 @@ The builder lives at `/builder`. Everything it does is also possible in SQL (see
|
|
|
6
6
|
## Signing in and developer accounts
|
|
7
7
|
|
|
8
8
|
Sign in with a developer account. The first one is `admin` / `admin`, and a red banner reminds you
|
|
9
|
-
to change it.
|
|
9
|
+
to change it. After signing in the builder opens the [Workspace home](#workspace-home) (`/builder/home`).
|
|
10
10
|
|
|
11
11
|
The sign-in page (`/builder/login`) is laid out like APEX's: **Workspace** (optional), **Username** and
|
|
12
12
|
**Password** (with a *Show* button). A workspace you name must be one of yours (administrators: any); it becomes the
|
|
@@ -75,7 +75,8 @@ its developers must not reach other teams' applications or data.
|
|
|
75
75
|
|
|
76
76
|
Administrators and the workspace's administrators set them on the workspace's page (*Manage service*, or the
|
|
77
77
|
Administration menu → *Workspace message and environment banner*; APEX: Define Workspace Message, Define Environment
|
|
78
|
-
Banner): a **message** (plain text, up to 2000 characters) shown to the workspace's developers on the
|
|
78
|
+
Banner): a **message** (plain text, up to 2000 characters) shown to the workspace's developers on the
|
|
79
|
+
[Workspace home](#workspace-home) (where they can also edit it in place) and the App Builder home,
|
|
79
80
|
and an **environment banner**: a label of up to 40 characters in one of eight colours, shown at the top of every
|
|
80
81
|
builder page while the workspace is current.
|
|
81
82
|
|
|
@@ -95,6 +96,11 @@ Administrators and the workspace's administrators set them on the workspace's pa
|
|
|
95
96
|
|
|
96
97
|
Both are on by default (migration 093) and are not exported.
|
|
97
98
|
|
|
99
|
+
- **Builder links open** (sprint 109, migration 119): what an address of just `/builder` (a bookmark from before the
|
|
100
|
+
Workspace home) opens in this workspace: the **App Builder** (the default: it is also at `/builder/apps`) or the
|
|
101
|
+
**Workspace home** (a redirect). Signing in always opens the Workspace home. It travels in a
|
|
102
|
+
[workspace export](#export-and-import)'s settings.
|
|
103
|
+
|
|
98
104
|
### Extension links
|
|
99
105
|
|
|
100
106
|
Links to the other tools a workspace's developers use (monitoring, a wiki, a ticket system; APEX: Manage Extension
|
|
@@ -151,6 +157,7 @@ applications' files. Choose what goes in:
|
|
|
151
157
|
| Extension links | Label, URL, description, order |
|
|
152
158
|
| REST source catalogs | Every [catalog](19-rest-data-sources.md#rest-source-catalogs) with its services |
|
|
153
159
|
| SQL scripts, blueprints, data generators | The SQL Workshop's saved work |
|
|
160
|
+
| Data Reporter datasets | Every [dataset](#data-reporter-datasets-and-reporting-applications) (sprint 110) |
|
|
154
161
|
|
|
155
162
|
Never in the file: the workspace's name, its [isolation](#isolated-workspaces) and database roles, passwords and
|
|
156
163
|
secrets, script runs and other history. **Applications are exported on their own** (an application's *Export*).
|
|
@@ -213,7 +220,8 @@ longer sign in. Delete a workspace only when it is shared and empty; its logins
|
|
|
213
220
|
|
|
214
221
|
Every builder page has the same frame, modelled on an IDE:
|
|
215
222
|
|
|
216
|
-
- **The icon rail** on the left:
|
|
223
|
+
- **The icon rail** on the left: Home (the [Workspace home](#workspace-home); the logo leads there too), App Builder,
|
|
224
|
+
SQL Workshop, [App Gallery](#app-gallery), [Data Reporter](#data-reporter-datasets-and-reporting-applications), **Search** (on the
|
|
217
225
|
pages of an application); at the bottom the **Administration** menu (Workspace utilities; for administrators of the
|
|
218
226
|
current workspace *Manage service*: [workspace message and environment banner](#workspace-message-and-environment-banner),
|
|
219
227
|
[workspace utilization](#workspace-utilization) and the workspace's page; Manage users and groups, Developers,
|
|
@@ -247,9 +255,43 @@ application of a workspace you are not a member of) shows a **Page not found** p
|
|
|
247
255
|
theme with a link to the App Builder home; a server error shows **Something went wrong** (the error
|
|
248
256
|
is in the server log, not on the page). Scripts get the plain answers they always got.
|
|
249
257
|
|
|
258
|
+
## Workspace home
|
|
259
|
+
|
|
260
|
+
(sprint 109; APEX: the workspace home page) The page the builder opens after signing in, `/builder/home`, above the
|
|
261
|
+
App Builder and the SQL Workshop. Everything on it is of the current [workspace](#workspaces), and it works without
|
|
262
|
+
JavaScript. The [default-password banner](#signing-in-and-developer-accounts) stays on top until the password is changed.
|
|
263
|
+
|
|
264
|
+
- **Tool cards**: App Builder (`/builder/apps`), SQL Workshop (not when the workspace's preferences turn it off),
|
|
265
|
+
**Data Reporter** (when the server has the Data Reporter tool at `/builder/reporter`) and the [App Gallery](#app-gallery).
|
|
266
|
+
- **Workspace message**: the [workspace message](#workspace-message-and-environment-banner), plain text. The
|
|
267
|
+
workspace's administrators (and the installation's) edit it in place with **Edit message**; empty removes it.
|
|
268
|
+
- **Summary**: the number of applications (opens the App Builder), tables in the schemas the workspace's database
|
|
269
|
+
roles may use (opens the Object Browser), developers (opens Developers) and reporting applications (applications
|
|
270
|
+
made by [Data Reporter](#data-reporter-datasets-and-reporting-applications) → *Create reporting application*; opens
|
|
271
|
+
the Data Reporter).
|
|
272
|
+
- **Activity**: **Top applications** (page views and users), **Top users** and **Top developers** (page views by the
|
|
273
|
+
workspace's developers and the installation's administrators in its applications) over **1 hour**, **1 day** (the
|
|
274
|
+
default) or **1 week**. The timeframe is remembered for each developer (`meta.developer.home_timeframe`).
|
|
275
|
+
- **System message**: the pgkiln version the server runs and, when the [release check](#the-release-check) is on and
|
|
276
|
+
a newer release is out, **pgkiln X is available** with a link to its release notes and how to upgrade (back up,
|
|
277
|
+
install the new version, `pgkiln migrate`, restart).
|
|
278
|
+
- **A side column**: About, **Learn more** (this guide, the [tutorial](10-tutorial.md),
|
|
279
|
+
[Coming from APEX](11-from-apex.md), the changelog and the discussions on GitHub) and Resources.
|
|
280
|
+
|
|
281
|
+
### The release check
|
|
282
|
+
|
|
283
|
+
Off by default. When it is on, the server asks GitHub's releases API (`api.github.com`) for the latest pgkiln release,
|
|
284
|
+
at most once a day per server process (an hour after a failure), with a 5-second timeout and a 1 MB limit; nothing
|
|
285
|
+
about the installation is sent. Pages never wait for it: they show what was fetched last and refresh it in the
|
|
286
|
+
background. Administrators turn it on or off on the Workspace home (**Check for new versions**, **Check now**,
|
|
287
|
+
**Turn off**) or on Workspace utilities → **Instance settings** → *New versions* (*On*, *Off*, or *As the environment
|
|
288
|
+
says*: the variable `PGKILN_RELEASE_CHECK`, [chapter 1](01-installation.md#configuration-reference)). Leave it off on a server
|
|
289
|
+
that may not reach the internet. Under the test runner the server never asks GitHub.
|
|
290
|
+
|
|
250
291
|
## App Builder home
|
|
251
292
|
|
|
252
|
-
The home page
|
|
293
|
+
The App Builder's home page, `/builder/apps` (`/builder` shows it too, unless the workspace's
|
|
294
|
+
[preferences](#workspace-preferences) send `/builder` to the Workspace home), is laid out like APEX's App Builder:
|
|
253
295
|
|
|
254
296
|
- **Four tiles**: **Create** and **Import** (each on its own page), the workspace **Dashboard**
|
|
255
297
|
(applications, pages, active accounts; page views, users, failed sign-ins and errors of the last
|
|
@@ -292,6 +334,49 @@ The **App Gallery** (the cube in the icon rail, `/builder/gallery`; APEX: App Ga
|
|
|
292
334
|
|
|
293
335
|
The list is `examples/gallery/gallery.json`; add your own starters there as blueprint files.
|
|
294
336
|
|
|
337
|
+
## Data Reporter: datasets and reporting applications
|
|
338
|
+
|
|
339
|
+
**Data Reporter** in the icon rail (`/builder/reporter`, sprint 110; APEX 26.1: Data Reporter as a workspace tool)
|
|
340
|
+
gives business users reports on the workspace's data without a developer writing a page per question. Every
|
|
341
|
+
developer of the workspace manages it; the page lists the workspace's **datasets** and its **reporting
|
|
342
|
+
applications** (with their users and published reports).
|
|
343
|
+
|
|
344
|
+
A **dataset** (`meta.dataset`, per workspace) is a trusted view of the data: tables and views of one schema, joined,
|
|
345
|
+
the columns users may see, and a row filter.
|
|
346
|
+
|
|
347
|
+
- **New dataset**: choose a schema (those your [SQL Workshop](#sql-workshop) connection may use; never pgkiln's own
|
|
348
|
+
or the system's), tick tables and views (the first is the main one) and give it a name (lower case, it can't
|
|
349
|
+
change) and a label. **Joins are proposed from foreign keys** in either direction (a left join on the key's
|
|
350
|
+
columns); every column is offered, labelled from its name, numbers with a number mask.
|
|
351
|
+
- **The dataset's page**: its label and description; the tables with their joins (to an earlier table, left or
|
|
352
|
+
inner, *on* `column = its column`; add a table, remove one); the **columns** (offer or not, a name reports use, a
|
|
353
|
+
label, a [format mask](14-globalization.md) and a description users see in the report editor); up to five
|
|
354
|
+
**row filter** conditions (column, operator, value) that every report on it gets; the **query** it builds, and a
|
|
355
|
+
**preview** of ten rows (read only, through your SQL Workshop connection). The dataset is checked against the
|
|
356
|
+
database when it is saved: tables, views and columns must exist; the page says what doesn't match (any more).
|
|
357
|
+
- **Download** one dataset or **Export all** as a file (`*.dataset.json`, format `pgkiln-dataset/1`); **Import**
|
|
358
|
+
reads such a file (or pasted text) in one transaction: each dataset is checked against this installation's
|
|
359
|
+
database, and one with the same name is kept unless you choose *Replace*. Datasets also travel in the
|
|
360
|
+
[workspace export](#export-and-import); they are not part of an application's export.
|
|
361
|
+
|
|
362
|
+
**Create reporting application** (on a dataset's row or page: the form is filled in, so *Create* is the second
|
|
363
|
+
click) makes an application of type *Reporting* on one or more datasets: page 1 is a
|
|
364
|
+
[Data Reporter](04-pages-and-regions.md#data_reporter-data-reporter) region offering the datasets, users sign in with
|
|
365
|
+
their accounts of the [user directory](#users-the-user-directory), and the first administrator is the account you
|
|
366
|
+
name (yours by default). Its database role `app_<alias>` may only **read** (SELECT) the datasets' tables and views,
|
|
367
|
+
so every report runs through those grants and [row level security](08-security.md) (a view with
|
|
368
|
+
`security_invoker` needs grants on its own tables too: grant them to the role yourself). Give accounts access and
|
|
369
|
+
roles under the application's *Users and roles*:
|
|
370
|
+
|
|
371
|
+
| Role | May |
|
|
372
|
+
|---|---|
|
|
373
|
+
| viewer (or no role) | Open published reports (by their stable URL too), pin them |
|
|
374
|
+
| editor | Also build reports, save them, publish and unpublish their own |
|
|
375
|
+
| administrator | Also unpublish and delete anyone's reports |
|
|
376
|
+
|
|
377
|
+
The application is an ordinary pgkiln application otherwise: change its pages, theme or sign-in in the builder as
|
|
378
|
+
you like. `meta.reporting_app_count(workspace_id)` counts a workspace's reporting applications.
|
|
379
|
+
|
|
295
380
|
### Creating an application
|
|
296
381
|
|
|
297
382
|
**Create** (a tile, or `/builder/create`) is one page, like APEX's Create Application wizard. Links at the top
|
|
@@ -756,7 +841,7 @@ out, other keys are kept, columns the query no longer returns stay listed so you
|
|
|
756
841
|
| `display_selector` | Tabs or a select list, "Show all", remember the choice; per other region of the page: in a tab and the tab name (saved in that region's settings) |
|
|
757
842
|
| `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)) |
|
|
758
843
|
| `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) |
|
|
759
|
-
| `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)) |
|
|
844
|
+
| `data_reporter` | Data sources (a table or view each: static id, label, description, offered columns with labels and format masks; or (sprint 110) a dataset of the workspace), who may share, build and moderate reports, publishing, rows per page ([Data Reporter](04-pages-and-regions.md#data_reporter-data-reporter)) |
|
|
760
845
|
| `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)) |
|
|
761
846
|
|
|
762
847
|
Links, lists of values and the facets' report are checked when saving: a form can only point to
|
|
@@ -963,6 +1048,7 @@ application has a **type** (Settings → Application type):
|
|
|
963
1048
|
| Theme application | Offers its theme (colours, navigation, light/dark settings and the Theme Roller's styles) and its template components to other applications |
|
|
964
1049
|
| Library application | Offers its lists of values, authorization schemes, build options, template components and lists (with their entries) to other applications |
|
|
965
1050
|
| Boilerplate application | A starting point: **Create** offers it under *Start from* |
|
|
1051
|
+
| Reporting application | (sprint 110) Made by [App Builder → Data Reporter](#data-reporter-datasets-and-reporting-applications) on datasets: its users build, publish and share reports |
|
|
966
1052
|
|
|
967
1053
|
**Shared Components → Subscriptions** subscribes the application to one of those components: it is
|
|
968
1054
|
copied now (replacing a component with the same name) and remembered as a subscription. The page
|
|
@@ -1186,9 +1186,12 @@ Attributes (written by the region's **Settings**):
|
|
|
1186
1186
|
|
|
1187
1187
|
| Key | Default | Meaning |
|
|
1188
1188
|
|---|---|---|
|
|
1189
|
-
| `sources` | | `[{"id": "orders", "label": "Orders", "description": "…", "schema": "sales", "table": "order_v", "columns": [{"name": "total", "label": "Total", "format": "FML999G990D00"}]}]` |
|
|
1189
|
+
| `sources` | | `[{"id": "orders", "label": "Orders", "description": "…", "schema": "sales", "table": "order_v", "columns": [{"name": "total", "label": "Total", "format": "FML999G990D00"}]}]`; (sprint 110) or a dataset: `{"id": "sales", "dataset": "sales"}` (label and description optional) |
|
|
1190
1190
|
| `sharing` | `true` | `false`: reports stay private |
|
|
1191
1191
|
| `share_authz` | | An authorization scheme: only users that pass it may share reports |
|
|
1192
|
+
| `edit_authz` | | (sprint 110) An authorization scheme: only users that pass it build, change, save and delete reports; the others only run shared ones |
|
|
1193
|
+
| `admin_authz` | | (sprint 110) An authorization scheme: users that pass it unpublish and delete anyone's reports |
|
|
1194
|
+
| `publishing` | `false` | (sprint 110) `true`: shared reports are *published*: a stable URL, Publish / Unpublish buttons, pins |
|
|
1192
1195
|
| `page_size` | `25` | Rows per page of a detail report (5 to 200) |
|
|
1193
1196
|
| `welcome` | `true` | `false`: the compact start (a list of sources and *Start*) instead of the welcome page |
|
|
1194
1197
|
| `welcome_title`, `welcome_text` | | The welcome page's greeting instead of pgkiln's (translated like other application texts) |
|
|
@@ -1200,6 +1203,27 @@ region when an application is replaced. The HR example's page 36 (*My reports*)
|
|
|
1200
1203
|
(a view without the user name and photo columns) and leave requests (row level security: an
|
|
1201
1204
|
employee sees only their own), with King's shared report *Salary by department*.
|
|
1202
1205
|
|
|
1206
|
+
#### Datasets and reporting applications
|
|
1207
|
+
|
|
1208
|
+
(sprint 110) A source may be a **dataset** of the workspace ([App Builder → Data
|
|
1209
|
+
Reporter](03-builder.md#data-reporter-datasets-and-reporting-applications)): tables and views of one schema with
|
|
1210
|
+
their joins, the offered columns with labels, format masks and descriptions (shown under the column in the editor),
|
|
1211
|
+
and a row filter. The region's Settings add one under *Add a data source → Or a dataset of the workspace*. The
|
|
1212
|
+
runtime reads the dataset when the page is drawn and builds its SELECT from the definition (identifiers quoted,
|
|
1213
|
+
values escaped literals, operators from the whitelist), and the report runs on it as a subquery, as the
|
|
1214
|
+
application's database role. A dataset that was deleted disappears from the region; a column that no longer exists
|
|
1215
|
+
makes the report show an error.
|
|
1216
|
+
|
|
1217
|
+
With **`publishing`**, shared reports are *published*: an editor saves a report privately and **Publishes** it
|
|
1218
|
+
(or ticks *Publish for all users* when saving), and **Unpublishes** it again. A published report has a **stable
|
|
1219
|
+
URL**, `/a/<alias>/reports/<id>`, shown on the report: it opens the report on its page (signing in first), so it
|
|
1220
|
+
can be bookmarked or sent. Every signed-in user may **Pin** a published report: pinned reports come first on the
|
|
1221
|
+
welcome page (a [preference](06-processing.md) of the user, `reporter.pins.<region>`). Users that don't pass
|
|
1222
|
+
`edit_authz` see only the published reports: no *New report* cards, no editor (report parameters in the URL are
|
|
1223
|
+
ignored), no saving. Users that pass `admin_authz` unpublish and delete anyone's reports. The HR example's dataset
|
|
1224
|
+
`hr` (`examples/hr/hr_63_datasets.sql`: employees with their department, active ones only) is the one a reporting
|
|
1225
|
+
application is made from in the guide's chapter 3.
|
|
1226
|
+
|
|
1203
1227
|
### `form_designer` (Form Designer)
|
|
1204
1228
|
|
|
1205
1229
|
A **Form Designer** region (sprint 85; pgkiln's own, APEX has no counterpart) lets the application's
|
|
@@ -21,6 +21,9 @@ src/
|
|
|
21
21
|
env.ts .env loader (imported first)
|
|
22
22
|
migrate.ts applies db/migrations and examples (scripts/migrate.ts, pgkiln migrate); logs each run that applies
|
|
23
23
|
instance.ts instance settings (meta.setting over environment variables, cached 30 s) and the configuration overview
|
|
24
|
+
release-check.ts (sprint 109) "pgkiln X is available": meta.setting 'release_check' over PGKILN_RELEASE_CHECK (off by default);
|
|
25
|
+
GitHub's releases/latest (PGKILN_RELEASE_URL in tests), 5 s timeout, 1 MB, cached a day per process,
|
|
26
|
+
never under node --test without PGKILN_RELEASE_URL; parseRelease keeps a semver and an https link only
|
|
24
27
|
or fails a file in public.pgkiln_install_log
|
|
25
28
|
appfiles.ts application export as one file per component (dir layout, static ids) and back
|
|
26
29
|
blueprint.ts blueprints (migration 063): checkBlueprint (names, types, references, pages, sample rows), tableOrder,
|
|
@@ -77,6 +80,13 @@ src/
|
|
|
77
80
|
datamodel.ts (sprint 98) Data Modeler diagrams: readModel() (catalog), boxSize(), fkPath() (crow's feet), autoLayout(), diagramSvg()
|
|
78
81
|
changelog.ts (sprint 106, migration 118) the change log: isSchemaDdl(), ddlTarget() (schema and object), changeName()
|
|
79
82
|
(add_bonus, create_index_x), recordChanges() (grouped per schema), Flyway / Liquibase / plain SQL writers
|
|
83
|
+
datasets.ts (sprint 110, migration 120) Data Reporter datasets: checkDataset() (names, joins to earlier tables, columns
|
|
84
|
+
and filters on its tables, whitelisted operators; with a catalog: existing objects), datasetSql() (quoted
|
|
85
|
+
identifiers, literal values), readSchemaCatalog() (tables, views, columns, foreign keys), proposeJoin() /
|
|
86
|
+
proposeDataset(), storeDataset(), appDatasets() (the runtime's read), pgkiln-dataset/1 files
|
|
87
|
+
reporting-app.ts (sprint 110) reporting applications: createReportingApp() (createApp, SELECT-only grants on the datasets'
|
|
88
|
+
objects, type reporting, roles viewer/editor/administrator as schemes EDITOR and ADMIN, page 1 a Data
|
|
89
|
+
Reporter), reportingApps(), reportingAppCount() (meta.reporting_app_count, for the workspace home)
|
|
80
90
|
tabledef.ts (sprint 95) a table as a definition: readTable(), checkTable(), tableSql() (CREATE, or ALTER from the catalog's version)
|
|
81
91
|
sqlformat.ts (sprint 93) formatSql(): the worksheet's Format (clauses per line, keyword case; strings and comments kept)
|
|
82
92
|
sqlplan.ts (sprint 92) EXPLAIN (FORMAT JSON) as a tree: parsePlan() (self time, slowest step, misestimates), planText()
|
|
@@ -185,7 +195,9 @@ src/
|
|
|
185
195
|
template-region.ts template_component region
|
|
186
196
|
tasks.ts task list region and task actions (approvals); (094) the vacation rule panel and route
|
|
187
197
|
data-reporter.ts Data Reporter region (migration 057): sources from the region's config, checkDef (offered columns, whitelists),
|
|
188
|
-
reportQuery/chartQuery, the list and editor (GET form), save/delete routes (meta.save_data_report)
|
|
198
|
+
reportQuery/chartQuery, the list and editor (GET form), save/delete routes (meta.save_data_report);
|
|
199
|
+
(sprint 110) dataset sources (resolveSources), edit_authz / admin_authz / publishing, pins (a preference),
|
|
200
|
+
publish / pin routes, the stable URL GET /a/:alias/reports/:id
|
|
189
201
|
form-designer.ts Form Designer region (migration 106): sources from the region's config, checkFormDef (offered columns, displays,
|
|
190
202
|
actions), forms as cards, a form's rows, a row's form (lost update hash), the designer; row/design/delete routes
|
|
191
203
|
workflows.ts workflow console region and its actions
|
|
@@ -217,7 +229,12 @@ src/
|
|
|
217
229
|
routes.ts sign-in, app home, settings, activity, developers, create (POST, via newapp.ts)/import (POST)
|
|
218
230
|
wizards.ts create page wizards: step 2 forms per page type (defaults from meta.wizard_defaults), POST → meta.generate_page
|
|
219
231
|
(the generators are PL/pgSQL in migration 047: catalog, defaults, form/cards/calendar/chart/map/facets/master-detail)
|
|
220
|
-
home.ts App Builder home (tiles, applications report/cards, Recent
|
|
232
|
+
home.ts App Builder home at /builder/apps and /builder (tiles, applications report/cards, Recent; /builder redirects
|
|
233
|
+
to the Workspace home when meta.workspace.builder_home = 'home'), Create, Import, Dashboard, Utilities
|
|
234
|
+
workspace-home.ts (sprint 109, migration 119) the Workspace home /builder/home, opened after sign-in: tool cards (Data Reporter
|
|
235
|
+
when GET /builder/reporter exists), workspace message edited in place (workspaceAdmin), Summary, Top
|
|
236
|
+
applications / users / developers over meta.developer.home_timeframe, System message (src/release-check.ts),
|
|
237
|
+
POST timeframe, message, release-check; releaseCheckRegion for Instance settings
|
|
221
238
|
newapp.ts creating an application (schema, role app_<alias>, Home page, first user): blank app, from a file, from tables
|
|
222
239
|
appfromfile.ts Create → From a file: upload (src/dataload.ts parsing), proposed table/columns, one transaction:
|
|
223
240
|
app + table + rows (loadRows) + pages (meta.generate_page: report and form, chart, facets)
|
|
@@ -305,7 +322,11 @@ src/
|
|
|
305
322
|
pwa.ts Settings → Progressive Web App (icon upload)
|
|
306
323
|
themeroller.ts Settings → Theme Roller: style variants (add, edit, rename, delete), default style, users may choose
|
|
307
324
|
subscriptions.ts Shared Components → Subscriptions: subscribe, refresh, unsubscribe, subscribers and publish; the note under a component
|
|
308
|
-
reporter.ts page designer: Data Reporter settings (sources: table or view, offered columns, labels, masks; sharing
|
|
325
|
+
reporter.ts page designer: Data Reporter settings (sources: table or view, offered columns, labels, masks; sharing;
|
|
326
|
+
(sprint 110) a dataset as a source, who may edit, who may moderate, publishing)
|
|
327
|
+
datasets.ts (sprint 110) App Builder → Data Reporter (/builder/reporter): datasets (new: schema, tables; a dataset's
|
|
328
|
+
joins, columns, row filter, query and preview), files (download, export all, import), Create reporting
|
|
329
|
+
application
|
|
309
330
|
form-designer.ts page designer: Form Designer settings (designers' scheme; sources: key, actions, offered columns, labels, lists of values)
|
|
310
331
|
workingcopies.ts Working copies: list and create, compare with differences, merge or refresh with conflict choices, delete
|
|
311
332
|
rest.ts REST module endpoints list and curl example (Shared Components)
|
|
@@ -389,6 +410,8 @@ test/
|
|
|
389
410
|
worksheet.test.ts (sprint 91) the SQL Worksheet: statement at the cursor, Run Script log, plans, notices, history, navigator, Run as
|
|
390
411
|
worksheet-txn.test.ts (sprint 107) transaction mode: the tab's transaction, Commit / Rollback, typed COMMIT, aborted, idle timeout, refusals,
|
|
391
412
|
Explain in it, Change Log at COMMIT, the JSON endpoint, sign-out
|
|
413
|
+
datasets.test.ts (sprint 110) datasets: checks and SQL, proposed joins, the builder's pages, files, the workspace export;
|
|
414
|
+
a reporting application in two clicks, an editor publishes, a viewer opens the stable URL, pins
|
|
392
415
|
quicksql.test.ts Quick SQL parser and DDL generator
|
|
393
416
|
xml.test.ts XML reader: rows, attributes, paths, refused DTDs and entities, limits
|
|
394
417
|
printing.test.ts report PDFs
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- HR example, part 63: a Data Reporter dataset (docs/guide/04-pages-and-
|
|
3
|
+
-- regions.md, "Datasets and reporting applications")
|
|
4
|
+
--
|
|
5
|
+
-- The dataset "hr" of the Default workspace: employees (hr.emp) joined to
|
|
6
|
+
-- their department (hr.dept, a left join on the foreign key deptno), the
|
|
7
|
+
-- columns business users may see with labels, format masks and
|
|
8
|
+
-- descriptions, and a row filter: active employees only. In the builder,
|
|
9
|
+
-- App Builder → Data Reporter → Create reporting application makes a
|
|
10
|
+
-- reporting application on it in two clicks; datasets are installation
|
|
11
|
+
-- data (a file of their own, and the workspace export), not part of the
|
|
12
|
+
-- HR application's export.
|
|
13
|
+
-- =====================================================================
|
|
14
|
+
|
|
15
|
+
insert into meta.dataset (workspace_id, name, label, description, schema_name, tables, columns, filters, created_by)
|
|
16
|
+
values (1, 'hr', 'HR', 'Active employees with their department.', 'hr',
|
|
17
|
+
'[{"alias": "t1", "table": "emp"},
|
|
18
|
+
{"alias": "t2", "table": "dept", "join": {"to": "t1", "type": "left", "on": [{"column": "deptno", "ref": "deptno"}]}}]',
|
|
19
|
+
'[{"name": "empno", "table": "t1", "column": "empno", "label": "No."},
|
|
20
|
+
{"name": "ename", "table": "t1", "column": "ename", "label": "Name"},
|
|
21
|
+
{"name": "job", "table": "t1", "column": "job", "label": "Job"},
|
|
22
|
+
{"name": "hiredate", "table": "t1", "column": "hiredate", "label": "Hire date"},
|
|
23
|
+
{"name": "sal", "table": "t1", "column": "sal", "label": "Salary", "format": "FML999G990D00", "description": "Monthly salary"},
|
|
24
|
+
{"name": "comm", "table": "t1", "column": "comm", "label": "Commission", "format": "FML999G990D00"},
|
|
25
|
+
{"name": "dname", "table": "t2", "column": "dname", "label": "Department"},
|
|
26
|
+
{"name": "loc", "table": "t2", "column": "loc", "label": "Location", "description": "Where the department is"}]',
|
|
27
|
+
'[{"table": "t1", "column": "active", "op": "eq", "value": "true"}]',
|
|
28
|
+
'admin')
|
|
29
|
+
on conflict (workspace_id, name) do nothing;
|
package/package.json
CHANGED
package/public/app.css
CHANGED
|
@@ -2042,3 +2042,9 @@ a.search-hit:hover, a.search-hit:focus-visible { background: var(--accent-soft);
|
|
|
2042
2042
|
.t-footer .icon { width: 1rem; height: 1rem; }
|
|
2043
2043
|
@media print { .t-footer { display: none; } }
|
|
2044
2044
|
.list-card:hover { border-top-color: var(--card-color); }
|
|
2045
|
+
|
|
2046
|
+
/* (sprint 110) Data Reporter: a saved report's link and actions, column descriptions */
|
|
2047
|
+
.reporter-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.6rem; margin: 0 0 0.75rem; min-width: 0; }
|
|
2048
|
+
.reporter-actions .buttons { margin: 0; }
|
|
2049
|
+
.reporter-link { flex: 1 1 14rem; min-width: 0; font-family: var(--mono, monospace); font-size: 0.85rem; }
|
|
2050
|
+
.reporter-coldesc { display: block; font-size: 0.78rem; }
|