@yuneta/gobj-ui 7.25.5 → 7.25.7
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 +35 -0
- package/dist/gobj-ui.cjs.js +243 -21
- package/dist/gobj-ui.es.js +243 -21
- package/package.json +1 -1
- package/src/c_yui_schema_editor.js +274 -23
- package/src/schema_editor_transport.wiring.test.js +457 -0
- package/src/shell_modals.js +32 -4
- package/src/shell_toast_once.test.js +64 -0
package/README.md
CHANGED
|
@@ -2154,6 +2154,41 @@ else.
|
|
|
2154
2154
|
- In: `EV_SHOW` (`{subpath}` — the tail it owns is `<treedb>[/<topic>]` or
|
|
2155
2155
|
`<treedb>/diagram`), `EV_HIDE`, `EV_TRANSPORT_STATE`, `EV_REFRESH`,
|
|
2156
2156
|
`EV_LANGUAGE_CHANGED`, `EV_MT_COMMAND_ANSWER`.
|
|
2157
|
+
- A **drop** of the transport — `EV_TRANSPORT_STATE {connected: false}`, or a
|
|
2158
|
+
failed answer that arrives while the transport is out of `ST_SESSION` — ends
|
|
2159
|
+
the load or the write it cut, and the model is asked again on the next
|
|
2160
|
+
`{connected: true}`. A write cut this way is shown as
|
|
2161
|
+
`the connection dropped during the write` (an i18n key the consumer's
|
|
2162
|
+
locales carry). Each request carries its round in `__md_command__`
|
|
2163
|
+
(`round` / `write`), so an answer of what the drop cut is ignored with a
|
|
2164
|
+
warning. The drop itself is logged ONCE; the failures a routing adapter
|
|
2165
|
+
settles for the same drop are that one event and are not logged again.
|
|
2166
|
+
- **Nothing moves the editor out of `ST_LOADING` or `ST_SAVING` but the end of
|
|
2167
|
+
what is in flight** (7.25.7). An `EV_SHOW` that arrives meanwhile waits, the
|
|
2168
|
+
last one wins, and it is applied when the load lands, fails or is cut, or
|
|
2169
|
+
when the write ends. 7.25.6 let it move a RELOAD out of `ST_LOADING`: every
|
|
2170
|
+
answer of that load was then "for a load that is over", and the next write
|
|
2171
|
+
patched the records the reload had emptied into a model with no treedb.
|
|
2172
|
+
With no model and no load, `EV_SHOW` keeps the position and stays in
|
|
2173
|
+
`ST_IDLE`; the next load goes there.
|
|
2174
|
+
|
|
2175
|
+
```js
|
|
2176
|
+
gobj_send_event(editor, "EV_REFRESH", {}, host); // ST_LOADING
|
|
2177
|
+
gobj_send_event(editor, "EV_SHOW", {subpath: "db"}, host); // waits
|
|
2178
|
+
// ... the three `nodes` answers land -> ST_TOPICS of `db`
|
|
2179
|
+
```
|
|
2180
|
+
- A write this view gave up on (a drop, a deadline) whose answer still says it
|
|
2181
|
+
was DONE makes the editor read the model again (at once, after the write in
|
|
2182
|
+
flight, or on the reconnect). Through a routing adapter that settled the
|
|
2183
|
+
write on its OWN deadline the late answer does not reach the view -- the
|
|
2184
|
+
adapter echoes a node event instead, which this view does not hear -- and
|
|
2185
|
+
Refresh is what reads the store.
|
|
2186
|
+
|
|
2187
|
+
```js
|
|
2188
|
+
// the host forwards its session edges; nothing else is needed
|
|
2189
|
+
gobj_send_event(editor, "EV_TRANSPORT_STATE", {connected: false}, host);
|
|
2190
|
+
gobj_send_event(editor, "EV_TRANSPORT_STATE", {connected: true}, host);
|
|
2191
|
+
```
|
|
2157
2192
|
- Out: `EV_POSITION_CHANGED` (`{subpath}` — the host writes the url; this view
|
|
2158
2193
|
navigates nothing itself), `EV_RECORD_WRITTEN` (whoever owns the Apply needs
|
|
2159
2194
|
to know the yuno has not re-read its schema yet), `EV_SCHEMA_CHECKED`
|
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -3025,6 +3025,14 @@ function maybe_apply_translator($node, opts) {
|
|
|
3025
3025
|
* Non-blocking, auto-dismiss after `opts.timeout` ms (default
|
|
3026
3026
|
* 5000). `opts.timeout = 0` disables auto-dismiss.
|
|
3027
3027
|
* Returns `{ close() }` so callers can dismiss programmatically.
|
|
3028
|
+
*
|
|
3029
|
+
* ONE toast per message on screen: a string message of the same
|
|
3030
|
+
* kind as a toast still showing is not stacked under it -- that
|
|
3031
|
+
* toast is kept, its time starts again, and its handle is
|
|
3032
|
+
* returned. One close of a transport settles every request it
|
|
3033
|
+
* cut, each view shows its failure, and the operator got a
|
|
3034
|
+
* column of identical "the connection dropped". A message built
|
|
3035
|
+
* of nodes is never merged: its text is not a key.
|
|
3028
3036
|
***************************************************************/
|
|
3029
3037
|
function show_notification(shell, kind, message, opts) {
|
|
3030
3038
|
let $layer = notification_layer(shell);
|
|
@@ -3032,6 +3040,13 @@ function show_notification(shell, kind, message, opts) {
|
|
|
3032
3040
|
(0, _yuneta_gobj_js.log_warning)("yui_shell_show_*: shell has no notification layer");
|
|
3033
3041
|
return { close: () => {} };
|
|
3034
3042
|
}
|
|
3043
|
+
let key = typeof message === "string" ? `${kind}\u0000${message}` : null;
|
|
3044
|
+
if (key !== null) {
|
|
3045
|
+
for (let $shown of Array.from($layer.children)) if ($shown.__toast_key__ === key && $shown.__toast__) {
|
|
3046
|
+
$shown.__toast__.restart();
|
|
3047
|
+
return $shown.__toast__.handle;
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3035
3050
|
let p_attrs = typeof message === "string" ? { i18n: message } : {};
|
|
3036
3051
|
let $note = (0, _yuneta_gobj_js.createElement2)([
|
|
3037
3052
|
"div",
|
|
@@ -3068,8 +3083,21 @@ function show_notification(shell, kind, message, opts) {
|
|
|
3068
3083
|
let $del = $note.querySelector(".delete");
|
|
3069
3084
|
if ($del) $del.addEventListener("click", close);
|
|
3070
3085
|
let timeout = opts && opts.timeout != null ? opts.timeout : 5e3;
|
|
3071
|
-
|
|
3072
|
-
|
|
3086
|
+
let restart = function() {
|
|
3087
|
+
if (timeout_id) {
|
|
3088
|
+
clearTimeout(timeout_id);
|
|
3089
|
+
timeout_id = null;
|
|
3090
|
+
}
|
|
3091
|
+
if (timeout > 0) timeout_id = setTimeout(close, timeout);
|
|
3092
|
+
};
|
|
3093
|
+
restart();
|
|
3094
|
+
let handle = { close };
|
|
3095
|
+
$note.__toast_key__ = key;
|
|
3096
|
+
$note.__toast__ = {
|
|
3097
|
+
handle,
|
|
3098
|
+
restart
|
|
3099
|
+
};
|
|
3100
|
+
return handle;
|
|
3073
3101
|
}
|
|
3074
3102
|
function yui_shell_show_info(shell, message, opts) {
|
|
3075
3103
|
return show_notification(shell, "info", message, opts);
|
|
@@ -72101,6 +72129,12 @@ function write_options(op) {
|
|
|
72101
72129
|
* `update-node` / `delete-node` on the treedb service, and it may
|
|
72102
72130
|
* be a routing adapter two hops away (the agent console's
|
|
72103
72131
|
* C_AGENT_TREEDB_LINK) — this view cannot tell, and must not.
|
|
72132
|
+
* A DROP of it (the host's EV_TRANSPORT_STATE, or a failure that
|
|
72133
|
+
* arrives while the transport is out of session) ends the load or
|
|
72134
|
+
* the write it cut, and the model is asked again when the session
|
|
72135
|
+
* is back. Every request carries its round (`round` for a load,
|
|
72136
|
+
* `write` for a write) in `__md_command__`, so an answer of what
|
|
72137
|
+
* was cut is ignored instead of counted in the next one.
|
|
72104
72138
|
*
|
|
72105
72139
|
* Copyright (c) 2026, ArtGins.
|
|
72106
72140
|
* All Rights Reserved.
|
|
@@ -72133,6 +72167,7 @@ var PRIVATE_DATA$1 = {
|
|
|
72133
72167
|
model: null,
|
|
72134
72168
|
pending: 0,
|
|
72135
72169
|
load_error: "",
|
|
72170
|
+
load_round: 0,
|
|
72136
72171
|
treedb_id: "",
|
|
72137
72172
|
topic_name: "",
|
|
72138
72173
|
diagram: false,
|
|
@@ -72146,7 +72181,12 @@ var PRIVATE_DATA$1 = {
|
|
|
72146
72181
|
save_queue: null,
|
|
72147
72182
|
save_return: "",
|
|
72148
72183
|
save_wrote: false,
|
|
72184
|
+
write_tag: 0,
|
|
72149
72185
|
connected: false,
|
|
72186
|
+
reload_on_open: false,
|
|
72187
|
+
dropped_round: 0,
|
|
72188
|
+
dropped_write: 0,
|
|
72189
|
+
reload_after_write: false,
|
|
72150
72190
|
pending_seg: null,
|
|
72151
72191
|
import_plan: null,
|
|
72152
72192
|
import_pane: null,
|
|
@@ -72317,6 +72357,7 @@ function request_model(gobj) {
|
|
|
72317
72357
|
};
|
|
72318
72358
|
priv.load_error = "";
|
|
72319
72359
|
priv.pending = 0;
|
|
72360
|
+
priv.load_round++;
|
|
72320
72361
|
(0, _yuneta_gobj_js.gobj_change_state)(gobj, "ST_LOADING");
|
|
72321
72362
|
show_notice(gobj, "loading the schemas");
|
|
72322
72363
|
for (let topic_name of [
|
|
@@ -72326,7 +72367,7 @@ function request_model(gobj) {
|
|
|
72326
72367
|
]) if (remote_command(gobj, "nodes", {
|
|
72327
72368
|
topic_name,
|
|
72328
72369
|
options: { list_dict: true }
|
|
72329
|
-
}) === 0) priv.pending++;
|
|
72370
|
+
}, { round: priv.load_round }) === 0) priv.pending++;
|
|
72330
72371
|
if (priv.pending === 0) {
|
|
72331
72372
|
priv.load_error = (0, i18next.t)("cannot reach the treedb");
|
|
72332
72373
|
(0, _yuneta_gobj_js.gobj_change_state)(gobj, "ST_IDLE");
|
|
@@ -72344,7 +72385,7 @@ function request_model(gobj) {
|
|
|
72344
72385
|
* answer says which topic it is about, since the command is
|
|
72345
72386
|
* `nodes` for all three.
|
|
72346
72387
|
***************************************************************/
|
|
72347
|
-
function remote_command(gobj, command, kw) {
|
|
72388
|
+
function remote_command(gobj, command, kw, tag) {
|
|
72348
72389
|
let remote = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(gobj, "gobj_remote_yuno");
|
|
72349
72390
|
let treedb_name = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "treedb_name");
|
|
72350
72391
|
if (!remote) {
|
|
@@ -72355,11 +72396,11 @@ function remote_command(gobj, command, kw) {
|
|
|
72355
72396
|
service: treedb_name,
|
|
72356
72397
|
treedb_name
|
|
72357
72398
|
}, kw || {});
|
|
72358
|
-
full_kw.__md_command__ = {
|
|
72399
|
+
full_kw.__md_command__ = Object.assign({
|
|
72359
72400
|
purpose: PURPOSE,
|
|
72360
72401
|
topic_name: kw && kw.topic_name || "",
|
|
72361
72402
|
record_id: kw && kw.record_id || ""
|
|
72362
|
-
};
|
|
72403
|
+
}, tag || {});
|
|
72363
72404
|
delete full_kw.record_id;
|
|
72364
72405
|
let ret = (0, _yuneta_gobj_js.gobj_command)(remote, command, full_kw, gobj);
|
|
72365
72406
|
if (ret) {
|
|
@@ -74590,12 +74631,92 @@ function run_next_write(gobj) {
|
|
|
74590
74631
|
let write = priv.save_queue[0];
|
|
74591
74632
|
let command = write_command(write.op);
|
|
74592
74633
|
let options = write_options(write.op);
|
|
74634
|
+
priv.write_tag++;
|
|
74593
74635
|
if (remote_command(gobj, command, {
|
|
74594
74636
|
topic_name: write.topic_name,
|
|
74595
74637
|
record: write.record,
|
|
74596
74638
|
options,
|
|
74597
74639
|
record_id: write.record.id || ""
|
|
74598
|
-
}) < 0) return end_writes(gobj, (0, i18next.t)("cannot reach the treedb"));
|
|
74640
|
+
}, { write: priv.write_tag }) < 0) return end_writes(gobj, (0, i18next.t)("cannot reach the treedb"));
|
|
74641
|
+
return 0;
|
|
74642
|
+
}
|
|
74643
|
+
/***************************************************************
|
|
74644
|
+
* Does the transport say it is in session? The state the library
|
|
74645
|
+
* reads off every transport (C_IEVENT_CLI and the routing adapters
|
|
74646
|
+
* name it the same).
|
|
74647
|
+
***************************************************************/
|
|
74648
|
+
function transport_in_session(gobj) {
|
|
74649
|
+
let remote = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(gobj, "gobj_remote_yuno");
|
|
74650
|
+
return !!remote && (0, _yuneta_gobj_js.gobj_current_state)(remote) === "ST_SESSION";
|
|
74651
|
+
}
|
|
74652
|
+
/***************************************************************
|
|
74653
|
+
* Is this answer of the load in flight, or of the write in
|
|
74654
|
+
* flight? Each request carries its round in `__md_command__`, and
|
|
74655
|
+
* one the drop abandoned (or a deadline settled) can still come
|
|
74656
|
+
* back: counted, it ended the next load with the old data or
|
|
74657
|
+
* moved the next write's queue.
|
|
74658
|
+
*
|
|
74659
|
+
* The state is part of the question, and that is only true
|
|
74660
|
+
* because NOTHING moves the editor out of ST_LOADING or ST_SAVING
|
|
74661
|
+
* but the end of what is in flight: a position the host sends
|
|
74662
|
+
* meanwhile waits in `pending_seg` (ac_show()). 7.25.6 let EV_SHOW
|
|
74663
|
+
* move a RELOAD out of ST_LOADING, and every answer of it was then
|
|
74664
|
+
* "for a load that is over": the records it had emptied stayed
|
|
74665
|
+
* empty, and the next write patched them into a model with no
|
|
74666
|
+
* treedb at all.
|
|
74667
|
+
***************************************************************/
|
|
74668
|
+
function is_current_load(gobj, md) {
|
|
74669
|
+
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;
|
|
74670
|
+
}
|
|
74671
|
+
function is_current_write(gobj, md) {
|
|
74672
|
+
return (0, _yuneta_gobj_js.gobj_current_state)(gobj) === "ST_SAVING" && (0, _yuneta_gobj_js.kw_get_int)(gobj, md, "write", 0, 0) === gobj.priv.write_tag;
|
|
74673
|
+
}
|
|
74674
|
+
/***************************************************************
|
|
74675
|
+
* The transport dropped under a load or a write: its answers
|
|
74676
|
+
* will never come. The load goes back to the screen it replaced
|
|
74677
|
+
* (or to "not connected" when there was none), the write ends
|
|
74678
|
+
* with the drop said -- whether it landed is unknown -- and both
|
|
74679
|
+
* mark the model to be asked again when the session is back.
|
|
74680
|
+
* Bumping the round makes an answer of what was cut stale.
|
|
74681
|
+
***************************************************************/
|
|
74682
|
+
function transport_dropped(gobj) {
|
|
74683
|
+
let priv = gobj.priv;
|
|
74684
|
+
let state = (0, _yuneta_gobj_js.gobj_current_state)(gobj);
|
|
74685
|
+
priv.reload_on_open = true;
|
|
74686
|
+
if (state === "ST_SAVING") {
|
|
74687
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: the transport dropped during a write: the model is read again on the reconnect`);
|
|
74688
|
+
priv.dropped_write = priv.write_tag;
|
|
74689
|
+
priv.write_tag++;
|
|
74690
|
+
return end_writes(gobj, "the connection dropped during the write");
|
|
74691
|
+
}
|
|
74692
|
+
if (state === "ST_LOADING") {
|
|
74693
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: the transport dropped during the load: the model is read again on the reconnect`);
|
|
74694
|
+
priv.dropped_round = priv.load_round;
|
|
74695
|
+
priv.load_round++;
|
|
74696
|
+
priv.pending = 0;
|
|
74697
|
+
priv.load_error = "";
|
|
74698
|
+
return end_load(gobj);
|
|
74699
|
+
}
|
|
74700
|
+
return 0;
|
|
74701
|
+
}
|
|
74702
|
+
/***************************************************************
|
|
74703
|
+
* A load is over -- landed, failed or cut -- and the editor goes
|
|
74704
|
+
* where the operator is: the position the host sent while it was
|
|
74705
|
+
* in flight (ac_show() kept it), or the one it had. Without a
|
|
74706
|
+
* model there is no screen to go to: the position is kept for the
|
|
74707
|
+
* next load, and the editor says why it is empty.
|
|
74708
|
+
***************************************************************/
|
|
74709
|
+
function end_load(gobj) {
|
|
74710
|
+
let priv = gobj.priv;
|
|
74711
|
+
let seg = priv.pending_seg;
|
|
74712
|
+
priv.pending_seg = null;
|
|
74713
|
+
if (priv.model) {
|
|
74714
|
+
if (seg !== null) return apply_seg(gobj, seg);
|
|
74715
|
+
return go(gobj, priv.treedb_id, priv.topic_name, priv.diagram, false);
|
|
74716
|
+
}
|
|
74717
|
+
if (seg !== null) adopt_seg(gobj, seg);
|
|
74718
|
+
(0, _yuneta_gobj_js.gobj_change_state)(gobj, "ST_IDLE");
|
|
74719
|
+
render(gobj);
|
|
74599
74720
|
return 0;
|
|
74600
74721
|
}
|
|
74601
74722
|
/***************************************************************
|
|
@@ -74618,7 +74739,7 @@ function end_writes(gobj, error) {
|
|
|
74618
74739
|
apply_seg(gobj, seg);
|
|
74619
74740
|
if (priv.save_wrote) (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_RECORD_WRITTEN", { treedb_name: (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "treedb_name") });
|
|
74620
74741
|
priv.save_wrote = false;
|
|
74621
|
-
return
|
|
74742
|
+
return reload_if_owed(gobj);
|
|
74622
74743
|
}
|
|
74623
74744
|
}
|
|
74624
74745
|
if (error) yui_shell_show_error(yui_shell_of(gobj), error, { t: i18next.t });
|
|
@@ -74626,9 +74747,25 @@ function end_writes(gobj, error) {
|
|
|
74626
74747
|
priv.save_wrote = false;
|
|
74627
74748
|
render(gobj);
|
|
74628
74749
|
publish_check(gobj);
|
|
74750
|
+
reload_if_owed(gobj);
|
|
74629
74751
|
return error ? -1 : 0;
|
|
74630
74752
|
}
|
|
74631
74753
|
/***************************************************************
|
|
74754
|
+
* A write given up earlier turned out DONE while another one was
|
|
74755
|
+
* in flight (see ac_mt_command_answer()): the model is read again
|
|
74756
|
+
* now that nothing is.
|
|
74757
|
+
***************************************************************/
|
|
74758
|
+
function reload_if_owed(gobj) {
|
|
74759
|
+
let priv = gobj.priv;
|
|
74760
|
+
if (!priv.reload_after_write) return 0;
|
|
74761
|
+
priv.reload_after_write = false;
|
|
74762
|
+
if (!transport_in_session(gobj)) {
|
|
74763
|
+
priv.reload_on_open = true;
|
|
74764
|
+
return 0;
|
|
74765
|
+
}
|
|
74766
|
+
return request_model(gobj);
|
|
74767
|
+
}
|
|
74768
|
+
/***************************************************************
|
|
74632
74769
|
* The record a column form produces.
|
|
74633
74770
|
*
|
|
74634
74771
|
* Everything the store needs and the operator did not type is
|
|
@@ -74696,7 +74833,7 @@ function go(gobj, treedb_id, topic_name, diagram, mirror) {
|
|
|
74696
74833
|
priv.topic_name = topic_name || "";
|
|
74697
74834
|
priv.diagram = !!diagram;
|
|
74698
74835
|
let state = "ST_TREEDBS";
|
|
74699
|
-
if (!priv.model) state = "
|
|
74836
|
+
if (!priv.model) state = "ST_IDLE";
|
|
74700
74837
|
else if (priv.model.treedbs.length === 0) state = "ST_EMPTY";
|
|
74701
74838
|
else if (priv.treedb_id && priv.diagram) state = "ST_DIAGRAM";
|
|
74702
74839
|
else if (priv.treedb_id && priv.topic_name) state = "ST_COLUMNS";
|
|
@@ -74723,12 +74860,39 @@ function position_seg(gobj) {
|
|
|
74723
74860
|
* empty screen: a shared link outlives the schema it points at.
|
|
74724
74861
|
***************************************************************/
|
|
74725
74862
|
function apply_seg(gobj, seg) {
|
|
74863
|
+
let pos = seg_position(seg);
|
|
74864
|
+
return go(gobj, pos.treedb_id, pos.topic_name, pos.diagram, false);
|
|
74865
|
+
}
|
|
74866
|
+
function seg_position(seg) {
|
|
74726
74867
|
let parts = String(seg || "").split("/").filter((x) => x.length > 0);
|
|
74727
74868
|
let treedb_id = parts[0] || "";
|
|
74728
74869
|
let tail = parts[1] || "";
|
|
74729
|
-
if (!treedb_id) return
|
|
74730
|
-
|
|
74731
|
-
|
|
74870
|
+
if (!treedb_id) return {
|
|
74871
|
+
treedb_id: "",
|
|
74872
|
+
topic_name: "",
|
|
74873
|
+
diagram: false
|
|
74874
|
+
};
|
|
74875
|
+
if (tail === DIAGRAM_SEG) return {
|
|
74876
|
+
treedb_id,
|
|
74877
|
+
topic_name: "",
|
|
74878
|
+
diagram: true
|
|
74879
|
+
};
|
|
74880
|
+
return {
|
|
74881
|
+
treedb_id,
|
|
74882
|
+
topic_name: tail,
|
|
74883
|
+
diagram: false
|
|
74884
|
+
};
|
|
74885
|
+
}
|
|
74886
|
+
/***************************************************************
|
|
74887
|
+
* Where the operator is, taken WITHOUT a screen: there is no model
|
|
74888
|
+
* to draw it on yet, and the load that brings one goes there.
|
|
74889
|
+
***************************************************************/
|
|
74890
|
+
function adopt_seg(gobj, seg) {
|
|
74891
|
+
let priv = gobj.priv;
|
|
74892
|
+
let pos = seg_position(seg);
|
|
74893
|
+
priv.treedb_id = pos.treedb_id;
|
|
74894
|
+
priv.topic_name = pos.topic_name;
|
|
74895
|
+
priv.diagram = pos.diagram;
|
|
74732
74896
|
}
|
|
74733
74897
|
/***************************
|
|
74734
74898
|
* Actions
|
|
@@ -74750,25 +74914,39 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
74750
74914
|
let kw_command = (0, _yuneta_gobj_js.kw_get_dict)(gobj, __command__, "kw", {}, 0);
|
|
74751
74915
|
let md = (0, _yuneta_gobj_js.is_object)(kw_command.__md_command__) ? kw_command.__md_command__ : kw_command;
|
|
74752
74916
|
if ((0, _yuneta_gobj_js.kw_get_str)(gobj, md, "purpose", "", 0) !== PURPOSE) return 0;
|
|
74917
|
+
if (result < 0 && !transport_in_session(gobj) && ((0, _yuneta_gobj_js.gobj_current_state)(gobj) === "ST_LOADING" || (0, _yuneta_gobj_js.gobj_current_state)(gobj) === "ST_SAVING")) {
|
|
74918
|
+
if (command === "nodes" && is_current_load(gobj, md) || command !== "nodes" && is_current_write(gobj, md)) return transport_dropped(gobj);
|
|
74919
|
+
}
|
|
74753
74920
|
if (command === "nodes") {
|
|
74754
74921
|
let topic_name = (0, _yuneta_gobj_js.kw_get_str)(gobj, md, "topic_name", "", 0);
|
|
74922
|
+
if (!is_current_load(gobj, md)) {
|
|
74923
|
+
if (result < 0 && (0, _yuneta_gobj_js.kw_get_int)(gobj, md, "round", 0, 0) === priv.dropped_round) return 0;
|
|
74924
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: 'nodes' of '${topic_name}' answered for a load that is over: ignored`);
|
|
74925
|
+
return 0;
|
|
74926
|
+
}
|
|
74755
74927
|
priv.pending--;
|
|
74756
74928
|
if (result < 0) priv.load_error = comment || (0, i18next.t)("cannot load the schemas");
|
|
74757
74929
|
else if (priv.records && Array.isArray(priv.records[topic_name])) priv.records[topic_name] = Array.isArray(data) ? data : [];
|
|
74758
74930
|
if (priv.pending > 0) return 0;
|
|
74759
74931
|
if (priv.load_error) {
|
|
74760
74932
|
priv.model = null;
|
|
74761
|
-
|
|
74762
|
-
render(gobj);
|
|
74763
|
-
return 0;
|
|
74933
|
+
return end_load(gobj);
|
|
74764
74934
|
}
|
|
74765
74935
|
priv.order_undo = {};
|
|
74766
74936
|
build_model(gobj);
|
|
74767
74937
|
start_measuring(gobj);
|
|
74768
|
-
return
|
|
74938
|
+
return end_load(gobj);
|
|
74769
74939
|
}
|
|
74770
74940
|
if (command === "update-node" || command === "delete-node") {
|
|
74771
74941
|
let topic_name = (0, _yuneta_gobj_js.kw_get_str)(gobj, md, "topic_name", "", 0);
|
|
74942
|
+
if (!is_current_write(gobj, md)) {
|
|
74943
|
+
if (result < 0 && (0, _yuneta_gobj_js.kw_get_int)(gobj, md, "write", 0, 0) === priv.dropped_write) return 0;
|
|
74944
|
+
if (result < 0) {
|
|
74945
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: '${command}' of '${topic_name}' answered for a write that is over (result ${result}): ignored`);
|
|
74946
|
+
return 0;
|
|
74947
|
+
}
|
|
74948
|
+
return late_write_done(gobj, command, topic_name);
|
|
74949
|
+
}
|
|
74772
74950
|
if (result < 0) return end_writes(gobj, comment || (0, i18next.t)("the treedb refused the write"));
|
|
74773
74951
|
priv.save_wrote = true;
|
|
74774
74952
|
if (command === "delete-node") forget_record(gobj, topic_name, (0, _yuneta_gobj_js.kw_get_str)(gobj, md, "record_id", "", 0));
|
|
@@ -74793,6 +74971,35 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
74793
74971
|
return 0;
|
|
74794
74972
|
}
|
|
74795
74973
|
/***************************************************************
|
|
74974
|
+
* A write this view gave up on (a drop, a deadline) answers that
|
|
74975
|
+
* it was DONE: the store holds a change the model does not show.
|
|
74976
|
+
* The model is read again -- now, or when what is in flight ends,
|
|
74977
|
+
* or on the reconnect. A load in flight needs nothing: it was
|
|
74978
|
+
* asked after the write, on the same transport, and reads it.
|
|
74979
|
+
*
|
|
74980
|
+
* Only when the answer reaches this view. A routing adapter that
|
|
74981
|
+
* settled the write on its own deadline (gui_agent's
|
|
74982
|
+
* C_AGENT_TREEDB_LINK) does not deliver its late answer again --
|
|
74983
|
+
* the view was answered once, as failed -- and echoes the node
|
|
74984
|
+
* event instead, which this view does not hear: there, Refresh is
|
|
74985
|
+
* what reads the store.
|
|
74986
|
+
***************************************************************/
|
|
74987
|
+
function late_write_done(gobj, command, topic_name) {
|
|
74988
|
+
let priv = gobj.priv;
|
|
74989
|
+
let state = (0, _yuneta_gobj_js.gobj_current_state)(gobj);
|
|
74990
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: '${command}' of '${topic_name}' was given up, and it was DONE: the model is read again`);
|
|
74991
|
+
if (state === "ST_LOADING") return 0;
|
|
74992
|
+
if (state === "ST_SAVING") {
|
|
74993
|
+
priv.reload_after_write = true;
|
|
74994
|
+
return 0;
|
|
74995
|
+
}
|
|
74996
|
+
if (!transport_in_session(gobj)) {
|
|
74997
|
+
priv.reload_on_open = true;
|
|
74998
|
+
return 0;
|
|
74999
|
+
}
|
|
75000
|
+
return request_model(gobj);
|
|
75001
|
+
}
|
|
75002
|
+
/***************************************************************
|
|
74796
75003
|
* Remember which topic this write belongs to, which is what
|
|
74797
75004
|
* "its version still has to move" is asked about.
|
|
74798
75005
|
***************************************************************/
|
|
@@ -74812,7 +75019,8 @@ function mark_written(gobj, topic_name, record) {
|
|
|
74812
75019
|
function ac_show(gobj, event, kw, src) {
|
|
74813
75020
|
let priv = gobj.priv;
|
|
74814
75021
|
let seg = kw && kw.subpath || "";
|
|
74815
|
-
|
|
75022
|
+
let state = (0, _yuneta_gobj_js.gobj_current_state)(gobj);
|
|
75023
|
+
if (state === "ST_SAVING" || state === "ST_LOADING") {
|
|
74816
75024
|
priv.pending_seg = seg;
|
|
74817
75025
|
return 0;
|
|
74818
75026
|
}
|
|
@@ -74828,14 +75036,28 @@ function ac_hide(gobj, event, kw, src) {
|
|
|
74828
75036
|
return 0;
|
|
74829
75037
|
}
|
|
74830
75038
|
/***************************************************************
|
|
74831
|
-
* The session came up or went down. The model stays
|
|
74832
|
-
*
|
|
74833
|
-
*
|
|
75039
|
+
* The session came up or went down. The model stays -- a schema
|
|
75040
|
+
* does not change under you -- unless the drop cut a load or a
|
|
75041
|
+
* write (transport_dropped()): then it is asked again on the way
|
|
75042
|
+
* back, as it is when a first load had no transport to run on.
|
|
75043
|
+
*
|
|
75044
|
+
* Nothing else ends a load or a write the drop cut: their answers
|
|
75045
|
+
* will never come, and waiting in ST_LOADING skipped the reload
|
|
75046
|
+
* itself (M-1 of the independent review of 7.25.4).
|
|
74834
75047
|
***************************************************************/
|
|
74835
75048
|
function ac_transport_state(gobj, event, kw, src) {
|
|
74836
75049
|
let priv = gobj.priv;
|
|
75050
|
+
let state = (0, _yuneta_gobj_js.gobj_current_state)(gobj);
|
|
74837
75051
|
priv.connected = !!(kw && kw.connected);
|
|
74838
|
-
if (priv.connected
|
|
75052
|
+
if (!priv.connected) {
|
|
75053
|
+
if (state === "ST_LOADING" || state === "ST_SAVING") return transport_dropped(gobj);
|
|
75054
|
+
render_toolbar(gobj);
|
|
75055
|
+
return 0;
|
|
75056
|
+
}
|
|
75057
|
+
if ((!priv.model || priv.reload_on_open) && state !== "ST_LOADING" && state !== "ST_SAVING") {
|
|
75058
|
+
priv.reload_on_open = false;
|
|
75059
|
+
return request_model(gobj);
|
|
75060
|
+
}
|
|
74839
75061
|
render_toolbar(gobj);
|
|
74840
75062
|
return 0;
|
|
74841
75063
|
}
|