pgkiln 0.42.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/db/migrations/099_layout_positions.sql +29 -0
- package/db/migrations/100_generated_labels.sql +381 -0
- package/db/migrations/101_theme_choice.sql +15 -0
- package/docs/apex-feature-parity.md +36 -9
- package/docs/guide/03-builder.md +82 -21
- package/docs/guide/04-pages-and-regions.md +55 -5
- package/docs/guide/05-items.md +1 -1
- package/docs/guide/09-reference.md +5 -1
- package/docs/guide/12-development.md +2 -1
- package/docs/guide/14-globalization.md +5 -1
- package/package.json +1 -1
- package/public/app.css +80 -0
- package/public/app.js +189 -1
- package/public/builder.css +112 -0
- package/public/builder.js +280 -3
- package/src/builder/appsheets.ts +53 -13
- package/src/builder/appwizard.ts +5 -3
- package/src/builder/arrange.ts +133 -17
- package/src/builder/components.ts +28 -22
- package/src/builder/designer.ts +67 -18
- package/src/builder/forms.ts +4 -1
- package/src/builder/object-browser.ts +342 -0
- package/src/builder/pwa.ts +3 -3
- package/src/builder/routes.ts +85 -26
- package/src/builder/shared.ts +103 -1
- package/src/builder/sql.ts +13 -65
- package/src/builder/ui.ts +21 -6
- package/src/i18n/ar.ts +18 -0
- package/src/i18n/cs.ts +18 -0
- package/src/i18n/da.ts +18 -0
- package/src/i18n/de.ts +18 -0
- package/src/i18n/el.ts +18 -0
- package/src/i18n/es.ts +18 -0
- package/src/i18n/fi.ts +18 -0
- package/src/i18n/fr.ts +18 -0
- package/src/i18n/he.ts +18 -0
- package/src/i18n/it.ts +18 -0
- package/src/i18n/ja.ts +18 -0
- package/src/i18n/ko.ts +18 -0
- package/src/i18n/nb.ts +18 -0
- package/src/i18n/pl.ts +18 -0
- package/src/i18n/pt.ts +18 -0
- package/src/i18n/ru.ts +18 -0
- package/src/i18n/sv.ts +18 -0
- package/src/i18n/tr.ts +18 -0
- package/src/i18n/uk.ts +18 -0
- package/src/i18n/zh.ts +18 -0
- package/src/i18n.ts +36 -0
- package/src/metadata.ts +5 -1
- package/src/runtime/account.ts +5 -5
- package/src/runtime/devbar.ts +16 -13
- package/src/runtime/engine.ts +6 -0
- package/src/runtime/facets.ts +34 -3
- package/src/runtime/format.ts +52 -0
- package/src/runtime/items.ts +27 -0
- package/src/runtime/locale.ts +7 -1
- package/src/runtime/regions.ts +36 -2
- package/src/runtime/render.ts +27 -6
- package/src/runtime/report.ts +141 -81
- package/src/runtime/routes.ts +39 -7
package/docs/guide/03-builder.md
CHANGED
|
@@ -371,15 +371,20 @@ The wizards (every *Create application* flow and the page wizards) make pages th
|
|
|
371
371
|
forms and dialog titles the singular (*Employee*).
|
|
372
372
|
- **Reports** show a foreign key's parent by its display column (a name, title or label, else its first
|
|
373
373
|
text column): *Manager* shows KING, *Department* shows SALES. The key itself stays in the query,
|
|
374
|
-
hidden, so filters can use it
|
|
374
|
+
hidden, so filters can use it; a report never has two columns with the same heading (also a faceted
|
|
375
|
+
search report, whose facets filter on the display column). A row starts with a pencil that opens the form.
|
|
376
|
+
- **Interactive grids** (the grid page and both grids of a master-detail page) use the same labels as
|
|
377
|
+
headings (*Department Number*, *Hire Date*); a foreign key is a select list of the parent's names.
|
|
375
378
|
- **Files**: a `bytea` column becomes one file upload item that also fills the columns that go with it
|
|
376
379
|
(`<col>_name`/`_filename`, `<col>_mime`/`_mime_type`, `<col>_size`, `<col>_updated`; or `filename`
|
|
377
380
|
and `mime_type` next to the only `bytea` column). Reports leave these columns out. Columns named like
|
|
378
381
|
*photo*, *image* or *logo* accept pictures only.
|
|
379
382
|
- **Numbers** get a format mask with group separators (and the scale's decimals for `numeric(p,s)`),
|
|
380
|
-
in reports and forms alike, in the application's language (*2,850.00*); keys get none.
|
|
381
|
-
- The **Dashboard** comes right after *Home* in the menu; its charts are titled *Employees by Manager
|
|
382
|
-
|
|
383
|
+
in reports, read-only grid cells and forms alike, in the application's language (*2,850.00*); keys get none.
|
|
384
|
+
- The **Dashboard** comes right after *Home* in the menu; its charts are titled *Employees by Manager*
|
|
385
|
+
(a count) or *Salary by Department* (the sum of an amount column: salary, total, price, cost, value…),
|
|
386
|
+
a donut for six groups or fewer, a line for a date, else a sorted bar; a grouping that says nothing (one
|
|
387
|
+
group, or every group the same size) is left out. Rows without a value are labelled *(none)*, and bar charts show the ten largest values (the rest is
|
|
383
388
|
one *Other* bar). Tables with row-level security are left out (the application's role may see none of
|
|
384
389
|
their rows); the result page says which.
|
|
385
390
|
- The **Home** page has a hero with the application's icon and name, and a card per page of the menu
|
|
@@ -462,6 +467,14 @@ they are **not** run until you choose to.
|
|
|
462
467
|
|
|
463
468
|
## App dashboard
|
|
464
469
|
|
|
470
|
+
(sprint 74) Above the pages: a **search** by page name or number (the rows filter while you type),
|
|
471
|
+
**Report** and **Icons** views, and **Create page** (the page wizards below). **Tasks** on the right: run the
|
|
472
|
+
application, create pages (also with AI), Shared Components, page groups, export, backups, supporting
|
|
473
|
+
objects, lock or delete the application.
|
|
474
|
+
|
|
475
|
+
The **default-password** warning shows on the App Builder home (and Developers) only; dismiss it with × until the
|
|
476
|
+
next sign-in. The avatar keeps a red dot until the password is changed.
|
|
477
|
+
|
|
465
478
|
Open an application to see its pages, with region/item/dynamic-action/process counts,
|
|
466
479
|
authorization and protection. The tabs under its name lead to **Shared Components**, **Activity**,
|
|
467
480
|
**REST API**, **Settings**, **Search** and **Advisor**; **Export** and **Run** are on the right.
|
|
@@ -485,7 +498,7 @@ step, which keeps the table and type.
|
|
|
485
498
|
| **Calendar** | A [calendar](04-pages-and-regions.md#calendar) region (month, week, day and list views) | Start: a date or timestamp column named like *start*, *begin* or *…_date* (not *created*/*updated*); end: one named like *end* or *until*; title: a name column, else the first foreign key's name |
|
|
486
499
|
| **Chart** | A [chart](04-pages-and-regions.md#chart) region: bar, column, line, area, donut, pie or funnel of the row count, or the sum, average, minimum or maximum of a number column, per label | Label: the first foreign key (its parent's name), else a text column that isn't unique |
|
|
487
500
|
| **Map** | A [map](04-pages-and-regions.md#map) region with popups and, if ticked, an interactive report of the same rows that the map filters (*Show this area in the list*) | Position: a PostGIS geometry or geography (markers, and lines and areas as shapes), a `point`, `lat`/`lng`-like number columns, or a *location* text column with `latitude,longitude` |
|
|
488
|
-
| **Faceted search** | An interactive report (9 columns wide) and a [facets](04-pages-and-regions.md#facets-faceted-search) panel (3 columns, collapsible) with a search field | Up to six facets: foreign keys (values of the parent's name, which the report shows
|
|
501
|
+
| **Faceted search** | An interactive report (9 columns wide) and a [facets](04-pages-and-regions.md#facets-faceted-search) panel (3 columns, collapsible) with a search field | Up to six facets: foreign keys (values of the parent's name, which the report shows instead of the key), booleans, text columns with few values, dates and numbers as ranges with *from*/*to* |
|
|
489
502
|
| **Master detail** | One page with a grid of the table and an editable grid of the selected row's details below it (the grids' [master-detail](04-pages-and-regions.md#grid-interactive-grid)): a hidden item for the selection, both grids with a grid DML process; new detail rows get the master's key | The detail table: a table with a foreign key to this table's primary key |
|
|
490
503
|
|
|
491
504
|
Cards, Calendar, Map and Faceted search take an optional **Form page** number: it adds a modal
|
|
@@ -532,8 +545,11 @@ choosing a component opens the Properties tab.
|
|
|
532
545
|
|
|
533
546
|
- **Left: the component tree**, with four tabs:
|
|
534
547
|
- **Rendering**: the page, *Pre-Rendering* (branches, computations and processes that run
|
|
535
|
-
before the page is shown), the
|
|
536
|
-
|
|
548
|
+
before the page is shown), the regions by
|
|
549
|
+
[display position](04-pages-and-regions.md#side-columns-and-display-positions) (Banner, Breadcrumb bar,
|
|
550
|
+
Left column, Body, Right column, Footer: the page template's positions and any other that has regions)
|
|
551
|
+
with their items and buttons (by [button position](04-pages-and-regions.md#button-positions): *Buttons*,
|
|
552
|
+
*Buttons: Next*, …), and page-level items and buttons;
|
|
537
553
|
- **Dynamic actions**, grouped by event (change, click, page load);
|
|
538
554
|
- **Processing**: computations after submit, validations, processes and the branches (the
|
|
539
555
|
[branch components](06-processing.md#branches) in sequence, then the buttons that go to
|
|
@@ -541,22 +557,36 @@ choosing a component opens the Properties tab.
|
|
|
541
557
|
- **Shared components** the page can use (lists of values, authorization schemes, navigation,
|
|
542
558
|
application items), linking to Shared Components.
|
|
543
559
|
|
|
544
|
-
Icons show which components have an authorization scheme, a condition or a build option
|
|
560
|
+
Icons show which components have an authorization scheme, a condition or a build option; type icons are coloured
|
|
561
|
+
by kind (regions, items, buttons, dynamic actions, processes). Folders open and close
|
|
545
562
|
with a click; with the keyboard, the arrow keys walk the tree (Left / Right close and open a
|
|
546
563
|
folder), Enter opens a component.
|
|
547
|
-
|
|
548
|
-
|
|
564
|
+
|
|
565
|
+
**Right-click** a region, item or button in the Rendering tree (or press <kbd>Shift</kbd>+<kbd>F10</kbd> or the
|
|
566
|
+
menu key) for its menu (APEX: the tree's context menu): *Create page item*, *Create button* (in the region),
|
|
567
|
+
*Create dynamic action*, *Create region below*, **Duplicate** (a copy right after it; a region comes with its
|
|
568
|
+
items and buttons, names get `_2`), **Copy to other page…** (to the end of a page of the same application; items
|
|
569
|
+
named `P<n>_` get that page's number, a region's buttons and items come along, references in SQL are not changed),
|
|
570
|
+
*Expand all below*, *Collapse all below* and *Delete*. The arrow keys move through the menu, Escape closes it.
|
|
571
|
+
APEX's *Create Sub Region* (pgkiln has no nested regions) and *Comment Out* (use a build option) are not there.
|
|
572
|
+
- **Middle: the Layout**: the page template's display positions as labelled zones (Banner, Breadcrumb bar,
|
|
573
|
+
the side column of a side-column template beside the Body, Footer), each with its regions on the 12-column
|
|
574
|
+
grid, each region with its items and its buttons in their button positions, as they will be placed on the page; under it a **gallery** of region types, item types
|
|
549
575
|
and button actions. The middle pane also has a **Page search** tab (searches the application)
|
|
550
576
|
a **Lock and comments** tab ([below](#page-locks-and-comments)) and a **Help** tab (layout keys and the substitution cheat sheet). Zoom in, zoom out and
|
|
551
577
|
maximize (hides the side panes) are above the layout.
|
|
552
578
|
- **Right: the property editor** for the selected component, grouped (Identification, Source,
|
|
553
579
|
Layout, Security, …) with help text for each property. Type in **Filter** to show only the
|
|
554
580
|
properties whose name contains the text (Escape clears it); click a group's name to fold it
|
|
555
|
-
(remembered on this device).
|
|
581
|
+
(remembered on this device). **Common** / **All** (APEX: Show Common / Show All) shows only the properties
|
|
582
|
+
most often set for regions, items and buttons, or all of them (remembered); **Go to group** jumps to a group
|
|
583
|
+
(opening the Attributes tab when the group is there). **Template options** open in a dialog from a button that
|
|
584
|
+
counts the chosen ones; they are saved with the other properties. Under the properties, the **Help** pane (APEX: the Help tab) shows the
|
|
556
585
|
property that has the focus (or the pointer): its help, the name it is stored under in exports and
|
|
557
586
|
application files, and a link to the guide section of the component's type.
|
|
558
587
|
|
|
559
|
-
The toolbar has the page switcher (previous,
|
|
588
|
+
The toolbar has the page switcher (previous, the page number: type or step to one and press Enter, a list of
|
|
589
|
+
all pages, next), **Undo** / **Redo** of
|
|
560
590
|
layout changes, the **Create** menu (region, item, button, dynamic action, computation, validation,
|
|
561
591
|
process, branch, or a new page), a **Utilities** menu (Advisor, search, shared components, all pages, export),
|
|
562
592
|
**Save** (saves the property editor; it is highlighted when there are unsaved changes) and **Run**
|
|
@@ -586,7 +616,11 @@ region that no longer fits starts a new row.
|
|
|
586
616
|
|
|
587
617
|
- **Drag a region** by its header to another place, or drag its right edge to make it wider or
|
|
588
618
|
narrower.
|
|
589
|
-
- **Drag
|
|
619
|
+
- **Drag a region into another position** (zone) to set its display position: e.g. a faceted search into
|
|
620
|
+
the *Left column* of a page with the Left side column template.
|
|
621
|
+
- **Drag an item or button** to another place in its region, to another region, or to *Page level*. While a
|
|
622
|
+
button is dragged, a region's empty [button positions](04-pages-and-regions.md#button-positions) (Create, Edit,
|
|
623
|
+
…, Previous, Next) show as drop targets; dropping it there sets its position.
|
|
590
624
|
- **Drag an entry of the gallery** onto the layout to create that component there, with a working
|
|
591
625
|
starting point (a sample query for reports, charts and cards; a name like `P5_NEW` for items);
|
|
592
626
|
then set its properties on the right. Clicking a gallery entry instead opens the create form
|
|
@@ -597,7 +631,8 @@ region that no longer fits starts a new row.
|
|
|
597
631
|
(move up, move down, narrower, wider, or move an item or button to another region); on phones and
|
|
598
632
|
tablets this is the way to arrange things.
|
|
599
633
|
- **Undo** and **Redo** in the toolbar take back the last 20 layout changes on this page (moving
|
|
600
|
-
and resizing; creating a component starts a new
|
|
634
|
+
and resizing, display and button positions too; creating, duplicating or copying a component starts a new
|
|
635
|
+
history).
|
|
601
636
|
|
|
602
637
|
Without JavaScript the panes are shown one under the other, every component is a link and the
|
|
603
638
|
Arrange buttons still work.
|
|
@@ -678,11 +713,13 @@ Chapters 4–7 describe every component type and property.
|
|
|
678
713
|
|
|
679
714
|
While you are signed in to the builder, the pages of your applications show the **developer
|
|
680
715
|
toolbar** when you run them in the same browser (APEX: the Runtime Developer Toolbar): a compact bar
|
|
681
|
-
|
|
716
|
+
centred at the bottom, each tool an icon with a short text (*Home*, *App 12*, *Page 3*, *Session*,
|
|
717
|
+
*Debug off*, *Quick edit*, *Customize*, *Info*) and a tooltip; on narrow screens, docked at the left or
|
|
718
|
+
right, or with *Icons only* in Settings, just the icons. It isn't shown to anyone else, nor inside
|
|
682
719
|
dialogs. The page keeps room for it, so it never covers the menu's last entry or a report's pager.
|
|
683
720
|
After a few seconds without use it shrinks to a slim tab at the edge; point at it or Tab to it to
|
|
684
|
-
bring it back. **Settings** (the last icon) docks it at the bottom, top, left or right
|
|
685
|
-
hiding off (kept in your browser). It has:
|
|
721
|
+
bring it back. **Settings** (the last icon) docks it at the bottom, top, left or right, turns the
|
|
722
|
+
hiding off and shows *Icons only* (kept in your browser). It has:
|
|
686
723
|
|
|
687
724
|
| Entry | Does |
|
|
688
725
|
|---|---|
|
|
@@ -813,7 +850,14 @@ exported.
|
|
|
813
850
|
|
|
814
851
|
## Shared components
|
|
815
852
|
|
|
816
|
-
Components used by the whole application:
|
|
853
|
+
Components used by the whole application. **Shared Components** opens on a grid like APEX's: ten groups
|
|
854
|
+
(Application Logic, Security, Other Components, Navigation and Search, User Interface, Files and Reports,
|
|
855
|
+
Data Sources, Workflows and Automations, Globalization, Generative AI) with a link and a count per component
|
|
856
|
+
type. A type opens its list (`?type=…`): search by name (the rows filter while you type), sort by name,
|
|
857
|
+
**Create**, and a row opens its editor. The types pgkiln keeps in the application's Settings (authentication,
|
|
858
|
+
security attributes, navigation bar list, user interface attributes, PWA, globalization attributes) open the
|
|
859
|
+
right Settings tab. **Breadcrumbs** shows the pages by their breadcrumb parent. **Tree view** (`?view=tree`)
|
|
860
|
+
is the earlier page: every component in one rail, with **Access control** next to it.
|
|
817
861
|
|
|
818
862
|
| Component | Purpose |
|
|
819
863
|
|---|---|
|
|
@@ -929,6 +973,12 @@ register at the provider, and has a *Test discovery* button. See
|
|
|
929
973
|
|
|
930
974
|
## Settings
|
|
931
975
|
|
|
976
|
+
Settings has tabs (APEX: Edit Application Definition and Security Attributes): **Definition**, **Security**,
|
|
977
|
+
**Sign-in**, **User Interface**, **Globalization**, **Errors and Sessions** and **Progressive Web App**. It opens
|
|
978
|
+
on Definition (`?tab=…` opens another). *Save settings* saves the first five together and comes back to the tab
|
|
979
|
+
you were on. The Security tab shows only the fields of the chosen authentication type (HTTP header, database
|
|
980
|
+
accounts or custom).
|
|
981
|
+
|
|
932
982
|
- **Application**: name, alias, home page.
|
|
933
983
|
- **Security**: authentication (*App users*, *HTTP header*, *Database accounts*, *Custom* or
|
|
934
984
|
*None*), the database role, and **debug mode** (shows full database errors to users; development
|
|
@@ -1152,13 +1202,24 @@ Commands; other developers' are never shown) and the workspace's **recent SQL sc
|
|
|
1152
1202
|
session's **schema** (APEX: the default schema): it goes first in the search path of SQL Commands and SQL Scripts until
|
|
1153
1203
|
you sign out. Tasks link to Quick SQL, blueprints, table descriptions, sample data and Generate DDL.
|
|
1154
1204
|
|
|
1205
|
+
(sprint 75) The tools are tabs: Home, Object Browser, SQL Commands, SQL Scripts and Utilities; **More** opens the
|
|
1206
|
+
others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compare, AI), and the open one is a tab too.
|
|
1207
|
+
|
|
1155
1208
|
- **SQL Commands** (`/builder/sql/commands`): run any SQL as the **owner connection**, not as an application role. Multiple
|
|
1156
1209
|
statements are allowed; the result of the last one is shown (up to 500 rows). Press
|
|
1157
1210
|
**Ctrl/Cmd + Enter** to run. The [code editor](#the-code-editor) suggests every schema, table,
|
|
1158
1211
|
column and function the owner sees.
|
|
1159
|
-
- **Object Browser
|
|
1160
|
-
|
|
1161
|
-
|
|
1212
|
+
- **Object Browser** (APEX's): the **schema** in the header (the session's schema by default) and a tree with a
|
|
1213
|
+
folder per object type (tables, views, materialized views, indexes, sequences, types, functions, procedures,
|
|
1214
|
+
triggers) and a **filter** by name. pgkiln's own schemas (`meta`, `pgkiln_plugins`) and objects that belong to an
|
|
1215
|
+
extension show only with **Show system objects**. **Create** (and the tiles shown when nothing is selected) opens
|
|
1216
|
+
SQL Commands with a CREATE TABLE, VIEW, FUNCTION, SEQUENCE or INDEX statement to fill in. A table opens in tabs:
|
|
1217
|
+
**Columns** (with comments; *Add*, *Rename* and *Drop column* write the ALTER TABLE statement into SQL Commands to
|
|
1218
|
+
review and run: nothing changes until you press Run), **Data** (25 rows a page), **Indexes**, **Constraints**
|
|
1219
|
+
(primary key, foreign keys with the table they refer to, unique, check), **Triggers**, **Grants**, **Row level
|
|
1220
|
+
security** (on or off, the policies), **Dependencies** (views and foreign keys that use it, and what it uses),
|
|
1221
|
+
**Statistics** (rows, sizes, analyze and vacuum times) and **DDL**. A view has the same tabs where they apply; a
|
|
1222
|
+
function or procedure shows its source, a trigger, index, sequence or type its definition.
|
|
1162
1223
|
- **SQL Scripts**: saved scripts, shared by the developers of the workspace. Create one in the editor, upload a
|
|
1163
1224
|
`.sql` file (UTF-8, up to 5 MB) or save one from Quick SQL; download it again as `.sql`. **Run**
|
|
1164
1225
|
splits the script into statements at semicolons (outside strings, comments, quoted identifiers,
|
|
@@ -40,6 +40,41 @@ template of the same name) shows the page without the header, the navigation men
|
|
|
40
40
|
navigation bar: the title and the regions only, centred. The application's
|
|
41
41
|
[login page](08-security.md#the-login-page) uses it and gets the sign-in page's backdrop.
|
|
42
42
|
|
|
43
|
+
### Side columns and display positions
|
|
44
|
+
|
|
45
|
+
Like APEX's Universal Theme, a page has **display positions** and a region chooses one with its
|
|
46
|
+
**Position** (Page Designer → region → Layout; `position` in the files; APEX: Layout → Position):
|
|
47
|
+
|
|
48
|
+
| `position` | Where the region shows |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `banner` | At the top of the page content, above everything else |
|
|
51
|
+
| `breadcrumb` | In the bar under the title (the place of APEX's Breadcrumb Bar) |
|
|
52
|
+
| `left`, `right` | In the side column of a page with page template *Left side column* or *Right side column* |
|
|
53
|
+
| `body` (or empty) | The page body, on the 12-column grid (the default) |
|
|
54
|
+
| `footer` | After the body |
|
|
55
|
+
|
|
56
|
+
The page templates **Left side column** and **Right side column** (Page Designer → Page → Appearance;
|
|
57
|
+
`page_template` `left_side_column` / `right_side_column`) put the regions of that position in a column
|
|
58
|
+
beside the body (14–18rem wide; under the body's start on screens under 900px). On a page without that
|
|
59
|
+
side column, `left` and `right` regions show in the body, in sequence. Regions keep their sequence within
|
|
60
|
+
a position, and a region its condition leaves out leaves no empty position behind. A faceted search in
|
|
61
|
+
the left column next to its report is the typical use.
|
|
62
|
+
|
|
63
|
+
### Button positions
|
|
64
|
+
|
|
65
|
+
A region's button has a **Button position** (Page Designer → button → Layout; `slot` in the files; APEX:
|
|
66
|
+
Button Position):
|
|
67
|
+
|
|
68
|
+
| `slot` | Where the button shows |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `create`, `edit`, `change`, `copy`, `help`, `up` | In the region's header, after the title |
|
|
71
|
+
| `previous`, `close`, `delete` | At the left end of the region's bottom bar |
|
|
72
|
+
| `next` | At the right end of the bottom bar |
|
|
73
|
+
| `region` (or empty) | With the region's other buttons, as before: the header of reports and charts, the bottom of forms and static content |
|
|
74
|
+
|
|
75
|
+
Positions apply to the `standard`, `collapsible` and `plain` templates; the other templates place every
|
|
76
|
+
button where they always do. Page-level buttons have no position.
|
|
77
|
+
|
|
43
78
|
### Dialogs and drawers
|
|
44
79
|
|
|
45
80
|
A modal page (Page Designer → Page → Appearance: *Page mode* Modal dialog) opens over the page that linked to it.
|
|
@@ -187,9 +222,18 @@ select e.empno, e.ename, e.job, d.dname as department, e.sal
|
|
|
187
222
|
|
|
188
223
|
Features for end users:
|
|
189
224
|
|
|
190
|
-
- **Search** across all columns
|
|
191
|
-
|
|
192
|
-
|
|
225
|
+
- **Search** across all columns, or in one column chosen under the magnifier at the start of the search field
|
|
226
|
+
(it shows the column's name once one is chosen); Enter searches (without JavaScript, a *Go* button)
|
|
227
|
+
(Enter searches; *Go* too).
|
|
228
|
+
- **Column heading menu** (sprint 76; with JavaScript): clicking a heading opens a menu with *Sort ascending*,
|
|
229
|
+
*Sort descending*, *Hide column*, *Control break* and the column's **values** with their counts (with the current
|
|
230
|
+
search and filters; at most 200), with a box to narrow them; choosing a value filters the report on it. The sort
|
|
231
|
+
arrow of the sorted column sorts at once. Without JavaScript a heading sorts (again for descending).
|
|
232
|
+
- **Hidden columns**: hidden from the heading menu or *Actions → Columns*, shown as chips to bring them back.
|
|
233
|
+
- **Pagination**: *1–15 of 107*, first, previous, next and last page, and the **rows per page** list.
|
|
234
|
+
- **Actions menu** (sprint 76: a short menu like APEX's; each entry opens a dialog, or unfolds in place without
|
|
235
|
+
JavaScript): *Columns*, *Filter*, *Data* (sort, aggregate, compute, control break), *Format* (highlight, rows per
|
|
236
|
+
page), *Chart*, *Group by*, *Pivot*, *Report* (saved reports, reset) and *Download* (CSV, Excel, PDF, print):
|
|
193
237
|
- **column filters** (`=`, `≠`, contains, does not contain, `>`, `≥`, `<`, `≤`, is empty, is
|
|
194
238
|
not empty) and **sort**;
|
|
195
239
|
- **control break**: group the rows by a column, with a heading row per group;
|
|
@@ -764,7 +808,9 @@ link is the way to change its dates.
|
|
|
764
808
|
A panel of filters, each with a live count, that filters a **report region on the same page**.
|
|
765
809
|
Counts take the search and all *other* facets into account. Three kinds of facet:
|
|
766
810
|
|
|
767
|
-
- **checkbox** (the default): the most frequent values of a column, each with a checkbox
|
|
811
|
+
- **checkbox** (the default): the most frequent values of a column, each with a checkbox; after the seventh
|
|
812
|
+
the rest sit under *Show all (n)* (open when one of them is chosen), and a boolean's values read *Yes* and
|
|
813
|
+
*No*. With
|
|
768
814
|
`"exclude": true` the facet gets an *Exclude the selected values* switch: the chosen values are
|
|
769
815
|
then left out instead (rows where the column is empty stay).
|
|
770
816
|
- **range**: a number or date column in ranges, as radio buttons ("Any", then each range). A
|
|
@@ -774,7 +820,11 @@ Counts take the search and all *other* facets into account. Three kinds of facet
|
|
|
774
820
|
- **star**: a rating column as "5 stars and up", "4 stars and up", … down to 1 (`max`, default 5).
|
|
775
821
|
|
|
776
822
|
With `"search": true` the panel starts with a search field: the same search as the report's own
|
|
777
|
-
(`r<id>_q`, the row as text contains the term).
|
|
823
|
+
(`r<id>_q`, the row as text contains the term). The report then shows no search field of its own (its
|
|
824
|
+
*Actions* menu stays), so the page has one.
|
|
825
|
+
|
|
826
|
+
The panel starts with the number of rows the search and the facets leave (*Total row count 14*,
|
|
827
|
+
APEX's *Total Row Count*).
|
|
778
828
|
|
|
779
829
|
**Facet charts** (APEX: facet charts): with `"chart": "bar"` or `"chart": "pie"` a facet shows its counts as a chart,
|
|
780
830
|
collapsed under its heading (*Chart*). Each bar or slice, and each row of the chart's data table, links to the page
|
package/docs/guide/05-items.md
CHANGED
|
@@ -11,7 +11,7 @@ page, optionally inside a region. Name them `P<page>_<NAME>` (uppercase letters,
|
|
|
11
11
|
| `text` | text field | text |
|
|
12
12
|
| `textarea` | multi-line text (always full width) | text |
|
|
13
13
|
| `number` | number field (numeric keyboard on phones) | e.g. `1250.50` |
|
|
14
|
-
| `date` | date picker | `YYYY-MM-DD` |
|
|
14
|
+
| `date` | date picker: the browser's, or (sprint 76) with an application date format or a date format mask on the item a text field in that format with a calendar button; typed dates are read back in the format | `YYYY-MM-DD` |
|
|
15
15
|
| `datetime` | date-time picker | `YYYY-MM-DDTHH:MM` |
|
|
16
16
|
| `email`, `tel`, `url` | typed fields with the matching phone keyboard | text |
|
|
17
17
|
| `password` | password field; never shown back, empty = unchanged | text |
|
|
@@ -281,6 +281,7 @@ Run these as the owner (in the SQL Workshop, `psql` or migrations):
|
|
|
281
281
|
| `meta.wizard_catalog(table)` | The columns as the wizards see them: kind (`text`, `number`, `date`, `timestamp`, `boolean`, `point`, `geometry`, `binary`, `other`), key, unique, foreign key and the parent's display column |
|
|
282
282
|
| `meta.wizard_label(name)`, `meta.wizard_table_label(table, plural default true)`, `meta.wizard_column_label(table, column)` | (097) The labels of the wizards: `hiredate` → *Hire Date*, `hr.emp` → *Employees* / *Employee*, `deptno` → *Department*; short comments win ([what the generated pages look like](03-builder.md#what-the-generated-pages-look-like)) |
|
|
283
283
|
| `meta.wizard_report(table, columns default null)` | (097) A report on a table as the wizards make it: `{"source", "hidden", "headings", "formats"}` (foreign keys joined to their parent's display column) |
|
|
284
|
+
| `meta.wizard_grid_labels(table)` | (100) An interactive grid's `{"headings", "formats"}` as the wizards make them: the labels of `meta.wizard_column_label` and the number format masks (keys get none) |
|
|
284
285
|
| `meta.app_activity(days default 30)` | (098) The current application's page views, sign-ins and errors of the last days (1 to 366, at most 10,000 rows, no IP addresses), for a signed-in user with the `admin` role of that application; others get an error. The Activity page of the Create Application wizard reads it |
|
|
285
286
|
| `meta.wizard_files(table)` | (097) The `bytea` columns and the columns holding their file name, mime type, size and change time |
|
|
286
287
|
| `meta.export_app(alias)` | The application as JSON (`pgkiln/2` format) |
|
|
@@ -423,6 +424,7 @@ navigation entries and application processes have the same `build_option` column
|
|
|
423
424
|
| `config` | Attributes per type ([chapter 4](04-pages-and-regions.md)) |
|
|
424
425
|
| `rest_source` | A REST data source the region reads; `source` is then SQL over `rest` ([chapter 19](19-rest-data-sources.md)) |
|
|
425
426
|
| `template_options` | text[]: CSS classes from a fixed list ([template options](04-pages-and-regions.md#template-options)) |
|
|
427
|
+
| `position` | `banner`, `breadcrumb`, `left`, `body` (or null), `right`, `footer` ([display positions](04-pages-and-regions.md#side-columns-and-display-positions)) |
|
|
426
428
|
|
|
427
429
|
**`item`**: `page_id`, `region_id`, `seq`, `name`, `label`, `type`, `lov`, `source_column`,
|
|
428
430
|
`default_value`, `required`, `help`, `readonly_condition`, `authz`, `config` ([chapter 5](05-items.md)).
|
|
@@ -430,7 +432,9 @@ navigation entries and application processes have the same `build_option` column
|
|
|
430
432
|
**`button`**: `page_id`, `region_id`, `seq`, `name`, `label`, `action` (`submit` / `redirect` / `da` /
|
|
431
433
|
`document` / `menu`), `target_page`, `target_items` (jsonb), `condition`, `authz`, `hot`, `confirm`,
|
|
432
434
|
`menu` (jsonb, for `menu`), `badge`, `badge_query` ([chapter 6](06-processing.md)), `template_options`
|
|
433
|
-
(text[], [template options](04-pages-and-regions.md#template-options))
|
|
435
|
+
(text[], [template options](04-pages-and-regions.md#template-options)), `slot` (a region button's
|
|
436
|
+
[button position](04-pages-and-regions.md#button-positions): `create`, `edit`, `change`, `copy`, `help`, `up`,
|
|
437
|
+
`previous`, `close`, `delete`, `next` or `region` / null).
|
|
434
438
|
|
|
435
439
|
**`dynamic_action`**: `page_id`, `seq`, `name`, `event`, `trigger_element`, `condition_type`,
|
|
436
440
|
`condition_value`, `action`, `affected_items`, `affected_region_id`, `code`, `items_to_submit`,
|
|
@@ -210,7 +210,8 @@ src/
|
|
|
210
210
|
shared.ts Shared Components and access control
|
|
211
211
|
designer.ts page designer: component tree (with computations and branches), layout canvas and gallery, property editor, toolbar
|
|
212
212
|
arrange.ts page designer layout changes: move, column span, create from the gallery, undo / redo
|
|
213
|
-
sql.ts SQL Workshop: SQL commands
|
|
213
|
+
sql.ts SQL Workshop: the home and SQL commands (templates and drafts to review)
|
|
214
|
+
object-browser.ts (sprint 75) the Object Browser: objects by type, system objects hidden, a table in tabs, column actions as SQL to review
|
|
214
215
|
scripts.ts SQL Workshop → SQL Scripts: editor, upload/download, run, results per statement, run history
|
|
215
216
|
quicksql.ts SQL Workshop → Quick SQL page (preview, save as script, run)
|
|
216
217
|
querybuilder.ts SQL Workshop → Query Builder: catalog, joins by foreign key or drawn, functions/group by, buildQuery() from the URL; the canvas is in builder.js
|
|
@@ -210,7 +210,11 @@ Under **Settings → Theme**, *Theme style* is **Automatic** (follow the device,
|
|
|
210
210
|
**Light** or **Dark**. With **Users may choose light or dark** (on by default, like APEX's
|
|
211
211
|
*Enable End Users to Choose Theme Style*), the user menu has an *Appearance* switch and My account
|
|
212
212
|
has the same choice. The choice is saved on the account, so it applies in every application that
|
|
213
|
-
allows it.
|
|
213
|
+
allows it. Until a user chooses, an application opens in its own *Theme style* (a new Iris application
|
|
214
|
+
light, also when the device is in dark mode); *Automatic* follows the device only when the application
|
|
215
|
+
or the user chose it. A user who isn't signed in has the *Appearance* switch in the user menu (with
|
|
216
|
+
*Sign in*), kept in a cookie of that application only (`pgkiln_mode`, path `/a/<alias>`), so a choice in
|
|
217
|
+
one application doesn't change another's.
|
|
214
218
|
|
|
215
219
|
## Base styles: Iris, Lavender and Standard
|
|
216
220
|
|
package/package.json
CHANGED
package/public/app.css
CHANGED
|
@@ -478,6 +478,8 @@ details.btn-menu[open] > summary .btn-caret { transform: rotate(-90deg); }
|
|
|
478
478
|
.report-toolbar { display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end; margin-bottom: 0.75rem; }
|
|
479
479
|
.report-toolbar .field { flex: 0 1 240px; }
|
|
480
480
|
.search { display: flex; gap: 0.4rem; flex: 1 1 320px; max-width: 560px; margin-left: auto; }
|
|
481
|
+
/* (sprint 78) a report whose search is the facets': the Actions menu at the start of the toolbar */
|
|
482
|
+
.report-toolbar .search:not(:has(input[type=search])) { flex: 0 1 auto; min-width: 0; margin-left: 0; }
|
|
481
483
|
.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.75rem; }
|
|
482
484
|
.chip { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.83rem; padding: 0.15rem 0.3rem 0.15rem 0.7rem; background: var(--accent-soft); border-radius: 99px; }
|
|
483
485
|
.chip a { text-decoration: none; font-size: 1rem; line-height: 1; padding: 0 0.3rem; border-radius: 99px; }
|
|
@@ -1144,6 +1146,10 @@ td[data-add]:hover > .cal-add, .cal-add:focus-visible { opacity: 1; }
|
|
|
1144
1146
|
.facet-chart .donut-figure { max-width: 9rem; margin: 0 auto; }
|
|
1145
1147
|
.facet-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
1146
1148
|
.facet-count { font-size: 0.75rem; color: var(--muted); background: var(--surface-3); border-radius: 99px; padding: 0 0.5rem; font-variant-numeric: tabular-nums; }
|
|
1149
|
+
/* (sprint 78) values after the seventh, and the rows the filters leave */
|
|
1150
|
+
.facet-more > summary { cursor: pointer; font-size: 0.85rem; color: var(--accent, var(--link)); padding: 0.15rem 0; }
|
|
1151
|
+
.facet-more[open] > summary { margin-bottom: 0.2rem; }
|
|
1152
|
+
.facet-total { margin: 0 0 0.6rem; font-size: 0.85rem; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
1147
1153
|
.js .facet-actions .btn-hot { display: none; }
|
|
1148
1154
|
.facet-exclude { font-size: 0.85rem; color: var(--muted); margin-top: 0.15rem; }
|
|
1149
1155
|
.facet-excluded .facet-value .facet-label { text-decoration: line-through; }
|
|
@@ -1811,6 +1817,14 @@ dialog.crop-dialog::backdrop { background: rgb(15 20 30 / 55%); }
|
|
|
1811
1817
|
.devbar-tool::-webkit-details-marker { display: none; }
|
|
1812
1818
|
.devbar .devbar-tool:hover, .devbar-menu[open] > .devbar-tool, .devbar-quick[aria-pressed="true"] { background: #2f3b4f; color: #fff; }
|
|
1813
1819
|
.devbar-debug-menu.is-on > .devbar-tool { color: #ffd166; }
|
|
1820
|
+
/* (sprint 79, UI-4) a text next to each icon (App 12, Page 3, Debug off); icons only when chosen or docked at a side */
|
|
1821
|
+
.devbar .devbar-tool:has(.devbar-text) { width: auto; min-width: 2.25rem; padding: 0 0.55rem; grid-auto-flow: column; gap: 0.35rem; white-space: nowrap; }
|
|
1822
|
+
.devbar[data-compact] .devbar-text, .devbar[data-dock="left"] .devbar-text, .devbar[data-dock="right"] .devbar-text { display: none; }
|
|
1823
|
+
.devbar[data-compact] .devbar-tool:has(.devbar-text), .devbar[data-dock="left"] .devbar-tool:has(.devbar-text), .devbar[data-dock="right"] .devbar-tool:has(.devbar-text) { width: 2.25rem; padding: 0; }
|
|
1824
|
+
@media (max-width: 900px) {
|
|
1825
|
+
.devbar .devbar-text { display: none; }
|
|
1826
|
+
.devbar .devbar-tool:has(.devbar-text) { width: 2.25rem; padding: 0; }
|
|
1827
|
+
}
|
|
1814
1828
|
.devbar a, .devbar-pop a { color: #9cc8ff; }
|
|
1815
1829
|
.devbar a:focus-visible, .devbar button:focus-visible, .devbar select:focus-visible, .devbar summary:focus-visible, .devbar input:focus-visible { outline: 2px solid #9cc8ff; outline-offset: 2px; }
|
|
1816
1830
|
.devbar-menu { position: relative; }
|
|
@@ -1885,3 +1899,69 @@ a.search-hit:hover, a.search-hit:focus-visible { background: var(--accent-soft);
|
|
|
1885
1899
|
/* (sprint 59) Quick edit from the developer toolbar */
|
|
1886
1900
|
.quick-edit .qe-target { outline: 2px dashed var(--accent); outline-offset: 2px; cursor: pointer; }
|
|
1887
1901
|
.devbar-quick[aria-pressed="true"] { background: var(--accent); color: var(--accent-text); }
|
|
1902
|
+
|
|
1903
|
+
/* (sprint 76) the pager: rows per page; a Go button only without JavaScript */
|
|
1904
|
+
.pager .pager-size { margin-right: 0; display: inline-flex; align-items: center; gap: 0.4rem; margin-left: auto; font-size: 0.85rem; }
|
|
1905
|
+
.pager-size select { min-height: 0; padding: 0.15rem 0.4rem; }
|
|
1906
|
+
.pager-size label { white-space: nowrap; }
|
|
1907
|
+
.js .no-js-only { display: none; }
|
|
1908
|
+
|
|
1909
|
+
/* (sprint 76) the interactive report's Actions menu: one line per entry, submenus, forms in dialogs */
|
|
1910
|
+
.actions-menu .menu-panel { min-width: 15rem; padding: 0.3rem 0; }
|
|
1911
|
+
.ir-menu { list-style: none; margin: 0; padding: 0; }
|
|
1912
|
+
.ir-item > summary, .ir-link { display: flex; align-items: center; gap: 0.55rem; width: 100%; padding: 0.45rem 0.9rem; cursor: pointer; list-style: none; color: var(--text); text-decoration: none; background: none; border: 0; font: inherit; text-align: left; }
|
|
1913
|
+
.ir-item > summary::-webkit-details-marker { display: none; }
|
|
1914
|
+
.ir-item > summary:hover, .ir-link:hover, .ir-item[open] > summary { background: var(--surface-3); }
|
|
1915
|
+
.ir-item > summary .icon, .ir-link .icon { color: var(--muted); }
|
|
1916
|
+
.ir-more { margin-left: auto; color: var(--muted); }
|
|
1917
|
+
.ir-sub > .ir-menu { padding-left: 1.25rem; }
|
|
1918
|
+
.ir-body { padding: 0.5rem 0.9rem 0.75rem; display: grid; gap: 0.5rem; }
|
|
1919
|
+
.ir-body .menu-section { padding: 0; border: 0; }
|
|
1920
|
+
.ir-columns { border: 0; margin: 0; padding: 0; display: grid; gap: 0.2rem; max-height: 50vh; overflow: auto; }
|
|
1921
|
+
.ir-columns legend { font-weight: 600; margin-bottom: 0.3rem; }
|
|
1922
|
+
.ir-dialog { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); padding: 0; width: min(34rem, calc(100vw - 2rem)); box-shadow: 0 12px 32px rgb(0 0 0 / 25%); }
|
|
1923
|
+
.ir-dialog::backdrop { background: rgb(0 0 0 / 35%); }
|
|
1924
|
+
.ir-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.75rem 1rem; border-bottom: 1px solid var(--border); }
|
|
1925
|
+
.ir-dialog-head h2 { margin: 0; font-size: 1.05rem; }
|
|
1926
|
+
.ir-dialog .ir-body { padding: 1rem; }
|
|
1927
|
+
.ir-dialog .filter-row { min-width: 0; }
|
|
1928
|
+
/* the search field with its column list (APEX: the magnifier's column menu) */
|
|
1929
|
+
.search-field { display: flex; flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
|
|
1930
|
+
.search-field:focus-within { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
1931
|
+
.search-field .search-scope { border: 0; border-right: 1px solid var(--border); border-radius: var(--radius) 0 0 var(--radius); max-width: 9rem; background: var(--surface-2); }
|
|
1932
|
+
/* (sprint 79, IR-3; APEX: the column scope in the magnifier of the search field) all columns: only the magnifier;
|
|
1933
|
+
a column: the magnifier and its name */
|
|
1934
|
+
.search-scope-wrap { position: relative; display: flex; flex: none; }
|
|
1935
|
+
.search-scope-wrap > .icon { position: absolute; left: 0.6rem; top: 50%; transform: translateY(-50%); pointer-events: none; color: var(--muted); }
|
|
1936
|
+
.search-field .search-scope-wrap .search-scope { padding-left: 2rem; }
|
|
1937
|
+
.search-field .search-scope-wrap .search-scope:has(option[value=""]:checked) { width: 2.75rem; padding-right: 0.5rem; color: transparent; }
|
|
1938
|
+
.search-field .search-scope option { color: var(--text); }
|
|
1939
|
+
.search-field input[type=search] { border: 0; flex: 1; min-width: 0; background: transparent; }
|
|
1940
|
+
.search-field input[type=search]:focus { outline: none; }
|
|
1941
|
+
/* a column heading's menu */
|
|
1942
|
+
.th-menu { z-index: 60; width: 17rem; padding: 0.4rem 0; display: grid; gap: 0.3rem; max-height: 70vh; overflow: auto; }
|
|
1943
|
+
.th-menu-actions { display: grid; }
|
|
1944
|
+
.th-menu-actions a, .th-menu-values a { display: flex; justify-content: space-between; gap: 0.5rem; padding: 0.35rem 0.9rem; color: var(--text); text-decoration: none; }
|
|
1945
|
+
.th-menu-actions a:hover, .th-menu-values a:hover, .th-menu a:focus-visible { background: var(--surface-3); }
|
|
1946
|
+
.th-menu input[type=search] { margin: 0.2rem 0.75rem; width: calc(100% - 1.5rem); }
|
|
1947
|
+
.th-menu-values { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border); overflow-wrap: anywhere; }
|
|
1948
|
+
.th-menu-values li.muted { padding: 0.35rem 0.9rem; }
|
|
1949
|
+
.js th[data-col] > a { cursor: pointer; }
|
|
1950
|
+
|
|
1951
|
+
/* (sprint 76) a date item in the application's date format: the browser's picker on a hidden date field */
|
|
1952
|
+
.date-field { position: relative; }
|
|
1953
|
+
.date-native { position: absolute; right: 0; bottom: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; border: 0; padding: 0; }
|
|
1954
|
+
|
|
1955
|
+
/* (sprint 77) display positions: banner, breadcrumb bar, a side column, footer; button positions in a region */
|
|
1956
|
+
.t-pos-banner, .t-pos-breadcrumb { margin-bottom: 1rem; }
|
|
1957
|
+
.t-pos-breadcrumb { padding: 0.5rem 0; border-bottom: 1px solid var(--border); }
|
|
1958
|
+
.t-pos-footer { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
|
|
1959
|
+
.t-columns { display: grid; gap: 1.25rem; align-items: start; }
|
|
1960
|
+
.t-columns-left { grid-template-columns: minmax(14rem, 18rem) minmax(0, 1fr); }
|
|
1961
|
+
.t-columns-right { grid-template-columns: minmax(0, 1fr) minmax(14rem, 18rem); }
|
|
1962
|
+
.t-columns-right > .t-side { order: 2; }
|
|
1963
|
+
.t-side .t-regions, .t-side { min-width: 0; }
|
|
1964
|
+
.t-side .region { grid-column: 1 / -1; }
|
|
1965
|
+
@media (max-width: 900px) { .t-columns-left, .t-columns-right { grid-template-columns: 1fr; } .t-columns-right > .t-side { order: 0; } }
|
|
1966
|
+
.region-footer-split { display: flex; justify-content: space-between; gap: 0.5rem; flex-wrap: wrap; }
|
|
1967
|
+
.region-footer-split > div { display: flex; gap: 0.5rem; }
|