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.
Files changed (60) hide show
  1. package/db/migrations/099_layout_positions.sql +29 -0
  2. package/db/migrations/100_generated_labels.sql +381 -0
  3. package/db/migrations/101_theme_choice.sql +15 -0
  4. package/docs/apex-feature-parity.md +36 -9
  5. package/docs/guide/03-builder.md +82 -21
  6. package/docs/guide/04-pages-and-regions.md +55 -5
  7. package/docs/guide/05-items.md +1 -1
  8. package/docs/guide/09-reference.md +5 -1
  9. package/docs/guide/12-development.md +2 -1
  10. package/docs/guide/14-globalization.md +5 -1
  11. package/package.json +1 -1
  12. package/public/app.css +80 -0
  13. package/public/app.js +189 -1
  14. package/public/builder.css +112 -0
  15. package/public/builder.js +280 -3
  16. package/src/builder/appsheets.ts +53 -13
  17. package/src/builder/appwizard.ts +5 -3
  18. package/src/builder/arrange.ts +133 -17
  19. package/src/builder/components.ts +28 -22
  20. package/src/builder/designer.ts +67 -18
  21. package/src/builder/forms.ts +4 -1
  22. package/src/builder/object-browser.ts +342 -0
  23. package/src/builder/pwa.ts +3 -3
  24. package/src/builder/routes.ts +85 -26
  25. package/src/builder/shared.ts +103 -1
  26. package/src/builder/sql.ts +13 -65
  27. package/src/builder/ui.ts +21 -6
  28. package/src/i18n/ar.ts +18 -0
  29. package/src/i18n/cs.ts +18 -0
  30. package/src/i18n/da.ts +18 -0
  31. package/src/i18n/de.ts +18 -0
  32. package/src/i18n/el.ts +18 -0
  33. package/src/i18n/es.ts +18 -0
  34. package/src/i18n/fi.ts +18 -0
  35. package/src/i18n/fr.ts +18 -0
  36. package/src/i18n/he.ts +18 -0
  37. package/src/i18n/it.ts +18 -0
  38. package/src/i18n/ja.ts +18 -0
  39. package/src/i18n/ko.ts +18 -0
  40. package/src/i18n/nb.ts +18 -0
  41. package/src/i18n/pl.ts +18 -0
  42. package/src/i18n/pt.ts +18 -0
  43. package/src/i18n/ru.ts +18 -0
  44. package/src/i18n/sv.ts +18 -0
  45. package/src/i18n/tr.ts +18 -0
  46. package/src/i18n/uk.ts +18 -0
  47. package/src/i18n/zh.ts +18 -0
  48. package/src/i18n.ts +36 -0
  49. package/src/metadata.ts +5 -1
  50. package/src/runtime/account.ts +5 -5
  51. package/src/runtime/devbar.ts +16 -13
  52. package/src/runtime/engine.ts +6 -0
  53. package/src/runtime/facets.ts +34 -3
  54. package/src/runtime/format.ts +52 -0
  55. package/src/runtime/items.ts +27 -0
  56. package/src/runtime/locale.ts +7 -1
  57. package/src/runtime/regions.ts +36 -2
  58. package/src/runtime/render.ts +27 -6
  59. package/src/runtime/report.ts +141 -81
  60. package/src/runtime/routes.ts +39 -7
@@ -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. A row starts with a pencil that opens the form.
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
- rows without a value are labelled *(none)*, and bar charts show the ten largest values (the rest is
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 next to the key), booleans, text columns with few values, dates and numbers as ranges with *from*/*to* |
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
- **Regions** with their items and buttons, and page-level items and buttons;
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. Folders open and close
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
- - **Middle: the Layout**: the page's regions on the 12-column grid, each with its items and
548
- buttons, as they will be placed on the page; under it a **gallery** of region types, item types
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). Under the properties, the **Help** pane (APEX: the Help tab) shows the
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, a list of all pages, next), **Undo** / **Redo** of
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 an item or button** to another place in its region, to another region, or to *Page level*.
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 history).
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
- of icons, centred at the bottom, each with a tooltip. It isn't shown to anyone else, nor inside
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 and turns the
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**: tables, views and functions per schema. For a table you see columns, types
1160
- and defaults, **row level security policies**, **grants** and the first 25 rows; for a
1161
- function, its source.
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
- - **Sort** by clicking a column heading (again for descending), or from the Actions menu.
192
- - **Actions menu**:
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. With
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
@@ -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, object browser
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. For public applications it's kept in a cookie.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgkiln",
3
- "version": "0.42.0",
3
+ "version": "0.44.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
@@ -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; }