@yuneta/gobj-ui 7.23.169 → 7.23.170

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.169",
3
+ "version": "7.23.170",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@rollup/plugin-terser": "^1.0.0",
32
32
  "@vitest/coverage-v8": "^4.1.10",
33
- "@yuneta/gobj-js": "^7.16.6",
33
+ "@yuneta/gobj-js": "^7.21.0",
34
34
  "vite": "^8.2.1",
35
35
  "vitest": "^4.1.10"
36
36
  },
@@ -96,7 +96,9 @@ import {t} from "i18next";
96
96
 
97
97
  import {yui_toolbar_icon} from "./yui_toolbar.js";
98
98
 
99
- import {plan_treedb_writes, READONLY_FORM_TOOLBAR} from "./treedb_write_plan.js";
99
+ import {
100
+ plan_treedb_writes, READONLY_FORM_TOOLBAR, col_goes_back_to_treedb
101
+ } from "./treedb_write_plan.js";
100
102
  import {
101
103
  yui_file_read, yui_files_manifest, yui_file_id_label, yui_file_size_label
102
104
  } from "./yui_file_field.js";
@@ -3262,42 +3264,6 @@ function get_schema_col(gobj, id)
3262
3264
  return null;
3263
3265
  }
3264
3266
 
3265
- /************************************************************
3266
- * Does column `col` travel back to treedb on a write?
3267
- *
3268
- * The form SHOWS every field and sends back only what the topic
3269
- * accepts: the writable cols, the fkeys (a link is edited by
3270
- * linking) and the pkey, which is not written but is what
3271
- * ADDRESSES the record.
3272
- *
3273
- * It matters because `treedb_update_node()` does not check
3274
- * `writable` -- it writes any col it is handed -- so a read-only
3275
- * field travelling back is written with whatever the form made of
3276
- * it, and the fields that describe a record are exactly the ones
3277
- * that do not survive a round trip through a widget: a `time` is an
3278
- * integer rendered as a `datetime-local`, with no seconds, so every
3279
- * save moved it back up to 59 s. Nothing looked wrong until the
3280
- * stored timestamp had moved.
3281
- *
3282
- * `is_file` and not the type: a `file` column IS an fkey (it is
3283
- * flagged ['fkey','file']) but answers `type: "file"`, and the write
3284
- * goes out with `autolink`, which rebuilds the links from what the
3285
- * record carries. Dropped, a read-only `file` column -- the one only
3286
- * a load fills -- was UNLINKED by every save of any other field.
3287
- ************************************************************/
3288
- function col_goes_back_to_treedb(gobj, col)
3289
- {
3290
- let desc = gobj_read_attr(gobj, "desc");
3291
- let pkey = desc.pkey || "id";
3292
- const field_desc = treedb_get_field_desc(col);
3293
-
3294
- if(field_desc.is_writable || field_desc.type === "fkey" ||
3295
- field_desc.is_file || col.id === pkey) {
3296
- return true;
3297
- }
3298
- return false;
3299
- }
3300
-
3301
3267
  /************************************************************
3302
3268
  * The record the FORM hands over, without the columns that do
3303
3269
  * not go back to treedb (see col_goes_back_to_treedb()). The
@@ -3309,7 +3275,7 @@ function strip_read_only_cols(gobj, record)
3309
3275
  let row = {};
3310
3276
  for(let field_name of Object.keys(record || {})) {
3311
3277
  let col = get_schema_col(gobj, field_name);
3312
- if(col && !col_goes_back_to_treedb(gobj, col)) {
3278
+ if(col && !col_goes_back_to_treedb(gobj_read_attr(gobj, "desc"), col)) {
3313
3279
  continue;
3314
3280
  }
3315
3281
  row[field_name] = record[field_name];
@@ -3336,7 +3302,7 @@ function transform__form_record_2_treedb_record(gobj, kw, operation)
3336
3302
  continue;
3337
3303
  }
3338
3304
 
3339
- if(!col_goes_back_to_treedb(gobj, col)) {
3305
+ if(!col_goes_back_to_treedb(gobj_read_attr(gobj, "desc"), col)) {
3340
3306
  continue;
3341
3307
  }
3342
3308
 
@@ -19,6 +19,9 @@
19
19
  * All Rights Reserved.
20
20
  ***********************************************************************/
21
21
 
22
+ import {treedb_get_field_desc} from "@yuneta/gobj-js";
23
+ import {topic_pkey2s} from "./schema_model.js";
24
+
22
25
  /* What a read-only form keeps: reading a record includes taking it with
23
26
  * you, so `copy` stays and the write half goes. */
24
27
  const READONLY_FORM_TOOLBAR = ["copy"];
@@ -70,4 +73,47 @@ function plan_treedb_writes(flags)
70
73
  }
71
74
 
72
75
 
73
- export {plan_treedb_writes, READONLY_FORM_TOOLBAR};
76
+ /************************************************************
77
+ * Does column `col` travel back to treedb on a write?
78
+ *
79
+ * The form SHOWS every field and sends back only what the topic
80
+ * accepts: the writable cols, the fkeys (a link is edited by
81
+ * linking) and the pkey, which is not written but is what
82
+ * ADDRESSES the record.
83
+ *
84
+ * It matters because `treedb_update_node()` does not check
85
+ * `writable` -- it writes any col it is handed -- so a read-only
86
+ * field travelling back is written with whatever the form made of
87
+ * it, and the fields that describe a record are exactly the ones
88
+ * that do not survive a round trip through a widget: a `time` is an
89
+ * integer rendered as a `datetime-local`, with no seconds, so every
90
+ * save moved it back up to 59 s. Nothing looked wrong until the
91
+ * stored timestamp had moved.
92
+ *
93
+ * `is_file` and not the type: a `file` column IS an fkey (it is
94
+ * flagged ['fkey','file']) but answers `type: "file"`, and the write
95
+ * goes out with `autolink`, which rebuilds the links from what the
96
+ * record carries. Dropped, a read-only `file` column -- the one only
97
+ * a load fills -- was UNLINKED by every save of any other field.
98
+ *
99
+ * The pkey2s go back for the same reason as the pkey: a secondary key
100
+ * names the INSTANCE the update is for (`yunos.yuno_release` in the
101
+ * agent), and it is `persistent, required`, not `writable`. Dropped,
102
+ * the update reached the backend with no pkey2 and C_NODE resolved it
103
+ * to the PRIMARY instance -- right by chance while the table lists
104
+ * primaries, wrong from a form opened on a row of `instances`.
105
+ ************************************************************/
106
+ function col_goes_back_to_treedb(desc, col)
107
+ {
108
+ let d = desc || {};
109
+ let pkey = d.pkey || "id";
110
+ const field_desc = treedb_get_field_desc(col);
111
+
112
+ if(field_desc.is_writable || field_desc.type === "fkey" ||
113
+ field_desc.is_file || col.id === pkey) {
114
+ return true;
115
+ }
116
+ return topic_pkey2s(d).includes(col.id);
117
+ }
118
+
119
+ export {plan_treedb_writes, READONLY_FORM_TOOLBAR, col_goes_back_to_treedb};
@@ -8,7 +8,9 @@
8
8
  * affordance back by accident.
9
9
  ***********************************************************************/
10
10
  import { describe, test, expect } from "vitest";
11
- import { plan_treedb_writes, READONLY_FORM_TOOLBAR } from "./treedb_write_plan.js";
11
+ import {
12
+ plan_treedb_writes, READONLY_FORM_TOOLBAR, col_goes_back_to_treedb
13
+ } from "./treedb_write_plan.js";
12
14
 
13
15
  const WRITES = ["edition_mode", "new_button", "delete_button", "paste_button", "in_row_icons"];
14
16
 
@@ -81,3 +83,53 @@ describe("readonly beats every with_*", () => {
81
83
  expect(plan_treedb_writes({readonly: "yes"}).new_button).toBe(false);
82
84
  });
83
85
  });
86
+
87
+
88
+ /***********************************************************************
89
+ * Which columns of a form go back in the write. The shape is the
90
+ * agent's `yunos`: a pkey, a secondary key that is required but not
91
+ * writable, and the read-only columns that never survive a widget.
92
+ ***********************************************************************/
93
+ const YUNOS_DESC = {
94
+ pkey: "id",
95
+ pkey2s: ["yuno_release"],
96
+ };
97
+ const COL = {
98
+ id: {id: "id", type: "string", flag: ["persistent", "required", "rowid"]},
99
+ yuno_release: {id: "yuno_release", type: "string", flag: ["persistent", "required"]},
100
+ yuno_name: {id: "yuno_name", type: "string", flag: ["persistent", "writable"]},
101
+ date: {id: "date", type: "integer", flag: ["persistent", "time"]},
102
+ realm_id: {id: "realm_id", type: "string", flag: ["persistent", "fkey"]},
103
+ photo: {id: "photo", type: "string", flag: ["persistent", "fkey", "file"]},
104
+ yunos: {id: "yunos", type: "object", flag: ["hook"], hook: {yunos: "realm_id"}},
105
+ };
106
+
107
+ describe("what goes back to treedb from a form", () => {
108
+ test("a writable column, an fkey and a file column go back", () => {
109
+ expect(col_goes_back_to_treedb(YUNOS_DESC, COL.yuno_name)).toBe(true);
110
+ expect(col_goes_back_to_treedb(YUNOS_DESC, COL.realm_id)).toBe(true);
111
+ expect(col_goes_back_to_treedb(YUNOS_DESC, COL.photo)).toBe(true);
112
+ });
113
+
114
+ test("a read-only time and a hook stay: they do not survive the widget", () => {
115
+ expect(col_goes_back_to_treedb(YUNOS_DESC, COL.date)).toBe(false);
116
+ expect(col_goes_back_to_treedb(YUNOS_DESC, COL.yunos)).toBe(false);
117
+ });
118
+
119
+ test("the pkey goes back although it is not writable: it addresses the record", () => {
120
+ expect(col_goes_back_to_treedb(YUNOS_DESC, COL.id)).toBe(true);
121
+ });
122
+
123
+ test("a pkey2 goes back although it is not writable: it names the INSTANCE", () => {
124
+ expect(col_goes_back_to_treedb(YUNOS_DESC, COL.yuno_release)).toBe(true);
125
+ });
126
+
127
+ test("a pkey2s declared as a bare string (the C literal) counts the same", () => {
128
+ expect(col_goes_back_to_treedb({pkey: "id", pkey2s: "yuno_release"}, COL.yuno_release)).toBe(true);
129
+ });
130
+
131
+ test("without pkey2s in the desc the same column stays read-only", () => {
132
+ expect(col_goes_back_to_treedb({pkey: "id"}, COL.yuno_release)).toBe(false);
133
+ expect(col_goes_back_to_treedb(null, COL.yuno_release)).toBe(false);
134
+ });
135
+ });