pgkiln 0.75.0 → 0.76.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.
@@ -7,14 +7,14 @@ open item and open an issue or pull request; see [CONTRIBUTING.md](../CONTRIBUTI
7
7
  Legend: ✅ available · 🟡 partial (see notes) · ❌ not yet · ➖ not planned (a deliberate choice,
8
8
  or better served by the PostgreSQL ecosystem; see the notes and [extensions](guide/15-extensions.md))
9
9
 
10
- Last reviewed: 2026-11-04 against **APEX 26.2** (sprint 142: JSON sources with a data profile and updatable views whose arrays are rows, document views of a table with its children (APEX's duality views), JSON path columns in reports (AP-8); sprint 141: static workspace files (`#WORKSPACE_FILES#`), remote servers for REST data sources, catalogs and AI services (an environment variable per environment), and workspace-level web credentials (AP-7); sprint 140: the items Shuttle (ordered), Select One and Select Many, the regions Classic Report (report templates, pagination types), Breadcrumb and Help Text with a page help text, and a [mapping of every APEX item and region type](#item-and-region-types-one-by-one) (AP-4); sprint 139: OpenTelemetry, traces with a span per SQL statement, web call, AI request and tool call, logs, metrics and `/metrics` for Prometheus, browser spans relayed by pgkiln, per workspace off or its own collector (AP-6); sprint 138: an application's Utilities tab with a dashboard, database object dependencies, change history per component, Upgrade application, UI defaults (APEX's Attribute Dictionary), application and page checksums and an icon browser (AP-5); sprint 137: Create page as a grid of page types with previews, the page types interactive report, smart filters, search page, data loading, tree, timeline, media list, content row, comments, dashboard, wizard, unified task list and workflow console, a Feature tab with nine features that install once, and Create page as copy with shared components mapped or copied (AP-3); sprint 136: vector providers (an AI service with an embedding model or a SQL function), `meta.embed`, *Add vector column* in Table Properties with an HNSW index and a queue that keeps embeddings current, search types vector and hybrid (reciprocal rank fusion with full-text) and a Retrieve (RAG) tool for AI agents, all as the app's role through RLS, on pgvector (AP-1); sprint 135: full-text search configurations, APEX's Oracle Text search type on PostgreSQL full-text search with stemming, ranking, highlights, *Did you mean* and *Add full-text search* in Table Properties (AP-2); sprint 134: the builder also in Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어, APEX's ten builder languages plus Nederlands (SEC-5); sprints 121, 123–125: the builder in Deutsch, English, Español, Français, Nederlands and Português, step by step: the frame, sign-in, Workspace home, App Builder, Page Designer menus, the SQL Workshop's home, SQL Worksheet, Object Browser and Table Properties, Shared Components, application settings, users, identity providers, developers and workspaces (WS-7); sprint 122: *Ask in your own words* sets faceted search and smart filter facets, smart filters read a typed phrase (WS-5), and Sample Maps, Sample Approvals, Sample Data Loading and Sample Files in the App Gallery (WS-8); sprint 120: the App Gallery's single-topic sample apps (charts, cards, calendar, interactive grids, dynamic actions, reporting), the UX Pattern Catalog and a Utility Apps tab with Lookup Lists, Release Notes and Announcements (WS-8); sprint 119: data security per table, a roles × columns matrix and masked values per application role in a masking view, the same identity for pages, AI tools, REST, AutoREST and MCP (WS-13); sprint 118: Administration → Mail queue with delivery per hour and per workspace, the slowest provider calls and failures with Retry and Purge, a workspace's own mail service, and workspace network access lists that narrow the installation's allow-list (WS-9); sprint 117: Pillar Light and Pillar Dark navigation appearances with a header strip, clearer navigation tree states, subtle colour utilities, RTL; sprint 116: the comparison moved from 26.1 to 26.2, with a section for the 26.2 workspace items WS-1 … WS-13 and OCI managed identities; the App Builder list with Updated by, working copies and the lock; `pgkiln import --only`, a file-level import; stale rows on facet menus and blueprints fixed; sprint 115: popup LOVs that load on scroll, Wait Popup dynamic actions and dynamic actions on menu entries; sprint 114: Workflow 26.2 with custom task outcomes, task events and notifications, Send E-Mail and draft steps, migrating running instances and the diagram as SVG / PNG; sprint 113: Team Development with issues, labels, milestones, templates, a board and a set-up wizard; sprint 112: AI interactive reports with chips, Undo, computed columns and a phrase parser that needs no AI service; sprint 111: AI Agents with tools as a shared component, a Navigate tool with checksummed URLs, Gemini and OpenAI-compatible services; sprint 110: Data Reporter as a workspace tool with datasets, reporting applications, editors and viewers, published reports with stable URLs and pins; sprint 109: the Workspace home above the App Builder and SQL Workshop, with a summary, top applications, users and developers, and an optional release check; sprint 108: the code editor's syntax colours in the builder's light and dark themes, read-only SQL highlighted, the Data Modeler in dark mode; sprint 107: a transaction mode in the SQL Worksheet with Commit and Rollback; DA-18: JavaScript (MLE) not planned, plv8 where installed; sprint 106: the change log of DDL change sets with Flyway, Liquibase and SQL downloads; sprint 104: RESTful Services modules, templates and handlers with PL/pgSQL and media handlers, privileges, OpenAPI and Try it; sprint 103: Schema Export / Import with pg_dump and pg_restore; sprint 102: the SQL Monitor with live sessions, Top SQL and a statement's plan; sprint 101: Scheduling of pg_cron jobs with a schedule builder, run now and run history; sprint 100: RESTful Services, tables and views published as REST endpoints with paging, filters, keys and OpenAPI; sprint 99: Administration → Database Users for PostgreSQL roles; sprint 98: the Data Modeler with relational diagrams, DDL and a data dictionary; sprint 97: charts of a query in the worksheet, saved charts and their dashboard; sprint 96: the SQL Workshop's Launchpad with pins and tool groups, the builder's search with Ctrl+K; sprint 95: Table Properties: create, edit or copy a table in a form with a DDL preview and Apply in one transaction; sprint 94: an object's menu with Open in a panel, Quick DDL, Add index / trigger / policy and Drop with dependents; sprint 93: worksheets saved as SQL Scripts with tabs and a Files list, Format, Convert case, find and replace, bind and substitution variables; sprint 92: the worksheet's Query Result with sort, value dialog, copy and downloads, plans as a tree with the slowest step and misestimates, SQL History with status, search and run again; sprint 91: the SQL Worksheet like Database Actions' SQL: navigator, Run Statement at the cursor and Run Script with a log per statement, Explain Plan, Autotrace, notices, history, Run as an application role; sprint 90: Comment Out in the page designer, gallery labels in title case; sprint 89: the Object Browser's schema, one row of tabs, blank NULLs, Modify column; sprint 88: home cards with colour bands and round icons, the hero on the page background, a page footer with the version and Back to top; sprint 87: the Create Application wizard reloads the page list for a schema, RLS badges, the alias from the name; sprint 86: the page designer by page number, HTML error pages in the builder; sprint 85: the Form Designer, beyond APEX; sprint 84: the date picker, facet menus; sprint 83: Component Settings and Component Groups; sprint 82: Report Queries; sprint 81: Application Computations and Shortcuts in Shared Components; sprint 80: the master grid's first row selected when the page opens and after a search; grid cells as text with their format mask until edited, with cell navigation by arrow keys, Enter, F2 and Escape; sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
10
+ Last reviewed: 2026-11-04 against **APEX 26.2** (sprint 143: the interactive report's 26.2 dialogs: *is one of* / *is not one of* filters with the column's values and counts, *is between* two values (dates with the date picker in the application's format), relative periods on date columns, and the column order by drag and drop or arrow buttons, followed by downloads and the PDF (AP-9); sprint 142: JSON sources with a data profile and updatable views whose arrays are rows, document views of a table with its children (APEX's duality views), JSON path columns in reports (AP-8); sprint 141: static workspace files (`#WORKSPACE_FILES#`), remote servers for REST data sources, catalogs and AI services (an environment variable per environment), and workspace-level web credentials (AP-7); sprint 140: the items Shuttle (ordered), Select One and Select Many, the regions Classic Report (report templates, pagination types), Breadcrumb and Help Text with a page help text, and a [mapping of every APEX item and region type](#item-and-region-types-one-by-one) (AP-4); sprint 139: OpenTelemetry, traces with a span per SQL statement, web call, AI request and tool call, logs, metrics and `/metrics` for Prometheus, browser spans relayed by pgkiln, per workspace off or its own collector (AP-6); sprint 138: an application's Utilities tab with a dashboard, database object dependencies, change history per component, Upgrade application, UI defaults (APEX's Attribute Dictionary), application and page checksums and an icon browser (AP-5); sprint 137: Create page as a grid of page types with previews, the page types interactive report, smart filters, search page, data loading, tree, timeline, media list, content row, comments, dashboard, wizard, unified task list and workflow console, a Feature tab with nine features that install once, and Create page as copy with shared components mapped or copied (AP-3); sprint 136: vector providers (an AI service with an embedding model or a SQL function), `meta.embed`, *Add vector column* in Table Properties with an HNSW index and a queue that keeps embeddings current, search types vector and hybrid (reciprocal rank fusion with full-text) and a Retrieve (RAG) tool for AI agents, all as the app's role through RLS, on pgvector (AP-1); sprint 135: full-text search configurations, APEX's Oracle Text search type on PostgreSQL full-text search with stemming, ranking, highlights, *Did you mean* and *Add full-text search* in Table Properties (AP-2); sprint 134: the builder also in Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어, APEX's ten builder languages plus Nederlands (SEC-5); sprints 121, 123–125: the builder in Deutsch, English, Español, Français, Nederlands and Português, step by step: the frame, sign-in, Workspace home, App Builder, Page Designer menus, the SQL Workshop's home, SQL Worksheet, Object Browser and Table Properties, Shared Components, application settings, users, identity providers, developers and workspaces (WS-7); sprint 122: *Ask in your own words* sets faceted search and smart filter facets, smart filters read a typed phrase (WS-5), and Sample Maps, Sample Approvals, Sample Data Loading and Sample Files in the App Gallery (WS-8); sprint 120: the App Gallery's single-topic sample apps (charts, cards, calendar, interactive grids, dynamic actions, reporting), the UX Pattern Catalog and a Utility Apps tab with Lookup Lists, Release Notes and Announcements (WS-8); sprint 119: data security per table, a roles × columns matrix and masked values per application role in a masking view, the same identity for pages, AI tools, REST, AutoREST and MCP (WS-13); sprint 118: Administration → Mail queue with delivery per hour and per workspace, the slowest provider calls and failures with Retry and Purge, a workspace's own mail service, and workspace network access lists that narrow the installation's allow-list (WS-9); sprint 117: Pillar Light and Pillar Dark navigation appearances with a header strip, clearer navigation tree states, subtle colour utilities, RTL; sprint 116: the comparison moved from 26.1 to 26.2, with a section for the 26.2 workspace items WS-1 … WS-13 and OCI managed identities; the App Builder list with Updated by, working copies and the lock; `pgkiln import --only`, a file-level import; stale rows on facet menus and blueprints fixed; sprint 115: popup LOVs that load on scroll, Wait Popup dynamic actions and dynamic actions on menu entries; sprint 114: Workflow 26.2 with custom task outcomes, task events and notifications, Send E-Mail and draft steps, migrating running instances and the diagram as SVG / PNG; sprint 113: Team Development with issues, labels, milestones, templates, a board and a set-up wizard; sprint 112: AI interactive reports with chips, Undo, computed columns and a phrase parser that needs no AI service; sprint 111: AI Agents with tools as a shared component, a Navigate tool with checksummed URLs, Gemini and OpenAI-compatible services; sprint 110: Data Reporter as a workspace tool with datasets, reporting applications, editors and viewers, published reports with stable URLs and pins; sprint 109: the Workspace home above the App Builder and SQL Workshop, with a summary, top applications, users and developers, and an optional release check; sprint 108: the code editor's syntax colours in the builder's light and dark themes, read-only SQL highlighted, the Data Modeler in dark mode; sprint 107: a transaction mode in the SQL Worksheet with Commit and Rollback; DA-18: JavaScript (MLE) not planned, plv8 where installed; sprint 106: the change log of DDL change sets with Flyway, Liquibase and SQL downloads; sprint 104: RESTful Services modules, templates and handlers with PL/pgSQL and media handlers, privileges, OpenAPI and Try it; sprint 103: Schema Export / Import with pg_dump and pg_restore; sprint 102: the SQL Monitor with live sessions, Top SQL and a statement's plan; sprint 101: Scheduling of pg_cron jobs with a schedule builder, run now and run history; sprint 100: RESTful Services, tables and views published as REST endpoints with paging, filters, keys and OpenAPI; sprint 99: Administration → Database Users for PostgreSQL roles; sprint 98: the Data Modeler with relational diagrams, DDL and a data dictionary; sprint 97: charts of a query in the worksheet, saved charts and their dashboard; sprint 96: the SQL Workshop's Launchpad with pins and tool groups, the builder's search with Ctrl+K; sprint 95: Table Properties: create, edit or copy a table in a form with a DDL preview and Apply in one transaction; sprint 94: an object's menu with Open in a panel, Quick DDL, Add index / trigger / policy and Drop with dependents; sprint 93: worksheets saved as SQL Scripts with tabs and a Files list, Format, Convert case, find and replace, bind and substitution variables; sprint 92: the worksheet's Query Result with sort, value dialog, copy and downloads, plans as a tree with the slowest step and misestimates, SQL History with status, search and run again; sprint 91: the SQL Worksheet like Database Actions' SQL: navigator, Run Statement at the cursor and Run Script with a log per statement, Explain Plan, Autotrace, notices, history, Run as an application role; sprint 90: Comment Out in the page designer, gallery labels in title case; sprint 89: the Object Browser's schema, one row of tabs, blank NULLs, Modify column; sprint 88: home cards with colour bands and round icons, the hero on the page background, a page footer with the version and Back to top; sprint 87: the Create Application wizard reloads the page list for a schema, RLS badges, the alias from the name; sprint 86: the page designer by page number, HTML error pages in the builder; sprint 85: the Form Designer, beyond APEX; sprint 84: the date picker, facet menus; sprint 83: Component Settings and Component Groups; sprint 82: Report Queries; sprint 81: Application Computations and Shortcuts in Shared Components; sprint 80: the master grid's first row selected when the page opens and after a search; grid cells as text with their format mask until edited, with cell navigation by arrow keys, Enter, F2 and Escape; sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
11
11
 
12
12
  ## At a glance
13
13
 
14
14
  | Area | ✅ | 🟡 | ❌ | ➖ | In short |
15
15
  |---|---:|---:|---:|---:|---|
16
16
  | App Builder and development | 22 | 0 | 0 | 0 | Page Designer with drag-and-drop and a code editor, wizards, search, where used, an Advisor, a CLI with one file per component, page locks and comments, supporting objects, working copies with a three-way merge, theme/library/boilerplate apps with subscriptions; App Builder AI (pages, SQL and table descriptions) |
17
- | Regions | 24 | 0 | 0 | 0 | All everyday regions incl. classic reports with report templates, breadcrumb and help text regions, a search region over search configurations and a URL region; twenty-two chart types with drill-down; calendars with week/day/list views and drag and drop; faceted search, smart filters and a region display selector; interactive reports with breaks, aggregates, highlights, compute, group by, pivot, chart view and saved reports; interactive grids with single row, group by and chart views; maps (with vector tiles) and trees; template components; row ranges, lazy loading and region caching for large tables |
17
+ | Regions | 25 | 0 | 0 | 0 | All everyday regions incl. classic reports with report templates, breadcrumb and help text regions, a search region over search configurations and a URL region; twenty-two chart types with drill-down; calendars with week/day/list views and drag and drop; faceted search, smart filters and a region display selector; interactive reports with breaks, aggregates, highlights, compute, group by, pivot, chart view, saved reports and 26.2's multi-select, date-range and column-order dialogs; interactive grids with single row, group by and chart views; maps (with vector tiles) and trees; template components; row ranges, lazy loading and region caching for large tables |
18
18
  | Items | 15 | 0 | 0 | 0 | All common items incl. shuttle, Select One and Select Many, file upload (several files per item), rich text and Markdown editors, star rating, combobox, date range, QR code, password reveal, display image and geocoded address |
19
19
  | Logic and processing | 18 | 0 | 0 | 1 | User preferences and application settings; all dynamic action events and actions, Ajax callbacks and an error handling function; Core APEX model complete with computations, conditional branches, build options and menu buttons, download, chain and workflow processes; JavaScript from static application files in dynamic actions; region, item, dynamic action and process plug-ins |
20
20
  | Security | 22 | 0 | 0 | 0 | An editable login page and Forgot password; a session timeout warning; On par or stricter (CSP without `unsafe-inline`); OIDC, SAML and LDAP; header authentication behind a proxy; database accounts; custom authentication |
@@ -24,7 +24,7 @@ Last reviewed: 2026-11-04 against **APEX 26.2** (sprint 142: JSON sources with a
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
25
  | Administration | 15 | 0 | 0 | 0 | OpenTelemetry traces, logs and metrics to the team's own monitoring and `/metrics` for Prometheus (24.2); An APEX-like sign-in with a workspace and a Workspace home; a mail queue dashboard, a workspace's own mail service and network access list (26.1 / 26.2); 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
26
  | APEX 26.2 workspace (WS-1 … WS-13) | 13 | 0 | 0 | 1 | Workspace home, Data Reporter as a workspace tool, Team Development, AI Agents, AI interactive reports, Workflow 26.2, the mail queue, workspace mail and network access, the 26.1 component details, the App Builder list's details, the Pillar navigation appearances and data security per table (rows, columns and masked values), the App Gallery's single-topic sample apps, UX Pattern Catalog and Utility Apps; the builder in eleven languages (APEX's ten and Nederlands) |
27
- | **Total** | **169** | **0** | **0** | **3** | 172 APEX features compared: 98% available, none missing, 3 deliberately not planned |
27
+ | **Total** | **170** | **0** | **0** | **3** | 173 APEX features compared: 98% available, none missing, 3 deliberately not planned |
28
28
 
29
29
  (Counts are of the rows in the tables below. A review on 2026-10-06 added 18 rows for APEX features that were
30
30
  not compared before, one on 2026-10-12 added two more (property help, application availability), and one on
@@ -70,6 +70,7 @@ database links row and added static workspace files with workspace web credentia
70
70
  |---|---|---|
71
71
  | Classic report (report templates, pagination types) | ✅ | (sprint 140) Region type `classic_report`: the report renderer without the Actions menu, column menus, saved reports or downloads, and none of an interactive report's settings from the URL; sorting by headings, an optional search; `report_template` `standard` (a table), `value_pairs` (Value Attribute Pairs), `badges` (Badge List) or `media_list` (Media List); `pagination` `total` (X–Y of Z), `range` (X–Y) or `none` ([chapter 4](guide/04-pages-and-regions.md#classic_report-classic-report)) |
72
72
  | Interactive report | ✅ | (sprint 76) An Actions menu of nine entries with dialogs, a column heading menu (sort, hide, control break, the column's values to filter by), a search in one column, hidden columns, pagination with the range, first/last and rows per page. Search, column filters, sort, rows per page, control break, aggregates (with subtotals), highlight, saved private and public reports, computed columns, group by, pivot, chart view, row selection into a page item, CSV, Excel (typed cells) and PDF download, print, reset, reflow on phones. a maximum row count (`max_rows`), natural-language control (*Ask in your own words*, 26.1) and row selection that stays across pages. Not possible: flashback queries (PostgreSQL has none; use an audit or temporal table) |
73
+ | Interactive report dialogs of 26.2: multi-select and date-range filters, drag-and-drop columns | ✅ | (sprint 143, AP-9) *Actions → Filter*: **is one of** / **is not one of** (several values at once: ticked in a list of the column's values with counts and a search, or typed with commas; *is not one of* keeps the rows without a value), **is between** two values (both included; either may stay empty; on a date column the date picker in the application's date format, and the whole last day of a timestamp), and **is in** a period on a date column (today, yesterday, the last 7 or 30 days, the next 7 days, this or last month, this or last year; rolling, so a saved report stays current). Each is a chip in words (*Job is one of CLERK, ANALYST*). *Actions → Columns*: the columns in their order, **dragged** into another or moved with **arrow buttons** (announced to screen readers; without JavaScript the arrows submit the form); the order is a chip that puts it back, is kept in saved reports and followed by the CSV, Excel and PDF downloads, which also leave out hidden columns ([chapter 4](guide/04-pages-and-regions.md#report-interactive-report)). *Ask in your own words* and AI answers use the same operators. Text templates for AI computed columns: computed columns stay expressions over the report's columns |
73
74
  | Interactive grid | ✅ | Inline edit, add and delete rows, lists of values, required columns, per-row errors, all-or-nothing save, signed row keys, search and paging; **aggregates** over the whole result (developer and user defined), **frozen columns**, column **reorder/resize/hide** (Actions → Columns, or drag and drop), per-user layouts and **saved grid reports** (private and public), **master-detail** (signed row selection, the first row selected on load and after a search, details refreshed in place), **navigation and edit mode** (cells as text with their format mask until clicked, Enter or F2; arrow keys between cells), a **row actions menu** (edit, duplicate, delete, links) and **copy/paste** of cell ranges (tab-separated, spreadsheet compatible) ([chapter 4](guide/04-pages-and-regions.md)) |
74
75
  | Interactive grid views: single row view, chart view, group by | ✅ | (sprint 54) **Single row view**: one row of the search as a form with first/previous/next/last and *Add row*, from the Actions or row actions menu, saved by the grid's own process with the same checks; **group by** and **chart** set up in the Actions menu over every row of the search, as for the interactive report; `views` limits them; Save comes back to the same search, page and view ([chapter 4](guide/04-pages-and-regions.md#grid-interactive-grid)). No pivot view on grids (the interactive report has one), no editing in the single row view of columns the grid doesn't show |
75
76
  | Form (automatic row processing) | ✅ | Fetch, insert, update, delete, in a page or a modal dialog. Detects rows deleted meanwhile. (sprint 50) **Lost update detection** (APEX: *Prevent Lost Updates* and *Lock Row*): the page carries a checksum of the row's form columns (`meta.row_version`, independent of time zone and date format, as the app's role); *Save* and *Delete* lock the row and refuse when it changed meanwhile; off per form with `{"lost_update": false}` ([chapter 4](guide/04-pages-and-regions.md#form)) |
@@ -234,12 +234,32 @@ Features for end users:
234
234
  search and filters; at most 200), with a box to narrow them; choosing a value filters the report on it. The sort
235
235
  arrow of the sorted column sorts at once. Without JavaScript a heading sorts (again for descending).
236
236
  - **Hidden columns**: hidden from the heading menu or *Actions → Columns*, shown as chips to bring them back.
237
+ - **Column order** (sprint 143; APEX 26.2: drag-and-drop columns): *Actions → Columns* lists the columns in their
238
+ order with a checkbox to hide each; drag one to another place, or move it with its ↑ / ↓ buttons (each move is
239
+ announced to screen readers; without JavaScript the buttons submit the dialog). *Own column order* is a chip that
240
+ puts the report's order back. The order is kept in saved reports (`r12_o=sal&r12_o=ename`, the columns it names
241
+ first, the rest after them in the report's order), and the CSV, Excel and PDF downloads follow it and leave out
242
+ the columns the user hid.
237
243
  - **Pagination**: *1–15 of 107*, first, previous, next and last page, and the **rows per page** list.
238
244
  - **Actions menu** (sprint 76: a short menu like APEX's; each entry opens a dialog, or unfolds in place without
239
245
  JavaScript): *Columns*, *Filter*, *Data* (sort, aggregate, compute, control break), *Format* (highlight, rows per
240
246
  page), *Chart*, *Group by*, *Pivot*, *Report* (saved reports, reset) and *Download* (CSV, Excel, PDF, print):
241
247
  - **column filters** (`=`, `≠`, contains, does not contain, `>`, `≥`, `<`, `≤`, is empty, is
242
- not empty) and **sort**;
248
+ not empty, and since sprint 143 the 26.2 operators below) and **sort**:
249
+ - **is one of** / **is not one of** (APEX 26.2: multi-select filters): tick values in the column's list (with
250
+ their counts and a search box, as in the heading menu), or type them separated by commas. *Is not one of*
251
+ keeps the rows without a value. In the URL the values are a JSON array: `r12_f=job|in|["CLERK","ANALYST"]`
252
+ (`job|in|CLERK, ANALYST` works too), at most 100 values;
253
+ - **is between** (date-range filters): two values, both included, either may stay empty (*Salary ≥ 1000*). On a
254
+ date or timestamp column the fields get the date picker and take dates in the application's date format, and
255
+ the last day counts as a whole (`hiredate|between|["1981-01-01","1981-12-31"]`);
256
+ - **is in** a period, on a date column: today, yesterday, the last 7 days, the last 30 days, the next 7 days,
257
+ this month, last month, this year or last year (`hiredate|period|last_30_days`). A period is computed
258
+ from today when the report runs, so a saved report stays current.
259
+
260
+ The dialog shows only the fields the chosen operator needs (without JavaScript it shows all of them); a filter
261
+ is a chip in words (*Job is one of CLERK, ANALYST*), also in the PDF's filter list. *Ask in your own words* and
262
+ an AI service may use the same operators; a highlight takes the one-value operators;
243
263
  - **control break**: group the rows by a column, with a heading row per group;
244
264
  - **aggregates**: sum, average, count, minimum or maximum of a column, over all filtered rows
245
265
  (not just the page). A *Total* row closes the table, and with a control break every group
@@ -267,7 +287,8 @@ Features for end users:
267
287
 
268
288
  The report's state lives in the URL (`?r12_q=…&r12_s=3&r12_d=desc&r12_b=job&r12_a=sum|sal&r12_h=sal|gt|green|3000`),
269
289
  so it can be bookmarked and shared. Everything the user enters is applied safely: search, filter
270
- and highlight values become literals, columns must exist in the result, operators, aggregate
290
+ and highlight values become literals (each value of a list and each bound of a range on its own; a period is one
291
+ of a fixed list of expressions), columns must exist in the result, operators, aggregate
271
292
  functions, chart types and colors come from fixed lists, sort positions are integers, and computed
272
293
  column expressions are parsed (below), never pasted into SQL.
273
294
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgkiln",
3
- "version": "0.75.0",
3
+ "version": "0.76.0",
4
4
  "description": "Open source low-code, SQL-driven application builder for PostgreSQL, inspired by Oracle APEX",
5
5
  "keywords": [
6
6
  "postgresql",
package/public/app.css CHANGED
@@ -2020,6 +2020,24 @@ a.search-hit:hover, a.search-hit:focus-visible { background: var(--accent-soft);
2020
2020
  .ir-dialog-head h2 { margin: 0; font-size: 1.05rem; }
2021
2021
  .ir-dialog .ir-body { padding: 1rem; }
2022
2022
  .ir-dialog .filter-row { min-width: 0; }
2023
+ .filter-dialog .date-field { display: flex; min-width: 0; }
2024
+ .filter-dialog .date-field input { flex: 1; min-width: 0; }
2025
+ .filter-dialog .filter-values, .filter-dialog .help { grid-column: 1 / -1; }
2026
+ .filter-values { display: grid; gap: 0.3rem; }
2027
+ .filter-values-list { list-style: none; margin: 0; padding: 0.25rem 0.4rem; max-height: 14rem; overflow: auto; border: 1px solid var(--border); border-radius: var(--radius); }
2028
+ .filter-values-list .check { display: flex; gap: 0.4rem; align-items: center; padding: 0.15rem 0; }
2029
+ .filter-values-list .muted { margin-left: auto; font-variant-numeric: tabular-nums; }
2030
+ /* (143) Actions → Columns: a row per column, dragged by its handle or moved with its arrows */
2031
+ .ir-col-order { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.15rem; }
2032
+ .ir-col-order > li { display: flex; align-items: center; gap: 0.4rem; padding: 0.15rem 0.3rem; border: 1px solid transparent; border-radius: var(--radius); background: var(--surface); }
2033
+ .ir-col-order > li:hover { border-color: var(--border); }
2034
+ .ir-col-order > li.dragging { opacity: 0.55; border-style: dashed; border-color: var(--accent); }
2035
+ .ir-col-order .check { flex: 1; min-width: 0; }
2036
+ .ir-col-order .drag-handle { color: var(--muted); cursor: grab; display: inline-flex; }
2037
+ .no-js .ir-col-order .drag-handle, html:not(.js) .ir-col-order .drag-handle { display: none; }
2038
+ .ir-col-move { display: inline-flex; gap: 0.15rem; }
2039
+ .ir-col-move .btn { min-width: 2rem; padding: 0.1rem 0.4rem; line-height: 1.2; }
2040
+ .ir-col-move .btn:disabled { opacity: 0.35; }
2023
2041
  /* the search field with its column list (APEX: the magnifier's column menu) */
2024
2042
  .search-field { display: flex; flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
2025
2043
  .search-field:focus-within { outline: 2px solid var(--accent); outline-offset: 1px; }
package/public/app.js CHANGED
@@ -4420,6 +4420,147 @@ const reportTexts = (() => {
4420
4420
  window.addEventListener('resize', shut);
4421
4421
  })();
4422
4422
 
4423
+ // (143; APEX 26.2: multi-select and date-range filters) Actions → Filter shows the fields its operator needs: one
4424
+ // value; "is one of" a list of the column's values with counts and a search (the ticked ones go as r<id>_fl, next to
4425
+ // values typed with commas); "is between" two values; "is in" a period, offered on date columns only. On a date
4426
+ // column the value fields get the date picker in the application's date format.
4427
+ (() => {
4428
+ const t = (k, d) => reportTexts[k] || d;
4429
+ const cache = new Map();
4430
+ function fill(box, column) {
4431
+ const list = box.querySelector('.filter-values');
4432
+ if (!list || list.dataset.column === column) return;
4433
+ list.dataset.column = column;
4434
+ list.replaceChildren();
4435
+ const search = document.createElement('input');
4436
+ search.type = 'search';
4437
+ search.placeholder = t('report.filter_values', 'Filter the values');
4438
+ search.setAttribute('aria-label', search.placeholder);
4439
+ const ul = document.createElement('ul');
4440
+ ul.className = 'filter-values-list';
4441
+ list.append(search, ul);
4442
+ search.addEventListener('input', () => {
4443
+ const q = search.value.trim().toLowerCase();
4444
+ ul.querySelectorAll('li').forEach((li) => { li.hidden = !!q && !li.textContent.toLowerCase().includes(q); });
4445
+ });
4446
+ const url = new URL(box.dataset.values, location.href);
4447
+ new URL(location.href).searchParams.forEach((v, k) => url.searchParams.append(k, v));
4448
+ url.searchParams.set('col', column);
4449
+ const key = url.toString();
4450
+ const got = cache.get(key) ?? fetch(url, { headers: { accept: 'application/json' }, credentials: 'same-origin' }).then((r) => (r.ok ? r.json() : { values: [] })).catch(() => ({ values: [] }));
4451
+ cache.set(key, got);
4452
+ got.then(({ values }) => {
4453
+ if (list.dataset.column !== column) return;
4454
+ const shown = (values || []).filter((x) => x.value !== null);
4455
+ if (!shown.length) {
4456
+ const li = document.createElement('li');
4457
+ li.className = 'muted';
4458
+ li.textContent = t('report.no_values', 'No values');
4459
+ ul.append(li);
4460
+ return;
4461
+ }
4462
+ for (const { value, count } of shown) {
4463
+ const li = document.createElement('li');
4464
+ const label = document.createElement('label');
4465
+ label.className = 'check';
4466
+ const box2 = document.createElement('input');
4467
+ box2.type = 'checkbox';
4468
+ box2.name = box.dataset.list;
4469
+ box2.value = value;
4470
+ box2.setAttribute('form', box.dataset.form);
4471
+ const n = document.createElement('span');
4472
+ n.className = 'muted';
4473
+ n.textContent = ` ${count}`;
4474
+ label.append(box2, ` ${value}`, n);
4475
+ li.append(label);
4476
+ ul.append(li);
4477
+ }
4478
+ });
4479
+ }
4480
+ function sync(box) {
4481
+ const col = box.querySelector('[data-filter-column]');
4482
+ const op = box.querySelector('[data-filter-op]');
4483
+ if (!col || !op) return;
4484
+ const date = col.selectedOptions[0]?.dataset.kind === 'date';
4485
+ op.querySelectorAll('option[data-op-kind="period"]').forEach((o) => { o.hidden = !date; o.disabled = !date; });
4486
+ if (!date && op.selectedOptions[0]?.dataset.opKind === 'period') op.value = 'eq';
4487
+ const kind = op.selectedOptions[0]?.dataset.opKind || 'one';
4488
+ box.querySelectorAll('.filter-field[data-show]').forEach((el) => { el.hidden = !el.dataset.show.split(' ').includes(kind); });
4489
+ for (const input of box.querySelectorAll('input[data-mask-off]')) {
4490
+ const picker = date && kind !== 'list';
4491
+ if (picker) input.dataset.dateMask = input.dataset.maskOff;
4492
+ else delete input.dataset.dateMask;
4493
+ input.placeholder = picker ? input.dataset.maskOff : input.getAttribute('aria-label') || '';
4494
+ const btn = input.parentElement?.querySelector('[data-date-pick]');
4495
+ if (btn) btn.hidden = !picker;
4496
+ }
4497
+ if (kind === 'list') fill(box, col.value);
4498
+ }
4499
+ document.querySelectorAll('[data-filter-dialog]').forEach(sync);
4500
+ document.addEventListener('change', (e) => {
4501
+ const box = e.target.closest?.('[data-filter-dialog]');
4502
+ if (box && e.target.matches('[data-filter-column], [data-filter-op]')) sync(box);
4503
+ });
4504
+ })();
4505
+
4506
+ // (143; APEX 26.2: drag-and-drop column ordering) Actions → Columns: drag a column to another place, or move it with
4507
+ // its arrow buttons (Up / Down; without JavaScript they submit the form and the server moves it); the dialog's form
4508
+ // sends the columns in the list's order when applied. Each move is announced.
4509
+ (() => {
4510
+ const t = (k, d) => reportTexts[k] || d;
4511
+ const fmt = (s, p) => s.replace(/\{(\w+)\}/g, (m, k) => (k in p ? p[k] : m));
4512
+ function refresh(list, moved) {
4513
+ const items = [...list.children];
4514
+ items.forEach((li, i) => {
4515
+ const [up, down] = li.querySelectorAll('.ir-col-move button');
4516
+ if (up) up.disabled = i === 0;
4517
+ if (down) down.disabled = i === items.length - 1;
4518
+ });
4519
+ if (!moved) return;
4520
+ const status = list.closest('.ir-columns')?.parentElement?.querySelector('[data-col-status]');
4521
+ const name = moved.querySelector('label')?.textContent.trim() || moved.dataset.colName;
4522
+ if (status) status.textContent = fmt(t('report.moved', '{column}: position {n} of {total}'), { column: name, n: items.indexOf(moved) + 1, total: items.length });
4523
+ }
4524
+ document.addEventListener('click', (e) => {
4525
+ const btn = e.target.closest?.('[data-col-order] .ir-col-move button');
4526
+ if (!btn) return;
4527
+ e.preventDefault();
4528
+ const li = btn.closest('li');
4529
+ const list = li.parentElement;
4530
+ const up = btn === li.querySelector('.ir-col-move button');
4531
+ const other = up ? li.previousElementSibling : li.nextElementSibling;
4532
+ if (!other) return;
4533
+ if (up) other.before(li);
4534
+ else other.after(li);
4535
+ refresh(list, li);
4536
+ (btn.disabled ? li.querySelector('.ir-col-move button:not(:disabled)') : btn)?.focus();
4537
+ });
4538
+ let dragged = null;
4539
+ document.addEventListener('dragstart', (e) => {
4540
+ const li = e.target.closest?.('[data-col-order] > li');
4541
+ if (!li) return;
4542
+ dragged = li;
4543
+ li.classList.add('dragging');
4544
+ e.dataTransfer.effectAllowed = 'move';
4545
+ e.dataTransfer.setData('text/plain', li.dataset.colName || '');
4546
+ });
4547
+ document.addEventListener('dragover', (e) => {
4548
+ const list = e.target.closest?.('[data-col-order]');
4549
+ if (!dragged || !list || dragged.parentElement !== list) return;
4550
+ e.preventDefault();
4551
+ const after = [...list.children].find((li) => li !== dragged && e.clientY < li.getBoundingClientRect().top + li.offsetHeight / 2);
4552
+ if (after) after.before(dragged);
4553
+ else list.append(dragged);
4554
+ });
4555
+ document.addEventListener('drop', (e) => { if (dragged && e.target.closest?.('[data-col-order]')) e.preventDefault(); });
4556
+ document.addEventListener('dragend', () => {
4557
+ if (!dragged) return;
4558
+ dragged.classList.remove('dragging');
4559
+ refresh(dragged.parentElement, dragged);
4560
+ dragged = null;
4561
+ });
4562
+ })();
4563
+
4423
4564
  // (sprint 76) the report pager's rows per page: sent on change
4424
4565
  document.addEventListener('change', (e) => {
4425
4566
  if (e.target.matches?.('select[data-go]')) e.target.form?.submit();
package/src/i18n/ar.ts CHANGED
@@ -475,6 +475,30 @@ export const ar: Record<MessageKey, string> = {
475
475
  'op.not_contains': "لا يحتوي على",
476
476
  'op.null': "فارغ",
477
477
  'op.not_null': "غير فارغ",
478
+ 'op.in': "أحد",
479
+ 'op.not_in': "ليس أيًا من",
480
+ 'op.between': "بين",
481
+ 'op.period': "ضمن",
482
+ 'report.value_to': "إلى",
483
+ 'report.values': "القيم",
484
+ 'report.period': "الفترة",
485
+ 'report.and': "و",
486
+ 'report.filter_help': "أحد: قيم مفصولة بفواصل أو محددة في القائمة. بين: يمكن ترك إحدى القيمتين فارغة. ضمن: فترة لعمود تاريخ.",
487
+ 'report.order_chip': "ترتيب أعمدة خاص",
488
+ 'report.order_reset': "العودة إلى ترتيب أعمدة التقرير",
489
+ 'report.order_help': "اسحب عمودًا أو استخدم الأسهم لتغيير الترتيب.",
490
+ 'report.move_up': "نقل {column} لأعلى",
491
+ 'report.move_down': "نقل {column} لأسفل",
492
+ 'report.moved': "{column}: الموضع {n} من {total}",
493
+ 'period.today': "اليوم",
494
+ 'period.yesterday': "أمس",
495
+ 'period.last_7_days': "آخر 7 أيام",
496
+ 'period.last_30_days': "آخر 30 يومًا",
497
+ 'period.next_7_days': "الأيام السبعة القادمة",
498
+ 'period.this_month': "هذا الشهر",
499
+ 'period.last_month': "الشهر الماضي",
500
+ 'period.this_year': "هذه السنة",
501
+ 'period.last_year': "السنة الماضية",
478
502
  'grid.delete_row': "حذف الصف {row}",
479
503
  'grid.new': "جديد",
480
504
  'grid.row_changed': "الصف {row}: تم تغيير هذا الصف خارج الشبكة؛ أعد تحميل الصفحة.",
package/src/i18n/cs.ts CHANGED
@@ -475,6 +475,30 @@ export const cs: Record<MessageKey, string> = {
475
475
  'op.not_contains': "neobsahuje",
476
476
  'op.null': "je prázdné",
477
477
  'op.not_null': "není prázdné",
478
+ 'op.in': "je jedno z",
479
+ 'op.not_in': "není žádné z",
480
+ 'op.between': "je mezi",
481
+ 'op.period': "je v",
482
+ 'report.value_to': "Do",
483
+ 'report.values': "Hodnoty",
484
+ 'report.period': "Období",
485
+ 'report.and': "a",
486
+ 'report.filter_help': "Je jedno z: hodnoty oddělené čárkami nebo zaškrtnuté v seznamu. Je mezi: jedna z hodnot může zůstat prázdná. Je v: období sloupce s datem.",
487
+ 'report.order_chip': "Vlastní pořadí sloupců",
488
+ 'report.order_reset': "Zpět na pořadí sloupců sestavy",
489
+ 'report.order_help': "Přetáhněte sloupec nebo použijte šipky ke změně pořadí.",
490
+ 'report.move_up': "Posunout {column} nahoru",
491
+ 'report.move_down': "Posunout {column} dolů",
492
+ 'report.moved': "{column}: pozice {n} z {total}",
493
+ 'period.today': "dnes",
494
+ 'period.yesterday': "včera",
495
+ 'period.last_7_days': "posledních 7 dnech",
496
+ 'period.last_30_days': "posledních 30 dnech",
497
+ 'period.next_7_days': "příštích 7 dnech",
498
+ 'period.this_month': "tomto měsíci",
499
+ 'period.last_month': "minulém měsíci",
500
+ 'period.this_year': "tomto roce",
501
+ 'period.last_year': "minulém roce",
478
502
  'grid.delete_row': "Smazat řádek {row}",
479
503
  'grid.new': "nový",
480
504
  'grid.row_changed': "Řádek {row}: tento řádek byl změněn mimo mřížku; načtěte stránku znovu.",
package/src/i18n/da.ts CHANGED
@@ -475,6 +475,30 @@ export const da: Record<MessageKey, string> = {
475
475
  'op.not_contains': "indeholder ikke",
476
476
  'op.null': "er tom",
477
477
  'op.not_null': "er ikke tom",
478
+ 'op.in': "er en af",
479
+ 'op.not_in': "er ingen af",
480
+ 'op.between': "er mellem",
481
+ 'op.period': "er i",
482
+ 'report.value_to': "Til",
483
+ 'report.values': "Værdier",
484
+ 'report.period': "Periode",
485
+ 'report.and': "og",
486
+ 'report.filter_help': "Er en af: værdier adskilt af kommaer, eller markeret på listen. Er mellem: den ene værdi må være tom. Er i: en periode for en datokolonne.",
487
+ 'report.order_chip': "Egen kolonnerækkefølge",
488
+ 'report.order_reset': "Tilbage til rapportens kolonnerækkefølge",
489
+ 'report.order_help': "Træk en kolonne, eller brug pilene, for at ændre rækkefølgen.",
490
+ 'report.move_up': "Flyt {column} op",
491
+ 'report.move_down': "Flyt {column} ned",
492
+ 'report.moved': "{column}: position {n} af {total}",
493
+ 'period.today': "i dag",
494
+ 'period.yesterday': "i går",
495
+ 'period.last_7_days': "de seneste 7 dage",
496
+ 'period.last_30_days': "de seneste 30 dage",
497
+ 'period.next_7_days': "de næste 7 dage",
498
+ 'period.this_month': "denne måned",
499
+ 'period.last_month': "sidste måned",
500
+ 'period.this_year': "dette år",
501
+ 'period.last_year': "sidste år",
478
502
  'grid.delete_row': "Slet række {row}",
479
503
  'grid.new': "ny",
480
504
  'grid.row_changed': "Række {row}: rækken er ændret uden for gitteret; genindlæs siden.",
package/src/i18n/de.ts CHANGED
@@ -472,6 +472,30 @@ export const de: Record<MessageKey, string> = {
472
472
  'op.not_contains': 'enthält nicht',
473
473
  'op.null': 'ist leer',
474
474
  'op.not_null': 'ist nicht leer',
475
+ 'op.in': "ist einer von",
476
+ 'op.not_in': "ist keiner von",
477
+ 'op.between': "liegt zwischen",
478
+ 'op.period': "liegt in",
479
+ 'report.value_to': "Bis",
480
+ 'report.values': "Werte",
481
+ 'report.period': "Zeitraum",
482
+ 'report.and': "und",
483
+ 'report.filter_help': "Ist einer von: Werte durch Kommas getrennt oder in der Liste angehakt. Liegt zwischen: ein Wert darf leer bleiben. Liegt in: ein Zeitraum einer Datumsspalte.",
484
+ 'report.order_chip': "Eigene Spaltenreihenfolge",
485
+ 'report.order_reset': "Zurück zur Spaltenreihenfolge des Berichts",
486
+ 'report.order_help': "Ziehen Sie eine Spalte oder verwenden Sie die Pfeile, um die Reihenfolge zu ändern.",
487
+ 'report.move_up': "{column} nach oben",
488
+ 'report.move_down': "{column} nach unten",
489
+ 'report.moved': "{column}: Position {n} von {total}",
490
+ 'period.today': "heute",
491
+ 'period.yesterday': "gestern",
492
+ 'period.last_7_days': "den letzten 7 Tagen",
493
+ 'period.last_30_days': "den letzten 30 Tagen",
494
+ 'period.next_7_days': "den nächsten 7 Tagen",
495
+ 'period.this_month': "diesem Monat",
496
+ 'period.last_month': "dem letzten Monat",
497
+ 'period.this_year': "diesem Jahr",
498
+ 'period.last_year': "dem letzten Jahr",
475
499
  'grid.delete_row': 'Zeile {row} löschen',
476
500
  'grid.new': 'neu',
477
501
  'grid.row_changed': 'Zeile {row}: Diese Zeile wurde außerhalb des Rasters geändert; laden Sie die Seite neu.',
package/src/i18n/el.ts CHANGED
@@ -475,6 +475,30 @@ export const el: Record<MessageKey, string> = {
475
475
  'op.not_contains': "δεν περιέχει",
476
476
  'op.null': "είναι κενό",
477
477
  'op.not_null': "δεν είναι κενό",
478
+ 'op.in': "είναι ένα από",
479
+ 'op.not_in': "δεν είναι κανένα από",
480
+ 'op.between': "είναι μεταξύ",
481
+ 'op.period': "είναι στο",
482
+ 'report.value_to': "Έως",
483
+ 'report.values': "Τιμές",
484
+ 'report.period': "Περίοδος",
485
+ 'report.and': "και",
486
+ 'report.filter_help': "Είναι ένα από: τιμές χωρισμένες με κόμματα ή επιλεγμένες στη λίστα. Είναι μεταξύ: μία από τις τιμές μπορεί να μείνει κενή. Είναι στο: μια περίοδος μιας στήλης ημερομηνίας.",
487
+ 'report.order_chip': "Δική σας σειρά στηλών",
488
+ 'report.order_reset': "Επιστροφή στη σειρά στηλών της αναφοράς",
489
+ 'report.order_help': "Σύρετε μια στήλη ή χρησιμοποιήστε τα βέλη της για να αλλάξετε τη σειρά.",
490
+ 'report.move_up': "Μετακίνηση {column} πάνω",
491
+ 'report.move_down': "Μετακίνηση {column} κάτω",
492
+ 'report.moved': "{column}: θέση {n} από {total}",
493
+ 'period.today': "σήμερα",
494
+ 'period.yesterday': "χθες",
495
+ 'period.last_7_days': "τις τελευταίες 7 ημέρες",
496
+ 'period.last_30_days': "τις τελευταίες 30 ημέρες",
497
+ 'period.next_7_days': "τις επόμενες 7 ημέρες",
498
+ 'period.this_month': "αυτόν τον μήνα",
499
+ 'period.last_month': "τον προηγούμενο μήνα",
500
+ 'period.this_year': "φέτος",
501
+ 'period.last_year': "πέρυσι",
478
502
  'grid.delete_row': "Διαγραφή γραμμής {row}",
479
503
  'grid.new': "νέα",
480
504
  'grid.row_changed': "Γραμμή {row}: η γραμμή άλλαξε εκτός πλέγματος· φορτώστε ξανά τη σελίδα.",
package/src/i18n/es.ts CHANGED
@@ -472,6 +472,30 @@ export const es: Record<MessageKey, string> = {
472
472
  'op.not_contains': 'no contiene',
473
473
  'op.null': 'está vacío',
474
474
  'op.not_null': 'no está vacío',
475
+ 'op.in': "es uno de",
476
+ 'op.not_in': "no es ninguno de",
477
+ 'op.between': "está entre",
478
+ 'op.period': "está en",
479
+ 'report.value_to': "Hasta",
480
+ 'report.values': "Valores",
481
+ 'report.period': "Periodo",
482
+ 'report.and': "y",
483
+ 'report.filter_help': "Es uno de: valores separados por comas, o marcados en la lista. Está entre: cualquiera de los valores puede quedar vacío. Está en: un periodo de una columna de fecha.",
484
+ 'report.order_chip': "Orden de columnas propio",
485
+ 'report.order_reset': "Volver al orden de columnas del informe",
486
+ 'report.order_help': "Arrastre una columna, o use sus flechas, para cambiar el orden.",
487
+ 'report.move_up': "Subir {column}",
488
+ 'report.move_down': "Bajar {column}",
489
+ 'report.moved': "{column}: posición {n} de {total}",
490
+ 'period.today': "hoy",
491
+ 'period.yesterday': "ayer",
492
+ 'period.last_7_days': "los últimos 7 días",
493
+ 'period.last_30_days': "los últimos 30 días",
494
+ 'period.next_7_days': "los próximos 7 días",
495
+ 'period.this_month': "este mes",
496
+ 'period.last_month': "el mes pasado",
497
+ 'period.this_year': "este año",
498
+ 'period.last_year': "el año pasado",
475
499
  'grid.delete_row': 'Suprimir la fila {row}',
476
500
  'grid.new': 'nueva',
477
501
  'grid.row_changed': 'Fila {row}: esta fila se ha modificado fuera de la cuadrícula; vuelva a cargar la página.',
package/src/i18n/fi.ts CHANGED
@@ -475,6 +475,30 @@ export const fi: Record<MessageKey, string> = {
475
475
  'op.not_contains': "ei sisällä",
476
476
  'op.null': "on tyhjä",
477
477
  'op.not_null': "ei ole tyhjä",
478
+ 'op.in': "on jokin näistä",
479
+ 'op.not_in': "ei ole mikään näistä",
480
+ 'op.between': "on välillä",
481
+ 'op.period': "on ajanjaksolla",
482
+ 'report.value_to': "Asti",
483
+ 'report.values': "Arvot",
484
+ 'report.period': "Ajanjakso",
485
+ 'report.and': "ja",
486
+ 'report.filter_help': "On jokin näistä: arvot pilkuilla eroteltuina tai valittuina luettelosta. On välillä: toinen arvoista voi jäädä tyhjäksi. On ajanjaksolla: päivämääräsarakkeen ajanjakso.",
487
+ 'report.order_chip': "Oma sarakejärjestys",
488
+ 'report.order_reset': "Takaisin raportin sarakejärjestykseen",
489
+ 'report.order_help': "Vedä saraketta tai käytä nuolia järjestyksen muuttamiseen.",
490
+ 'report.move_up': "Siirrä {column} ylös",
491
+ 'report.move_down': "Siirrä {column} alas",
492
+ 'report.moved': "{column}: sijainti {n}/{total}",
493
+ 'period.today': "tänään",
494
+ 'period.yesterday': "eilen",
495
+ 'period.last_7_days': "viimeiset 7 päivää",
496
+ 'period.last_30_days': "viimeiset 30 päivää",
497
+ 'period.next_7_days': "seuraavat 7 päivää",
498
+ 'period.this_month': "tämä kuukausi",
499
+ 'period.last_month': "viime kuukausi",
500
+ 'period.this_year': "tämä vuosi",
501
+ 'period.last_year': "viime vuosi",
478
502
  'grid.delete_row': "Poista rivi {row}",
479
503
  'grid.new': "uusi",
480
504
  'grid.row_changed': "Rivi {row}: riviä on muutettu ruudukon ulkopuolella; lataa sivu uudelleen.",
package/src/i18n/fr.ts CHANGED
@@ -472,6 +472,30 @@ export const fr: Record<MessageKey, string> = {
472
472
  'op.not_contains': 'ne contient pas',
473
473
  'op.null': 'est vide',
474
474
  'op.not_null': 'n’est pas vide',
475
+ 'op.in': "est l'une des valeurs",
476
+ 'op.not_in': "n'est aucune des valeurs",
477
+ 'op.between': "est entre",
478
+ 'op.period': "est dans",
479
+ 'report.value_to': "À",
480
+ 'report.values': "Valeurs",
481
+ 'report.period': "Période",
482
+ 'report.and': "et",
483
+ 'report.filter_help': "Est l'une des valeurs : valeurs séparées par des virgules, ou cochées dans la liste. Est entre : l'une des valeurs peut rester vide. Est dans : une période d'une colonne de date.",
484
+ 'report.order_chip': "Ordre des colonnes personnalisé",
485
+ 'report.order_reset': "Revenir à l'ordre des colonnes du rapport",
486
+ 'report.order_help': "Faites glisser une colonne, ou utilisez ses flèches, pour changer l'ordre.",
487
+ 'report.move_up': "Monter {column}",
488
+ 'report.move_down': "Descendre {column}",
489
+ 'report.moved': "{column} : position {n} sur {total}",
490
+ 'period.today': "aujourd'hui",
491
+ 'period.yesterday': "hier",
492
+ 'period.last_7_days': "les 7 derniers jours",
493
+ 'period.last_30_days': "les 30 derniers jours",
494
+ 'period.next_7_days': "les 7 prochains jours",
495
+ 'period.this_month': "ce mois-ci",
496
+ 'period.last_month': "le mois dernier",
497
+ 'period.this_year': "cette année",
498
+ 'period.last_year': "l'année dernière",
475
499
  'grid.delete_row': 'Supprimer la ligne {row}',
476
500
  'grid.new': 'nouveau',
477
501
  'grid.row_changed': 'Ligne {row} : cette ligne a été modifiée en dehors de la grille ; rechargez la page.',