@yuneta/gobj-ui 5.15.0 → 5.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -15
- package/dist/gobj-ui.cjs.js +412 -75
- package/dist/gobj-ui.es.js +412 -75
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +38 -24
- package/src/c_yui_treedb_graph.js +99 -1
- package/src/c_yui_treedb_schema.js +348 -43
- package/src/c_yui_treedb_topic_with_form.js +16 -1
- package/src/c_yui_treedb_topics.js +2 -1
- package/src/treedb_node_label.js +73 -0
- package/src/treedb_node_label.test.js +92 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -15500,7 +15500,7 @@ function request_print_tranger$1(gobj, path) {
|
|
|
15500
15500
|
* would travel, be refused by the yuno, and come back as a toast --
|
|
15501
15501
|
* after the table had already drawn the row.
|
|
15502
15502
|
***************************************************************/
|
|
15503
|
-
function refuse_if_readonly$
|
|
15503
|
+
function refuse_if_readonly$2(gobj, event) {
|
|
15504
15504
|
if (!gobj_read_bool_attr(gobj, "readonly")) return false;
|
|
15505
15505
|
log_error(`${gobj_short_name(gobj)}: ${event} refused, treedb '${gobj_read_str_attr(gobj, "treedb_name")}' is READ-ONLY`);
|
|
15506
15506
|
return true;
|
|
@@ -15572,7 +15572,8 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
|
|
|
15572
15572
|
treedb_name: kw_get_str(gobj, kw_command, "treedb_name", "", 0),
|
|
15573
15573
|
topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
|
|
15574
15574
|
record: kw_get_dict(gobj, kw_command, "record", {}, 0),
|
|
15575
|
-
created: command === "create-node"
|
|
15575
|
+
created: command === "create-node",
|
|
15576
|
+
command
|
|
15576
15577
|
});
|
|
15577
15578
|
break;
|
|
15578
15579
|
case "delete-node": break;
|
|
@@ -15777,7 +15778,7 @@ function ac_treedb_node_deleted$1(gobj, event, kw, src) {
|
|
|
15777
15778
|
* }
|
|
15778
15779
|
********************************************/
|
|
15779
15780
|
function ac_create_record(gobj, event, kw, src) {
|
|
15780
|
-
if (refuse_if_readonly$
|
|
15781
|
+
if (refuse_if_readonly$2(gobj, event)) return -1;
|
|
15781
15782
|
let treedb_name = gobj_read_str_attr(gobj, "treedb_name");
|
|
15782
15783
|
let topic_name = gobj_read_attr(src, "topic_name");
|
|
15783
15784
|
let record = kw.record;
|
|
@@ -15795,7 +15796,7 @@ function ac_create_record(gobj, event, kw, src) {
|
|
|
15795
15796
|
* }
|
|
15796
15797
|
********************************************/
|
|
15797
15798
|
function ac_update_record(gobj, event, kw, src) {
|
|
15798
|
-
if (refuse_if_readonly$
|
|
15799
|
+
if (refuse_if_readonly$2(gobj, event)) return -1;
|
|
15799
15800
|
let treedb_name = gobj_read_str_attr(gobj, "treedb_name");
|
|
15800
15801
|
let topic_name = gobj_read_attr(src, "topic_name");
|
|
15801
15802
|
let record = kw.record;
|
|
@@ -15812,7 +15813,7 @@ function ac_update_record(gobj, event, kw, src) {
|
|
|
15812
15813
|
* }
|
|
15813
15814
|
********************************************/
|
|
15814
15815
|
function ac_delete_record(gobj, event, kw, src) {
|
|
15815
|
-
if (refuse_if_readonly$
|
|
15816
|
+
if (refuse_if_readonly$2(gobj, event)) return -1;
|
|
15816
15817
|
let treedb_name = gobj_read_str_attr(gobj, "treedb_name");
|
|
15817
15818
|
let topic_name = gobj_read_attr(src, "topic_name");
|
|
15818
15819
|
let record = kw.record;
|
|
@@ -17633,7 +17634,7 @@ function write_plan(gobj) {
|
|
|
17633
17634
|
* A read-only topic refuses the write EVENTS too, not only their
|
|
17634
17635
|
* buttons.
|
|
17635
17636
|
***************************************************************/
|
|
17636
|
-
function refuse_if_readonly(gobj, event) {
|
|
17637
|
+
function refuse_if_readonly$1(gobj, event) {
|
|
17637
17638
|
if (!gobj_read_bool_attr(gobj, "readonly")) return false;
|
|
17638
17639
|
log_error(`${gobj_short_name(gobj)}: ${event} refused, topic '${gobj_read_str_attr(gobj, "topic_name")}' is READ-ONLY`);
|
|
17639
17640
|
return true;
|
|
@@ -17705,7 +17706,10 @@ function ac_load_node_updated(gobj, event, kw, src) {
|
|
|
17705
17706
|
return -1;
|
|
17706
17707
|
}
|
|
17707
17708
|
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
17708
|
-
if (tabulator)
|
|
17709
|
+
if (tabulator) {
|
|
17710
|
+
for (let record of data) if (tabulator.getRow(record.id)) tabulator.updateData([record]);
|
|
17711
|
+
else if (tabulator.getDataCount() > 0) log_error(`${gobj_short_name(gobj)}: updated node is not in the loaded table: ${record.id}`);
|
|
17712
|
+
}
|
|
17709
17713
|
return 0;
|
|
17710
17714
|
}
|
|
17711
17715
|
/************************************************************
|
|
@@ -17730,7 +17734,7 @@ function ac_node_deleted$1(gobj, event, kw, src) {
|
|
|
17730
17734
|
* and the Op column is visible (with row's edit/delete icons)
|
|
17731
17735
|
************************************************************/
|
|
17732
17736
|
function ac_edition_mode(gobj, event, kw, src) {
|
|
17733
|
-
if (refuse_if_readonly(gobj, event)) return -1;
|
|
17737
|
+
if (refuse_if_readonly$1(gobj, event)) return -1;
|
|
17734
17738
|
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
17735
17739
|
let editable = gobj_read_bool_attr(gobj, "editable");
|
|
17736
17740
|
editable = !editable;
|
|
@@ -17774,7 +17778,7 @@ function ac_edition_mode(gobj, event, kw, src) {
|
|
|
17774
17778
|
* - the backend will broadcast the new record that will be added to table
|
|
17775
17779
|
************************************************************/
|
|
17776
17780
|
function ac_new_row(gobj, event, kw, src) {
|
|
17777
|
-
if (refuse_if_readonly(gobj, event)) return -1;
|
|
17781
|
+
if (refuse_if_readonly$1(gobj, event)) return -1;
|
|
17778
17782
|
let row = {};
|
|
17779
17783
|
let desc = gobj_read_attr(gobj, "desc");
|
|
17780
17784
|
for (let i = 0; i < desc.cols.length; i++) {
|
|
@@ -17804,7 +17808,7 @@ function ac_new_row(gobj, event, kw, src) {
|
|
|
17804
17808
|
* kw {index:, row:}
|
|
17805
17809
|
************************************************************/
|
|
17806
17810
|
function ac_delete_rows(gobj, event, kw, src) {
|
|
17807
|
-
if (refuse_if_readonly(gobj, event)) return -1;
|
|
17811
|
+
if (refuse_if_readonly$1(gobj, event)) return -1;
|
|
17808
17812
|
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
17809
17813
|
if (json_size(kw) === 0) {
|
|
17810
17814
|
let rows = tabulator.getSelectedData();
|
|
@@ -17868,7 +17872,7 @@ function ac_copy_rows(gobj, event, kw, src) {
|
|
|
17868
17872
|
* From internal
|
|
17869
17873
|
************************************************************/
|
|
17870
17874
|
function ac_paste_rows(gobj, event, kw, src) {
|
|
17871
|
-
if (refuse_if_readonly(gobj, event)) return -1;
|
|
17875
|
+
if (refuse_if_readonly$1(gobj, event)) return -1;
|
|
17872
17876
|
if (kw.topic_name === gobj_read_str_attr(gobj, "topic_name") && kw.treedb_name === gobj_read_str_attr(gobj, "treedb_name")) for (let row of kw.rows) gobj_publish_event(gobj, "EV_CREATE_RECORD", {
|
|
17873
17877
|
topic_name: gobj_read_str_attr(gobj, "topic_name"),
|
|
17874
17878
|
record: row
|
|
@@ -17881,7 +17885,7 @@ function ac_paste_rows(gobj, event, kw, src) {
|
|
|
17881
17885
|
* fkeys, times and numbers). Route by the form's mode.
|
|
17882
17886
|
************************************************************/
|
|
17883
17887
|
function ac_form_save_record(gobj, event, kw, src) {
|
|
17884
|
-
if (refuse_if_readonly(gobj, event)) return -1;
|
|
17888
|
+
if (refuse_if_readonly$1(gobj, event)) return -1;
|
|
17885
17889
|
let mode = gobj_read_str_attr(src, "form_mode");
|
|
17886
17890
|
gobj_publish_event(gobj, mode === "create" ? "EV_CREATE_RECORD" : "EV_UPDATE_RECORD", {
|
|
17887
17891
|
topic_name: gobj_read_str_attr(gobj, "topic_name"),
|
|
@@ -18289,6 +18293,7 @@ var attrs_table$3 = [
|
|
|
18289
18293
|
SDATA(data_type_t.DTP_STRING, "treedb_name", 0, null, "Remote service treedb name"),
|
|
18290
18294
|
SDATA(data_type_t.DTP_DICT, "descs", 0, null, "Descriptions of topics obtained"),
|
|
18291
18295
|
SDATA(data_type_t.DTP_BOOLEAN, "system", 0, false, "Manage system topics (true) or user topics (false)"),
|
|
18296
|
+
SDATA(data_type_t.DTP_BOOLEAN, "readonly", 0, false, "The whole treedb is read-only: the graph drops its `edition` mode (the only one that draws write affordances) and refuses every write event. Set it when this yuno is not the MASTER of the treedb's tranger -- only the master can write, and the yuno answers 'READ-ONLY' to a write since SDK 7.13.0 (ask `treedb-info`)"),
|
|
18292
18297
|
SDATA(data_type_t.DTP_STRING, "back_route", 0, "", "Optional hash route for a '← topics' button back to the topics grid (host-supplied; empty = no button)"),
|
|
18293
18298
|
SDATA(data_type_t.DTP_STRING, "base_route", 0, "", "This view's base route (host-supplied); used to declare its per-topic focus sub-routes to the site map (ROUTING.md contributor)."),
|
|
18294
18299
|
SDATA(data_type_t.DTP_DICT, "records", 0, "{}", "Data of topics"),
|
|
@@ -18339,6 +18344,7 @@ function mt_create$3(gobj) {
|
|
|
18339
18344
|
if (!subscriber) subscriber = gobj_parent(gobj);
|
|
18340
18345
|
gobj_subscribe_event(gobj, null, {}, subscriber);
|
|
18341
18346
|
if (!priv.treedb_name) log_error(`${gobj_name(gobj)} -> treedb_name not configured`);
|
|
18347
|
+
if (gobj_read_bool_attr(gobj, "readonly") && priv.operation_mode === "edition") gobj_write_str_attr(gobj, "operation_mode", "reading");
|
|
18342
18348
|
let canvas_id = clean_name(gobj_name(gobj)) + "-canvas";
|
|
18343
18349
|
gobj_write_attr(gobj, "canvas_id", canvas_id);
|
|
18344
18350
|
let $container_canvas = build_ui$3(gobj).querySelector(`#${priv.canvas_id}`);
|
|
@@ -18493,6 +18499,8 @@ function destroy_ui(gobj) {
|
|
|
18493
18499
|
************************************************************/
|
|
18494
18500
|
function make_toolbar(gobj) {
|
|
18495
18501
|
gobj.priv;
|
|
18502
|
+
let modes = gobj_read_attr(gobj, "operation_modes");
|
|
18503
|
+
if (gobj_read_bool_attr(gobj, "readonly")) modes = modes.filter((mode) => mode !== "edition");
|
|
18496
18504
|
const $toolbar_header = yui_toolbar({}, [
|
|
18497
18505
|
[
|
|
18498
18506
|
"div",
|
|
@@ -18531,7 +18539,7 @@ function make_toolbar(gobj) {
|
|
|
18531
18539
|
[[
|
|
18532
18540
|
"select",
|
|
18533
18541
|
{ class: "GRAPH_MODE_SELECT" },
|
|
18534
|
-
|
|
18542
|
+
modes.map((item) => [
|
|
18535
18543
|
"option",
|
|
18536
18544
|
{},
|
|
18537
18545
|
item
|
|
@@ -19083,6 +19091,19 @@ function refresh_data(gobj) {
|
|
|
19083
19091
|
if (priv.gobj_nodes_tree) gobj_send_event(priv.gobj_nodes_tree, "EV_CLEAR_DATA", {}, gobj);
|
|
19084
19092
|
request_treedb_descs(gobj);
|
|
19085
19093
|
}
|
|
19094
|
+
/********************************************
|
|
19095
|
+
* The last gate before a write leaves for the yuno. The `edition`
|
|
19096
|
+
* mode is gone on a replica, so no button can raise these -- but the
|
|
19097
|
+
* G6 child also publishes them from its undo/redo history and from
|
|
19098
|
+
* saving the node geometry, and a write that got this far would
|
|
19099
|
+
* travel, be refused by the yuno, and come back as a toast with the
|
|
19100
|
+
* graph already redrawn.
|
|
19101
|
+
********************************************/
|
|
19102
|
+
function refuse_if_readonly(gobj, event) {
|
|
19103
|
+
if (!gobj_read_bool_attr(gobj, "readonly")) return false;
|
|
19104
|
+
log_error(`${gobj_short_name(gobj)}: ${event} refused, treedb '${gobj_read_str_attr(gobj, "treedb_name")}' is READ-ONLY`);
|
|
19105
|
+
return true;
|
|
19106
|
+
}
|
|
19086
19107
|
/***************************
|
|
19087
19108
|
* Actions
|
|
19088
19109
|
***************************/
|
|
@@ -19151,7 +19172,15 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
19151
19172
|
case "update-node":
|
|
19152
19173
|
case "delete-node":
|
|
19153
19174
|
case "link-nodes":
|
|
19154
|
-
case "unlink-nodes":
|
|
19175
|
+
case "unlink-nodes":
|
|
19176
|
+
if (result >= 0 && kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") gobj_publish_event(gobj, "EV_RECORD_WRITTEN", {
|
|
19177
|
+
treedb_name: kw_get_str(gobj, kw_command, "treedb_name", "", 0),
|
|
19178
|
+
topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
|
|
19179
|
+
record: kw_get_dict(gobj, kw_command, "record", {}, 0),
|
|
19180
|
+
created: command === "create-node",
|
|
19181
|
+
command
|
|
19182
|
+
});
|
|
19183
|
+
break;
|
|
19155
19184
|
default: log_error(`${gobj_short_name(gobj)} Command unknown: ${command}`);
|
|
19156
19185
|
}
|
|
19157
19186
|
return 0;
|
|
@@ -19370,7 +19399,9 @@ function ac_edge_clicked(gobj, event, kw, src) {
|
|
|
19370
19399
|
* Send to backend
|
|
19371
19400
|
********************************************/
|
|
19372
19401
|
function ac_create_node(gobj, event, kw, src) {
|
|
19373
|
-
let
|
|
19402
|
+
let priv = gobj.priv;
|
|
19403
|
+
if (refuse_if_readonly(gobj, event)) return -1;
|
|
19404
|
+
let treedb_name = priv.treedb_name;
|
|
19374
19405
|
let topic_name = kw.topic_name;
|
|
19375
19406
|
let record = kw.record;
|
|
19376
19407
|
return treedb_create_node(gobj, treedb_name, topic_name, record, kw.options || {});
|
|
@@ -19385,7 +19416,9 @@ function ac_create_node(gobj, event, kw, src) {
|
|
|
19385
19416
|
* Send to backend
|
|
19386
19417
|
********************************************/
|
|
19387
19418
|
function ac_update_node(gobj, event, kw, src) {
|
|
19388
|
-
let
|
|
19419
|
+
let priv = gobj.priv;
|
|
19420
|
+
if (refuse_if_readonly(gobj, event)) return -1;
|
|
19421
|
+
let treedb_name = priv.treedb_name;
|
|
19389
19422
|
let topic_name = kw.topic_name;
|
|
19390
19423
|
let record = kw.record;
|
|
19391
19424
|
return treedb_update_node(gobj, treedb_name, topic_name, record, kw.options || {});
|
|
@@ -19400,7 +19433,9 @@ function ac_update_node(gobj, event, kw, src) {
|
|
|
19400
19433
|
* Send to backend
|
|
19401
19434
|
********************************************/
|
|
19402
19435
|
function ac_delete_node(gobj, event, kw, src) {
|
|
19403
|
-
let
|
|
19436
|
+
let priv = gobj.priv;
|
|
19437
|
+
if (refuse_if_readonly(gobj, event)) return -1;
|
|
19438
|
+
let treedb_name = priv.treedb_name;
|
|
19404
19439
|
let topic_name = kw.topic_name;
|
|
19405
19440
|
let record = kw.record;
|
|
19406
19441
|
return treedb_delete_node(gobj, treedb_name, topic_name, record, kw.options || {});
|
|
@@ -19415,7 +19450,9 @@ function ac_delete_node(gobj, event, kw, src) {
|
|
|
19415
19450
|
* Send to backend
|
|
19416
19451
|
********************************************/
|
|
19417
19452
|
function ac_link_nodes(gobj, event, kw, src) {
|
|
19418
|
-
let
|
|
19453
|
+
let priv = gobj.priv;
|
|
19454
|
+
if (refuse_if_readonly(gobj, event)) return -1;
|
|
19455
|
+
let treedb_name = priv.treedb_name;
|
|
19419
19456
|
let parent_ref = kw.parent_ref;
|
|
19420
19457
|
let child_ref = kw.child_ref;
|
|
19421
19458
|
return treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, kw.options || {});
|
|
@@ -19430,7 +19467,9 @@ function ac_link_nodes(gobj, event, kw, src) {
|
|
|
19430
19467
|
* Send to backend
|
|
19431
19468
|
********************************************/
|
|
19432
19469
|
function ac_unlink_nodes(gobj, event, kw, src) {
|
|
19433
|
-
let
|
|
19470
|
+
let priv = gobj.priv;
|
|
19471
|
+
if (refuse_if_readonly(gobj, event)) return -1;
|
|
19472
|
+
let treedb_name = priv.treedb_name;
|
|
19434
19473
|
let parent_ref = kw.parent_ref;
|
|
19435
19474
|
let child_ref = kw.child_ref;
|
|
19436
19475
|
return treedb_unlink_nodes(gobj, treedb_name, parent_ref, child_ref, kw.options || {});
|
|
@@ -19470,6 +19509,10 @@ function ac_set_layout$1(gobj, event, kw, src) {
|
|
|
19470
19509
|
function ac_set_operation_mode$1(gobj, event, kw, src) {
|
|
19471
19510
|
let priv = gobj.priv;
|
|
19472
19511
|
let operation_mode = kw.operation_mode;
|
|
19512
|
+
if (operation_mode === "edition" && gobj_read_bool_attr(gobj, "readonly")) {
|
|
19513
|
+
log_error(`${gobj_short_name(gobj)}: edition mode refused, treedb '${gobj_read_str_attr(gobj, "treedb_name")}' is READ-ONLY`);
|
|
19514
|
+
return -1;
|
|
19515
|
+
}
|
|
19473
19516
|
gobj_write_str_attr(gobj, "operation_mode", operation_mode);
|
|
19474
19517
|
gobj_save_persistent_attrs(gobj, "operation_mode");
|
|
19475
19518
|
let $operation_mode_select = priv.$container.querySelector(".GRAPH_MODE_SELECT");
|
|
@@ -19691,6 +19734,7 @@ function create_gclass$3(gclass_name) {
|
|
|
19691
19734
|
["EV_SET_OPERATION_MODE", 0],
|
|
19692
19735
|
["EV_SET_FOCUS_TOPIC", 0],
|
|
19693
19736
|
["EV_OPERATION_MODE_CHANGED", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
19737
|
+
["EV_RECORD_WRITTEN", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
19694
19738
|
["EV_SHOW", 0],
|
|
19695
19739
|
["EV_HIDE", 0],
|
|
19696
19740
|
["EV_TRANSPORT_STATE", 0]
|
|
@@ -19710,11 +19754,26 @@ function register_c_yui_treedb_graph() {
|
|
|
19710
19754
|
/***********************************************************************
|
|
19711
19755
|
* c_yui_treedb_schema.js
|
|
19712
19756
|
*
|
|
19713
|
-
* Schema-graph landing
|
|
19714
|
-
*
|
|
19715
|
-
*
|
|
19716
|
-
*
|
|
19717
|
-
* the
|
|
19757
|
+
* Schema-graph landing: the treedb drawn the way its `.c` literal
|
|
19758
|
+
* draws it in ASCII (treedb_schema_*.c, treedb_system_schema.c) —
|
|
19759
|
+
* one CARD per topic listing its fields in schema order, one edge
|
|
19760
|
+
* per hook, from the row that declares the hook to the fkey row of
|
|
19761
|
+
* the child it names. Built from the schema `descs` alone: no data,
|
|
19762
|
+
* no backend calls.
|
|
19763
|
+
*
|
|
19764
|
+
* WHY THE CARD AND NOT A DOT. A topic is its fields; a schema is
|
|
19765
|
+
* read to find out what a topic holds and what links to what. A
|
|
19766
|
+
* graph of labelled dots answers neither, and the node graph next
|
|
19767
|
+
* door (C_G6_NODES_TREE) answers a different question entirely —
|
|
19768
|
+
* it draws the RECORDS, so on a treedb whose records are schemas
|
|
19769
|
+
* it draws one box per column, hundreds of them, each labelled by
|
|
19770
|
+
* a pkey that may be a rowid. This view draws the schema itself.
|
|
19771
|
+
*
|
|
19772
|
+
* The marks are the notation of the `.c` literals, so the drawing
|
|
19773
|
+
* and the source read the same — see schema_rows().
|
|
19774
|
+
*
|
|
19775
|
+
* A node click opens that topic's table (a real hash navigation
|
|
19776
|
+
* via the host-supplied `node_route`). An alternate landing to the
|
|
19718
19777
|
* topic cards, in the spirit of "every treedb is a graph".
|
|
19719
19778
|
*
|
|
19720
19779
|
* Copyright (c) 2026, ArtGins.
|
|
@@ -19724,6 +19783,27 @@ function register_c_yui_treedb_graph() {
|
|
|
19724
19783
|
* Constants
|
|
19725
19784
|
***************************************************************/
|
|
19726
19785
|
var GCLASS_NAME$2 = "C_YUI_TREEDB_SCHEMA";
|
|
19786
|
+
/************************************************************
|
|
19787
|
+
* Geometry of a card, in one place: the row height is what
|
|
19788
|
+
* turns a field's index into the vertical position of its
|
|
19789
|
+
* port, so an edge leaves the very row that declares the
|
|
19790
|
+
* hook and lands on the row that declares the fkey.
|
|
19791
|
+
************************************************************/
|
|
19792
|
+
var CARD_HEADER_H = 30;
|
|
19793
|
+
var CARD_ROW_H = 19;
|
|
19794
|
+
var CARD_PAD_V = 7;
|
|
19795
|
+
var CARD_MIN_W = 210;
|
|
19796
|
+
var CARD_MAX_W = 340;
|
|
19797
|
+
var topic_colors = [
|
|
19798
|
+
"rgb(237, 201, 73)",
|
|
19799
|
+
"rgb(118, 183, 178)",
|
|
19800
|
+
"rgb(255, 157, 167)",
|
|
19801
|
+
"rgb(175, 122, 161)",
|
|
19802
|
+
"rgb(89, 161, 79)",
|
|
19803
|
+
"rgb(186, 176, 171)",
|
|
19804
|
+
"rgb(66, 146, 198)"
|
|
19805
|
+
];
|
|
19806
|
+
var SYSTEM_TOPIC_COLOR = "rgb(148, 163, 184)";
|
|
19727
19807
|
/***************************************************************
|
|
19728
19808
|
* Data
|
|
19729
19809
|
***************************************************************/
|
|
@@ -19785,48 +19865,254 @@ function build_ui$2(gobj) {
|
|
|
19785
19865
|
gobj_write_attr(gobj, "$container", $container);
|
|
19786
19866
|
}
|
|
19787
19867
|
/************************************************************
|
|
19868
|
+
* The shape of a hook/fkey field, from the type it declares.
|
|
19869
|
+
* `dict` and `object` are the SAME thing to treedb (both build
|
|
19870
|
+
* a json object keyed by child id), and so are `list` and
|
|
19871
|
+
* `array` — see the hook/fkey switches in tr_treedb.c. A
|
|
19872
|
+
* `string` holds one reference, so it draws as one.
|
|
19873
|
+
************************************************************/
|
|
19874
|
+
function hook_mark(type) {
|
|
19875
|
+
if (type === "dict" || type === "object") return "{}";
|
|
19876
|
+
if (type === "list" || type === "array") return "[]";
|
|
19877
|
+
return "()";
|
|
19878
|
+
}
|
|
19879
|
+
/************************************************************
|
|
19880
|
+
* The fields of one topic, as the schema declares them.
|
|
19881
|
+
*
|
|
19882
|
+
* The marks are the notation of the schema `.c` literals
|
|
19883
|
+
* (treedb_schema_*.c, treedb_system_schema.c), so the
|
|
19884
|
+
* drawing and the source read the same:
|
|
19885
|
+
* {} dict hook (N unique children)
|
|
19886
|
+
* [] list hook (n not-unique children)
|
|
19887
|
+
* () 1 child
|
|
19888
|
+
* (↖) 1 fkey (1 parent)
|
|
19889
|
+
* [↖] n fkeys (n parents)
|
|
19890
|
+
* {↖} N fkeys (N parents)
|
|
19891
|
+
* * required
|
|
19892
|
+
* # the primary key
|
|
19893
|
+
*
|
|
19894
|
+
* A column can be BOTH hook and fkey, so the flags are read
|
|
19895
|
+
* here rather than through treedb_get_field_desc's single
|
|
19896
|
+
* `type`, which keeps only the last flag it saw.
|
|
19897
|
+
************************************************************/
|
|
19898
|
+
function schema_rows(desc) {
|
|
19899
|
+
let rows = [];
|
|
19900
|
+
if (!is_object(desc) || !Array.isArray(desc.cols)) return rows;
|
|
19901
|
+
for (let col of desc.cols) {
|
|
19902
|
+
if (!is_object(col) || !col.id) continue;
|
|
19903
|
+
let flags = Array.isArray(col.flag) ? col.flag : [];
|
|
19904
|
+
let is_hook = flags.indexOf("hook") >= 0;
|
|
19905
|
+
let is_fkey = flags.indexOf("fkey") >= 0;
|
|
19906
|
+
let mark = "";
|
|
19907
|
+
if (is_hook) mark = hook_mark(col.type);
|
|
19908
|
+
if (is_fkey) {
|
|
19909
|
+
let fmark = hook_mark(col.type).replace("}", "↖}").replace("]", "↖]").replace(")", "↖)");
|
|
19910
|
+
mark = mark ? mark + " " + fmark : fmark;
|
|
19911
|
+
}
|
|
19912
|
+
rows.push({
|
|
19913
|
+
name: col.id,
|
|
19914
|
+
type: col.type || "",
|
|
19915
|
+
mark,
|
|
19916
|
+
is_hook,
|
|
19917
|
+
is_fkey,
|
|
19918
|
+
is_pkey: col.id === desc.pkey,
|
|
19919
|
+
required: flags.indexOf("required") >= 0 || flags.indexOf("notnull") >= 0
|
|
19920
|
+
});
|
|
19921
|
+
}
|
|
19922
|
+
return rows;
|
|
19923
|
+
}
|
|
19924
|
+
/************************************************************
|
|
19925
|
+
* Size of the card that holds those rows. The width follows
|
|
19926
|
+
* the longest line so a long field name is not clipped into
|
|
19927
|
+
* an ellipsis — the point of the drawing is to read them.
|
|
19928
|
+
************************************************************/
|
|
19929
|
+
function card_size(rows) {
|
|
19930
|
+
let longest = 0;
|
|
19931
|
+
for (let row of rows) {
|
|
19932
|
+
let len = row.name.length + (row.mark ? row.mark.length + 2 : 0) + 2;
|
|
19933
|
+
if (len > longest) longest = len;
|
|
19934
|
+
}
|
|
19935
|
+
let w = Math.round(26 + longest * 6.6);
|
|
19936
|
+
if (w < CARD_MIN_W) w = CARD_MIN_W;
|
|
19937
|
+
if (w > CARD_MAX_W) w = CARD_MAX_W;
|
|
19938
|
+
let h = 44 + rows.length * CARD_ROW_H;
|
|
19939
|
+
return [w, h];
|
|
19940
|
+
}
|
|
19941
|
+
/************************************************************
|
|
19942
|
+
* Vertical placement of a field's port, as a fraction of the
|
|
19943
|
+
* card height: the centre of its own row.
|
|
19944
|
+
************************************************************/
|
|
19945
|
+
function row_placement(index, height) {
|
|
19946
|
+
return (37 + index * CARD_ROW_H + CARD_ROW_H / 2) / height;
|
|
19947
|
+
}
|
|
19948
|
+
/************************************************************
|
|
19949
|
+
* The card itself. Header = topic name on its topic colour;
|
|
19950
|
+
* body = one line per field, in schema order.
|
|
19951
|
+
************************************************************/
|
|
19952
|
+
function build_card_innerHTML(topic, rows, color, dark) {
|
|
19953
|
+
let surface = dark ? "#1b2230" : "#ffffff";
|
|
19954
|
+
let bg = dark ? `color-mix(in srgb, ${color} 18%, #232b38)` : `color-mix(in srgb, ${color} 6%, ${surface})`;
|
|
19955
|
+
let border = dark ? `color-mix(in srgb, ${color} 85%, #ffffff)` : color;
|
|
19956
|
+
let header_bg = dark ? `color-mix(in srgb, ${color} 45%, #2c3542)` : `color-mix(in srgb, ${color} 28%, ${surface})`;
|
|
19957
|
+
let title_color = dark ? "#e8eaed" : "#0f172a";
|
|
19958
|
+
let text_color = dark ? "#d3d8de" : "#334155";
|
|
19959
|
+
let mute_color = dark ? "#98a2b0" : "#7c8694";
|
|
19960
|
+
let rule_color = dark ? "rgba(255,255,255,0.06)" : "rgba(15,23,42,0.05)";
|
|
19961
|
+
let shadow = dark ? "0 1px 3px rgba(0,0,0,0.45), 0 1px 2px rgba(0,0,0,0.30)" : "0 1px 3px rgba(15,23,42,0.12), 0 1px 2px rgba(15,23,42,0.06)";
|
|
19962
|
+
let rows_html = "";
|
|
19963
|
+
for (let row of rows) {
|
|
19964
|
+
let lead = row.is_pkey ? "#" : row.required ? "*" : "";
|
|
19965
|
+
let name_weight = row.is_pkey || row.required ? "600" : "400";
|
|
19966
|
+
let name_color = row.is_hook || row.is_fkey ? title_color : text_color;
|
|
19967
|
+
rows_html += ` <div class="TREEDB_SCHEMA_FIELD" style="
|
|
19968
|
+
display: flex; align-items: center; gap: 6px;
|
|
19969
|
+
height: ${CARD_ROW_H}px; line-height: ${CARD_ROW_H}px;
|
|
19970
|
+
padding: 0 10px; border-top: 1px solid ${rule_color};
|
|
19971
|
+
">
|
|
19972
|
+
<span style="
|
|
19973
|
+
width: 8px; flex: 0 0 8px; text-align: center;
|
|
19974
|
+
color: ${mute_color}; font-size: 11px;
|
|
19975
|
+
">${lead}</span>
|
|
19976
|
+
<span style="
|
|
19977
|
+
flex: 1 1 auto; min-width: 0; overflow: hidden;
|
|
19978
|
+
text-overflow: ellipsis; white-space: nowrap;
|
|
19979
|
+
font-size: 12px; font-weight: ${name_weight}; color: ${name_color};
|
|
19980
|
+
">${escapeHtml(row.name)}</span>
|
|
19981
|
+
<span style="
|
|
19982
|
+
flex: 0 0 auto; font-size: 11px; color: ${mute_color};
|
|
19983
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
19984
|
+
">${escapeHtml(row.mark)}</span>
|
|
19985
|
+
</div>
|
|
19986
|
+
`;
|
|
19987
|
+
}
|
|
19988
|
+
return `
|
|
19989
|
+
<div class="TREEDB_SCHEMA_CARD" title="${escapeHtml(topic)}" style="
|
|
19990
|
+
box-sizing: border-box;
|
|
19991
|
+
width: 100%;
|
|
19992
|
+
height: 100%;
|
|
19993
|
+
background: ${bg};
|
|
19994
|
+
border: 1.5px solid ${border};
|
|
19995
|
+
border-radius: 8px;
|
|
19996
|
+
box-shadow: ${shadow};
|
|
19997
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
19998
|
+
display: flex;
|
|
19999
|
+
flex-direction: column;
|
|
20000
|
+
overflow: hidden;
|
|
20001
|
+
cursor: pointer;
|
|
20002
|
+
">
|
|
20003
|
+
<div class="TREEDB_SCHEMA_CARD_HEADER" style="
|
|
20004
|
+
height: ${CARD_HEADER_H}px; line-height: ${CARD_HEADER_H}px;
|
|
20005
|
+
flex: 0 0 ${CARD_HEADER_H}px;
|
|
20006
|
+
padding: 0 10px; background: ${header_bg}; color: ${title_color};
|
|
20007
|
+
font-size: 13px; font-weight: 700;
|
|
20008
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
20009
|
+
">${escapeHtml(topic)}</div>
|
|
20010
|
+
<div class="TREEDB_SCHEMA_CARD_BODY" style="
|
|
20011
|
+
flex: 1 1 auto; padding: ${CARD_PAD_V}px 0; overflow: hidden;
|
|
20012
|
+
">
|
|
20013
|
+
${rows_html} </div>
|
|
20014
|
+
</div>
|
|
20015
|
+
`;
|
|
20016
|
+
}
|
|
20017
|
+
/************************************************************
|
|
19788
20018
|
* Derive {nodes, edges} from the schema.
|
|
19789
|
-
*
|
|
19790
|
-
*
|
|
20019
|
+
*
|
|
20020
|
+
* Node = a topic, drawn as the card the `.c` literal draws in
|
|
20021
|
+
* ASCII: its name and its fields. Edge = a hook, from the row
|
|
20022
|
+
* that declares it to the fkey row of the child it names —
|
|
20023
|
+
* `'hook': {'users': 'departments'}` says both ends, so the
|
|
20024
|
+
* arrow can land where the `.c` drawing lands it. An fkey
|
|
20025
|
+
* whose parent declares no hook still gets its edge, or a
|
|
20026
|
+
* half-declared schema would draw as disconnected.
|
|
20027
|
+
*
|
|
19791
20028
|
* Left-to-right dagre follows the parent -> child data flow.
|
|
19792
20029
|
************************************************************/
|
|
19793
20030
|
function schema_to_graph(gobj) {
|
|
19794
20031
|
let descs = gobj_read_attr(gobj, "descs");
|
|
19795
20032
|
let system = gobj_read_bool_attr(gobj, "system");
|
|
20033
|
+
let dark = yui_is_dark();
|
|
19796
20034
|
let nodes = [];
|
|
19797
|
-
let
|
|
20035
|
+
let cards = {};
|
|
19798
20036
|
if (!is_object(descs)) return {
|
|
19799
20037
|
nodes,
|
|
19800
20038
|
edges: []
|
|
19801
20039
|
};
|
|
20040
|
+
let idx = 0;
|
|
19802
20041
|
for (let topic of Object.keys(descs)) {
|
|
19803
|
-
|
|
19804
|
-
|
|
20042
|
+
let is_system = topic.substring(0, 2) === "__";
|
|
20043
|
+
if (!system && is_system) continue;
|
|
20044
|
+
let rows = schema_rows(descs[topic]);
|
|
20045
|
+
let color;
|
|
20046
|
+
if (is_system) color = SYSTEM_TOPIC_COLOR;
|
|
20047
|
+
else {
|
|
20048
|
+
color = topic_colors[idx % topic_colors.length];
|
|
20049
|
+
idx++;
|
|
20050
|
+
}
|
|
20051
|
+
cards[topic] = {
|
|
20052
|
+
rows,
|
|
20053
|
+
size: card_size(rows),
|
|
20054
|
+
color
|
|
20055
|
+
};
|
|
20056
|
+
}
|
|
20057
|
+
for (let topic of Object.keys(cards)) {
|
|
20058
|
+
let card = cards[topic];
|
|
20059
|
+
let [w, h] = card.size;
|
|
20060
|
+
let ports = [];
|
|
20061
|
+
for (let i = 0; i < card.rows.length; i++) {
|
|
20062
|
+
let row = card.rows[i];
|
|
20063
|
+
if (!row.is_hook && !row.is_fkey) continue;
|
|
20064
|
+
ports.push({
|
|
20065
|
+
key: row.name,
|
|
20066
|
+
placement: [row.is_hook ? 1 : 0, row_placement(i, h)],
|
|
20067
|
+
fill: card.color,
|
|
20068
|
+
stroke: getStrokeColor(card.color)
|
|
20069
|
+
});
|
|
20070
|
+
}
|
|
19805
20071
|
nodes.push({
|
|
19806
20072
|
id: topic,
|
|
19807
|
-
|
|
20073
|
+
type: "html",
|
|
20074
|
+
style: {
|
|
20075
|
+
size: [w, h],
|
|
20076
|
+
dx: -w / 2,
|
|
20077
|
+
dy: -h / 2,
|
|
20078
|
+
innerHTML: build_card_innerHTML(topic, card.rows, card.color, dark),
|
|
20079
|
+
port: ports.length > 0,
|
|
20080
|
+
ports,
|
|
20081
|
+
portR: 3,
|
|
20082
|
+
portLineWidth: 1
|
|
20083
|
+
},
|
|
20084
|
+
data: {
|
|
20085
|
+
topic_name: topic,
|
|
20086
|
+
rows: card.rows,
|
|
20087
|
+
color: card.color
|
|
20088
|
+
}
|
|
19808
20089
|
});
|
|
19809
20090
|
}
|
|
19810
20091
|
let edge_seen = {};
|
|
19811
20092
|
let edges = [];
|
|
19812
|
-
let add_edge = (source, target) => {
|
|
19813
|
-
if (!
|
|
19814
|
-
let key = source
|
|
20093
|
+
let add_edge = (source, source_port, target, target_port) => {
|
|
20094
|
+
if (!cards[source] || !cards[target]) return;
|
|
20095
|
+
let key = `${source}|${source_port}|${target}|${target_port}`;
|
|
19815
20096
|
if (edge_seen[key]) return;
|
|
19816
20097
|
edge_seen[key] = true;
|
|
19817
20098
|
edges.push({
|
|
19818
20099
|
id: key,
|
|
20100
|
+
type: "cubic",
|
|
19819
20101
|
source,
|
|
19820
|
-
target
|
|
20102
|
+
target,
|
|
20103
|
+
style: {
|
|
20104
|
+
sourcePort: source_port,
|
|
20105
|
+
targetPort: target_port
|
|
20106
|
+
}
|
|
19821
20107
|
});
|
|
19822
20108
|
};
|
|
19823
|
-
for (let topic of Object.keys(
|
|
20109
|
+
for (let topic of Object.keys(cards)) {
|
|
19824
20110
|
let desc = descs[topic];
|
|
19825
20111
|
if (!is_object(desc) || !Array.isArray(desc.cols)) continue;
|
|
19826
20112
|
for (let col of desc.cols) {
|
|
19827
|
-
if (!col) continue;
|
|
19828
|
-
if (is_object(col.hook)) for (let child of Object.keys(col.hook)) add_edge(topic, child);
|
|
19829
|
-
|
|
20113
|
+
if (!is_object(col) || !col.id) continue;
|
|
20114
|
+
if (is_object(col.hook)) for (let child of Object.keys(col.hook)) add_edge(topic, col.id, child, col.hook[child]);
|
|
20115
|
+
if (is_object(col.fkey)) for (let parent of Object.keys(col.fkey)) add_edge(parent, col.fkey[parent], topic, col.id);
|
|
19830
20116
|
}
|
|
19831
20117
|
}
|
|
19832
20118
|
return {
|
|
@@ -19835,26 +20121,15 @@ function schema_to_graph(gobj) {
|
|
|
19835
20121
|
};
|
|
19836
20122
|
}
|
|
19837
20123
|
/************************************************************
|
|
19838
|
-
* The theme-dependent
|
|
19839
|
-
*
|
|
20124
|
+
* The theme-dependent edge style, in ONE place: applied as
|
|
20125
|
+
* the graph is built and re-applied on a theme switch
|
|
19840
20126
|
* (ac_theme), which restyles the LIVE graph — rebuilding it
|
|
19841
20127
|
* would drop the user's zoom/pan and any dragged node.
|
|
19842
20128
|
************************************************************/
|
|
19843
|
-
function node_style(dark) {
|
|
19844
|
-
return {
|
|
19845
|
-
size: 40,
|
|
19846
|
-
fill: "#5B8FF9",
|
|
19847
|
-
labelText: (d) => d.id,
|
|
19848
|
-
labelPlacement: "bottom",
|
|
19849
|
-
labelFill: dark ? "#e6e6e6" : "#333333",
|
|
19850
|
-
labelBackground: true,
|
|
19851
|
-
labelBackgroundFill: dark ? "rgba(0,0,0,0.5)" : "rgba(255,255,255,0.7)",
|
|
19852
|
-
cursor: "pointer"
|
|
19853
|
-
};
|
|
19854
|
-
}
|
|
19855
20129
|
function edge_style(dark) {
|
|
19856
20130
|
return {
|
|
19857
|
-
stroke: dark ? "#
|
|
20131
|
+
stroke: dark ? "#7a8593" : "#9aa4b2",
|
|
20132
|
+
lineWidth: 1.2,
|
|
19858
20133
|
endArrow: true
|
|
19859
20134
|
};
|
|
19860
20135
|
}
|
|
@@ -19886,13 +20161,12 @@ function build_graph$1(gobj) {
|
|
|
19886
20161
|
container: $container,
|
|
19887
20162
|
autoResize: true,
|
|
19888
20163
|
data,
|
|
19889
|
-
node: { style: node_style(dark) },
|
|
19890
20164
|
edge: { style: edge_style(dark) },
|
|
19891
20165
|
layout: {
|
|
19892
20166
|
type: "antv-dagre",
|
|
19893
20167
|
rankdir: "LR",
|
|
19894
|
-
nodesep:
|
|
19895
|
-
ranksep:
|
|
20168
|
+
nodesep: 28,
|
|
20169
|
+
ranksep: 90
|
|
19896
20170
|
},
|
|
19897
20171
|
behaviors: [
|
|
19898
20172
|
"zoom-canvas",
|
|
@@ -19977,8 +20251,17 @@ function ac_theme$1(gobj, event, kw, src) {
|
|
|
19977
20251
|
let dark = kw && kw.theme ? kw.theme === "dark" : yui_is_dark();
|
|
19978
20252
|
try {
|
|
19979
20253
|
graph.setTheme(dark ? "dark" : "light");
|
|
19980
|
-
graph.setNode({ style: node_style(dark) });
|
|
19981
20254
|
graph.setEdge({ style: edge_style(dark) });
|
|
20255
|
+
let updates = [];
|
|
20256
|
+
for (let node of graph.getNodeData()) {
|
|
20257
|
+
let data = node.data;
|
|
20258
|
+
if (!is_object(data) || !Array.isArray(data.rows)) continue;
|
|
20259
|
+
updates.push({
|
|
20260
|
+
id: node.id,
|
|
20261
|
+
style: { innerHTML: build_card_innerHTML(data.topic_name, data.rows, data.color, dark) }
|
|
20262
|
+
});
|
|
20263
|
+
}
|
|
20264
|
+
if (updates.length > 0) graph.updateNodeData(updates);
|
|
19982
20265
|
graph.draw().catch((e) => {
|
|
19983
20266
|
log_error(`${gobj_short_name(gobj)}: schema graph redraw failed: ${e}`);
|
|
19984
20267
|
});
|
|
@@ -20043,6 +20326,58 @@ function register_c_yui_treedb_schema() {
|
|
|
20043
20326
|
return create_gclass$2(GCLASS_NAME$2);
|
|
20044
20327
|
}
|
|
20045
20328
|
//#endregion
|
|
20329
|
+
//#region src/treedb_node_label.js
|
|
20330
|
+
/***********************************************************************
|
|
20331
|
+
* treedb_node_label.js
|
|
20332
|
+
*
|
|
20333
|
+
* Pure, testable logic behind the label of a node in the treedb
|
|
20334
|
+
* graph: WHAT A RECORD IS CALLED, which is not always what it is
|
|
20335
|
+
* keyed by. Kept out of the gclass so it can be unit-tested with
|
|
20336
|
+
* no DOM and no G6.
|
|
20337
|
+
*
|
|
20338
|
+
* Copyright (c) 2026, ArtGins.
|
|
20339
|
+
* All Rights Reserved.
|
|
20340
|
+
***********************************************************************/
|
|
20341
|
+
/************************************************************
|
|
20342
|
+
* What a node is CALLED, which is not always what it is
|
|
20343
|
+
* keyed by.
|
|
20344
|
+
*
|
|
20345
|
+
* A topic whose id column is flagged `rowid` or `uuid` keys
|
|
20346
|
+
* its records by a value nobody reads — that is the point of
|
|
20347
|
+
* those flags — and the name a human knows the record by
|
|
20348
|
+
* lives in the secondary key the topic declares (`pkey2s`,
|
|
20349
|
+
* carried in the desc since SDK > 7.13.0). The `topics` and
|
|
20350
|
+
* `cols` topics of treedb_system_schema are the case that
|
|
20351
|
+
* forced this: keyed by rowid, named in `value`, so every
|
|
20352
|
+
* card in the graph read "181", "225", "193".
|
|
20353
|
+
*
|
|
20354
|
+
* The pkey stays reachable: it is the card's tooltip.
|
|
20355
|
+
*
|
|
20356
|
+
* Falls back to the id whenever the schema does not say
|
|
20357
|
+
* otherwise — an older node whose desc carries no `pkey2s`
|
|
20358
|
+
* included.
|
|
20359
|
+
************************************************************/
|
|
20360
|
+
function node_label(desc, record) {
|
|
20361
|
+
let id = record.id;
|
|
20362
|
+
let id_col = null;
|
|
20363
|
+
if (Array.isArray(desc.cols)) {
|
|
20364
|
+
for (let col of desc.cols) if (col && col.id === (desc.pkey || "id")) {
|
|
20365
|
+
id_col = col;
|
|
20366
|
+
break;
|
|
20367
|
+
}
|
|
20368
|
+
}
|
|
20369
|
+
if (!id_col || !Array.isArray(id_col.flag)) return id;
|
|
20370
|
+
if (id_col.flag.indexOf("rowid") < 0 && id_col.flag.indexOf("uuid") < 0) return id;
|
|
20371
|
+
let pkey2s = desc.pkey2s;
|
|
20372
|
+
if (typeof pkey2s === "string") pkey2s = pkey2s ? [pkey2s] : [];
|
|
20373
|
+
if (!Array.isArray(pkey2s)) return id;
|
|
20374
|
+
for (let name of pkey2s) {
|
|
20375
|
+
let value = record[name];
|
|
20376
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
20377
|
+
}
|
|
20378
|
+
return id;
|
|
20379
|
+
}
|
|
20380
|
+
//#endregion
|
|
20046
20381
|
//#region node_modules/@babel/runtime/helpers/esm/typeof.js
|
|
20047
20382
|
function _typeof(o) {
|
|
20048
20383
|
"@babel/helpers - typeof";
|
|
@@ -47575,19 +47910,19 @@ function create_topic_node(gobj, desc, record) {
|
|
|
47575
47910
|
style.size = [116, 40];
|
|
47576
47911
|
style.dx = -58;
|
|
47577
47912
|
style.dy = -20;
|
|
47578
|
-
style.innerHTML = build_chip_innerHTML(desc.color, priv.theme, record.icon, record.id);
|
|
47913
|
+
style.innerHTML = build_chip_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), record.id);
|
|
47579
47914
|
} else if (node_treedb_type === "extended") {
|
|
47580
47915
|
node_graph_type = "html";
|
|
47581
47916
|
style.size = [144, 66];
|
|
47582
47917
|
style.dx = -72;
|
|
47583
47918
|
style.dy = -33;
|
|
47584
|
-
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, record
|
|
47919
|
+
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, true, record.id);
|
|
47585
47920
|
} else {
|
|
47586
47921
|
node_graph_type = "html";
|
|
47587
47922
|
style.size = [172, 96];
|
|
47588
47923
|
style.dx = -86;
|
|
47589
47924
|
style.dy = -48;
|
|
47590
|
-
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, record
|
|
47925
|
+
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, false, record.id);
|
|
47591
47926
|
}
|
|
47592
47927
|
let topic_props = priv._graph_properties[desc.topic_name];
|
|
47593
47928
|
let topic_defaults = is_object(topic_props) && is_object(topic_props.defaults) ? topic_props.defaults : null;
|
|
@@ -47655,15 +47990,15 @@ function update_topic_node(gobj, desc, node_name, record) {
|
|
|
47655
47990
|
nodedata.data.record = record;
|
|
47656
47991
|
if (desc.node_treedb_type === "child") graph.updateNodeData([{
|
|
47657
47992
|
id: node_name,
|
|
47658
|
-
style: { innerHTML: build_chip_innerHTML(desc.color, priv.theme, record.icon, record.id) }
|
|
47993
|
+
style: { innerHTML: build_chip_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), record.id) }
|
|
47659
47994
|
}]);
|
|
47660
47995
|
else if (desc.node_treedb_type === "extended") graph.updateNodeData([{
|
|
47661
47996
|
id: node_name,
|
|
47662
|
-
style: { innerHTML: build_node_innerHTML(desc.color, priv.theme, record.icon, record
|
|
47997
|
+
style: { innerHTML: build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, true, record.id) }
|
|
47663
47998
|
}]);
|
|
47664
47999
|
else if (desc.node_treedb_type === "hierarchical") graph.updateNodeData([{
|
|
47665
48000
|
id: node_name,
|
|
47666
|
-
style: { innerHTML: build_node_innerHTML(desc.color, priv.theme, record.icon, record
|
|
48001
|
+
style: { innerHTML: build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, false, record.id) }
|
|
47667
48002
|
}]);
|
|
47668
48003
|
} catch (e) {
|
|
47669
48004
|
log_error(e.message);
|
|
@@ -49570,7 +49905,7 @@ function show_node_popover(gobj) {
|
|
|
49570
49905
|
};
|
|
49571
49906
|
if (node_graph_type === "hierarchical") {
|
|
49572
49907
|
let record = nodeData.data.record || {};
|
|
49573
|
-
updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon,
|
|
49908
|
+
updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id);
|
|
49574
49909
|
}
|
|
49575
49910
|
graph.updateNodeData([{
|
|
49576
49911
|
id: node_id,
|
|
@@ -49610,7 +49945,7 @@ function show_node_popover(gobj) {
|
|
|
49610
49945
|
};
|
|
49611
49946
|
if (node_graph_type === "hierarchical") {
|
|
49612
49947
|
let record = nodeData.data.record || {};
|
|
49613
|
-
restoreStyle.innerHTML = build_node_innerHTML(origFill, priv.theme, record.icon,
|
|
49948
|
+
restoreStyle.innerHTML = build_node_innerHTML(origFill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id);
|
|
49614
49949
|
}
|
|
49615
49950
|
graph.updateNodeData([{
|
|
49616
49951
|
id: node_id,
|
|
@@ -49711,15 +50046,15 @@ function refresh_html_nodes_theme(gobj, theme) {
|
|
|
49711
50046
|
let record = nd.data.record || {};
|
|
49712
50047
|
if (tt === "hierarchical") updates.push({
|
|
49713
50048
|
id: nodes[i].id,
|
|
49714
|
-
style: { innerHTML: build_node_innerHTML(nd.data.desc.color, theme, record.icon,
|
|
50049
|
+
style: { innerHTML: build_node_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, false, record.id) }
|
|
49715
50050
|
});
|
|
49716
50051
|
else if (tt === "child") updates.push({
|
|
49717
50052
|
id: nodes[i].id,
|
|
49718
|
-
style: { innerHTML: build_chip_innerHTML(nd.data.desc.color, theme, record.icon, record.id) }
|
|
50053
|
+
style: { innerHTML: build_chip_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), record.id) }
|
|
49719
50054
|
});
|
|
49720
50055
|
else if (tt === "extended") updates.push({
|
|
49721
50056
|
id: nodes[i].id,
|
|
49722
|
-
style: { innerHTML: build_node_innerHTML(nd.data.desc.color, theme, record.icon,
|
|
50057
|
+
style: { innerHTML: build_node_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, true, record.id) }
|
|
49723
50058
|
});
|
|
49724
50059
|
}
|
|
49725
50060
|
if (updates.length > 0) graph.updateNodeData(updates);
|
|
@@ -49751,7 +50086,8 @@ function refresh_default_edges_theme(gobj, theme) {
|
|
|
49751
50086
|
* but lighter (1px border, no shadow, single line). The name is
|
|
49752
50087
|
* always legible (ellipsis + native title tooltip on overflow).
|
|
49753
50088
|
************************************************************/
|
|
49754
|
-
function build_chip_innerHTML(color, theme, icon,
|
|
50089
|
+
function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
50090
|
+
let title = key || label;
|
|
49755
50091
|
let dark = theme === "dark";
|
|
49756
50092
|
let bg = dark ? `color-mix(in srgb, ${color} 30%, #2c3542)` : `color-mix(in srgb, ${color} 10%, ${dark ? "#1b2230" : "#ffffff"})`;
|
|
49757
50093
|
let border = dark ? `color-mix(in srgb, ${color} 85%, #ffffff)` : color;
|
|
@@ -49762,7 +50098,7 @@ function build_chip_innerHTML(color, theme, icon, id) {
|
|
|
49762
50098
|
margin-right: 6px; flex: 0 0 auto;
|
|
49763
50099
|
"/>`;
|
|
49764
50100
|
return `
|
|
49765
|
-
<div title="${escapeHtml(
|
|
50101
|
+
<div title="${escapeHtml(title)}" style="
|
|
49766
50102
|
box-sizing: border-box;
|
|
49767
50103
|
width: 100%;
|
|
49768
50104
|
height: 100%;
|
|
@@ -49779,7 +50115,7 @@ function build_chip_innerHTML(color, theme, icon, id) {
|
|
|
49779
50115
|
">${icon_html}<span style="
|
|
49780
50116
|
font-size: 12px; font-weight: 600; line-height: 1;
|
|
49781
50117
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
49782
|
-
">${escapeHtml(
|
|
50118
|
+
">${escapeHtml(label)}</span>
|
|
49783
50119
|
</div>
|
|
49784
50120
|
`;
|
|
49785
50121
|
}
|
|
@@ -49793,7 +50129,8 @@ function build_chip_innerHTML(color, theme, icon, id) {
|
|
|
49793
50129
|
* colour is kept (per-topic differentiation) but softened via
|
|
49794
50130
|
* color-mix instead of a harsh saturated fill. Theme-aware.
|
|
49795
50131
|
************************************************************/
|
|
49796
|
-
function build_node_innerHTML(color, theme, icon,
|
|
50132
|
+
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key) {
|
|
50133
|
+
let title = key || label;
|
|
49797
50134
|
let dark = theme === "dark";
|
|
49798
50135
|
let surface = dark ? "#1b2230" : "#ffffff";
|
|
49799
50136
|
let bg, border, border_style;
|
|
@@ -49823,7 +50160,7 @@ function build_node_innerHTML(color, theme, icon, id, topic_name, structural) {
|
|
|
49823
50160
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
49824
50161
|
">${escapeHtml(topic_name)}</div>`;
|
|
49825
50162
|
return `
|
|
49826
|
-
<div title="${escapeHtml(
|
|
50163
|
+
<div title="${escapeHtml(title)}" style="
|
|
49827
50164
|
box-sizing: border-box;
|
|
49828
50165
|
width: 100%;
|
|
49829
50166
|
height: 100%;
|
|
@@ -49846,7 +50183,7 @@ function build_node_innerHTML(color, theme, icon, id, topic_name, structural) {
|
|
|
49846
50183
|
max-width: 100%; overflow: hidden; text-overflow: ellipsis;
|
|
49847
50184
|
display: -webkit-box; -webkit-line-clamp: 2;
|
|
49848
50185
|
-webkit-box-orient: vertical; word-break: break-word;
|
|
49849
|
-
">${escapeHtml(
|
|
50186
|
+
">${escapeHtml(label)}</div>${sub_html}
|
|
49850
50187
|
</div>
|
|
49851
50188
|
`;
|
|
49852
50189
|
}
|
|
@@ -50067,7 +50404,7 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope) {
|
|
|
50067
50404
|
};
|
|
50068
50405
|
if (nd.data.desc.node_treedb_type === "hierarchical") {
|
|
50069
50406
|
let record = nd.data.record || {};
|
|
50070
|
-
updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon,
|
|
50407
|
+
updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, false, record.id);
|
|
50071
50408
|
}
|
|
50072
50409
|
updates.push({
|
|
50073
50410
|
id: nodes[i].id,
|