@yuneta/gobj-ui 5.16.0 → 5.17.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 +60 -10
- package/dist/gobj-ui.cjs.js +349 -56
- package/dist/gobj-ui.es.js +349 -56
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +38 -24
- package/src/c_yui_treedb_schema.js +348 -43
- package/src/treedb_node_label.js +73 -0
- package/src/treedb_node_label.test.js +92 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/***********************************************************************
|
|
2
|
+
* treedb_node_label.js
|
|
3
|
+
*
|
|
4
|
+
* Pure, testable logic behind the label of a node in the treedb
|
|
5
|
+
* graph: WHAT A RECORD IS CALLED, which is not always what it is
|
|
6
|
+
* keyed by. Kept out of the gclass so it can be unit-tested with
|
|
7
|
+
* no DOM and no G6.
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2026, ArtGins.
|
|
10
|
+
* All Rights Reserved.
|
|
11
|
+
***********************************************************************/
|
|
12
|
+
|
|
13
|
+
/************************************************************
|
|
14
|
+
* What a node is CALLED, which is not always what it is
|
|
15
|
+
* keyed by.
|
|
16
|
+
*
|
|
17
|
+
* A topic whose id column is flagged `rowid` or `uuid` keys
|
|
18
|
+
* its records by a value nobody reads — that is the point of
|
|
19
|
+
* those flags — and the name a human knows the record by
|
|
20
|
+
* lives in the secondary key the topic declares (`pkey2s`,
|
|
21
|
+
* carried in the desc since SDK > 7.13.0). The `topics` and
|
|
22
|
+
* `cols` topics of treedb_system_schema are the case that
|
|
23
|
+
* forced this: keyed by rowid, named in `value`, so every
|
|
24
|
+
* card in the graph read "181", "225", "193".
|
|
25
|
+
*
|
|
26
|
+
* The pkey stays reachable: it is the card's tooltip.
|
|
27
|
+
*
|
|
28
|
+
* Falls back to the id whenever the schema does not say
|
|
29
|
+
* otherwise — an older node whose desc carries no `pkey2s`
|
|
30
|
+
* included.
|
|
31
|
+
************************************************************/
|
|
32
|
+
export function node_label(desc, record)
|
|
33
|
+
{
|
|
34
|
+
/* treedb stores every record under `id` (the pkey name is fixed in
|
|
35
|
+
* tranger2_create_topic), so the fallback reads `id` while the FLAGS
|
|
36
|
+
* are read from whatever column the desc names as the pkey. */
|
|
37
|
+
let id = record.id;
|
|
38
|
+
|
|
39
|
+
let id_col = null;
|
|
40
|
+
if(Array.isArray(desc.cols)) {
|
|
41
|
+
for(let col of desc.cols) {
|
|
42
|
+
if(col && col.id === (desc.pkey || "id")) {
|
|
43
|
+
id_col = col;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if(!id_col || !Array.isArray(id_col.flag)) {
|
|
49
|
+
return id;
|
|
50
|
+
}
|
|
51
|
+
if(id_col.flag.indexOf("rowid") < 0 && id_col.flag.indexOf("uuid") < 0) {
|
|
52
|
+
return id;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* `pkey2s` is a list in the desc, but the schema literal may
|
|
56
|
+
* declare it as a bare string — take either. */
|
|
57
|
+
let pkey2s = desc.pkey2s;
|
|
58
|
+
if(typeof pkey2s === "string") {
|
|
59
|
+
pkey2s = pkey2s? [pkey2s] : [];
|
|
60
|
+
}
|
|
61
|
+
if(!Array.isArray(pkey2s)) {
|
|
62
|
+
return id;
|
|
63
|
+
}
|
|
64
|
+
for(let name of pkey2s) {
|
|
65
|
+
let value = record[name];
|
|
66
|
+
if(typeof value === "string" && value.length > 0) {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return id;
|
|
72
|
+
}
|
|
73
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/***********************************************************************
|
|
2
|
+
* treedb_node_label.test.js
|
|
3
|
+
*
|
|
4
|
+
* The label of a treedb graph node: the pkey when it names the
|
|
5
|
+
* record, the secondary key when the pkey is synthetic.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2026, ArtGins.
|
|
8
|
+
* All Rights Reserved.
|
|
9
|
+
***********************************************************************/
|
|
10
|
+
import {describe, it, expect} from "vitest";
|
|
11
|
+
|
|
12
|
+
import {node_label} from "./treedb_node_label.js";
|
|
13
|
+
|
|
14
|
+
/* The `cols` topic of treedb_system_schema, as the backend describes
|
|
15
|
+
* it: keyed by rowid, named in `value` (its pkey2). */
|
|
16
|
+
const COLS_DESC = {
|
|
17
|
+
topic_name: "cols",
|
|
18
|
+
pkey: "id",
|
|
19
|
+
pkey2s: ["value"],
|
|
20
|
+
cols: [
|
|
21
|
+
{id: "id", header: "rowid", type: "string", flag: ["persistent", "rowid"]},
|
|
22
|
+
{id: "value", header: "Column", type: "string", flag: ["persistent", "required"]},
|
|
23
|
+
{id: "header", header: "Header", type: "string", flag: ["persistent", "required"]},
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/* An ordinary topic: the pkey IS the name. */
|
|
28
|
+
const REALMS_DESC = {
|
|
29
|
+
topic_name: "realms",
|
|
30
|
+
pkey: "id",
|
|
31
|
+
cols: [
|
|
32
|
+
{id: "id", header: "id", type: "string", flag: ["persistent", "required"]},
|
|
33
|
+
{id: "realm_name", header: "Name", type: "string", flag: ["persistent", "required"]},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
describe("node_label", () => {
|
|
38
|
+
it("uses the secondary key when the pkey is a rowid", () => {
|
|
39
|
+
expect(node_label(COLS_DESC, {id: "181", value: "yuno_role"}))
|
|
40
|
+
.toBe("yuno_role");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("uses the pkey when it names the record", () => {
|
|
44
|
+
expect(node_label(REALMS_DESC, {id: "artgins.utilities.all", realm_name: "all"}))
|
|
45
|
+
.toBe("artgins.utilities.all");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("accepts a pkey2s declared as a bare string", () => {
|
|
49
|
+
let desc = {...COLS_DESC, pkey2s: "value"};
|
|
50
|
+
expect(node_label(desc, {id: "181", value: "yuno_role"})).toBe("yuno_role");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("treats a uuid pkey like a rowid one", () => {
|
|
54
|
+
let desc = {
|
|
55
|
+
...COLS_DESC,
|
|
56
|
+
cols: [
|
|
57
|
+
{id: "id", type: "string", flag: ["persistent", "uuid"]},
|
|
58
|
+
{id: "value", type: "string", flag: ["persistent", "required"]},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
expect(node_label(desc, {id: "3f2a…", value: "named"})).toBe("named");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("falls back to the id when the desc carries no pkey2s (older node)", () => {
|
|
65
|
+
let desc = {topic_name: "cols", pkey: "id", cols: COLS_DESC.cols};
|
|
66
|
+
expect(node_label(desc, {id: "181", value: "yuno_role"})).toBe("181");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("falls back to the id when the secondary key is empty in the record", () => {
|
|
70
|
+
expect(node_label(COLS_DESC, {id: "181", value: ""})).toBe("181");
|
|
71
|
+
expect(node_label(COLS_DESC, {id: "181"})).toBe("181");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("honours a pkey that is not called 'id'", () => {
|
|
75
|
+
let desc = {
|
|
76
|
+
topic_name: "x",
|
|
77
|
+
pkey: "key",
|
|
78
|
+
pkey2s: ["name"],
|
|
79
|
+
cols: [
|
|
80
|
+
{id: "key", type: "string", flag: ["persistent", "rowid"]},
|
|
81
|
+
{id: "name", type: "string", flag: ["persistent", "required"]},
|
|
82
|
+
/* A col called `id` that is NOT the pkey must not decide. */
|
|
83
|
+
{id: "id", type: "string", flag: ["persistent"]},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
expect(node_label(desc, {id: "7", key: "7", name: "seven"})).toBe("seven");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("survives a desc with no cols", () => {
|
|
90
|
+
expect(node_label({topic_name: "x", pkey: "id"}, {id: "42"})).toBe("42");
|
|
91
|
+
});
|
|
92
|
+
});
|