@yuneta/gobj-ui 7.25.19 → 7.25.20

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 CHANGED
@@ -586,7 +586,7 @@ Two layout facts the browser taught this component, both worth keeping:
586
586
  `"graph"`), `$container` (mounted by the parent).
587
587
  - Input events: `EV_SET_JSON {json}` (replace the whole document; `ST_EMPTY` →
588
588
  `ST_READY`), `EV_SUBTREE_LOADED {path, json}` (splice a fetched subtree),
589
- `EV_SUBTREE_ERROR {path, error}`, `EV_SET_VIEW_MODE {mode}` (`"tree"` /
589
+ `EV_SUBTREE_ERROR {path, error | i18n, by_design}`, `EV_SET_VIEW_MODE {mode}` (`"tree"` /
590
590
  `"text"` / `"graph"`; **no mode advances** to the next view, which is what
591
591
  the two-view toggle did when the list was two long), plus `EV_REFRESH` /
592
592
  `EV_SHOW` / `EV_HIDE` / `EV_LANGUAGE_CHANGED`.
@@ -597,10 +597,22 @@ Two layout facts the browser taught this component, both worth keeping:
597
597
  `C_YUI_TREEDB_TOPIC_WITH_FORM` does for its schema, cell and table viewers
598
598
  since `7.25.19` (before, it declared nothing: *"Event NOT DEFINED"*):
599
599
  ```js
600
- gobj_send_event(src, "EV_SUBTREE_ERROR",
601
- {path: kw.path, error: t("this part cannot be loaded here")}, gobj);
602
- ``` That is the ONLY
603
- one, on purpose: this viewer is a child of its host and subscribes it to
600
+ gobj_send_event(src, "EV_SUBTREE_ERROR", {
601
+ path: kw.path,
602
+ i18n: "this part cannot be loaded here", // a KEY: t(key) + data-i18n
603
+ by_design: true // not a failure: logged as a warning
604
+ }, gobj);
605
+ ```
606
+ `error` is text, drawn as it came (a backend's comment); `i18n` is a key,
607
+ so the stub changes language with the app -- a text translated by the host
608
+ stays in the language it was sent in. The name `i18n` is the one a
609
+ `validate-locales` scan looks for, so the key stays visible to it. `by_design`
610
+ says the host CANNOT, which is not a failure: the viewer logs it as a
611
+ WARNING, and anything else as an ERROR. Before `7.25.20` the form sent
612
+ `t(...)`, and every click on a stub logged an ERROR, which broke a
613
+ clean-console check and reached the backend through the remote log.
614
+
615
+ `EV_EXPAND_PATH` is the ONLY output event, on purpose: this viewer is a child of its host and subscribes it to
604
616
  everything it publishes, so every output event is a mandatory declaration in
605
617
  every host's FSM. The graph child's `EV_JSON_ITEM_CLICKED` stops here
606
618
  (`7.21.0` forwarded it and broke exactly that way); a host that wants node
@@ -1900,10 +1912,34 @@ worked only in a test whose fake transport echoed the whole request. The host
1900
1912
  now puts the topic in the echo it asks for:
1901
1913
 
1902
1914
  ```js
1903
- kw.__md_command__ = {topic_name: "__graphs__", graph_topic: "users"};
1915
+ kw.__md_command__ = {topic_name: "__graphs__", graph_topic: "users", graphs_load: 3};
1904
1916
  // the answer: __md_iev__.command_stack[0].kw === that echo, and nothing else
1905
1917
  ```
1906
1918
 
1919
+ **A refusal belongs to the LOAD its write was sent from** (since `7.25.20`).
1920
+ "A reload forgets it" held only for a refusal that arrived BEFORE the reload:
1921
+ one answered after it was applied to the fresh load -- Save, Refresh, then the
1922
+ refusal lands -- and lit Save over nothing changed, and pressing it wrote a
1923
+ record identical to what the backend holds. The engine now counts its loads
1924
+ (each `EV_CLEAR_DATA` starts one) and puts the number in every `EV_UPDATE_NODE`
1925
+ of `__graphs__` as `graphs_load`; the host echoes it in `__md_command__` and
1926
+ hands it back with `EV_GRAPHS_WRITE_REFUSED {topic, graphs_load}`. A refusal of
1927
+ an earlier load is logged as a warning and ignored. A host that sends no
1928
+ `graphs_load` is taken at its word, as before:
1929
+
1930
+ ```js
1931
+ // in the host: the engine's load, from the EV_UPDATE_NODE it published
1932
+ gobj_send_event(engine, "EV_GRAPHS_WRITE_REFUSED",
1933
+ {topic: record.topic, graphs_load: kw.graphs_load}, gobj);
1934
+ ```
1935
+
1936
+ **A `__graphs__` create echo moves only its own topic** (since `7.25.20`), as
1937
+ an update echo has since `7.25.19` (`apply_graphs_echo()`). The first record of
1938
+ a topic's arrangement -- from this browser or another -- rebuilt the saved
1939
+ copies of EVERY topic from the live objects the view arranges in place, so an
1940
+ unsaved change of another topic (a look reset in edition, say) counted as saved
1941
+ and the next Save did not write it.
1942
+
1907
1943
  **Every saved look has a way back, in the context menu** (since `7.23.134`,
1908
1944
  replacing `reset sizes` / `reset topic sizes`). In edition, the node, the port
1909
1945
  and the edge menus each offer three resets — this one, its kind (`reset topic
@@ -2381,7 +2417,13 @@ else.
2381
2417
  consumer's locales carry). A write that ends with an error -- a drop
2382
2418
  included -- still applies a position that waited, as a load does. Out of
2383
2419
  session a load is not asked at all (no *"not in session"* errors); the
2384
- reconnect loads.
2420
+ reconnect loads. **Nor is a write** (7.25.20): each one of the queue asks
2421
+ first, and out of session the writes end with `cannot reach the treedb`, a
2422
+ warning, and a reload owed to the next session. A direct `C_IEVENT_CLI`
2423
+ answers a command out of session with `null`, the answer of a request that
2424
+ left, so before this the editor sat in `ST_SAVING`, inert, until another
2425
+ drop. (gui_agent's `C_AGENT_TREEDB_LINK` answers an error string there, so
2426
+ it was not hit.)
2385
2427
  - **A dialog is built on ONE model, and a load that replaces it closes it**
2386
2428
  (7.25.9). Every load that lands bumps `model_gen`; a dialog records the one
2387
2429
  it was opened on, and its Save, its import Preview/Run, an orphan delete and
@@ -14743,10 +14743,18 @@ function push_collapsed_row(ctx, value, segments, depth, key, rows) {
14743
14743
  },
14744
14744
  is_pending ? "loading" : "click to load"
14745
14745
  ]);
14746
- if (err) children.push([
14746
+ if (err && err.is_key) children.push([
14747
+ "span",
14748
+ {
14749
+ class: "JSON_STUB_ERR has-text-danger is-size-7 ml-2",
14750
+ "data-i18n": err.error
14751
+ },
14752
+ (0, i18next.t)(err.error)
14753
+ ]);
14754
+ else if (err) children.push([
14747
14755
  "span",
14748
14756
  { class: "JSON_STUB_ERR has-text-danger is-size-7 ml-2" },
14749
- String(err)
14757
+ String(err.error)
14750
14758
  ]);
14751
14759
  let attrs = {
14752
14760
  class: "JSON_ROW JSON_COLLAPSED" + (is_pending ? " is-pending" : ""),
@@ -14963,14 +14971,32 @@ function ac_subtree_loaded(gobj, event, kw, src) {
14963
14971
  return 0;
14964
14972
  }
14965
14973
  /************************************************************
14966
- * EV_SUBTREE_ERROR { path, error } — mark the failed branch
14974
+ * EV_SUBTREE_ERROR { path, error | i18n, by_design }
14975
+ * — mark the branch that was not loaded.
14976
+ *
14977
+ * `error` is text, drawn as it came (a backend's comment).
14978
+ * `i18n` is a KEY, drawn as t(key) with data-i18n so the stub
14979
+ * changes language with the app (a text translated by the host
14980
+ * stays in the language it was sent in). The name is the one a
14981
+ * locale check scans for (`i18n: "<key>"`), so the key of every
14982
+ * host stays visible to it.
14983
+ * `by_design`: the host answers that it CANNOT read a subtree
14984
+ * (a form holds records, a pasted pad has no backend) -- that is
14985
+ * not a failure, and it is logged as a warning. Anything else is
14986
+ * a load that failed, logged as an error.
14967
14987
  ************************************************************/
14968
14988
  function ac_subtree_error(gobj, event, kw, src) {
14969
14989
  let priv = gobj.priv;
14970
14990
  let path = kw.path || "";
14991
+ let is_key = !!kw.i18n;
14992
+ let error = kw.i18n || kw.error || "error";
14971
14993
  priv.pending.delete(path);
14972
- priv.errors.set(path, kw.error || "error");
14973
- (0, _yuneta_gobj_js.log_error)(`${GCLASS_NAME$13}: subtree load failed at '${path}': ${kw.error || ""}`);
14994
+ priv.errors.set(path, {
14995
+ error,
14996
+ is_key
14997
+ });
14998
+ if (kw.by_design) (0, _yuneta_gobj_js.log_warning)(`${GCLASS_NAME$13}: subtree not loaded at '${path}': ${error}`);
14999
+ else (0, _yuneta_gobj_js.log_error)(`${GCLASS_NAME$13}: subtree load failed at '${path}': ${error}`);
14974
15000
  render_view$1(gobj);
14975
15001
  return 0;
14976
15002
  }
@@ -16023,7 +16049,8 @@ function ac_hide_diff(gobj, event, kw, src) {
16023
16049
  function ac_expand_path$1(gobj, event, kw, src) {
16024
16050
  (0, _yuneta_gobj_js.gobj_send_event)(src, "EV_SUBTREE_ERROR", {
16025
16051
  path: kw && kw.path || "",
16026
- error: (0, i18next.t)("collapsed in the source")
16052
+ i18n: "collapsed in the source",
16053
+ by_design: true
16027
16054
  }, gobj);
16028
16055
  return 0;
16029
16056
  }
@@ -25119,7 +25146,7 @@ function request_print_tranger$1(gobj, path) {
25119
25146
  let jv = priv.json_gobj;
25120
25147
  if (path && jv && (0, _yuneta_gobj_js.is_gobj)(jv) && !(0, _yuneta_gobj_js.gobj_is_destroying)(jv)) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
25121
25148
  path,
25122
- error: (0, i18next.t)("no session")
25149
+ i18n: "no session"
25123
25150
  }, gobj);
25124
25151
  return;
25125
25152
  }
@@ -29470,7 +29497,8 @@ function ac_expand_path(gobj, event, kw, src) {
29470
29497
  let path = kw && kw.path || "";
29471
29498
  (0, _yuneta_gobj_js.gobj_send_event)(src, "EV_SUBTREE_ERROR", {
29472
29499
  path,
29473
- error: (0, i18next.t)("this part cannot be loaded here")
29500
+ i18n: "this part cannot be loaded here",
29501
+ by_design: true
29474
29502
  }, gobj);
29475
29503
  return 0;
29476
29504
  }
@@ -59294,6 +59322,7 @@ var PRIVATE_DATA$4 = {
59294
59322
  _graph_properties: {},
59295
59323
  _saved_graph_properties: {},
59296
59324
  _graphs_writes_owed: {},
59325
+ _graphs_load: 0,
59297
59326
  yet_showed: false,
59298
59327
  edit_mode: false,
59299
59328
  operation_mode: null,
@@ -61003,7 +61032,8 @@ function save_topic_graph_properties(gobj, topic_name) {
61003
61032
  list_dict: true,
61004
61033
  autolink: false,
61005
61034
  create: true
61006
- }
61035
+ },
61036
+ graphs_load: priv._graphs_load
61007
61037
  };
61008
61038
  (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_UPDATE_NODE", kw_update);
61009
61039
  }
@@ -65784,6 +65814,7 @@ function ac_clear_data(gobj, event, kw, src) {
65784
65814
  hide_create_popover(gobj);
65785
65815
  (0, _yuneta_gobj_js.gobj_write_attr)(gobj, "records", {});
65786
65816
  priv._graphs_writes_owed = {};
65817
+ priv._graphs_load++;
65787
65818
  priv._nodes_total = 0;
65788
65819
  priv._nodes_placed = 0;
65789
65820
  priv._fold_model = null;
@@ -65885,12 +65916,19 @@ function ac_save_graph(gobj, event, kw, src) {
65885
65916
  /************************************************************
65886
65917
  * The host says a write of `__graphs__` did not land: the
65887
65918
  * backend refused it, the transport refused it on the way out,
65888
- * or there was no session to send it on. kw: {topic}
65919
+ * or there was no session to send it on.
65920
+ * kw: {topic, graphs_load}
65889
65921
  *
65890
65922
  * save_topic_graph_properties() recorded it as saved before it
65891
65923
  * left. Forgotten now, and the Save is lit again: the next Save
65892
65924
  * writes the topic again. Before, the view believed the backend
65893
65925
  * held the arrangement, and the next Save had nothing to write.
65926
+ *
65927
+ * `graphs_load` is the load the write was sent from, echoed by the
65928
+ * host. A refusal of an EARLIER load is about an arrangement the
65929
+ * reload replaced with what the backend holds: applied, it lit the
65930
+ * Save over nothing changed (before gobj-ui 7.25.20). A host that
65931
+ * echoes no load is taken at its word, as before.
65894
65932
  ************************************************************/
65895
65933
  function ac_graphs_write_refused(gobj, event, kw, src) {
65896
65934
  let priv = gobj.priv;
@@ -65899,6 +65937,10 @@ function ac_graphs_write_refused(gobj, event, kw, src) {
65899
65937
  (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} names no topic`);
65900
65938
  return -1;
65901
65939
  }
65940
+ if (kw.graphs_load !== void 0 && kw.graphs_load !== priv._graphs_load) {
65941
+ (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: a refused write of the arrangement of '${topic_name}' belongs to an earlier load: ignored`);
65942
+ return 0;
65943
+ }
65902
65944
  (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: the arrangement of '${topic_name}' was not saved: the next Save writes it again`);
65903
65945
  forget_refused_graphs_write(priv._saved_graph_properties, topic_name);
65904
65946
  priv._graphs_writes_owed[topic_name] = true;
@@ -65932,7 +65974,7 @@ function ac_node_created(gobj, event, kw, src) {
65932
65974
  if (!priv.descs || !priv.graph) return 0;
65933
65975
  if (topic_name === "__graphs__") {
65934
65976
  priv.__graphs__.push(node);
65935
- build_graph_properties(gobj);
65977
+ apply_graphs_echo(priv._graph_properties, priv._saved_graph_properties, priv.__graphs__, node);
65936
65978
  settle_owed_graphs_write(gobj, node);
65937
65979
  return 0;
65938
65980
  }
@@ -68313,7 +68355,7 @@ function request_print_tranger(gobj, path) {
68313
68355
  let jv = priv.json_gobj;
68314
68356
  if (path && jv && (0, _yuneta_gobj_js.is_gobj)(jv) && !(0, _yuneta_gobj_js.gobj_is_destroying)(jv)) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
68315
68357
  path,
68316
- error: (0, i18next.t)("no session")
68358
+ i18n: "no session"
68317
68359
  }, gobj);
68318
68360
  return;
68319
68361
  }
@@ -68422,7 +68464,7 @@ function treedb_create_node(gobj, treedb_name, topic_name, record, options) {
68422
68464
  /************************************************************
68423
68465
  * Command to remote service
68424
68466
  ************************************************************/
68425
- function treedb_update_node(gobj, treedb_name, topic_name, record, options) {
68467
+ function treedb_update_node(gobj, treedb_name, topic_name, record, options, graphs_load) {
68426
68468
  let priv = gobj.priv;
68427
68469
  if (!priv.gobj_remote_yuno) {
68428
68470
  (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: No gobj_remote_yuno defined`);
@@ -68437,7 +68479,10 @@ function treedb_update_node(gobj, treedb_name, topic_name, record, options) {
68437
68479
  options: options || {}
68438
68480
  };
68439
68481
  kw.__md_command__ = { topic_name };
68440
- if (topic_name === "__graphs__") kw.__md_command__.graph_topic = graph_topic_of(record);
68482
+ if (topic_name === "__graphs__") {
68483
+ kw.__md_command__.graph_topic = graph_topic_of(record);
68484
+ if (graphs_load !== void 0) kw.__md_command__.graphs_load = graphs_load;
68485
+ }
68441
68486
  let ret = (0, _yuneta_gobj_js.gobj_command)(priv.gobj_remote_yuno, command, kw, gobj);
68442
68487
  if (ret) {
68443
68488
  (0, _yuneta_gobj_js.log_error)(ret);
@@ -68741,7 +68786,7 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
68741
68786
  case "delete-node":
68742
68787
  case "link-nodes":
68743
68788
  case "unlink-nodes":
68744
- if (result < 0 && command === "update-node") graphs_write_refused(gobj, (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0), (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "graph_topic", "", 0));
68789
+ if (result < 0 && command === "update-node") graphs_write_refused(gobj, (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0), (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "graph_topic", "", 0), kw_command ? kw_command.graphs_load : void 0);
68745
68790
  if (result >= 0 && (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") {
68746
68791
  let written = {
68747
68792
  treedb_name: priv.treedb_name,
@@ -68996,17 +69041,18 @@ function ac_update_node(gobj, event, kw, src) {
68996
69041
  let topic_name = kw.topic_name;
68997
69042
  let record = kw.record;
68998
69043
  let options = kw.options || {};
69044
+ let graphs_load = kw.graphs_load;
68999
69045
  if (refuse_if_readonly$1(gobj, event)) {
69000
- graphs_write_refused(gobj, topic_name, graph_topic_of(record));
69046
+ graphs_write_refused(gobj, topic_name, graph_topic_of(record), graphs_load);
69001
69047
  return -1;
69002
69048
  }
69003
69049
  if (topic_name === "__graphs__" && !is_connected(gobj)) {
69004
69050
  (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no session, the arrangement was not sent`);
69005
- graphs_write_refused(gobj, topic_name, graph_topic_of(record));
69051
+ graphs_write_refused(gobj, topic_name, graph_topic_of(record), graphs_load);
69006
69052
  return -1;
69007
69053
  }
69008
- let ret = treedb_update_node(gobj, treedb_name, topic_name, record, options);
69009
- if (ret < 0) graphs_write_refused(gobj, topic_name, graph_topic_of(record));
69054
+ let ret = treedb_update_node(gobj, treedb_name, topic_name, record, options, graphs_load);
69055
+ if (ret < 0) graphs_write_refused(gobj, topic_name, graph_topic_of(record), graphs_load);
69010
69056
  return ret;
69011
69057
  }
69012
69058
  /************************************************************
@@ -69021,9 +69067,11 @@ function graph_topic_of(record) {
69021
69067
  * (C_G6_NODES_TREE) took it for granted when it left -- nothing
69022
69068
  * answers it when it lands -- so it is told, and its next Save
69023
69069
  * writes the topic again. Other topics are the operator's data:
69024
- * the answer's error says what happened to them.
69070
+ * the answer's error says what happened to them. `graphs_load` is
69071
+ * the engine's load the write was sent from, handed back so it can
69072
+ * tell a refusal of an earlier load from one of the current.
69025
69073
  ************************************************************/
69026
- function graphs_write_refused(gobj, topic_name, topic) {
69074
+ function graphs_write_refused(gobj, topic_name, topic, graphs_load) {
69027
69075
  let priv = gobj.priv;
69028
69076
  if (topic_name !== "__graphs__") return;
69029
69077
  if (!topic) {
@@ -69031,7 +69079,9 @@ function graphs_write_refused(gobj, topic_name, topic) {
69031
69079
  return;
69032
69080
  }
69033
69081
  if (!priv.gobj_nodes_tree) return;
69034
- (0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_GRAPHS_WRITE_REFUSED", { topic }, gobj);
69082
+ let kw = { topic };
69083
+ if (graphs_load !== void 0) kw.graphs_load = graphs_load;
69084
+ (0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_GRAPHS_WRITE_REFUSED", kw, gobj);
69035
69085
  }
69036
69086
  /********************************************
69037
69087
  * Message from G6_nodes_tree
@@ -75222,13 +75272,18 @@ function run_next_write(gobj) {
75222
75272
  let write = priv.save_queue[0];
75223
75273
  let command = write_command(write.op);
75224
75274
  let options = write_options(write.op);
75275
+ if (!transport_in_session(gobj)) {
75276
+ (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no session, '${command}' of '${write.topic_name}' was not sent`);
75277
+ priv.reload_on_open = true;
75278
+ return end_writes(gobj, "cannot reach the treedb");
75279
+ }
75225
75280
  priv.write_tag++;
75226
75281
  if (remote_command(gobj, command, {
75227
75282
  topic_name: write.topic_name,
75228
75283
  record: write.record,
75229
75284
  options,
75230
75285
  record_id: write.record.id || ""
75231
- }, { write: priv.write_tag }) < 0) return end_writes(gobj, (0, i18next.t)("cannot reach the treedb"));
75286
+ }, { write: priv.write_tag }) < 0) return end_writes(gobj, "cannot reach the treedb");
75232
75287
  return 0;
75233
75288
  }
75234
75289
  /***************************************************************
@@ -14738,10 +14738,18 @@ function push_collapsed_row(ctx, value, segments, depth, key, rows) {
14738
14738
  },
14739
14739
  is_pending ? "loading" : "click to load"
14740
14740
  ]);
14741
- if (err) children.push([
14741
+ if (err && err.is_key) children.push([
14742
+ "span",
14743
+ {
14744
+ class: "JSON_STUB_ERR has-text-danger is-size-7 ml-2",
14745
+ "data-i18n": err.error
14746
+ },
14747
+ t(err.error)
14748
+ ]);
14749
+ else if (err) children.push([
14742
14750
  "span",
14743
14751
  { class: "JSON_STUB_ERR has-text-danger is-size-7 ml-2" },
14744
- String(err)
14752
+ String(err.error)
14745
14753
  ]);
14746
14754
  let attrs = {
14747
14755
  class: "JSON_ROW JSON_COLLAPSED" + (is_pending ? " is-pending" : ""),
@@ -14958,14 +14966,32 @@ function ac_subtree_loaded(gobj, event, kw, src) {
14958
14966
  return 0;
14959
14967
  }
14960
14968
  /************************************************************
14961
- * EV_SUBTREE_ERROR { path, error } — mark the failed branch
14969
+ * EV_SUBTREE_ERROR { path, error | i18n, by_design }
14970
+ * — mark the branch that was not loaded.
14971
+ *
14972
+ * `error` is text, drawn as it came (a backend's comment).
14973
+ * `i18n` is a KEY, drawn as t(key) with data-i18n so the stub
14974
+ * changes language with the app (a text translated by the host
14975
+ * stays in the language it was sent in). The name is the one a
14976
+ * locale check scans for (`i18n: "<key>"`), so the key of every
14977
+ * host stays visible to it.
14978
+ * `by_design`: the host answers that it CANNOT read a subtree
14979
+ * (a form holds records, a pasted pad has no backend) -- that is
14980
+ * not a failure, and it is logged as a warning. Anything else is
14981
+ * a load that failed, logged as an error.
14962
14982
  ************************************************************/
14963
14983
  function ac_subtree_error(gobj, event, kw, src) {
14964
14984
  let priv = gobj.priv;
14965
14985
  let path = kw.path || "";
14986
+ let is_key = !!kw.i18n;
14987
+ let error = kw.i18n || kw.error || "error";
14966
14988
  priv.pending.delete(path);
14967
- priv.errors.set(path, kw.error || "error");
14968
- log_error(`${GCLASS_NAME$13}: subtree load failed at '${path}': ${kw.error || ""}`);
14989
+ priv.errors.set(path, {
14990
+ error,
14991
+ is_key
14992
+ });
14993
+ if (kw.by_design) log_warning(`${GCLASS_NAME$13}: subtree not loaded at '${path}': ${error}`);
14994
+ else log_error(`${GCLASS_NAME$13}: subtree load failed at '${path}': ${error}`);
14969
14995
  render_view$1(gobj);
14970
14996
  return 0;
14971
14997
  }
@@ -16018,7 +16044,8 @@ function ac_hide_diff(gobj, event, kw, src) {
16018
16044
  function ac_expand_path$1(gobj, event, kw, src) {
16019
16045
  gobj_send_event(src, "EV_SUBTREE_ERROR", {
16020
16046
  path: kw && kw.path || "",
16021
- error: t("collapsed in the source")
16047
+ i18n: "collapsed in the source",
16048
+ by_design: true
16022
16049
  }, gobj);
16023
16050
  return 0;
16024
16051
  }
@@ -25114,7 +25141,7 @@ function request_print_tranger$1(gobj, path) {
25114
25141
  let jv = priv.json_gobj;
25115
25142
  if (path && jv && is_gobj(jv) && !gobj_is_destroying(jv)) gobj_send_event(jv, "EV_SUBTREE_ERROR", {
25116
25143
  path,
25117
- error: t("no session")
25144
+ i18n: "no session"
25118
25145
  }, gobj);
25119
25146
  return;
25120
25147
  }
@@ -29465,7 +29492,8 @@ function ac_expand_path(gobj, event, kw, src) {
29465
29492
  let path = kw && kw.path || "";
29466
29493
  gobj_send_event(src, "EV_SUBTREE_ERROR", {
29467
29494
  path,
29468
- error: t("this part cannot be loaded here")
29495
+ i18n: "this part cannot be loaded here",
29496
+ by_design: true
29469
29497
  }, gobj);
29470
29498
  return 0;
29471
29499
  }
@@ -59289,6 +59317,7 @@ var PRIVATE_DATA$4 = {
59289
59317
  _graph_properties: {},
59290
59318
  _saved_graph_properties: {},
59291
59319
  _graphs_writes_owed: {},
59320
+ _graphs_load: 0,
59292
59321
  yet_showed: false,
59293
59322
  edit_mode: false,
59294
59323
  operation_mode: null,
@@ -60998,7 +61027,8 @@ function save_topic_graph_properties(gobj, topic_name) {
60998
61027
  list_dict: true,
60999
61028
  autolink: false,
61000
61029
  create: true
61001
- }
61030
+ },
61031
+ graphs_load: priv._graphs_load
61002
61032
  };
61003
61033
  gobj_publish_event(gobj, "EV_UPDATE_NODE", kw_update);
61004
61034
  }
@@ -65779,6 +65809,7 @@ function ac_clear_data(gobj, event, kw, src) {
65779
65809
  hide_create_popover(gobj);
65780
65810
  gobj_write_attr(gobj, "records", {});
65781
65811
  priv._graphs_writes_owed = {};
65812
+ priv._graphs_load++;
65782
65813
  priv._nodes_total = 0;
65783
65814
  priv._nodes_placed = 0;
65784
65815
  priv._fold_model = null;
@@ -65880,12 +65911,19 @@ function ac_save_graph(gobj, event, kw, src) {
65880
65911
  /************************************************************
65881
65912
  * The host says a write of `__graphs__` did not land: the
65882
65913
  * backend refused it, the transport refused it on the way out,
65883
- * or there was no session to send it on. kw: {topic}
65914
+ * or there was no session to send it on.
65915
+ * kw: {topic, graphs_load}
65884
65916
  *
65885
65917
  * save_topic_graph_properties() recorded it as saved before it
65886
65918
  * left. Forgotten now, and the Save is lit again: the next Save
65887
65919
  * writes the topic again. Before, the view believed the backend
65888
65920
  * held the arrangement, and the next Save had nothing to write.
65921
+ *
65922
+ * `graphs_load` is the load the write was sent from, echoed by the
65923
+ * host. A refusal of an EARLIER load is about an arrangement the
65924
+ * reload replaced with what the backend holds: applied, it lit the
65925
+ * Save over nothing changed (before gobj-ui 7.25.20). A host that
65926
+ * echoes no load is taken at its word, as before.
65889
65927
  ************************************************************/
65890
65928
  function ac_graphs_write_refused(gobj, event, kw, src) {
65891
65929
  let priv = gobj.priv;
@@ -65894,6 +65932,10 @@ function ac_graphs_write_refused(gobj, event, kw, src) {
65894
65932
  log_error(`${gobj_short_name(gobj)}: ${event} names no topic`);
65895
65933
  return -1;
65896
65934
  }
65935
+ if (kw.graphs_load !== void 0 && kw.graphs_load !== priv._graphs_load) {
65936
+ log_warning(`${gobj_short_name(gobj)}: a refused write of the arrangement of '${topic_name}' belongs to an earlier load: ignored`);
65937
+ return 0;
65938
+ }
65897
65939
  log_warning(`${gobj_short_name(gobj)}: the arrangement of '${topic_name}' was not saved: the next Save writes it again`);
65898
65940
  forget_refused_graphs_write(priv._saved_graph_properties, topic_name);
65899
65941
  priv._graphs_writes_owed[topic_name] = true;
@@ -65927,7 +65969,7 @@ function ac_node_created(gobj, event, kw, src) {
65927
65969
  if (!priv.descs || !priv.graph) return 0;
65928
65970
  if (topic_name === "__graphs__") {
65929
65971
  priv.__graphs__.push(node);
65930
- build_graph_properties(gobj);
65972
+ apply_graphs_echo(priv._graph_properties, priv._saved_graph_properties, priv.__graphs__, node);
65931
65973
  settle_owed_graphs_write(gobj, node);
65932
65974
  return 0;
65933
65975
  }
@@ -68308,7 +68350,7 @@ function request_print_tranger(gobj, path) {
68308
68350
  let jv = priv.json_gobj;
68309
68351
  if (path && jv && is_gobj(jv) && !gobj_is_destroying(jv)) gobj_send_event(jv, "EV_SUBTREE_ERROR", {
68310
68352
  path,
68311
- error: t("no session")
68353
+ i18n: "no session"
68312
68354
  }, gobj);
68313
68355
  return;
68314
68356
  }
@@ -68417,7 +68459,7 @@ function treedb_create_node(gobj, treedb_name, topic_name, record, options) {
68417
68459
  /************************************************************
68418
68460
  * Command to remote service
68419
68461
  ************************************************************/
68420
- function treedb_update_node(gobj, treedb_name, topic_name, record, options) {
68462
+ function treedb_update_node(gobj, treedb_name, topic_name, record, options, graphs_load) {
68421
68463
  let priv = gobj.priv;
68422
68464
  if (!priv.gobj_remote_yuno) {
68423
68465
  log_error(`${gobj_short_name(gobj)}: No gobj_remote_yuno defined`);
@@ -68432,7 +68474,10 @@ function treedb_update_node(gobj, treedb_name, topic_name, record, options) {
68432
68474
  options: options || {}
68433
68475
  };
68434
68476
  kw.__md_command__ = { topic_name };
68435
- if (topic_name === "__graphs__") kw.__md_command__.graph_topic = graph_topic_of(record);
68477
+ if (topic_name === "__graphs__") {
68478
+ kw.__md_command__.graph_topic = graph_topic_of(record);
68479
+ if (graphs_load !== void 0) kw.__md_command__.graphs_load = graphs_load;
68480
+ }
68436
68481
  let ret = gobj_command(priv.gobj_remote_yuno, command, kw, gobj);
68437
68482
  if (ret) {
68438
68483
  log_error(ret);
@@ -68736,7 +68781,7 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
68736
68781
  case "delete-node":
68737
68782
  case "link-nodes":
68738
68783
  case "unlink-nodes":
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));
68784
+ 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), kw_command ? kw_command.graphs_load : void 0);
68740
68785
  if (result >= 0 && kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") {
68741
68786
  let written = {
68742
68787
  treedb_name: priv.treedb_name,
@@ -68991,17 +69036,18 @@ function ac_update_node(gobj, event, kw, src) {
68991
69036
  let topic_name = kw.topic_name;
68992
69037
  let record = kw.record;
68993
69038
  let options = kw.options || {};
69039
+ let graphs_load = kw.graphs_load;
68994
69040
  if (refuse_if_readonly$1(gobj, event)) {
68995
- graphs_write_refused(gobj, topic_name, graph_topic_of(record));
69041
+ graphs_write_refused(gobj, topic_name, graph_topic_of(record), graphs_load);
68996
69042
  return -1;
68997
69043
  }
68998
69044
  if (topic_name === "__graphs__" && !is_connected(gobj)) {
68999
69045
  log_warning(`${gobj_short_name(gobj)}: no session, the arrangement was not sent`);
69000
- graphs_write_refused(gobj, topic_name, graph_topic_of(record));
69046
+ graphs_write_refused(gobj, topic_name, graph_topic_of(record), graphs_load);
69001
69047
  return -1;
69002
69048
  }
69003
- let ret = treedb_update_node(gobj, treedb_name, topic_name, record, options);
69004
- if (ret < 0) graphs_write_refused(gobj, topic_name, graph_topic_of(record));
69049
+ let ret = treedb_update_node(gobj, treedb_name, topic_name, record, options, graphs_load);
69050
+ if (ret < 0) graphs_write_refused(gobj, topic_name, graph_topic_of(record), graphs_load);
69005
69051
  return ret;
69006
69052
  }
69007
69053
  /************************************************************
@@ -69016,9 +69062,11 @@ function graph_topic_of(record) {
69016
69062
  * (C_G6_NODES_TREE) took it for granted when it left -- nothing
69017
69063
  * answers it when it lands -- so it is told, and its next Save
69018
69064
  * writes the topic again. Other topics are the operator's data:
69019
- * the answer's error says what happened to them.
69065
+ * the answer's error says what happened to them. `graphs_load` is
69066
+ * the engine's load the write was sent from, handed back so it can
69067
+ * tell a refusal of an earlier load from one of the current.
69020
69068
  ************************************************************/
69021
- function graphs_write_refused(gobj, topic_name, topic) {
69069
+ function graphs_write_refused(gobj, topic_name, topic, graphs_load) {
69022
69070
  let priv = gobj.priv;
69023
69071
  if (topic_name !== "__graphs__") return;
69024
69072
  if (!topic) {
@@ -69026,7 +69074,9 @@ function graphs_write_refused(gobj, topic_name, topic) {
69026
69074
  return;
69027
69075
  }
69028
69076
  if (!priv.gobj_nodes_tree) return;
69029
- gobj_send_event(priv.gobj_nodes_tree, "EV_GRAPHS_WRITE_REFUSED", { topic }, gobj);
69077
+ let kw = { topic };
69078
+ if (graphs_load !== void 0) kw.graphs_load = graphs_load;
69079
+ gobj_send_event(priv.gobj_nodes_tree, "EV_GRAPHS_WRITE_REFUSED", kw, gobj);
69030
69080
  }
69031
69081
  /********************************************
69032
69082
  * Message from G6_nodes_tree
@@ -75217,13 +75267,18 @@ function run_next_write(gobj) {
75217
75267
  let write = priv.save_queue[0];
75218
75268
  let command = write_command(write.op);
75219
75269
  let options = write_options(write.op);
75270
+ if (!transport_in_session(gobj)) {
75271
+ log_warning(`${gobj_short_name(gobj)}: no session, '${command}' of '${write.topic_name}' was not sent`);
75272
+ priv.reload_on_open = true;
75273
+ return end_writes(gobj, "cannot reach the treedb");
75274
+ }
75220
75275
  priv.write_tag++;
75221
75276
  if (remote_command(gobj, command, {
75222
75277
  topic_name: write.topic_name,
75223
75278
  record: write.record,
75224
75279
  options,
75225
75280
  record_id: write.record.id || ""
75226
- }, { write: priv.write_tag }) < 0) return end_writes(gobj, t("cannot reach the treedb"));
75281
+ }, { write: priv.write_tag }) < 0) return end_writes(gobj, "cannot reach the treedb");
75227
75282
  return 0;
75228
75283
  }
75229
75284
  /***************************************************************
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.25.19",
3
+ "version": "7.25.20",
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.5",
33
+ "@yuneta/gobj-js": "^7.25.6",
34
34
  "vite": "^8.2.1",
35
35
  "vitest": "^4.1.10"
36
36
  },