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
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- 099: display positions, button positions and side-column page templates
|
|
3
|
+
-- (sprint 77; APEX: a region's Layout → Position, a button's Layout →
|
|
4
|
+
-- Button Position, the Left / Right Side Column page templates)
|
|
5
|
+
--
|
|
6
|
+
-- meta.region.position: where the region shows on the page: banner (above
|
|
7
|
+
-- everything), breadcrumb (the bar under the title), left or right (the side
|
|
8
|
+
-- column of a side-column page template; on other pages in the body, in
|
|
9
|
+
-- sequence), body (the default) or footer (after the body). Null is body.
|
|
10
|
+
-- meta.button.slot: where a region's button shows: create, edit, change,
|
|
11
|
+
-- copy, help or up (the region's top bar), previous, close or delete (the
|
|
12
|
+
-- bottom bar, on the left), next (the bottom bar, on the right) or region
|
|
13
|
+
-- (with the region's other buttons, as before). Null is region.
|
|
14
|
+
-- meta.page.page_template: left_side_column and right_side_column too.
|
|
15
|
+
--
|
|
16
|
+
-- The columns are nullable (older exports and imports leave them null) and
|
|
17
|
+
-- travel with an application's export like its other columns.
|
|
18
|
+
-- =====================================================================
|
|
19
|
+
alter table meta.region add column position text
|
|
20
|
+
check (position in ('banner', 'breadcrumb', 'left', 'body', 'right', 'footer'));
|
|
21
|
+
comment on column meta.region.position is 'Where the region shows (099): banner, breadcrumb, left, body (null), right or footer.';
|
|
22
|
+
|
|
23
|
+
alter table meta.button add column slot text
|
|
24
|
+
check (slot in ('create', 'edit', 'change', 'copy', 'help', 'up', 'previous', 'close', 'delete', 'next', 'region'));
|
|
25
|
+
comment on column meta.button.slot is 'Where a region''s button shows (099): the top bar (create, edit, change, copy, help, up), the bottom bar (previous, close, delete; next on the right) or with the other buttons (region, null).';
|
|
26
|
+
|
|
27
|
+
alter table meta.page drop constraint page_page_template_check;
|
|
28
|
+
alter table meta.page add constraint page_page_template_check
|
|
29
|
+
check (page_template in ('standard', 'minimal', 'left_side_column', 'right_side_column'));
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- 100: generated reports and grids read the same (sprint 78; parity
|
|
3
|
+
-- handoff GEN-2, GEN-1, GEN-7)
|
|
4
|
+
--
|
|
5
|
+
-- - A faceted search page's report shows one column per foreign key: the
|
|
6
|
+
-- parent's display value (Manager → KING) under the key's label. The key
|
|
7
|
+
-- itself is hidden (config.hidden: not shown, not in Actions › Columns,
|
|
8
|
+
-- still in the query for filters and links). Before, both showed, so the
|
|
9
|
+
-- report had two "Manager" and two "Department" headings.
|
|
10
|
+
-- - Interactive grids (the grid page, both grids of a master-detail page)
|
|
11
|
+
-- get headings from meta.wizard_column_label (Deptno → Department Number)
|
|
12
|
+
-- and the number format masks of meta.wizard_mask, like the reports.
|
|
13
|
+
-- - The faceted search report and a map's list report get the format masks
|
|
14
|
+
-- too, so a salary reads 2,850.00 in the report, the grid and the form.
|
|
15
|
+
-- - A faceted search report's rows start with a pencil that opens the form
|
|
16
|
+
-- (link.icon), like a report and form page; the key is plain text.
|
|
17
|
+
--
|
|
18
|
+
-- meta.generate_page is 097's with those changes. Pages generated before
|
|
19
|
+
-- keep their configuration.
|
|
20
|
+
-- =====================================================================
|
|
21
|
+
|
|
22
|
+
-- a grid's headings and number formats: {"headings": {...}, "formats": {...}}
|
|
23
|
+
create or replace function meta.wizard_grid_labels(p_table regclass) returns jsonb
|
|
24
|
+
language sql stable as $$
|
|
25
|
+
select jsonb_build_object(
|
|
26
|
+
'headings', coalesce(jsonb_object_agg(column_name, meta.wizard_column_label(p_table, column_name)), '{}'),
|
|
27
|
+
'formats', coalesce(jsonb_object_agg(column_name, meta.wizard_mask(type_sql, kind, is_pk or fk_table is not null))
|
|
28
|
+
filter (where meta.wizard_mask(type_sql, kind, is_pk or fk_table is not null) is not null), '{}'))
|
|
29
|
+
from meta.wizard_catalog(p_table)
|
|
30
|
+
where kind not in ('binary', 'geometry')
|
|
31
|
+
$$;
|
|
32
|
+
|
|
33
|
+
create or replace function meta.generate_page(
|
|
34
|
+
p_app text,
|
|
35
|
+
p_kind text,
|
|
36
|
+
p_table regclass,
|
|
37
|
+
p_page int,
|
|
38
|
+
p_options jsonb default '{}'
|
|
39
|
+
) returns int
|
|
40
|
+
language plpgsql as $$
|
|
41
|
+
declare
|
|
42
|
+
v_app meta.app;
|
|
43
|
+
o jsonb;
|
|
44
|
+
v_label text;
|
|
45
|
+
v_flabel text;
|
|
46
|
+
v_icon text;
|
|
47
|
+
v_pk text := meta.wizard_pk(p_table);
|
|
48
|
+
v_page int;
|
|
49
|
+
v_region int;
|
|
50
|
+
v_report int;
|
|
51
|
+
v_form int;
|
|
52
|
+
v_fpage int;
|
|
53
|
+
v_link jsonb;
|
|
54
|
+
v_cols text;
|
|
55
|
+
v_heads jsonb := '{}';
|
|
56
|
+
v_src text;
|
|
57
|
+
v_cfg jsonb;
|
|
58
|
+
v_a text;
|
|
59
|
+
v_b text;
|
|
60
|
+
v_c text;
|
|
61
|
+
v_d text;
|
|
62
|
+
v_kind text;
|
|
63
|
+
v_detail regclass;
|
|
64
|
+
v_dpk text;
|
|
65
|
+
v_item text;
|
|
66
|
+
v_facets jsonb := '[]';
|
|
67
|
+
v_hidden jsonb := '[]';
|
|
68
|
+
v_fmts jsonb := '{}';
|
|
69
|
+
v_mask text;
|
|
70
|
+
v_geo text;
|
|
71
|
+
v_key text;
|
|
72
|
+
v_skip text[] := meta.wizard_sidecars(p_table);
|
|
73
|
+
c record;
|
|
74
|
+
begin
|
|
75
|
+
select * into v_app from meta.app where alias = p_app;
|
|
76
|
+
if v_app.id is null then
|
|
77
|
+
raise exception 'application "%" does not exist', p_app;
|
|
78
|
+
end if;
|
|
79
|
+
if p_kind not in ('report_form', 'grid', 'form', 'cards', 'calendar', 'chart', 'map', 'facets', 'master_detail') then
|
|
80
|
+
raise exception 'unknown page type "%"', p_kind;
|
|
81
|
+
end if;
|
|
82
|
+
-- the application's own data: not pgkiln's or the system's tables
|
|
83
|
+
if (select n.nspname ~ '^pg_' or n.nspname in ('information_schema', 'meta')
|
|
84
|
+
from pg_class rel join pg_namespace n on n.oid = rel.relnamespace where rel.oid = p_table) then
|
|
85
|
+
raise exception 'pages can''t be generated on %', p_table;
|
|
86
|
+
end if;
|
|
87
|
+
if (select relkind from pg_class where oid = p_table) not in ('r', 'p', 'v', 'm') then
|
|
88
|
+
raise exception '% is not a table or view', p_table;
|
|
89
|
+
end if;
|
|
90
|
+
if p_options is null or jsonb_typeof(p_options) <> 'object' then
|
|
91
|
+
p_options := '{}';
|
|
92
|
+
end if;
|
|
93
|
+
-- an option given as JSON null or '' means "none"; a missing one takes the default
|
|
94
|
+
o := meta.wizard_defaults(p_kind, p_table) || p_options;
|
|
95
|
+
v_label := coalesce(nullif(btrim(o ->> 'label'), ''), meta.wizard_table_label(p_table, p_kind <> 'form'));
|
|
96
|
+
-- (097) a form page of a listing is titled with the singular: Employees → Employee
|
|
97
|
+
v_flabel := coalesce(nullif(btrim(o ->> 'form_label'), ''), meta.wizard_table_label(p_table, false));
|
|
98
|
+
v_icon := nullif(o ->> 'icon', '');
|
|
99
|
+
v_fpage := nullif(o ->> 'form_page', '')::int;
|
|
100
|
+
if v_fpage = p_page then
|
|
101
|
+
raise exception 'the form page needs a page number of its own';
|
|
102
|
+
end if;
|
|
103
|
+
|
|
104
|
+
if p_kind = 'report_form' then
|
|
105
|
+
v_page := meta.wizard_report_form(v_app, p_table, p_page, v_fpage, v_label, v_flabel);
|
|
106
|
+
elsif p_kind = 'grid' then
|
|
107
|
+
perform meta.generate_grid(p_app, p_table, p_page, v_label, coalesce(v_icon, 'grid'));
|
|
108
|
+
v_page := (select id from meta.page where app_id = v_app.id and page_no = p_page);
|
|
109
|
+
-- (100) the grid's headings and number formats, like the report's
|
|
110
|
+
update meta.region set config = config || meta.wizard_grid_labels(p_table) where page_id = v_page and type = 'grid';
|
|
111
|
+
return v_page;
|
|
112
|
+
elsif p_kind = 'form' then
|
|
113
|
+
v_page := meta.wizard_form(v_app, p_table, p_page, v_label, nullif(o ->> 'return_page', '')::int, o ->> 'mode' = 'modal',
|
|
114
|
+
case when jsonb_typeof(o -> 'columns') = 'array'
|
|
115
|
+
then (select array_agg(meta.wizard_col(p_table, x, 'form column')) from jsonb_array_elements_text(o -> 'columns') x) end);
|
|
116
|
+
elsif p_kind = 'master_detail' then
|
|
117
|
+
if v_pk is null then
|
|
118
|
+
raise exception 'the master table % needs a single-column primary key', p_table;
|
|
119
|
+
end if;
|
|
120
|
+
if nullif(o ->> 'detail', '') is null then
|
|
121
|
+
raise exception 'no detail table: % has no table with a foreign key to it', p_table;
|
|
122
|
+
end if;
|
|
123
|
+
v_detail := (o ->> 'detail')::regclass;
|
|
124
|
+
v_dpk := meta.wizard_pk(v_detail);
|
|
125
|
+
if v_dpk is null then
|
|
126
|
+
raise exception 'the detail table % needs a single-column primary key', v_detail;
|
|
127
|
+
end if;
|
|
128
|
+
v_a := meta.wizard_col(v_detail, o ->> 'detail_column', 'detail column');
|
|
129
|
+
if v_a is null then
|
|
130
|
+
raise exception 'choose the detail column that refers to the master row';
|
|
131
|
+
end if;
|
|
132
|
+
v_item := meta.wizard_item(p_page, v_pk);
|
|
133
|
+
v_page := meta.wizard_new_page(v_app, p_page, v_label, v_app.home_page);
|
|
134
|
+
insert into meta.region (page_id, seq, title, type, columns, source, table_name, pk_column, config)
|
|
135
|
+
values (v_page, 10, meta.wizard_table_label(p_table), 'grid', 12,
|
|
136
|
+
format(E'select %s\n from %s', (select string_agg(quote_ident(column_name), ', ' order by ordinal)
|
|
137
|
+
from meta.wizard_catalog(p_table) where kind <> 'binary' and not (column_name = any (v_skip))),
|
|
138
|
+
meta.wizard_qname(p_table)),
|
|
139
|
+
meta.wizard_qname(p_table), v_pk,
|
|
140
|
+
jsonb_build_object('page_size', 10, 'columns', meta.wizard_grid_columns(p_table),
|
|
141
|
+
'select_row', jsonb_build_object('column', v_pk, 'item', v_item))
|
|
142
|
+
|| meta.wizard_grid_labels(p_table))
|
|
143
|
+
returning id into v_region;
|
|
144
|
+
insert into meta.item (page_id, region_id, seq, name, label, type)
|
|
145
|
+
values (v_page, v_region, 10, v_item, meta.wizard_column_label(p_table, v_pk), 'hidden');
|
|
146
|
+
insert into meta.region (page_id, seq, title, type, columns, source, table_name, pk_column, config)
|
|
147
|
+
values (v_page, 20, meta.wizard_table_label(v_detail), 'grid', 12,
|
|
148
|
+
format(E'select %s\n from %s\n where %I = :%s::%s',
|
|
149
|
+
(select string_agg(quote_ident(column_name), ', ' order by ordinal)
|
|
150
|
+
from meta.wizard_catalog(v_detail) where kind <> 'binary' and column_name <> v_a
|
|
151
|
+
and not (column_name = any (meta.wizard_sidecars(v_detail)))),
|
|
152
|
+
meta.wizard_qname(v_detail), v_a, v_item, (select type_sql from meta.wizard_catalog(p_table) where column_name = v_pk)),
|
|
153
|
+
meta.wizard_qname(v_detail), v_dpk,
|
|
154
|
+
jsonb_build_object('page_size', 10, 'columns', meta.wizard_grid_columns(v_detail, v_a),
|
|
155
|
+
'master', jsonb_build_object('item', v_item, 'column', v_a))
|
|
156
|
+
|| meta.wizard_grid_labels(v_detail))
|
|
157
|
+
returning id into v_report;
|
|
158
|
+
insert into meta.process (page_id, seq, name, type, region_id) values
|
|
159
|
+
(v_page, 10, 'Save ' || meta.wizard_table_label(p_table), 'grid_dml', v_region),
|
|
160
|
+
(v_page, 20, 'Save ' || meta.wizard_table_label(v_detail), 'grid_dml', v_report);
|
|
161
|
+
else
|
|
162
|
+
-- the listing kinds, with an optional modal form page for a row
|
|
163
|
+
if v_fpage is not null and v_pk is null then
|
|
164
|
+
raise exception 'a form page needs a table with a single-column primary key (% has none)', p_table;
|
|
165
|
+
end if;
|
|
166
|
+
v_page := meta.wizard_new_page(v_app, p_page, v_label, v_app.home_page);
|
|
167
|
+
v_key := case when v_pk is not null then format('t.%I', v_pk) end;
|
|
168
|
+
if v_fpage is not null then
|
|
169
|
+
v_link := jsonb_build_object('page', v_fpage, 'items', jsonb_build_object(meta.wizard_item(v_fpage, v_pk), '#' || v_pk || '#'));
|
|
170
|
+
end if;
|
|
171
|
+
|
|
172
|
+
if p_kind = 'cards' then
|
|
173
|
+
v_a := meta.wizard_col(p_table, o ->> 'title', 'title column');
|
|
174
|
+
v_b := meta.wizard_col(p_table, o ->> 'subtitle', 'subtitle column');
|
|
175
|
+
v_c := meta.wizard_col(p_table, o ->> 'body', 'body column');
|
|
176
|
+
v_d := meta.wizard_col(p_table, o ->> 'badge', 'badge column');
|
|
177
|
+
if v_a is null then
|
|
178
|
+
raise exception 'choose the column for the card titles';
|
|
179
|
+
end if;
|
|
180
|
+
v_src := concat_ws(E',\n ',
|
|
181
|
+
meta.wizard_expr(p_table, v_a) || ' as title',
|
|
182
|
+
meta.wizard_expr(p_table, v_b) || ' as subtitle',
|
|
183
|
+
meta.wizard_expr(p_table, v_c) || ' as body',
|
|
184
|
+
meta.wizard_expr(p_table, v_d) || ' as badge',
|
|
185
|
+
v_key);
|
|
186
|
+
insert into meta.region (page_id, seq, title, type, source, config)
|
|
187
|
+
values (v_page, 10, v_label, 'cards', format(E'select %s\n from %s t\n order by 1', v_src, meta.wizard_qname(p_table)),
|
|
188
|
+
jsonb_strip_nulls(jsonb_build_object('link', v_link)))
|
|
189
|
+
returning id into v_region;
|
|
190
|
+
|
|
191
|
+
elsif p_kind = 'calendar' then
|
|
192
|
+
v_a := meta.wizard_col(p_table, o ->> 'start', 'start column');
|
|
193
|
+
v_b := meta.wizard_col(p_table, o ->> 'end', 'end column');
|
|
194
|
+
v_c := meta.wizard_col(p_table, o ->> 'title', 'title column');
|
|
195
|
+
if v_a is null or (select kind from meta.wizard_catalog(p_table) where column_name = v_a) not in ('date', 'timestamp') then
|
|
196
|
+
raise exception 'a calendar needs a date or timestamp start column';
|
|
197
|
+
end if;
|
|
198
|
+
if v_b is not null and (select kind from meta.wizard_catalog(p_table) where column_name = v_b) not in ('date', 'timestamp') then
|
|
199
|
+
raise exception 'the end column must be a date or timestamp';
|
|
200
|
+
end if;
|
|
201
|
+
v_src := concat_ws(E',\n ',
|
|
202
|
+
format('t.%I as start_date', v_a),
|
|
203
|
+
case when v_b is not null then format('t.%I as end_date', v_b) end,
|
|
204
|
+
coalesce(meta.wizard_expr(p_table, v_c), quote_literal(v_label)) || ' as title',
|
|
205
|
+
v_key);
|
|
206
|
+
v_cfg := jsonb_strip_nulls(jsonb_build_object('link', v_link, 'key', v_pk));
|
|
207
|
+
if v_fpage is not null then
|
|
208
|
+
v_cfg := v_cfg || jsonb_build_object('create', jsonb_build_object('page', v_fpage, 'items',
|
|
209
|
+
jsonb_strip_nulls(jsonb_build_object(meta.wizard_item(v_fpage, v_a), '#start#')
|
|
210
|
+
|| case when v_b is not null then jsonb_build_object(meta.wizard_item(v_fpage, v_b), '#end#') else '{}' end)));
|
|
211
|
+
end if;
|
|
212
|
+
if coalesce((o ->> 'drag')::boolean, false) then
|
|
213
|
+
if v_pk is null then
|
|
214
|
+
raise exception 'drag and drop needs a table with a single-column primary key (% has none)', p_table;
|
|
215
|
+
end if;
|
|
216
|
+
v_cfg := v_cfg || jsonb_build_object('move', format('update %s set %I = :NEW_START::%s%s where %I = :EVENT_ID::%s',
|
|
217
|
+
meta.wizard_qname(p_table), v_a, (select type_sql from meta.wizard_catalog(p_table) where column_name = v_a),
|
|
218
|
+
case when v_b is not null then format(', %I = :NEW_END::%s', v_b, (select type_sql from meta.wizard_catalog(p_table) where column_name = v_b)) else '' end,
|
|
219
|
+
v_pk, (select type_sql from meta.wizard_catalog(p_table) where column_name = v_pk)));
|
|
220
|
+
end if;
|
|
221
|
+
insert into meta.region (page_id, seq, title, type, source, config)
|
|
222
|
+
values (v_page, 10, v_label, 'calendar', format(E'select %s\n from %s t', v_src, meta.wizard_qname(p_table)), v_cfg)
|
|
223
|
+
returning id into v_region;
|
|
224
|
+
|
|
225
|
+
elsif p_kind = 'chart' then
|
|
226
|
+
v_a := meta.wizard_col(p_table, o ->> 'label_column', 'label column');
|
|
227
|
+
v_b := meta.wizard_col(p_table, o ->> 'value_column', 'value column');
|
|
228
|
+
v_kind := coalesce(nullif(o ->> 'chart', ''), 'bar');
|
|
229
|
+
v_c := lower(coalesce(nullif(o ->> 'function', ''), 'count'));
|
|
230
|
+
if v_a is null then
|
|
231
|
+
raise exception 'choose the label column of the chart';
|
|
232
|
+
end if;
|
|
233
|
+
if v_kind not in ('bar', 'column', 'line', 'area', 'donut', 'pie', 'funnel') then
|
|
234
|
+
raise exception 'unknown chart type "%"', v_kind;
|
|
235
|
+
end if;
|
|
236
|
+
if v_c not in ('count', 'sum', 'avg', 'min', 'max') then
|
|
237
|
+
raise exception 'unknown function "%"', v_c;
|
|
238
|
+
end if;
|
|
239
|
+
if v_c <> 'count' and (v_b is null or (select kind from meta.wizard_catalog(p_table) where column_name = v_b) <> 'number') then
|
|
240
|
+
raise exception 'the function % needs a number column', v_c;
|
|
241
|
+
end if;
|
|
242
|
+
v_d := case when v_c = 'count' and v_b is null then 'Count'
|
|
243
|
+
else initcap(case v_c when 'avg' then 'average' when 'min' then 'minimum' when 'max' then 'maximum' else v_c end)
|
|
244
|
+
|| ' of ' || meta.wizard_column_label(p_table, v_b) end;
|
|
245
|
+
-- the label as a derived column, so a foreign key's display value can be grouped;
|
|
246
|
+
-- (097) rows without a value are labelled "(none)" instead of an empty bar
|
|
247
|
+
v_src := meta.wizard_expr(p_table, v_a);
|
|
248
|
+
if exists (select 1 from meta.wizard_catalog(p_table) where column_name = v_a and (kind = 'text' or fk_table is not null) and not (not_null and fk_table is null)) then
|
|
249
|
+
v_src := format('coalesce((%s)::text, %L)', v_src, '(none)');
|
|
250
|
+
end if;
|
|
251
|
+
insert into meta.region (page_id, seq, title, type, source, config)
|
|
252
|
+
values (v_page, 10, v_label, 'chart',
|
|
253
|
+
format(E'select t.%I,\n %s as %I\n from (select %s as %I%s from %s t) t\n group by 1\n order by %s',
|
|
254
|
+
meta.wizard_column_label(p_table, v_a),
|
|
255
|
+
case when v_b is null then 'count(*)' else format('%s(t.%I)', v_c, v_b) end, v_d,
|
|
256
|
+
v_src, meta.wizard_column_label(p_table, v_a),
|
|
257
|
+
case when v_b is null then '' else format(', t.%I', v_b) end,
|
|
258
|
+
meta.wizard_qname(p_table), case when v_kind in ('bar', 'donut', 'pie', 'funnel') then '2 desc' else '1' end),
|
|
259
|
+
jsonb_build_object('kind', v_kind) || case when v_kind in ('bar', 'donut', 'pie', 'funnel') then '{"top": 10}'::jsonb else '{}' end)
|
|
260
|
+
returning id into v_region;
|
|
261
|
+
|
|
262
|
+
elsif p_kind = 'map' then
|
|
263
|
+
v_a := meta.wizard_col(p_table, o ->> 'lat', 'latitude column');
|
|
264
|
+
v_b := meta.wizard_col(p_table, o ->> 'lng', 'longitude column');
|
|
265
|
+
v_c := meta.wizard_col(p_table, o ->> 'location', 'location column');
|
|
266
|
+
if v_c is not null then
|
|
267
|
+
v_kind := (select kind from meta.wizard_catalog(p_table) where column_name = v_c);
|
|
268
|
+
v_src := case v_kind
|
|
269
|
+
when 'geometry' then format('st_y(st_pointonsurface(t.%1$I::geometry)) as lat, st_x(st_pointonsurface(t.%1$I::geometry)) as lng', v_c)
|
|
270
|
+
when 'point' then format('t.%1$I[1] as lat, t.%1$I[0] as lng', v_c)
|
|
271
|
+
when 'text' then format('t.%I as location', v_c)
|
|
272
|
+
else null end;
|
|
273
|
+
-- lines and areas are drawn as shapes too
|
|
274
|
+
if v_kind = 'geometry' then
|
|
275
|
+
v_geo := format('case when geometrytype(t.%1$I::geometry) <> ''POINT'' then st_asgeojson(t.%1$I::geometry) end as geojson', v_c);
|
|
276
|
+
end if;
|
|
277
|
+
if v_src is null then
|
|
278
|
+
raise exception 'the location column must hold "latitude,longitude" text, a point or a PostGIS geometry';
|
|
279
|
+
end if;
|
|
280
|
+
v_d := format('t.%I is not null', v_c);
|
|
281
|
+
elsif v_a is not null and v_b is not null then
|
|
282
|
+
if (select count(*) from meta.wizard_catalog(p_table) where column_name in (v_a, v_b) and kind = 'number') <> 2 then
|
|
283
|
+
raise exception 'latitude and longitude must be number columns';
|
|
284
|
+
end if;
|
|
285
|
+
v_src := format('t.%I as lat, t.%I as lng', v_a, v_b);
|
|
286
|
+
v_d := format('t.%I is not null and t.%I is not null', v_a, v_b);
|
|
287
|
+
else
|
|
288
|
+
raise exception 'a map needs latitude and longitude columns, or a location, point or geometry column';
|
|
289
|
+
end if;
|
|
290
|
+
v_cols := concat_ws(E',\n ', v_src, v_geo,
|
|
291
|
+
meta.wizard_expr(p_table, meta.wizard_col(p_table, o ->> 'title', 'title column')) || ' as title',
|
|
292
|
+
meta.wizard_expr(p_table, meta.wizard_col(p_table, o ->> 'body', 'body column')) || ' as body',
|
|
293
|
+
v_key);
|
|
294
|
+
insert into meta.region (page_id, seq, title, type, source, config)
|
|
295
|
+
values (v_page, 10, v_label, 'map', format(E'select %s\n from %s t\n where %s', v_cols, meta.wizard_qname(p_table), v_d),
|
|
296
|
+
jsonb_strip_nulls(jsonb_build_object('link', v_link)))
|
|
297
|
+
returning id into v_region;
|
|
298
|
+
if coalesce((o ->> 'report')::boolean, true) then
|
|
299
|
+
-- a report of the same rows, filtered by the map area ("Show this area in the list")
|
|
300
|
+
insert into meta.region (page_id, seq, title, type, source, config)
|
|
301
|
+
values (v_page, 20, v_label || ' list', 'report',
|
|
302
|
+
format(E'select %s,\n %s\n from %s t',
|
|
303
|
+
(select string_agg(meta.wizard_expr(p_table, column_name) || ' as ' || quote_ident(column_name), ', ' order by ordinal)
|
|
304
|
+
from meta.wizard_catalog(p_table)
|
|
305
|
+
where kind not in ('binary', 'geometry', 'point') and column_name not in ('lat', 'lng', 'location')
|
|
306
|
+
and not (column_name = any (v_skip))),
|
|
307
|
+
v_src, meta.wizard_qname(p_table)),
|
|
308
|
+
jsonb_strip_nulls(jsonb_build_object('link', v_link || jsonb_build_object('column', v_pk),
|
|
309
|
+
'headings', (select jsonb_object_agg(column_name, meta.wizard_column_label(p_table, column_name)) from meta.wizard_catalog(p_table)),
|
|
310
|
+
'formats', nullif(meta.wizard_grid_labels(p_table) -> 'formats', '{}'))))
|
|
311
|
+
returning id into v_report;
|
|
312
|
+
update meta.region set config = config || jsonb_build_object('report', v_report) where id = v_region;
|
|
313
|
+
end if;
|
|
314
|
+
|
|
315
|
+
elsif p_kind = 'facets' then
|
|
316
|
+
perform meta.wizard_col(p_table, x, 'report column') from jsonb_array_elements_text(coalesce(o -> 'columns', '[]')) x;
|
|
317
|
+
perform meta.wizard_col(p_table, x, 'facet column') from jsonb_array_elements_text(coalesce(o -> 'facets', '[]')) x;
|
|
318
|
+
-- the report: the chosen columns, and the parent's display column next to each foreign key
|
|
319
|
+
v_cols := null;
|
|
320
|
+
for c in
|
|
321
|
+
select w.* from meta.wizard_catalog(p_table) w
|
|
322
|
+
where w.column_name in (select x from jsonb_array_elements_text(coalesce(o -> 'columns', '[]')) x)
|
|
323
|
+
or w.is_pk
|
|
324
|
+
or w.column_name in (select x from jsonb_array_elements_text(coalesce(o -> 'facets', '[]')) x)
|
|
325
|
+
order by w.ordinal
|
|
326
|
+
loop
|
|
327
|
+
continue when c.kind in ('binary', 'geometry');
|
|
328
|
+
v_cols := concat_ws(E',\n ', v_cols, format('t.%I', c.column_name));
|
|
329
|
+
if c.fk_display is not null and c.fk_display <> c.fk_column and not c.is_pk then
|
|
330
|
+
-- (100) one column per foreign key: the parent's display value; the key itself is hidden (still filterable)
|
|
331
|
+
v_cols := concat_ws(E',\n ', v_cols, meta.wizard_expr(p_table, c.column_name) || ' as ' || quote_ident(c.column_name || '_' || c.fk_display));
|
|
332
|
+
v_heads := v_heads || jsonb_build_object(c.column_name || '_' || c.fk_display, meta.wizard_column_label(p_table, c.column_name));
|
|
333
|
+
v_hidden := v_hidden || to_jsonb(c.column_name);
|
|
334
|
+
else
|
|
335
|
+
v_heads := v_heads || jsonb_build_object(c.column_name, meta.wizard_column_label(p_table, c.column_name));
|
|
336
|
+
v_mask := meta.wizard_mask(c.type_sql, c.kind, c.is_pk or c.fk_table is not null);
|
|
337
|
+
if v_mask is not null then
|
|
338
|
+
v_fmts := v_fmts || jsonb_build_object(c.column_name, v_mask);
|
|
339
|
+
end if;
|
|
340
|
+
end if;
|
|
341
|
+
end loop;
|
|
342
|
+
if v_cols is null then
|
|
343
|
+
raise exception 'choose at least one report column';
|
|
344
|
+
end if;
|
|
345
|
+
for c in
|
|
346
|
+
select w.* from jsonb_array_elements_text(coalesce(o -> 'facets', '[]')) with ordinality x(col, n)
|
|
347
|
+
join meta.wizard_catalog(p_table) w on w.column_name = x.col
|
|
348
|
+
order by x.n
|
|
349
|
+
loop
|
|
350
|
+
continue when c.kind in ('binary', 'geometry', 'point', 'other');
|
|
351
|
+
v_facets := v_facets || jsonb_build_array(jsonb_strip_nulls(jsonb_build_object(
|
|
352
|
+
'column', case when c.fk_display is not null and c.fk_display <> c.fk_column then c.column_name || '_' || c.fk_display else c.column_name end,
|
|
353
|
+
'label', meta.wizard_column_label(p_table, c.column_name),
|
|
354
|
+
'type', case when c.kind in ('number', 'date', 'timestamp') and c.fk_table is null then 'range' end,
|
|
355
|
+
'custom', case when c.kind in ('number', 'date', 'timestamp') and c.fk_table is null then true end)));
|
|
356
|
+
end loop;
|
|
357
|
+
insert into meta.region (page_id, seq, title, type, columns, source, config)
|
|
358
|
+
values (v_page, 20, v_label, 'report', 9, format(E'select %s\n from %s t', v_cols, meta.wizard_qname(p_table)),
|
|
359
|
+
jsonb_strip_nulls(jsonb_build_object('link', v_link || jsonb_build_object('column', v_pk, 'icon', true), 'headings', v_heads,
|
|
360
|
+
'hidden', nullif(v_hidden, '[]'), 'formats', nullif(v_fmts, '{}'))))
|
|
361
|
+
returning id into v_region;
|
|
362
|
+
insert into meta.region (page_id, seq, title, type, columns, template, config)
|
|
363
|
+
values (v_page, 10, 'Filters', 'facets', 3, 'collapsible',
|
|
364
|
+
jsonb_build_object('report', v_region, 'search', coalesce((o ->> 'search')::boolean, true), 'facets', v_facets));
|
|
365
|
+
end if;
|
|
366
|
+
|
|
367
|
+
if v_fpage is not null then
|
|
368
|
+
perform meta.wizard_form(v_app, p_table, v_fpage, v_flabel, p_page, true, null);
|
|
369
|
+
insert into meta.button (page_id, region_id, seq, name, label, action, target_page, hot)
|
|
370
|
+
values (v_page, v_region, 10, 'CREATE', 'Create', 'redirect', v_fpage, true);
|
|
371
|
+
end if;
|
|
372
|
+
end if;
|
|
373
|
+
|
|
374
|
+
if coalesce((o ->> 'nav')::boolean, false) then
|
|
375
|
+
perform meta.wizard_nav(v_app, v_label, v_icon, p_page);
|
|
376
|
+
end if;
|
|
377
|
+
return v_page;
|
|
378
|
+
end
|
|
379
|
+
$$;
|
|
380
|
+
|
|
381
|
+
revoke all on function meta.wizard_grid_labels(regclass) from public;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- 101: an application opens in its own light or dark mode until the user
|
|
3
|
+
-- chooses (sprint 79; parity handoff UI-2)
|
|
4
|
+
--
|
|
5
|
+
-- meta.account.theme_pref was 'auto' unless the user chose: at sign-in that
|
|
6
|
+
-- choice replaced the application's mode, so an Iris application (light)
|
|
7
|
+
-- followed the operating system's dark mode for every signed-in user. Null
|
|
8
|
+
-- now means "no choice": the application's mode (meta.app.theme.mode).
|
|
9
|
+
-- The 'auto' that every account had is cleared; a user who chose
|
|
10
|
+
-- Automatic chooses it again from the Appearance menu.
|
|
11
|
+
-- =====================================================================
|
|
12
|
+
alter table meta.account alter column theme_pref drop not null;
|
|
13
|
+
alter table meta.account alter column theme_pref set default null;
|
|
14
|
+
update meta.account set theme_pref = null where theme_pref = 'auto';
|
|
15
|
+
comment on column meta.account.theme_pref is 'The user''s light/dark choice (auto, light, dark); null: the application''s mode (101).';
|
|
@@ -7,7 +7,7 @@ open item and open an issue or pull request; see [CONTRIBUTING.md](../CONTRIBUTI
|
|
|
7
7
|
Legend: ✅ available · 🟡 partial (see notes) · ❌ not yet · ➖ not planned (a deliberate choice,
|
|
8
8
|
or better served by the PostgreSQL ecosystem; see the notes and [extensions](guide/15-extensions.md))
|
|
9
9
|
|
|
10
|
-
Last reviewed: 2026-10-14 (sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
|
|
10
|
+
Last reviewed: 2026-10-14 (sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
|
|
11
11
|
|
|
12
12
|
## At a glance
|
|
13
13
|
|
|
@@ -38,8 +38,8 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
38
38
|
| App Builder: create, edit, delete, run apps | ✅ | Builder at `/builder` |
|
|
39
39
|
| Create application wizard | ✅ | Blank app with its own database role and schema, started from a **boilerplate application** if wanted; **from a file**: CSV/TSV/XLSX/JSON/XML, where an Excel workbook with several sheets (or JSON with several arrays) becomes several tables, with a preview to include or leave out each sheet, edit table/column names, types and primary keys, and **foreign keys proposed** from matching columns; **from pasted data** (CSV/TSV text); **from existing tables** (pick the tables and views of a schema). Each gives a report and form per table, navigation and an optional dashboard (a chart per table), plus an optional faceted search for a single table, all created in one transaction. (sprint 73) **One page like APEX's**: name, icon and description, appearance (theme style, side or top menu, accent), a **page type per table** (interactive report with form, faceted search, cards, calendar, master detail, interactive grid, report, none; large tables proposed as a grid), **features** (About page, access control roles, activity reporting, feedback, theme style selection, PWA, push), settings (alias, authentication, first user, language) and a boilerplate under Advanced; a progress message, then straight to the new application. (sprint 71) The generated pages read like APEX's: human labels (abbreviations, run-together words, column and table comments), plural page and menu names with singular form titles, foreign keys shown by the parent's name in reports, `bytea` columns as one file item with their name/mime/size/updated columns, number format masks, a pencil per report row, the Dashboard after Home with *(none)* and top-N charts, and a Home page with a hero and a card per page. **Missing:** blueprints (26.1) |
|
|
40
40
|
| Create page wizards | ✅ | Report and form, interactive grid, form, cards, calendar, chart, map, faceted search and master-detail (stacked grids) from any table or view, with defaults from the catalog (columns, key, dates, positions, foreign keys), an optional modal form page and a navigation entry; also from SQL (`meta.generate_page`). No side-by-side or drill-down master-detail, no wizard for smart filters or trees |
|
|
41
|
-
| Page Designer | ✅ | IDE-style window (dark or light): component tree, a layout canvas with drag and drop (with keyboard and button alternatives) and a gallery of regions, items and buttons, a filterable property editor; undo/redo; panes become tabs on phones. Settings forms for report, grid, chart, cards, calendar, faceted search, smart filters, display selector, map, tree and template component regions. A code editor for SQL, PL/pgSQL, JSON and HTML with highlighting and autocomplete of tables, columns and `:ITEM` binds (no extra libraries). Drag and drop needs a mouse; on touch screens the Arrange buttons move components |
|
|
42
|
-
| Shared components | ✅ | Navigation menu, **lists** (static entries with nesting, badges, conditions, authorization and build options, or a query; for list regions, the navigation menu and the navigation bar), authorization schemes, build options, lists of values, application items and processes, access control, globalization, template components and plug-ins, web credentials, REST data sources, data load definitions, supporting objects |
|
|
41
|
+
| Page Designer | ✅ | IDE-style window (dark or light): component tree, a layout canvas with drag and drop (with keyboard and button alternatives) and a gallery of regions, items and buttons, a filterable property editor; undo/redo; panes become tabs on phones. Settings forms for report, grid, chart, cards, calendar, faceted search, smart filters, display selector, map, tree and template component regions. A code editor for SQL, PL/pgSQL, JSON and HTML with highlighting and autocomplete of tables, columns and `:ITEM` binds (no extra libraries). Drag and drop needs a mouse; on touch screens the Arrange buttons move components. (sprint 77) The layout draws the page template's display positions (banner, breadcrumb bar, left/right column, body, footer) as drop zones and a region's button positions; the rendering tree groups by position and has a context menu (create in or below, Duplicate, Copy to other page, expand/collapse all, delete); the property editor has Common / All, Go to group and a Template Options dialog; a page number in the toolbar. No nested regions (APEX's sub regions) and no Comment Out |
|
|
42
|
+
| Shared components | ✅ | (sprint 74) A grid of ten groups with counts like APEX's, a searchable, sortable list per type with Create, and Settings-backed types linking to their Settings tab ([mapping below](#shared-components-apex-links-and-pgkiln)). Navigation menu, **lists** (static entries with nesting, badges, conditions, authorization and build options, or a query; for list regions, the navigation menu and the navigation bar), authorization schemes, build options, lists of values, application items and processes, access control, globalization, template components and plug-ins, web credentials, REST data sources, data load definitions, supporting objects |
|
|
43
43
|
| Export / import | ✅ | `meta.export_app()` / `meta.import_app()`: portable JSON, also in the builder (new applications; `pgkiln import --replace` and the MCP `import_app` update one in place, live for every user at the commit). (sprint 51) **Checked imports**: `pgkiln import --check` (`--dry-run`, `--force`), the MCP import (by default) and the builder's import run the Advisor inside the import's transaction (SQL planned as the application's role: missing tables, columns, functions, types, grants; references) and refuse on errors, so nothing changes; APEX doesn't check. The version an import replaces is [backed up](guide/03-builder.md#backups) first ([chapter 18](guide/18-cli.md#checking-before-an-import)) |
|
|
44
44
|
| APEXlang: human-readable, diffable app files; static IDs (26.1) | ✅ | `pgkiln export --format dir`: one JSON file per component with sorted keys, SQL and HTML in sibling files, references by static id instead of database ids; `pgkiln import --replace` updates an app in place, `pgkiln diff` compares ([chapter 18](guide/18-cli.md)). (0.31) **`--format text`**: the same files as YAML (a strict subset any YAML tool reads) with the SQL and templates inline, read back losslessly ([text files](guide/18-cli.md#text-files-apexlang)); regions have a stored **Static ID** (exported as their key, rendered as `data-static-id`), other components are named by their stored names. The syntax is YAML rather than APEXlang's own, so APEXlang files don't import |
|
|
45
45
|
| Working copies, merge, team development | ✅ | **Working copies** of an application ([chapter 3](guide/03-builder.md#working-copies)): a second app on the same schema and data, compared three ways per component (settings, each shared component, page, region, item, …) with the main app as it was when copied; changes on one side merge, conflicts are chosen per component with a line diff; merge into the main app or refresh the copy, keeping users, sessions, saved reports, secrets and automation switches; locks respected. Conflicts are resolved per component, not per property |
|
|
@@ -61,14 +61,14 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
61
61
|
| APEX | pgkiln | Notes |
|
|
62
62
|
|---|---|---|
|
|
63
63
|
| Classic report | ✅ | `report` with `interactive: false` |
|
|
64
|
-
| Interactive report | ✅ | 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) |
|
|
64
|
+
| 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) |
|
|
65
65
|
| 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, details refreshed in place), 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)) |
|
|
66
66
|
| 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 |
|
|
67
67
|
| 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)) |
|
|
68
68
|
| Charts | ✅ | Bar, column, stacked, line, area, combination (columns + lines), scatter, bubble, donut, pie, gauge, funnel, radar, **Gantt** (start/end, progress, milestones, dependencies, a today line, a time axis from hours to years), **pyramid** (area-proportional segments, or two series back to back) and **polar** (polar area); (sprint 63) **range** (floating columns from low to high), **box plot** (from one value per row or five statistics) and **stock** (candlesticks from open, high, low and close); multi-series, tooltips, data table, (sprint 71) a value axis with gridlines on horizontal bars and top-N with an *Other* bar (`"top": 10`), palette checked for colour-vision deficiency; drill-down links on chart marks (checksummed, only to pages the user may open). Drawn on the server as SVG without inline styles. (sprint 69) **Gantt editing**: drag a task or its end, or the arrow keys, runs the region's SQL as the app's role. (sprint 70) **treemap** (squarified, two levels shown), **sunburst** (up to four rings) from `node_id` / `parent_id` columns, and **timeline** (lanes by a `series` column, points and periods, overlaps in rows). **Missing:** other Oracle JET types (e.g. picto, NBox, Sankey) |
|
|
69
69
|
| Cards and metric cards (26.1 metric card template) | ✅ | Cards from SQL, with a KPI "metric" style |
|
|
70
70
|
| Calendar | ✅ | Month, week, day and list views (agenda list on phones); create on click (a checksummed link with the slot); drag and drop to move events through the developer's move SQL, run as the app's role (CSRF, a *who may drag* authorization, only events the user sees). Works without JavaScript; dragging adds on top ([chapter 4](guide/04-pages-and-regions.md#calendar)) |
|
|
71
|
-
| Faceted search | ✅ | Checkbox, range (predefined, or a custom from/to on numbers and dates), star rating and search facets with live counts that honour the other facets; exclude on checkbox facets (26.1). Values travel as query parameters, never as SQL text. (sprint 65) **Facet charts**: a bar or pie chart of a facet's counts, each mark filtering on its value |
|
|
71
|
+
| Faceted search | ✅ | Checkbox, range (predefined, or a custom from/to on numbers and dates), star rating and search facets with live counts that honour the other facets; exclude on checkbox facets (26.1). Values travel as query parameters, never as SQL text. (sprint 65) **Facet charts**: a bar or pie chart of a facet's counts, each mark filtering on its value. (sprint 78) The **total row count**, *Show all* after seven values, booleans as Yes/No, one search field (the report's own is left out). No per-facet menu (sort by count or name) |
|
|
72
72
|
| Smart filters | ✅ | One search field with filter chips and suggestions over a report, the same facet types; URL-based, works without JavaScript ([chapter 4](guide/04-pages-and-regions.md#smart_filters)) |
|
|
73
73
|
| Static content, dynamic content | ✅ | `static` (HTML with substitutions) and `dynamic` (a SELECT returning HTML) |
|
|
74
74
|
| Breadcrumb | ✅ | Automatic, from the page's breadcrumb parent |
|
|
@@ -156,7 +156,7 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
156
156
|
|
|
157
157
|
| APEX | pgkiln | Notes |
|
|
158
158
|
|---|---|---|
|
|
159
|
-
| Universal Theme look and layout | ✅ | Header, side/top navigation, breadcrumbs, 12-column grid, region templates |
|
|
159
|
+
| Universal Theme look and layout | ✅ | Header, side/top navigation, breadcrumbs, 12-column grid, region templates. (sprint 77) Region display positions (banner, breadcrumb bar, left and right column, body, footer), the Left / Right Side Column page templates and button positions (create, edit, change, copy, help, up, previous, close, delete, next) ([chapter 4](guide/04-pages-and-regions.md#side-columns-and-display-positions)) |
|
|
160
160
|
| Region templates (Carousel, Hero, Inline Dialog/Popup/Drawer, Wizard Container, Title Bar, Buttons Container, Login) | ✅ | Standard, plain and collapsible; (sprint 57) **hero**, **title bar**, **buttons container**, **inline dialog** and **inline drawer** (opened by the dynamic action *Open region* or a link to `#R<id>`), **wizard** with the list template **wizard progress**, and the **carousel** style of the display selector; dialog and drawer **pages**; the login page's **Login** region (sprint 55) ([chapter 4](guide/04-pages-and-regions.md#layout)). An inline popup (anchored to a button) is an inline dialog |
|
|
161
161
|
| Warn on unsaved changes | ✅ | (sprint 50) A page attribute: the browser asks before the user leaves the page (links, redirect buttons, other forms, closing a dialog, closing or reloading the tab) while an item differs from the value it was shown with, also after a submit that failed; submitting doesn't ask; items opt out with `{"warn_unsaved": false}`; `pgkiln.isChanged()` (APEX: `apex.page.isChanged()`); on for the form pages the wizards make. The interactive grid keeps its own check ([chapter 4](guide/04-pages-and-regions.md#warn-on-unsaved-changes)). No per-button "do not check" |
|
|
162
162
|
| Responsive: phone, tablet, desktop | ✅ | Tested at 390, 768, 1024 and 1440px on every change (`npm run test:e2e`) |
|
|
@@ -176,7 +176,7 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
176
176
|
| Translated applications (26.1: text-message-based translation of one app) | ✅ | One app with translations, like 26.1; XLIFF 1.2 and CSV export/import, coverage per language |
|
|
177
177
|
| Text messages (`APEX_LANG.MESSAGE`, `&APP_TEXT$…`) | ✅ | `meta.message()`, `&APP_TEXT$NAME.`, fallback to the base and primary language |
|
|
178
178
|
| Language from browser, preference or session | ✅ | Browser, user preference or primary; `?lang=`; right-to-left languages |
|
|
179
|
-
| Date and timestamp format masks | ✅ | Per app or per language |
|
|
179
|
+
| Date and timestamp format masks | ✅ | Per app or per language; (sprint 76) date items show and read the application's date format (or their own) with a calendar button |
|
|
180
180
|
| Dynamic translations (`APEX_LANG.LANG`: translated data values, e.g. list of values entries) | ✅ | (sprint 53) Shared Components → Dynamic translations; `meta.lang(text)` in a query returns the value in the session's language (base language fallback); exported with the application |
|
|
181
181
|
| Number format masks, automatic time zone | ✅ | Oracle-style number masks (`999G999G990D00`, `FML…`, `0000`, `%`, `S`/`MI`/`PR`, `EEEE`, `X`, `RN`) on report, grid and cards columns, charts and number/display items, in the language's separators with the app's currency; Automatic Time Zone (browser, My account, app or database), `timestamptz` shown in it ([chapter 14](guide/14-globalization.md)) |
|
|
182
182
|
|
|
@@ -184,7 +184,7 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
184
184
|
|
|
185
185
|
| APEX | pgkiln | Notes |
|
|
186
186
|
|---|---|---|
|
|
187
|
-
| SQL Workshop: SQL commands, object browser | ✅ | (sprint 61) A **home page** like APEX's: tiles, recently created tables, your recent SQL commands and the workspace's recent scripts, and the session's **default schema** (first in the search path of SQL Commands and Scripts). The object
|
|
187
|
+
| SQL Workshop: SQL commands, object browser | ✅ | (sprint 61) A **home page** like APEX's: tiles, recently created tables, your recent SQL commands and the workspace's recent scripts, and the session's **default schema** (first in the search path of SQL Commands and Scripts). (sprint 75) The **Object Browser** like APEX's: a schema in the header, a tree by object type (tables, views, materialized views, indexes, sequences, types, functions, procedures, triggers) with a filter and a Create menu, system and extension objects hidden unless asked, and a table in tabs (columns with Add/Rename/Drop column writing the ALTER TABLE to review, data in pages, indexes, constraints, triggers, grants, row level security, dependencies, statistics, DDL); the tools as main tabs and a More menu. (sprint 62) **Utilities** like APEX's: the tools on one page, **Object Reports** (tables without a primary key, unindexed foreign keys, row-level security without policies or not enabled, PUBLIC grants, unused indexes, largest tables, missing comments), **About Database** and a **Database Monitor** of sessions and blocked queries for administrators. **Missing:** a recycle bin (PostgreSQL has none), user interface defaults (pgkiln's wizards read the catalog and comments) |
|
|
188
188
|
| RESTful services (ORDS) | ✅ | [PostgREST](https://postgrest.org) next to pgkiln: `api` schema, the same RLS as the UI, per-app API role, tokens in the builder, a pre-request check, and **OAuth clients** (client credentials, like ORDS `oauth.create_client`) so tokens renew themselves |
|
|
189
189
|
| REST handler editor, REST-enabled SQL | ✅ | **REST modules** in the builder: handlers (method, path with parameters, SQL as collection, item or statements, roles, public) served by pgkiln with bearer tokens and an OpenAPI description; plus PostgREST for schema-wide APIs. **Missing:** REST-enabled SQL (rarely desirable) |
|
|
190
190
|
| SQL scripts, query builder, Quick SQL | ✅ | **SQL Scripts**: saved, upload/download, a result per statement, stop or continue on errors, optionally one transaction, run history. **Quick SQL** (a subset: tables, child tables, types, the main column directives, `/auditcols`, settings, views). A graphical **query builder**: tables as boxes on a canvas (dragged, placed where left), joins along foreign keys or drawn from column to column (inner or left), column functions with automatic `group by`, conditions, sort, open in SQL Commands; without JavaScript the same as forms ([chapter 3](guide/03-builder.md#sql-workshop)) |
|
|
@@ -219,7 +219,7 @@ two, REST source catalogs and the workspace export, with their features.)
|
|
|
219
219
|
| Workspace message, environment banner, workspace utilization, preferences and extension links (Manage Service) | ✅ | (sprint 61) An **Administration** menu in the icon rail; administrators and workspace administrators set a **workspace message** (on the App Builder home) and an **environment banner** (a coloured label on every builder page of the workspace), and see **workspace utilization** (applications, pages, page views, users, static files, schema storage) ([chapter 3](guide/03-builder.md#workspace-message-and-environment-banner)). (sprint 62) **Workspace preferences**: the SQL Workshop and the applications' RESTful services (REST modules) on or off per workspace; **extension links** in an Extensions menu of the rail ([chapter 3](guide/03-builder.md#workspace-preferences)). **Missing:** the account login controls of APEX's preferences (pgkiln's password policy and sign-in throttling are installation-wide) |
|
|
220
220
|
| Instance administration, install/upgrade logs (26.1) | ✅ | Versioned migrations (`npm run db:migrate`), every run logged; Workspace utilities → **Installation** (administrators): server version, install and upgrade runs with errors, applied migrations, and warnings for migrations the database misses or the server doesn't know ([chapter 3](guide/03-builder.md)). Workspace utilities → **Instance settings**: session length and sign-in throttling (stored in the database, over the environment variables) and an overview of the server's configuration without secrets; a server whose database lacks migrations says so (503) or applies them (`MIGRATE_ON_START`). Other settings stay environment variables |
|
|
221
221
|
| Debug messages | ✅ | Debug levels 1–9 per app; `meta.debug(level, text)` and `meta.debug_enabled(level)` from application SQL (APEX_DEBUG); timed entries per request (page steps, regions, processes, branches, errors, SQL notices); Activity → **Debug messages** viewer per page view with filters and the slowest step highlighted; retention 1–90 days; password item values are never recorded ([chapter 6](guide/06-processing.md)). (sprint 50) Debug for **one session** from the developer toolbar, the application staying out of debug. **Missing:** debug entries for background jobs and REST requests |
|
|
222
|
-
| Developer toolbar, session state viewer | ✅ | (sprint 50) Developers signed in to the builder see a toolbar on the pages of their applications in the same browser: App Builder, the application, **Edit page** (Page Designer), **Session** (the session state viewer: user, roles, session, language, time zone, debug level, this page's items, application items and other pages' items; passwords never shown; clear the page's items) **Quick edit** (sprint 59: click a region, item or button to open it in the Page Designer) and **Debug** for this session only. A separate random token (cookie path `/a`, HttpOnly) of a live builder session of a developer of the application's workspace ([chapter 3](guide/03-builder.md#developer-toolbar)). (sprint 72) A compact bar of icons with tooltips like APEX's, centred at the bottom, **Customize** (the Theme Roller) and **Info**, hidden to a slim tab when not used, docked at the bottom, top, left or right; the page keeps room for it |
|
|
222
|
+
| Developer toolbar, session state viewer | ✅ | (sprint 50) Developers signed in to the builder see a toolbar on the pages of their applications in the same browser: App Builder, the application, **Edit page** (Page Designer), **Session** (the session state viewer: user, roles, session, language, time zone, debug level, this page's items, application items and other pages' items; passwords never shown; clear the page's items) **Quick edit** (sprint 59: click a region, item or button to open it in the Page Designer) and **Debug** for this session only. A separate random token (cookie path `/a`, HttpOnly) of a live builder session of a developer of the application's workspace ([chapter 3](guide/03-builder.md#developer-toolbar)). (sprint 72) A compact bar of icons with tooltips like APEX's, centred at the bottom, **Customize** (the Theme Roller) and **Info**, hidden to a slim tab when not used, docked at the bottom, top, left or right; the page keeps room for it (sprint 79) Each tool with a short text like APEX's (*App 12*, *Page 3*, *Debug off*), *Icons only* as a setting |
|
|
223
223
|
| Feedback (users send feedback from a page, developers answer) | ✅ | (sprint 51) With *Users can send feedback* on, the navigation bar's **Feedback** link opens a page for a comment, idea or problem about the page (optional rating), with the user's earlier feedback and the developers' answers; developers read, filter, set a status and answer under Application → Feedback ([chapter 3](guide/03-builder.md#feedback)). No screenshots, no e-mail to developers |
|
|
224
224
|
| Automatic application backups, page groups | ✅ | (sprint 51) **Backups**: before every import that replaces an application (CLI, MCP, working copy merge, restore), daily when it changed, and by hand; the newest 25 (configurable) are kept; download and restore from the builder ([chapter 3](guide/03-builder.md#backups)); (sprint 62) Workspace utilities → **Manage backups** across the workspace's applications, with a backup of all of them at once. (sprint 58) **Page groups**: Shared Components → Page groups, a page's *Page group*, the page list by group with a filter ([chapter 3](guide/03-builder.md#page-groups)) |
|
|
225
225
|
| Application availability (Available, Developers only, Restricted access, Unavailable; build status *Run only*) | ✅ | (sprint 51) Available, available to developers only (a builder session in the same browser), restricted to named users, or unavailable with a message, for pages, file downloads, REST modules and PostgREST; build status **Run only** refuses builder changes as if the application were locked, while `pgkiln import --replace` still deploys. Installation settings: not exported, kept by an import ([chapter 3](guide/03-builder.md#availability-and-build-status)) |
|
|
@@ -304,3 +304,30 @@ report filters, App Builder AI and blueprints.
|
|
|
304
304
|
Sources: [APEX 26.1 new features](https://docs.oracle.com/en/database/oracle/apex/26.1/htmrn/new-features.html),
|
|
305
305
|
[What's new in APEX 24.2](https://apex.oracle.com/en/platform/features/whats-new-242/),
|
|
306
306
|
[APEX_MAIL (APEX API reference)](https://docs.oracle.com/en/database/oracle/apex/24.2/aeapi/APEX_MAIL.html).
|
|
307
|
+
|
|
308
|
+
## Shared Components: APEX links and pgkiln
|
|
309
|
+
|
|
310
|
+
(sprint 74) Every link of APEX 26.2's Shared Components page and where it is in pgkiln.
|
|
311
|
+
|
|
312
|
+
| APEX | pgkiln |
|
|
313
|
+
|---|---|
|
|
314
|
+
| Application Definition, Application Items, Application Processes, Application Settings, Build Options | The same names (Application Logic) |
|
|
315
|
+
| Application Computations | ➖ Not planned: an application process *before every page* or an item's computation does it |
|
|
316
|
+
| Authentication Schemes | Settings → Security: one authentication per application (its type and fields); several schemes to switch between are ➖ not planned |
|
|
317
|
+
| Authorization Schemes, Access Control | The same names (Security) |
|
|
318
|
+
| Security Attributes, Session State Protection | Settings → Security and Sign-in; session state protection is per page (Page Designer → *Protection*) |
|
|
319
|
+
| Lists of Values, Lists, Email Templates, Supporting Objects, Subscriptions | The same names (Other Components) |
|
|
320
|
+
| Navigation Menu, Navigation Bar List, Breadcrumbs, Search Configurations | The same names (Navigation and Search); breadcrumbs follow each page's breadcrumb parent |
|
|
321
|
+
| Shortcuts | ➖ Not planned: application items and substitutions (`&ITEM.`) |
|
|
322
|
+
| Themes, Templates, User Interface Attributes, Theme Roller | Themes and Theme Roller, Template Components, Settings → User Interface; page and region templates are a fixed list (➖ no template editor) |
|
|
323
|
+
| Plug-ins, Component Settings | Plug-ins; component settings ➖ not planned |
|
|
324
|
+
| Component Groups | Page Groups (pages); groups of other components ➖ not planned |
|
|
325
|
+
| Progressive Web App | Settings → Progressive Web App |
|
|
326
|
+
| Static Application Files, Static Workspace Files | Static Application Files; workspace files ➖ not planned |
|
|
327
|
+
| Report Layouts, Report Queries | Report Layouts and Document Templates (a template with its own queries) |
|
|
328
|
+
| REST Data Sources, Web Credentials, REST Enabled SQL, Data Load Definitions | The same names (Data Sources); REST Enabled SQL ➖ not planned (one database) |
|
|
329
|
+
| Workflows, Task Definitions, Automations | The same names |
|
|
330
|
+
| Text Messages, Translate, Dynamic Translations, Globalization Attributes | Translations and Text Messages, Dynamic Translations, Settings → Globalization |
|
|
331
|
+
| Map Backgrounds | The installation's map tile server (`MAP_TILE_URL`) |
|
|
332
|
+
| AI Attributes, AI Services, AI Agents | AI Services; AI agents ➖ not planned |
|
|
333
|
+
|