pgkiln 0.42.0 → 0.43.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/docs/apex-feature-parity.md +34 -7
- package/docs/guide/03-builder.md +67 -13
- package/docs/guide/04-pages-and-regions.md +46 -3
- package/docs/guide/05-items.md +1 -1
- package/docs/guide/09-reference.md +4 -1
- package/docs/guide/12-development.md +2 -1
- package/package.json +1 -1
- package/public/app.css +58 -0
- package/public/app.js +183 -0
- package/public/builder.css +112 -0
- package/public/builder.js +280 -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 +16 -0
- package/src/i18n/cs.ts +16 -0
- package/src/i18n/da.ts +16 -0
- package/src/i18n/de.ts +16 -0
- package/src/i18n/el.ts +16 -0
- package/src/i18n/es.ts +16 -0
- package/src/i18n/fi.ts +16 -0
- package/src/i18n/fr.ts +16 -0
- package/src/i18n/he.ts +16 -0
- package/src/i18n/it.ts +16 -0
- package/src/i18n/ja.ts +16 -0
- package/src/i18n/ko.ts +16 -0
- package/src/i18n/nb.ts +16 -0
- package/src/i18n/pl.ts +16 -0
- package/src/i18n/pt.ts +16 -0
- package/src/i18n/ru.ts +16 -0
- package/src/i18n/sv.ts +16 -0
- package/src/i18n/tr.ts +16 -0
- package/src/i18n/uk.ts +16 -0
- package/src/i18n/zh.ts +16 -0
- package/src/i18n.ts +32 -0
- package/src/metadata.ts +5 -1
- package/src/runtime/engine.ts +6 -0
- package/src/runtime/format.ts +52 -0
- package/src/runtime/items.ts +27 -0
- package/src/runtime/locale.ts +3 -0
- package/src/runtime/regions.ts +36 -2
- package/src/runtime/render.ts +20 -4
- package/src/runtime/report.ts +134 -79
- package/src/runtime/routes.ts +34 -3
package/src/runtime/routes.ts
CHANGED
|
@@ -24,15 +24,16 @@ import { startDebug } from '../debug.ts';
|
|
|
24
24
|
import { assignable, clearPageItems, fetchForms, processConditionHolds, ProcessFailed, runAppProcesses, runProcesses, runSql, validate, ValidationFailed } from './engine.ts';
|
|
25
25
|
import { aiInputs, aiProcessOf, runAiProcess } from './ai.ts';
|
|
26
26
|
import { branchTarget, ComputationFailed, runComputations } from './logic.ts';
|
|
27
|
-
import { comboMultiple, itemMask, MULTI_VALUE, popupPageSize, renderItem, searchLov, splitValues } from './items.ts';
|
|
27
|
+
import { comboMultiple, itemDateMask, itemMask, MULTI_VALUE, popupPageSize, renderItem, searchLov, splitValues } from './items.ts';
|
|
28
28
|
import { parseNumber } from '../numformat.ts';
|
|
29
|
+
import { parseDateMask } from './format.ts';
|
|
29
30
|
import { cleanRichText } from '../richtext.ts';
|
|
30
31
|
import { applyUploads, fileRoutes, readMultipart, type Upload } from './files.ts';
|
|
31
32
|
import { renderRegion } from './regions.ts';
|
|
32
33
|
import { downloadHeaders, type Download } from './processes.ts';
|
|
33
34
|
import { moveGanttTask } from './gantt-move.ts';
|
|
34
35
|
import { moveCalendarEvent } from './calendar.ts';
|
|
35
|
-
import { openDownload, reportParams, normaliseReportParams, selectionOf } from './report.ts';
|
|
36
|
+
import { columnValues, openDownload, reportParams, normaliseReportParams, selectionOf } from './report.ts';
|
|
36
37
|
import { invalidatePage, lazyOf } from './region-cache.ts';
|
|
37
38
|
import { applyRowSelection, mastersOf } from './master-detail.ts';
|
|
38
39
|
import { layerInArea, layerTile, parseTile, servedLayer } from './maps.ts';
|
|
@@ -373,7 +374,10 @@ function applyPostedItems(ctx: PageContext, body: Body, only?: string[]) {
|
|
|
373
374
|
else if (item.type === 'markdown') ctx.session.state[item.name] = posted ? String(posted).replace(/\r\n?/g, '\n') : null;
|
|
374
375
|
else if (item.type === 'checkbox' || item.type === 'switch') ctx.session.state[item.name] = posted === 'true' ? 'true' : 'false';
|
|
375
376
|
else if (item.type === 'password' && !posted) continue;
|
|
376
|
-
else if (
|
|
377
|
+
else if (item.type === 'date' && itemDateMask(ctx, item) && posted !== undefined && posted !== '') {
|
|
378
|
+
// (sprint 76) "23-05-1987" in the date format → "1987-05-23"; other text is kept as typed, and validate() reports it
|
|
379
|
+
ctx.session.state[item.name] = parseDateMask(String(posted), itemDateMask(ctx, item)!, ctx.locale.lang) ?? String(posted);
|
|
380
|
+
} else if (itemMask(item) && posted !== undefined && posted !== '') {
|
|
377
381
|
// "1.234,50 €" → "1234.5"; text that isn't a number is kept as typed, and validate() reports it
|
|
378
382
|
const parsed = parseNumber(String(posted), itemMask(item), ctx.locale.numbers);
|
|
379
383
|
ctx.session.state[item.name] = parsed === null ? String(posted) : parsed || null;
|
|
@@ -736,6 +740,33 @@ export async function runtimeRoutes(app: FastifyInstance) {
|
|
|
736
740
|
}
|
|
737
741
|
});
|
|
738
742
|
|
|
743
|
+
// ---------------------------------------------------------------- a column heading's values
|
|
744
|
+
// (sprint 76) The values of a report column with their counts, for its heading's menu: the report must be
|
|
745
|
+
// visible and interactive; the query runs as the application's role with the request's search and filters;
|
|
746
|
+
// only a column the user may see. Read only.
|
|
747
|
+
app.get('/a/:alias/:page/report/:id/values', async (req: Req, reply) => {
|
|
748
|
+
const ctx = await loadContext(req, reply, { json: true });
|
|
749
|
+
if (!ctx) return;
|
|
750
|
+
reply.header('cache-control', 'private, no-store');
|
|
751
|
+
const column = String((req.query as Record<string, unknown>)?.col ?? '');
|
|
752
|
+
try {
|
|
753
|
+
const out = await appTx(txContext(ctx), async (c) => {
|
|
754
|
+
ctx.client = c;
|
|
755
|
+
await checkPageAccess(ctx);
|
|
756
|
+
const vis = await computeVisibility(ctx);
|
|
757
|
+
const r = ctx.page.regions.find((x) => x.id === Number(req.params.id) && x.type === 'report');
|
|
758
|
+
if (!r || !vis.regions.has(r.id) || r.config.interactive === false || r.config.searchable === false) throw new Forbidden(ctx.locale.t('error.access_denied'));
|
|
759
|
+
const list = column ? await columnValues(ctx, r, column) : null;
|
|
760
|
+
if (!list) throw new Forbidden(ctx.locale.t('error.access_denied'));
|
|
761
|
+
return { values: list };
|
|
762
|
+
});
|
|
763
|
+
return reply.send(out);
|
|
764
|
+
} catch (e) {
|
|
765
|
+
if (e instanceof Forbidden) return reply.code(403).send({ error: e.message });
|
|
766
|
+
return reply.code(400).send({ error: await publicError(ctx, e, 'column values') });
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
|
|
739
770
|
// ---------------------------------------------------------------- map layers loaded by the browser
|
|
740
771
|
// (0.31) A map layer with "visible_area" (JSON for ?bb=south,west,north,east)
|
|
741
772
|
// or "tiles" (Mapbox Vector Tiles, …/tiles/<layer>/<z>/<x>/<y>.mvt). Page
|