@yuneta/gobj-ui 7.25.14 → 7.25.15
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 +41 -0
- package/dist/gobj-ui.cjs.js +184 -53
- package/dist/gobj-ui.es.js +184 -53
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +42 -11
- package/src/c_yui_schema_editor.js +104 -37
- package/src/c_yui_treedb_graph.js +53 -6
- package/src/c_yui_treedb_topic_with_form.js +10 -10
- package/src/c_yui_treedb_topics.js +7 -7
- package/src/form_busy.js +2 -3
- package/src/form_time_value.js +1 -1
- package/src/form_time_value.test.js +1 -1
- package/src/form_writes_in_flight.js +1 -2
- package/src/g6_nodes_tree_fsm.test.js +33 -0
- package/src/graph_save_plan.js +28 -0
- package/src/graph_save_plan.test.js +36 -2
- package/src/host_drafts.js +2 -3
- package/src/schema_editor_drafts.wiring.test.js +1 -1
- package/src/schema_editor_reload.wiring.test.js +178 -46
- package/src/schema_editor_transport.wiring.test.js +2 -2
- package/src/schema_version_bump.test.js +1 -1
- package/src/shell_modals.js +2 -3
- package/src/shell_toast_once.test.js +10 -10
- package/src/table_cell_text.js +1 -1
- package/src/treedb_graph_writes.wiring.test.js +208 -0
- package/src/treedb_topics_transport.wiring.test.js +1 -1
- package/src/yui_row_search.test.js +1 -1
- package/src/yui_table_select.test.js +1 -1
package/README.md
CHANGED
|
@@ -1790,6 +1790,25 @@ size. A card on its tier's default now saves its position and nothing else;
|
|
|
1790
1790
|
a closed node saves no size at all (a square is not the card's size), its
|
|
1791
1791
|
entry keeps what it had.
|
|
1792
1792
|
|
|
1793
|
+
**A Save that does not land is written again** (since `7.25.15`). `Save`
|
|
1794
|
+
writes one `__graphs__` record per topic that changed, and nothing answers such
|
|
1795
|
+
a write when it lands, so the engine takes it for granted when it leaves. A
|
|
1796
|
+
refused one was recorded as saved all the same: the next Save found nothing to
|
|
1797
|
+
write, and the arrangement was never stored. Now the host (`C_YUI_TREEDB_GRAPH`)
|
|
1798
|
+
tells the engine every way the write can fail -- the backend answers an error
|
|
1799
|
+
(shown as before), the transport refuses the command, or there is no session
|
|
1800
|
+
(the write is not sent) -- with `EV_GRAPHS_WRITE_REFUSED {topic}`. The engine
|
|
1801
|
+
forgets what it believed the backend holds for that topic
|
|
1802
|
+
(`forget_refused_graphs_write()` in `graph_save_plan.js`), logs a warning and
|
|
1803
|
+
lights Save again, so the next Save writes the topic. A host of its own that
|
|
1804
|
+
hosts `C_G6_NODES_TREE` sends the same event when its write of `__graphs__`
|
|
1805
|
+
fails:
|
|
1806
|
+
|
|
1807
|
+
```js
|
|
1808
|
+
// in the host, when the answer to its update-node of __graphs__ is an error
|
|
1809
|
+
gobj_send_event(engine, "EV_GRAPHS_WRITE_REFUSED", {topic: record.topic}, gobj);
|
|
1810
|
+
```
|
|
1811
|
+
|
|
1793
1812
|
**Every saved look has a way back, in the context menu** (since `7.23.134`,
|
|
1794
1813
|
replacing `reset sizes` / `reset topic sizes`). In edition, the node, the port
|
|
1795
1814
|
and the edge menus each offer three resets — this one, its kind (`reset topic
|
|
@@ -2245,6 +2264,28 @@ else.
|
|
|
2245
2264
|
gobj_send_event(editor, "EV_REFRESH", {}, host); // Save -> "wait for them"
|
|
2246
2265
|
// ... the load lands (model_gen N+1): the form closes, the operator reopens it
|
|
2247
2266
|
```
|
|
2267
|
+
- **A move sent by the host closes the dialog of the screen it left**
|
|
2268
|
+
(7.25.15). `C_YUI_SHELL` keeps the overlays open on a move that changes only
|
|
2269
|
+
the subpath (a url typed in, a link), so a dialog outlived its screen: its
|
|
2270
|
+
Save, its import Preview or an orphan delete sent an event only that screen
|
|
2271
|
+
declares, answered *"Event NOT DEFINED"*, and the edit was lost with no word.
|
|
2272
|
+
Now an `EV_SHOW` that moves the view to another position -- at once, or when
|
|
2273
|
+
a load or a write in flight ends -- closes the column form, the topic form,
|
|
2274
|
+
the import (its plan goes with it) and the orphans, and tells the operator
|
|
2275
|
+
`the view moved: open the dialog again` (an i18n key the consumer's locales
|
|
2276
|
+
carry). The export and the check stay up: they show the texts they were
|
|
2277
|
+
opened with and send nothing a screen declares. The same position sent again
|
|
2278
|
+
closes nothing. A **confirmation** is a shell modal, which the move does not
|
|
2279
|
+
close; it carries the position it was asked on (`seg`), and a Yes answered
|
|
2280
|
+
on another position is refused with the same words. Before, a Yes to "delete
|
|
2281
|
+
this column?" asked on `db/users` and answered after a move to `db2/users`
|
|
2282
|
+
deleted `db2`'s column of the same name.
|
|
2283
|
+
|
|
2284
|
+
```js
|
|
2285
|
+
gobj_send_event(editor, "EV_EDIT_COLUMN", {col: "id"}, host); // on db/users
|
|
2286
|
+
gobj_send_event(editor, "EV_SHOW", {subpath: "db"}, host); // form closed, said
|
|
2287
|
+
gobj_send_event(editor, "EV_SHOW", {subpath: "db"}, host); // same position: nothing
|
|
2288
|
+
```
|
|
2248
2289
|
- **A load refused IN session keeps the model it was replacing** (7.25.9): a
|
|
2249
2290
|
routing adapter's deadline on a slow `nodes` answers -1 while the session
|
|
2250
2291
|
is up. The records are put back, the screen and any open dialog stay, and
|
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -3038,9 +3038,8 @@ function maybe_apply_translator($node, opts) {
|
|
|
3038
3038
|
* it -- until every handle is closed or has timed out. Handed the
|
|
3039
3039
|
* first caller's handle and timer, a repeat asking `timeout: 0`
|
|
3040
3040
|
* was dismissed on the first one's timer, and closing one
|
|
3041
|
-
* caller's handle closed a toast another was still showing
|
|
3042
|
-
*
|
|
3043
|
-
* everybody.
|
|
3041
|
+
* caller's handle closed a toast another was still showing.
|
|
3042
|
+
* The operator's ✕ closes it for everybody.
|
|
3044
3043
|
***************************************************************/
|
|
3045
3044
|
function show_notification(shell, kind, message, opts) {
|
|
3046
3045
|
let $layer = notification_layer(shell);
|
|
@@ -7425,7 +7424,7 @@ function json_diff_rows(doc_a, doc_b) {
|
|
|
7425
7424
|
* A Date -> the value of a `datetime-local` input, in local time,
|
|
7426
7425
|
* WITH seconds: the input is built with `step: 1`, which is what
|
|
7427
7426
|
* lets it hold them. Written as "YYYY-MM-DDTHH:mm" it lost them on
|
|
7428
|
-
* every save of any field
|
|
7427
|
+
* every save of any field.
|
|
7429
7428
|
************************************************************/
|
|
7430
7429
|
function date_to_datetime_local(value) {
|
|
7431
7430
|
if (!(value instanceof Date) || isNaN(value.getTime())) return "";
|
|
@@ -23130,8 +23129,7 @@ function yui_shell_show_route_map(shell, opts) {
|
|
|
23130
23129
|
* answers, so the host has to answer EVERY way a write ends --
|
|
23131
23130
|
* and the transport closing under a write in flight, or a
|
|
23132
23131
|
* command that never left because there was no session, are two
|
|
23133
|
-
* of them that nobody answered: the form stayed busy for ever
|
|
23134
|
-
* (N8 of the 2026-09-22 review).
|
|
23132
|
+
* of them that nobody answered: the form stayed busy for ever.
|
|
23135
23133
|
*
|
|
23136
23134
|
* A write is known by its TOPIC and its `form_write` serial,
|
|
23137
23135
|
* never by the serial alone: each topic has its own form, and
|
|
@@ -25682,8 +25680,8 @@ function ac_update_record(gobj, event, kw, src) {
|
|
|
25682
25680
|
/************************************************************
|
|
25683
25681
|
* A write sent with no session never leaves: C_IEVENT_CLI logs
|
|
25684
25682
|
* "Not in session" and answers null, as it does when the command
|
|
25685
|
-
* went -- so a form waiting for the answer waited for ever
|
|
25686
|
-
*
|
|
25683
|
+
* went -- so a form waiting for the answer waited for ever. Refused
|
|
25684
|
+
* before it is sent, aloud.
|
|
25687
25685
|
************************************************************/
|
|
25688
25686
|
function refuse_without_session(gobj, topic_name) {
|
|
25689
25687
|
if (is_connected$1(gobj)) return false;
|
|
@@ -26795,9 +26793,8 @@ function delete_impact(desc, records) {
|
|
|
26795
26793
|
* that back. So a second busy(true) while already busy must not
|
|
26796
26794
|
* run at all -- it read the buttons it had just disabled as
|
|
26797
26795
|
* "disabled on their own", and the busy(false) of a refused write
|
|
26798
|
-
* left Save and Cancel dead (
|
|
26799
|
-
*
|
|
26800
|
-
* the write). The caller owns `state` ({busy}) for the form's life.
|
|
26796
|
+
* left Save and Cancel dead (a record with a picked file went
|
|
26797
|
+
* busy for the read, then busy again for the write). The caller owns `state` ({busy}) for the form's life.
|
|
26801
26798
|
*
|
|
26802
26799
|
* Copyright (c) 2026, ArtGins.
|
|
26803
26800
|
* All Rights Reserved.
|
|
@@ -26835,7 +26832,7 @@ function set_toolbar_busy($container, state, busy) {
|
|
|
26835
26832
|
* (only its own `plaintext` formatter escapes), so a record's text
|
|
26836
26833
|
* returned as a string is parsed as markup: `a<b and c>d` showed
|
|
26837
26834
|
* as `ad`, and a field holding `<img src=x onerror=...>` ran it in
|
|
26838
|
-
* the operator's browser
|
|
26835
|
+
* the operator's browser. Record
|
|
26839
26836
|
* data goes in as a TEXT NODE, and a cell built around it as DOM,
|
|
26840
26837
|
* never as an HTML string with the data interpolated.
|
|
26841
26838
|
*
|
|
@@ -29597,7 +29594,7 @@ function ac_new_row(gobj, event, kw, src) {
|
|
|
29597
29594
|
* What crosses the confirmation is the rows' IDENTITY, never their
|
|
29598
29595
|
* position: the view applies EV_TREEDB_NODE_* of every writer while the
|
|
29599
29596
|
* dialog is open, and a position names whatever row sits there when the
|
|
29600
|
-
* person answers -- with force:true
|
|
29597
|
+
* person answers -- with force:true.
|
|
29601
29598
|
************************************************************/
|
|
29602
29599
|
function ac_delete_rows(gobj, event, kw, src) {
|
|
29603
29600
|
if (refuse_if_readonly$2(gobj, event)) return -1;
|
|
@@ -29808,8 +29805,8 @@ function ac_files_read(gobj, event, kw, src) {
|
|
|
29808
29805
|
* open and BUSY, and the serial it waits for is taken here.
|
|
29809
29806
|
*
|
|
29810
29807
|
* A refused write used to close the form all the same and throw
|
|
29811
|
-
* away what was typed, although the README said it stayed open
|
|
29812
|
-
*
|
|
29808
|
+
* away what was typed, although the README said it stayed open:
|
|
29809
|
+
* the close was posted with the
|
|
29813
29810
|
* publish, before the backend had answered anything.
|
|
29814
29811
|
************************************************************/
|
|
29815
29812
|
function wait_for_write_answer(gobj) {
|
|
@@ -30981,6 +30978,28 @@ function apply_graphs_echo(live, saved, records, rec) {
|
|
|
30981
30978
|
delete saved[rec.topic];
|
|
30982
30979
|
}
|
|
30983
30980
|
}
|
|
30981
|
+
/***************************************************************
|
|
30982
|
+
* A write of one topic's arrangement did NOT land: the backend
|
|
30983
|
+
* refused it, the transport refused it on the way out, or there
|
|
30984
|
+
* was no session to send it on.
|
|
30985
|
+
*
|
|
30986
|
+
* saved {topic_name: properties} what the backend has
|
|
30987
|
+
* topic_name the topic of the refused record
|
|
30988
|
+
*
|
|
30989
|
+
* The view records a write as saved BEFORE it leaves, because
|
|
30990
|
+
* nothing answers it when it lands. So a refused one left the view
|
|
30991
|
+
* believing the backend held an arrangement it does not, and the
|
|
30992
|
+
* next Save found nothing to write. What the backend holds for the
|
|
30993
|
+
* topic is not known any more, so it is forgotten: the next Save
|
|
30994
|
+
* writes the topic again (plan_graph_saves()).
|
|
30995
|
+
*
|
|
30996
|
+
* Returns TRUE if there was something to forget.
|
|
30997
|
+
***************************************************************/
|
|
30998
|
+
function forget_refused_graphs_write(saved, topic_name) {
|
|
30999
|
+
if (!(0, _yuneta_gobj_js.is_object)(saved) || !topic_name || !Object.prototype.hasOwnProperty.call(saved, topic_name)) return false;
|
|
31000
|
+
delete saved[topic_name];
|
|
31001
|
+
return true;
|
|
31002
|
+
}
|
|
30984
31003
|
//#endregion
|
|
30985
31004
|
//#region src/treedb_node_label.js
|
|
30986
31005
|
/***********************************************************************
|
|
@@ -65788,6 +65807,28 @@ function ac_save_graph(gobj, event, kw, src) {
|
|
|
65788
65807
|
return 0;
|
|
65789
65808
|
}
|
|
65790
65809
|
/************************************************************
|
|
65810
|
+
* The host says a write of `__graphs__` did not land: the
|
|
65811
|
+
* backend refused it, the transport refused it on the way out,
|
|
65812
|
+
* or there was no session to send it on. kw: {topic}
|
|
65813
|
+
*
|
|
65814
|
+
* save_topic_graph_properties() recorded it as saved before it
|
|
65815
|
+
* left. Forgotten now, and the Save is lit again: the next Save
|
|
65816
|
+
* writes the topic again. Before, the view believed the backend
|
|
65817
|
+
* held the arrangement, and the next Save had nothing to write.
|
|
65818
|
+
************************************************************/
|
|
65819
|
+
function ac_graphs_write_refused(gobj, event, kw, src) {
|
|
65820
|
+
let priv = gobj.priv;
|
|
65821
|
+
let topic_name = kw && kw.topic;
|
|
65822
|
+
if (!topic_name) {
|
|
65823
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} names no topic`);
|
|
65824
|
+
return -1;
|
|
65825
|
+
}
|
|
65826
|
+
(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`);
|
|
65827
|
+
forget_refused_graphs_write(priv._saved_graph_properties, topic_name);
|
|
65828
|
+
if (priv.edit_mode) mark_graph_dirty(gobj);
|
|
65829
|
+
return 0;
|
|
65830
|
+
}
|
|
65831
|
+
/************************************************************
|
|
65791
65832
|
* Node created, from subscription
|
|
65792
65833
|
************************************************************/
|
|
65793
65834
|
function ac_node_created(gobj, event, kw, src) {
|
|
@@ -66855,6 +66896,11 @@ function create_gclass$4(gclass_name) {
|
|
|
66855
66896
|
ac_node_deleted,
|
|
66856
66897
|
null
|
|
66857
66898
|
],
|
|
66899
|
+
[
|
|
66900
|
+
"EV_GRAPHS_WRITE_REFUSED",
|
|
66901
|
+
ac_graphs_write_refused,
|
|
66902
|
+
null
|
|
66903
|
+
],
|
|
66858
66904
|
[
|
|
66859
66905
|
"EV_NODE_CLICK",
|
|
66860
66906
|
ac_node_click$2,
|
|
@@ -67108,6 +67154,7 @@ function create_gclass$4(gclass_name) {
|
|
|
67108
67154
|
["EV_NODE_CREATED", 0],
|
|
67109
67155
|
["EV_NODE_UPDATED", 0],
|
|
67110
67156
|
["EV_NODE_DELETED", 0],
|
|
67157
|
+
["EV_GRAPHS_WRITE_REFUSED", 0],
|
|
67111
67158
|
["EV_NODE_CLICK", 0],
|
|
67112
67159
|
["EV_EDGE_CLICK", 0],
|
|
67113
67160
|
["EV_NODE_CONTEXT_MENU", 0],
|
|
@@ -68284,7 +68331,7 @@ function treedb_update_node(gobj, treedb_name, topic_name, record, options) {
|
|
|
68284
68331
|
let priv = gobj.priv;
|
|
68285
68332
|
if (!priv.gobj_remote_yuno) {
|
|
68286
68333
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: No gobj_remote_yuno defined`);
|
|
68287
|
-
return;
|
|
68334
|
+
return -1;
|
|
68288
68335
|
}
|
|
68289
68336
|
let command = "update-node";
|
|
68290
68337
|
let kw = {
|
|
@@ -68296,7 +68343,11 @@ function treedb_update_node(gobj, treedb_name, topic_name, record, options) {
|
|
|
68296
68343
|
};
|
|
68297
68344
|
kw.__md_command__ = { topic_name };
|
|
68298
68345
|
let ret = (0, _yuneta_gobj_js.gobj_command)(priv.gobj_remote_yuno, command, kw, gobj);
|
|
68299
|
-
if (ret)
|
|
68346
|
+
if (ret) {
|
|
68347
|
+
(0, _yuneta_gobj_js.log_error)(ret);
|
|
68348
|
+
return -1;
|
|
68349
|
+
}
|
|
68350
|
+
return 0;
|
|
68300
68351
|
}
|
|
68301
68352
|
/************************************************************
|
|
68302
68353
|
* Command to remote service
|
|
@@ -68569,6 +68620,7 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
|
|
|
68569
68620
|
case "delete-node":
|
|
68570
68621
|
case "link-nodes":
|
|
68571
68622
|
case "unlink-nodes":
|
|
68623
|
+
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_dict)(gobj, kw_command, "record", {}, 0));
|
|
68572
68624
|
if (result >= 0 && (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_RECORD_WRITTEN", {
|
|
68573
68625
|
treedb_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "treedb_name", "", 0),
|
|
68574
68626
|
topic_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0),
|
|
@@ -68812,12 +68864,40 @@ function ac_create_node(gobj, event, kw, src) {
|
|
|
68812
68864
|
* Send to backend
|
|
68813
68865
|
********************************************/
|
|
68814
68866
|
function ac_update_node(gobj, event, kw, src) {
|
|
68815
|
-
let
|
|
68816
|
-
if (refuse_if_readonly$1(gobj, event)) return -1;
|
|
68817
|
-
let treedb_name = priv.treedb_name;
|
|
68867
|
+
let treedb_name = gobj.priv.treedb_name;
|
|
68818
68868
|
let topic_name = kw.topic_name;
|
|
68819
68869
|
let record = kw.record;
|
|
68820
|
-
|
|
68870
|
+
let options = kw.options || {};
|
|
68871
|
+
if (refuse_if_readonly$1(gobj, event)) {
|
|
68872
|
+
graphs_write_refused(gobj, topic_name, record);
|
|
68873
|
+
return -1;
|
|
68874
|
+
}
|
|
68875
|
+
if (topic_name === "__graphs__" && !is_connected(gobj)) {
|
|
68876
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no session, the arrangement was not sent`);
|
|
68877
|
+
graphs_write_refused(gobj, topic_name, record);
|
|
68878
|
+
return -1;
|
|
68879
|
+
}
|
|
68880
|
+
let ret = treedb_update_node(gobj, treedb_name, topic_name, record, options);
|
|
68881
|
+
if (ret < 0) graphs_write_refused(gobj, topic_name, record);
|
|
68882
|
+
return ret;
|
|
68883
|
+
}
|
|
68884
|
+
/************************************************************
|
|
68885
|
+
* A write of `__graphs__` did not land. The engine
|
|
68886
|
+
* (C_G6_NODES_TREE) took it for granted when it left -- nothing
|
|
68887
|
+
* answers it when it lands -- so it is told, and its next Save
|
|
68888
|
+
* writes the topic again. Other topics are the operator's data:
|
|
68889
|
+
* the answer's error says what happened to them.
|
|
68890
|
+
************************************************************/
|
|
68891
|
+
function graphs_write_refused(gobj, topic_name, record) {
|
|
68892
|
+
let priv = gobj.priv;
|
|
68893
|
+
if (topic_name !== "__graphs__") return;
|
|
68894
|
+
let topic = record && typeof record === "object" ? record.topic || record.id : "";
|
|
68895
|
+
if (!topic) {
|
|
68896
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: a refused __graphs__ write names no topic`);
|
|
68897
|
+
return;
|
|
68898
|
+
}
|
|
68899
|
+
if (!priv.gobj_nodes_tree) return;
|
|
68900
|
+
(0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_GRAPHS_WRITE_REFUSED", { topic }, gobj);
|
|
68821
68901
|
}
|
|
68822
68902
|
/********************************************
|
|
68823
68903
|
* Message from G6_nodes_tree
|
|
@@ -70473,9 +70553,8 @@ function register_c_yui_treedb_schema() {
|
|
|
70473
70553
|
* it, and that mark lived in the memory of the session only:
|
|
70474
70554
|
* a reload of the page, a reconnect or a refresh of the model
|
|
70475
70555
|
* lost the chip, the banner and the export warning while
|
|
70476
|
-
* __system__ still differed from the file in use
|
|
70477
|
-
*
|
|
70478
|
-
* C_TREEDB's `saved-schema` (`draft_changed`, by treedb) and
|
|
70556
|
+
* __system__ still differed from the file in use. The host
|
|
70557
|
+
* reads that difference from C_TREEDB's `saved-schema` (`draft_changed`, by treedb) and
|
|
70479
70558
|
* hands it here; the editor applies it to its model, in place
|
|
70480
70559
|
* of what the host said before.
|
|
70481
70560
|
*
|
|
@@ -72143,11 +72222,10 @@ function write_options(op) {
|
|
|
72143
72222
|
* AN EDIT IS A DRAFT. A write here moves no version and reaches no
|
|
72144
72223
|
* treedb: the host SAVES it (C_TREEDB's save-schema raises the
|
|
72145
72224
|
* topic_version of what changed and the schema_version, once) and
|
|
72146
|
-
* APPLIES it (apply-schema + a restart of the owning yuno).
|
|
72147
|
-
*
|
|
72148
|
-
*
|
|
72149
|
-
*
|
|
72150
|
-
* wrote and has not saved (EV_REFRESH forgets it: the view's own
|
|
72225
|
+
* APPLIES it (apply-schema + a restart of the owning yuno). If a
|
|
72226
|
+
* write here raised both versions, an edit half made would already
|
|
72227
|
+
* be the schema of the next start. The topic list marks what this
|
|
72228
|
+
* session wrote and has not saved (EV_REFRESH forgets it: the view's own
|
|
72151
72229
|
* Refresh button sends it, and a host may after a save -- the
|
|
72152
72230
|
* agent console's does not) and what the host says is not saved
|
|
72153
72231
|
* (EV_DRAFTS, replaced whole each time it is sent).
|
|
@@ -72213,6 +72291,7 @@ var HOOK_TOPICS = "topics";
|
|
|
72213
72291
|
var HOOK_COLS = "cols";
|
|
72214
72292
|
var DIAGRAM_SEG = "diagram";
|
|
72215
72293
|
var PURPOSE = "schema_editor";
|
|
72294
|
+
var DIALOGS_THAT_READ_NOTHING = ["SCHEMA_EXPORT_DIALOG", "SCHEMA_REPORT_DIALOG"];
|
|
72216
72295
|
/***************************************************************
|
|
72217
72296
|
* Attrs
|
|
72218
72297
|
***************************************************************/
|
|
@@ -72245,6 +72324,7 @@ var PRIVATE_DATA$1 = {
|
|
|
72245
72324
|
diagram_gobj: null,
|
|
72246
72325
|
dialog: null,
|
|
72247
72326
|
dialog_gen: 0,
|
|
72327
|
+
dialog_kind: "",
|
|
72248
72328
|
save_queue: null,
|
|
72249
72329
|
save_return: "",
|
|
72250
72330
|
save_wrote: false,
|
|
@@ -72413,9 +72493,9 @@ function refuse_if_readonly(gobj, event) {
|
|
|
72413
72493
|
* dumped by the machine trace).
|
|
72414
72494
|
*
|
|
72415
72495
|
* Refused, and said. A column form sends every field it shows, so
|
|
72416
|
-
* its Save after a reload wrote the OLD record over the newer one
|
|
72417
|
-
*
|
|
72418
|
-
*
|
|
72496
|
+
* its Save after a reload wrote the OLD record over the newer one;
|
|
72497
|
+
* a form whose column the reload removed answered "names no column"
|
|
72498
|
+
* for ever. end_load()
|
|
72419
72499
|
* closes such a dialog when the load lands; this is the same rule
|
|
72420
72500
|
* for whatever arrives anyway -- a stale screen, a confirmation
|
|
72421
72501
|
* that was up, a keyboard.
|
|
@@ -72435,8 +72515,7 @@ function built_on_a_replaced_model(gobj, event, kw) {
|
|
|
72435
72515
|
* the model shown is kept, and it may be older than the store.
|
|
72436
72516
|
* The session is up, so no reconnect will ask for it again -- it
|
|
72437
72517
|
* was owed for as long as the session lasted, and a form opened
|
|
72438
|
-
* on that model wrote every field of it over the newer record
|
|
72439
|
-
* (fifth independent review; A3 of the fourth, by another path).
|
|
72518
|
+
* on that model wrote every field of it over the newer record.
|
|
72440
72519
|
*
|
|
72441
72520
|
* So the operator's NEXT action asks it. An edit -- a form, a
|
|
72442
72521
|
* write, a confirmation, what reads the model whole (check,
|
|
@@ -72486,7 +72565,7 @@ function reload_after_move(gobj) {
|
|
|
72486
72565
|
* none of the actions of a screen, so the screen it replaces goes
|
|
72487
72566
|
* and the toolbar stops answering: left up, a click on a card, on
|
|
72488
72567
|
* Back or on the drawing answered "Event NOT DEFINED in state
|
|
72489
|
-
* ST_LOADING" and was lost
|
|
72568
|
+
* ST_LOADING" and was lost. A dialog
|
|
72490
72569
|
* left open is answered in ST_LOADING instead (ac_wait_for_the_load),
|
|
72491
72570
|
* and a load that LANDS closes it (end_load()): it was built on the
|
|
72492
72571
|
* model the load replaced, and its Save sends every field it shows.
|
|
@@ -73706,6 +73785,7 @@ function close_dialog(gobj) {
|
|
|
73706
73785
|
if (!priv.dialog) return;
|
|
73707
73786
|
let dialog = priv.dialog;
|
|
73708
73787
|
priv.dialog = null;
|
|
73788
|
+
priv.dialog_kind = "";
|
|
73709
73789
|
priv.export_view = null;
|
|
73710
73790
|
try {
|
|
73711
73791
|
dialog.close();
|
|
@@ -73717,6 +73797,7 @@ function open_dialog(gobj, $content, title, logical, title_prefix) {
|
|
|
73717
73797
|
let priv = gobj.priv;
|
|
73718
73798
|
close_dialog(gobj);
|
|
73719
73799
|
priv.dialog_gen = priv.model_gen;
|
|
73800
|
+
priv.dialog_kind = logical;
|
|
73720
73801
|
priv.dialog = yui_shell_show_modal(yui_shell_of(gobj), $content, {
|
|
73721
73802
|
dialog: true,
|
|
73722
73803
|
title,
|
|
@@ -73725,6 +73806,7 @@ function open_dialog(gobj, $content, title, logical, title_prefix) {
|
|
|
73725
73806
|
t: i18next.t,
|
|
73726
73807
|
on_close: () => {
|
|
73727
73808
|
priv.dialog = null;
|
|
73809
|
+
priv.dialog_kind = "";
|
|
73728
73810
|
priv.export_view = null;
|
|
73729
73811
|
}
|
|
73730
73812
|
});
|
|
@@ -74919,11 +75001,11 @@ function transport_in_session(gobj) {
|
|
|
74919
75001
|
* The state is part of the question, and that is only true
|
|
74920
75002
|
* because NOTHING moves the editor out of ST_LOADING or ST_SAVING
|
|
74921
75003
|
* but the end of what is in flight: a position the host sends
|
|
74922
|
-
* meanwhile waits in `pending_seg` (ac_show()).
|
|
74923
|
-
*
|
|
74924
|
-
*
|
|
74925
|
-
*
|
|
74926
|
-
*
|
|
75004
|
+
* meanwhile waits in `pending_seg` (ac_show()). If EV_SHOW moved a
|
|
75005
|
+
* RELOAD out of ST_LOADING, every answer of it would be "for a load
|
|
75006
|
+
* that is over": the records it had emptied would stay empty, and
|
|
75007
|
+
* the next write would patch them into a model with no treedb at
|
|
75008
|
+
* all.
|
|
74927
75009
|
***************************************************************/
|
|
74928
75010
|
function is_current_load(gobj, md) {
|
|
74929
75011
|
return (0, _yuneta_gobj_js.gobj_current_state)(gobj) === "ST_LOADING" && (0, _yuneta_gobj_js.kw_get_int)(gobj, md, "round", 0, 0) === gobj.priv.load_round;
|
|
@@ -75129,10 +75211,59 @@ function position_seg(gobj) {
|
|
|
75129
75211
|
* ...and the same in reverse. A tail naming a treedb or a topic
|
|
75130
75212
|
* the store does not have lands one level up rather than on an
|
|
75131
75213
|
* empty screen: a shared link outlives the schema it points at.
|
|
75214
|
+
*
|
|
75215
|
+
* Every position the HOST sends comes through here, at once
|
|
75216
|
+
* (ac_show()) or when what was in flight ends (end_load(),
|
|
75217
|
+
* end_writes()). A move to another position closes the dialog of
|
|
75218
|
+
* the screen the editor left (close_dialog_left_behind()).
|
|
75132
75219
|
***************************************************************/
|
|
75133
75220
|
function apply_seg(gobj, seg) {
|
|
75221
|
+
let before = position_seg(gobj);
|
|
75134
75222
|
let pos = seg_position(seg);
|
|
75135
|
-
|
|
75223
|
+
let ret = go(gobj, pos.treedb_id, pos.topic_name, pos.diagram, false);
|
|
75224
|
+
if (position_seg(gobj) !== before) close_dialog_left_behind(gobj);
|
|
75225
|
+
return ret;
|
|
75226
|
+
}
|
|
75227
|
+
/***************************************************************
|
|
75228
|
+
* The host moved the editor while a dialog was up. C_YUI_SHELL
|
|
75229
|
+
* keeps the overlays open on a move that changes only the subpath
|
|
75230
|
+
* (a url typed in, a link), so the dialog outlives its screen.
|
|
75231
|
+
*
|
|
75232
|
+
* A form, the import and the orphans send events that only the
|
|
75233
|
+
* screen they were opened from declares, and they name their
|
|
75234
|
+
* topic under the treedb open at the time. Left up on another
|
|
75235
|
+
* screen, their Save answered "Event NOT DEFINED" and the edit was
|
|
75236
|
+
* lost with no word. So the dialog is closed and the operator told.
|
|
75237
|
+
* The import plan goes with its dialog: it was computed for the
|
|
75238
|
+
* treedb the editor left.
|
|
75239
|
+
*
|
|
75240
|
+
* The export and the check stay: they show the texts they were
|
|
75241
|
+
* opened with, and what they send is legal in every state.
|
|
75242
|
+
***************************************************************/
|
|
75243
|
+
function close_dialog_left_behind(gobj) {
|
|
75244
|
+
let priv = gobj.priv;
|
|
75245
|
+
if (!priv.dialog || DIALOGS_THAT_READ_NOTHING.includes(priv.dialog_kind)) return;
|
|
75246
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: the host moved the view while the dialog ${priv.dialog_kind} was open: closed`);
|
|
75247
|
+
close_dialog(gobj);
|
|
75248
|
+
forget_import_plan(gobj);
|
|
75249
|
+
yui_shell_show_error(yui_shell_of(gobj), "the view moved: open the dialog again", { t: i18next.t });
|
|
75250
|
+
}
|
|
75251
|
+
/***************************************************************
|
|
75252
|
+
* A confirmation answered on another screen than the one it was
|
|
75253
|
+
* asked from. A confirmation is a shell modal, so a move sent by
|
|
75254
|
+
* the host does not close it. It names its topic and column, and
|
|
75255
|
+
* the actions look them up under the treedb open NOW: a Yes after
|
|
75256
|
+
* a move to another treedb deleted the topic or column of the same
|
|
75257
|
+
* name THERE.
|
|
75258
|
+
*
|
|
75259
|
+
* Refused, and said. A kw with no `seg` stamp is not a
|
|
75260
|
+
* confirmation's and is not asked.
|
|
75261
|
+
***************************************************************/
|
|
75262
|
+
function asked_on_another_screen(gobj, event, kw) {
|
|
75263
|
+
if (!kw || kw.seg === void 0 || kw.seg === position_seg(gobj)) return false;
|
|
75264
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} refused, it was asked on '${kw.seg}' and the view is on '${position_seg(gobj)}'`);
|
|
75265
|
+
yui_shell_show_error(yui_shell_of(gobj), "the view moved: open the dialog again", { t: i18next.t });
|
|
75266
|
+
return true;
|
|
75136
75267
|
}
|
|
75137
75268
|
function seg_position(seg) {
|
|
75138
75269
|
let parts = String(seg || "").split("/").filter((x) => x.length > 0);
|
|
@@ -75308,8 +75439,7 @@ function late_write_done(gobj, command, topic_name, data) {
|
|
|
75308
75439
|
* The fkey is read with parse_fkey_ref(), because the store answers
|
|
75309
75440
|
* in list_dict -- `[{topic_name, id, hook_name}]` -- and not in the
|
|
75310
75441
|
* `topics^<topic id>^cols` strings this view writes. Split as a
|
|
75311
|
-
* string, every production answer marked nothing
|
|
75312
|
-
* review, probe C).
|
|
75442
|
+
* string, every production answer marked nothing.
|
|
75313
75443
|
***************************************************************/
|
|
75314
75444
|
function mark_written_record(gobj, topic_name, record) {
|
|
75315
75445
|
let priv = gobj.priv;
|
|
@@ -75366,7 +75496,7 @@ function ac_hide(gobj, event, kw, src) {
|
|
|
75366
75496
|
*
|
|
75367
75497
|
* Nothing else ends a load or a write the drop cut: their answers
|
|
75368
75498
|
* will never come, and waiting in ST_LOADING skipped the reload
|
|
75369
|
-
* itself
|
|
75499
|
+
* itself.
|
|
75370
75500
|
***************************************************************/
|
|
75371
75501
|
function ac_transport_state(gobj, event, kw, src) {
|
|
75372
75502
|
let priv = gobj.priv;
|
|
@@ -75405,12 +75535,11 @@ function ac_refresh$1(gobj, event, kw, src) {
|
|
|
75405
75535
|
* a model the answers in the air are about to replace.
|
|
75406
75536
|
*
|
|
75407
75537
|
* Refused, and SAID. Undeclared, it answered "Event NOT DEFINED
|
|
75408
|
-
* in state ST_LOADING" and the edit was gone with no word
|
|
75409
|
-
* independent review).
|
|
75538
|
+
* in state ST_LOADING" and the edit was gone with no word.
|
|
75410
75539
|
*
|
|
75411
75540
|
* And NOT "try again": the same Save, once the load was in, sent
|
|
75412
75541
|
* the form built on the old model -- every field of the old record
|
|
75413
|
-
* over the newer one
|
|
75542
|
+
* over the newer one. The load that
|
|
75414
75543
|
* lands closes such a dialog (end_load()); one that fails leaves it
|
|
75415
75544
|
* up, on the model it was built on.
|
|
75416
75545
|
***************************************************************/
|
|
@@ -75424,8 +75553,7 @@ function ac_wait_for_the_load(gobj, event, kw, src) {
|
|
|
75424
75553
|
* reload landed on zero treedbs while it was up) or ST_IDLE (no
|
|
75425
75554
|
* model). A confirmation is a shell modal, not this view's dialog,
|
|
75426
75555
|
* so the load that lands does not close it, and its Yes arrives
|
|
75427
|
-
* anyway. Undeclared, it answered "Event NOT DEFINED"
|
|
75428
|
-
* independent review).
|
|
75556
|
+
* anyway. Undeclared, it answered "Event NOT DEFINED".
|
|
75429
75557
|
*
|
|
75430
75558
|
* Refused with the stamp's own words: whatever it was decided on
|
|
75431
75559
|
* is not on screen any more.
|
|
@@ -75441,13 +75569,12 @@ function ac_confirmed_on_nothing(gobj, event, kw, src) {
|
|
|
75441
75569
|
* topics hold a draft in __system__ that is not saved (C_TREEDB's
|
|
75442
75570
|
* saved-schema, `draft_changed`). The mark of a write lived in this
|
|
75443
75571
|
* session's memory only, so a reload of the page, a reconnect or a
|
|
75444
|
-
* refresh showed no draft while __system__ still differed
|
|
75445
|
-
* the 2026-09-22 review).
|
|
75572
|
+
* refresh showed no draft while __system__ still differed.
|
|
75446
75573
|
*
|
|
75447
75574
|
* REPLACES what the host said before -- the host is the truth after
|
|
75448
75575
|
* a reload, and a Save is exactly the host saying "none any more".
|
|
75449
75576
|
* It only ever added, and a topic stayed a draft after the Save that
|
|
75450
|
-
* published it
|
|
75577
|
+
* published it. What this session wrote
|
|
75451
75578
|
* stays marked: it is kept apart (see topic_is_draft()).
|
|
75452
75579
|
***************************************************************/
|
|
75453
75580
|
function ac_drafts(gobj, event, kw, src) {
|
|
@@ -75504,7 +75631,10 @@ function ac_show_orphans(gobj, event, kw, src) {
|
|
|
75504
75631
|
* to feed.
|
|
75505
75632
|
***************************************************************/
|
|
75506
75633
|
function confirm_then(gobj, message, detail, kw) {
|
|
75507
|
-
kw = Object.assign({
|
|
75634
|
+
kw = Object.assign({
|
|
75635
|
+
model_gen: gobj.priv.model_gen,
|
|
75636
|
+
seg: position_seg(gobj)
|
|
75637
|
+
}, kw);
|
|
75508
75638
|
yui_shell_confirm_danger(yui_shell_of(gobj), message, {
|
|
75509
75639
|
t: i18next.t,
|
|
75510
75640
|
detail,
|
|
@@ -75890,6 +76020,7 @@ function ac_confirmed(gobj, event, kw, src) {
|
|
|
75890
76020
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75891
76021
|
if (reload_first(gobj, event)) return -1;
|
|
75892
76022
|
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
76023
|
+
if (asked_on_another_screen(gobj, event, kw)) return -1;
|
|
75893
76024
|
if (kw.what === "import") return run_import(gobj);
|
|
75894
76025
|
if (kw.what === "topic") {
|
|
75895
76026
|
let topic = find_topic(priv.model, priv.treedb_id, kw.topic);
|