@yuneta/gobj-ui 7.23.168 → 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/README.md +2 -2
- package/dist/gobj-ui.cjs.js +784 -478
- package/dist/gobj-ui.es.js +784 -478
- package/package.json +2 -2
- package/src/broadcast_attrs.test.js +115 -0
- package/src/c_g6_nodes_tree.js +208 -19
- package/src/c_yui_treedb_topic_with_form.js +206 -107
- package/src/treedb_write_plan.js +47 -1
- package/src/treedb_write_plan.test.js +53 -1
- package/src/yui_row_search.js +56 -27
- package/src/yui_row_search.test.js +51 -1
package/src/yui_row_search.js
CHANGED
|
@@ -1,33 +1,38 @@
|
|
|
1
1
|
/***********************************************************************
|
|
2
2
|
* yui_row_search.js
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* IS THIS TERM IN THIS ROW?
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `[
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* había mirado en otro sitio.
|
|
6
|
+
* The search box of a treedb table looked at the row's values with
|
|
7
|
+
* `String(val)`, and a treedb row is not flat: an fkey arrives as a
|
|
8
|
+
* LIST OF OBJECTS `[{id, topic_name, hook_name}]`, and `String()`
|
|
9
|
+
* of that is `"[object Object]"`. So looking for the workshop of
|
|
10
|
+
* a device -- which is where the datum an operator has in mind
|
|
11
|
+
* lives -- never found anything, and the box gave no hint that it
|
|
12
|
+
* had looked somewhere else.
|
|
14
13
|
*
|
|
15
|
-
*
|
|
14
|
+
* THREE RULES, AND THE LAST TWO ARE WHAT MAKE IT USEFUL:
|
|
16
15
|
*
|
|
17
|
-
* -
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
16
|
+
* - It walks down lists and objects to a short depth: an fkey is
|
|
17
|
+
* two levels down and nothing anybody searches for is deeper.
|
|
18
|
+
* - **Of an fkey only the `id` is looked at.** `topic_name` and
|
|
19
|
+
* `hook_name` are the SAME two words on every row, so looking at
|
|
20
|
+
* them turns the term into a wildcard: searching "devices" would
|
|
21
|
+
* bring the whole topic. The `id` is the only thing that names
|
|
22
|
+
* the linked thing.
|
|
23
|
+
* - **A hook read as its COUNT is not looked at at all.** Since
|
|
24
|
+
* `hook_size` (7.23.163) a topic table loads a hook as
|
|
25
|
+
* `[{"size": N}]` instead of the id of every child, and that
|
|
26
|
+
* number is not a value of the row: matching it made "5" answer
|
|
27
|
+
* every row whose hook happens to hold 5 children, next to the
|
|
28
|
+
* rows that really say 5. A count nobody can see in the cell as
|
|
29
|
+
* text is not what a person typing in a search box is after.
|
|
25
30
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* (`__md_treedb__`),
|
|
31
|
+
* Keys that start with `_` are not looked at on any level: they
|
|
32
|
+
* belong to the scaffolding (`_check_box_state_`, `_operation`) or
|
|
33
|
+
* are metadata (`__md_treedb__`), and nobody searches by them.
|
|
29
34
|
*
|
|
30
|
-
* Copyright (c) 2026, ArtGins.
|
|
35
|
+
* Copyright (c) 2024-2026, ArtGins.
|
|
31
36
|
* All Rights Reserved.
|
|
32
37
|
***********************************************************************/
|
|
33
38
|
|
|
@@ -35,7 +40,7 @@ const MAX_DEPTH = 4;
|
|
|
35
40
|
|
|
36
41
|
|
|
37
42
|
/***************************************************************
|
|
38
|
-
*
|
|
43
|
+
* An fkey, as `nodes` answers it with `list_dict`.
|
|
39
44
|
***************************************************************/
|
|
40
45
|
function is_fkey_ref(value)
|
|
41
46
|
{
|
|
@@ -47,9 +52,29 @@ function is_fkey_ref(value)
|
|
|
47
52
|
&& ("hook_name" in value);
|
|
48
53
|
}
|
|
49
54
|
|
|
55
|
+
|
|
56
|
+
/***************************************************************
|
|
57
|
+
* A hook read with `hook_size`: the COUNT of its children,
|
|
58
|
+
* `[{"size": N}]`, in the place of the children themselves.
|
|
59
|
+
* The same shape `delete_impact`'s `ref_count()` reads.
|
|
60
|
+
***************************************************************/
|
|
61
|
+
function is_hook_size(value)
|
|
62
|
+
{
|
|
63
|
+
if(!Array.isArray(value) || value.length !== 1) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const first = value[0];
|
|
67
|
+
return !!first
|
|
68
|
+
&& typeof first === "object"
|
|
69
|
+
&& !Array.isArray(first)
|
|
70
|
+
&& typeof first.size === "number"
|
|
71
|
+
&& Object.keys(first).length === 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
50
75
|
/***************************************************************
|
|
51
|
-
*
|
|
52
|
-
*
|
|
76
|
+
* Does `value` hold the term? The term comes ALREADY in lower
|
|
77
|
+
* case: whoever searches lowers it once, not once per cell.
|
|
53
78
|
***************************************************************/
|
|
54
79
|
function value_matches(value, term, depth)
|
|
55
80
|
{
|
|
@@ -59,6 +84,9 @@ function value_matches(value, term, depth)
|
|
|
59
84
|
if(depth > MAX_DEPTH) {
|
|
60
85
|
return false;
|
|
61
86
|
}
|
|
87
|
+
if(is_hook_size(value)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
62
90
|
if(Array.isArray(value)) {
|
|
63
91
|
return value.some((v) => value_matches(v, term, depth + 1));
|
|
64
92
|
}
|
|
@@ -76,8 +104,9 @@ function value_matches(value, term, depth)
|
|
|
76
104
|
return String(value).toLowerCase().includes(term);
|
|
77
105
|
}
|
|
78
106
|
|
|
107
|
+
|
|
79
108
|
/***************************************************************
|
|
80
|
-
*
|
|
109
|
+
* Is the term anywhere in this row?
|
|
81
110
|
***************************************************************/
|
|
82
111
|
function row_matches(row, term)
|
|
83
112
|
{
|
|
@@ -93,4 +122,4 @@ function row_matches(row, term)
|
|
|
93
122
|
}
|
|
94
123
|
|
|
95
124
|
|
|
96
|
-
export {row_matches, value_matches, is_fkey_ref};
|
|
125
|
+
export {row_matches, value_matches, is_fkey_ref, is_hook_size};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {describe, it, expect} from "vitest";
|
|
2
2
|
|
|
3
|
-
import {row_matches, is_fkey_ref} from "./yui_row_search.js";
|
|
3
|
+
import {row_matches, is_fkey_ref, is_hook_size} from "./yui_row_search.js";
|
|
4
4
|
|
|
5
5
|
describe("row_matches", () => {
|
|
6
6
|
const row = {
|
|
@@ -52,6 +52,41 @@ describe("row_matches", () => {
|
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
describe("row_matches, on a table loaded with hook_size", () => {
|
|
56
|
+
/* What a topic table gets since 7.23.163: the hook is the COUNT
|
|
57
|
+
* of its children, not their ids. */
|
|
58
|
+
const row = {
|
|
59
|
+
id: "places-madrid",
|
|
60
|
+
name: "Madrid",
|
|
61
|
+
devices: [{size: 400}],
|
|
62
|
+
__md_treedb__: {topic_name: "places"}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
it("does NOT match the count of a hook", () => {
|
|
66
|
+
/* It did, and "400" then answered every place holding 400
|
|
67
|
+
* devices together with the ones that really say 400. */
|
|
68
|
+
expect(row_matches(row, "400")).toBe(false);
|
|
69
|
+
expect(row_matches(row, "40")).toBe(false);
|
|
70
|
+
expect(row_matches(row, "0")).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("still matches the rest of the row", () => {
|
|
74
|
+
expect(row_matches(row, "madrid")).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("still walks a hook that DID come with its children", () => {
|
|
78
|
+
/* A node event carries whole hooks whatever the table asked
|
|
79
|
+
* for, so both shapes reach this row. */
|
|
80
|
+
const loaded = {
|
|
81
|
+
id: "places-madrid",
|
|
82
|
+
devices: [
|
|
83
|
+
{id: "E22003089", topic_name: "devices", hook_name: "places"}
|
|
84
|
+
]
|
|
85
|
+
};
|
|
86
|
+
expect(row_matches(loaded, "e22003089")).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
55
90
|
describe("is_fkey_ref", () => {
|
|
56
91
|
it("wants the three keys", () => {
|
|
57
92
|
expect(is_fkey_ref({id: "a", topic_name: "t", hook_name: "h"})).toBe(true);
|
|
@@ -60,3 +95,18 @@ describe("is_fkey_ref", () => {
|
|
|
60
95
|
expect(is_fkey_ref(null)).toBe(false);
|
|
61
96
|
});
|
|
62
97
|
});
|
|
98
|
+
|
|
99
|
+
describe("is_hook_size", () => {
|
|
100
|
+
it("wants the one-element list holding only a numeric size", () => {
|
|
101
|
+
expect(is_hook_size([{size: 5}])).toBe(true);
|
|
102
|
+
expect(is_hook_size([{size: 0}])).toBe(true);
|
|
103
|
+
expect(is_hook_size([])).toBe(false);
|
|
104
|
+
expect(is_hook_size([{size: 5}, {size: 6}])).toBe(false);
|
|
105
|
+
expect(is_hook_size([{size: "5"}])).toBe(false);
|
|
106
|
+
expect(is_hook_size({size: 5})).toBe(false);
|
|
107
|
+
/* A record that happens to carry a `size` column is data, and
|
|
108
|
+
* is searched like any other. */
|
|
109
|
+
expect(is_hook_size([{id: "a", size: 5}])).toBe(false);
|
|
110
|
+
expect(is_hook_size(null)).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
});
|