@fieldia/designer 0.28.0 → 0.29.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 +23 -0
- package/package.json +4 -4
- package/src/lib/approval-settings.d.mts +13 -0
- package/src/lib/approval-settings.d.ts +13 -0
- package/src/lib/approval-settings.js +49 -0
- package/src/lib/approval-settings.js.map +1 -0
- package/src/lib/approval-settings.mjs +46 -0
- package/src/lib/approval-settings.mjs.map +1 -0
- package/src/lib/assist-settings.d.mts +12 -0
- package/src/lib/assist-settings.d.ts +12 -0
- package/src/lib/assist-settings.js +64 -0
- package/src/lib/assist-settings.js.map +1 -0
- package/src/lib/assist-settings.mjs +61 -0
- package/src/lib/assist-settings.mjs.map +1 -0
- package/src/lib/bottom-bar.d.mts +22 -0
- package/src/lib/bottom-bar.d.ts +22 -0
- package/src/lib/bottom-bar.js +99 -0
- package/src/lib/bottom-bar.js.map +1 -0
- package/src/lib/bottom-bar.mjs +93 -0
- package/src/lib/bottom-bar.mjs.map +1 -0
- package/src/lib/designer.d.mts +21 -0
- package/src/lib/designer.d.ts +21 -0
- package/src/lib/designer.js +96 -0
- package/src/lib/designer.js.map +1 -1
- package/src/lib/designer.mjs +96 -0
- package/src/lib/designer.mjs.map +1 -1
- package/src/lib/icons.js +2 -0
- package/src/lib/icons.js.map +1 -1
- package/src/lib/icons.mjs +2 -0
- package/src/lib/icons.mjs.map +1 -1
- package/src/lib/inline-settings.js +9 -2
- package/src/lib/inline-settings.js.map +1 -1
- package/src/lib/inline-settings.mjs +9 -2
- package/src/lib/inline-settings.mjs.map +1 -1
- package/src/lib/input-changes.js +11 -0
- package/src/lib/input-changes.js.map +1 -1
- package/src/lib/input-changes.mjs +11 -0
- package/src/lib/input-changes.mjs.map +1 -1
- package/src/lib/input-commands.d.mts +11 -0
- package/src/lib/input-commands.d.ts +11 -0
- package/src/lib/input-commands.js +58 -0
- package/src/lib/input-commands.js.map +1 -1
- package/src/lib/input-commands.mjs +58 -0
- package/src/lib/input-commands.mjs.map +1 -1
- package/src/lib/kind-settings-inputs.d.mts +2 -0
- package/src/lib/kind-settings-inputs.d.ts +2 -0
- package/src/lib/kind-settings-inputs.js +97 -0
- package/src/lib/kind-settings-inputs.js.map +1 -1
- package/src/lib/kind-settings-inputs.mjs +96 -0
- package/src/lib/kind-settings-inputs.mjs.map +1 -1
- package/src/lib/kind-settings-structures.d.mts +2 -2
- package/src/lib/kind-settings-structures.d.ts +2 -2
- package/src/lib/kind-settings-structures.js +34 -0
- package/src/lib/kind-settings-structures.js.map +1 -1
- package/src/lib/kind-settings-structures.mjs +34 -0
- package/src/lib/kind-settings-structures.mjs.map +1 -1
- package/src/lib/kinds.js +6 -1
- package/src/lib/kinds.js.map +1 -1
- package/src/lib/kinds.mjs +6 -1
- package/src/lib/kinds.mjs.map +1 -1
- package/src/lib/list-commands.d.mts +4 -0
- package/src/lib/list-commands.d.ts +4 -0
- package/src/lib/list-commands.js +11 -0
- package/src/lib/list-commands.js.map +1 -1
- package/src/lib/list-commands.mjs +12 -1
- package/src/lib/list-commands.mjs.map +1 -1
- package/src/lib/list-properties.js +19 -1
- package/src/lib/list-properties.js.map +1 -1
- package/src/lib/list-properties.mjs +19 -1
- package/src/lib/list-properties.mjs.map +1 -1
- package/src/lib/locales/ar/changes.js +12 -0
- package/src/lib/locales/ar/changes.js.map +1 -1
- package/src/lib/locales/ar/changes.mjs +12 -0
- package/src/lib/locales/ar/changes.mjs.map +1 -1
- package/src/lib/locales/ar/kinds.js +1 -0
- package/src/lib/locales/ar/kinds.js.map +1 -1
- package/src/lib/locales/ar/kinds.mjs +1 -0
- package/src/lib/locales/ar/kinds.mjs.map +1 -1
- package/src/lib/locales/ar/list.js +4 -0
- package/src/lib/locales/ar/list.js.map +1 -1
- package/src/lib/locales/ar/list.mjs +4 -0
- package/src/lib/locales/ar/list.mjs.map +1 -1
- package/src/lib/locales/ar/panel.js +31 -0
- package/src/lib/locales/ar/panel.js.map +1 -1
- package/src/lib/locales/ar/panel.mjs +31 -0
- package/src/lib/locales/ar/panel.mjs.map +1 -1
- package/src/lib/locales/ar/questions.js +15 -0
- package/src/lib/locales/ar/questions.js.map +1 -1
- package/src/lib/locales/ar/questions.mjs +15 -0
- package/src/lib/locales/ar/questions.mjs.map +1 -1
- package/src/lib/locales/ar/refusals.js +10 -0
- package/src/lib/locales/ar/refusals.js.map +1 -1
- package/src/lib/locales/ar/refusals.mjs +10 -0
- package/src/lib/locales/ar/refusals.mjs.map +1 -1
- package/src/lib/locales/ar/settings-changes.js +9 -0
- package/src/lib/locales/ar/settings-changes.js.map +1 -1
- package/src/lib/locales/ar/settings-changes.mjs +9 -0
- package/src/lib/locales/ar/settings-changes.mjs.map +1 -1
- package/src/lib/locales/en/changes.d.mts +12 -0
- package/src/lib/locales/en/changes.d.ts +12 -0
- package/src/lib/locales/en/changes.js +13 -0
- package/src/lib/locales/en/changes.js.map +1 -1
- package/src/lib/locales/en/changes.mjs +13 -0
- package/src/lib/locales/en/changes.mjs.map +1 -1
- package/src/lib/locales/en/index.d.mts +70 -0
- package/src/lib/locales/en/index.d.ts +70 -0
- package/src/lib/locales/en/kinds.d.mts +1 -0
- package/src/lib/locales/en/kinds.d.ts +1 -0
- package/src/lib/locales/en/kinds.js +1 -0
- package/src/lib/locales/en/kinds.js.map +1 -1
- package/src/lib/locales/en/kinds.mjs +1 -0
- package/src/lib/locales/en/kinds.mjs.map +1 -1
- package/src/lib/locales/en/list.d.mts +4 -0
- package/src/lib/locales/en/list.d.ts +4 -0
- package/src/lib/locales/en/list.js +4 -0
- package/src/lib/locales/en/list.js.map +1 -1
- package/src/lib/locales/en/list.mjs +4 -0
- package/src/lib/locales/en/list.mjs.map +1 -1
- package/src/lib/locales/en/panel.d.mts +23 -0
- package/src/lib/locales/en/panel.d.ts +23 -0
- package/src/lib/locales/en/panel.js +25 -0
- package/src/lib/locales/en/panel.js.map +1 -1
- package/src/lib/locales/en/panel.mjs +25 -0
- package/src/lib/locales/en/panel.mjs.map +1 -1
- package/src/lib/locales/en/questions.d.mts +17 -0
- package/src/lib/locales/en/questions.d.ts +17 -0
- package/src/lib/locales/en/questions.js +17 -0
- package/src/lib/locales/en/questions.js.map +1 -1
- package/src/lib/locales/en/questions.mjs +17 -0
- package/src/lib/locales/en/questions.mjs.map +1 -1
- package/src/lib/locales/en/refusals.d.mts +10 -0
- package/src/lib/locales/en/refusals.d.ts +10 -0
- package/src/lib/locales/en/refusals.js +11 -0
- package/src/lib/locales/en/refusals.js.map +1 -1
- package/src/lib/locales/en/refusals.mjs +11 -0
- package/src/lib/locales/en/refusals.mjs.map +1 -1
- package/src/lib/locales/en/settings-changes.d.mts +7 -0
- package/src/lib/locales/en/settings-changes.d.ts +7 -0
- package/src/lib/locales/en/settings-changes.js +10 -0
- package/src/lib/locales/en/settings-changes.js.map +1 -1
- package/src/lib/locales/en/settings-changes.mjs +10 -0
- package/src/lib/locales/en/settings-changes.mjs.map +1 -1
- package/src/lib/page-checks.js +21 -2
- package/src/lib/page-checks.js.map +1 -1
- package/src/lib/page-checks.mjs +21 -2
- package/src/lib/page-checks.mjs.map +1 -1
- package/src/lib/panel-field.js +24 -1
- package/src/lib/panel-field.js.map +1 -1
- package/src/lib/panel-field.mjs +24 -1
- package/src/lib/panel-field.mjs.map +1 -1
- package/src/lib/panel-page.js +9 -1
- package/src/lib/panel-page.js.map +1 -1
- package/src/lib/panel-page.mjs +9 -1
- package/src/lib/panel-page.mjs.map +1 -1
- package/src/lib/styles-kinds.d.mts +1 -1
- package/src/lib/styles-kinds.d.ts +1 -1
- package/src/lib/styles-kinds.js +7 -0
- package/src/lib/styles-kinds.js.map +1 -1
- package/src/lib/styles-kinds.mjs +7 -0
- package/src/lib/styles-kinds.mjs.map +1 -1
- package/src/lib/styles.d.mts +1 -1
- package/src/lib/styles.d.ts +1 -1
- package/src/lib/styles.js +4 -2
- package/src/lib/styles.js.map +1 -1
- package/src/lib/styles.mjs +4 -2
- package/src/lib/styles.mjs.map +1 -1
- package/src/lib/survey-editor.js +19 -0
- package/src/lib/survey-editor.js.map +1 -1
- package/src/lib/survey-editor.mjs +19 -0
- package/src/lib/survey-editor.mjs.map +1 -1
- package/src/lib/toolbox.js +1 -1
- package/src/lib/toolbox.js.map +1 -1
- package/src/lib/toolbox.mjs +1 -1
- package/src/lib/toolbox.mjs.map +1 -1
- package/src/lib/try-drawer.js +7 -0
- package/src/lib/try-drawer.js.map +1 -1
- package/src/lib/try-drawer.mjs +7 -0
- package/src/lib/try-drawer.mjs.map +1 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** The air left between a control and the bar at the foot of the screen. */
|
|
2
|
+
const AIR = 8;
|
|
3
|
+
/**
|
|
4
|
+
* A bar kept at the foot of the screen (`position: sticky` with a `bottom`) never hides what a person works on, and
|
|
5
|
+
* keeping it clear never hides it under the bar at the top instead (WCAG 2.4.11, both ways). A control focused in the
|
|
6
|
+
* area the bar floats over — by Tab or Shift+Tab, by a press — is moved up from behind the bar once the engine's own
|
|
7
|
+
* scroll on focus is done (that scroll knows nothing of it), but never so far that its top goes under the room the
|
|
8
|
+
* top bar keeps (the scroller's `scroll-padding-top`, the designer bar's): where it cannot fit between the two, its
|
|
9
|
+
* top wins. The bar stays where it is; the area's end is the bar's own place in the flow, where it rests once the area
|
|
10
|
+
* is scrolled to its end. Where the bar is not at the foot (sticky no longer: a wide screen's rail beside its card),
|
|
11
|
+
* nothing is moved.
|
|
12
|
+
*
|
|
13
|
+
* No `scroll-margin-bottom` on what is focused: an element taller than the room between the bars would then be
|
|
14
|
+
* aligned by its end as the engine scrolls to it — walking up by Shift+Tab, its top under the top bar.
|
|
15
|
+
*/
|
|
16
|
+
export function keepClearOfBar(bar, area) {
|
|
17
|
+
const view = bar.ownerDocument.defaultView;
|
|
18
|
+
/** Whether the bar has been in the page: once taken out of it (a new drawer in its place), the watch ends. */
|
|
19
|
+
let placed = false;
|
|
20
|
+
const measure = () => {
|
|
21
|
+
if (!bar.isConnected)
|
|
22
|
+
return placed ? stop() : undefined;
|
|
23
|
+
placed = true;
|
|
24
|
+
const style = view?.getComputedStyle(bar);
|
|
25
|
+
const atFoot = !!style && style.position === 'sticky' && style.bottom !== 'auto' && !bar.hidden;
|
|
26
|
+
const room = atFoot ? Math.ceil(bar.getBoundingClientRect().height + (parseFloat(style.bottom) || 0) + AIR) : 0;
|
|
27
|
+
area.style.setProperty('--fd-foot-room', `${room}px`);
|
|
28
|
+
};
|
|
29
|
+
const onFocus = (event) => {
|
|
30
|
+
const control = event.target;
|
|
31
|
+
if (!control?.getBoundingClientRect || !view)
|
|
32
|
+
return;
|
|
33
|
+
// After the engine's own scroll on focus, which comes after the focus event.
|
|
34
|
+
view.requestAnimationFrame(() => {
|
|
35
|
+
if (barRoom(area) && view.document.activeElement === control)
|
|
36
|
+
clearOfBar(bar, control);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
area.addEventListener('focusin', onFocus);
|
|
40
|
+
const ResizeWatcher = view?.ResizeObserver;
|
|
41
|
+
const watcher = ResizeWatcher ? new ResizeWatcher(measure) : null;
|
|
42
|
+
// The bar's own size, and the area's width: a container query that puts the bar at the foot or takes it away.
|
|
43
|
+
watcher?.observe(bar);
|
|
44
|
+
watcher?.observe(area);
|
|
45
|
+
measure();
|
|
46
|
+
function stop() {
|
|
47
|
+
watcher?.disconnect();
|
|
48
|
+
area.removeEventListener('focusin', onFocus);
|
|
49
|
+
area.style.removeProperty('--fd-foot-room');
|
|
50
|
+
}
|
|
51
|
+
return stop;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The scroller that can move an element up by `by`: its nearest ancestor that scrolls up and down with that much room
|
|
55
|
+
* left — a row of tabs that scrolls sideways is no such scroller, though its `overflow-y` reads `auto` — else the page.
|
|
56
|
+
*/
|
|
57
|
+
function scrollerOf(element, by) {
|
|
58
|
+
const doc = element.ownerDocument;
|
|
59
|
+
const view = doc.defaultView;
|
|
60
|
+
for (let at = element.parentElement; at && at !== doc.body && at !== doc.documentElement; at = at.parentElement) {
|
|
61
|
+
const overflow = view?.getComputedStyle(at).overflowY ?? 'visible';
|
|
62
|
+
if ((overflow === 'auto' || overflow === 'scroll') && at.scrollHeight - at.clientHeight - at.scrollTop >= by)
|
|
63
|
+
return at;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* An element moved up from behind the bar at the foot (with a little air), as far as that takes — but its top never
|
|
69
|
+
* under the room its scroller keeps at its top (`scroll-padding-top`: the designer bar's, on the page). Where both
|
|
70
|
+
* cannot hold, the top wins. Nothing moves for an element clear of the bar already.
|
|
71
|
+
*/
|
|
72
|
+
export function clearOfBar(bar, element) {
|
|
73
|
+
const box = element.getBoundingClientRect();
|
|
74
|
+
const limit = bar.getBoundingClientRect().top - AIR;
|
|
75
|
+
if (box.bottom <= limit)
|
|
76
|
+
return;
|
|
77
|
+
const doc = element.ownerDocument;
|
|
78
|
+
const view = doc.defaultView;
|
|
79
|
+
const want = box.bottom - limit;
|
|
80
|
+
const own = scrollerOf(element, want);
|
|
81
|
+
const scroller = own ?? (doc.scrollingElement ?? doc.documentElement);
|
|
82
|
+
const top = (own ? own.getBoundingClientRect().top : 0) + (parseFloat(view?.getComputedStyle(scroller).scrollPaddingTop ?? '') || 0);
|
|
83
|
+
const by = Math.min(want, box.top - top);
|
|
84
|
+
if (by <= 0)
|
|
85
|
+
return;
|
|
86
|
+
if (own)
|
|
87
|
+
own.scrollTop += by;
|
|
88
|
+
else
|
|
89
|
+
view?.scrollBy(0, by);
|
|
90
|
+
}
|
|
91
|
+
/** The room the bar takes now, as `keepClearOfBar` measured it: 0 where it is not at the foot. */
|
|
92
|
+
export const barRoom = (area) => parseFloat(area.style.getPropertyValue('--fd-foot-room')) || 0;
|
|
93
|
+
//# sourceMappingURL=bottom-bar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bottom-bar.mjs","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/bottom-bar.ts"],"names":[],"mappings":"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"}
|
package/src/lib/designer.d.mts
CHANGED
|
@@ -279,6 +279,27 @@ export interface Designer extends HeaderCommands, ListCommands, ChoiceCommands,
|
|
|
279
279
|
}): boolean;
|
|
280
280
|
/** "Continue later" (`continueLater`): the answers kept on the app's server with a link to carry on; false takes it away. */
|
|
281
281
|
setContinueLater(on: boolean): boolean;
|
|
282
|
+
/**
|
|
283
|
+
* Approvals on a record's screen (`approval`): on, its records waiting for approval as the app's data source says —
|
|
284
|
+
* `on: false` takes the setting away — the fields left open while one waits (`open`; `null` or none, every field
|
|
285
|
+
* locked), and whether it locks at all (`lock: false`, which leaves none open to name). A record's own screen only,
|
|
286
|
+
* refused on a form of responses or a list.
|
|
287
|
+
*/
|
|
288
|
+
setApproval(patch: {
|
|
289
|
+
on?: boolean;
|
|
290
|
+
open?: string[] | null;
|
|
291
|
+
lock?: boolean | null;
|
|
292
|
+
}): boolean;
|
|
293
|
+
/**
|
|
294
|
+
* AI help's Fill from text (`suggest`): `{}` offers it, `null` takes it away; its button's words (`label`), the fields
|
|
295
|
+
* it may fill (`fields`: none, every one shown a person can set) and a text field whose words it reads in place of
|
|
296
|
+
* words pasted (`fromField`) — each `null` (or empty) taking that one away. Refused on a list of records.
|
|
297
|
+
*/
|
|
298
|
+
setSuggest(patch: {
|
|
299
|
+
label?: string | null;
|
|
300
|
+
fields?: string[] | null;
|
|
301
|
+
fromField?: string | null;
|
|
302
|
+
} | null): boolean;
|
|
282
303
|
/**
|
|
283
304
|
* The page's phone numbers (`phone`): read the world over (`on`), or text boxes as typed (`on: false` takes the
|
|
284
305
|
* setting away); the country a number typed without its + is read in, and whether a number shows abroad's way or at
|
package/src/lib/designer.d.ts
CHANGED
|
@@ -279,6 +279,27 @@ export interface Designer extends HeaderCommands, ListCommands, ChoiceCommands,
|
|
|
279
279
|
}): boolean;
|
|
280
280
|
/** "Continue later" (`continueLater`): the answers kept on the app's server with a link to carry on; false takes it away. */
|
|
281
281
|
setContinueLater(on: boolean): boolean;
|
|
282
|
+
/**
|
|
283
|
+
* Approvals on a record's screen (`approval`): on, its records waiting for approval as the app's data source says —
|
|
284
|
+
* `on: false` takes the setting away — the fields left open while one waits (`open`; `null` or none, every field
|
|
285
|
+
* locked), and whether it locks at all (`lock: false`, which leaves none open to name). A record's own screen only,
|
|
286
|
+
* refused on a form of responses or a list.
|
|
287
|
+
*/
|
|
288
|
+
setApproval(patch: {
|
|
289
|
+
on?: boolean;
|
|
290
|
+
open?: string[] | null;
|
|
291
|
+
lock?: boolean | null;
|
|
292
|
+
}): boolean;
|
|
293
|
+
/**
|
|
294
|
+
* AI help's Fill from text (`suggest`): `{}` offers it, `null` takes it away; its button's words (`label`), the fields
|
|
295
|
+
* it may fill (`fields`: none, every one shown a person can set) and a text field whose words it reads in place of
|
|
296
|
+
* words pasted (`fromField`) — each `null` (or empty) taking that one away. Refused on a list of records.
|
|
297
|
+
*/
|
|
298
|
+
setSuggest(patch: {
|
|
299
|
+
label?: string | null;
|
|
300
|
+
fields?: string[] | null;
|
|
301
|
+
fromField?: string | null;
|
|
302
|
+
} | null): boolean;
|
|
282
303
|
/**
|
|
283
304
|
* The page's phone numbers (`phone`): read the world over (`on`), or text boxes as typed (`on: false` takes the
|
|
284
305
|
* setting away); the country a number typed without its + is read in, and whether a number shows abroad's way or at
|
package/src/lib/designer.js
CHANGED
|
@@ -299,6 +299,10 @@ function createDesigner(options) {
|
|
|
299
299
|
(0, steps_places_1.forgetGoneTargets)(draft);
|
|
300
300
|
// A field taken away, or made a kind records are not compared by, is no longer one possible duplicates are found by.
|
|
301
301
|
forgetGoneDuplicates(draft);
|
|
302
|
+
// A field taken away is no longer one left open while a record waits for approval.
|
|
303
|
+
forgetGoneOpenFields(draft);
|
|
304
|
+
// Nor one AI help fills or reads, and a field no longer of text has no text tools.
|
|
305
|
+
forgetGoneAssist(draft);
|
|
302
306
|
// A related list taken out of a tab takes the tab's count of it with it.
|
|
303
307
|
(0, head_parts_1.forgetGoneCounts)(draft);
|
|
304
308
|
const checked = checkEdit(page, draft);
|
|
@@ -624,6 +628,10 @@ function createDesigner(options) {
|
|
|
624
628
|
next.help = old.help;
|
|
625
629
|
if (old.required)
|
|
626
630
|
next.required = true;
|
|
631
|
+
// Typed in several languages, it stays so as words of another kind typed: a short answer made a paragraph.
|
|
632
|
+
const languages = old;
|
|
633
|
+
if (languages.translate && ['char', 'text', 'html'].includes(next.type) && !kind.widget)
|
|
634
|
+
Object.assign(next, { translate: languages.translate, ...(languages.requiredIn ? { requiredIn: languages.requiredIn } : {}) });
|
|
627
635
|
draft.fields[node.field] = next;
|
|
628
636
|
if (kind.widget)
|
|
629
637
|
node.widget = kind.widget;
|
|
@@ -1099,6 +1107,46 @@ function createDesigner(options) {
|
|
|
1099
1107
|
delete draft.continueLater;
|
|
1100
1108
|
}, 'continueLater');
|
|
1101
1109
|
},
|
|
1110
|
+
setApproval(patch) {
|
|
1111
|
+
return apply((draft) => {
|
|
1112
|
+
if (patch.on === false)
|
|
1113
|
+
return void delete draft.approval;
|
|
1114
|
+
if (draft.data.kind !== 'record' || draft.layout.type === 'list')
|
|
1115
|
+
throw new refusal_1.Refusal((w) => w.refusals.approvalForRecords);
|
|
1116
|
+
const now = { ...(draft.approval ?? {}) };
|
|
1117
|
+
if (patch.open !== undefined) {
|
|
1118
|
+
const open = [...new Set(patch.open ?? [])].filter((name) => draft.fields[name]);
|
|
1119
|
+
if (open.length)
|
|
1120
|
+
now.open = open;
|
|
1121
|
+
else
|
|
1122
|
+
delete now.open;
|
|
1123
|
+
}
|
|
1124
|
+
// Nothing locked, nothing to leave open.
|
|
1125
|
+
if (patch.lock === false) {
|
|
1126
|
+
now.lock = false;
|
|
1127
|
+
delete now.open;
|
|
1128
|
+
}
|
|
1129
|
+
else if (patch.lock !== undefined)
|
|
1130
|
+
delete now.lock;
|
|
1131
|
+
draft.approval = now;
|
|
1132
|
+
}, `approval:${Object.keys(patch).join(',')}`);
|
|
1133
|
+
},
|
|
1134
|
+
setSuggest(patch) {
|
|
1135
|
+
return apply((draft) => {
|
|
1136
|
+
if (patch === null)
|
|
1137
|
+
return void delete draft.suggest;
|
|
1138
|
+
if (draft.layout.type === 'list')
|
|
1139
|
+
throw new refusal_1.Refusal((w) => w.refusals.suggestForForms);
|
|
1140
|
+
const now = { ...draft.suggest };
|
|
1141
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
1142
|
+
if (value === null || value === '' || (Array.isArray(value) && !value.length))
|
|
1143
|
+
delete now[key];
|
|
1144
|
+
else
|
|
1145
|
+
now[key] = Array.isArray(value) ? [...new Set(value)] : typeof value === 'string' && key === 'label' ? value.trim() : value;
|
|
1146
|
+
}
|
|
1147
|
+
draft.suggest = now;
|
|
1148
|
+
}, patch ? `suggest:${Object.keys(patch).join(',')}` : null);
|
|
1149
|
+
},
|
|
1102
1150
|
setDuplicates(patch) {
|
|
1103
1151
|
return apply((draft) => {
|
|
1104
1152
|
if (patch.fields !== undefined && !patch.fields?.length)
|
|
@@ -1208,6 +1256,9 @@ function createDesigner(options) {
|
|
|
1208
1256
|
if (rules.multiple === true)
|
|
1209
1257
|
field.multiple = true;
|
|
1210
1258
|
else if (rules.multiple === false) {
|
|
1259
|
+
// A photo set is several photos: one has no order, no cover.
|
|
1260
|
+
if (fieldNode(draft, id).widget === 'photos')
|
|
1261
|
+
throw new refusal_1.Refusal((w) => w.refusals.photoSetSeveral);
|
|
1211
1262
|
delete field.multiple;
|
|
1212
1263
|
delete field.minFiles;
|
|
1213
1264
|
delete field.maxFiles;
|
|
@@ -1678,6 +1729,51 @@ function changeRelated(draft, node, patch, functions) {
|
|
|
1678
1729
|
}
|
|
1679
1730
|
}
|
|
1680
1731
|
}
|
|
1732
|
+
/** The fields left open while a record waits for approval (`approval.open`) that are still on the page: none left, every field locks. */
|
|
1733
|
+
function forgetGoneOpenFields(page) {
|
|
1734
|
+
const open = page.approval?.open;
|
|
1735
|
+
if (!page.approval || !open)
|
|
1736
|
+
return;
|
|
1737
|
+
const kept = open.filter((name) => page.fields[name]);
|
|
1738
|
+
if (kept.length === open.length)
|
|
1739
|
+
return;
|
|
1740
|
+
const { open: _, ...rest } = page.approval;
|
|
1741
|
+
page.approval = kept.length ? { ...rest, open: kept } : rest;
|
|
1742
|
+
}
|
|
1743
|
+
/** The kinds AI help fills (`suggest.fields`), and those whose words it reads and rewrites. */
|
|
1744
|
+
const FILLED = new Set(['char', 'text', 'html', 'integer', 'float', 'monetary', 'boolean', 'selection', 'date', 'datetime', 'many2one', 'many2many', 'one2many']);
|
|
1745
|
+
const TEXTS = new Set(['char', 'text', 'html']);
|
|
1746
|
+
/**
|
|
1747
|
+
* AI help as its fields change: those Fill from text fills still on the page, of a kind it fills and a person can set
|
|
1748
|
+
* (none left, it fills every one shown); the words it reads a text field's still; a text field's tools on text alone.
|
|
1749
|
+
*/
|
|
1750
|
+
function forgetGoneAssist(page) {
|
|
1751
|
+
const suggest = page.suggest;
|
|
1752
|
+
if (suggest) {
|
|
1753
|
+
const from = suggest.fromField && TEXTS.has(page.fields[suggest.fromField]?.type ?? '') ? suggest.fromField : undefined;
|
|
1754
|
+
const fields = suggest.fields?.filter((name) => name !== from && FILLED.has(page.fields[name]?.type ?? '') && page.fields[name]?.readonly !== true && page.fields[name]?.compute === undefined);
|
|
1755
|
+
const { fields: _fields, fromField: _from, ...rest } = suggest;
|
|
1756
|
+
page.suggest = { ...rest, ...(fields?.length ? { fields } : {}), ...(from ? { fromField: from } : {}) };
|
|
1757
|
+
}
|
|
1758
|
+
const visit = (value) => {
|
|
1759
|
+
if (Array.isArray(value))
|
|
1760
|
+
return value.forEach(visit);
|
|
1761
|
+
if (!value || typeof value !== 'object')
|
|
1762
|
+
return;
|
|
1763
|
+
const node = value;
|
|
1764
|
+
if (node.type === 'field' && node.options && 'rewrite' in node.options && !TEXTS.has(page.fields[node.field]?.type ?? '')) {
|
|
1765
|
+
const { rewrite: _, ...options } = node.options;
|
|
1766
|
+
if (Object.keys(options).length)
|
|
1767
|
+
node.options = options;
|
|
1768
|
+
else
|
|
1769
|
+
delete node.options;
|
|
1770
|
+
}
|
|
1771
|
+
for (const child of Object.values(value))
|
|
1772
|
+
if (child && typeof child === 'object')
|
|
1773
|
+
visit(child);
|
|
1774
|
+
};
|
|
1775
|
+
visit(page.layout);
|
|
1776
|
+
}
|
|
1681
1777
|
/** The fields possible duplicates are found by (`duplicates`) that are still on the page and of a kind to compare: none left, the setting goes. */
|
|
1682
1778
|
function forgetGoneDuplicates(page) {
|
|
1683
1779
|
if (!page.duplicates)
|