@yuneta/gobj-ui 7.25.7 → 7.25.8
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 +32 -1
- package/dist/gobj-ui.cjs.js +204 -75
- package/dist/gobj-ui.es.js +204 -75
- package/package.json +1 -1
- package/src/c_yui_schema_editor.js +186 -50
- package/src/schema_editor_reload.wiring.test.js +473 -0
- package/src/shell_modals.js +50 -29
- package/src/shell_toast_once.test.js +64 -3
package/dist/gobj-ui.es.js
CHANGED
|
@@ -3022,12 +3022,20 @@ function maybe_apply_translator($node, opts) {
|
|
|
3022
3022
|
* Returns `{ close() }` so callers can dismiss programmatically.
|
|
3023
3023
|
*
|
|
3024
3024
|
* ONE toast per message on screen: a string message of the same
|
|
3025
|
-
* kind as a toast still showing is not stacked under it
|
|
3026
|
-
*
|
|
3027
|
-
*
|
|
3028
|
-
*
|
|
3029
|
-
*
|
|
3030
|
-
*
|
|
3025
|
+
* kind as a toast still showing is not stacked under it. One
|
|
3026
|
+
* close of a transport settles every request it cut, each view
|
|
3027
|
+
* shows its failure, and the operator got a column of identical
|
|
3028
|
+
* "the connection dropped". A message built of nodes is never
|
|
3029
|
+
* merged: its text is not a key.
|
|
3030
|
+
*
|
|
3031
|
+
* A repeat is still a CALLER of its own: it gets its own handle
|
|
3032
|
+
* and its own time, and the toast stays while any caller holds
|
|
3033
|
+
* it -- until every handle is closed or has timed out. Handed the
|
|
3034
|
+
* first caller's handle and timer, a repeat asking `timeout: 0`
|
|
3035
|
+
* was dismissed on the first one's timer, and closing one
|
|
3036
|
+
* caller's handle closed a toast another was still showing
|
|
3037
|
+
* (third independent review). The operator's ✕ closes it for
|
|
3038
|
+
* everybody.
|
|
3031
3039
|
***************************************************************/
|
|
3032
3040
|
function show_notification(shell, kind, message, opts) {
|
|
3033
3041
|
let $layer = notification_layer(shell);
|
|
@@ -3035,12 +3043,10 @@ function show_notification(shell, kind, message, opts) {
|
|
|
3035
3043
|
log_warning("yui_shell_show_*: shell has no notification layer");
|
|
3036
3044
|
return { close: () => {} };
|
|
3037
3045
|
}
|
|
3046
|
+
let timeout = opts && opts.timeout != null ? opts.timeout : 5e3;
|
|
3038
3047
|
let key = typeof message === "string" ? `${kind}\u0000${message}` : null;
|
|
3039
3048
|
if (key !== null) {
|
|
3040
|
-
for (let $shown of Array.from($layer.children)) if ($shown.__toast_key__ === key && $shown.__toast__)
|
|
3041
|
-
$shown.__toast__.restart();
|
|
3042
|
-
return $shown.__toast__.handle;
|
|
3043
|
-
}
|
|
3049
|
+
for (let $shown of Array.from($layer.children)) if ($shown.__toast_key__ === key && $shown.__toast__) return $shown.__toast__.hold(timeout);
|
|
3044
3050
|
}
|
|
3045
3051
|
let p_attrs = typeof message === "string" ? { i18n: message } : {};
|
|
3046
3052
|
let $note = createElement2([
|
|
@@ -3064,35 +3070,38 @@ function show_notification(shell, kind, message, opts) {
|
|
|
3064
3070
|
]);
|
|
3065
3071
|
$layer.appendChild($note);
|
|
3066
3072
|
maybe_apply_translator($note, opts);
|
|
3067
|
-
let
|
|
3073
|
+
let holders = /* @__PURE__ */ new Set();
|
|
3068
3074
|
let closed = false;
|
|
3069
|
-
let
|
|
3075
|
+
let close_toast = function() {
|
|
3070
3076
|
if (closed) return;
|
|
3071
3077
|
closed = true;
|
|
3072
|
-
if (timeout_id) {
|
|
3073
|
-
clearTimeout(timeout_id);
|
|
3074
|
-
timeout_id = null;
|
|
3078
|
+
for (let holder of holders) if (holder.timeout_id) {
|
|
3079
|
+
clearTimeout(holder.timeout_id);
|
|
3080
|
+
holder.timeout_id = null;
|
|
3075
3081
|
}
|
|
3082
|
+
holders.clear();
|
|
3076
3083
|
if ($note.parentNode) $note.parentNode.removeChild($note);
|
|
3077
3084
|
};
|
|
3078
|
-
let
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3085
|
+
let hold = function(ms) {
|
|
3086
|
+
let holder = { timeout_id: null };
|
|
3087
|
+
let release = function() {
|
|
3088
|
+
if (!holders.has(holder)) return;
|
|
3089
|
+
if (holder.timeout_id) {
|
|
3090
|
+
clearTimeout(holder.timeout_id);
|
|
3091
|
+
holder.timeout_id = null;
|
|
3092
|
+
}
|
|
3093
|
+
holders.delete(holder);
|
|
3094
|
+
if (holders.size === 0) close_toast();
|
|
3095
|
+
};
|
|
3096
|
+
holders.add(holder);
|
|
3097
|
+
if (ms > 0) holder.timeout_id = setTimeout(release, ms);
|
|
3098
|
+
return { close: release };
|
|
3087
3099
|
};
|
|
3088
|
-
|
|
3089
|
-
|
|
3100
|
+
let $del = $note.querySelector(".delete");
|
|
3101
|
+
if ($del) $del.addEventListener("click", close_toast);
|
|
3090
3102
|
$note.__toast_key__ = key;
|
|
3091
|
-
$note.__toast__ = {
|
|
3092
|
-
|
|
3093
|
-
restart
|
|
3094
|
-
};
|
|
3095
|
-
return handle;
|
|
3103
|
+
$note.__toast__ = { hold };
|
|
3104
|
+
return hold(timeout);
|
|
3096
3105
|
}
|
|
3097
3106
|
function yui_shell_show_info(shell, message, opts) {
|
|
3098
3107
|
return show_notification(shell, "info", message, opts);
|
|
@@ -72163,6 +72172,7 @@ var PRIVATE_DATA$1 = {
|
|
|
72163
72172
|
pending: 0,
|
|
72164
72173
|
load_error: "",
|
|
72165
72174
|
load_round: 0,
|
|
72175
|
+
load_keeps_written: false,
|
|
72166
72176
|
treedb_id: "",
|
|
72167
72177
|
topic_name: "",
|
|
72168
72178
|
diagram: false,
|
|
@@ -72341,10 +72351,28 @@ function refuse_if_readonly(gobj, event) {
|
|
|
72341
72351
|
* schema set of the yuno is here: everything below — the
|
|
72342
72352
|
* drawing, the validation, the export — is computed from these
|
|
72343
72353
|
* and asks the backend nothing more.
|
|
72354
|
+
*
|
|
72355
|
+
* THE LOADING SCREEN IS DRAWN, not assumed. ST_LOADING declares
|
|
72356
|
+
* none of the actions of a screen, so the screen it replaces goes
|
|
72357
|
+
* and the toolbar stops answering: left up, a click on a card, on
|
|
72358
|
+
* Back or on the drawing answered "Event NOT DEFINED in state
|
|
72359
|
+
* ST_LOADING" and was lost (third independent review). A dialog
|
|
72360
|
+
* left open is answered in ST_LOADING instead (ac_wait_for_the_load).
|
|
72361
|
+
*
|
|
72362
|
+
* `keep_written`: a load the host did not ask for -- the reconnect,
|
|
72363
|
+
* a write that turned out done -- keeps what this session wrote.
|
|
72364
|
+
* Only the host's EV_REFRESH (a Save sends it) forgets it.
|
|
72365
|
+
*
|
|
72366
|
+
* A load that cannot leave WHOLE did not happen (out of session it
|
|
72367
|
+
* is not even asked): the records the model was built on are put
|
|
72368
|
+
* back (emptied, the next write patched them into a model with no
|
|
72369
|
+
* treedb), the round is spent so a request that did leave is
|
|
72370
|
+
* stale, and the session back asks again.
|
|
72344
72371
|
***************************************************************/
|
|
72345
|
-
function request_model(gobj) {
|
|
72372
|
+
function request_model(gobj, keep_written) {
|
|
72346
72373
|
let priv = gobj.priv;
|
|
72347
72374
|
if (!gobj_read_pointer_attr(gobj, "gobj_remote_yuno")) return -1;
|
|
72375
|
+
let previous = priv.records;
|
|
72348
72376
|
priv.records = {
|
|
72349
72377
|
treedbs: [],
|
|
72350
72378
|
topics: [],
|
|
@@ -72353,22 +72381,31 @@ function request_model(gobj) {
|
|
|
72353
72381
|
priv.load_error = "";
|
|
72354
72382
|
priv.pending = 0;
|
|
72355
72383
|
priv.load_round++;
|
|
72384
|
+
priv.load_keeps_written = !!keep_written;
|
|
72356
72385
|
gobj_change_state(gobj, "ST_LOADING");
|
|
72357
|
-
|
|
72358
|
-
|
|
72359
|
-
|
|
72360
|
-
|
|
72361
|
-
|
|
72362
|
-
|
|
72363
|
-
|
|
72364
|
-
|
|
72365
|
-
|
|
72366
|
-
|
|
72386
|
+
set_busy(gobj, false);
|
|
72387
|
+
render(gobj);
|
|
72388
|
+
let left = 0;
|
|
72389
|
+
if (transport_in_session(gobj)) {
|
|
72390
|
+
for (let topic_name of [
|
|
72391
|
+
T_TREEDBS,
|
|
72392
|
+
T_TOPICS,
|
|
72393
|
+
T_COLS
|
|
72394
|
+
]) if (remote_command(gobj, "nodes", {
|
|
72395
|
+
topic_name,
|
|
72396
|
+
options: { list_dict: true }
|
|
72397
|
+
}, { round: priv.load_round }) === 0) left++;
|
|
72398
|
+
}
|
|
72399
|
+
if (left < 3) {
|
|
72400
|
+
priv.records = previous;
|
|
72401
|
+
priv.load_round++;
|
|
72402
|
+
priv.reload_on_open = true;
|
|
72367
72403
|
priv.load_error = t("cannot reach the treedb");
|
|
72368
|
-
|
|
72369
|
-
|
|
72404
|
+
if (priv.model) yui_shell_show_error(yui_shell_of(gobj), "cannot reach the treedb", { t });
|
|
72405
|
+
end_load(gobj);
|
|
72370
72406
|
return -1;
|
|
72371
72407
|
}
|
|
72408
|
+
priv.pending = left;
|
|
72372
72409
|
return 0;
|
|
72373
72410
|
}
|
|
72374
72411
|
/***************************************************************
|
|
@@ -72431,15 +72468,19 @@ function build_model(gobj) {
|
|
|
72431
72468
|
* From here on, "did this session change it?" has an answer.
|
|
72432
72469
|
*
|
|
72433
72470
|
* Called ONLY when records arrive from the store: that is what a
|
|
72434
|
-
* measurement of "changed since" can be measured against.
|
|
72435
|
-
*
|
|
72436
|
-
*
|
|
72437
|
-
*
|
|
72471
|
+
* measurement of "changed since" can be measured against.
|
|
72472
|
+
*
|
|
72473
|
+
* `written` is forgotten only by a load the HOST asked for (its
|
|
72474
|
+
* EV_REFRESH, which a Save sends). Since M36 a write moves no
|
|
72475
|
+
* version, so `written` is the draft chip of what this session
|
|
72476
|
+
* wrote and no longer half of a version measurement: a reload of
|
|
72477
|
+
* the reconnect, or of a write that turned out done, forgot the
|
|
72478
|
+
* chips of writes the host had not been told about.
|
|
72438
72479
|
***************************************************************/
|
|
72439
72480
|
function start_measuring(gobj) {
|
|
72440
72481
|
let priv = gobj.priv;
|
|
72441
72482
|
priv.baseline = {};
|
|
72442
|
-
priv.written = {};
|
|
72483
|
+
if (!priv.load_keeps_written) priv.written = {};
|
|
72443
72484
|
priv.host_ids = {};
|
|
72444
72485
|
if (!priv.model) return;
|
|
72445
72486
|
for (let treedb of priv.model.treedbs) for (let topic of treedb.topics) priv.baseline[topic.id] = topic.topic_version;
|
|
@@ -72621,8 +72662,10 @@ function render_toolbar(gobj) {
|
|
|
72621
72662
|
let state = gobj_current_state(gobj);
|
|
72622
72663
|
let readonly = is_readonly(gobj);
|
|
72623
72664
|
let has_model = !!priv.model;
|
|
72665
|
+
let on_a_treedb = state !== "ST_IDLE" && state !== "ST_EMPTY";
|
|
72666
|
+
let in_flight = state === "ST_SAVING" || state === "ST_LOADING";
|
|
72624
72667
|
let $left = [];
|
|
72625
|
-
if (priv.treedb_id) $left.push([
|
|
72668
|
+
if (priv.treedb_id && on_a_treedb) $left.push([
|
|
72626
72669
|
"button",
|
|
72627
72670
|
{
|
|
72628
72671
|
class: "SCHEMA_BACK button",
|
|
@@ -72695,17 +72738,17 @@ function render_toolbar(gobj) {
|
|
|
72695
72738
|
$trail
|
|
72696
72739
|
]);
|
|
72697
72740
|
let $right = [];
|
|
72698
|
-
if (priv.treedb_id && has_model) {
|
|
72741
|
+
if (priv.treedb_id && has_model && on_a_treedb) {
|
|
72699
72742
|
$right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-compass-drafting", priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
|
|
72700
72743
|
$right.push(toolbar_button("SCHEMA_VALIDATE_BTN", "yi-square-check", "check", "EV_VALIDATE", false));
|
|
72701
72744
|
$right.push(toolbar_button("SCHEMA_EXPORT_BTN", "yi-download", "export", "EV_EXPORT", false));
|
|
72702
72745
|
if (!readonly) $right.push(toolbar_button("SCHEMA_IMPORT_BTN", "yi-upload", "import", "EV_IMPORT", false));
|
|
72703
72746
|
}
|
|
72704
|
-
if (priv.topic_name && !readonly && !priv.diagram) {
|
|
72747
|
+
if (priv.topic_name && !readonly && !priv.diagram && on_a_treedb) {
|
|
72705
72748
|
if (undo_order_writes(gobj, current_topic(gobj)).length > 0) $right.push(toolbar_button("SCHEMA_UNDO_ORDER_BTN", "yi-arrow-rotate-left", "undo the order", "EV_UNDO_ORDER", false));
|
|
72706
72749
|
$right.push(toolbar_button("SCHEMA_ADD_COL_BTN", "yi-plus", "new column", "EV_ADD_COLUMN", false));
|
|
72707
72750
|
}
|
|
72708
|
-
if (priv.treedb_id && !priv.topic_name && !readonly && !priv.diagram) $right.push(toolbar_button("SCHEMA_ADD_TOPIC_BTN", "yi-plus", "new topic", "EV_ADD_TOPIC", false));
|
|
72751
|
+
if (priv.treedb_id && !priv.topic_name && !readonly && !priv.diagram && on_a_treedb) $right.push(toolbar_button("SCHEMA_ADD_TOPIC_BTN", "yi-plus", "new topic", "EV_ADD_TOPIC", false));
|
|
72709
72752
|
$right.push(toolbar_button("SCHEMA_REFRESH_BTN", "yi-arrows-rotate", "refresh", "EV_REFRESH", state === "ST_LOADING"));
|
|
72710
72753
|
let $bar = createElement2([
|
|
72711
72754
|
"div",
|
|
@@ -72731,7 +72774,7 @@ function render_toolbar(gobj) {
|
|
|
72731
72774
|
]);
|
|
72732
72775
|
for (let $button of $bar.querySelectorAll("button")) {
|
|
72733
72776
|
$button.__gobj__ = gobj;
|
|
72734
|
-
if (
|
|
72777
|
+
if (in_flight) $button.disabled = true;
|
|
72735
72778
|
}
|
|
72736
72779
|
$toolbar.appendChild($bar);
|
|
72737
72780
|
refresh_language($toolbar, t);
|
|
@@ -72749,16 +72792,19 @@ function render(gobj) {
|
|
|
72749
72792
|
render_toolbar(gobj);
|
|
72750
72793
|
if (state === "ST_LOADING") {
|
|
72751
72794
|
show_notice(gobj, "loading the schemas");
|
|
72795
|
+
destroy_diagram(gobj);
|
|
72752
72796
|
clear($body);
|
|
72753
72797
|
return;
|
|
72754
72798
|
}
|
|
72755
72799
|
if (state === "ST_IDLE") {
|
|
72756
72800
|
show_notice(gobj, priv.load_error ? "cannot load the schemas" : "not connected", priv.load_error);
|
|
72801
|
+
destroy_diagram(gobj);
|
|
72757
72802
|
clear($body);
|
|
72758
72803
|
return;
|
|
72759
72804
|
}
|
|
72760
72805
|
if (state === "ST_EMPTY") {
|
|
72761
72806
|
show_notice(gobj, "this yuno stores no schema");
|
|
72807
|
+
destroy_diagram(gobj);
|
|
72762
72808
|
clear($body);
|
|
72763
72809
|
return;
|
|
72764
72810
|
}
|
|
@@ -73447,12 +73493,16 @@ function render_diagram(gobj) {
|
|
|
73447
73493
|
let priv = gobj.priv;
|
|
73448
73494
|
let $body = $of(gobj, ".SCHEMA_BODY");
|
|
73449
73495
|
let treedb = current_treedb(gobj);
|
|
73450
|
-
if (!$body
|
|
73496
|
+
if (!$body) return;
|
|
73497
|
+
if (!treedb) {
|
|
73498
|
+
destroy_diagram(gobj);
|
|
73499
|
+
clear($body);
|
|
73451
73500
|
show_notice(gobj, "that treedb is not here any more", priv.treedb_id);
|
|
73452
73501
|
return;
|
|
73453
73502
|
}
|
|
73454
73503
|
if (!gclass_find_by_name("C_YUI_TREEDB_SCHEMA")) {
|
|
73455
73504
|
log_error(`${gobj_short_name(gobj)}: C_YUI_TREEDB_SCHEMA not registered by the app`);
|
|
73505
|
+
clear($body);
|
|
73456
73506
|
show_notice(gobj, "the schema drawing is not available");
|
|
73457
73507
|
return;
|
|
73458
73508
|
}
|
|
@@ -74722,26 +74772,21 @@ function end_load(gobj) {
|
|
|
74722
74772
|
***************************************************************/
|
|
74723
74773
|
function end_writes(gobj, error) {
|
|
74724
74774
|
let priv = gobj.priv;
|
|
74775
|
+
let seg = priv.pending_seg;
|
|
74725
74776
|
priv.save_queue = [];
|
|
74777
|
+
priv.pending_seg = null;
|
|
74726
74778
|
gobj_change_state(gobj, priv.save_return || "ST_TREEDBS");
|
|
74727
74779
|
priv.save_return = "";
|
|
74728
74780
|
show_notice(gobj, "");
|
|
74729
74781
|
set_busy(gobj, false);
|
|
74730
|
-
if (priv.pending_seg !== null) {
|
|
74731
|
-
let seg = priv.pending_seg;
|
|
74732
|
-
priv.pending_seg = null;
|
|
74733
|
-
if (!error) {
|
|
74734
|
-
apply_seg(gobj, seg);
|
|
74735
|
-
if (priv.save_wrote) gobj_publish_event(gobj, "EV_RECORD_WRITTEN", { treedb_name: gobj_read_str_attr(gobj, "treedb_name") });
|
|
74736
|
-
priv.save_wrote = false;
|
|
74737
|
-
return reload_if_owed(gobj);
|
|
74738
|
-
}
|
|
74739
|
-
}
|
|
74740
74782
|
if (error) yui_shell_show_error(yui_shell_of(gobj), error, { t });
|
|
74741
74783
|
if (priv.save_wrote) gobj_publish_event(gobj, "EV_RECORD_WRITTEN", { treedb_name: gobj_read_str_attr(gobj, "treedb_name") });
|
|
74742
74784
|
priv.save_wrote = false;
|
|
74743
|
-
|
|
74744
|
-
|
|
74785
|
+
if (seg !== null) apply_seg(gobj, seg);
|
|
74786
|
+
else {
|
|
74787
|
+
render(gobj);
|
|
74788
|
+
publish_check(gobj);
|
|
74789
|
+
}
|
|
74745
74790
|
reload_if_owed(gobj);
|
|
74746
74791
|
return error ? -1 : 0;
|
|
74747
74792
|
}
|
|
@@ -74758,7 +74803,7 @@ function reload_if_owed(gobj) {
|
|
|
74758
74803
|
priv.reload_on_open = true;
|
|
74759
74804
|
return 0;
|
|
74760
74805
|
}
|
|
74761
|
-
return request_model(gobj);
|
|
74806
|
+
return request_model(gobj, true);
|
|
74762
74807
|
}
|
|
74763
74808
|
/***************************************************************
|
|
74764
74809
|
* The record a column form produces.
|
|
@@ -74824,6 +74869,7 @@ function topic_record(gobj, treedb, topic, values) {
|
|
|
74824
74869
|
***************************************************************/
|
|
74825
74870
|
function go(gobj, treedb_id, topic_name, diagram, mirror) {
|
|
74826
74871
|
let priv = gobj.priv;
|
|
74872
|
+
priv.pending_seg = null;
|
|
74827
74873
|
priv.treedb_id = treedb_id || "";
|
|
74828
74874
|
priv.topic_name = topic_name || "";
|
|
74829
74875
|
priv.diagram = !!diagram;
|
|
@@ -74940,7 +74986,7 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
74940
74986
|
log_warning(`${gobj_short_name(gobj)}: '${command}' of '${topic_name}' answered for a write that is over (result ${result}): ignored`);
|
|
74941
74987
|
return 0;
|
|
74942
74988
|
}
|
|
74943
|
-
return late_write_done(gobj, command, topic_name);
|
|
74989
|
+
return late_write_done(gobj, command, topic_name, data);
|
|
74944
74990
|
}
|
|
74945
74991
|
if (result < 0) return end_writes(gobj, comment || t("the treedb refused the write"));
|
|
74946
74992
|
priv.save_wrote = true;
|
|
@@ -74950,8 +74996,15 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
74950
74996
|
if (record) patch_record(gobj, topic_name, record);
|
|
74951
74997
|
else {
|
|
74952
74998
|
log_warning(`${gobj_short_name(gobj)}: '${command}' answered no record`);
|
|
74999
|
+
if (topic_name === T_TOPICS || topic_name === T_COLS) {
|
|
75000
|
+
let write = priv.save_queue[0];
|
|
75001
|
+
mark_written(gobj, topic_name, write ? write.record : null);
|
|
75002
|
+
}
|
|
74953
75003
|
priv.save_queue = [];
|
|
74954
|
-
|
|
75004
|
+
priv.save_return = "";
|
|
75005
|
+
priv.save_wrote = false;
|
|
75006
|
+
gobj_publish_event(gobj, "EV_RECORD_WRITTEN", { treedb_name: gobj_read_str_attr(gobj, "treedb_name") });
|
|
75007
|
+
request_model(gobj, true);
|
|
74955
75008
|
return 0;
|
|
74956
75009
|
}
|
|
74957
75010
|
}
|
|
@@ -74978,11 +75031,18 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
74978
75031
|
* the view was answered once, as failed -- and echoes the node
|
|
74979
75032
|
* event instead, which this view does not hear: there, Refresh is
|
|
74980
75033
|
* what reads the store.
|
|
75034
|
+
*
|
|
75035
|
+
* It is a WRITE like any other for the host (EV_RECORD_WRITTEN):
|
|
75036
|
+
* the host was told nothing when it was given up, and it owns the
|
|
75037
|
+
* Save that publishes it. The reload keeps what this session wrote
|
|
75038
|
+
* (request_model()), and the record it answered marks its topic.
|
|
74981
75039
|
***************************************************************/
|
|
74982
|
-
function late_write_done(gobj, command, topic_name) {
|
|
75040
|
+
function late_write_done(gobj, command, topic_name, data) {
|
|
74983
75041
|
let priv = gobj.priv;
|
|
74984
75042
|
let state = gobj_current_state(gobj);
|
|
74985
75043
|
log_warning(`${gobj_short_name(gobj)}: '${command}' of '${topic_name}' was given up, and it was DONE: the model is read again`);
|
|
75044
|
+
mark_written_record(gobj, topic_name, is_object(data) ? data : Array.isArray(data) && is_object(data[0]) ? data[0] : null);
|
|
75045
|
+
gobj_publish_event(gobj, "EV_RECORD_WRITTEN", { treedb_name: gobj_read_str_attr(gobj, "treedb_name") });
|
|
74986
75046
|
if (state === "ST_LOADING") return 0;
|
|
74987
75047
|
if (state === "ST_SAVING") {
|
|
74988
75048
|
priv.reload_after_write = true;
|
|
@@ -74992,7 +75052,27 @@ function late_write_done(gobj, command, topic_name) {
|
|
|
74992
75052
|
priv.reload_on_open = true;
|
|
74993
75053
|
return 0;
|
|
74994
75054
|
}
|
|
74995
|
-
return request_model(gobj);
|
|
75055
|
+
return request_model(gobj, true);
|
|
75056
|
+
}
|
|
75057
|
+
/***************************************************************
|
|
75058
|
+
* The topic a record written belongs to, read off the RECORD and
|
|
75059
|
+
* not off the screen: a write answered late may be about a topic
|
|
75060
|
+
* the operator has left. A column names its topic in its fkey
|
|
75061
|
+
* (`topics^<topic id>^cols`); a topic is its own id.
|
|
75062
|
+
***************************************************************/
|
|
75063
|
+
function mark_written_record(gobj, topic_name, record) {
|
|
75064
|
+
let priv = gobj.priv;
|
|
75065
|
+
if (!record) return;
|
|
75066
|
+
if (topic_name === T_TOPICS && typeof record.id === "string" && record.id) {
|
|
75067
|
+
priv.written[record.id] = true;
|
|
75068
|
+
return;
|
|
75069
|
+
}
|
|
75070
|
+
if (topic_name !== T_COLS) return;
|
|
75071
|
+
let refs = Array.isArray(record.topics) ? record.topics : typeof record.topics === "string" ? [record.topics] : [];
|
|
75072
|
+
for (let ref of refs) {
|
|
75073
|
+
let parts = String(ref).split("^");
|
|
75074
|
+
if (parts.length >= 2 && parts[1]) priv.written[parts[1]] = true;
|
|
75075
|
+
}
|
|
74996
75076
|
}
|
|
74997
75077
|
/***************************************************************
|
|
74998
75078
|
* Remember which topic this write belongs to, which is what
|
|
@@ -75051,7 +75131,7 @@ function ac_transport_state(gobj, event, kw, src) {
|
|
|
75051
75131
|
}
|
|
75052
75132
|
if ((!priv.model || priv.reload_on_open) && state !== "ST_LOADING" && state !== "ST_SAVING") {
|
|
75053
75133
|
priv.reload_on_open = false;
|
|
75054
|
-
return request_model(gobj);
|
|
75134
|
+
return request_model(gobj, true);
|
|
75055
75135
|
}
|
|
75056
75136
|
render_toolbar(gobj);
|
|
75057
75137
|
return 0;
|
|
@@ -75066,7 +75146,25 @@ function ac_language_changed$1(gobj, event, kw, src) {
|
|
|
75066
75146
|
return 0;
|
|
75067
75147
|
}
|
|
75068
75148
|
function ac_refresh$1(gobj, event, kw, src) {
|
|
75069
|
-
return request_model(gobj);
|
|
75149
|
+
return request_model(gobj, false);
|
|
75150
|
+
}
|
|
75151
|
+
/***************************************************************
|
|
75152
|
+
* What a DIALOG sends while the model is being read again: the
|
|
75153
|
+
* Save of a form left open when the reload started, a
|
|
75154
|
+
* confirmation, an import. The loading screen took the rest of
|
|
75155
|
+
* the view away (request_model()); a dialog is the one thing the
|
|
75156
|
+
* operator can still reach, and what it asks is computed against
|
|
75157
|
+
* a model the answers in the air are about to replace.
|
|
75158
|
+
*
|
|
75159
|
+
* Refused, and SAID -- and the dialog stays open with what was
|
|
75160
|
+
* typed, so the same Save works once the load is in. Undeclared,
|
|
75161
|
+
* it answered "Event NOT DEFINED in state ST_LOADING" and the
|
|
75162
|
+
* edit was gone with no word (third independent review).
|
|
75163
|
+
***************************************************************/
|
|
75164
|
+
function ac_wait_for_the_load(gobj, event, kw, src) {
|
|
75165
|
+
log_warning(`${gobj_short_name(gobj)}: ${event} refused, the schemas are loading`);
|
|
75166
|
+
yui_shell_show_error(yui_shell_of(gobj), "the schemas are loading: try again when they are in", { t });
|
|
75167
|
+
return -1;
|
|
75070
75168
|
}
|
|
75071
75169
|
/***************************************************************
|
|
75072
75170
|
* {drafts: {treedb_name: [topic names]}} -- the host says which
|
|
@@ -75614,7 +75712,38 @@ function create_gclass$1(gclass_name) {
|
|
|
75614
75712
|
];
|
|
75615
75713
|
const states = [
|
|
75616
75714
|
["ST_IDLE", COMMON.slice()],
|
|
75617
|
-
["ST_LOADING", COMMON.
|
|
75715
|
+
["ST_LOADING", COMMON.concat([
|
|
75716
|
+
[
|
|
75717
|
+
"EV_SAVE_COLUMN",
|
|
75718
|
+
ac_wait_for_the_load,
|
|
75719
|
+
null
|
|
75720
|
+
],
|
|
75721
|
+
[
|
|
75722
|
+
"EV_SAVE_TOPIC",
|
|
75723
|
+
ac_wait_for_the_load,
|
|
75724
|
+
null
|
|
75725
|
+
],
|
|
75726
|
+
[
|
|
75727
|
+
"EV_DELETE_ORPHAN",
|
|
75728
|
+
ac_wait_for_the_load,
|
|
75729
|
+
null
|
|
75730
|
+
],
|
|
75731
|
+
[
|
|
75732
|
+
"EV_PREVIEW_IMPORT",
|
|
75733
|
+
ac_wait_for_the_load,
|
|
75734
|
+
null
|
|
75735
|
+
],
|
|
75736
|
+
[
|
|
75737
|
+
"EV_APPLY_IMPORT",
|
|
75738
|
+
ac_wait_for_the_load,
|
|
75739
|
+
null
|
|
75740
|
+
],
|
|
75741
|
+
[
|
|
75742
|
+
"EV_CONFIRMED",
|
|
75743
|
+
ac_wait_for_the_load,
|
|
75744
|
+
null
|
|
75745
|
+
]
|
|
75746
|
+
])],
|
|
75618
75747
|
["ST_EMPTY", COMMON.slice()],
|
|
75619
75748
|
["ST_TREEDBS", COMMON.concat([
|
|
75620
75749
|
[
|