@yuneta/gobj-ui 7.23.65 → 7.23.67
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 +58 -0
- package/dist/gobj-ui.cjs.js +1330 -186
- package/dist/gobj-ui.es.js +1330 -186
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +1193 -256
- package/src/c_yui_treedb_graph.js +45 -2
- package/src/treedb_fold_model.js +592 -0
- package/src/treedb_fold_model.test.js +308 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -11254,7 +11254,7 @@ function ensure_drag_canvas_patch() {
|
|
|
11254
11254
|
* Constants
|
|
11255
11255
|
***************************************************************/
|
|
11256
11256
|
var GCLASS_NAME$13 = "C_YUI_JSON_GRAPH";
|
|
11257
|
-
var FOLD_SWALLOWED_EVENTS = [
|
|
11257
|
+
var FOLD_SWALLOWED_EVENTS$1 = [
|
|
11258
11258
|
"pointerdown",
|
|
11259
11259
|
"pointerup",
|
|
11260
11260
|
"mousedown",
|
|
@@ -11562,7 +11562,7 @@ function build_ui$12(gobj) {
|
|
|
11562
11562
|
keep: $card ? $card.getAttribute("data-json-path") : ""
|
|
11563
11563
|
}, gobj);
|
|
11564
11564
|
};
|
|
11565
|
-
for (let type of FOLD_SWALLOWED_EVENTS) $mount.addEventListener(type, priv.fold_listener, true);
|
|
11565
|
+
for (let type of FOLD_SWALLOWED_EVENTS$1) $mount.addEventListener(type, priv.fold_listener, true);
|
|
11566
11566
|
} else (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no canvas mount, fold handles are dead`);
|
|
11567
11567
|
priv.$layout_select = $container.querySelector(".JSON_GRAPH_LAYOUT");
|
|
11568
11568
|
priv.$find_input = $container.querySelector(".JSON_GRAPH_FIND_INPUT");
|
|
@@ -11578,7 +11578,7 @@ function destroy_ui$8(gobj) {
|
|
|
11578
11578
|
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
11579
11579
|
if (priv.fold_listener) {
|
|
11580
11580
|
let $mount = $container ? $container.querySelector("#" + priv.canvas_id) : null;
|
|
11581
|
-
if ($mount) for (let type of FOLD_SWALLOWED_EVENTS) $mount.removeEventListener(type, priv.fold_listener, true);
|
|
11581
|
+
if ($mount) for (let type of FOLD_SWALLOWED_EVENTS$1) $mount.removeEventListener(type, priv.fold_listener, true);
|
|
11582
11582
|
priv.fold_listener = null;
|
|
11583
11583
|
}
|
|
11584
11584
|
if ($container) {
|
|
@@ -12429,7 +12429,7 @@ function ac_change_layout$2(gobj, event, kw, src) {
|
|
|
12429
12429
|
* would throw away where the reader was looking. The toolbar
|
|
12430
12430
|
* pair, which changes everything at once, does refit.
|
|
12431
12431
|
************************************************************/
|
|
12432
|
-
function ac_toggle_fold(gobj, event, kw, src) {
|
|
12432
|
+
function ac_toggle_fold$1(gobj, event, kw, src) {
|
|
12433
12433
|
let priv = gobj.priv;
|
|
12434
12434
|
let path = kw && kw.path || "";
|
|
12435
12435
|
if ((0, _yuneta_gobj_js.empty_string)(path)) {
|
|
@@ -12468,7 +12468,7 @@ function ac_find_nodes$3(gobj, event, kw, src) {
|
|
|
12468
12468
|
/************************************************************
|
|
12469
12469
|
* EV_EXPAND_ALL
|
|
12470
12470
|
************************************************************/
|
|
12471
|
-
function ac_expand_all$
|
|
12471
|
+
function ac_expand_all$4(gobj, event, kw, src) {
|
|
12472
12472
|
let priv = gobj.priv;
|
|
12473
12473
|
if (priv.collapsed.size === 0) return 0;
|
|
12474
12474
|
priv.collapsed.clear();
|
|
@@ -12480,7 +12480,7 @@ function ac_expand_all$2(gobj, event, kw, src) {
|
|
|
12480
12480
|
/************************************************************
|
|
12481
12481
|
* EV_COLLAPSE_ALL — fold every card but the root.
|
|
12482
12482
|
************************************************************/
|
|
12483
|
-
function ac_collapse_all$
|
|
12483
|
+
function ac_collapse_all$4(gobj, event, kw, src) {
|
|
12484
12484
|
let priv = gobj.priv;
|
|
12485
12485
|
let json_data = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "json_data");
|
|
12486
12486
|
if (!json_data) return 0;
|
|
@@ -12770,7 +12770,7 @@ function create_gclass$13(gclass_name) {
|
|
|
12770
12770
|
],
|
|
12771
12771
|
[
|
|
12772
12772
|
"EV_TOGGLE_FOLD",
|
|
12773
|
-
ac_toggle_fold,
|
|
12773
|
+
ac_toggle_fold$1,
|
|
12774
12774
|
null
|
|
12775
12775
|
],
|
|
12776
12776
|
[
|
|
@@ -12780,12 +12780,12 @@ function create_gclass$13(gclass_name) {
|
|
|
12780
12780
|
],
|
|
12781
12781
|
[
|
|
12782
12782
|
"EV_EXPAND_ALL",
|
|
12783
|
-
ac_expand_all$
|
|
12783
|
+
ac_expand_all$4,
|
|
12784
12784
|
null
|
|
12785
12785
|
],
|
|
12786
12786
|
[
|
|
12787
12787
|
"EV_COLLAPSE_ALL",
|
|
12788
|
-
ac_collapse_all$
|
|
12788
|
+
ac_collapse_all$4,
|
|
12789
12789
|
null
|
|
12790
12790
|
],
|
|
12791
12791
|
[
|
|
@@ -13850,7 +13850,7 @@ function ac_search$2(gobj, event, kw, src) {
|
|
|
13850
13850
|
/************************************************************
|
|
13851
13851
|
* EV_EXPAND_ALL — expand every already-loaded container
|
|
13852
13852
|
************************************************************/
|
|
13853
|
-
function ac_expand_all$
|
|
13853
|
+
function ac_expand_all$3(gobj, event, kw, src) {
|
|
13854
13854
|
let priv = gobj.priv;
|
|
13855
13855
|
if (priv.root === null || priv.root === void 0) return 0;
|
|
13856
13856
|
let paths = [];
|
|
@@ -13868,7 +13868,7 @@ function ac_expand_all$1(gobj, event, kw, src) {
|
|
|
13868
13868
|
/************************************************************
|
|
13869
13869
|
* EV_COLLAPSE_ALL
|
|
13870
13870
|
************************************************************/
|
|
13871
|
-
function ac_collapse_all$
|
|
13871
|
+
function ac_collapse_all$3(gobj, event, kw, src) {
|
|
13872
13872
|
gobj.priv.expanded.clear();
|
|
13873
13873
|
render_view$1(gobj);
|
|
13874
13874
|
return 0;
|
|
@@ -14053,12 +14053,12 @@ function create_gclass$12(gclass_name) {
|
|
|
14053
14053
|
],
|
|
14054
14054
|
[
|
|
14055
14055
|
"EV_EXPAND_ALL",
|
|
14056
|
-
ac_expand_all$
|
|
14056
|
+
ac_expand_all$3,
|
|
14057
14057
|
null
|
|
14058
14058
|
],
|
|
14059
14059
|
[
|
|
14060
14060
|
"EV_COLLAPSE_ALL",
|
|
14061
|
-
ac_collapse_all$
|
|
14061
|
+
ac_collapse_all$3,
|
|
14062
14062
|
null
|
|
14063
14063
|
],
|
|
14064
14064
|
[
|
|
@@ -19061,7 +19061,7 @@ function ac_toggle_collapse(gobj, event, kw, src) {
|
|
|
19061
19061
|
/************************************************************
|
|
19062
19062
|
* Force every node visible (overrides threshold).
|
|
19063
19063
|
************************************************************/
|
|
19064
|
-
function ac_expand_all(gobj, event, kw, src) {
|
|
19064
|
+
function ac_expand_all$2(gobj, event, kw, src) {
|
|
19065
19065
|
let priv = gobj.priv;
|
|
19066
19066
|
if (!priv.collapse_state) priv.collapse_state = {};
|
|
19067
19067
|
if (priv.node_by_id) for (let id of Object.keys(priv.node_by_id)) {
|
|
@@ -19074,7 +19074,7 @@ function ac_expand_all(gobj, event, kw, src) {
|
|
|
19074
19074
|
/************************************************************
|
|
19075
19075
|
* Collapse every node that has children.
|
|
19076
19076
|
************************************************************/
|
|
19077
|
-
function ac_collapse_all(gobj, event, kw, src) {
|
|
19077
|
+
function ac_collapse_all$2(gobj, event, kw, src) {
|
|
19078
19078
|
let priv = gobj.priv;
|
|
19079
19079
|
if (!priv.collapse_state) priv.collapse_state = {};
|
|
19080
19080
|
if (priv.node_by_id) for (let id of Object.keys(priv.node_by_id)) {
|
|
@@ -19426,12 +19426,12 @@ function create_gclass$9(gclass_name) {
|
|
|
19426
19426
|
],
|
|
19427
19427
|
[
|
|
19428
19428
|
"EV_EXPAND_ALL",
|
|
19429
|
-
ac_expand_all,
|
|
19429
|
+
ac_expand_all$2,
|
|
19430
19430
|
null
|
|
19431
19431
|
],
|
|
19432
19432
|
[
|
|
19433
19433
|
"EV_COLLAPSE_ALL",
|
|
19434
|
-
ac_collapse_all,
|
|
19434
|
+
ac_collapse_all$2,
|
|
19435
19435
|
null
|
|
19436
19436
|
],
|
|
19437
19437
|
[
|
|
@@ -26800,6 +26800,429 @@ function node_label(desc, record) {
|
|
|
26800
26800
|
return id;
|
|
26801
26801
|
}
|
|
26802
26802
|
//#endregion
|
|
26803
|
+
//#region src/treedb_fold_model.js
|
|
26804
|
+
/***********************************************************************
|
|
26805
|
+
* treedb_fold_model.js
|
|
26806
|
+
*
|
|
26807
|
+
* A treedb read as a TREE, and which part of it is on screen.
|
|
26808
|
+
*
|
|
26809
|
+
* A treedb is a graph: a record hangs from every parent one of its
|
|
26810
|
+
* fkeys names, and a parent reaches its children through a hook.
|
|
26811
|
+
* Drawn whole it is a pile -- a nave with a hundred and forty
|
|
26812
|
+
* devices is a row of a hundred and forty cards -- so the graph
|
|
26813
|
+
* opens FOLDED, the way a JSON viewer opens: the roots, a level or
|
|
26814
|
+
* two under them, and a count on every cut saying what went with it.
|
|
26815
|
+
*
|
|
26816
|
+
* This module is the arithmetic of that, and nothing else: no G6,
|
|
26817
|
+
* no DOM, no gobj. The graph engine (c_g6_nodes_tree.js) asks it
|
|
26818
|
+
* what is visible and draws exactly that.
|
|
26819
|
+
*
|
|
26820
|
+
* Vocabulary
|
|
26821
|
+
*
|
|
26822
|
+
* node key "topic^id" -- one record
|
|
26823
|
+
* group the children of ONE node through ONE hook,
|
|
26824
|
+
* keyed "topic^id|hook"; the roots of a topic are
|
|
26825
|
+
* a group of their own, keyed "|topic"
|
|
26826
|
+
* shown how many of a group's children are on screen:
|
|
26827
|
+
* absent means folded, a number means the first
|
|
26828
|
+
* N, in record order, a page at a time
|
|
26829
|
+
*
|
|
26830
|
+
* Two rules that are not obvious:
|
|
26831
|
+
*
|
|
26832
|
+
* - A node is visible when SOME visible parent shows it, or it is
|
|
26833
|
+
* a shown root. A record with two parents (a device hangs from
|
|
26834
|
+
* its place AND its controller) is drawn ONCE, under whichever
|
|
26835
|
+
* opened first, and folding one of the two leaves it where the
|
|
26836
|
+
* other one shows it. The union, never the intersection.
|
|
26837
|
+
*
|
|
26838
|
+
* - A parent that the engine does not draw an edge to is not a
|
|
26839
|
+
* parent here either: the `extended` tier (hooks and no fkeys)
|
|
26840
|
+
* gets no edges in draw_link(), so its children are roots. The
|
|
26841
|
+
* tree on screen and the tree in this model have to agree, or a
|
|
26842
|
+
* pill counts children that no line reaches.
|
|
26843
|
+
*
|
|
26844
|
+
* Copyright (c) 2026, ArtGins.
|
|
26845
|
+
* All Rights Reserved.
|
|
26846
|
+
***********************************************************************/
|
|
26847
|
+
var PAGE_SIZE_DEFAULT = 24;
|
|
26848
|
+
/************************************************************
|
|
26849
|
+
* Keys
|
|
26850
|
+
************************************************************/
|
|
26851
|
+
function fold_node_key(topic_name, id) {
|
|
26852
|
+
return `${topic_name}^${id}`;
|
|
26853
|
+
}
|
|
26854
|
+
function fold_group_key(node_key, hook_name) {
|
|
26855
|
+
return `${node_key}|${hook_name}`;
|
|
26856
|
+
}
|
|
26857
|
+
function fold_root_group_key(topic_name) {
|
|
26858
|
+
return `|${topic_name}`;
|
|
26859
|
+
}
|
|
26860
|
+
function fold_split_group_key(group_key) {
|
|
26861
|
+
let i = group_key.lastIndexOf("|");
|
|
26862
|
+
if (i < 0) return null;
|
|
26863
|
+
return {
|
|
26864
|
+
node_key: group_key.slice(0, i),
|
|
26865
|
+
hook: group_key.slice(i + 1)
|
|
26866
|
+
};
|
|
26867
|
+
}
|
|
26868
|
+
/************************************************************
|
|
26869
|
+
* Every parent a record names, decoded, in column order.
|
|
26870
|
+
*
|
|
26871
|
+
* Only the parents that will be DRAWN: a topic missing from
|
|
26872
|
+
* `descs` (a system topic such as `__assets__`, never fetched)
|
|
26873
|
+
* and an `extended` parent (no edge is drawn to one, see the
|
|
26874
|
+
* header) are left out, so a child of nothing else is a root.
|
|
26875
|
+
************************************************************/
|
|
26876
|
+
function parents_of(descs, desc, record) {
|
|
26877
|
+
let out = [];
|
|
26878
|
+
let cols = desc.cols || [];
|
|
26879
|
+
for (let i = 0; i < cols.length; i++) {
|
|
26880
|
+
let col = cols[i];
|
|
26881
|
+
if (!col.fkey) continue;
|
|
26882
|
+
let fkeys = record[col.id];
|
|
26883
|
+
if (!fkeys) continue;
|
|
26884
|
+
let list = (0, _yuneta_gobj_js.is_array)(fkeys) ? fkeys : [fkeys];
|
|
26885
|
+
for (let j = 0; j < list.length; j++) {
|
|
26886
|
+
let ref = (0, _yuneta_gobj_js.treedb_decoder_fkey)(col, list[j]);
|
|
26887
|
+
if (!ref || !ref.topic_name || !ref.hook_name) continue;
|
|
26888
|
+
let parent_desc = descs[ref.topic_name];
|
|
26889
|
+
if (!parent_desc) continue;
|
|
26890
|
+
if (parent_desc.node_treedb_type === "extended") continue;
|
|
26891
|
+
out.push({
|
|
26892
|
+
node_key: fold_node_key(ref.topic_name, String(ref.id)),
|
|
26893
|
+
hook: ref.hook_name,
|
|
26894
|
+
fkey_name: col.id
|
|
26895
|
+
});
|
|
26896
|
+
}
|
|
26897
|
+
}
|
|
26898
|
+
return out;
|
|
26899
|
+
}
|
|
26900
|
+
/************************************************************
|
|
26901
|
+
* Build the model from the topic descriptions and their records.
|
|
26902
|
+
*
|
|
26903
|
+
* descs {topic_name: desc}, system topics included (skipped)
|
|
26904
|
+
* records {topic_name: [record, ...]}, in the order the
|
|
26905
|
+
* backend returned them -- that order is the order of
|
|
26906
|
+
* the children on screen, and of the pages
|
|
26907
|
+
*
|
|
26908
|
+
* Returns
|
|
26909
|
+
* {
|
|
26910
|
+
* nodes: Map<node_key, {key, topic_name, id, record,
|
|
26911
|
+
* parents: [{node_key, hook, fkey_name}],
|
|
26912
|
+
* hooks: {hook: [child_key, ...]}}>
|
|
26913
|
+
* groups: Map<group_key, [child_key, ...]> (roots included)
|
|
26914
|
+
* topics: [topic_name, ...] topics with records, in desc order
|
|
26915
|
+
* }
|
|
26916
|
+
************************************************************/
|
|
26917
|
+
function fold_build_model(descs, records) {
|
|
26918
|
+
let nodes = /* @__PURE__ */ new Map();
|
|
26919
|
+
let groups = /* @__PURE__ */ new Map();
|
|
26920
|
+
let topics = [];
|
|
26921
|
+
descs = (0, _yuneta_gobj_js.is_object)(descs) ? descs : {};
|
|
26922
|
+
records = (0, _yuneta_gobj_js.is_object)(records) ? records : {};
|
|
26923
|
+
for (let topic_name of Object.keys(descs)) {
|
|
26924
|
+
if (topic_name.substring(0, 2) === "__") continue;
|
|
26925
|
+
descs[topic_name];
|
|
26926
|
+
let list = records[topic_name];
|
|
26927
|
+
if (!(0, _yuneta_gobj_js.is_array)(list)) continue;
|
|
26928
|
+
topics.push(topic_name);
|
|
26929
|
+
for (let i = 0; i < list.length; i++) {
|
|
26930
|
+
let record = list[i];
|
|
26931
|
+
if (!(0, _yuneta_gobj_js.is_object)(record) || record.id === void 0 || record.id === null) continue;
|
|
26932
|
+
let key = fold_node_key(topic_name, String(record.id));
|
|
26933
|
+
nodes.set(key, {
|
|
26934
|
+
key,
|
|
26935
|
+
topic_name,
|
|
26936
|
+
id: String(record.id),
|
|
26937
|
+
record,
|
|
26938
|
+
parents: [],
|
|
26939
|
+
hooks: {}
|
|
26940
|
+
});
|
|
26941
|
+
}
|
|
26942
|
+
}
|
|
26943
|
+
for (let node of nodes.values()) {
|
|
26944
|
+
let desc = descs[node.topic_name];
|
|
26945
|
+
let parents = parents_of(descs, desc, node.record);
|
|
26946
|
+
for (let p of parents) {
|
|
26947
|
+
let parent = nodes.get(p.node_key);
|
|
26948
|
+
if (!parent) continue;
|
|
26949
|
+
node.parents.push(p);
|
|
26950
|
+
if (!parent.hooks[p.hook]) parent.hooks[p.hook] = [];
|
|
26951
|
+
parent.hooks[p.hook].push(node.key);
|
|
26952
|
+
}
|
|
26953
|
+
}
|
|
26954
|
+
for (let node of nodes.values()) for (let hook of Object.keys(node.hooks)) groups.set(fold_group_key(node.key, hook), node.hooks[hook]);
|
|
26955
|
+
let roots = {};
|
|
26956
|
+
for (let topic_name of topics) roots[topic_name] = [];
|
|
26957
|
+
for (let node of nodes.values()) if (node.parents.length === 0) roots[node.topic_name].push(node.key);
|
|
26958
|
+
let reached = reach_from(nodes, [].concat(...Object.values(roots)));
|
|
26959
|
+
for (let node of nodes.values()) if (!reached.has(node.key)) {
|
|
26960
|
+
roots[node.topic_name].push(node.key);
|
|
26961
|
+
for (let k of reach_from(nodes, [node.key])) reached.add(k);
|
|
26962
|
+
}
|
|
26963
|
+
for (let topic_name of topics) if (roots[topic_name].length > 0) groups.set(fold_root_group_key(topic_name), roots[topic_name]);
|
|
26964
|
+
return {
|
|
26965
|
+
nodes,
|
|
26966
|
+
groups,
|
|
26967
|
+
topics
|
|
26968
|
+
};
|
|
26969
|
+
}
|
|
26970
|
+
/************************************************************
|
|
26971
|
+
* Everything reachable downwards from `start`, cycles included.
|
|
26972
|
+
************************************************************/
|
|
26973
|
+
function reach_from(nodes, start) {
|
|
26974
|
+
let seen = /* @__PURE__ */ new Set();
|
|
26975
|
+
let queue = start.slice();
|
|
26976
|
+
while (queue.length) {
|
|
26977
|
+
let key = queue.shift();
|
|
26978
|
+
if (seen.has(key)) continue;
|
|
26979
|
+
seen.add(key);
|
|
26980
|
+
let node = nodes.get(key);
|
|
26981
|
+
if (!node) continue;
|
|
26982
|
+
for (let hook of Object.keys(node.hooks)) for (let child of node.hooks[hook]) if (!seen.has(child)) queue.push(child);
|
|
26983
|
+
}
|
|
26984
|
+
return seen;
|
|
26985
|
+
}
|
|
26986
|
+
/************************************************************
|
|
26987
|
+
* Fold state: which groups are open, and how far.
|
|
26988
|
+
************************************************************/
|
|
26989
|
+
function fold_new_state(page_size) {
|
|
26990
|
+
return {
|
|
26991
|
+
page_size: page_size > 0 ? page_size : PAGE_SIZE_DEFAULT,
|
|
26992
|
+
shown: /* @__PURE__ */ new Map()
|
|
26993
|
+
};
|
|
26994
|
+
}
|
|
26995
|
+
function fold_group_total(model, group_key) {
|
|
26996
|
+
let list = model.groups.get(group_key);
|
|
26997
|
+
return list ? list.length : 0;
|
|
26998
|
+
}
|
|
26999
|
+
function fold_group_shown(model, state, group_key) {
|
|
27000
|
+
let total = fold_group_total(model, group_key);
|
|
27001
|
+
let n = state.shown.get(group_key) || 0;
|
|
27002
|
+
return Math.min(n, total);
|
|
27003
|
+
}
|
|
27004
|
+
function fold_is_open(state, group_key) {
|
|
27005
|
+
return (state.shown.get(group_key) || 0) > 0;
|
|
27006
|
+
}
|
|
27007
|
+
function page_ceiling(state, n) {
|
|
27008
|
+
let p = state.page_size;
|
|
27009
|
+
return Math.ceil(n / p) * p;
|
|
27010
|
+
}
|
|
27011
|
+
/************************************************************
|
|
27012
|
+
* Open a group on its first page, or close it.
|
|
27013
|
+
* Returns true when it ends OPEN.
|
|
27014
|
+
************************************************************/
|
|
27015
|
+
function fold_toggle(model, state, group_key) {
|
|
27016
|
+
if (fold_is_open(state, group_key)) {
|
|
27017
|
+
state.shown.delete(group_key);
|
|
27018
|
+
return false;
|
|
27019
|
+
}
|
|
27020
|
+
if (fold_group_total(model, group_key) === 0) return false;
|
|
27021
|
+
state.shown.set(group_key, state.page_size);
|
|
27022
|
+
return true;
|
|
27023
|
+
}
|
|
27024
|
+
/************************************************************
|
|
27025
|
+
* One more page of a group. Returns how many are shown now.
|
|
27026
|
+
************************************************************/
|
|
27027
|
+
function fold_show_more(model, state, group_key) {
|
|
27028
|
+
let total = fold_group_total(model, group_key);
|
|
27029
|
+
let n = fold_group_shown(model, state, group_key) + state.page_size;
|
|
27030
|
+
n = Math.min(n, total);
|
|
27031
|
+
if (n > 0) state.shown.set(group_key, n);
|
|
27032
|
+
return n;
|
|
27033
|
+
}
|
|
27034
|
+
/************************************************************
|
|
27035
|
+
* Every group open on ALL its children. This is the reader
|
|
27036
|
+
* asking for the whole thing; the pages are for the other way in.
|
|
27037
|
+
************************************************************/
|
|
27038
|
+
function fold_expand_all(model, state) {
|
|
27039
|
+
state.shown.clear();
|
|
27040
|
+
for (let [group_key, list] of model.groups) if (list.length > 0) state.shown.set(group_key, list.length);
|
|
27041
|
+
}
|
|
27042
|
+
/************************************************************
|
|
27043
|
+
* The roots and nothing else -- the first page of each topic's
|
|
27044
|
+
* roots, the way the graph looks before anything is opened.
|
|
27045
|
+
************************************************************/
|
|
27046
|
+
function fold_collapse_all(model, state) {
|
|
27047
|
+
state.shown.clear();
|
|
27048
|
+
for (let topic_name of model.topics) {
|
|
27049
|
+
let key = fold_root_group_key(topic_name);
|
|
27050
|
+
if (fold_group_total(model, key) > 0) state.shown.set(key, state.page_size);
|
|
27051
|
+
}
|
|
27052
|
+
}
|
|
27053
|
+
/************************************************************
|
|
27054
|
+
* Open the tree down to `depth` levels: the roots are level 1,
|
|
27055
|
+
* their children level 2. A node reached by two paths takes the
|
|
27056
|
+
* shallowest. Each group opens on its first page. `depth` of 1
|
|
27057
|
+
* is the roots alone; anything below that is treated as 1.
|
|
27058
|
+
************************************************************/
|
|
27059
|
+
function fold_expand_to_depth(model, state, depth) {
|
|
27060
|
+
fold_collapse_all(model, state);
|
|
27061
|
+
if (!(depth > 1)) return;
|
|
27062
|
+
let level = /* @__PURE__ */ new Map();
|
|
27063
|
+
let queue = [];
|
|
27064
|
+
for (let topic_name of model.topics) {
|
|
27065
|
+
let roots = model.groups.get(fold_root_group_key(topic_name)) || [];
|
|
27066
|
+
for (let key of roots) if (!level.has(key)) {
|
|
27067
|
+
level.set(key, 1);
|
|
27068
|
+
queue.push(key);
|
|
27069
|
+
}
|
|
27070
|
+
}
|
|
27071
|
+
while (queue.length) {
|
|
27072
|
+
let key = queue.shift();
|
|
27073
|
+
let lv = level.get(key);
|
|
27074
|
+
if (lv >= depth) continue;
|
|
27075
|
+
let node = model.nodes.get(key);
|
|
27076
|
+
if (!node) continue;
|
|
27077
|
+
for (let hook of Object.keys(node.hooks)) {
|
|
27078
|
+
let children = node.hooks[hook];
|
|
27079
|
+
if (children.length === 0) continue;
|
|
27080
|
+
state.shown.set(fold_group_key(key, hook), state.page_size);
|
|
27081
|
+
for (let child of children) if (!level.has(child)) {
|
|
27082
|
+
level.set(child, lv + 1);
|
|
27083
|
+
queue.push(child);
|
|
27084
|
+
}
|
|
27085
|
+
}
|
|
27086
|
+
}
|
|
27087
|
+
}
|
|
27088
|
+
/************************************************************
|
|
27089
|
+
* The set of node keys on screen, from the roots down through
|
|
27090
|
+
* every open group -- and only through open groups whose parent
|
|
27091
|
+
* is itself on screen: a group remembered open under a folded
|
|
27092
|
+
* ancestor stays remembered, not shown.
|
|
27093
|
+
************************************************************/
|
|
27094
|
+
function fold_visible_set(model, state) {
|
|
27095
|
+
let visible = /* @__PURE__ */ new Set();
|
|
27096
|
+
let queue = [];
|
|
27097
|
+
let push_group = (group_key, children) => {
|
|
27098
|
+
let n = fold_group_shown(model, state, group_key);
|
|
27099
|
+
for (let i = 0; i < n; i++) {
|
|
27100
|
+
let key = children[i];
|
|
27101
|
+
if (!visible.has(key)) {
|
|
27102
|
+
visible.add(key);
|
|
27103
|
+
queue.push(key);
|
|
27104
|
+
}
|
|
27105
|
+
}
|
|
27106
|
+
};
|
|
27107
|
+
for (let topic_name of model.topics) {
|
|
27108
|
+
let key = fold_root_group_key(topic_name);
|
|
27109
|
+
let roots = model.groups.get(key);
|
|
27110
|
+
if (roots) push_group(key, roots);
|
|
27111
|
+
}
|
|
27112
|
+
while (queue.length) {
|
|
27113
|
+
let key = queue.shift();
|
|
27114
|
+
let node = model.nodes.get(key);
|
|
27115
|
+
if (!node) continue;
|
|
27116
|
+
for (let hook of Object.keys(node.hooks)) push_group(fold_group_key(key, hook), node.hooks[hook]);
|
|
27117
|
+
}
|
|
27118
|
+
return visible;
|
|
27119
|
+
}
|
|
27120
|
+
/************************************************************
|
|
27121
|
+
* The open groups that still have children off screen, with the
|
|
27122
|
+
* parent that owns each -- what the "+N" chips are drawn for.
|
|
27123
|
+
* Only groups whose parent is visible (or root groups).
|
|
27124
|
+
*
|
|
27125
|
+
* Returns [{group_key, node_key, hook, shown, total, rest}]
|
|
27126
|
+
************************************************************/
|
|
27127
|
+
function fold_pending_groups(model, state, visible) {
|
|
27128
|
+
let out = [];
|
|
27129
|
+
for (let [group_key, list] of model.groups) {
|
|
27130
|
+
let shown = fold_group_shown(model, state, group_key);
|
|
27131
|
+
if (shown === 0 || shown >= list.length) continue;
|
|
27132
|
+
let g = fold_split_group_key(group_key);
|
|
27133
|
+
if (g.node_key && !visible.has(g.node_key)) continue;
|
|
27134
|
+
out.push({
|
|
27135
|
+
group_key,
|
|
27136
|
+
node_key: g.node_key,
|
|
27137
|
+
hook: g.hook,
|
|
27138
|
+
shown,
|
|
27139
|
+
total: list.length,
|
|
27140
|
+
rest: list.length - shown
|
|
27141
|
+
});
|
|
27142
|
+
}
|
|
27143
|
+
return out;
|
|
27144
|
+
}
|
|
27145
|
+
/************************************************************
|
|
27146
|
+
* The pills of one card: one per hook that has children.
|
|
27147
|
+
*
|
|
27148
|
+
* Returns [{hook, group_key, total, shown, open, child_topic}]
|
|
27149
|
+
* `child_topic` is the topic of the first child, which is what
|
|
27150
|
+
* the pill is coloured with (a hook can name several topics in
|
|
27151
|
+
* the schema, but the children it has are what it links).
|
|
27152
|
+
************************************************************/
|
|
27153
|
+
function fold_pills_of(model, state, node_key) {
|
|
27154
|
+
let node = model.nodes.get(node_key);
|
|
27155
|
+
if (!node) return [];
|
|
27156
|
+
let out = [];
|
|
27157
|
+
for (let hook of Object.keys(node.hooks)) {
|
|
27158
|
+
let children = node.hooks[hook];
|
|
27159
|
+
if (children.length === 0) continue;
|
|
27160
|
+
let group_key = fold_group_key(node_key, hook);
|
|
27161
|
+
let first = model.nodes.get(children[0]);
|
|
27162
|
+
out.push({
|
|
27163
|
+
hook,
|
|
27164
|
+
group_key,
|
|
27165
|
+
total: children.length,
|
|
27166
|
+
shown: fold_group_shown(model, state, group_key),
|
|
27167
|
+
open: fold_is_open(state, group_key),
|
|
27168
|
+
child_topic: first ? first.topic_name : ""
|
|
27169
|
+
});
|
|
27170
|
+
}
|
|
27171
|
+
return out;
|
|
27172
|
+
}
|
|
27173
|
+
/************************************************************
|
|
27174
|
+
* Make ONE node visible, opening the groups on a path from a
|
|
27175
|
+
* root to it, and as many pages of each as it takes for the
|
|
27176
|
+
* node to be inside the shown prefix. Prefers the shortest path
|
|
27177
|
+
* (breadth-first upwards). Returns false if no root reaches it,
|
|
27178
|
+
* which cannot happen with a model built here (see roots) but
|
|
27179
|
+
* is the honest answer for a key the model does not know.
|
|
27180
|
+
************************************************************/
|
|
27181
|
+
function fold_reveal(model, state, node_key) {
|
|
27182
|
+
if (!model.nodes.get(node_key)) return false;
|
|
27183
|
+
let root_group_of = (key) => {
|
|
27184
|
+
let rg = fold_root_group_key(model.nodes.get(key).topic_name);
|
|
27185
|
+
return (model.groups.get(rg) || []).indexOf(key) >= 0 ? rg : null;
|
|
27186
|
+
};
|
|
27187
|
+
let via = /* @__PURE__ */ new Map();
|
|
27188
|
+
let queue = [node_key];
|
|
27189
|
+
via.set(node_key, null);
|
|
27190
|
+
let root_key = null;
|
|
27191
|
+
while (queue.length) {
|
|
27192
|
+
let key = queue.shift();
|
|
27193
|
+
if (root_group_of(key)) {
|
|
27194
|
+
root_key = key;
|
|
27195
|
+
break;
|
|
27196
|
+
}
|
|
27197
|
+
let n = model.nodes.get(key);
|
|
27198
|
+
for (let p of n.parents) {
|
|
27199
|
+
if (!model.nodes.has(p.node_key) || via.has(p.node_key)) continue;
|
|
27200
|
+
via.set(p.node_key, {
|
|
27201
|
+
child_key: key,
|
|
27202
|
+
hook: p.hook
|
|
27203
|
+
});
|
|
27204
|
+
queue.push(p.node_key);
|
|
27205
|
+
}
|
|
27206
|
+
}
|
|
27207
|
+
if (root_key === null) return false;
|
|
27208
|
+
let open_up_to = (group_key, child_key) => {
|
|
27209
|
+
let list = model.groups.get(group_key) || [];
|
|
27210
|
+
let idx = list.indexOf(child_key);
|
|
27211
|
+
if (idx < 0) return;
|
|
27212
|
+
let need = page_ceiling(state, idx + 1);
|
|
27213
|
+
if (need > (state.shown.get(group_key) || 0)) state.shown.set(group_key, Math.min(need, list.length));
|
|
27214
|
+
};
|
|
27215
|
+
open_up_to(root_group_of(root_key), root_key);
|
|
27216
|
+
let key = root_key;
|
|
27217
|
+
while (true) {
|
|
27218
|
+
let step = via.get(key);
|
|
27219
|
+
if (!step) break;
|
|
27220
|
+
open_up_to(fold_group_key(key, step.hook), step.child_key);
|
|
27221
|
+
key = step.child_key;
|
|
27222
|
+
}
|
|
27223
|
+
return true;
|
|
27224
|
+
}
|
|
27225
|
+
//#endregion
|
|
26803
27226
|
//#region node_modules/@babel/runtime/helpers/esm/typeof.js
|
|
26804
27227
|
function _typeof(o) {
|
|
26805
27228
|
"@babel/helpers - typeof";
|
|
@@ -53544,6 +53967,23 @@ function ensure_brush_select_owned() {
|
|
|
53544
53967
|
* record: null, // Data of node
|
|
53545
53968
|
* }
|
|
53546
53969
|
*
|
|
53970
|
+
* The graph opens FOLDED, like a JSON viewer.
|
|
53971
|
+
*
|
|
53972
|
+
* Every record of every topic is fetched, but only the ones on
|
|
53973
|
+
* screen become G6 nodes: the roots, `expand_depth` levels under
|
|
53974
|
+
* them, one page (`fold_page_size`) of children per hook. Each
|
|
53975
|
+
* card carries a pill per hook that has children -- `▸ devices
|
|
53976
|
+
* 142` -- which opens or folds that hook; an open hook with more
|
|
53977
|
+
* children than its page ends in a `+N` chip that opens the next
|
|
53978
|
+
* page. The arithmetic lives in treedb_fold_model.js; this file
|
|
53979
|
+
* reconciles the G6 data with what that model says is visible
|
|
53980
|
+
* (see reconcile_fold) and lays it out again.
|
|
53981
|
+
*
|
|
53982
|
+
* `dagre` reads LEFT TO RIGHT: the children of a node are a
|
|
53983
|
+
* column beside it, the ports move to the sides with it, and
|
|
53984
|
+
* the edges are horizontal beziers. `antv-dagre` keeps the
|
|
53985
|
+
* top-down reading.
|
|
53986
|
+
*
|
|
53547
53987
|
* Copyright (c) 2020-2021 Niyamaka.
|
|
53548
53988
|
* Copyright (c) 2025-2026, ArtGins.
|
|
53549
53989
|
* All Rights Reserved.
|
|
@@ -53603,8 +54043,18 @@ var SELECT_RING = "rgba(59,130,246,0.95)";
|
|
|
53603
54043
|
***************************************************************/
|
|
53604
54044
|
var _layouts = {
|
|
53605
54045
|
"manual": { type: "manual" },
|
|
53606
|
-
"dagre": {
|
|
53607
|
-
|
|
54046
|
+
"dagre": {
|
|
54047
|
+
type: "dagre",
|
|
54048
|
+
rankdir: "LR",
|
|
54049
|
+
nodesep: 18,
|
|
54050
|
+
ranksep: 110
|
|
54051
|
+
},
|
|
54052
|
+
"antv-dagre": {
|
|
54053
|
+
type: "antv-dagre",
|
|
54054
|
+
rankdir: "TB",
|
|
54055
|
+
nodesep: 30,
|
|
54056
|
+
ranksep: 80
|
|
54057
|
+
},
|
|
53608
54058
|
"d3-force": {
|
|
53609
54059
|
type: "d3-force",
|
|
53610
54060
|
link: {
|
|
@@ -53652,6 +54102,8 @@ var attrs_table$4 = [
|
|
|
53652
54102
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_LIST, "layout_names", _yuneta_gobj_js.sdata_flag_t.SDF_RD, JSON.stringify(Object.keys(_layouts)), "Available layout names (read-only, for parent to query)"),
|
|
53653
54103
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "hook_port_position", 0, "bottom", "Hook port position"),
|
|
53654
54104
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "fkey_port_position", 0, "top", "Fkey port position"),
|
|
54105
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_INTEGER, "expand_depth", 0, 2, "Levels open when a treedb loads: 1 = the roots alone, 2 = the roots and their children. Every open hook shows its first page"),
|
|
54106
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_INTEGER, "fold_page_size", 0, 24, "Children of one hook shown per page; the `+N` chip after the page opens the next one"),
|
|
53655
54107
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "confirm_delete_node", 0, true, "Ask confirmation before deleting a node"),
|
|
53656
54108
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "confirm_unlink_edge", 0, true, "Ask confirmation before unlinking an edge"),
|
|
53657
54109
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "wide", 0, "40px", "Height of header"),
|
|
@@ -53720,10 +54172,18 @@ var PRIVATE_DATA$4 = {
|
|
|
53720
54172
|
selection_mode: false,
|
|
53721
54173
|
_selected_paint_ids: [],
|
|
53722
54174
|
_pending_focus_topic: null,
|
|
54175
|
+
_pending_focus_all: false,
|
|
53723
54176
|
_pending_find: null,
|
|
53724
54177
|
_layout_asked: "",
|
|
53725
54178
|
_nodes_total: 0,
|
|
53726
|
-
_nodes_placed: 0
|
|
54179
|
+
_nodes_placed: 0,
|
|
54180
|
+
expand_depth: 2,
|
|
54181
|
+
fold_page_size: 24,
|
|
54182
|
+
_fold_model: null,
|
|
54183
|
+
_fold_state: null,
|
|
54184
|
+
_fold_listener: null,
|
|
54185
|
+
_pill_sig: null,
|
|
54186
|
+
_fold_busy: false
|
|
53727
54187
|
};
|
|
53728
54188
|
var __gclass__$4 = null;
|
|
53729
54189
|
/******************************
|
|
@@ -53743,6 +54203,7 @@ function mt_create$4(gobj) {
|
|
|
53743
54203
|
build_ui$4(gobj);
|
|
53744
54204
|
register_layouts(gobj);
|
|
53745
54205
|
build_graph$1(gobj);
|
|
54206
|
+
install_fold_listener(gobj);
|
|
53746
54207
|
if (typeof ResizeObserver !== "undefined" && priv.$container) {
|
|
53747
54208
|
let ro = new ResizeObserver(() => {
|
|
53748
54209
|
if (priv._resize_raf) cancelAnimationFrame(priv._resize_raf);
|
|
@@ -53782,6 +54243,7 @@ function mt_destroy$4(gobj) {
|
|
|
53782
54243
|
i18next.default.off("languageChanged", priv._on_language_changed);
|
|
53783
54244
|
priv._on_language_changed = null;
|
|
53784
54245
|
}
|
|
54246
|
+
uninstall_fold_listener(gobj);
|
|
53785
54247
|
if (priv._on_pointerdown_focus) {
|
|
53786
54248
|
priv.$container.removeEventListener("pointerdown", priv._on_pointerdown_focus, true);
|
|
53787
54249
|
priv._on_pointerdown_focus = null;
|
|
@@ -53969,6 +54431,7 @@ function configure_events(gobj) {
|
|
|
53969
54431
|
});
|
|
53970
54432
|
priv._on_language_changed = () => {
|
|
53971
54433
|
update_toolbar(gobj);
|
|
54434
|
+
repaint_more_chips(gobj);
|
|
53972
54435
|
};
|
|
53973
54436
|
i18next.default.on("languageChanged", priv._on_language_changed);
|
|
53974
54437
|
priv._on_pointerdown_focus = (ev) => {
|
|
@@ -54466,15 +54929,79 @@ function build_ports(gobj, desc) {
|
|
|
54466
54929
|
top_ports.push(port);
|
|
54467
54930
|
}
|
|
54468
54931
|
}
|
|
54469
|
-
|
|
54470
|
-
for (let i = 0; i < bottom_ports.length; i++) {
|
|
54471
|
-
let point = getPointPosition(bottom_ports.length, i);
|
|
54472
|
-
if (top_ports.length === 0) bottom_ports[i].placement = [0, .5];
|
|
54473
|
-
else bottom_ports[i].placement = [point, 1];
|
|
54474
|
-
}
|
|
54932
|
+
place_ports(gobj, top_ports, bottom_ports);
|
|
54475
54933
|
return [...top_ports, ...bottom_ports];
|
|
54476
54934
|
}
|
|
54477
54935
|
/************************************************************
|
|
54936
|
+
* Which way the graph reads. `dagre` is the left-to-right
|
|
54937
|
+
* layout; everything else keeps the top-down reading, `manual`
|
|
54938
|
+
* included, because the saved arrangements were made with the
|
|
54939
|
+
* ports on the top and bottom edges.
|
|
54940
|
+
************************************************************/
|
|
54941
|
+
function layout_direction(gobj) {
|
|
54942
|
+
return gobj.priv.layout === "dagre" ? "LR" : "TB";
|
|
54943
|
+
}
|
|
54944
|
+
function edge_type_for(gobj) {
|
|
54945
|
+
return layout_direction(gobj) === "LR" ? "cubic-horizontal" : "cubic";
|
|
54946
|
+
}
|
|
54947
|
+
/************************************************************
|
|
54948
|
+
* Where the ports sit, by direction: fkeys (the way in from a
|
|
54949
|
+
* parent) all on one point of the leading edge, hooks (the way
|
|
54950
|
+
* out to the children) spread along the trailing edge. Left and
|
|
54951
|
+
* right when the graph reads left to right; top and bottom
|
|
54952
|
+
* otherwise.
|
|
54953
|
+
************************************************************/
|
|
54954
|
+
function place_ports(gobj, fkey_ports, hook_ports) {
|
|
54955
|
+
let lr = layout_direction(gobj) === "LR";
|
|
54956
|
+
for (let i = 0; i < fkey_ports.length; i++) fkey_ports[i].placement = lr ? [0, .5] : [.5, 0];
|
|
54957
|
+
for (let i = 0; i < hook_ports.length; i++) {
|
|
54958
|
+
let point = getPointPosition(hook_ports.length, i);
|
|
54959
|
+
if (fkey_ports.length === 0 && !lr) hook_ports[i].placement = [0, .5];
|
|
54960
|
+
else if (lr) hook_ports[i].placement = [1, point];
|
|
54961
|
+
else hook_ports[i].placement = [point, 1];
|
|
54962
|
+
}
|
|
54963
|
+
}
|
|
54964
|
+
/************************************************************
|
|
54965
|
+
* The layout changed direction: move every port to the edge
|
|
54966
|
+
* the new reading needs, and give every edge the curve that
|
|
54967
|
+
* goes with it. Called before the layout runs, so the lines
|
|
54968
|
+
* are drawn once, in the right place.
|
|
54969
|
+
************************************************************/
|
|
54970
|
+
function apply_layout_direction(gobj) {
|
|
54971
|
+
let graph = gobj.priv.graph;
|
|
54972
|
+
if (!graph) return;
|
|
54973
|
+
let node_updates = [];
|
|
54974
|
+
for (let nd of graph.getNodeData() || []) {
|
|
54975
|
+
if (!nd || !nd.data || !nd.data.desc || !nd.style || !(0, _yuneta_gobj_js.is_array)(nd.style.ports)) continue;
|
|
54976
|
+
let desc = nd.data.desc;
|
|
54977
|
+
let fkey_ports = [];
|
|
54978
|
+
let hook_ports = [];
|
|
54979
|
+
for (let port of nd.style.ports) {
|
|
54980
|
+
let col = get_col_by_id(desc, port.key);
|
|
54981
|
+
let copy = Object.assign({}, port);
|
|
54982
|
+
if (col && col.fkey) fkey_ports.push(copy);
|
|
54983
|
+
else hook_ports.push(copy);
|
|
54984
|
+
}
|
|
54985
|
+
place_ports(gobj, fkey_ports, hook_ports);
|
|
54986
|
+
node_updates.push({
|
|
54987
|
+
id: nd.id,
|
|
54988
|
+
style: { ports: [...fkey_ports, ...hook_ports] }
|
|
54989
|
+
});
|
|
54990
|
+
}
|
|
54991
|
+
let type = edge_type_for(gobj);
|
|
54992
|
+
let edge_updates = [];
|
|
54993
|
+
for (let ed of graph.getEdgeData() || []) if (ed && ed.type !== type) edge_updates.push({
|
|
54994
|
+
id: ed.id,
|
|
54995
|
+
type
|
|
54996
|
+
});
|
|
54997
|
+
try {
|
|
54998
|
+
if (node_updates.length) graph.updateNodeData(node_updates);
|
|
54999
|
+
if (edge_updates.length) graph.updateEdgeData(edge_updates);
|
|
55000
|
+
} catch (e) {
|
|
55001
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot turn the ports: ${e}`);
|
|
55002
|
+
}
|
|
55003
|
+
}
|
|
55004
|
+
/************************************************************
|
|
54478
55005
|
* Create a topic node in the G6 graph
|
|
54479
55006
|
************************************************************/
|
|
54480
55007
|
function create_topic_node(gobj, desc, record) {
|
|
@@ -54483,8 +55010,6 @@ function create_topic_node(gobj, desc, record) {
|
|
|
54483
55010
|
let node_name = build_node_name(gobj, desc.topic_name, record.id);
|
|
54484
55011
|
let xy = get_default_ne_xy(gobj);
|
|
54485
55012
|
let geometry = get_node_graph_props(gobj, desc.topic_name, record.id, record);
|
|
54486
|
-
priv._nodes_total++;
|
|
54487
|
-
if (geometry_has_position(geometry)) priv._nodes_placed++;
|
|
54488
55013
|
let x = (0, _yuneta_gobj_js.kw_get_int)(gobj, geometry, "x", xy, _yuneta_gobj_js.kw_flag_t.KW_CREATE);
|
|
54489
55014
|
let y = (0, _yuneta_gobj_js.kw_get_int)(gobj, geometry, "y", xy, _yuneta_gobj_js.kw_flag_t.KW_CREATE);
|
|
54490
55015
|
let ports = build_ports(gobj, desc);
|
|
@@ -54497,24 +55022,26 @@ function create_topic_node(gobj, desc, record) {
|
|
|
54497
55022
|
stroke: getStrokeColor(desc.color),
|
|
54498
55023
|
lineWidth: 1
|
|
54499
55024
|
};
|
|
55025
|
+
let pills_html = pills_html_of_key(gobj, fold_node_key(desc.topic_name, String(record.id)));
|
|
55026
|
+
let size = card_size_for(node_treedb_type, !!pills_html);
|
|
54500
55027
|
if (node_treedb_type === "child") {
|
|
54501
55028
|
node_graph_type = "html";
|
|
54502
|
-
style.size =
|
|
54503
|
-
style.dx = -
|
|
54504
|
-
style.dy = -
|
|
55029
|
+
style.size = size;
|
|
55030
|
+
style.dx = -size[0] / 2;
|
|
55031
|
+
style.dy = -size[1] / 2;
|
|
54505
55032
|
style.innerHTML = build_chip_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), record.id);
|
|
54506
55033
|
} else if (node_treedb_type === "extended") {
|
|
54507
55034
|
node_graph_type = "html";
|
|
54508
|
-
style.size =
|
|
54509
|
-
style.dx = -
|
|
54510
|
-
style.dy = -
|
|
54511
|
-
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, true, record.id);
|
|
55035
|
+
style.size = size;
|
|
55036
|
+
style.dx = -size[0] / 2;
|
|
55037
|
+
style.dy = -size[1] / 2;
|
|
55038
|
+
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, true, record.id, false, false, false, pills_html);
|
|
54512
55039
|
} else {
|
|
54513
55040
|
node_graph_type = "html";
|
|
54514
|
-
style.size =
|
|
54515
|
-
style.dx = -
|
|
54516
|
-
style.dy = -
|
|
54517
|
-
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, false, record.id);
|
|
55041
|
+
style.size = size;
|
|
55042
|
+
style.dx = -size[0] / 2;
|
|
55043
|
+
style.dy = -size[1] / 2;
|
|
55044
|
+
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, false, record.id, false, false, false, pills_html);
|
|
54518
55045
|
}
|
|
54519
55046
|
let topic_props = priv._graph_properties[desc.topic_name];
|
|
54520
55047
|
let topic_defaults = (0, _yuneta_gobj_js.is_object)(topic_props) && (0, _yuneta_gobj_js.is_object)(topic_props.defaults) ? topic_props.defaults : null;
|
|
@@ -54571,8 +55098,7 @@ function create_topic_node(gobj, desc, record) {
|
|
|
54571
55098
|
* Update topic node data
|
|
54572
55099
|
************************************************************/
|
|
54573
55100
|
function update_topic_node(gobj, desc, node_name, record) {
|
|
54574
|
-
let
|
|
54575
|
-
let graph = priv.graph;
|
|
55101
|
+
let graph = gobj.priv.graph;
|
|
54576
55102
|
try {
|
|
54577
55103
|
let nodedata = graph.getNodeData(node_name);
|
|
54578
55104
|
if (!nodedata) {
|
|
@@ -54580,18 +55106,7 @@ function update_topic_node(gobj, desc, node_name, record) {
|
|
|
54580
55106
|
return;
|
|
54581
55107
|
}
|
|
54582
55108
|
nodedata.data.record = record;
|
|
54583
|
-
|
|
54584
|
-
id: node_name,
|
|
54585
|
-
style: { innerHTML: build_chip_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), record.id) }
|
|
54586
|
-
}]);
|
|
54587
|
-
else if (desc.node_treedb_type === "extended") graph.updateNodeData([{
|
|
54588
|
-
id: node_name,
|
|
54589
|
-
style: { innerHTML: build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, true, record.id) }
|
|
54590
|
-
}]);
|
|
54591
|
-
else if (desc.node_treedb_type === "hierarchical") graph.updateNodeData([{
|
|
54592
|
-
id: node_name,
|
|
54593
|
-
style: { innerHTML: build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, false, record.id) }
|
|
54594
|
-
}]);
|
|
55109
|
+
repaint_cards(gobj, /* @__PURE__ */ new Set([node_name]));
|
|
54595
55110
|
} catch (e) {
|
|
54596
55111
|
(0, _yuneta_gobj_js.log_error)(e.message);
|
|
54597
55112
|
}
|
|
@@ -54630,19 +55145,6 @@ function remove_local_node(gobj, topic_name, node) {
|
|
|
54630
55145
|
}
|
|
54631
55146
|
}
|
|
54632
55147
|
/************************************************************
|
|
54633
|
-
* Create all links from records, initial load from parent
|
|
54634
|
-
************************************************************/
|
|
54635
|
-
function create_links(gobj) {
|
|
54636
|
-
let priv = gobj.priv;
|
|
54637
|
-
for (const [topic_name, records] of Object.entries(priv.records)) {
|
|
54638
|
-
let desc = priv.descs[topic_name];
|
|
54639
|
-
for (let i = 0; i < records.length; i++) {
|
|
54640
|
-
let record = records[i];
|
|
54641
|
-
draw_links(gobj, desc, record, true);
|
|
54642
|
-
}
|
|
54643
|
-
}
|
|
54644
|
-
}
|
|
54645
|
-
/************************************************************
|
|
54646
55148
|
* Collect all fkey references from a record as a Set.
|
|
54647
55149
|
*
|
|
54648
55150
|
* Each entry is a string: "col_id\tcol_idx\tfkey_value"
|
|
@@ -54722,6 +55224,17 @@ function draw_link(gobj, child_topic, child_id, source_col, fkey, verbose) {
|
|
|
54722
55224
|
return;
|
|
54723
55225
|
}
|
|
54724
55226
|
let child_node = build_node_name(gobj, child_topic, child_id);
|
|
55227
|
+
let child_cell = null;
|
|
55228
|
+
try {
|
|
55229
|
+
child_cell = graph.getNodeData(child_node);
|
|
55230
|
+
} catch (e) {
|
|
55231
|
+
child_cell = null;
|
|
55232
|
+
}
|
|
55233
|
+
if (!child_cell) {
|
|
55234
|
+
if (verbose) (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: child node NOT FOUND: ${child_node}`);
|
|
55235
|
+
return;
|
|
55236
|
+
}
|
|
55237
|
+
if (get_edge_by_link(gobj, parent_topic, parent_id, hook_name, child_topic, child_id, fkey_name)) return;
|
|
54725
55238
|
let dark = priv.theme === "dark";
|
|
54726
55239
|
let is_tree = parent_topic === child_topic;
|
|
54727
55240
|
let saved_lineWidth = is_tree ? 2 : 1.6;
|
|
@@ -54760,7 +55273,7 @@ function draw_link(gobj, child_topic, child_id, source_col, fkey, verbose) {
|
|
|
54760
55273
|
}
|
|
54761
55274
|
let edge = {
|
|
54762
55275
|
id: build_edge_id(gobj),
|
|
54763
|
-
type:
|
|
55276
|
+
type: edge_type_for(gobj),
|
|
54764
55277
|
source: parent_node,
|
|
54765
55278
|
target: child_node,
|
|
54766
55279
|
style: {
|
|
@@ -54891,7 +55404,10 @@ function save_geometry(gobj) {
|
|
|
54891
55404
|
let priv = gobj.priv;
|
|
54892
55405
|
let graph = priv.graph;
|
|
54893
55406
|
const nodes = graph.getData().nodes;
|
|
54894
|
-
for (let i = 0; i < nodes.length; i++)
|
|
55407
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
55408
|
+
if (!nodes[i].data || !nodes[i].data.desc) continue;
|
|
55409
|
+
update_geometry(gobj, nodes[i].id);
|
|
55410
|
+
}
|
|
54895
55411
|
const edges = graph.getData().edges;
|
|
54896
55412
|
for (let i = 0; i < edges.length; i++) update_edge_geometry(gobj, edges[i].id);
|
|
54897
55413
|
let origin = (0, _yuneta_gobj_js.gobj_read_str_attr)((0, _yuneta_gobj_js.gobj_yuno)(), "node_uuid");
|
|
@@ -55146,40 +55662,75 @@ async function graph_fit_selection(gobj, ids) {
|
|
|
55146
55662
|
* once the data loads (see ac_load_data). Guarded end-to-end — a
|
|
55147
55663
|
* missing G6 API or an unknown topic logs and no-ops, never throws.
|
|
55148
55664
|
************************************************************/
|
|
55149
|
-
function graph_focus_topic(gobj, topic) {
|
|
55665
|
+
function graph_focus_topic(gobj, topic, reveal_all) {
|
|
55150
55666
|
let priv = gobj.priv;
|
|
55151
|
-
|
|
55152
|
-
if (!graph || !priv.graph_rendered) {
|
|
55667
|
+
if (!priv.graph || !priv.graph_rendered || !priv._fold_model) {
|
|
55153
55668
|
priv._pending_focus_topic = topic;
|
|
55669
|
+
priv._pending_focus_all = !!reveal_all;
|
|
55154
55670
|
return;
|
|
55155
55671
|
}
|
|
55156
|
-
let
|
|
55157
|
-
|
|
55158
|
-
|
|
55159
|
-
|
|
55160
|
-
(
|
|
55161
|
-
|
|
55672
|
+
let model = priv._fold_model;
|
|
55673
|
+
let state = priv._fold_state;
|
|
55674
|
+
let keys = [];
|
|
55675
|
+
if (!(0, _yuneta_gobj_js.empty_string)(topic)) {
|
|
55676
|
+
for (let node of model.nodes.values()) if (node.topic_name === topic) keys.push(node.key);
|
|
55677
|
+
if (keys.length === 0) (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: focus topic '${topic}' has no nodes`);
|
|
55678
|
+
let visible = fold_visible_set(model, state);
|
|
55679
|
+
let revealed = 0;
|
|
55680
|
+
for (let key of keys) {
|
|
55681
|
+
if (visible.has(key)) continue;
|
|
55682
|
+
if (!reveal_all && revealed >= state.page_size) break;
|
|
55683
|
+
fold_reveal(model, state, key);
|
|
55684
|
+
revealed++;
|
|
55685
|
+
}
|
|
55162
55686
|
}
|
|
55163
|
-
|
|
55687
|
+
priv._focus_topic = topic || null;
|
|
55688
|
+
reconcile_fold(gobj, {}).then(() => {
|
|
55689
|
+
apply_focus_ids(gobj, keys, "focus topic");
|
|
55690
|
+
});
|
|
55691
|
+
}
|
|
55692
|
+
/************************************************************
|
|
55693
|
+
* Paint the highlight on these records (by model key) and put
|
|
55694
|
+
* the first of them in the middle. Shared by the find and the
|
|
55695
|
+
* topic focus, after the reconcile that brought them on screen.
|
|
55696
|
+
* Keys that are still off screen are skipped: a match beyond the
|
|
55697
|
+
* page a reveal opened is counted, not painted.
|
|
55698
|
+
************************************************************/
|
|
55699
|
+
function apply_focus_ids(gobj, keys, what) {
|
|
55700
|
+
let priv = gobj.priv;
|
|
55701
|
+
let graph = priv.graph;
|
|
55702
|
+
if (!graph) return;
|
|
55164
55703
|
let states = {};
|
|
55165
55704
|
for (let id of priv._focus_ids || []) states[id] = [];
|
|
55166
55705
|
let ids = [];
|
|
55167
|
-
|
|
55168
|
-
|
|
55169
|
-
|
|
55170
|
-
|
|
55706
|
+
for (let key of keys) {
|
|
55707
|
+
let id = node_id_of_key(gobj, key);
|
|
55708
|
+
let nd = null;
|
|
55709
|
+
try {
|
|
55710
|
+
nd = graph.getNodeData(id);
|
|
55711
|
+
} catch (e) {
|
|
55712
|
+
nd = null;
|
|
55713
|
+
}
|
|
55714
|
+
if (nd) {
|
|
55715
|
+
ids.push(id);
|
|
55716
|
+
states[id] = ["active"];
|
|
55717
|
+
}
|
|
55171
55718
|
}
|
|
55172
55719
|
let prev_ids = priv._focus_ids || [];
|
|
55173
55720
|
priv._focus_ids = ids;
|
|
55174
|
-
priv._focus_topic = topic || null;
|
|
55175
55721
|
try {
|
|
55176
55722
|
if (typeof graph.setElementState === "function") graph.setElementState(states);
|
|
55177
55723
|
apply_node_highlight(gobj, prev_ids, ids);
|
|
55178
|
-
if (ids.length
|
|
55724
|
+
if (ids.length) yui_graph_center_on(graph, ids[0]);
|
|
55179
55725
|
} catch (e) {
|
|
55180
|
-
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}:
|
|
55726
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${what} apply failed: ${e}`);
|
|
55181
55727
|
}
|
|
55182
55728
|
}
|
|
55729
|
+
function node_id_of_key(gobj, key) {
|
|
55730
|
+
let i = key.indexOf("^");
|
|
55731
|
+
if (i < 0) return "";
|
|
55732
|
+
return build_node_name(gobj, key.slice(0, i), key.slice(i + 1));
|
|
55733
|
+
}
|
|
55183
55734
|
/************************************************************
|
|
55184
55735
|
* Find the nodes whose name, id or topic contains `term`, highlight
|
|
55185
55736
|
* them with the same amber 'active' state the topic focus uses, and
|
|
@@ -55196,52 +55747,43 @@ function graph_focus_topic(gobj, topic) {
|
|
|
55196
55747
|
************************************************************/
|
|
55197
55748
|
function graph_find_nodes(gobj, term) {
|
|
55198
55749
|
let priv = gobj.priv;
|
|
55199
|
-
|
|
55200
|
-
if (!graph || !priv.graph_rendered) {
|
|
55750
|
+
if (!priv.graph || !priv.graph_rendered || !priv._fold_model) {
|
|
55201
55751
|
priv._pending_find = term;
|
|
55202
55752
|
return 0;
|
|
55203
55753
|
}
|
|
55204
|
-
let
|
|
55205
|
-
|
|
55206
|
-
|
|
55207
|
-
} catch (e) {
|
|
55208
|
-
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: graph.getData() failed: ${e}`);
|
|
55209
|
-
return 0;
|
|
55210
|
-
}
|
|
55211
|
-
let nodes = (0, _yuneta_gobj_js.is_array)(data.nodes) ? data.nodes : [];
|
|
55212
|
-
let states = {};
|
|
55213
|
-
for (let id of priv._focus_ids || []) states[id] = [];
|
|
55214
|
-
let ids = [];
|
|
55754
|
+
let model = priv._fold_model;
|
|
55755
|
+
let state = priv._fold_state;
|
|
55756
|
+
let keys = [];
|
|
55215
55757
|
if (!(0, _yuneta_gobj_js.empty_string)(term)) {
|
|
55216
55758
|
let needle = String(term).toLowerCase();
|
|
55217
|
-
for (let
|
|
55218
|
-
|
|
55219
|
-
let record = n.data.record || {};
|
|
55759
|
+
for (let node of model.nodes.values()) {
|
|
55760
|
+
let record = node.record || {};
|
|
55220
55761
|
let label = "";
|
|
55221
55762
|
try {
|
|
55222
|
-
label = node_label(
|
|
55763
|
+
label = node_label(priv.descs[node.topic_name] || {}, record) || "";
|
|
55223
55764
|
} catch (e) {
|
|
55224
55765
|
label = "";
|
|
55225
55766
|
}
|
|
55226
55767
|
if ([
|
|
55227
55768
|
label,
|
|
55228
55769
|
record.id,
|
|
55229
|
-
|
|
55230
|
-
].filter((v) => typeof v === "string").join(" ").toLowerCase().includes(needle))
|
|
55770
|
+
node.topic_name
|
|
55771
|
+
].filter((v) => typeof v === "string").join(" ").toLowerCase().includes(needle)) keys.push(node.key);
|
|
55231
55772
|
}
|
|
55232
|
-
for (let id of ids) states[id] = ["active"];
|
|
55233
55773
|
}
|
|
55234
|
-
let
|
|
55235
|
-
|
|
55236
|
-
|
|
55237
|
-
|
|
55238
|
-
if (
|
|
55239
|
-
|
|
55240
|
-
|
|
55241
|
-
} catch (e) {
|
|
55242
|
-
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: find apply failed: ${e}`);
|
|
55774
|
+
let visible = fold_visible_set(model, state);
|
|
55775
|
+
let revealed = 0;
|
|
55776
|
+
for (let key of keys) {
|
|
55777
|
+
if (visible.has(key)) continue;
|
|
55778
|
+
if (revealed >= state.page_size) break;
|
|
55779
|
+
fold_reveal(model, state, key);
|
|
55780
|
+
revealed++;
|
|
55243
55781
|
}
|
|
55244
|
-
|
|
55782
|
+
priv._focus_topic = null;
|
|
55783
|
+
reconcile_fold(gobj, {}).then(() => {
|
|
55784
|
+
apply_focus_ids(gobj, keys, "find");
|
|
55785
|
+
});
|
|
55786
|
+
return keys.length;
|
|
55245
55787
|
}
|
|
55246
55788
|
async function graph_zoom_in(gobj) {
|
|
55247
55789
|
let graph = gobj.priv.graph;
|
|
@@ -55354,20 +55896,43 @@ var LightNode = class extends _antv_g6.Circle {
|
|
|
55354
55896
|
************************************************************/
|
|
55355
55897
|
var ManualLayout = class extends _antv_g6.BaseLayout {
|
|
55356
55898
|
async execute(data, options) {
|
|
55357
|
-
const { nodes = [] } = data;
|
|
55358
|
-
|
|
55359
|
-
|
|
55360
|
-
|
|
55899
|
+
const { nodes = [], edges = [] } = data;
|
|
55900
|
+
let placed = {};
|
|
55901
|
+
let out = [];
|
|
55902
|
+
let chips = [];
|
|
55903
|
+
for (let node of nodes) {
|
|
55904
|
+
let d = node.data || {};
|
|
55905
|
+
if (d.more) {
|
|
55906
|
+
chips.push(node);
|
|
55907
|
+
continue;
|
|
55908
|
+
}
|
|
55909
|
+
let gp = d.graph_props;
|
|
55910
|
+
let geo = d.record ? d.record._geometry : null;
|
|
55361
55911
|
let x = gp && gp.x != null ? gp.x : geo && geo.x != null ? geo.x : 0;
|
|
55362
55912
|
let y = gp && gp.y != null ? gp.y : geo && geo.y != null ? geo.y : 0;
|
|
55363
|
-
|
|
55913
|
+
placed[node.id] = [x, y];
|
|
55914
|
+
out.push({
|
|
55364
55915
|
id: node.id,
|
|
55365
55916
|
style: {
|
|
55366
55917
|
x,
|
|
55367
55918
|
y
|
|
55368
55919
|
}
|
|
55369
|
-
};
|
|
55370
|
-
}
|
|
55920
|
+
});
|
|
55921
|
+
}
|
|
55922
|
+
for (let node of chips) {
|
|
55923
|
+
let edge = edges.find((e) => e.target === node.id);
|
|
55924
|
+
let p = edge ? placed[edge.source] : null;
|
|
55925
|
+
let x = p ? p[0] : node.style && node.style.x || 0;
|
|
55926
|
+
let y = p ? p[1] + 80 : node.style && node.style.y || 0;
|
|
55927
|
+
out.push({
|
|
55928
|
+
id: node.id,
|
|
55929
|
+
style: {
|
|
55930
|
+
x,
|
|
55931
|
+
y
|
|
55932
|
+
}
|
|
55933
|
+
});
|
|
55934
|
+
}
|
|
55935
|
+
return { nodes: out };
|
|
55371
55936
|
}
|
|
55372
55937
|
};
|
|
55373
55938
|
/************************************************************
|
|
@@ -56871,7 +57436,7 @@ function show_node_popover(gobj) {
|
|
|
56871
57436
|
};
|
|
56872
57437
|
if (node_graph_type === "hierarchical") {
|
|
56873
57438
|
let record = nodeData.data.record || {};
|
|
56874
|
-
updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id);
|
|
57439
|
+
updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nodeData));
|
|
56875
57440
|
}
|
|
56876
57441
|
graph.updateNodeData([{
|
|
56877
57442
|
id: node_id,
|
|
@@ -56911,7 +57476,7 @@ function show_node_popover(gobj) {
|
|
|
56911
57476
|
};
|
|
56912
57477
|
if (node_graph_type === "hierarchical") {
|
|
56913
57478
|
let record = nodeData.data.record || {};
|
|
56914
|
-
restoreStyle.innerHTML = build_node_innerHTML(origFill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id);
|
|
57479
|
+
restoreStyle.innerHTML = build_node_innerHTML(origFill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nodeData));
|
|
56915
57480
|
}
|
|
56916
57481
|
graph.updateNodeData([{
|
|
56917
57482
|
id: node_id,
|
|
@@ -57096,6 +57661,7 @@ function refresh_minimap(gobj) {
|
|
|
57096
57661
|
let nd = graph.getNodeData(id);
|
|
57097
57662
|
let size = nd && nd.style && nd.style.size || [120, 60];
|
|
57098
57663
|
let color = nd && nd.data && nd.data.desc && nd.data.desc.color || "#94a3b8";
|
|
57664
|
+
if (is_more_node(nd)) color = "rgba(148, 163, 184, 0.35)";
|
|
57099
57665
|
return new Rect({ style: {
|
|
57100
57666
|
x: -size[0] / 2,
|
|
57101
57667
|
y: -size[1] / 2,
|
|
@@ -57118,15 +57684,15 @@ function refresh_minimap(gobj) {
|
|
|
57118
57684
|
* same three-way choice — it lived inline in the theme refresh and is
|
|
57119
57685
|
* shared now. Returns null for a node that carries no desc.
|
|
57120
57686
|
************************************************************/
|
|
57121
|
-
function node_innerHTML_of(nd, theme, highlight, selected, anchored) {
|
|
57687
|
+
function node_innerHTML_of(nd, theme, highlight, selected, anchored, pills_html) {
|
|
57122
57688
|
if (!nd || !nd.data || !nd.data.desc) return null;
|
|
57123
57689
|
let desc = nd.data.desc;
|
|
57124
57690
|
let record = nd.data.record || {};
|
|
57125
57691
|
let label = node_label(desc, record);
|
|
57126
57692
|
switch (desc.node_treedb_type) {
|
|
57127
57693
|
case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight, selected, anchored);
|
|
57128
|
-
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected, anchored);
|
|
57129
|
-
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected, anchored);
|
|
57694
|
+
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected, anchored, pills_html);
|
|
57695
|
+
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected, anchored, pills_html);
|
|
57130
57696
|
}
|
|
57131
57697
|
return null;
|
|
57132
57698
|
}
|
|
@@ -57147,7 +57713,13 @@ function repaint_cards(gobj, ids) {
|
|
|
57147
57713
|
let selected = new Set(priv._selected_paint_ids || []);
|
|
57148
57714
|
let updates = [];
|
|
57149
57715
|
for (let id of ids) {
|
|
57150
|
-
let
|
|
57716
|
+
let nd;
|
|
57717
|
+
try {
|
|
57718
|
+
nd = graph.getNodeData(id);
|
|
57719
|
+
} catch (e) {
|
|
57720
|
+
continue;
|
|
57721
|
+
}
|
|
57722
|
+
let html = node_innerHTML_of(nd, priv.theme, focus.has(id), selected.has(id), priv.anchor_state === "on" && id === priv.anchor_id, pills_html_of(gobj, nd));
|
|
57151
57723
|
if (html !== null) updates.push({
|
|
57152
57724
|
id,
|
|
57153
57725
|
style: { innerHTML: html }
|
|
@@ -57183,7 +57755,9 @@ function refresh_html_nodes_theme(gobj, theme) {
|
|
|
57183
57755
|
let updates = [];
|
|
57184
57756
|
for (let i = 0; i < nodes.length; i++) {
|
|
57185
57757
|
let id = nodes[i].id;
|
|
57186
|
-
let
|
|
57758
|
+
let nd = graph.getNodeData(id);
|
|
57759
|
+
let html = node_innerHTML_of(nd, theme, highlighted.has(id), selected.has(id), priv.anchor_state === "on" && id === priv.anchor_id, pills_html_of(gobj, nd));
|
|
57760
|
+
if (html === null) html = more_innerHTML_of(gobj, nd, theme);
|
|
57187
57761
|
if (html !== null) updates.push({
|
|
57188
57762
|
id,
|
|
57189
57763
|
style: { innerHTML: html }
|
|
@@ -57298,7 +57872,7 @@ function build_chip_innerHTML(color, theme, icon, label, key, highlight, selecte
|
|
|
57298
57872
|
* colour is kept (per-topic differentiation) but softened via
|
|
57299
57873
|
* color-mix instead of a harsh saturated fill. Theme-aware.
|
|
57300
57874
|
************************************************************/
|
|
57301
|
-
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight, selected, anchored) {
|
|
57875
|
+
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight, selected, anchored, pills_html) {
|
|
57302
57876
|
let title = key || label;
|
|
57303
57877
|
let dark = theme === "dark";
|
|
57304
57878
|
let surface = dark ? "#1b2230" : "#ffffff";
|
|
@@ -57332,6 +57906,12 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
57332
57906
|
margin-top: 2px; max-width: 100%;
|
|
57333
57907
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
57334
57908
|
">${(0, _yuneta_gobj_js.escapeHtml)(topic_name)}</div>`;
|
|
57909
|
+
let pills_row = "";
|
|
57910
|
+
if (pills_html) pills_row = `
|
|
57911
|
+
<div class="TREEDB_PILLS" style="
|
|
57912
|
+
display: flex; flex-wrap: nowrap; gap: 4px; justify-content: center;
|
|
57913
|
+
margin-top: 6px; max-width: 100%; overflow: hidden;
|
|
57914
|
+
">${pills_html}</div>`;
|
|
57335
57915
|
return `
|
|
57336
57916
|
<div class="TREEDB_CARD" title="${(0, _yuneta_gobj_js.escapeHtml)(title)}" style="
|
|
57337
57917
|
box-sizing: border-box;
|
|
@@ -57357,7 +57937,7 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
57357
57937
|
max-width: 100%; overflow: hidden; text-overflow: ellipsis;
|
|
57358
57938
|
display: -webkit-box; -webkit-line-clamp: 2;
|
|
57359
57939
|
-webkit-box-orient: vertical; word-break: break-word;
|
|
57360
|
-
">${(0, _yuneta_gobj_js.escapeHtml)(label)}</div>${sub_html}
|
|
57940
|
+
">${(0, _yuneta_gobj_js.escapeHtml)(label)}</div>${sub_html}${pills_row}
|
|
57361
57941
|
</div>
|
|
57362
57942
|
`;
|
|
57363
57943
|
}
|
|
@@ -57390,7 +57970,7 @@ function execute_delete_node(gobj, nodeData) {
|
|
|
57390
57970
|
function select_all_nodes(gobj) {
|
|
57391
57971
|
let graph = gobj.priv.graph;
|
|
57392
57972
|
if (!graph) return;
|
|
57393
|
-
set_selection(gobj, ((graph.getData() || {}).nodes || []).map((nd) => nd.id));
|
|
57973
|
+
set_selection(gobj, ((graph.getData() || {}).nodes || []).filter((nd) => nd.data && nd.data.desc).map((nd) => nd.id));
|
|
57394
57974
|
}
|
|
57395
57975
|
/************************************************************
|
|
57396
57976
|
* The nodes currently selected, as their node data.
|
|
@@ -57654,7 +58234,7 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope) {
|
|
|
57654
58234
|
};
|
|
57655
58235
|
if (nd.data.desc.node_treedb_type === "hierarchical") {
|
|
57656
58236
|
let record = nd.data.record || {};
|
|
57657
|
-
updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, false, record.id);
|
|
58237
|
+
updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nd));
|
|
57658
58238
|
}
|
|
57659
58239
|
updates.push({
|
|
57660
58240
|
id: nodes[i].id,
|
|
@@ -57730,7 +58310,7 @@ function apply_edge_properties(gobj, edge_id, lineWidth, stroke, scope) {
|
|
|
57730
58310
|
function update_edge_geometry(gobj, edge_id) {
|
|
57731
58311
|
let priv = gobj.priv;
|
|
57732
58312
|
let edgeData = priv.graph.getEdgeData(edge_id);
|
|
57733
|
-
if (!edgeData || !edgeData.data) return;
|
|
58313
|
+
if (!edgeData || !edgeData.data || !edgeData.data.parent_topic) return;
|
|
57734
58314
|
let style = edgeData.style || {};
|
|
57735
58315
|
let lineWidth = style.lineWidth;
|
|
57736
58316
|
let stroke = style.stroke;
|
|
@@ -57871,7 +58451,7 @@ function copy_size_to_nodes(gobj, same_topic_only) {
|
|
|
57871
58451
|
const nodes = graph.getData().nodes;
|
|
57872
58452
|
for (let i = 0; i < nodes.length; i++) {
|
|
57873
58453
|
let nd = graph.getNodeData(nodes[i].id);
|
|
57874
|
-
if (!nd || !nd.data) continue;
|
|
58454
|
+
if (!nd || !nd.data || !nd.data.desc) continue;
|
|
57875
58455
|
if (same_topic_only && nd.data.topic_name !== source_topic) continue;
|
|
57876
58456
|
if (nodes[i].id === node_id) continue;
|
|
57877
58457
|
let updateStyle = { size: [...source_size] };
|
|
@@ -57959,6 +58539,415 @@ function copy_size_to_ports(gobj, same_topic_only) {
|
|
|
57959
58539
|
}
|
|
57960
58540
|
}
|
|
57961
58541
|
/***************************
|
|
58542
|
+
* Folding
|
|
58543
|
+
***************************/
|
|
58544
|
+
var PILL_ROW_HEIGHT = 24;
|
|
58545
|
+
var MORE_CHIP_SIZE = [76, 26];
|
|
58546
|
+
/************************************************************
|
|
58547
|
+
* The three card sizes, with room for the pill row when there
|
|
58548
|
+
* is one. A chip (pure child) never has pills: it has no hooks.
|
|
58549
|
+
************************************************************/
|
|
58550
|
+
function card_size_for(node_treedb_type, has_pills) {
|
|
58551
|
+
let extra = has_pills ? PILL_ROW_HEIGHT : 0;
|
|
58552
|
+
switch (node_treedb_type) {
|
|
58553
|
+
case "child": return [116, 40];
|
|
58554
|
+
case "extended": return [144, 66 + extra];
|
|
58555
|
+
default: return [172, 96 + extra];
|
|
58556
|
+
}
|
|
58557
|
+
}
|
|
58558
|
+
/************************************************************
|
|
58559
|
+
* The model's key of a G6 record node, or "" for anything else.
|
|
58560
|
+
************************************************************/
|
|
58561
|
+
function node_key_of(nd) {
|
|
58562
|
+
if (!nd || !nd.data || !nd.data.desc || !nd.data.record) return "";
|
|
58563
|
+
return fold_node_key(nd.data.desc.topic_name, String(nd.data.record.id));
|
|
58564
|
+
}
|
|
58565
|
+
function is_more_node(nd) {
|
|
58566
|
+
return !!(nd && nd.data && nd.data.more);
|
|
58567
|
+
}
|
|
58568
|
+
function more_node_id(gobj, group_key) {
|
|
58569
|
+
return (0, _yuneta_gobj_js.sprintf)("more-%s-%s", gobj.priv.treedb_name, group_key);
|
|
58570
|
+
}
|
|
58571
|
+
function more_edge_id(gobj, group_key) {
|
|
58572
|
+
return (0, _yuneta_gobj_js.sprintf)("more-edge-%s-%s", gobj.priv.treedb_name, group_key);
|
|
58573
|
+
}
|
|
58574
|
+
/************************************************************
|
|
58575
|
+
* The colours of a pill or a chip, from the topic colour it
|
|
58576
|
+
* stands for -- the CHILD topic, the same colour its hook port
|
|
58577
|
+
* wears, so the pill and the port say the same thing.
|
|
58578
|
+
************************************************************/
|
|
58579
|
+
function pill_colors(color, theme) {
|
|
58580
|
+
let dark = theme === "dark";
|
|
58581
|
+
return {
|
|
58582
|
+
bg: dark ? `color-mix(in srgb, ${color} 45%, #1b2230)` : `color-mix(in srgb, ${color} 22%, #ffffff)`,
|
|
58583
|
+
fg: dark ? `color-mix(in srgb, ${color} 35%, #ffffff)` : `color-mix(in srgb, ${color} 55%, #0f172a)`,
|
|
58584
|
+
border: dark ? `color-mix(in srgb, ${color} 80%, #ffffff)` : color
|
|
58585
|
+
};
|
|
58586
|
+
}
|
|
58587
|
+
/************************************************************
|
|
58588
|
+
* One pill: `▸ devices 142` folded, `▾ devices 24/142` open on a
|
|
58589
|
+
* page, `▾ devices 142` open whole. A glyph and numbers on
|
|
58590
|
+
* purpose: the card is an innerHTML string where a WORD could
|
|
58591
|
+
* carry no i18n key, and the hook name is a schema identifier,
|
|
58592
|
+
* like the topic subtitle above it.
|
|
58593
|
+
************************************************************/
|
|
58594
|
+
function build_pill_html(pill, color, theme) {
|
|
58595
|
+
let c = pill_colors(color, theme);
|
|
58596
|
+
let glyph = pill.open ? "▾" : "▸";
|
|
58597
|
+
let count = pill.open && pill.shown < pill.total ? `${pill.shown}/${pill.total}` : `${pill.total}`;
|
|
58598
|
+
return `<span class="TREEDB_PILL" data-fold-group="${(0, _yuneta_gobj_js.escapeHtml)(pill.group_key)}"
|
|
58599
|
+
title="${(0, _yuneta_gobj_js.escapeHtml)(pill.hook)}" style="
|
|
58600
|
+
display: inline-flex; align-items: center; gap: 3px; flex: 0 1 auto;
|
|
58601
|
+
height: 16px; padding: 0 6px; border-radius: 8px;
|
|
58602
|
+
background: ${c.bg}; color: ${c.fg}; border: 1px solid ${c.border};
|
|
58603
|
+
font-size: 10px; font-weight: 700; line-height: 1; white-space: nowrap;
|
|
58604
|
+
overflow: hidden; text-overflow: ellipsis;
|
|
58605
|
+
cursor: pointer; user-select: none;
|
|
58606
|
+
"><span style="font-size: 9px;">${glyph}</span>${(0, _yuneta_gobj_js.escapeHtml)(pill.hook)}<span style="opacity: .75; font-weight: 600;">${count}</span></span>`;
|
|
58607
|
+
}
|
|
58608
|
+
/************************************************************
|
|
58609
|
+
* The pill row of one node, as html; "" when it has nothing to
|
|
58610
|
+
* fold or the model is not built yet.
|
|
58611
|
+
************************************************************/
|
|
58612
|
+
function pills_html_of_key(gobj, node_key) {
|
|
58613
|
+
let priv = gobj.priv;
|
|
58614
|
+
if (!priv._fold_model || !priv._fold_state || !node_key) return "";
|
|
58615
|
+
let pills = fold_pills_of(priv._fold_model, priv._fold_state, node_key);
|
|
58616
|
+
if (!pills.length) return "";
|
|
58617
|
+
let out = [];
|
|
58618
|
+
for (let pill of pills) {
|
|
58619
|
+
let child_desc = priv.descs ? priv.descs[pill.child_topic] : null;
|
|
58620
|
+
let color = child_desc && child_desc.color || "#94a3b8";
|
|
58621
|
+
out.push(build_pill_html(pill, color, priv.theme));
|
|
58622
|
+
}
|
|
58623
|
+
return out.join("");
|
|
58624
|
+
}
|
|
58625
|
+
function pills_html_of(gobj, nd) {
|
|
58626
|
+
return pills_html_of_key(gobj, node_key_of(nd));
|
|
58627
|
+
}
|
|
58628
|
+
function pills_signature(gobj, node_key) {
|
|
58629
|
+
let priv = gobj.priv;
|
|
58630
|
+
if (!priv._fold_model || !priv._fold_state) return "";
|
|
58631
|
+
return fold_pills_of(priv._fold_model, priv._fold_state, node_key).map((p) => `${p.hook}:${p.open ? p.shown : "-"}/${p.total}`).join(",");
|
|
58632
|
+
}
|
|
58633
|
+
/************************************************************
|
|
58634
|
+
* The `+N` chip at the end of a page: the rest of the group,
|
|
58635
|
+
* in the child topic's colour, dashed like a cut. Its title is
|
|
58636
|
+
* the one WORD of the folding, and it is translated at build
|
|
58637
|
+
* time: the chips are rebuilt on a language change.
|
|
58638
|
+
************************************************************/
|
|
58639
|
+
function build_more_innerHTML(color, theme, rest) {
|
|
58640
|
+
let c = pill_colors(color, theme);
|
|
58641
|
+
return `
|
|
58642
|
+
<div class="TREEDB_MORE" title="${(0, _yuneta_gobj_js.escapeHtml)((0, i18next.t)("show more"))}" style="
|
|
58643
|
+
box-sizing: border-box; width: 100%; height: 100%;
|
|
58644
|
+
display: flex; align-items: center; justify-content: center; gap: 4px;
|
|
58645
|
+
background: ${c.bg}; color: ${c.fg}; border: 1px dashed ${c.border};
|
|
58646
|
+
border-radius: 13px;
|
|
58647
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
58648
|
+
font-size: 12px; font-weight: 700; line-height: 1;
|
|
58649
|
+
cursor: pointer; user-select: none;
|
|
58650
|
+
">+${rest}<span style="font-size: 10px; opacity: .8;">…</span></div>
|
|
58651
|
+
`;
|
|
58652
|
+
}
|
|
58653
|
+
function more_innerHTML_of(gobj, nd, theme) {
|
|
58654
|
+
if (!is_more_node(nd)) return null;
|
|
58655
|
+
let priv = gobj.priv;
|
|
58656
|
+
let child_desc = priv.descs ? priv.descs[nd.data.child_topic] : null;
|
|
58657
|
+
return build_more_innerHTML(child_desc && child_desc.color || "#94a3b8", theme, nd.data.rest);
|
|
58658
|
+
}
|
|
58659
|
+
/************************************************************
|
|
58660
|
+
* The pills live inside an `innerHTML` string, so no handler can
|
|
58661
|
+
* be attached to them: the click is delegated from the container
|
|
58662
|
+
* in the CAPTURE phase over four event types -- the same door the
|
|
58663
|
+
* JSON graph opens for its fold handles, for the same reasons: G6
|
|
58664
|
+
* binds on the html node element, a descendant, so only capture
|
|
58665
|
+
* runs first; and G6 never reads the DOM `click`, it builds its
|
|
58666
|
+
* own from the pointer pair, so `pointerdown`/`pointerup` are the
|
|
58667
|
+
* ones that have to be cut or the card is ALSO clicked.
|
|
58668
|
+
************************************************************/
|
|
58669
|
+
var FOLD_SWALLOWED_EVENTS = [
|
|
58670
|
+
"pointerdown",
|
|
58671
|
+
"pointerup",
|
|
58672
|
+
"mousedown",
|
|
58673
|
+
"click"
|
|
58674
|
+
];
|
|
58675
|
+
function install_fold_listener(gobj) {
|
|
58676
|
+
let priv = gobj.priv;
|
|
58677
|
+
if (!priv.$container) {
|
|
58678
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no container, the fold pills are dead`);
|
|
58679
|
+
return;
|
|
58680
|
+
}
|
|
58681
|
+
priv._fold_listener = function(evt) {
|
|
58682
|
+
let $pill = evt.target && evt.target.closest ? evt.target.closest("[data-fold-group]") : null;
|
|
58683
|
+
if (!$pill) return;
|
|
58684
|
+
evt.stopPropagation();
|
|
58685
|
+
evt.preventDefault();
|
|
58686
|
+
if (evt.type !== "click") return;
|
|
58687
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_FOLD", { group: $pill.getAttribute("data-fold-group") }, gobj);
|
|
58688
|
+
};
|
|
58689
|
+
for (let type of FOLD_SWALLOWED_EVENTS) priv.$container.addEventListener(type, priv._fold_listener, true);
|
|
58690
|
+
}
|
|
58691
|
+
function uninstall_fold_listener(gobj) {
|
|
58692
|
+
let priv = gobj.priv;
|
|
58693
|
+
if (priv._fold_listener && priv.$container) for (let type of FOLD_SWALLOWED_EVENTS) priv.$container.removeEventListener(type, priv._fold_listener, true);
|
|
58694
|
+
priv._fold_listener = null;
|
|
58695
|
+
}
|
|
58696
|
+
/************************************************************
|
|
58697
|
+
* (Re)build the tree of the records. Cheap -- one pass over the
|
|
58698
|
+
* records -- so it runs again on every create/update/delete
|
|
58699
|
+
* rather than being patched. The fold state survives: it is
|
|
58700
|
+
* keyed by group, and a group that is gone is simply never read.
|
|
58701
|
+
************************************************************/
|
|
58702
|
+
function rebuild_fold_model(gobj) {
|
|
58703
|
+
let priv = gobj.priv;
|
|
58704
|
+
priv._fold_model = fold_build_model(priv.descs || {}, priv.records || {});
|
|
58705
|
+
if (!priv._fold_state) priv._fold_state = fold_new_state((0, _yuneta_gobj_js.gobj_read_integer_attr)(gobj, "fold_page_size"));
|
|
58706
|
+
if (!priv._pill_sig) priv._pill_sig = /* @__PURE__ */ new Map();
|
|
58707
|
+
}
|
|
58708
|
+
/************************************************************
|
|
58709
|
+
* How many records there are, and how many carry a saved
|
|
58710
|
+
* position -- what auto_layout decides on. Counted over the
|
|
58711
|
+
* RECORDS, because the nodes on screen are a fraction of them.
|
|
58712
|
+
************************************************************/
|
|
58713
|
+
function count_placed_records(gobj) {
|
|
58714
|
+
let priv = gobj.priv;
|
|
58715
|
+
priv._nodes_total = 0;
|
|
58716
|
+
priv._nodes_placed = 0;
|
|
58717
|
+
for (const [topic_name, records] of Object.entries(priv.records || {})) {
|
|
58718
|
+
if (topic_name.substring(0, 2) === "__" || !(0, _yuneta_gobj_js.is_array)(records)) continue;
|
|
58719
|
+
for (let record of records) {
|
|
58720
|
+
priv._nodes_total++;
|
|
58721
|
+
if (geometry_has_position(get_node_graph_props(gobj, topic_name, record.id, record))) priv._nodes_placed++;
|
|
58722
|
+
}
|
|
58723
|
+
}
|
|
58724
|
+
}
|
|
58725
|
+
/************************************************************
|
|
58726
|
+
* Make the G6 data say what the fold model says is visible.
|
|
58727
|
+
*
|
|
58728
|
+
* Record nodes not visible any more are removed (their edges go
|
|
58729
|
+
* with them), the visible ones missing are created, the links
|
|
58730
|
+
* between visible nodes are drawn, the `+N` chips are placed or
|
|
58731
|
+
* taken away, and every card whose pills changed is repainted.
|
|
58732
|
+
* Then a draw, a layout if the set of nodes changed, and the
|
|
58733
|
+
* camera: fit the whole thing on the first load, or put `keep`
|
|
58734
|
+
* back where it was on screen before the change.
|
|
58735
|
+
*
|
|
58736
|
+
* Serialised: one reconcile at a time, in order. Two pills tapped
|
|
58737
|
+
* quickly would otherwise interleave their draws.
|
|
58738
|
+
*
|
|
58739
|
+
* opts.relayout run the layout even if no node came or went
|
|
58740
|
+
* opts.fit fit the viewport afterwards
|
|
58741
|
+
* opts.keep node id to hold still on screen
|
|
58742
|
+
* opts.keep_vp where it was ([x, y] viewport px)
|
|
58743
|
+
************************************************************/
|
|
58744
|
+
function reconcile_fold(gobj, opts) {
|
|
58745
|
+
let priv = gobj.priv;
|
|
58746
|
+
let run = () => reconcile_fold_now(gobj, opts || {}).catch((e) => {
|
|
58747
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: reconcile failed: ${e}`);
|
|
58748
|
+
});
|
|
58749
|
+
priv._fold_chain = (priv._fold_chain || Promise.resolve()).then(run, run);
|
|
58750
|
+
return priv._fold_chain;
|
|
58751
|
+
}
|
|
58752
|
+
async function reconcile_fold_now(gobj, opts) {
|
|
58753
|
+
let priv = gobj.priv;
|
|
58754
|
+
let graph = priv.graph;
|
|
58755
|
+
let model = priv._fold_model;
|
|
58756
|
+
let state = priv._fold_state;
|
|
58757
|
+
if (!graph || !model || !state || (0, _yuneta_gobj_js.gobj_is_destroying)(gobj)) return;
|
|
58758
|
+
let visible = fold_visible_set(model, state);
|
|
58759
|
+
let changed = false;
|
|
58760
|
+
history_pause(gobj);
|
|
58761
|
+
try {
|
|
58762
|
+
changed = await reconcile_fold_apply(gobj, opts, visible);
|
|
58763
|
+
} finally {
|
|
58764
|
+
history_resume(gobj);
|
|
58765
|
+
}
|
|
58766
|
+
return changed;
|
|
58767
|
+
}
|
|
58768
|
+
async function reconcile_fold_apply(gobj, opts, visible) {
|
|
58769
|
+
let priv = gobj.priv;
|
|
58770
|
+
let graph = priv.graph;
|
|
58771
|
+
let model = priv._fold_model;
|
|
58772
|
+
let state = priv._fold_state;
|
|
58773
|
+
let changed = false;
|
|
58774
|
+
let present = /* @__PURE__ */ new Map();
|
|
58775
|
+
let more_present = /* @__PURE__ */ new Map();
|
|
58776
|
+
for (let nd of graph.getNodeData() || []) {
|
|
58777
|
+
if (is_more_node(nd)) {
|
|
58778
|
+
more_present.set(nd.data.more, nd.id);
|
|
58779
|
+
continue;
|
|
58780
|
+
}
|
|
58781
|
+
let key = node_key_of(nd);
|
|
58782
|
+
if (key) present.set(key, nd.id);
|
|
58783
|
+
}
|
|
58784
|
+
let to_remove = [];
|
|
58785
|
+
for (let [key, id] of present) if (!visible.has(key)) to_remove.push(id);
|
|
58786
|
+
if (to_remove.length) {
|
|
58787
|
+
let gone = new Set(to_remove);
|
|
58788
|
+
if (priv._selected_node_id && gone.has(priv._selected_node_id)) deselect_node(gobj);
|
|
58789
|
+
if (priv._detail_node_id && gone.has(priv._detail_node_id)) hide_node_detail(gobj);
|
|
58790
|
+
priv._focus_ids = (priv._focus_ids || []).filter((id) => !gone.has(id));
|
|
58791
|
+
priv._selected_paint_ids = (priv._selected_paint_ids || []).filter((id) => !gone.has(id));
|
|
58792
|
+
if (priv.anchor_state === "on" && gone.has(priv.anchor_id)) {
|
|
58793
|
+
priv.anchor_id = "";
|
|
58794
|
+
priv.anchor_state = "off";
|
|
58795
|
+
update_toolbar(gobj);
|
|
58796
|
+
}
|
|
58797
|
+
for (let id of to_remove) priv._pill_sig.delete(id);
|
|
58798
|
+
graph.removeNodeData(to_remove);
|
|
58799
|
+
changed = true;
|
|
58800
|
+
}
|
|
58801
|
+
for (let key of visible) {
|
|
58802
|
+
if (present.has(key)) continue;
|
|
58803
|
+
let node = model.nodes.get(key);
|
|
58804
|
+
let desc = priv.descs[node.topic_name];
|
|
58805
|
+
if (!desc) {
|
|
58806
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no desc for ${key}`);
|
|
58807
|
+
continue;
|
|
58808
|
+
}
|
|
58809
|
+
create_topic_node(gobj, desc, node.record);
|
|
58810
|
+
priv._pill_sig.set(build_node_name(gobj, node.topic_name, node.id), pills_signature(gobj, key));
|
|
58811
|
+
changed = true;
|
|
58812
|
+
}
|
|
58813
|
+
for (let key of visible) {
|
|
58814
|
+
let node = model.nodes.get(key);
|
|
58815
|
+
let desc = priv.descs[node.topic_name];
|
|
58816
|
+
if (desc) draw_links(gobj, desc, node.record, false);
|
|
58817
|
+
}
|
|
58818
|
+
let pending = fold_pending_groups(model, state, visible);
|
|
58819
|
+
let wanted = /* @__PURE__ */ new Map();
|
|
58820
|
+
for (let p of pending) wanted.set(p.group_key, p);
|
|
58821
|
+
let more_gone = [];
|
|
58822
|
+
for (let [group_key, id] of more_present) if (!wanted.has(group_key)) more_gone.push(id);
|
|
58823
|
+
if (more_gone.length) {
|
|
58824
|
+
graph.removeNodeData(more_gone);
|
|
58825
|
+
changed = true;
|
|
58826
|
+
}
|
|
58827
|
+
for (let p of pending) {
|
|
58828
|
+
let first = model.nodes.get((model.groups.get(p.group_key) || [])[0]);
|
|
58829
|
+
let child_topic = first ? first.topic_name : "";
|
|
58830
|
+
let child_desc = priv.descs[child_topic];
|
|
58831
|
+
let color = child_desc && child_desc.color || "#94a3b8";
|
|
58832
|
+
let id = more_node_id(gobj, p.group_key);
|
|
58833
|
+
if (more_present.has(p.group_key)) {
|
|
58834
|
+
let nd = graph.getNodeData(id);
|
|
58835
|
+
if (nd && nd.data.rest !== p.rest) {
|
|
58836
|
+
nd.data.rest = p.rest;
|
|
58837
|
+
graph.updateNodeData([{
|
|
58838
|
+
id,
|
|
58839
|
+
style: { innerHTML: build_more_innerHTML(color, priv.theme, p.rest) }
|
|
58840
|
+
}]);
|
|
58841
|
+
}
|
|
58842
|
+
continue;
|
|
58843
|
+
}
|
|
58844
|
+
let xy = get_default_ne_xy(gobj);
|
|
58845
|
+
graph.addNodeData([{
|
|
58846
|
+
id,
|
|
58847
|
+
type: "html",
|
|
58848
|
+
style: {
|
|
58849
|
+
x: xy,
|
|
58850
|
+
y: xy,
|
|
58851
|
+
size: [...MORE_CHIP_SIZE],
|
|
58852
|
+
dx: -MORE_CHIP_SIZE[0] / 2,
|
|
58853
|
+
dy: -MORE_CHIP_SIZE[1] / 2,
|
|
58854
|
+
innerHTML: build_more_innerHTML(color, priv.theme, p.rest)
|
|
58855
|
+
},
|
|
58856
|
+
data: {
|
|
58857
|
+
more: p.group_key,
|
|
58858
|
+
child_topic,
|
|
58859
|
+
rest: p.rest
|
|
58860
|
+
}
|
|
58861
|
+
}]);
|
|
58862
|
+
if (p.node_key) {
|
|
58863
|
+
let parent = model.nodes.get(p.node_key);
|
|
58864
|
+
let dark = priv.theme === "dark";
|
|
58865
|
+
graph.addEdgeData([{
|
|
58866
|
+
id: more_edge_id(gobj, p.group_key),
|
|
58867
|
+
type: edge_type_for(gobj),
|
|
58868
|
+
source: build_node_name(gobj, parent.topic_name, parent.id),
|
|
58869
|
+
target: id,
|
|
58870
|
+
style: {
|
|
58871
|
+
sourcePort: p.hook,
|
|
58872
|
+
lineWidth: 1,
|
|
58873
|
+
lineDash: [4, 3],
|
|
58874
|
+
stroke: dark ? "#8b94a3" : "#94a3b8",
|
|
58875
|
+
startArrow: false,
|
|
58876
|
+
endArrow: false
|
|
58877
|
+
},
|
|
58878
|
+
data: { more: p.group_key }
|
|
58879
|
+
}]);
|
|
58880
|
+
}
|
|
58881
|
+
changed = true;
|
|
58882
|
+
}
|
|
58883
|
+
let repaint = /* @__PURE__ */ new Set();
|
|
58884
|
+
let resize = [];
|
|
58885
|
+
for (let key of visible) {
|
|
58886
|
+
let node = model.nodes.get(key);
|
|
58887
|
+
let id = build_node_name(gobj, node.topic_name, node.id);
|
|
58888
|
+
let sig = pills_signature(gobj, key);
|
|
58889
|
+
if (priv._pill_sig.get(id) === sig) continue;
|
|
58890
|
+
let had = !!priv._pill_sig.get(id);
|
|
58891
|
+
priv._pill_sig.set(id, sig);
|
|
58892
|
+
repaint.add(id);
|
|
58893
|
+
if (had !== !!sig) {
|
|
58894
|
+
let nd = graph.getNodeData(id);
|
|
58895
|
+
let desc = nd && nd.data && nd.data.desc;
|
|
58896
|
+
let geometry = nd && nd.data && nd.data.graph_props || {};
|
|
58897
|
+
if (desc && !(0, _yuneta_gobj_js.is_array)(geometry.size)) {
|
|
58898
|
+
let size = card_size_for(desc.node_treedb_type, !!sig);
|
|
58899
|
+
resize.push({
|
|
58900
|
+
id,
|
|
58901
|
+
style: {
|
|
58902
|
+
size,
|
|
58903
|
+
dx: -size[0] / 2,
|
|
58904
|
+
dy: -size[1] / 2
|
|
58905
|
+
}
|
|
58906
|
+
});
|
|
58907
|
+
}
|
|
58908
|
+
}
|
|
58909
|
+
}
|
|
58910
|
+
if (resize.length) graph.updateNodeData(resize);
|
|
58911
|
+
if (repaint.size) repaint_cards(gobj, repaint);
|
|
58912
|
+
try {
|
|
58913
|
+
refresh_minimap(gobj);
|
|
58914
|
+
} catch (e) {
|
|
58915
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: refresh_minimap failed: ${e}`);
|
|
58916
|
+
}
|
|
58917
|
+
await graph_draw(gobj);
|
|
58918
|
+
if (changed || opts.relayout) await graph_layout(gobj);
|
|
58919
|
+
if (opts.fit) await graph_fit_readable(gobj);
|
|
58920
|
+
else if (opts.keep && opts.keep_vp) await yui_graph_place_at(graph, opts.keep, opts.keep_vp);
|
|
58921
|
+
update_resize_handles_position(gobj);
|
|
58922
|
+
update_port_resize_handles_position(gobj);
|
|
58923
|
+
update_edge_icon_position(gobj);
|
|
58924
|
+
update_node_icon_position(gobj);
|
|
58925
|
+
update_link_icon_position(gobj);
|
|
58926
|
+
return changed;
|
|
58927
|
+
}
|
|
58928
|
+
/************************************************************
|
|
58929
|
+
* Repaint the `+N` chips (theme or language changed).
|
|
58930
|
+
************************************************************/
|
|
58931
|
+
function repaint_more_chips(gobj) {
|
|
58932
|
+
let priv = gobj.priv;
|
|
58933
|
+
let graph = priv.graph;
|
|
58934
|
+
if (!graph) return;
|
|
58935
|
+
let updates = [];
|
|
58936
|
+
for (let nd of graph.getNodeData() || []) {
|
|
58937
|
+
let html = more_innerHTML_of(gobj, nd, priv.theme);
|
|
58938
|
+
if (html !== null) updates.push({
|
|
58939
|
+
id: nd.id,
|
|
58940
|
+
style: { innerHTML: html }
|
|
58941
|
+
});
|
|
58942
|
+
}
|
|
58943
|
+
if (updates.length) try {
|
|
58944
|
+
graph.updateNodeData(updates);
|
|
58945
|
+
graph.draw();
|
|
58946
|
+
} catch (e) {
|
|
58947
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot repaint the chips: ${e}`);
|
|
58948
|
+
}
|
|
58949
|
+
}
|
|
58950
|
+
/***************************
|
|
57962
58951
|
* Actions
|
|
57963
58952
|
***************************/
|
|
57964
58953
|
/************************************************************
|
|
@@ -57987,6 +58976,9 @@ function ac_clear_data(gobj, event, kw, src) {
|
|
|
57987
58976
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "records", {});
|
|
57988
58977
|
priv._nodes_total = 0;
|
|
57989
58978
|
priv._nodes_placed = 0;
|
|
58979
|
+
priv._fold_model = null;
|
|
58980
|
+
priv._fold_state = null;
|
|
58981
|
+
priv._pill_sig = null;
|
|
57990
58982
|
graph_remove_plugin(gobj, "history");
|
|
57991
58983
|
update_history_buttons(gobj);
|
|
57992
58984
|
graph_clear(gobj);
|
|
@@ -58017,53 +59009,45 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
58017
59009
|
}
|
|
58018
59010
|
return 0;
|
|
58019
59011
|
}
|
|
58020
|
-
|
|
59012
|
+
priv.descs[topic_name];
|
|
58021
59013
|
priv.records[topic_name] = data;
|
|
58022
59014
|
priv.descs[topic_name].loaded = true;
|
|
58023
|
-
|
|
58024
|
-
let record = data[i];
|
|
58025
|
-
create_topic_node(gobj, desc, record);
|
|
58026
|
-
}
|
|
58027
|
-
let do_links = true;
|
|
59015
|
+
let all_loaded = true;
|
|
58028
59016
|
for (const [topic_name, desc] of Object.entries(priv.descs)) {
|
|
58029
59017
|
if (topic_name.substring(0, 2) === "__") continue;
|
|
58030
59018
|
if (!desc.loaded) {
|
|
58031
|
-
|
|
59019
|
+
all_loaded = false;
|
|
58032
59020
|
break;
|
|
58033
59021
|
}
|
|
58034
59022
|
}
|
|
58035
|
-
if (
|
|
59023
|
+
if (all_loaded && priv.graph) {
|
|
59024
|
+
rebuild_fold_model(gobj);
|
|
59025
|
+
fold_expand_to_depth(priv._fold_model, priv._fold_state, (0, _yuneta_gobj_js.gobj_read_integer_attr)(gobj, "expand_depth"));
|
|
59026
|
+
count_placed_records(gobj);
|
|
59027
|
+
let auto_laid = false;
|
|
58036
59028
|
try {
|
|
58037
|
-
|
|
59029
|
+
auto_laid = auto_layout(gobj);
|
|
58038
59030
|
} catch (e) {
|
|
58039
|
-
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}:
|
|
58040
|
-
}
|
|
58041
|
-
|
|
58042
|
-
|
|
58043
|
-
|
|
58044
|
-
|
|
58045
|
-
|
|
58046
|
-
|
|
58047
|
-
|
|
58048
|
-
|
|
58049
|
-
|
|
58050
|
-
|
|
58051
|
-
|
|
58052
|
-
|
|
58053
|
-
|
|
58054
|
-
|
|
58055
|
-
|
|
58056
|
-
|
|
58057
|
-
|
|
58058
|
-
|
|
58059
|
-
}
|
|
58060
|
-
if (priv._pending_find !== null) {
|
|
58061
|
-
let term = priv._pending_find;
|
|
58062
|
-
priv._pending_find = null;
|
|
58063
|
-
publish_find_result(gobj, term, graph_find_nodes(gobj, term));
|
|
58064
|
-
}
|
|
58065
|
-
});
|
|
58066
|
-
});
|
|
59031
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: auto_layout failed: ${e}`);
|
|
59032
|
+
}
|
|
59033
|
+
apply_layout_direction(gobj);
|
|
59034
|
+
reconcile_fold(gobj, {
|
|
59035
|
+
relayout: true,
|
|
59036
|
+
fit: auto_laid
|
|
59037
|
+
}).then(() => {
|
|
59038
|
+
sync_history_plugin(gobj);
|
|
59039
|
+
if (priv._pending_focus_topic !== null) {
|
|
59040
|
+
let ft = priv._pending_focus_topic;
|
|
59041
|
+
let all = priv._pending_focus_all;
|
|
59042
|
+
priv._pending_focus_topic = null;
|
|
59043
|
+
priv._pending_focus_all = false;
|
|
59044
|
+
graph_focus_topic(gobj, ft, all);
|
|
59045
|
+
}
|
|
59046
|
+
if (priv._pending_find !== null) {
|
|
59047
|
+
let term = priv._pending_find;
|
|
59048
|
+
priv._pending_find = null;
|
|
59049
|
+
publish_find_result(gobj, term, graph_find_nodes(gobj, term));
|
|
59050
|
+
}
|
|
58067
59051
|
});
|
|
58068
59052
|
}
|
|
58069
59053
|
return 0;
|
|
@@ -58099,19 +59083,15 @@ function ac_node_created(gobj, event, kw, src) {
|
|
|
58099
59083
|
build_graph_properties(gobj);
|
|
58100
59084
|
return 0;
|
|
58101
59085
|
}
|
|
58102
|
-
|
|
58103
|
-
if (!desc) {
|
|
59086
|
+
if (!priv.descs[topic_name]) {
|
|
58104
59087
|
(0, _yuneta_gobj_js.log_error)(`ac_node_created: unknown topic: ${topic_name}`);
|
|
58105
59088
|
return 0;
|
|
58106
59089
|
}
|
|
58107
59090
|
if (!priv.records[topic_name]) priv.records[topic_name] = [];
|
|
58108
59091
|
priv.records[topic_name].push(node);
|
|
58109
|
-
|
|
58110
|
-
|
|
58111
|
-
|
|
58112
|
-
graph_draw(gobj).then(() => {
|
|
58113
|
-
history_resume(gobj);
|
|
58114
|
-
});
|
|
59092
|
+
rebuild_fold_model(gobj);
|
|
59093
|
+
fold_reveal(priv._fold_model, priv._fold_state, fold_node_key(topic_name, String(node.id)));
|
|
59094
|
+
reconcile_fold(gobj, {});
|
|
58115
59095
|
return 0;
|
|
58116
59096
|
}
|
|
58117
59097
|
/************************************************************
|
|
@@ -58160,8 +59140,14 @@ function ac_node_updated(gobj, event, kw, src) {
|
|
|
58160
59140
|
let [col_idx, fkey_value] = ref.split(" ");
|
|
58161
59141
|
clear_link(gobj, topic_name, node.id, cols[parseInt(col_idx)], fkey_value, false);
|
|
58162
59142
|
}
|
|
58163
|
-
update_topic_node(gobj, desc, node_name, node);
|
|
58164
59143
|
update_local_node(gobj, topic_name, node);
|
|
59144
|
+
let on_screen = false;
|
|
59145
|
+
try {
|
|
59146
|
+
on_screen = !!graph.getNodeData(node_name);
|
|
59147
|
+
} catch (e) {
|
|
59148
|
+
on_screen = false;
|
|
59149
|
+
}
|
|
59150
|
+
if (on_screen) update_topic_node(gobj, desc, node_name, node);
|
|
58165
59151
|
for (let ref of new_refs) if (!old_refs.has(ref)) {
|
|
58166
59152
|
let [col_idx, fkey_value] = ref.split(" ");
|
|
58167
59153
|
draw_link(gobj, topic_name, node.id, cols[parseInt(col_idx)], fkey_value, false);
|
|
@@ -58169,6 +59155,8 @@ function ac_node_updated(gobj, event, kw, src) {
|
|
|
58169
59155
|
graph_draw(gobj).then(() => {
|
|
58170
59156
|
history_resume(gobj);
|
|
58171
59157
|
});
|
|
59158
|
+
rebuild_fold_model(gobj);
|
|
59159
|
+
reconcile_fold(gobj, {});
|
|
58172
59160
|
return 0;
|
|
58173
59161
|
}
|
|
58174
59162
|
/************************************************************
|
|
@@ -58194,9 +59182,12 @@ function ac_node_deleted(gobj, event, kw, src) {
|
|
|
58194
59182
|
clear_links(gobj, desc, node, false);
|
|
58195
59183
|
remove_topic_node(gobj, node_name);
|
|
58196
59184
|
remove_local_node(gobj, topic_name, node);
|
|
59185
|
+
if (priv._pill_sig) priv._pill_sig.delete(node_name);
|
|
58197
59186
|
graph_draw(gobj).then(() => {
|
|
58198
59187
|
history_resume(gobj);
|
|
58199
59188
|
});
|
|
59189
|
+
rebuild_fold_model(gobj);
|
|
59190
|
+
reconcile_fold(gobj, {});
|
|
58200
59191
|
return 0;
|
|
58201
59192
|
}
|
|
58202
59193
|
/************************************************************
|
|
@@ -58255,6 +59246,7 @@ function ac_theme$1(gobj, event, kw, src) {
|
|
|
58255
59246
|
});
|
|
58256
59247
|
refresh_html_nodes_theme(gobj, theme);
|
|
58257
59248
|
refresh_default_edges_theme(gobj, theme);
|
|
59249
|
+
repaint_more_chips(gobj);
|
|
58258
59250
|
graph_draw(gobj).then(() => {
|
|
58259
59251
|
update_history_buttons(gobj);
|
|
58260
59252
|
});
|
|
@@ -58365,7 +59357,86 @@ function ac_zoom_selection(gobj, event, kw, src) {
|
|
|
58365
59357
|
return 0;
|
|
58366
59358
|
}
|
|
58367
59359
|
function ac_focus_topic(gobj, event, kw, src) {
|
|
58368
|
-
graph_focus_topic(gobj, kw && kw.topic);
|
|
59360
|
+
graph_focus_topic(gobj, kw && kw.topic, !!(kw && kw.reveal === "all"));
|
|
59361
|
+
return 0;
|
|
59362
|
+
}
|
|
59363
|
+
/************************************************************
|
|
59364
|
+
* A pill was tapped: open that hook on its first page, or fold
|
|
59365
|
+
* it. The card the pill is on stays where it was on screen --
|
|
59366
|
+
* the layout moves everything else around it.
|
|
59367
|
+
************************************************************/
|
|
59368
|
+
function ac_toggle_fold(gobj, event, kw, src) {
|
|
59369
|
+
let priv = gobj.priv;
|
|
59370
|
+
let group = kw && kw.group || "";
|
|
59371
|
+
if (!priv._fold_model || !group) {
|
|
59372
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: fold of '${group}' with no tree loaded`);
|
|
59373
|
+
return -1;
|
|
59374
|
+
}
|
|
59375
|
+
let g = fold_split_group_key(group);
|
|
59376
|
+
if (!g) {
|
|
59377
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: bad fold group '${group}'`);
|
|
59378
|
+
return -1;
|
|
59379
|
+
}
|
|
59380
|
+
let node_id = g.node_key ? node_id_of_key(gobj, g.node_key) : "";
|
|
59381
|
+
let vp = node_id ? yui_graph_viewport_of(priv.graph, node_id) : null;
|
|
59382
|
+
fold_toggle(priv._fold_model, priv._fold_state, group);
|
|
59383
|
+
reconcile_fold(gobj, {
|
|
59384
|
+
keep: node_id,
|
|
59385
|
+
keep_vp: vp
|
|
59386
|
+
});
|
|
59387
|
+
return 0;
|
|
59388
|
+
}
|
|
59389
|
+
/************************************************************
|
|
59390
|
+
* A `+N` chip was tapped: the next page of its group. The
|
|
59391
|
+
* parent holds still; the chip itself moves down the column.
|
|
59392
|
+
************************************************************/
|
|
59393
|
+
function ac_show_more(gobj, event, kw, src) {
|
|
59394
|
+
let priv = gobj.priv;
|
|
59395
|
+
let group = kw && kw.group || "";
|
|
59396
|
+
if (!priv._fold_model || !group) {
|
|
59397
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: show more of '${group}' with no tree loaded`);
|
|
59398
|
+
return -1;
|
|
59399
|
+
}
|
|
59400
|
+
let g = fold_split_group_key(group);
|
|
59401
|
+
if (!g) {
|
|
59402
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: bad fold group '${group}'`);
|
|
59403
|
+
return -1;
|
|
59404
|
+
}
|
|
59405
|
+
let node_id = g.node_key ? node_id_of_key(gobj, g.node_key) : "";
|
|
59406
|
+
let vp = node_id ? yui_graph_viewport_of(priv.graph, node_id) : null;
|
|
59407
|
+
fold_show_more(priv._fold_model, priv._fold_state, group);
|
|
59408
|
+
reconcile_fold(gobj, {
|
|
59409
|
+
keep: node_id,
|
|
59410
|
+
keep_vp: vp
|
|
59411
|
+
});
|
|
59412
|
+
return 0;
|
|
59413
|
+
}
|
|
59414
|
+
/************************************************************
|
|
59415
|
+
* The whole treedb, every hook open on all its children. This
|
|
59416
|
+
* is the reader asking for the pile on purpose; the pages are
|
|
59417
|
+
* the other way in.
|
|
59418
|
+
************************************************************/
|
|
59419
|
+
function ac_expand_all$1(gobj, event, kw, src) {
|
|
59420
|
+
let priv = gobj.priv;
|
|
59421
|
+
if (!priv._fold_model) {
|
|
59422
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: expand all with no tree loaded`);
|
|
59423
|
+
return -1;
|
|
59424
|
+
}
|
|
59425
|
+
fold_expand_all(priv._fold_model, priv._fold_state);
|
|
59426
|
+
reconcile_fold(gobj, { fit: true });
|
|
59427
|
+
return 0;
|
|
59428
|
+
}
|
|
59429
|
+
/************************************************************
|
|
59430
|
+
* The roots alone.
|
|
59431
|
+
************************************************************/
|
|
59432
|
+
function ac_collapse_all$1(gobj, event, kw, src) {
|
|
59433
|
+
let priv = gobj.priv;
|
|
59434
|
+
if (!priv._fold_model) {
|
|
59435
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: collapse all with no tree loaded`);
|
|
59436
|
+
return -1;
|
|
59437
|
+
}
|
|
59438
|
+
fold_collapse_all(priv._fold_model, priv._fold_state);
|
|
59439
|
+
reconcile_fold(gobj, { fit: true });
|
|
58369
59440
|
return 0;
|
|
58370
59441
|
}
|
|
58371
59442
|
/************************************************************
|
|
@@ -58399,7 +59470,9 @@ function ac_fullscreen(gobj, event, kw, src) {
|
|
|
58399
59470
|
************************************************************/
|
|
58400
59471
|
function ac_set_layout$1(gobj, event, kw, src) {
|
|
58401
59472
|
gobj.priv;
|
|
58402
|
-
|
|
59473
|
+
let layout = select_layout(gobj, kw.layout);
|
|
59474
|
+
apply_layout_direction(gobj);
|
|
59475
|
+
graph_set_layout(gobj, layout).then(() => {
|
|
58403
59476
|
configure_behaviour(gobj);
|
|
58404
59477
|
update_toolbar(gobj);
|
|
58405
59478
|
});
|
|
@@ -58506,6 +59579,16 @@ function ac_node_click$2(gobj, event, kw, src) {
|
|
|
58506
59579
|
let priv = gobj.priv;
|
|
58507
59580
|
let graph = priv.graph;
|
|
58508
59581
|
let node_id = kw.evt.target.id;
|
|
59582
|
+
let more_nd = null;
|
|
59583
|
+
try {
|
|
59584
|
+
more_nd = graph.getNodeData(node_id);
|
|
59585
|
+
} catch (e) {
|
|
59586
|
+
more_nd = null;
|
|
59587
|
+
}
|
|
59588
|
+
if (is_more_node(more_nd)) {
|
|
59589
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SHOW_MORE", { group: more_nd.data.more }, gobj);
|
|
59590
|
+
return 0;
|
|
59591
|
+
}
|
|
58509
59592
|
if (priv.anchor_state === "arming") {
|
|
58510
59593
|
priv.anchor_id = node_id;
|
|
58511
59594
|
priv.anchor_state = "on";
|
|
@@ -58810,6 +59893,26 @@ function create_gclass$4(gclass_name) {
|
|
|
58810
59893
|
ac_find_nodes$1,
|
|
58811
59894
|
null
|
|
58812
59895
|
],
|
|
59896
|
+
[
|
|
59897
|
+
"EV_TOGGLE_FOLD",
|
|
59898
|
+
ac_toggle_fold,
|
|
59899
|
+
null
|
|
59900
|
+
],
|
|
59901
|
+
[
|
|
59902
|
+
"EV_SHOW_MORE",
|
|
59903
|
+
ac_show_more,
|
|
59904
|
+
null
|
|
59905
|
+
],
|
|
59906
|
+
[
|
|
59907
|
+
"EV_EXPAND_ALL",
|
|
59908
|
+
ac_expand_all$1,
|
|
59909
|
+
null
|
|
59910
|
+
],
|
|
59911
|
+
[
|
|
59912
|
+
"EV_COLLAPSE_ALL",
|
|
59913
|
+
ac_collapse_all$1,
|
|
59914
|
+
null
|
|
59915
|
+
],
|
|
58813
59916
|
[
|
|
58814
59917
|
"EV_CENTER",
|
|
58815
59918
|
ac_center,
|
|
@@ -58907,6 +60010,10 @@ function create_gclass$4(gclass_name) {
|
|
|
58907
60010
|
["EV_FIND_NODES", 0],
|
|
58908
60011
|
["EV_FIND_RESULT", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT],
|
|
58909
60012
|
["EV_LAYOUT_AUTOSET", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT],
|
|
60013
|
+
["EV_TOGGLE_FOLD", 0],
|
|
60014
|
+
["EV_SHOW_MORE", 0],
|
|
60015
|
+
["EV_EXPAND_ALL", 0],
|
|
60016
|
+
["EV_COLLAPSE_ALL", 0],
|
|
58910
60017
|
["EV_CENTER", 0],
|
|
58911
60018
|
["EV_FULLSCREEN", 0],
|
|
58912
60019
|
["EV_SET_LAYOUT", 0],
|
|
@@ -58964,6 +60071,8 @@ var attrs_table$3 = [
|
|
|
58964
60071
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "subscriber", 0, null, "Subscriber of output events"),
|
|
58965
60072
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_LIST, "operation_modes", 0, "[\"reading\", \"operation\", \"writing\", \"edition\"]", "Available **permission** or behaviour modes. These operation modes are required to be accomplish by the graph handler (G6 child). TODO permissions must match treedb permissions."),
|
|
58966
60073
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "with_treedb_tables", 0, false, "Include treedb tables"),
|
|
60074
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_INTEGER, "expand_depth", 0, 2, "Levels of the treedb open when it loads: 1 = the roots alone, 2 = the roots and their children. Forwarded to the G6 child"),
|
|
60075
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_INTEGER, "fold_page_size", 0, 24, "Children of one hook shown per page in the graph; a `+N` chip opens the next page. Forwarded to the G6 child"),
|
|
58967
60076
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "operation_mode", _yuneta_gobj_js.sdata_flag_t.SDF_PERSIST, "reading", "Current operation mode (internal behaviour or role). Changed by the user trough the gui."),
|
|
58968
60077
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "layout", _yuneta_gobj_js.sdata_flag_t.SDF_PERSIST, "", "Current graph layout. User preference. Changed by the user through the gui."),
|
|
58969
60078
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "gobj_remote_yuno", 0, null, "Remote Yuno to request data"),
|
|
@@ -59037,7 +60146,9 @@ function mt_create$3(gobj) {
|
|
|
59037
60146
|
layout: priv.layout,
|
|
59038
60147
|
with_treedb_tables: priv.with_treedb_tables,
|
|
59039
60148
|
hook_port_position: "bottom",
|
|
59040
|
-
fkey_port_position: "top"
|
|
60149
|
+
fkey_port_position: "top",
|
|
60150
|
+
expand_depth: (0, _yuneta_gobj_js.gobj_read_integer_attr)(gobj, "expand_depth"),
|
|
60151
|
+
fold_page_size: (0, _yuneta_gobj_js.gobj_read_integer_attr)(gobj, "fold_page_size")
|
|
59041
60152
|
}, gobj);
|
|
59042
60153
|
populate_nodes_tree_options(gobj);
|
|
59043
60154
|
if (priv.with_treedb_tables) {}
|
|
@@ -59295,6 +60406,7 @@ function make_toolbar(gobj) {
|
|
|
59295
60406
|
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_REFRESH_TREEDB", { evt }, gobj);
|
|
59296
60407
|
} }
|
|
59297
60408
|
],
|
|
60409
|
+
...yui_graph_fold_items(gobj, (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "wide")),
|
|
59298
60410
|
[
|
|
59299
60411
|
"button",
|
|
59300
60412
|
{
|
|
@@ -60408,7 +61520,10 @@ function ac_legend_topic(gobj, event, kw, src) {
|
|
|
60408
61520
|
return -1;
|
|
60409
61521
|
}
|
|
60410
61522
|
let next = priv.focus_topic === topic ? "" : topic;
|
|
60411
|
-
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SET_FOCUS_TOPIC", {
|
|
61523
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SET_FOCUS_TOPIC", {
|
|
61524
|
+
topic: next,
|
|
61525
|
+
reveal: "all"
|
|
61526
|
+
}, gobj);
|
|
60412
61527
|
(0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_TOPIC_SELECTED", { topic: next });
|
|
60413
61528
|
return 0;
|
|
60414
61529
|
}
|
|
@@ -60436,6 +61551,20 @@ function ac_find_nodes(gobj, event, kw, src) {
|
|
|
60436
61551
|
return 0;
|
|
60437
61552
|
}
|
|
60438
61553
|
/************************************************************
|
|
61554
|
+
* The fold pair of the toolbar, forwarded to the G6 child,
|
|
61555
|
+
* which owns the tree.
|
|
61556
|
+
************************************************************/
|
|
61557
|
+
function ac_expand_all(gobj, event, kw, src) {
|
|
61558
|
+
let priv = gobj.priv;
|
|
61559
|
+
if (priv.gobj_nodes_tree) (0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_EXPAND_ALL", {}, gobj);
|
|
61560
|
+
return 0;
|
|
61561
|
+
}
|
|
61562
|
+
function ac_collapse_all(gobj, event, kw, src) {
|
|
61563
|
+
let priv = gobj.priv;
|
|
61564
|
+
if (priv.gobj_nodes_tree) (0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_COLLAPSE_ALL", {}, gobj);
|
|
61565
|
+
return 0;
|
|
61566
|
+
}
|
|
61567
|
+
/************************************************************
|
|
60439
61568
|
* How many nodes the term matched, from the graph child. Zero with a
|
|
60440
61569
|
* term typed is an ANSWER and is shown; an empty box shows nothing.
|
|
60441
61570
|
************************************************************/
|
|
@@ -60457,7 +61586,10 @@ function ac_find_result(gobj, event, kw, src) {
|
|
|
60457
61586
|
function ac_set_focus_topic(gobj, event, kw, src) {
|
|
60458
61587
|
let priv = gobj.priv;
|
|
60459
61588
|
priv.focus_topic = kw && kw.topic || "";
|
|
60460
|
-
if (priv.gobj_nodes_tree) (0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_FOCUS_TOPIC", {
|
|
61589
|
+
if (priv.gobj_nodes_tree) (0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_FOCUS_TOPIC", {
|
|
61590
|
+
topic: priv.focus_topic,
|
|
61591
|
+
reveal: kw && kw.reveal || "page"
|
|
61592
|
+
}, gobj);
|
|
60461
61593
|
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
60462
61594
|
let $legend = $container ? $container.querySelector(".GRAPH_LEGEND") : null;
|
|
60463
61595
|
if ($legend && !$legend.classList.contains("is-hidden")) refresh_legend(gobj);
|
|
@@ -60628,6 +61760,16 @@ function create_gclass$3(gclass_name) {
|
|
|
60628
61760
|
ac_find_nodes,
|
|
60629
61761
|
null
|
|
60630
61762
|
],
|
|
61763
|
+
[
|
|
61764
|
+
"EV_EXPAND_ALL",
|
|
61765
|
+
ac_expand_all,
|
|
61766
|
+
null
|
|
61767
|
+
],
|
|
61768
|
+
[
|
|
61769
|
+
"EV_COLLAPSE_ALL",
|
|
61770
|
+
ac_collapse_all,
|
|
61771
|
+
null
|
|
61772
|
+
],
|
|
60631
61773
|
[
|
|
60632
61774
|
"EV_LAYOUT_AUTOSET",
|
|
60633
61775
|
ac_layout_autoset,
|
|
@@ -60690,6 +61832,8 @@ function create_gclass$3(gclass_name) {
|
|
|
60690
61832
|
["EV_SET_OPERATION_MODE", 0],
|
|
60691
61833
|
["EV_SET_FOCUS_TOPIC", 0],
|
|
60692
61834
|
["EV_FIND_NODES", 0],
|
|
61835
|
+
["EV_EXPAND_ALL", 0],
|
|
61836
|
+
["EV_COLLAPSE_ALL", 0],
|
|
60693
61837
|
["EV_FIND_RESULT", 0],
|
|
60694
61838
|
["EV_LAYOUT_AUTOSET", 0],
|
|
60695
61839
|
["EV_TOGGLE_LEGEND", 0],
|