@fieldia/core 0.10.0 → 0.12.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/README.md +204 -0
- package/package.json +1 -1
- package/schema/page.schema.json +4700 -904
- package/src/index.d.mts +2 -1
- package/src/index.d.ts +2 -1
- package/src/index.js +7 -1
- package/src/index.js.map +1 -1
- package/src/index.mjs +2 -1
- package/src/index.mjs.map +1 -1
- package/src/lib/expression/built-ins.d.mts +4 -0
- package/src/lib/expression/built-ins.d.ts +4 -0
- package/src/lib/expression/built-ins.js +8 -0
- package/src/lib/expression/built-ins.js.map +1 -0
- package/src/lib/expression/built-ins.mjs +5 -0
- package/src/lib/expression/built-ins.mjs.map +1 -0
- package/src/lib/expression/evaluator.js +17 -7
- package/src/lib/expression/evaluator.js.map +1 -1
- package/src/lib/expression/evaluator.mjs +17 -7
- package/src/lib/expression/evaluator.mjs.map +1 -1
- package/src/lib/expression/expression.d.mts +7 -0
- package/src/lib/expression/expression.d.ts +7 -0
- package/src/lib/expression/expression.js +2 -0
- package/src/lib/expression/expression.js.map +1 -1
- package/src/lib/expression/expression.mjs +3 -1
- package/src/lib/expression/expression.mjs.map +1 -1
- package/src/lib/expression/functions.d.mts +2 -0
- package/src/lib/expression/functions.d.ts +2 -0
- package/src/lib/expression/functions.js +38 -5
- package/src/lib/expression/functions.js.map +1 -1
- package/src/lib/expression/functions.mjs +38 -5
- package/src/lib/expression/functions.mjs.map +1 -1
- package/src/lib/expression/modifier.d.mts +7 -0
- package/src/lib/expression/modifier.d.ts +7 -0
- package/src/lib/expression/modifier.js +3 -1
- package/src/lib/expression/modifier.js.map +1 -1
- package/src/lib/expression/modifier.mjs +4 -2
- package/src/lib/expression/modifier.mjs.map +1 -1
- package/src/lib/expression/parser.d.mts +8 -1
- package/src/lib/expression/parser.d.ts +8 -1
- package/src/lib/expression/parser.js +30 -2
- package/src/lib/expression/parser.js.map +1 -1
- package/src/lib/expression/parser.mjs +30 -2
- package/src/lib/expression/parser.mjs.map +1 -1
- package/src/lib/expression/reads.d.mts +7 -0
- package/src/lib/expression/reads.d.ts +7 -0
- package/src/lib/expression/reads.js +23 -0
- package/src/lib/expression/reads.js.map +1 -1
- package/src/lib/expression/reads.mjs +21 -0
- package/src/lib/expression/reads.mjs.map +1 -1
- package/src/lib/format/actions.d.mts +1176 -0
- package/src/lib/format/actions.d.ts +1176 -0
- package/src/lib/format/actions.js +62 -0
- package/src/lib/format/actions.js.map +1 -0
- package/src/lib/format/actions.mjs +59 -0
- package/src/lib/format/actions.mjs.map +1 -0
- package/src/lib/format/check-page.d.mts +7 -2
- package/src/lib/format/check-page.d.ts +7 -2
- package/src/lib/format/check-page.js +6 -3
- package/src/lib/format/check-page.js.map +1 -1
- package/src/lib/format/check-page.mjs +6 -3
- package/src/lib/format/check-page.mjs.map +1 -1
- package/src/lib/format/field.d.mts +3285 -214
- package/src/lib/format/field.d.ts +3285 -214
- package/src/lib/format/field.js +105 -16
- package/src/lib/format/field.js.map +1 -1
- package/src/lib/format/field.mjs +104 -15
- package/src/lib/format/field.mjs.map +1 -1
- package/src/lib/format/hotkeys.d.mts +6 -0
- package/src/lib/format/hotkeys.d.ts +6 -0
- package/src/lib/format/hotkeys.js +11 -0
- package/src/lib/format/hotkeys.js.map +1 -0
- package/src/lib/format/hotkeys.mjs +7 -0
- package/src/lib/format/hotkeys.mjs.map +1 -0
- package/src/lib/format/layout.d.mts +4773 -211
- package/src/lib/format/layout.d.ts +4773 -211
- package/src/lib/format/layout.js +147 -21
- package/src/lib/format/layout.js.map +1 -1
- package/src/lib/format/layout.mjs +146 -20
- package/src/lib/format/layout.mjs.map +1 -1
- package/src/lib/format/layout.types.d.mts +2 -1
- package/src/lib/format/layout.types.d.ts +2 -1
- package/src/lib/format/page.d.mts +3563 -222
- package/src/lib/format/page.d.ts +3563 -222
- package/src/lib/format/page.js +19 -2
- package/src/lib/format/page.js.map +1 -1
- package/src/lib/format/page.mjs +20 -3
- package/src/lib/format/page.mjs.map +1 -1
- package/src/lib/format/part-look.d.mts +36 -0
- package/src/lib/format/part-look.d.ts +36 -0
- package/src/lib/format/part-look.js +23 -0
- package/src/lib/format/part-look.js.map +1 -0
- package/src/lib/format/part-look.mjs +20 -0
- package/src/lib/format/part-look.mjs.map +1 -0
- package/src/lib/format/references.d.mts +54 -2
- package/src/lib/format/references.d.ts +54 -2
- package/src/lib/format/references.js +450 -43
- package/src/lib/format/references.js.map +1 -1
- package/src/lib/format/references.mjs +450 -43
- package/src/lib/format/references.mjs.map +1 -1
- package/src/lib/format/translate.js +5 -3
- package/src/lib/format/translate.js.map +1 -1
- package/src/lib/format/translate.mjs +5 -3
- package/src/lib/format/translate.mjs.map +1 -1
- package/src/lib/format/words.d.mts +9 -0
- package/src/lib/format/words.d.ts +9 -0
- package/src/lib/format/words.js +35 -0
- package/src/lib/format/words.js.map +1 -0
- package/src/lib/format/words.mjs +30 -0
- package/src/lib/format/words.mjs.map +1 -0
- package/src/lib/record/cells.d.mts +37 -0
- package/src/lib/record/cells.d.ts +37 -0
- package/src/lib/record/cells.js +59 -0
- package/src/lib/record/cells.js.map +1 -0
- package/src/lib/record/cells.mjs +54 -0
- package/src/lib/record/cells.mjs.map +1 -0
- package/src/lib/record/compute.d.mts +5 -4
- package/src/lib/record/compute.d.ts +5 -4
- package/src/lib/record/compute.js +11 -10
- package/src/lib/record/compute.js.map +1 -1
- package/src/lib/record/compute.mjs +12 -11
- package/src/lib/record/compute.mjs.map +1 -1
- package/src/lib/record/data-source.d.mts +37 -3
- package/src/lib/record/data-source.d.ts +37 -3
- package/src/lib/record/data-source.js.map +1 -1
- package/src/lib/record/data-source.mjs.map +1 -1
- package/src/lib/record/env.d.mts +38 -1
- package/src/lib/record/env.d.ts +38 -1
- package/src/lib/record/env.js +41 -3
- package/src/lib/record/env.js.map +1 -1
- package/src/lib/record/env.mjs +38 -3
- package/src/lib/record/env.mjs.map +1 -1
- package/src/lib/record/filter.d.mts +10 -0
- package/src/lib/record/filter.d.ts +10 -0
- package/src/lib/record/filter.js +49 -0
- package/src/lib/record/filter.js.map +1 -1
- package/src/lib/record/filter.mjs +48 -0
- package/src/lib/record/filter.mjs.map +1 -1
- package/src/lib/record/form.d.mts +226 -25
- package/src/lib/record/form.d.ts +226 -25
- package/src/lib/record/form.js +785 -83
- package/src/lib/record/form.js.map +1 -1
- package/src/lib/record/form.mjs +787 -85
- package/src/lib/record/form.mjs.map +1 -1
- package/src/lib/record/locales/ar.js +3 -0
- package/src/lib/record/locales/ar.js.map +1 -1
- package/src/lib/record/locales/ar.mjs +3 -0
- package/src/lib/record/locales/ar.mjs.map +1 -1
- package/src/lib/record/locales/de.js +3 -0
- package/src/lib/record/locales/de.js.map +1 -1
- package/src/lib/record/locales/de.mjs +3 -0
- package/src/lib/record/locales/de.mjs.map +1 -1
- package/src/lib/record/locales/fr.js +3 -0
- package/src/lib/record/locales/fr.js.map +1 -1
- package/src/lib/record/locales/fr.mjs +3 -0
- package/src/lib/record/locales/fr.mjs.map +1 -1
- package/src/lib/record/memory-data-source.d.mts +26 -2
- package/src/lib/record/memory-data-source.d.ts +26 -2
- package/src/lib/record/memory-data-source.js +98 -7
- package/src/lib/record/memory-data-source.js.map +1 -1
- package/src/lib/record/memory-data-source.mjs +98 -7
- package/src/lib/record/memory-data-source.mjs.map +1 -1
- package/src/lib/record/messages.d.mts +5 -0
- package/src/lib/record/messages.d.ts +5 -0
- package/src/lib/record/messages.js +3 -0
- package/src/lib/record/messages.js.map +1 -1
- package/src/lib/record/messages.mjs +3 -0
- package/src/lib/record/messages.mjs.map +1 -1
- package/src/lib/record/roles.d.mts +10 -0
- package/src/lib/record/roles.d.ts +10 -0
- package/src/lib/record/roles.js +21 -0
- package/src/lib/record/roles.js.map +1 -0
- package/src/lib/record/roles.mjs +18 -0
- package/src/lib/record/roles.mjs.map +1 -0
- package/src/lib/record/rules.js +30 -0
- package/src/lib/record/rules.js.map +1 -1
- package/src/lib/record/rules.mjs +31 -1
- package/src/lib/record/rules.mjs.map +1 -1
- package/src/lib/record/run.d.mts +248 -0
- package/src/lib/record/run.d.ts +248 -0
- package/src/lib/record/run.js +455 -0
- package/src/lib/record/run.js.map +1 -0
- package/src/lib/record/run.mjs +450 -0
- package/src/lib/record/run.mjs.map +1 -0
- package/src/lib/record/set-when.d.mts +5 -2
- package/src/lib/record/set-when.d.ts +5 -2
- package/src/lib/record/set-when.js +28 -12
- package/src/lib/record/set-when.js.map +1 -1
- package/src/lib/record/set-when.mjs +30 -14
- package/src/lib/record/set-when.mjs.map +1 -1
- package/src/lib/record/value-map.d.mts +41 -0
- package/src/lib/record/value-map.d.ts +41 -0
- package/src/lib/record/value-map.js +80 -0
- package/src/lib/record/value-map.js.map +1 -0
- package/src/lib/record/value-map.mjs +73 -0
- package/src/lib/record/value-map.mjs.map +1 -0
- package/src/lib/record/values.d.mts +10 -0
- package/src/lib/record/values.d.ts +10 -0
- package/src/lib/record/values.js.map +1 -1
- package/src/lib/record/values.mjs.map +1 -1
- package/src/runtime.d.mts +11 -4
- package/src/runtime.d.ts +11 -4
- package/src/runtime.js +13 -1
- package/src/runtime.js.map +1 -1
- package/src/runtime.mjs +4 -0
- package/src/runtime.mjs.map +1 -1
package/src/lib/record/filter.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.matchesFilter = matchesFilter;
|
|
4
|
+
exports.resolveFilter = resolveFilter;
|
|
4
5
|
/**
|
|
5
6
|
* Whether a record passes a filter, the way a search should judge it: every
|
|
6
7
|
* item of the list holds, an `any` group when one of its items holds, an `all`
|
|
@@ -20,6 +21,12 @@ function holds(values, item) {
|
|
|
20
21
|
function isSet(value) {
|
|
21
22
|
return value !== null && value !== undefined && value !== '' && value !== false && !(Array.isArray(value) && !value.length);
|
|
22
23
|
}
|
|
24
|
+
/** The ids a list of links holds: records by their id, ids as they are. */
|
|
25
|
+
function idsIn(value) {
|
|
26
|
+
if (!Array.isArray(value))
|
|
27
|
+
return [];
|
|
28
|
+
return value.map((item) => (item !== null && typeof item === 'object' && 'id' in item ? item.id : item));
|
|
29
|
+
}
|
|
23
30
|
function meets(values, condition) {
|
|
24
31
|
const raw = values[condition.field];
|
|
25
32
|
// A link compares by its id.
|
|
@@ -30,6 +37,15 @@ function meets(values, condition) {
|
|
|
30
37
|
switch (condition.op) {
|
|
31
38
|
case '=':
|
|
32
39
|
return actual === expected;
|
|
40
|
+
case '=?':
|
|
41
|
+
return !isSet(expected) || actual === expected;
|
|
42
|
+
case 'contains':
|
|
43
|
+
case 'not contains': {
|
|
44
|
+
const held = idsIn(raw);
|
|
45
|
+
const wanted = Array.isArray(expected) ? expected : [expected];
|
|
46
|
+
const found = wanted.some((value) => held.includes(value));
|
|
47
|
+
return condition.op === 'contains' ? found : !found;
|
|
48
|
+
}
|
|
33
49
|
case '!=':
|
|
34
50
|
return actual !== expected;
|
|
35
51
|
case '<':
|
|
@@ -64,4 +80,37 @@ function meets(values, condition) {
|
|
|
64
80
|
}
|
|
65
81
|
}
|
|
66
82
|
}
|
|
83
|
+
/** What a condition left out stands for: it always holds. */
|
|
84
|
+
const ALWAYS = null;
|
|
85
|
+
/**
|
|
86
|
+
* A filter as a search or a list receives it: each `valueFrom` — a field, or a
|
|
87
|
+
* path such as `parent.company_id` or `user.id` — replaced by its value in
|
|
88
|
+
* `context`. A `=?` whose value is empty is left out, and so is a group it
|
|
89
|
+
* makes always hold: an `any` group with one item always holding, an `all`
|
|
90
|
+
* group left with none. A `=?` with a value goes as `=`, so a data source
|
|
91
|
+
* never sees `=?`.
|
|
92
|
+
*/
|
|
93
|
+
function resolveFilter(items, context) {
|
|
94
|
+
const resolve = (item) => {
|
|
95
|
+
if ('any' in item) {
|
|
96
|
+
const inner = item.any.map(resolve);
|
|
97
|
+
return inner.includes(ALWAYS) ? ALWAYS : { any: inner };
|
|
98
|
+
}
|
|
99
|
+
if ('all' in item) {
|
|
100
|
+
const inner = item.all.map(resolve).filter((r) => r !== ALWAYS);
|
|
101
|
+
return inner.length ? { all: inner } : ALWAYS;
|
|
102
|
+
}
|
|
103
|
+
const value = (item.valueFrom !== undefined ? valueAt(context, item.valueFrom) : (item.value ?? null));
|
|
104
|
+
if (item.op === '=?')
|
|
105
|
+
return isSet(value) ? { field: item.field, op: '=', value } : ALWAYS;
|
|
106
|
+
return { field: item.field, op: item.op, value };
|
|
107
|
+
};
|
|
108
|
+
return items.map(resolve).filter((r) => r !== ALWAYS);
|
|
109
|
+
}
|
|
110
|
+
function valueAt(context, path) {
|
|
111
|
+
let at = context;
|
|
112
|
+
for (const part of path.split('.'))
|
|
113
|
+
at = at === null || typeof at !== 'object' ? undefined : at[part];
|
|
114
|
+
return at ?? null;
|
|
115
|
+
}
|
|
67
116
|
//# sourceMappingURL=filter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/filter.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,12 @@ function holds(values, item) {
|
|
|
17
17
|
function isSet(value) {
|
|
18
18
|
return value !== null && value !== undefined && value !== '' && value !== false && !(Array.isArray(value) && !value.length);
|
|
19
19
|
}
|
|
20
|
+
/** The ids a list of links holds: records by their id, ids as they are. */
|
|
21
|
+
function idsIn(value) {
|
|
22
|
+
if (!Array.isArray(value))
|
|
23
|
+
return [];
|
|
24
|
+
return value.map((item) => (item !== null && typeof item === 'object' && 'id' in item ? item.id : item));
|
|
25
|
+
}
|
|
20
26
|
function meets(values, condition) {
|
|
21
27
|
const raw = values[condition.field];
|
|
22
28
|
// A link compares by its id.
|
|
@@ -27,6 +33,15 @@ function meets(values, condition) {
|
|
|
27
33
|
switch (condition.op) {
|
|
28
34
|
case '=':
|
|
29
35
|
return actual === expected;
|
|
36
|
+
case '=?':
|
|
37
|
+
return !isSet(expected) || actual === expected;
|
|
38
|
+
case 'contains':
|
|
39
|
+
case 'not contains': {
|
|
40
|
+
const held = idsIn(raw);
|
|
41
|
+
const wanted = Array.isArray(expected) ? expected : [expected];
|
|
42
|
+
const found = wanted.some((value) => held.includes(value));
|
|
43
|
+
return condition.op === 'contains' ? found : !found;
|
|
44
|
+
}
|
|
30
45
|
case '!=':
|
|
31
46
|
return actual !== expected;
|
|
32
47
|
case '<':
|
|
@@ -61,4 +76,37 @@ function meets(values, condition) {
|
|
|
61
76
|
}
|
|
62
77
|
}
|
|
63
78
|
}
|
|
79
|
+
/** What a condition left out stands for: it always holds. */
|
|
80
|
+
const ALWAYS = null;
|
|
81
|
+
/**
|
|
82
|
+
* A filter as a search or a list receives it: each `valueFrom` — a field, or a
|
|
83
|
+
* path such as `parent.company_id` or `user.id` — replaced by its value in
|
|
84
|
+
* `context`. A `=?` whose value is empty is left out, and so is a group it
|
|
85
|
+
* makes always hold: an `any` group with one item always holding, an `all`
|
|
86
|
+
* group left with none. A `=?` with a value goes as `=`, so a data source
|
|
87
|
+
* never sees `=?`.
|
|
88
|
+
*/
|
|
89
|
+
export function resolveFilter(items, context) {
|
|
90
|
+
const resolve = (item) => {
|
|
91
|
+
if ('any' in item) {
|
|
92
|
+
const inner = item.any.map(resolve);
|
|
93
|
+
return inner.includes(ALWAYS) ? ALWAYS : { any: inner };
|
|
94
|
+
}
|
|
95
|
+
if ('all' in item) {
|
|
96
|
+
const inner = item.all.map(resolve).filter((r) => r !== ALWAYS);
|
|
97
|
+
return inner.length ? { all: inner } : ALWAYS;
|
|
98
|
+
}
|
|
99
|
+
const value = (item.valueFrom !== undefined ? valueAt(context, item.valueFrom) : (item.value ?? null));
|
|
100
|
+
if (item.op === '=?')
|
|
101
|
+
return isSet(value) ? { field: item.field, op: '=', value } : ALWAYS;
|
|
102
|
+
return { field: item.field, op: item.op, value };
|
|
103
|
+
};
|
|
104
|
+
return items.map(resolve).filter((r) => r !== ALWAYS);
|
|
105
|
+
}
|
|
106
|
+
function valueAt(context, path) {
|
|
107
|
+
let at = context;
|
|
108
|
+
for (const part of path.split('.'))
|
|
109
|
+
at = at === null || typeof at !== 'object' ? undefined : at[part];
|
|
110
|
+
return at ?? null;
|
|
111
|
+
}
|
|
64
112
|
//# sourceMappingURL=filter.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/filter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"filter.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/filter.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,MAAiC;IAC7E,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,KAAK,CAAC,MAAc,EAAE,IAAoB;IACjD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACzE,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1E,OAAO,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,6DAA6D;AAC7D,SAAS,KAAK,CAAC,KAAc;IAC3B,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC9H,CAAC;AAED,2EAA2E;AAC3E,SAAS,KAAK,CAAC,KAAc;IAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAE,IAAsB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9H,CAAC;AAED,SAAS,KAAK,CAAC,MAAc,EAAE,SAAkC;IAC/D,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACpC,6BAA6B;IAC7B,MAAM,MAAM,GAAG,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,CAAE,GAAqB,CAAC,EAAE,CAAC,CAAC,CAAE,GAA6B,CAAC;IAC1J,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC;IACjC,iEAAiE;IACjE,MAAM,IAAI,GAAG,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAE,GAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAC5J,QAAQ,SAAS,CAAC,EAAE,EAAE,CAAC;QACrB,KAAK,GAAG;YACN,OAAO,MAAM,KAAK,QAAQ,CAAC;QAC7B,KAAK,IAAI;YACP,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,MAAM,KAAK,QAAQ,CAAC;QACjD,KAAK,UAAU,CAAC;QAChB,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YACxB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3D,OAAO,SAAS,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACtD,CAAC;QACD,KAAK,IAAI;YACP,OAAO,MAAM,KAAK,QAAQ,CAAC;QAC7B,KAAK,GAAG;YACN,OAAO,KAAK,CAAC,MAAM,CAAC,IAAK,MAAiB,GAAI,QAAmB,CAAC;QACpE,KAAK,GAAG;YACN,OAAO,KAAK,CAAC,MAAM,CAAC,IAAK,MAAiB,GAAI,QAAmB,CAAC;QACpE,KAAK,IAAI;YACP,OAAO,KAAK,CAAC,MAAM,CAAC,IAAK,MAAiB,IAAK,QAAmB,CAAC;QACrE,KAAK,IAAI;YACP,OAAO,KAAK,CAAC,MAAM,CAAC,IAAK,MAAiB,IAAK,QAAmB,CAAC;QACrE,KAAK,IAAI;YACP,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAmB,CAAC,CAAC;QAC3E,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAmB,CAAC,CAAC;QAC5E,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzC,KAAK,OAAO;YACV,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACrE,KAAK,YAAY;YACf,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACvE,KAAK,UAAU;YACb,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACrE,KAAK,KAAK;YACR,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC;QACpB,KAAK,QAAQ;YACX,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC7D,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,QAA+B,CAAC;YACpD,OAAQ,MAA0B,IAAI,GAAG,IAAK,MAA0B,IAAI,IAAI,CAAC;QACnF,CAAC;IACH,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,MAAM,MAAM,GAAG,IAAI,CAAC;AAEpB;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,KAA4B,EAAE,OAA0C;IACpG,MAAM,OAAO,GAAG,CAAC,IAAgB,EAAkC,EAAE;QACnE,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACpC,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAyB,EAAE,CAAC;QAC9E,CAAC;QACD,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAuB,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;YACrF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAChD,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAc,CAAC;QACpH,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3F,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;IACnD,CAAC,CAAC;IACF,OAAO,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAuB,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,OAAO,CAAC,OAA0C,EAAE,IAAY;IACvE,IAAI,EAAE,GAAY,OAAO,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,EAAE,GAAG,EAAE,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,EAA8B,CAAC,IAAI,CAAC,CAAC;IACnI,OAAO,EAAE,IAAI,IAAI,CAAC;AACpB,CAAC"}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { ActionStep } from '../format/actions.mjs';
|
|
2
|
+
import type { Field, LineField, Option, PropertyDefinition } from '../format/field.mjs';
|
|
3
3
|
import type { Page } from '../format/page.mjs';
|
|
4
|
+
import type { JsonValue } from '../format/json.mjs';
|
|
5
|
+
import { type FieldTone, type LineState } from './cells.mjs';
|
|
4
6
|
import { type Messages } from './messages.mjs';
|
|
5
7
|
import { type DataSource, type RecordChanges, type SaveProblem } from './data-source.mjs';
|
|
6
8
|
import { type Scheduler } from './scheduler.mjs';
|
|
9
|
+
import { type ActionHost, type ActionRequest, type ActionResult, type OnAction, type PostedMessage, type RunContext, type RunResult } from './run.mjs';
|
|
7
10
|
import { type RecordId, type RelatedRecord, type Value, type Values } from './values.mjs';
|
|
8
11
|
export type FormStatus = 'idle' | 'loading' | 'ready' | 'saving' | 'saved' | 'error';
|
|
9
12
|
export interface FormState {
|
|
10
13
|
readonly status: FormStatus;
|
|
11
14
|
readonly recordId: RecordId | null;
|
|
12
15
|
readonly values: Readonly<Values>;
|
|
13
|
-
/** Messages by field name; a line's field is `field.lineKey.subfield`. */
|
|
16
|
+
/** Messages by field name; a line's field is `field.lineKey.subfield`, a saved form's field `name.field`. */
|
|
14
17
|
readonly errors: Readonly<Record<string, string>>;
|
|
15
18
|
/** Fields that differ from the record as loaded or last saved. */
|
|
16
19
|
readonly dirty: readonly string[];
|
|
@@ -37,6 +40,16 @@ export interface FormState {
|
|
|
37
40
|
readonly saveProblem: SaveProblem | null;
|
|
38
41
|
/** The choices loaded from the app's lists, by field: those of a selection with `optionsFrom`, once asked for. */
|
|
39
42
|
readonly choices: Readonly<Record<string, Choices>>;
|
|
43
|
+
/** The definitions loaded for a properties field with `definitionsFrom`, by field, once asked for. */
|
|
44
|
+
readonly definitions: Readonly<Record<string, Definitions>>;
|
|
45
|
+
}
|
|
46
|
+
/** A properties field's definitions from the app, as they load. */
|
|
47
|
+
export interface Definitions {
|
|
48
|
+
/** The definitions last loaded: null until the first load ends well. */
|
|
49
|
+
readonly definitions: PropertyDefinition[] | null;
|
|
50
|
+
readonly loading?: boolean;
|
|
51
|
+
/** Why the last load failed. */
|
|
52
|
+
readonly error?: string;
|
|
40
53
|
}
|
|
41
54
|
/** A field's choices from one of the app's lists, as they load. */
|
|
42
55
|
export interface Choices {
|
|
@@ -58,17 +71,69 @@ export interface DraftStore {
|
|
|
58
71
|
setItem(key: string, value: string): void;
|
|
59
72
|
removeItem(key: string): void;
|
|
60
73
|
}
|
|
61
|
-
export
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
export type { ActionRequest } from './run.mjs';
|
|
75
|
+
/** Whose change it was: a person's (in the UI), a step's, or the app's (`setValues`, or `setValue` told so). Only a person's runs the page's `change` steps. */
|
|
76
|
+
export type ChangeBy = 'person' | 'step' | 'app';
|
|
77
|
+
/** What a form tells the app, by event: `form.on(event, listener)`. */
|
|
78
|
+
export interface FormEvents {
|
|
79
|
+
/** A field was written: by a person, a step or the app. Values worked out from it are not told. */
|
|
80
|
+
change: {
|
|
81
|
+
field: string;
|
|
82
|
+
value: Value;
|
|
83
|
+
values: Readonly<Values>;
|
|
84
|
+
by: ChangeBy;
|
|
85
|
+
};
|
|
86
|
+
/** A record was saved. */
|
|
87
|
+
save: {
|
|
88
|
+
recordId: RecordId | null;
|
|
89
|
+
values: Readonly<Values>;
|
|
90
|
+
};
|
|
91
|
+
/** A page of responses sent its answers: those sent. */
|
|
92
|
+
send: {
|
|
93
|
+
values: Values;
|
|
94
|
+
};
|
|
95
|
+
/** The app answered a call: with nothing (undefined), or an `ActionResult`. */
|
|
96
|
+
action: {
|
|
97
|
+
request: ActionRequest;
|
|
98
|
+
result: ActionResult | undefined;
|
|
99
|
+
};
|
|
100
|
+
/** A run of steps ended — a button's, a moment's, `form.run`'s — and how. */
|
|
101
|
+
run: {
|
|
102
|
+
id: string;
|
|
103
|
+
steps: readonly ActionStep[];
|
|
104
|
+
result: RunResult;
|
|
105
|
+
};
|
|
106
|
+
/** A wizard's step was entered. */
|
|
107
|
+
step: {
|
|
108
|
+
step: string;
|
|
109
|
+
};
|
|
110
|
+
/** The form has its values: loaded, or new. */
|
|
111
|
+
open: {
|
|
112
|
+
recordId: RecordId | null;
|
|
113
|
+
values: Readonly<Values>;
|
|
114
|
+
};
|
|
115
|
+
/** The record was archived (`archived` true) or brought back, by a step. */
|
|
116
|
+
archive: {
|
|
117
|
+
recordId: RecordId;
|
|
118
|
+
archived: boolean;
|
|
119
|
+
};
|
|
120
|
+
/** The record was copied, by a step: the form shows the copy now. */
|
|
121
|
+
duplicate: {
|
|
122
|
+
from: RecordId;
|
|
123
|
+
recordId: RecordId;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* The record was deleted, by a step. A listener may show another record
|
|
127
|
+
* (`openRecord`), as a pager moves on; else the form starts a new one.
|
|
128
|
+
*/
|
|
129
|
+
delete: {
|
|
130
|
+
recordId: RecordId;
|
|
131
|
+
};
|
|
132
|
+
/** Words to post in the record's conversation, from a `post` step or the app's answer: the chatter beside it listens. */
|
|
133
|
+
post: {
|
|
134
|
+
recordId: RecordId | null;
|
|
135
|
+
message: PostedMessage;
|
|
67
136
|
};
|
|
68
|
-
recordId: RecordId | null;
|
|
69
|
-
values: Values;
|
|
70
|
-
/** The records chosen in a list, when the button belongs to one. */
|
|
71
|
-
recordIds?: RecordId[];
|
|
72
137
|
}
|
|
73
138
|
export interface FormOptions {
|
|
74
139
|
page: Page;
|
|
@@ -77,8 +142,17 @@ export interface FormOptions {
|
|
|
77
142
|
recordId?: RecordId | null;
|
|
78
143
|
/** Values to start with, on top of each field's default. */
|
|
79
144
|
values?: Values;
|
|
80
|
-
/**
|
|
81
|
-
|
|
145
|
+
/**
|
|
146
|
+
* The app's own actions: a button's `action`, and each `call` step. Fieldia
|
|
147
|
+
* hands the request over and waits; the app may answer (`ActionResult`)
|
|
148
|
+
* with values to set, words to say, a page to open, or to stop. Nothing
|
|
149
|
+
* answered means go on.
|
|
150
|
+
*/
|
|
151
|
+
onAction?: OnAction;
|
|
152
|
+
/** The UI the core cannot draw — pages opened, words said, questions asked — given by the viewer. */
|
|
153
|
+
host?: ActionHost;
|
|
154
|
+
/** How a question is asked when there is no host. Without either, a question goes on as though answered Yes. */
|
|
155
|
+
confirm?: (message: string) => boolean | Promise<boolean>;
|
|
82
156
|
drafts?: {
|
|
83
157
|
store: DraftStore;
|
|
84
158
|
restore?: 'auto' | 'ask';
|
|
@@ -92,14 +166,55 @@ export interface FormOptions {
|
|
|
92
166
|
messages?: Messages;
|
|
93
167
|
/** The clock, for `today()` and for dates that must be past or future. The computer's own when left out. */
|
|
94
168
|
now?: () => Date;
|
|
169
|
+
/**
|
|
170
|
+
* The person using the form: conditions read it as `user` (`user.id`,
|
|
171
|
+
* `user.name`, `user.roles`), and a part with `roles` shows only to people
|
|
172
|
+
* in them. Left out, the person has no id and no roles.
|
|
173
|
+
*/
|
|
174
|
+
user?: FormUser;
|
|
175
|
+
/** Whether the record starts being edited, as conditions read `editing`; true unless said. A view locking it says so with `setEditing`. */
|
|
176
|
+
editing?: boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Values the app passes in, as Flectra's context: read by conditions and
|
|
179
|
+
* expressions as `context.name`, and by a filter's `valueFrom:
|
|
180
|
+
* "context.name"` — a transfer opened from Receipts restricting its
|
|
181
|
+
* operation types. They are the app's, never the page's: nothing saves
|
|
182
|
+
* them, and a page's field of that name comes first.
|
|
183
|
+
*/
|
|
184
|
+
context?: Readonly<Record<string, JsonValue>>;
|
|
185
|
+
/**
|
|
186
|
+
* The record this form's values are a line of, when the form edits one
|
|
187
|
+
* table's line in a form of its own (a node's `lineForm`): its values and
|
|
188
|
+
* fields, read by conditions and filters as `parent`, as a line's are —
|
|
189
|
+
* `parent.state`, a filter's `valueFrom: "parent.company_id"`.
|
|
190
|
+
*/
|
|
191
|
+
parent?: {
|
|
192
|
+
values: Readonly<Values>;
|
|
193
|
+
fields: Readonly<Record<string, Field | LineField>>;
|
|
194
|
+
id?: RecordId | null;
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/** The person using a form, as the app knows them. */
|
|
198
|
+
export interface FormUser {
|
|
199
|
+
id: RecordId | null;
|
|
200
|
+
name?: string;
|
|
201
|
+
/** The roles they hold, by the names the page's `roles` use: Flectra's groups, such as `sales_team.group_sale_manager`. */
|
|
202
|
+
roles?: readonly string[];
|
|
95
203
|
}
|
|
96
204
|
export interface Form {
|
|
97
205
|
readonly page: Page;
|
|
98
206
|
getState(): FormState;
|
|
99
207
|
subscribe(listener: (state: FormState) => void): () => void;
|
|
100
208
|
load(): Promise<void>;
|
|
101
|
-
|
|
209
|
+
/** Write a field: a person's change unless told otherwise, and only a person's runs the page's `change` steps. */
|
|
210
|
+
setValue(name: string, value: Value, how?: {
|
|
211
|
+
by?: ChangeBy;
|
|
212
|
+
}): void;
|
|
213
|
+
/** Write several fields at once, worked out once: the app's change, never a person's. Throws for a field the page lacks. */
|
|
214
|
+
setValues(values: Values): void;
|
|
102
215
|
node(id: string): NodeState;
|
|
216
|
+
/** Whether the record is being edited, as conditions read `editing`: a view that locks it to be read says false, and parts follow. */
|
|
217
|
+
setEditing(editing: boolean): void;
|
|
103
218
|
fieldReadonly(name: string): boolean;
|
|
104
219
|
/** What a field would be told if the form were checked now, or null when it passes. Nothing is shown. */
|
|
105
220
|
problem(field: string): string | null;
|
|
@@ -118,25 +233,68 @@ export interface Form {
|
|
|
118
233
|
* written: the record, its changes and its autosave stay as they are.
|
|
119
234
|
*/
|
|
120
235
|
previewLine(field: string, key: string, values: Values): Promise<Values>;
|
|
236
|
+
/**
|
|
237
|
+
* Show another record of the page's model in this form, loaded from the
|
|
238
|
+
* data source as a pager moves to it, or a new one for null. Changes not
|
|
239
|
+
* saved are dropped: save first. The page's `open` steps run for it.
|
|
240
|
+
*/
|
|
241
|
+
openRecord(id: RecordId | null): Promise<void>;
|
|
242
|
+
/**
|
|
243
|
+
* Post words in the record's conversation, as a `post` step does: through
|
|
244
|
+
* the form's host when it has a way to, else told to the form's own
|
|
245
|
+
* listeners (`post`). False when nothing heard them.
|
|
246
|
+
*/
|
|
247
|
+
post(message: PostedMessage): Promise<boolean>;
|
|
121
248
|
/**
|
|
122
249
|
* Load, or load again, the choices of a selection whose options come from
|
|
123
250
|
* the app's list (`optionsFrom`). Once loaded, they load again by themselves
|
|
124
251
|
* when a field they change with changes; the latest answer wins.
|
|
125
252
|
*/
|
|
126
253
|
loadChoices(field: string): void;
|
|
127
|
-
/**
|
|
254
|
+
/**
|
|
255
|
+
* Load, or load again, the definitions of a properties field whose
|
|
256
|
+
* definitions come from a linked record (`definitionsFrom`). Once loaded,
|
|
257
|
+
* they load again by themselves when a field they change with changes.
|
|
258
|
+
*/
|
|
259
|
+
loadDefinitions(field: string): void;
|
|
260
|
+
/** A property added in place to such a field: kept in its definitions, and handed to the data source's `saveDefinitions`. */
|
|
261
|
+
addDefinition(field: string, definition: PropertyDefinition): Promise<void>;
|
|
262
|
+
/**
|
|
263
|
+
* Records a many2one, many2many or reference may point to. A reference needs
|
|
264
|
+
* `options.model`, and so does structured data naming records of a model (a
|
|
265
|
+
* json field, such as an analytic distribution's accounts); `options.ids`
|
|
266
|
+
* finds those records alone, for their names.
|
|
267
|
+
*/
|
|
128
268
|
search(field: string, query: string, limit?: number, options?: {
|
|
129
269
|
model?: string;
|
|
270
|
+
ids?: RecordId[];
|
|
130
271
|
}): Promise<RelatedRecord[]>;
|
|
131
|
-
/** The same, for a relation inside a one2many line, filtered by that line's values. */
|
|
132
|
-
searchLine(field: string, key: string, subfield: string, query: string, limit?: number
|
|
272
|
+
/** The same, for a relation inside a one2many line, filtered by that line's values — or structured data of a line naming records of a model (`options.model`). */
|
|
273
|
+
searchLine(field: string, key: string, subfield: string, query: string, limit?: number, options?: {
|
|
274
|
+
model?: string;
|
|
275
|
+
ids?: RecordId[];
|
|
276
|
+
}): Promise<RelatedRecord[]>;
|
|
277
|
+
/**
|
|
278
|
+
* The values of records a many2many links to, for a table of them: `fields`
|
|
279
|
+
* of the records with these ids, in the order asked, read with the data
|
|
280
|
+
* source's `list`. None without one.
|
|
281
|
+
*/
|
|
282
|
+
linkedValues(field: string, ids: readonly RecordId[], fields: readonly string[]): Promise<{
|
|
283
|
+
id: RecordId;
|
|
284
|
+
values: Values;
|
|
285
|
+
}[]>;
|
|
133
286
|
/** Whether a link field can make a record from a typed name: the data source must be able to. */
|
|
134
287
|
canCreate(field: string): boolean;
|
|
135
|
-
/** Make a record from a typed name, for the link field to point to. */
|
|
288
|
+
/** Make a record from a typed name, for the link field to point to, with what its `createValues` hand on. */
|
|
136
289
|
quickCreate(field: string, name: string): Promise<RelatedRecord>;
|
|
137
|
-
/** The same, for a link inside a one2many's lines. */
|
|
290
|
+
/** The same, for a link inside a one2many's lines; with the line's key, its `createValues` are read on that line. */
|
|
138
291
|
canCreateLine(field: string, subfield: string): boolean;
|
|
139
|
-
quickCreateLine(field: string, subfield: string, name: string): Promise<RelatedRecord>;
|
|
292
|
+
quickCreateLine(field: string, subfield: string, name: string, key?: string): Promise<RelatedRecord>;
|
|
293
|
+
/** What a record made from a link starts with besides its name: its `createValues`, read now — on a line, on that line. */
|
|
294
|
+
createValues(field: string, line?: {
|
|
295
|
+
lines: string;
|
|
296
|
+
key: string;
|
|
297
|
+
}): Values;
|
|
140
298
|
steps(): string[];
|
|
141
299
|
next(): boolean;
|
|
142
300
|
back(): boolean;
|
|
@@ -148,14 +306,57 @@ export interface Form {
|
|
|
148
306
|
* an optional one instead.
|
|
149
307
|
*/
|
|
150
308
|
goTo(step: string): boolean;
|
|
151
|
-
/**
|
|
309
|
+
/**
|
|
310
|
+
* Press a button: ask its `confirm` first, run its `steps`, then call its
|
|
311
|
+
* `action`, when it names one, as a final `call`. A list's button passes
|
|
312
|
+
* the records chosen in it, and every call of the run carries them.
|
|
313
|
+
*/
|
|
152
314
|
runAction(id: string, chosen?: {
|
|
153
315
|
recordIds: RecordId[];
|
|
154
|
-
}): Promise<
|
|
316
|
+
}): Promise<RunResult>;
|
|
317
|
+
/** A field's own value as its tones have it now: its tone and whether it is bold, read on the record. */
|
|
318
|
+
fieldTone(nodeId: string): FieldTone;
|
|
319
|
+
/** A table's line as its rules have it now — its tone, each ruled column's cells, which of its buttons show — by the table's field node. */
|
|
320
|
+
lineState(nodeId: string, key: string): LineState;
|
|
321
|
+
/** Whether a table's column is hidden now by its `hidden` rule, read on the record. */
|
|
322
|
+
columnHidden(nodeId: string, column: string): boolean;
|
|
323
|
+
/**
|
|
324
|
+
* The words a field's empty box shows now, by its node (`#title` for a
|
|
325
|
+
* sheet's title): its first `placeholderWhen` that holds, else its
|
|
326
|
+
* `placeholder`; undefined when it has neither.
|
|
327
|
+
*/
|
|
328
|
+
placeholder(nodeId: string): string | undefined;
|
|
329
|
+
/** Press a button on a table's line: its confirmation, its steps, then its action, each call carrying the line. Hidden on that line, it does not run. */
|
|
330
|
+
runRowAction(nodeId: string, buttonId: string, key: string): Promise<RunResult>;
|
|
331
|
+
/**
|
|
332
|
+
* Press a button for the lines chosen in a table (its `selectedButtons`),
|
|
333
|
+
* by their keys: its confirmation, its steps, then its action, each call
|
|
334
|
+
* carrying the lines. Hidden, or with no line chosen, it does not run.
|
|
335
|
+
*/
|
|
336
|
+
runLinesAction(nodeId: string, buttonId: string, keys: readonly string[]): Promise<RunResult>;
|
|
337
|
+
/** Run steps on this form, as a button would: `context.id` is what their calls carry (`run` when left out). */
|
|
338
|
+
run(steps: readonly ActionStep[], context?: RunContext): Promise<RunResult>;
|
|
339
|
+
/** A tab was shown: the viewer says so, and the page's `show` steps for it run. */
|
|
340
|
+
shown(tab: string): void;
|
|
341
|
+
/** Listen to one of the form's events; returns what stops listening. */
|
|
342
|
+
on<E extends keyof FormEvents>(event: E, listener: (event: FormEvents[E]) => void): () => void;
|
|
155
343
|
restoreDraft(): void;
|
|
156
344
|
discardDraft(): void;
|
|
157
|
-
/** Resolves once every onchange, save and
|
|
345
|
+
/** Resolves once every onchange, save, autosave and run of steps started so far has finished — a question still waiting for its answer included. */
|
|
158
346
|
settled(): Promise<void>;
|
|
347
|
+
/**
|
|
348
|
+
* Give a saved form placed on this page (a `form` part, by its id) its page,
|
|
349
|
+
* once the app has found it. From then its answers sit under the part's
|
|
350
|
+
* name as an object, checked by that page's own rules: this form refuses
|
|
351
|
+
* to save or send while one of them fails, with the error under
|
|
352
|
+
* `name.field`, and shows it on the inner form beside its field. Returns the
|
|
353
|
+
* inner form, which a view draws the part's fields from; giving the page
|
|
354
|
+
* again returns the same one. A page placed inside itself, directly or
|
|
355
|
+
* through others, is refused.
|
|
356
|
+
*/
|
|
357
|
+
embed(id: string, page: Page): Form;
|
|
358
|
+
/** The inner form of a saved form placed on this page, once it has its page; null until then. */
|
|
359
|
+
embedded(id: string): Form | null;
|
|
159
360
|
dispose(): void;
|
|
160
361
|
}
|
|
161
362
|
/**
|