pgkiln 0.84.0 → 0.86.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/155_mail_available.sql +23 -0
- package/docs/apex-feature-parity.md +2 -2
- package/docs/guide/03-builder.md +14 -5
- package/docs/guide/04-pages-and-regions.md +1 -1
- package/docs/guide/06-processing.md +7 -3
- package/docs/guide/07-dynamic-actions.md +3 -3
- package/docs/guide/09-reference.md +1 -0
- package/docs/guide/12-development.md +10 -1
- package/examples/gallery/README.md +23 -6
- package/examples/gallery/gallery.json +4 -0
- package/examples/gallery/samples/sample-approvals.sql +102 -11
- package/examples/gallery/samples/sample-calendar.sql +40 -5
- package/examples/gallery/samples/sample-dynamic-actions.sql +237 -9
- package/examples/gallery/samples/sample-grids.sql +35 -3
- package/examples/gallery/samples/sample-maps.sql +65 -7
- package/examples/gallery/samples/sample-processes.sql +466 -0
- package/examples/gallery/samples/sample-validations.sql +407 -0
- package/examples/gallery/samples/ux-patterns.sql +154 -14
- package/examples/hr/README.md +2 -0
- package/examples/hr/hr_80_notifications.sql +125 -0
- package/examples/hr/hr_81_vector_search_type.sql +33 -0
- package/package.json +1 -1
- package/public/app.css +8 -1
- package/public/app.js +28 -9
- package/src/app.ts +9 -0
- package/src/builder/ai-agents.ts +86 -85
- package/src/builder/ai-builder.ts +30 -30
- package/src/builder/ai.ts +93 -92
- package/src/builder/api.ts +47 -47
- package/src/builder/app-groups.ts +33 -32
- package/src/builder/appfromfile.ts +57 -58
- package/src/builder/appsheets.ts +33 -32
- package/src/builder/appwizard.ts +65 -65
- package/src/builder/arrange.ts +23 -22
- package/src/builder/assistant.ts +39 -38
- package/src/builder/automations.ts +32 -31
- package/src/builder/availability.ts +24 -24
- package/src/builder/backups.ts +30 -31
- package/src/builder/blueprints.ts +62 -61
- package/src/builder/create-page.ts +52 -50
- package/src/builder/cross-app.ts +37 -35
- package/src/builder/dataload.ts +2 -2
- package/src/builder/datasets.ts +107 -106
- package/src/builder/dependencies.ts +20 -19
- package/src/builder/designer.ts +36 -36
- package/src/builder/diagnostics.ts +58 -57
- package/src/builder/features.ts +39 -35
- package/src/builder/feedback.ts +23 -20
- package/src/builder/find-workspace.ts +28 -24
- package/src/builder/form-designer.ts +36 -35
- package/src/builder/gallery.ts +25 -29
- package/src/builder/globalization.ts +50 -49
- package/src/builder/i18n/de.ts +3453 -0
- package/src/builder/i18n/en.ts +3453 -0
- package/src/builder/i18n/es.ts +3453 -0
- package/src/builder/i18n/fr.ts +3453 -0
- package/src/builder/i18n/it.ts +3453 -0
- package/src/builder/i18n/ja.ts +3453 -0
- package/src/builder/i18n/ko.ts +3453 -0
- package/src/builder/i18n/nl.ts +3453 -0
- package/src/builder/i18n/pt.ts +3453 -0
- package/src/builder/i18n/zh-cn.ts +3453 -0
- package/src/builder/i18n/zh-tw.ts +3453 -0
- package/src/builder/i18n.ts +17 -3
- package/src/builder/json-sources.ts +63 -62
- package/src/builder/layouts.ts +12 -11
- package/src/builder/locks.ts +29 -28
- package/src/builder/login-page.ts +26 -25
- package/src/builder/mail.ts +148 -147
- package/src/builder/newapp.ts +15 -12
- package/src/builder/plugins.ts +47 -44
- package/src/builder/process-jobs.ts +11 -10
- package/src/builder/pwa.ts +22 -21
- package/src/builder/remote-databases.ts +55 -56
- package/src/builder/report-settings.ts +1 -1
- package/src/builder/reporter.ts +43 -42
- package/src/builder/rest-catalogs.ts +87 -86
- package/src/builder/rest.ts +9 -8
- package/src/builder/routes.ts +27 -27
- package/src/builder/search.ts +14 -13
- package/src/builder/static-files.ts +31 -32
- package/src/builder/subscriptions.ts +47 -45
- package/src/builder/supporting.ts +23 -18
- package/src/builder/team.ts +179 -179
- package/src/builder/telemetry.ts +59 -62
- package/src/builder/templates.ts +66 -65
- package/src/builder/themeroller.ts +60 -63
- package/src/builder/ui-defaults.ts +21 -20
- package/src/builder/ui.ts +2 -1
- package/src/builder/upgrade.ts +25 -24
- package/src/builder/utilities.ts +48 -47
- package/src/builder/vector-providers.ts +67 -66
- package/src/builder/websources.ts +43 -42
- package/src/builder/wizards.ts +95 -89
- package/src/builder/workflow-migrate.ts +30 -31
- package/src/builder/workflows.ts +40 -39
- package/src/builder/workingcopies.ts +41 -49
- package/src/builder/workspace-backups.ts +21 -20
- package/src/builder/workspace-mail.ts +17 -16
- package/src/builder/workspace-resources.ts +104 -112
- package/src/builder/workspace-transfer.ts +34 -26
- package/src/runtime/engine.ts +6 -3
- package/src/runtime/lists.ts +2 -2
- package/src/runtime/push.ts +7 -1
- package/src/runtime/regions.ts +9 -4
package/src/builder/cross-app.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { html, raw } from '../html.ts';
|
|
|
4
4
|
import { icon } from '../icons.ts';
|
|
5
5
|
import { BASE, developer, region, send, shell, type Req } from './ui.ts';
|
|
6
6
|
import { currentWorkspace } from './workspaces.ts';
|
|
7
|
+
import { scopedTx as tx, type BuilderKey } from './i18n.ts';
|
|
7
8
|
|
|
8
9
|
// Cross-application reports (sprint 61; APEX: Workspace Utilities → Cross
|
|
9
10
|
// Application Reports): one read-only report per topic over every application
|
|
@@ -11,9 +12,10 @@ import { currentWorkspace } from './workspaces.ts';
|
|
|
11
12
|
// returns app_id and app (the name) first; those become a link.
|
|
12
13
|
|
|
13
14
|
interface Report {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
/** Message keys (src/builder/i18n): the title, the introduction and the column labels. */
|
|
16
|
+
title: BuilderKey;
|
|
17
|
+
about: BuilderKey;
|
|
18
|
+
columns: [key: string, label: BuilderKey, cls?: 'num'][];
|
|
17
19
|
sql: string;
|
|
18
20
|
}
|
|
19
21
|
|
|
@@ -22,56 +24,56 @@ const IN_WS = 'meta.app_workspace(a.id) = $1';
|
|
|
22
24
|
|
|
23
25
|
export const REPORTS: Record<string, Report> = {
|
|
24
26
|
attributes: {
|
|
25
|
-
title: '
|
|
26
|
-
about: '
|
|
27
|
-
columns: [['alias', '
|
|
27
|
+
title: 'xap.attributes.title',
|
|
28
|
+
about: 'xap.attributes.about',
|
|
29
|
+
columns: [['alias', 'xap.col.alias'], ['app_type', 'xap.col.type'], ['authentication', 'xap.col.sign_in'], ['availability', 'xap.col.availability'], ['build_status', 'xap.col.build_status'], ['debug_level', 'xap.col.debug', 'num'], ['language', 'xap.col.language'], ['db_role', 'xap.col.database_role'], ['updated', 'xap.col.updated']],
|
|
28
30
|
sql: `select a.id as app_id, a.name as app, a.alias, a.app_type, a.authentication, a.availability, a.build_status, a.debug_level,
|
|
29
31
|
a.language, coalesce(a.db_role, '(runtime connection)') as db_role, to_char(a.updated_at, 'YYYY-MM-DD HH24:MI') as updated
|
|
30
32
|
from meta.app a where ${IN_WS} order by lower(a.name)`,
|
|
31
33
|
},
|
|
32
34
|
'build-options': {
|
|
33
|
-
title: '
|
|
34
|
-
about: '
|
|
35
|
-
columns: [['name', '
|
|
35
|
+
title: 'xap.build_options.title',
|
|
36
|
+
about: 'xap.build_options.about',
|
|
37
|
+
columns: [['name', 'xap.col.build_option'], ['status', 'xap.col.status'], ['description', 'xap.col.description']],
|
|
36
38
|
sql: `select a.id as app_id, a.name as app, b.name, b.status, b.description
|
|
37
39
|
from meta.app a join meta.build_option b on b.app_id = a.id where ${IN_WS} order by lower(a.name), b.name`,
|
|
38
40
|
},
|
|
39
41
|
comments: {
|
|
40
|
-
title: '
|
|
41
|
-
about: '
|
|
42
|
-
columns: [['page_no', '
|
|
42
|
+
title: 'xap.comments.title',
|
|
43
|
+
about: 'xap.comments.about',
|
|
44
|
+
columns: [['page_no', 'xap.col.page', 'num'], ['author', 'xap.col.author'], ['created', 'xap.col.written'], ['body', 'xap.col.comment']],
|
|
43
45
|
sql: `select a.id as app_id, a.name as app, c.page_no, c.author, to_char(c.created_at, 'YYYY-MM-DD HH24:MI') as created, left(c.body, 500) as body
|
|
44
46
|
from meta.app a join meta.dev_comment c on c.app_id = a.id where ${IN_WS} order by c.created_at desc limit 500`,
|
|
45
47
|
},
|
|
46
48
|
authentication: {
|
|
47
|
-
title: '
|
|
48
|
-
about: '
|
|
49
|
-
columns: [['authentication', '
|
|
49
|
+
title: 'xap.authentication.title',
|
|
50
|
+
about: 'xap.authentication.about',
|
|
51
|
+
columns: [['authentication', 'xap.col.sign_in'], ['local_login', 'xap.col.passwords'], ['providers', 'xap.col.identity_providers'], ['ldap', 'xap.col.ldap_directories'], ['access_control', 'xap.col.access'], ['remember_me_days', 'xap.col.keep_me_signed_in_days', 'num'], ['login_page', 'xap.col.login_page', 'num'], ['password_reset', 'xap.col.forgot_password']],
|
|
50
52
|
sql: `select a.id as app_id, a.name as app, a.authentication, case when a.local_login then 'yes' else 'no' end as local_login,
|
|
51
53
|
array_to_string(a.sso_providers, ', ') as providers, array_to_string(a.ldap_directories, ', ') as ldap,
|
|
52
54
|
a.access_control, a.remember_me_days, a.login_page, case when a.password_reset then 'yes' else 'no' end as password_reset
|
|
53
55
|
from meta.app a where ${IN_WS} order by lower(a.name)`,
|
|
54
56
|
},
|
|
55
57
|
authorization: {
|
|
56
|
-
title: '
|
|
57
|
-
about: '
|
|
58
|
-
columns: [['name', '
|
|
58
|
+
title: 'xap.authorization.title',
|
|
59
|
+
about: 'xap.authorization.about',
|
|
60
|
+
columns: [['name', 'xap.col.scheme'], ['type', 'xap.col.type'], ['value', 'xap.col.checks'], ['error_message', 'xap.col.error_message']],
|
|
59
61
|
sql: `select a.id as app_id, a.name as app, s.name, s.type, left(s.value, 300) as value, s.error_message
|
|
60
62
|
from meta.app a join meta.authz_scheme s on s.app_id = a.id where ${IN_WS} order by lower(a.name), s.name`,
|
|
61
63
|
},
|
|
62
64
|
'password-items': {
|
|
63
|
-
title: '
|
|
64
|
-
about: '
|
|
65
|
-
columns: [['page_no', '
|
|
65
|
+
title: 'xap.password_items.title',
|
|
66
|
+
about: 'xap.password_items.about',
|
|
67
|
+
columns: [['page_no', 'xap.col.page', 'num'], ['name', 'xap.col.item'], ['label', 'xap.col.label'], ['reveal', 'xap.col.show_button'], ['required', 'xap.col.required']],
|
|
66
68
|
sql: `select a.id as app_id, a.name as app, p.page_no, i.name, i.label,
|
|
67
69
|
case when (i.config ->> 'reveal')::boolean then 'yes' else 'no' end as reveal, case when i.required then 'yes' else 'no' end as required
|
|
68
70
|
from meta.app a join meta.page p on p.app_id = a.id join meta.item i on i.page_id = p.id
|
|
69
71
|
where ${IN_WS} and i.type = 'password' order by lower(a.name), p.page_no, i.seq`,
|
|
70
72
|
},
|
|
71
73
|
theme: {
|
|
72
|
-
title: '
|
|
73
|
-
about: '
|
|
74
|
-
columns: [['base', '
|
|
74
|
+
title: 'xap.theme.title',
|
|
75
|
+
about: 'xap.theme.about',
|
|
76
|
+
columns: [['base', 'xap.col.base_style'], ['style', 'xap.col.style'], ['nav', 'xap.col.navigation'], ['colors', 'xap.col.colours_set', 'num'], ['pwa', 'xap.col.installable_pwa']],
|
|
75
77
|
sql: `select a.id as app_id, a.name as app, coalesce(a.theme ->> 'base', 'default') as base, coalesce(a.theme ->> 'style', '-') as style,
|
|
76
78
|
coalesce(a.theme ->> 'nav', 'side') as nav,
|
|
77
79
|
(select count(*) from jsonb_object_keys(coalesce(a.theme -> 'colors', '{}'::jsonb)))::int as colors,
|
|
@@ -82,7 +84,7 @@ export const REPORTS: Record<string, Report> = {
|
|
|
82
84
|
|
|
83
85
|
/** The links in Workspace utilities' side column. */
|
|
84
86
|
export const crossAppLinks = () =>
|
|
85
|
-
Object.entries(REPORTS).map(([k, r]) => html`<li><a href="${BASE}/utilities/reports/${k}">${r.title}${icon('chevron')}</a></li>`);
|
|
87
|
+
Object.entries(REPORTS).map(([k, r]) => html`<li><a href="${BASE}/utilities/reports/${k}">${tx(r.title)}${icon('chevron')}</a></li>`);
|
|
86
88
|
|
|
87
89
|
export async function crossAppRoutes(app: FastifyInstance) {
|
|
88
90
|
app.get(`${BASE}/utilities/reports/:kind`, async (req: Req, reply) => {
|
|
@@ -92,15 +94,15 @@ export async function crossAppRoutes(app: FastifyInstance) {
|
|
|
92
94
|
if (!r) return reply.code(404).send('Not found');
|
|
93
95
|
const rows = (await owner.query(r.sql, [currentWorkspace(s)])).rows;
|
|
94
96
|
const cell = (v: unknown) => (v === null || v === undefined || v === '' ? html`<span class="muted">-</span>` : String(v));
|
|
95
|
-
const main = html`<div class="title-row"><h1>${r.title}</h1></div>
|
|
96
|
-
<p class="muted u-mt0">${r.about}
|
|
97
|
-
<nav class="ide-tabs u-mb1" aria-label="
|
|
98
|
-
html`<a class="ide-tab" href="${BASE}/utilities/reports/${k}"${k === req.params.kind ? raw(' aria-current="page"') : ''}><span>${x.title}</span></a>`)}</nav>
|
|
99
|
-
${region(r.title, rows.length
|
|
100
|
-
? html`<div class="table-wrap"><table class="report report-reflow"><thead><tr><th
|
|
101
|
-
<tbody>${rows.map((row) => html`<tr><td data-label="
|
|
102
|
-
${r.columns.map(([k, l, c]) => html`<td data-label="${l}"${c ? raw(` class="${c}"`) : ''}>${cell(row[k])}</td>`)}</tr>`)}</tbody></table></div>`
|
|
103
|
-
: html`<p class="muted"
|
|
104
|
-
return send(reply, s, shell(s, r.title, [['
|
|
97
|
+
const main = html`<div class="title-row"><h1>${tx(r.title)}</h1></div>
|
|
98
|
+
<p class="muted u-mt0">${tx(r.about)} ${tx('xap.of_workspace', { name: s.workspace?.name ?? '' })}</p>
|
|
99
|
+
<nav class="ide-tabs u-mb1" aria-label="${tx('xap.nav')}">${Object.entries(REPORTS).map(([k, x]) =>
|
|
100
|
+
html`<a class="ide-tab" href="${BASE}/utilities/reports/${k}"${k === req.params.kind ? raw(' aria-current="page"') : ''}><span>${tx(x.title)}</span></a>`)}</nav>
|
|
101
|
+
${region(tx(r.title), rows.length
|
|
102
|
+
? html`<div class="table-wrap"><table class="report report-reflow"><thead><tr><th>${tx('xap.application')}</th>${r.columns.map(([, l, c]) => html`<th${c ? raw(` class="${c}"`) : ''}>${tx(l)}</th>`)}</tr></thead>
|
|
103
|
+
<tbody>${rows.map((row) => html`<tr><td data-label="${tx('xap.application')}"><a href="${BASE}/apps/${row.app_id}">${row.app}</a></td>
|
|
104
|
+
${r.columns.map(([k, l, c]) => html`<td data-label="${tx(l)}"${c ? raw(` class="${c}"`) : ''}>${cell(row[k])}</td>`)}</tr>`)}</tbody></table></div>`
|
|
105
|
+
: html`<p class="muted">${tx('xap.nothing')}</p>`, html`<span class="count">${rows.length}</span>`)}`;
|
|
106
|
+
return send(reply, s, shell(s, tx(r.title), [[tx('rail.app_builder'), BASE], [tx('wu.title'), `${BASE}/utilities`], [tx(r.title)]], main));
|
|
105
107
|
});
|
|
106
108
|
}
|
package/src/builder/dataload.ts
CHANGED
|
@@ -27,7 +27,7 @@ import type { Session } from '../session.ts';
|
|
|
27
27
|
import type { ComponentSpec } from './components.ts';
|
|
28
28
|
import { back, BASE, csrf, developer, flash, region, send, shell, workshopTabs, type Body, type Req } from './ui.ts';
|
|
29
29
|
import { appWorkspace, currentWorkspace, workshopDb } from './workspaces.ts';
|
|
30
|
-
import { tr, translatorFor, type BuilderTranslate } from './i18n.ts';
|
|
30
|
+
import { scopedTx, tr, translatorFor, type BuilderTranslate } from './i18n.ts';
|
|
31
31
|
|
|
32
32
|
// SQL Workshop → Load Data: upload a CSV/TSV/XLSX/JSON/XML file, preview it,
|
|
33
33
|
// and load it into a new table (column types inferred) or an existing one
|
|
@@ -73,7 +73,7 @@ export const DATA_LOAD_DEF_SPEC: ComponentSpec = {
|
|
|
73
73
|
|
|
74
74
|
/** "Load a file with it" on a definition's Shared Components page. */
|
|
75
75
|
export const dataLoadDefExtras = (row: { id: number }) =>
|
|
76
|
-
html`<p class="u-mt1"><a class="btn" href="${BASE}/sql/load?definition=${row.id}">${icon('upload')}
|
|
76
|
+
html`<p class="u-mt1"><a class="btn" href="${BASE}/sql/load?definition=${row.id}">${icon('upload')} ${scopedTx('dl.load_with_def')}</a></p>`;
|
|
77
77
|
|
|
78
78
|
/** The data load definitions of the current workspace's applications. */
|
|
79
79
|
async function definitions(s: Session) {
|