@yuneta/gobj-ui 7.25.17 → 7.25.19
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 +69 -3
- package/dist/gobj-ui.cjs.js +126 -30
- package/dist/gobj-ui.es.js +126 -30
- package/package.json +2 -2
- package/src/c_g6_nodes_tree.js +23 -0
- package/src/c_yui_node.js +71 -0
- package/src/c_yui_schema_editor.js +20 -10
- package/src/c_yui_treedb_graph.js +49 -6
- package/src/c_yui_treedb_topic_with_form.js +23 -0
- package/src/c_yui_treedb_topics.js +43 -9
- package/src/c_yui_uplot.js +10 -5
- package/src/form_json_expand.wiring.test.js +121 -0
- package/src/g6_graphs_write_owed.wiring.test.js +37 -0
- package/src/node_nav_events.wiring.test.js +150 -0
- package/src/schema_editor_reload.wiring.test.js +37 -0
- package/src/treedb_graph_writes.wiring.test.js +71 -3
- package/src/treedb_topics_transport.wiring.test.js +111 -7
- package/src/uplot_add_serie.test.js +92 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -10896,7 +10896,7 @@ function register_c_yui_map() {
|
|
|
10896
10896
|
*
|
|
10897
10897
|
* Graphics, Charts with uPlot
|
|
10898
10898
|
*
|
|
10899
|
-
* Copyright (c) 2025, ArtGins.
|
|
10899
|
+
* Copyright (c) 2025-2026, ArtGins.
|
|
10900
10900
|
* All Rights Reserved.
|
|
10901
10901
|
***********************************************************************/
|
|
10902
10902
|
/***************************************************************
|
|
@@ -11146,8 +11146,8 @@ function ac_add_serie(gobj, event, kw, src) {
|
|
|
11146
11146
|
let colors = gobj_read_attr(gobj, "colors");
|
|
11147
11147
|
if (!Array.isArray(colors) || !colors.length) colors = CHART_PALETTE;
|
|
11148
11148
|
let color = colors[Math.max(0, idx - 1) % colors.length];
|
|
11149
|
-
|
|
11150
|
-
|
|
11149
|
+
if (kw.stroke === void 0) kw.stroke = color.stroke;
|
|
11150
|
+
if (kw.fill === void 0) kw.fill = color.fill;
|
|
11151
11151
|
uplot.addSeries(kw);
|
|
11152
11152
|
return 0;
|
|
11153
11153
|
}
|
|
@@ -16015,7 +16015,7 @@ function ac_hide_diff(gobj, event, kw, src) {
|
|
|
16015
16015
|
* document has no backend to ask for it: the SOURCE truncated
|
|
16016
16016
|
* it, and that is the answer, to the viewer that asked.
|
|
16017
16017
|
***************************************************************/
|
|
16018
|
-
function ac_expand_path(gobj, event, kw, src) {
|
|
16018
|
+
function ac_expand_path$1(gobj, event, kw, src) {
|
|
16019
16019
|
gobj_send_event(src, "EV_SUBTREE_ERROR", {
|
|
16020
16020
|
path: kw && kw.path || "",
|
|
16021
16021
|
error: t("collapsed in the source")
|
|
@@ -16076,7 +16076,7 @@ function create_gclass$12(gclass_name) {
|
|
|
16076
16076
|
],
|
|
16077
16077
|
[
|
|
16078
16078
|
"EV_EXPAND_PATH",
|
|
16079
|
-
ac_expand_path,
|
|
16079
|
+
ac_expand_path$1,
|
|
16080
16080
|
null
|
|
16081
16081
|
]
|
|
16082
16082
|
]],
|
|
@@ -16113,7 +16113,7 @@ function create_gclass$12(gclass_name) {
|
|
|
16113
16113
|
],
|
|
16114
16114
|
[
|
|
16115
16115
|
"EV_EXPAND_PATH",
|
|
16116
|
-
ac_expand_path,
|
|
16116
|
+
ac_expand_path$1,
|
|
16117
16117
|
null
|
|
16118
16118
|
]
|
|
16119
16119
|
]],
|
|
@@ -24919,9 +24919,20 @@ function treedb_nodes$1(gobj, treedb_name, topic_name, options, page, purpose) {
|
|
|
24919
24919
|
return 0;
|
|
24920
24920
|
}
|
|
24921
24921
|
/************************************************************
|
|
24922
|
+
* The record a write answered: the node the store wrote (an
|
|
24923
|
+
* update or a create), deleted, or the child of a link. The
|
|
24924
|
+
* answer's frame carries back only `__md_command__`, never the
|
|
24925
|
+
* request's own record.
|
|
24926
|
+
************************************************************/
|
|
24927
|
+
function answered_record$1(data) {
|
|
24928
|
+
if (data && typeof data === "object" && !Array.isArray(data)) return data;
|
|
24929
|
+
if (Array.isArray(data) && data[0] && typeof data[0] === "object") return data[0];
|
|
24930
|
+
return {};
|
|
24931
|
+
}
|
|
24932
|
+
/************************************************************
|
|
24922
24933
|
* Command to remote service
|
|
24923
24934
|
************************************************************/
|
|
24924
|
-
function treedb_update_node$1(gobj, treedb_name, topic_name, record, options, form_write) {
|
|
24935
|
+
function treedb_update_node$1(gobj, treedb_name, topic_name, record, options, form_write, created) {
|
|
24925
24936
|
let command = "update-node";
|
|
24926
24937
|
let gobj_remote_yuno = gobj_read_pointer_attr(gobj, "gobj_remote_yuno");
|
|
24927
24938
|
let kw = {
|
|
@@ -24933,6 +24944,7 @@ function treedb_update_node$1(gobj, treedb_name, topic_name, record, options, fo
|
|
|
24933
24944
|
};
|
|
24934
24945
|
kw.__md_command__ = { topic_name };
|
|
24935
24946
|
if (form_write) kw.__md_command__.form_write = form_write;
|
|
24947
|
+
if (created) kw.__md_command__.created = true;
|
|
24936
24948
|
let ret = gobj_command(gobj_remote_yuno, command, kw, gobj);
|
|
24937
24949
|
if (ret) {
|
|
24938
24950
|
log_error(ret);
|
|
@@ -24956,7 +24968,11 @@ function treedb_delete_node$1(gobj, treedb_name, topic_name, record, options) {
|
|
|
24956
24968
|
};
|
|
24957
24969
|
kw.__md_command__ = { topic_name };
|
|
24958
24970
|
let ret = gobj_command(gobj_remote_yuno, command, kw, gobj);
|
|
24959
|
-
if (ret)
|
|
24971
|
+
if (ret) {
|
|
24972
|
+
log_error(ret);
|
|
24973
|
+
return -1;
|
|
24974
|
+
}
|
|
24975
|
+
return 0;
|
|
24960
24976
|
}
|
|
24961
24977
|
/************************************************************
|
|
24962
24978
|
* True on a phone-width viewport (Bulma's mobile breakpoint).
|
|
@@ -25239,17 +25255,18 @@ function ac_mt_command_answer$2(gobj, event, kw, src) {
|
|
|
25239
25255
|
break;
|
|
25240
25256
|
case "create-node":
|
|
25241
25257
|
case "update-node":
|
|
25258
|
+
case "delete-node":
|
|
25242
25259
|
gobj_publish_event(gobj, "EV_RECORD_WRITTEN", {
|
|
25243
|
-
treedb_name:
|
|
25260
|
+
treedb_name: gobj_read_str_attr(gobj, "treedb_name"),
|
|
25244
25261
|
topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
|
|
25245
|
-
record:
|
|
25246
|
-
created: command === "create-node",
|
|
25262
|
+
record: answered_record$1(data),
|
|
25263
|
+
created: command === "create-node" || kw_command.created === true,
|
|
25247
25264
|
command
|
|
25248
25265
|
});
|
|
25266
|
+
if (command === "delete-node") break;
|
|
25249
25267
|
settle_form_write(gobj.priv.form_writes, kw_get_int(gobj, kw_command, "form_write", 0, 0), kw_get_str(gobj, kw_command, "topic_name", "", 0));
|
|
25250
25268
|
answer_form_write(gobj, get_gobj_formtable(gobj, kw_get_str(gobj, kw_command, "topic_name", "", 0)), kw_get_int(gobj, kw_command, "form_write", 0, 0), true);
|
|
25251
25269
|
break;
|
|
25252
|
-
case "delete-node": break;
|
|
25253
25270
|
default: log_error(`${gobj_short_name(gobj)} Command unknown: ${command}`);
|
|
25254
25271
|
}
|
|
25255
25272
|
return 0;
|
|
@@ -25517,7 +25534,7 @@ function ac_create_record(gobj, event, kw, src) {
|
|
|
25517
25534
|
create: true,
|
|
25518
25535
|
create_only: true,
|
|
25519
25536
|
autolink: true
|
|
25520
|
-
}, form_write) < 0) {
|
|
25537
|
+
}, form_write, true) < 0) {
|
|
25521
25538
|
answer_form_write(gobj, src, form_write, false);
|
|
25522
25539
|
return -1;
|
|
25523
25540
|
}
|
|
@@ -29435,6 +29452,24 @@ function refuse_if_readonly$2(gobj, event) {
|
|
|
29435
29452
|
* From external, at the beginning, load all topic data
|
|
29436
29453
|
************************************************************/
|
|
29437
29454
|
/***************************************************************
|
|
29455
|
+
* One of MY json viewers (the schema, a cell, the table's records)
|
|
29456
|
+
* met a `__collapsed__` sentinel and the reader opened it. The
|
|
29457
|
+
* viewer never fetches: it asks its host, and waits on "loading"
|
|
29458
|
+
* until it is answered. This view holds records, not a store it can
|
|
29459
|
+
* read a subtree of -- the lazy drill is `print-tranger`, which the
|
|
29460
|
+
* TOPICS view runs for its own viewer, over a whole tranger -- so the
|
|
29461
|
+
* answer is that it cannot, and the viewer shows that on the stub
|
|
29462
|
+
* instead of loading for ever.
|
|
29463
|
+
***************************************************************/
|
|
29464
|
+
function ac_expand_path(gobj, event, kw, src) {
|
|
29465
|
+
let path = kw && kw.path || "";
|
|
29466
|
+
gobj_send_event(src, "EV_SUBTREE_ERROR", {
|
|
29467
|
+
path,
|
|
29468
|
+
error: t("this part cannot be loaded here")
|
|
29469
|
+
}, gobj);
|
|
29470
|
+
return 0;
|
|
29471
|
+
}
|
|
29472
|
+
/***************************************************************
|
|
29438
29473
|
* The language changed (the shell publishes it after the app switched).
|
|
29439
29474
|
*
|
|
29440
29475
|
* The column headers carry their key (col_label's title formatter emits a
|
|
@@ -30728,6 +30763,11 @@ function create_gclass$5(gclass_name) {
|
|
|
30728
30763
|
ac_show_schema,
|
|
30729
30764
|
null
|
|
30730
30765
|
],
|
|
30766
|
+
[
|
|
30767
|
+
"EV_EXPAND_PATH",
|
|
30768
|
+
ac_expand_path,
|
|
30769
|
+
null
|
|
30770
|
+
],
|
|
30731
30771
|
[
|
|
30732
30772
|
"EV_CELL_EDITED",
|
|
30733
30773
|
ac_cell_edited,
|
|
@@ -30843,6 +30883,7 @@ function create_gclass$5(gclass_name) {
|
|
|
30843
30883
|
["EV_CHANGE_LOCALE", 0],
|
|
30844
30884
|
["EV_REFRESH", 0],
|
|
30845
30885
|
["EV_SHOW_SCHEMA", 0],
|
|
30886
|
+
["EV_EXPAND_PATH", 0],
|
|
30846
30887
|
["EV_CELL_EDITED", 0],
|
|
30847
30888
|
["EV_REPULL_PAGE", 0],
|
|
30848
30889
|
["EV_PAGE_LOADED", 0],
|
|
@@ -65860,6 +65901,22 @@ function ac_graphs_write_refused(gobj, event, kw, src) {
|
|
|
65860
65901
|
return 0;
|
|
65861
65902
|
}
|
|
65862
65903
|
/************************************************************
|
|
65904
|
+
* An echo of a `__graphs__` record is what the backend holds for
|
|
65905
|
+
* its topic now, and the view has just taken it as shown and as
|
|
65906
|
+
* saved: a write of that topic owed from an earlier refusal is
|
|
65907
|
+
* owed no more. Left owed, the Save stayed lit with nothing to
|
|
65908
|
+
* write -- the plan compares the two, and they are equal -- until
|
|
65909
|
+
* a reload: a refused Save #1 answered after Save #2 landed, or
|
|
65910
|
+
* another browser saving the topic, did exactly that.
|
|
65911
|
+
************************************************************/
|
|
65912
|
+
function settle_owed_graphs_write(gobj, rec) {
|
|
65913
|
+
let priv = gobj.priv;
|
|
65914
|
+
let topic_name = rec && rec.topic;
|
|
65915
|
+
if (!topic_name || !priv._graphs_writes_owed[topic_name]) return;
|
|
65916
|
+
delete priv._graphs_writes_owed[topic_name];
|
|
65917
|
+
update_history_buttons(gobj);
|
|
65918
|
+
}
|
|
65919
|
+
/************************************************************
|
|
65863
65920
|
* Node created, from subscription
|
|
65864
65921
|
************************************************************/
|
|
65865
65922
|
function ac_node_created(gobj, event, kw, src) {
|
|
@@ -65871,6 +65928,7 @@ function ac_node_created(gobj, event, kw, src) {
|
|
|
65871
65928
|
if (topic_name === "__graphs__") {
|
|
65872
65929
|
priv.__graphs__.push(node);
|
|
65873
65930
|
build_graph_properties(gobj);
|
|
65931
|
+
settle_owed_graphs_write(gobj, node);
|
|
65874
65932
|
return 0;
|
|
65875
65933
|
}
|
|
65876
65934
|
if (!priv.descs[topic_name]) {
|
|
@@ -65906,6 +65964,7 @@ function ac_node_updated(gobj, event, kw, src) {
|
|
|
65906
65964
|
}
|
|
65907
65965
|
if (!found) priv.__graphs__.push(node);
|
|
65908
65966
|
apply_graphs_echo(priv._graph_properties, priv._saved_graph_properties, priv.__graphs__, node);
|
|
65967
|
+
settle_owed_graphs_write(gobj, node);
|
|
65909
65968
|
return 0;
|
|
65910
65969
|
}
|
|
65911
65970
|
let desc = priv.descs[topic_name];
|
|
@@ -68403,6 +68462,29 @@ function treedb_delete_node(gobj, treedb_name, topic_name, record, options) {
|
|
|
68403
68462
|
if (ret) log_error(ret);
|
|
68404
68463
|
}
|
|
68405
68464
|
/************************************************************
|
|
68465
|
+
* What a link or an unlink asks back with its answer: the
|
|
68466
|
+
* topic of the CHILD (the node a link saves) and both refs.
|
|
68467
|
+
* `child_ref` is "topic^id", `parent_ref` "topic^id^hook".
|
|
68468
|
+
************************************************************/
|
|
68469
|
+
function link_echo(parent_ref, child_ref) {
|
|
68470
|
+
return {
|
|
68471
|
+
topic_name: typeof child_ref === "string" ? child_ref.split("^")[0] : "",
|
|
68472
|
+
parent_ref,
|
|
68473
|
+
child_ref
|
|
68474
|
+
};
|
|
68475
|
+
}
|
|
68476
|
+
/************************************************************
|
|
68477
|
+
* The record a write answered: the node the store wrote (an
|
|
68478
|
+
* update or a create), deleted, or the child of a link. The
|
|
68479
|
+
* answer's frame carries back only `__md_command__`, never the
|
|
68480
|
+
* request's own record.
|
|
68481
|
+
************************************************************/
|
|
68482
|
+
function answered_record(data) {
|
|
68483
|
+
if (data && typeof data === "object" && !Array.isArray(data)) return data;
|
|
68484
|
+
if (Array.isArray(data) && data[0] && typeof data[0] === "object") return data[0];
|
|
68485
|
+
return {};
|
|
68486
|
+
}
|
|
68487
|
+
/************************************************************
|
|
68406
68488
|
* Command to remote service
|
|
68407
68489
|
************************************************************/
|
|
68408
68490
|
function treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, options) {
|
|
@@ -68419,6 +68501,7 @@ function treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, options) {
|
|
|
68419
68501
|
child_ref,
|
|
68420
68502
|
options: options || {}
|
|
68421
68503
|
};
|
|
68504
|
+
kw.__md_command__ = link_echo(parent_ref, child_ref);
|
|
68422
68505
|
let ret = gobj_command(priv.gobj_remote_yuno, command, kw, gobj);
|
|
68423
68506
|
if (ret) log_error(ret);
|
|
68424
68507
|
}
|
|
@@ -68439,6 +68522,7 @@ function treedb_unlink_nodes(gobj, treedb_name, parent_ref, child_ref, options)
|
|
|
68439
68522
|
child_ref,
|
|
68440
68523
|
options: options || {}
|
|
68441
68524
|
};
|
|
68525
|
+
kw.__md_command__ = link_echo(parent_ref, child_ref);
|
|
68442
68526
|
let ret = gobj_command(priv.gobj_remote_yuno, command, kw, gobj);
|
|
68443
68527
|
if (ret) log_error(ret);
|
|
68444
68528
|
}
|
|
@@ -68653,13 +68737,20 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
|
|
|
68653
68737
|
case "link-nodes":
|
|
68654
68738
|
case "unlink-nodes":
|
|
68655
68739
|
if (result < 0 && command === "update-node") graphs_write_refused(gobj, kw_get_str(gobj, kw_command, "topic_name", "", 0), kw_get_str(gobj, kw_command, "graph_topic", "", 0));
|
|
68656
|
-
if (result >= 0 && kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__")
|
|
68657
|
-
|
|
68658
|
-
|
|
68659
|
-
|
|
68660
|
-
|
|
68661
|
-
|
|
68662
|
-
|
|
68740
|
+
if (result >= 0 && kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") {
|
|
68741
|
+
let written = {
|
|
68742
|
+
treedb_name: priv.treedb_name,
|
|
68743
|
+
topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
|
|
68744
|
+
record: answered_record(data),
|
|
68745
|
+
created: command === "create-node",
|
|
68746
|
+
command
|
|
68747
|
+
};
|
|
68748
|
+
if (command === "link-nodes" || command === "unlink-nodes") {
|
|
68749
|
+
written.parent_ref = kw_get_str(gobj, kw_command, "parent_ref", "", 0);
|
|
68750
|
+
written.child_ref = kw_get_str(gobj, kw_command, "child_ref", "", 0);
|
|
68751
|
+
}
|
|
68752
|
+
gobj_publish_event(gobj, "EV_RECORD_WRITTEN", written);
|
|
68753
|
+
}
|
|
68663
68754
|
break;
|
|
68664
68755
|
default: log_error(`${gobj_short_name(gobj)} Command unknown: ${command}`);
|
|
68665
68756
|
}
|
|
@@ -72908,8 +72999,12 @@ function current_topic(gobj) {
|
|
|
72908
72999
|
* One line for what the whole view has to say: loading, empty,
|
|
72909
73000
|
* or the reason nothing loaded. Carries its i18n key, so it
|
|
72910
73001
|
* follows a language change like any other text.
|
|
73002
|
+
*
|
|
73003
|
+
* `detail` is a NAME (a treedb, a topic) shown as it is, unless
|
|
73004
|
+
* `detail_is_key` says it is a key: a name is not text to
|
|
73005
|
+
* translate, and a topic called `nodes` is not "Nodos".
|
|
72911
73006
|
***************************************************************/
|
|
72912
|
-
function show_notice(gobj, key, detail) {
|
|
73007
|
+
function show_notice(gobj, key, detail, detail_is_key) {
|
|
72913
73008
|
let $notice = $of(gobj, ".SCHEMA_NOTICE");
|
|
72914
73009
|
if (!$notice) return;
|
|
72915
73010
|
clear($notice);
|
|
@@ -72926,14 +73021,15 @@ function show_notice(gobj, key, detail) {
|
|
|
72926
73021
|
},
|
|
72927
73022
|
t(key)
|
|
72928
73023
|
]));
|
|
72929
|
-
if (detail && detail !== key)
|
|
72930
|
-
"
|
|
72931
|
-
{
|
|
72932
|
-
|
|
72933
|
-
|
|
72934
|
-
|
|
72935
|
-
|
|
72936
|
-
|
|
73024
|
+
if (detail && detail !== key) {
|
|
73025
|
+
let attrs = { class: "SCHEMA_NOTICE_DETAIL yui-text-quiet ml-2" };
|
|
73026
|
+
if (detail_is_key) attrs.i18n = `${detail}`;
|
|
73027
|
+
$notice.appendChild(createElement2([
|
|
73028
|
+
"span",
|
|
73029
|
+
attrs,
|
|
73030
|
+
detail_is_key ? t(`${detail}`) : `${detail}`
|
|
73031
|
+
]));
|
|
73032
|
+
}
|
|
72937
73033
|
}
|
|
72938
73034
|
/***************************************************************
|
|
72939
73035
|
* A button of the toolbar. Every one carries an icon and a
|
|
@@ -73120,7 +73216,7 @@ function render(gobj) {
|
|
|
73120
73216
|
return;
|
|
73121
73217
|
}
|
|
73122
73218
|
if (state === "ST_IDLE") {
|
|
73123
|
-
show_notice(gobj, priv.load_error ? "cannot load the schemas" : "not connected", priv.load_error);
|
|
73219
|
+
show_notice(gobj, priv.load_error ? "cannot load the schemas" : "not connected", priv.load_error, true);
|
|
73124
73220
|
destroy_diagram(gobj);
|
|
73125
73221
|
clear($body);
|
|
73126
73222
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuneta/gobj-ui",
|
|
3
|
-
"version": "7.25.
|
|
3
|
+
"version": "7.25.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/gobj-ui.cjs.js",
|
|
6
6
|
"module": "dist/gobj-ui.es.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@rollup/plugin-terser": "^1.0.0",
|
|
32
32
|
"@vitest/coverage-v8": "^4.1.10",
|
|
33
|
-
"@yuneta/gobj-js": "^7.25.
|
|
33
|
+
"@yuneta/gobj-js": "^7.25.5",
|
|
34
34
|
"vite": "^8.2.1",
|
|
35
35
|
"vitest": "^4.1.10"
|
|
36
36
|
},
|
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -10565,6 +10565,27 @@ function ac_graphs_write_refused(gobj, event, kw, src)
|
|
|
10565
10565
|
return 0;
|
|
10566
10566
|
}
|
|
10567
10567
|
|
|
10568
|
+
/************************************************************
|
|
10569
|
+
* An echo of a `__graphs__` record is what the backend holds for
|
|
10570
|
+
* its topic now, and the view has just taken it as shown and as
|
|
10571
|
+
* saved: a write of that topic owed from an earlier refusal is
|
|
10572
|
+
* owed no more. Left owed, the Save stayed lit with nothing to
|
|
10573
|
+
* write -- the plan compares the two, and they are equal -- until
|
|
10574
|
+
* a reload: a refused Save #1 answered after Save #2 landed, or
|
|
10575
|
+
* another browser saving the topic, did exactly that.
|
|
10576
|
+
************************************************************/
|
|
10577
|
+
function settle_owed_graphs_write(gobj, rec)
|
|
10578
|
+
{
|
|
10579
|
+
let priv = gobj.priv;
|
|
10580
|
+
let topic_name = rec && rec.topic;
|
|
10581
|
+
|
|
10582
|
+
if(!topic_name || !priv._graphs_writes_owed[topic_name]) {
|
|
10583
|
+
return;
|
|
10584
|
+
}
|
|
10585
|
+
delete priv._graphs_writes_owed[topic_name];
|
|
10586
|
+
update_history_buttons(gobj);
|
|
10587
|
+
}
|
|
10588
|
+
|
|
10568
10589
|
/************************************************************
|
|
10569
10590
|
* Node created, from subscription
|
|
10570
10591
|
************************************************************/
|
|
@@ -10583,6 +10604,7 @@ function ac_node_created(gobj, event, kw, src)
|
|
|
10583
10604
|
if(topic_name === '__graphs__') {
|
|
10584
10605
|
priv.__graphs__.push(node);
|
|
10585
10606
|
build_graph_properties(gobj);
|
|
10607
|
+
settle_owed_graphs_write(gobj, node);
|
|
10586
10608
|
return 0;
|
|
10587
10609
|
}
|
|
10588
10610
|
|
|
@@ -10649,6 +10671,7 @@ function ac_node_updated(gobj, event, kw, src)
|
|
|
10649
10671
|
apply_graphs_echo(
|
|
10650
10672
|
priv._graph_properties, priv._saved_graph_properties, priv.__graphs__, node
|
|
10651
10673
|
);
|
|
10674
|
+
settle_owed_graphs_write(gobj, node);
|
|
10652
10675
|
return 0;
|
|
10653
10676
|
}
|
|
10654
10677
|
|
package/src/c_yui_node.js
CHANGED
|
@@ -1278,6 +1278,65 @@ function ac_nav_clicked(gobj, event, kw, src)
|
|
|
1278
1278
|
return 0;
|
|
1279
1279
|
}
|
|
1280
1280
|
|
|
1281
|
+
/************************************************************
|
|
1282
|
+
* The ✕ of a closable item, from a projection nav. A node's own
|
|
1283
|
+
* items never carry `closable` (child_nav_items() builds them), so
|
|
1284
|
+
* this is an item the node does not own the fate of: whether it
|
|
1285
|
+
* goes away is the app's call, as for the shell's own closable
|
|
1286
|
+
* tabs. Handed to the shell, which re-publishes it to the app
|
|
1287
|
+
* (ac_nav_item_close there).
|
|
1288
|
+
************************************************************/
|
|
1289
|
+
function ac_nav_item_close(gobj, event, kw, src)
|
|
1290
|
+
{
|
|
1291
|
+
let shell = yui_shell_of(gobj);
|
|
1292
|
+
if(!shell) {
|
|
1293
|
+
log_error(`${GCLASS_NAME} '${node_path_str(gobj)}': no shell to hand ` +
|
|
1294
|
+
`the close of '${(kw && kw.item_id) || ""}' to`);
|
|
1295
|
+
return -1;
|
|
1296
|
+
}
|
|
1297
|
+
gobj_send_event(shell, "EV_NAV_ITEM_CLOSE", {
|
|
1298
|
+
item_id: (kw && kw.item_id) || "",
|
|
1299
|
+
route: (kw && kw.route) || "",
|
|
1300
|
+
menu_id: (kw && kw.menu_id) || "",
|
|
1301
|
+
zone: (kw && kw.zone) || ""
|
|
1302
|
+
}, gobj);
|
|
1303
|
+
return 0;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
/************************************************************
|
|
1307
|
+
* The backdrop of a drawer projection was clicked. The drawer is
|
|
1308
|
+
* one of MY navs (a projection with `layout: "drawer"`), not one of
|
|
1309
|
+
* the shell's, so the shell's close_drawer() cannot find it: the
|
|
1310
|
+
* node closes it. A drawer opened through the shell carries the
|
|
1311
|
+
* shell's own close handler (escape stack, focus trap) on its
|
|
1312
|
+
* element, and that is what runs then; otherwise it is only hidden.
|
|
1313
|
+
************************************************************/
|
|
1314
|
+
function ac_drawer_close_requested(gobj, event, kw, src)
|
|
1315
|
+
{
|
|
1316
|
+
let priv = gobj.priv;
|
|
1317
|
+
let menu_id = (kw && kw.menu_id) || "";
|
|
1318
|
+
let navs = priv.navs.concat(Object.values(priv.zone_navs));
|
|
1319
|
+
|
|
1320
|
+
for(let nav of navs) {
|
|
1321
|
+
if(gobj_read_attr(nav, "layout") !== "drawer") {
|
|
1322
|
+
continue;
|
|
1323
|
+
}
|
|
1324
|
+
if(menu_id && gobj_read_attr(nav, "menu_id") !== menu_id) {
|
|
1325
|
+
continue;
|
|
1326
|
+
}
|
|
1327
|
+
let $c = gobj_read_attr(nav, "$container");
|
|
1328
|
+
if(!$c || !$c.classList.contains("is-active")) {
|
|
1329
|
+
continue;
|
|
1330
|
+
}
|
|
1331
|
+
if(typeof $c.__yui_close_handler__ === "function") {
|
|
1332
|
+
$c.__yui_close_handler__();
|
|
1333
|
+
} else {
|
|
1334
|
+
$c.classList.remove("is-active");
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
return 0;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1281
1340
|
/************************************************************
|
|
1282
1341
|
* Runtime API: add a child. Same path the declared tree takes.
|
|
1283
1342
|
************************************************************/
|
|
@@ -1666,6 +1725,12 @@ function create_gclass(gclass_name)
|
|
|
1666
1725
|
["ST_OFF", [
|
|
1667
1726
|
["EV_ROUTE_CHANGED", ac_route_changed, null],
|
|
1668
1727
|
["EV_ACTIVATE", ac_activate, null],
|
|
1728
|
+
/* A ZONE projection outlives the path (it is the app's
|
|
1729
|
+
* standing chrome, stopped only in mt_stop), so its clicks
|
|
1730
|
+
* reach a root that is off the path too. */
|
|
1731
|
+
["EV_NAV_CLICKED", ac_nav_clicked, null],
|
|
1732
|
+
["EV_NAV_ITEM_CLOSE", ac_nav_item_close, null],
|
|
1733
|
+
["EV_DRAWER_CLOSE_REQUESTED", ac_drawer_close_requested, null],
|
|
1669
1734
|
["EV_ADD_NODE", ac_add_node, null],
|
|
1670
1735
|
["EV_REMOVE_NODE", ac_remove_node, null],
|
|
1671
1736
|
["EV_SET_PROJECTION", ac_set_projection, null],
|
|
@@ -1679,6 +1744,8 @@ function create_gclass(gclass_name)
|
|
|
1679
1744
|
["EV_ACTIVATE", ac_activate, null],
|
|
1680
1745
|
["EV_DEACTIVATE", ac_deactivate, null],
|
|
1681
1746
|
["EV_NAV_CLICKED", ac_nav_clicked, null],
|
|
1747
|
+
["EV_NAV_ITEM_CLOSE", ac_nav_item_close, null],
|
|
1748
|
+
["EV_DRAWER_CLOSE_REQUESTED", ac_drawer_close_requested, null],
|
|
1682
1749
|
["EV_ADD_NODE", ac_add_node, null],
|
|
1683
1750
|
["EV_REMOVE_NODE", ac_remove_node, null],
|
|
1684
1751
|
["EV_SET_PROJECTION", ac_set_projection, null],
|
|
@@ -1692,6 +1759,8 @@ function create_gclass(gclass_name)
|
|
|
1692
1759
|
["EV_ACTIVATE", ac_activate, null],
|
|
1693
1760
|
["EV_DEACTIVATE", ac_deactivate, null],
|
|
1694
1761
|
["EV_NAV_CLICKED", ac_nav_clicked, null],
|
|
1762
|
+
["EV_NAV_ITEM_CLOSE", ac_nav_item_close, null],
|
|
1763
|
+
["EV_DRAWER_CLOSE_REQUESTED", ac_drawer_close_requested, null],
|
|
1695
1764
|
["EV_ADD_NODE", ac_add_node, null],
|
|
1696
1765
|
["EV_REMOVE_NODE", ac_remove_node, null],
|
|
1697
1766
|
["EV_SET_PROJECTION", ac_set_projection, null],
|
|
@@ -1710,6 +1779,8 @@ function create_gclass(gclass_name)
|
|
|
1710
1779
|
["EV_ACTIVATE", 0],
|
|
1711
1780
|
["EV_DEACTIVATE", 0],
|
|
1712
1781
|
["EV_NAV_CLICKED", 0],
|
|
1782
|
+
["EV_NAV_ITEM_CLOSE", 0],
|
|
1783
|
+
["EV_DRAWER_CLOSE_REQUESTED", 0],
|
|
1713
1784
|
["EV_ADD_NODE", 0],
|
|
1714
1785
|
["EV_REMOVE_NODE", 0],
|
|
1715
1786
|
["EV_SET_PROJECTION", 0],
|
|
@@ -755,8 +755,11 @@ function remote_command(gobj, command, kw, tag)
|
|
|
755
755
|
* echoes `__md_command__` AS that frame (c_agent_treedb_link.js).
|
|
756
756
|
* Same names in both places is what makes the answer readable
|
|
757
757
|
* whichever one is under this view — and `record_id` is here and
|
|
758
|
-
* NOT at the top level because a
|
|
759
|
-
*
|
|
758
|
+
* NOT at the top level because a parameter the treedb does not know
|
|
759
|
+
* has no business travelling. It is echoed at all because an answer
|
|
760
|
+
* does not always name its record: a delete answers the node deleted,
|
|
761
|
+
* but a REFUSED write answers none, and the view still has to know
|
|
762
|
+
* which record it was. */
|
|
760
763
|
full_kw.__md_command__ = Object.assign({
|
|
761
764
|
purpose: PURPOSE,
|
|
762
765
|
topic_name: (kw && kw.topic_name) || "",
|
|
@@ -981,8 +984,12 @@ function current_topic(gobj)
|
|
|
981
984
|
* One line for what the whole view has to say: loading, empty,
|
|
982
985
|
* or the reason nothing loaded. Carries its i18n key, so it
|
|
983
986
|
* follows a language change like any other text.
|
|
987
|
+
*
|
|
988
|
+
* `detail` is a NAME (a treedb, a topic) shown as it is, unless
|
|
989
|
+
* `detail_is_key` says it is a key: a name is not text to
|
|
990
|
+
* translate, and a topic called `nodes` is not "Nodos".
|
|
984
991
|
***************************************************************/
|
|
985
|
-
function show_notice(gobj, key, detail)
|
|
992
|
+
function show_notice(gobj, key, detail, detail_is_key)
|
|
986
993
|
{
|
|
987
994
|
let $notice = $of(gobj, ".SCHEMA_NOTICE");
|
|
988
995
|
|
|
@@ -998,14 +1005,17 @@ function show_notice(gobj, key, detail)
|
|
|
998
1005
|
$notice.appendChild(createElement2(
|
|
999
1006
|
["span", {class: "SCHEMA_NOTICE_TEXT", i18n: key}, t(key)]
|
|
1000
1007
|
));
|
|
1001
|
-
/*
|
|
1002
|
-
* translate to themselves when no locale has them)
|
|
1003
|
-
*
|
|
1004
|
-
*
|
|
1008
|
+
/* A detail that is a KEY (the load error: ours, or the backend's
|
|
1009
|
+
* words, which translate to themselves when no locale has them)
|
|
1010
|
+
* changes language with the rest. One that repeats the title
|
|
1011
|
+
* says nothing. */
|
|
1005
1012
|
if(detail && detail !== key) {
|
|
1013
|
+
let attrs = {class: "SCHEMA_NOTICE_DETAIL yui-text-quiet ml-2"};
|
|
1014
|
+
if(detail_is_key) {
|
|
1015
|
+
attrs.i18n = `${detail}`;
|
|
1016
|
+
}
|
|
1006
1017
|
$notice.appendChild(createElement2(
|
|
1007
|
-
["span",
|
|
1008
|
-
t(`${detail}`)]
|
|
1018
|
+
["span", attrs, detail_is_key ? t(`${detail}`) : `${detail}`]
|
|
1009
1019
|
));
|
|
1010
1020
|
}
|
|
1011
1021
|
}
|
|
@@ -1188,7 +1198,7 @@ function render(gobj)
|
|
|
1188
1198
|
}
|
|
1189
1199
|
if(state === "ST_IDLE") {
|
|
1190
1200
|
show_notice(gobj, priv.load_error ? "cannot load the schemas" : "not connected",
|
|
1191
|
-
priv.load_error);
|
|
1201
|
+
priv.load_error, true);
|
|
1192
1202
|
destroy_diagram(gobj);
|
|
1193
1203
|
clear($body);
|
|
1194
1204
|
return;
|
|
@@ -1575,6 +1575,38 @@ function treedb_delete_node(gobj, treedb_name, topic_name, record, options)
|
|
|
1575
1575
|
}
|
|
1576
1576
|
}
|
|
1577
1577
|
|
|
1578
|
+
/************************************************************
|
|
1579
|
+
* What a link or an unlink asks back with its answer: the
|
|
1580
|
+
* topic of the CHILD (the node a link saves) and both refs.
|
|
1581
|
+
* `child_ref` is "topic^id", `parent_ref` "topic^id^hook".
|
|
1582
|
+
************************************************************/
|
|
1583
|
+
function link_echo(parent_ref, child_ref)
|
|
1584
|
+
{
|
|
1585
|
+
let child_topic = (typeof child_ref === "string") ? child_ref.split("^")[0] : "";
|
|
1586
|
+
return {
|
|
1587
|
+
topic_name: child_topic,
|
|
1588
|
+
parent_ref: parent_ref,
|
|
1589
|
+
child_ref: child_ref
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
/************************************************************
|
|
1594
|
+
* The record a write answered: the node the store wrote (an
|
|
1595
|
+
* update or a create), deleted, or the child of a link. The
|
|
1596
|
+
* answer's frame carries back only `__md_command__`, never the
|
|
1597
|
+
* request's own record.
|
|
1598
|
+
************************************************************/
|
|
1599
|
+
function answered_record(data)
|
|
1600
|
+
{
|
|
1601
|
+
if(data && typeof data === "object" && !Array.isArray(data)) {
|
|
1602
|
+
return data;
|
|
1603
|
+
}
|
|
1604
|
+
if(Array.isArray(data) && data[0] && typeof data[0] === "object") {
|
|
1605
|
+
return data[0];
|
|
1606
|
+
}
|
|
1607
|
+
return {};
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1578
1610
|
/************************************************************
|
|
1579
1611
|
* Command to remote service
|
|
1580
1612
|
************************************************************/
|
|
@@ -1596,6 +1628,7 @@ function treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, options)
|
|
|
1596
1628
|
child_ref: child_ref,
|
|
1597
1629
|
options: options || {}
|
|
1598
1630
|
};
|
|
1631
|
+
kw.__md_command__ = link_echo(parent_ref, child_ref);
|
|
1599
1632
|
|
|
1600
1633
|
let ret = gobj_command(priv.gobj_remote_yuno,
|
|
1601
1634
|
command,
|
|
@@ -1628,6 +1661,7 @@ function treedb_unlink_nodes(gobj, treedb_name, parent_ref, child_ref, options)
|
|
|
1628
1661
|
child_ref: child_ref,
|
|
1629
1662
|
options: options || {}
|
|
1630
1663
|
};
|
|
1664
|
+
kw.__md_command__ = link_echo(parent_ref, child_ref);
|
|
1631
1665
|
|
|
1632
1666
|
let ret = gobj_command(priv.gobj_remote_yuno,
|
|
1633
1667
|
command,
|
|
@@ -2111,8 +2145,12 @@ function ac_mt_command_answer(gobj, event, kw, src)
|
|
|
2111
2145
|
* answering its own writes in a loop.
|
|
2112
2146
|
*
|
|
2113
2147
|
* Same event and same kw as C_YUI_TREEDB_TOPICS, plus `command`:
|
|
2114
|
-
* in a graph a LINK is as much a write as a record is, and
|
|
2115
|
-
*
|
|
2148
|
+
* in a graph a LINK is as much a write as a record is, and a
|
|
2149
|
+
* link adds its two refs. Read from what THIS view knows and
|
|
2150
|
+
* from the answer, never from the request: the frame carries
|
|
2151
|
+
* back only `__md_command__`. `treedb_name` is the view's,
|
|
2152
|
+
* `record` is the node the store answered (the child, for a
|
|
2153
|
+
* link).
|
|
2116
2154
|
*
|
|
2117
2155
|
* `__graphs__` is EXCLUDED, and that exclusion is the point of
|
|
2118
2156
|
* reading this comment: the view writes that topic ITSELF, one
|
|
@@ -2128,13 +2166,18 @@ function ac_mt_command_answer(gobj, event, kw, src)
|
|
|
2128
2166
|
}
|
|
2129
2167
|
if(result >= 0 &&
|
|
2130
2168
|
kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") {
|
|
2131
|
-
|
|
2132
|
-
treedb_name:
|
|
2169
|
+
let written = {
|
|
2170
|
+
treedb_name: priv.treedb_name,
|
|
2133
2171
|
topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
|
|
2134
|
-
record:
|
|
2172
|
+
record: answered_record(data),
|
|
2135
2173
|
created: (command === "create-node"),
|
|
2136
2174
|
command: command
|
|
2137
|
-
}
|
|
2175
|
+
};
|
|
2176
|
+
if(command === "link-nodes" || command === "unlink-nodes") {
|
|
2177
|
+
written.parent_ref = kw_get_str(gobj, kw_command, "parent_ref", "", 0);
|
|
2178
|
+
written.child_ref = kw_get_str(gobj, kw_command, "child_ref", "", 0);
|
|
2179
|
+
}
|
|
2180
|
+
gobj_publish_event(gobj, "EV_RECORD_WRITTEN", written);
|
|
2138
2181
|
}
|
|
2139
2182
|
break;
|
|
2140
2183
|
|