@yuneta/gobj-ui 7.23.70 → 7.23.71
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/dist/gobj-ui.cjs.js +52 -1
- package/dist/gobj-ui.es.js +52 -1
- package/package.json +1 -1
- package/src/c_yui_form.js +8 -2
- package/src/form_field_readonly.js +61 -0
- package/src/form_field_readonly.test.js +50 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -6403,6 +6403,57 @@ function plan_toolbar(wanted) {
|
|
|
6403
6403
|
};
|
|
6404
6404
|
}
|
|
6405
6405
|
//#endregion
|
|
6406
|
+
//#region src/form_field_readonly.js
|
|
6407
|
+
/***********************************************************************
|
|
6408
|
+
* form_field_readonly.js
|
|
6409
|
+
*
|
|
6410
|
+
* Is this field of the form read-only?
|
|
6411
|
+
*
|
|
6412
|
+
* Pure, so the rule can be tested without a DOM: the gclass turns
|
|
6413
|
+
* the answer into `readonly`/`disabled` on a control, this decides
|
|
6414
|
+
* the answer. Same split as form_toolbar_plan.js and
|
|
6415
|
+
* treedb_write_plan.js.
|
|
6416
|
+
*
|
|
6417
|
+
* The rule it exists to state ONCE: **`writable` governs the WRITE
|
|
6418
|
+
* of a column's VALUE, and an fkey is not written — it is LINKED.**
|
|
6419
|
+
* An fkey column is normally declared with no `writable` flag at
|
|
6420
|
+
* all (`treedb_authzs`'s `users.roles` is `['fkey']`, and so is
|
|
6421
|
+
* almost every fkey in the tree), so reading "not writable" as "not
|
|
6422
|
+
* editable" takes away the only way to link a record to its parent
|
|
6423
|
+
* — with `users.roles`, the only way to give a person a role.
|
|
6424
|
+
*
|
|
6425
|
+
* The other half of this rule is already written down in
|
|
6426
|
+
* c_yui_treedb_topic_with_form.js, where the record travels back:
|
|
6427
|
+
* the form sends "the writable cols, the fkeys (a link is edited by
|
|
6428
|
+
* linking) and the pkey". The two halves have to agree, and when
|
|
6429
|
+
* they did not, the form disabled the control whose value the save
|
|
6430
|
+
* path was still waiting for.
|
|
6431
|
+
*
|
|
6432
|
+
* A `file` column is an fkey too (flagged `['fkey','file']`) and is
|
|
6433
|
+
* NOT covered: it answers `type: "file"`, its bytes travel beside
|
|
6434
|
+
* the record, and the SDK declares as legal a `file` column that
|
|
6435
|
+
* only a load fills.
|
|
6436
|
+
*
|
|
6437
|
+
* Copyright (c) 2026, ArtGins.
|
|
6438
|
+
* All Rights Reserved.
|
|
6439
|
+
***********************************************************************/
|
|
6440
|
+
/***************************************************************
|
|
6441
|
+
* field_is_readonly(form_readonly, field_desc) -> boolean
|
|
6442
|
+
*
|
|
6443
|
+
* form_readonly the FORM is read-only: a record opened to be
|
|
6444
|
+
* looked at, or a store nobody may write. It is
|
|
6445
|
+
* a property of the opening, not of the schema,
|
|
6446
|
+
* and it wins over everything.
|
|
6447
|
+
* field_desc as treedb_get_field_desc() answers it
|
|
6448
|
+
* (`type`, `is_writable`).
|
|
6449
|
+
***************************************************************/
|
|
6450
|
+
function field_is_readonly(form_readonly, field_desc) {
|
|
6451
|
+
if (form_readonly) return true;
|
|
6452
|
+
let desc = field_desc || {};
|
|
6453
|
+
if (desc.type === "fkey") return false;
|
|
6454
|
+
return !desc.is_writable;
|
|
6455
|
+
}
|
|
6456
|
+
//#endregion
|
|
6406
6457
|
//#region src/yui_theme.js
|
|
6407
6458
|
/***********************************************************************
|
|
6408
6459
|
* yui_theme.js
|
|
@@ -7215,7 +7266,7 @@ function build_form_field_conf(gobj, field_desc) {
|
|
|
7215
7266
|
placeholder: "",
|
|
7216
7267
|
options: [],
|
|
7217
7268
|
extras: {},
|
|
7218
|
-
readonly: (0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "readonly")
|
|
7269
|
+
readonly: field_is_readonly((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "readonly"), field_desc),
|
|
7219
7270
|
required: field_desc.is_required,
|
|
7220
7271
|
hidden: field_desc.is_hidden,
|
|
7221
7272
|
default_value: field_desc.default_value
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -6398,6 +6398,57 @@ function plan_toolbar(wanted) {
|
|
|
6398
6398
|
};
|
|
6399
6399
|
}
|
|
6400
6400
|
//#endregion
|
|
6401
|
+
//#region src/form_field_readonly.js
|
|
6402
|
+
/***********************************************************************
|
|
6403
|
+
* form_field_readonly.js
|
|
6404
|
+
*
|
|
6405
|
+
* Is this field of the form read-only?
|
|
6406
|
+
*
|
|
6407
|
+
* Pure, so the rule can be tested without a DOM: the gclass turns
|
|
6408
|
+
* the answer into `readonly`/`disabled` on a control, this decides
|
|
6409
|
+
* the answer. Same split as form_toolbar_plan.js and
|
|
6410
|
+
* treedb_write_plan.js.
|
|
6411
|
+
*
|
|
6412
|
+
* The rule it exists to state ONCE: **`writable` governs the WRITE
|
|
6413
|
+
* of a column's VALUE, and an fkey is not written — it is LINKED.**
|
|
6414
|
+
* An fkey column is normally declared with no `writable` flag at
|
|
6415
|
+
* all (`treedb_authzs`'s `users.roles` is `['fkey']`, and so is
|
|
6416
|
+
* almost every fkey in the tree), so reading "not writable" as "not
|
|
6417
|
+
* editable" takes away the only way to link a record to its parent
|
|
6418
|
+
* — with `users.roles`, the only way to give a person a role.
|
|
6419
|
+
*
|
|
6420
|
+
* The other half of this rule is already written down in
|
|
6421
|
+
* c_yui_treedb_topic_with_form.js, where the record travels back:
|
|
6422
|
+
* the form sends "the writable cols, the fkeys (a link is edited by
|
|
6423
|
+
* linking) and the pkey". The two halves have to agree, and when
|
|
6424
|
+
* they did not, the form disabled the control whose value the save
|
|
6425
|
+
* path was still waiting for.
|
|
6426
|
+
*
|
|
6427
|
+
* A `file` column is an fkey too (flagged `['fkey','file']`) and is
|
|
6428
|
+
* NOT covered: it answers `type: "file"`, its bytes travel beside
|
|
6429
|
+
* the record, and the SDK declares as legal a `file` column that
|
|
6430
|
+
* only a load fills.
|
|
6431
|
+
*
|
|
6432
|
+
* Copyright (c) 2026, ArtGins.
|
|
6433
|
+
* All Rights Reserved.
|
|
6434
|
+
***********************************************************************/
|
|
6435
|
+
/***************************************************************
|
|
6436
|
+
* field_is_readonly(form_readonly, field_desc) -> boolean
|
|
6437
|
+
*
|
|
6438
|
+
* form_readonly the FORM is read-only: a record opened to be
|
|
6439
|
+
* looked at, or a store nobody may write. It is
|
|
6440
|
+
* a property of the opening, not of the schema,
|
|
6441
|
+
* and it wins over everything.
|
|
6442
|
+
* field_desc as treedb_get_field_desc() answers it
|
|
6443
|
+
* (`type`, `is_writable`).
|
|
6444
|
+
***************************************************************/
|
|
6445
|
+
function field_is_readonly(form_readonly, field_desc) {
|
|
6446
|
+
if (form_readonly) return true;
|
|
6447
|
+
let desc = field_desc || {};
|
|
6448
|
+
if (desc.type === "fkey") return false;
|
|
6449
|
+
return !desc.is_writable;
|
|
6450
|
+
}
|
|
6451
|
+
//#endregion
|
|
6401
6452
|
//#region src/yui_theme.js
|
|
6402
6453
|
/***********************************************************************
|
|
6403
6454
|
* yui_theme.js
|
|
@@ -7210,7 +7261,7 @@ function build_form_field_conf(gobj, field_desc) {
|
|
|
7210
7261
|
placeholder: "",
|
|
7211
7262
|
options: [],
|
|
7212
7263
|
extras: {},
|
|
7213
|
-
readonly: gobj_read_bool_attr(gobj, "readonly")
|
|
7264
|
+
readonly: field_is_readonly(gobj_read_bool_attr(gobj, "readonly"), field_desc),
|
|
7214
7265
|
required: field_desc.is_required,
|
|
7215
7266
|
hidden: field_desc.is_hidden,
|
|
7216
7267
|
default_value: field_desc.default_value
|
package/package.json
CHANGED
package/src/c_yui_form.js
CHANGED
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
import "./c_yui_form.css";
|
|
66
66
|
import {attach_clear, refresh_clear} from "./yui_inputs.js";
|
|
67
67
|
import {plan_toolbar, DEFAULT_TOOLBAR} from "./form_toolbar_plan.js";
|
|
68
|
+
import {field_is_readonly} from "./form_field_readonly.js";
|
|
68
69
|
/* Read at field-build time only — deliberately NOT watched: the hosting
|
|
69
70
|
* dialog rebuilds the form on every open, and re-rendering a form under
|
|
70
71
|
* the user mid-edit would throw away what they typed. */
|
|
@@ -601,8 +602,13 @@ function build_form_field_conf(gobj, field_desc)
|
|
|
601
602
|
extras: {}, // extra html input/textarea attributes
|
|
602
603
|
/* A form opened to LOOK at a record has no editable field, and
|
|
603
604
|
* that is a property of the opening, not of the schema: the same
|
|
604
|
-
* col is writable when the same form is opened to edit.
|
|
605
|
-
|
|
605
|
+
* col is writable when the same form is opened to edit. And an
|
|
606
|
+
* fkey is editable WITHOUT `writable`, because a link is not
|
|
607
|
+
* written, it is linked -- the rule and its why live in
|
|
608
|
+
* form_field_readonly.js. */
|
|
609
|
+
readonly: field_is_readonly(
|
|
610
|
+
gobj_read_bool_attr(gobj, "readonly"), field_desc
|
|
611
|
+
),
|
|
606
612
|
required: field_desc.is_required,
|
|
607
613
|
hidden: field_desc.is_hidden,
|
|
608
614
|
default_value: field_desc.default_value,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/***********************************************************************
|
|
2
|
+
* form_field_readonly.js
|
|
3
|
+
*
|
|
4
|
+
* Is this field of the form read-only?
|
|
5
|
+
*
|
|
6
|
+
* Pure, so the rule can be tested without a DOM: the gclass turns
|
|
7
|
+
* the answer into `readonly`/`disabled` on a control, this decides
|
|
8
|
+
* the answer. Same split as form_toolbar_plan.js and
|
|
9
|
+
* treedb_write_plan.js.
|
|
10
|
+
*
|
|
11
|
+
* The rule it exists to state ONCE: **`writable` governs the WRITE
|
|
12
|
+
* of a column's VALUE, and an fkey is not written — it is LINKED.**
|
|
13
|
+
* An fkey column is normally declared with no `writable` flag at
|
|
14
|
+
* all (`treedb_authzs`'s `users.roles` is `['fkey']`, and so is
|
|
15
|
+
* almost every fkey in the tree), so reading "not writable" as "not
|
|
16
|
+
* editable" takes away the only way to link a record to its parent
|
|
17
|
+
* — with `users.roles`, the only way to give a person a role.
|
|
18
|
+
*
|
|
19
|
+
* The other half of this rule is already written down in
|
|
20
|
+
* c_yui_treedb_topic_with_form.js, where the record travels back:
|
|
21
|
+
* the form sends "the writable cols, the fkeys (a link is edited by
|
|
22
|
+
* linking) and the pkey". The two halves have to agree, and when
|
|
23
|
+
* they did not, the form disabled the control whose value the save
|
|
24
|
+
* path was still waiting for.
|
|
25
|
+
*
|
|
26
|
+
* A `file` column is an fkey too (flagged `['fkey','file']`) and is
|
|
27
|
+
* NOT covered: it answers `type: "file"`, its bytes travel beside
|
|
28
|
+
* the record, and the SDK declares as legal a `file` column that
|
|
29
|
+
* only a load fills.
|
|
30
|
+
*
|
|
31
|
+
* Copyright (c) 2026, ArtGins.
|
|
32
|
+
* All Rights Reserved.
|
|
33
|
+
***********************************************************************/
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/***************************************************************
|
|
37
|
+
* field_is_readonly(form_readonly, field_desc) -> boolean
|
|
38
|
+
*
|
|
39
|
+
* form_readonly the FORM is read-only: a record opened to be
|
|
40
|
+
* looked at, or a store nobody may write. It is
|
|
41
|
+
* a property of the opening, not of the schema,
|
|
42
|
+
* and it wins over everything.
|
|
43
|
+
* field_desc as treedb_get_field_desc() answers it
|
|
44
|
+
* (`type`, `is_writable`).
|
|
45
|
+
***************************************************************/
|
|
46
|
+
function field_is_readonly(form_readonly, field_desc)
|
|
47
|
+
{
|
|
48
|
+
if(form_readonly) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let desc = field_desc || {};
|
|
53
|
+
if(desc.type === "fkey") {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return !desc.is_writable;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
export {field_is_readonly};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {describe, it, expect} from "vitest";
|
|
2
|
+
import {field_is_readonly} from "./form_field_readonly.js";
|
|
3
|
+
|
|
4
|
+
describe("field_is_readonly", () => {
|
|
5
|
+
|
|
6
|
+
it("a form opened to LOOK has no editable field, fkey included", () => {
|
|
7
|
+
/* A record opened to be read: the schema does not enter into it. */
|
|
8
|
+
expect(field_is_readonly(true, {type: "fkey", is_writable: false}))
|
|
9
|
+
.toBe(true);
|
|
10
|
+
expect(field_is_readonly(true, {type: "fkey", is_writable: true}))
|
|
11
|
+
.toBe(true);
|
|
12
|
+
expect(field_is_readonly(true, {type: "string", is_writable: true}))
|
|
13
|
+
.toBe(true);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("an fkey is EDITABLE without `writable`: a link is edited by linking", () => {
|
|
17
|
+
/* `treedb_authzs`'s `users.roles` is declared `['fkey']` and
|
|
18
|
+
* nothing else -- as almost every fkey in the tree is. Reading
|
|
19
|
+
* that as "not editable" left a user with no way to be given a
|
|
20
|
+
* role, while the save path was still sending the column. */
|
|
21
|
+
expect(field_is_readonly(false, {type: "fkey", is_writable: false}))
|
|
22
|
+
.toBe(false);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("a plain column still needs `writable`", () => {
|
|
26
|
+
expect(field_is_readonly(false, {type: "string", is_writable: false}))
|
|
27
|
+
.toBe(true);
|
|
28
|
+
expect(field_is_readonly(false, {type: "string", is_writable: true}))
|
|
29
|
+
.toBe(false);
|
|
30
|
+
expect(field_is_readonly(false, {type: "enum", is_writable: false}))
|
|
31
|
+
.toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("a `file` column is NOT covered by the fkey exemption", () => {
|
|
35
|
+
/* It is an fkey (`['fkey','file']`) but answers `type: "file"`,
|
|
36
|
+
* and the SDK declares as legal a `file` column that only a load
|
|
37
|
+
* fills. */
|
|
38
|
+
expect(field_is_readonly(false, {type: "file", is_writable: false, is_file: true}))
|
|
39
|
+
.toBe(true);
|
|
40
|
+
expect(field_is_readonly(false, {type: "file", is_writable: true, is_file: true}))
|
|
41
|
+
.toBe(false);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("no descriptor is read-only, not editable", () => {
|
|
45
|
+
/* Nothing known about a field is not a reason to let it be
|
|
46
|
+
* written. */
|
|
47
|
+
expect(field_is_readonly(false, undefined)).toBe(true);
|
|
48
|
+
expect(field_is_readonly(false, {})).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
});
|