@yuneta/gobj-ui 7.25.14 → 7.25.16

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.
Files changed (35) hide show
  1. package/README.md +100 -4
  2. package/dist/gobj-ui.cjs.js +406 -94
  3. package/dist/gobj-ui.es.js +406 -94
  4. package/package.json +2 -2
  5. package/src/c_g6_nodes_tree.js +79 -15
  6. package/src/c_yui_schema_editor.js +343 -66
  7. package/src/c_yui_treedb_graph.js +53 -6
  8. package/src/c_yui_treedb_topic_with_form.js +10 -10
  9. package/src/c_yui_treedb_topics.js +7 -7
  10. package/src/form_busy.js +2 -3
  11. package/src/form_busy.test.js +1 -1
  12. package/src/form_time_value.js +1 -1
  13. package/src/form_time_value.test.js +1 -1
  14. package/src/form_writes_in_flight.js +1 -2
  15. package/src/form_writes_in_flight.test.js +1 -1
  16. package/src/g6_graphs_write_owed.wiring.test.js +200 -0
  17. package/src/g6_nodes_tree_fsm.test.js +33 -0
  18. package/src/graph_save_plan.js +28 -0
  19. package/src/graph_save_plan.test.js +36 -2
  20. package/src/host_drafts.js +2 -3
  21. package/src/host_drafts.test.js +2 -2
  22. package/src/schema_editor_drafts.wiring.test.js +2 -2
  23. package/src/schema_editor_reload.wiring.test.js +329 -49
  24. package/src/schema_editor_transport.wiring.test.js +2 -2
  25. package/src/schema_version_bump.test.js +1 -1
  26. package/src/shell_modals.js +31 -11
  27. package/src/shell_toast_once.test.js +73 -10
  28. package/src/table_cell_text.js +1 -1
  29. package/src/table_cell_text.test.js +1 -1
  30. package/src/treedb_graph_writes.wiring.test.js +208 -0
  31. package/src/treedb_topics_transport.wiring.test.js +2 -2
  32. package/src/yui_install.js +14 -3
  33. package/src/yui_install.test.js +23 -0
  34. package/src/yui_row_search.test.js +1 -1
  35. package/src/yui_table_select.test.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.25.14",
3
+ "version": "7.25.16",
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.22.2",
33
+ "@yuneta/gobj-js": "^7.25.2",
34
34
  "vite": "^8.2.1",
35
35
  "vitest": "^4.1.10"
36
36
  },
@@ -94,6 +94,7 @@ import {
94
94
 
95
95
  import {
96
96
  apply_graphs_echo,
97
+ forget_refused_graphs_write,
97
98
  plan_graph_saves,
98
99
  topic_arrangement_changed,
99
100
  } from "./graph_save_plan.js";
@@ -492,6 +493,7 @@ let PRIVATE_DATA = {
492
493
  __graphs__: [], // Rows of __graphs__
493
494
  _graph_properties: {}, // topic_name → {nodes: {node_id: {x,y,size,...}}}
494
495
  _saved_graph_properties: {}, // the same, as the BACKEND has it: what a Save compares against
496
+ _graphs_writes_owed: {}, // topic_name → true: a __graphs__ write the host said did not land
495
497
  yet_showed: false,
496
498
  edit_mode: false,
497
499
  operation_mode: null,
@@ -3275,13 +3277,16 @@ function save_topic_graph_properties(gobj, topic_name)
3275
3277
  * the publish and as a copy, because the object below travels by
3276
3278
  * reference and goes on being arranged after the write.
3277
3279
  *
3278
- * Nothing answers an `EV_UPDATE_NODE` of `__graphs__` -- the view
3279
- * writes that topic itself and is deliberately not told about it
3280
- * (see the EV_RECORD_WRITTEN of C_YUI_TREEDB_GRAPH) -- so this is
3281
- * the write taken for granted. A refused one leaves the view
3282
- * believing the backend holds an arrangement it does not, until
3283
- * the next load reads the records again. */
3280
+ * Nothing answers an `EV_UPDATE_NODE` of `__graphs__` when it
3281
+ * lands -- the view writes that topic itself and is deliberately
3282
+ * not told about it (see the EV_RECORD_WRITTEN of
3283
+ * C_YUI_TREEDB_GRAPH) -- so this is the write taken for granted.
3284
+ * The host says when one does NOT land (EV_GRAPHS_WRITE_REFUSED),
3285
+ * and the next Save writes the topic again. */
3284
3286
  priv._saved_graph_properties[topic_name] = json_deep_copy(properties);
3287
+ /* Paid: this is the write that was owed, if one was. Refused
3288
+ * again, EV_GRAPHS_WRITE_REFUSED owes it again. */
3289
+ delete priv._graphs_writes_owed[topic_name];
3285
3290
 
3286
3291
  let kw_update = {
3287
3292
  treedb_name: priv.treedb_name,
@@ -3387,9 +3392,16 @@ function update_history_buttons(gobj)
3387
3392
  disableElements($container, ".EV_HISTORY_UNDO");
3388
3393
  set_active_state($container, ".EV_HISTORY_UNDO", false);
3389
3394
 
3390
- // No more undos: graph is back to original state, disable save
3391
- disableElements($container, ".EV_SAVE_GRAPH");
3392
- set_submit_state($container, ".EV_SAVE_GRAPH", false);
3395
+ /* No more undos: the graph is back to what was loaded
3396
+ * or saved -- unless a write of it did not land. That
3397
+ * one is still owed, and only a Save pays it. */
3398
+ if(graphs_write_is_owed(gobj)) {
3399
+ enableElements($container, ".EV_SAVE_GRAPH");
3400
+ set_submit_state($container, ".EV_SAVE_GRAPH", true);
3401
+ } else {
3402
+ disableElements($container, ".EV_SAVE_GRAPH");
3403
+ set_submit_state($container, ".EV_SAVE_GRAPH", false);
3404
+ }
3393
3405
  }
3394
3406
  } else {
3395
3407
  disableElements($container, ".EV_HISTORY_REDO");
@@ -4762,6 +4774,17 @@ function run_preview_undo(gobj, key)
4762
4774
  }
4763
4775
  }
4764
4776
 
4777
+ /************************************************************
4778
+ * Is a `__graphs__` write owed? The host said one did not land
4779
+ * (EV_GRAPHS_WRITE_REFUSED), and no Save has written that topic
4780
+ * since. The Save button stays lit while it is: the history
4781
+ * knows nothing of it, so `canUndo()` alone would put it out.
4782
+ ************************************************************/
4783
+ function graphs_write_is_owed(gobj)
4784
+ {
4785
+ return Object.keys(gobj.priv._graphs_writes_owed).length > 0;
4786
+ }
4787
+
4765
4788
  function mark_graph_dirty(gobj)
4766
4789
  {
4767
4790
  let $container = gobj_read_attr(gobj, "$container");
@@ -10345,6 +10368,11 @@ function ac_clear_data(gobj, event, kw, src)
10345
10368
 
10346
10369
  gobj_write_attr(gobj, "records", {});
10347
10370
 
10371
+ /* A write owed is owed on the arrangement being thrown away: the
10372
+ * reload brings what the backend holds, and that is what the view
10373
+ * will hold. */
10374
+ priv._graphs_writes_owed = {};
10375
+
10348
10376
  /* The node counters belong to the data that is going away: a refresh
10349
10377
  * that kept them would decide the layout on the previous treedb. */
10350
10378
  priv._nodes_total = 0;
@@ -10494,15 +10522,49 @@ function ac_save_graph(gobj, event, kw, src)
10494
10522
  let history = graph_get_plugin(gobj, "history");
10495
10523
  if(history) {
10496
10524
  history.clear();
10497
- update_history_buttons(gobj);
10498
10525
  }
10499
10526
 
10500
10527
  save_geometry(gobj); // Publish an EV_UPDATE_NODE of each node
10528
+
10529
+ /* After the writes: they pay a write owed, and the buttons
10530
+ * are repainted from what is still owed. */
10531
+ update_history_buttons(gobj);
10501
10532
  }
10502
10533
 
10503
10534
  return 0;
10504
10535
  }
10505
10536
 
10537
+ /************************************************************
10538
+ * The host says a write of `__graphs__` did not land: the
10539
+ * backend refused it, the transport refused it on the way out,
10540
+ * or there was no session to send it on. kw: {topic}
10541
+ *
10542
+ * save_topic_graph_properties() recorded it as saved before it
10543
+ * left. Forgotten now, and the Save is lit again: the next Save
10544
+ * writes the topic again. Before, the view believed the backend
10545
+ * held the arrangement, and the next Save had nothing to write.
10546
+ ************************************************************/
10547
+ function ac_graphs_write_refused(gobj, event, kw, src)
10548
+ {
10549
+ let priv = gobj.priv;
10550
+ let topic_name = kw && kw.topic;
10551
+
10552
+ if(!topic_name) {
10553
+ log_error(`${gobj_short_name(gobj)}: ${event} names no topic`);
10554
+ return -1;
10555
+ }
10556
+ log_warning(`${gobj_short_name(gobj)}: the arrangement of '${topic_name}' ` +
10557
+ `was not saved: the next Save writes it again`);
10558
+ forget_refused_graphs_write(priv._saved_graph_properties, topic_name);
10559
+ /* Owed until a Save writes it: update_history_buttons() keeps
10560
+ * the Save lit while it is, in edition and on entering it. */
10561
+ priv._graphs_writes_owed[topic_name] = true;
10562
+ if(priv.edit_mode) {
10563
+ mark_graph_dirty(gobj);
10564
+ }
10565
+ return 0;
10566
+ }
10567
+
10506
10568
  /************************************************************
10507
10569
  * Node created, from subscription
10508
10570
  ************************************************************/
@@ -10582,8 +10644,8 @@ function ac_node_updated(gobj, event, kw, src)
10582
10644
  priv.__graphs__.push(node);
10583
10645
  }
10584
10646
  /* Only THIS record's topic: a rebuild of every topic took their
10585
- * saved copies from the live objects (M32 of the 2026-09-21
10586
- * review). build_graph_properties() is for the load. */
10647
+ * saved copies from the live objects.
10648
+ * build_graph_properties() is for the load. */
10587
10649
  apply_graphs_echo(
10588
10650
  priv._graph_properties, priv._saved_graph_properties, priv.__graphs__, node
10589
10651
  );
@@ -10637,7 +10699,7 @@ function ac_node_updated(gobj, event, kw, src)
10637
10699
  update_local_node(gobj, topic_name, node);
10638
10700
  /* `priv.graph`: this read an undeclared `graph`, the ReferenceError
10639
10701
  * fell into the catch, and a card on screen kept its old record after
10640
- * every UPDATED (M33 of the 2026-09-21 review). The catch is for G6,
10702
+ * every UPDATED. The catch is for G6,
10641
10703
  * which throws on an id it does not hold -- a folded card. */
10642
10704
  let on_screen = false;
10643
10705
  try {
@@ -11778,8 +11840,8 @@ function ac_confirmed(gobj, event, kw, src)
11778
11840
  }
11779
11841
  if(missing.length) {
11780
11842
  /* Gone while the question was open (another writer deleted
11781
- * them): said, to the log and to the person (a low of the
11782
- * 2026-09-22 review); the rest go on. */
11843
+ * them): said, to the log and to the person; the rest go
11844
+ * on. */
11783
11845
  log_error(`${gobj_short_name(gobj)}: ${event}: cards gone while ` +
11784
11846
  `confirming the delete, not deleted: ${missing.join(", ")}`);
11785
11847
  yui_shell_show_error(yui_shell_of(gobj), "some records were gone before the delete", {t: t});
@@ -12022,6 +12084,7 @@ function create_gclass(gclass_name)
12022
12084
  ["EV_NODE_CREATED", ac_node_created, null],
12023
12085
  ["EV_NODE_UPDATED", ac_node_updated, null],
12024
12086
  ["EV_NODE_DELETED", ac_node_deleted, null],
12087
+ ["EV_GRAPHS_WRITE_REFUSED", ac_graphs_write_refused, null],
12025
12088
 
12026
12089
  /*--- Graph interaction events ---*/
12027
12090
  ["EV_NODE_CLICK", ac_node_click, null],
@@ -12091,6 +12154,7 @@ function create_gclass(gclass_name)
12091
12154
  ["EV_NODE_CREATED", 0],
12092
12155
  ["EV_NODE_UPDATED", 0],
12093
12156
  ["EV_NODE_DELETED", 0],
12157
+ ["EV_GRAPHS_WRITE_REFUSED", 0],
12094
12158
 
12095
12159
  /*--- Graph interaction (internal) ---*/
12096
12160
  ["EV_NODE_CLICK", 0],