@yuneta/gobj-ui 7.25.15 → 7.25.17
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 +106 -4
- package/dist/gobj-ui.cjs.js +274 -66
- package/dist/gobj-ui.es.js +274 -66
- package/package.json +2 -2
- package/src/c_g6_nodes_tree.js +37 -4
- package/src/c_yui_schema_editor.js +280 -47
- package/src/c_yui_treedb_graph.js +22 -6
- package/src/form_busy.test.js +1 -1
- package/src/form_writes_in_flight.test.js +1 -1
- package/src/g6_graphs_write_owed.wiring.test.js +200 -0
- package/src/host_drafts.test.js +2 -2
- package/src/schema_editor_drafts.wiring.test.js +1 -1
- package/src/schema_editor_reload.wiring.test.js +313 -4
- package/src/shell_modals.js +29 -8
- package/src/shell_toast_once.test.js +63 -0
- package/src/table_cell_text.test.js +1 -1
- package/src/treedb_graph_writes.wiring.test.js +8 -1
- package/src/treedb_topics_transport.wiring.test.js +1 -1
- package/src/yui_install.js +14 -3
- package/src/yui_install.test.js +23 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -3432,8 +3432,28 @@ function build_dialog(shell, message, buttons, opts) {
|
|
|
3432
3432
|
if ($primary) $primary.focus();
|
|
3433
3433
|
});
|
|
3434
3434
|
}
|
|
3435
|
+
/***************************************************************
|
|
3436
|
+
* The labels a confirmation shows when the caller names none.
|
|
3437
|
+
*
|
|
3438
|
+
* They are i18n KEYS, lower-case like every key: a button
|
|
3439
|
+
* translates its label with the app's t() -- its text, its title
|
|
3440
|
+
* and its aria-label. Until 7.25.16 they were "OK", "Yes", "No",
|
|
3441
|
+
* "Delete" and "Cancel", keys that no locale carries, so a dialog
|
|
3442
|
+
* that took the defaults read in English in every language.
|
|
3443
|
+
*
|
|
3444
|
+
* Written as `i18n:` entries so the validate-locales script of a
|
|
3445
|
+
* consumer finds them when it scans this module: an app that
|
|
3446
|
+
* mounts these dialogs must define the five keys.
|
|
3447
|
+
***************************************************************/
|
|
3448
|
+
var DEFAULT_LABEL = Object.freeze({
|
|
3449
|
+
ok: Object.freeze({ i18n: "ok" }),
|
|
3450
|
+
yes: Object.freeze({ i18n: "yes" }),
|
|
3451
|
+
no: Object.freeze({ i18n: "no" }),
|
|
3452
|
+
delete: Object.freeze({ i18n: "delete" }),
|
|
3453
|
+
cancel: Object.freeze({ i18n: "cancel" })
|
|
3454
|
+
});
|
|
3435
3455
|
function yui_shell_confirm_ok(shell, message, opts) {
|
|
3436
|
-
let label = opts && opts.ok_label ||
|
|
3456
|
+
let label = opts && opts.ok_label || DEFAULT_LABEL.ok.i18n;
|
|
3437
3457
|
if (!opts || !opts.type) opts = Object.assign({}, opts, { type: "success" });
|
|
3438
3458
|
return build_dialog(shell, message, [{
|
|
3439
3459
|
label,
|
|
@@ -3442,8 +3462,8 @@ function yui_shell_confirm_ok(shell, message, opts) {
|
|
|
3442
3462
|
}], opts).then(() => void 0);
|
|
3443
3463
|
}
|
|
3444
3464
|
function yui_shell_confirm_yesno(shell, message, opts) {
|
|
3445
|
-
let yes_label = opts && opts.yes_label ||
|
|
3446
|
-
let no_label = opts && opts.no_label ||
|
|
3465
|
+
let yes_label = opts && opts.yes_label || DEFAULT_LABEL.yes.i18n;
|
|
3466
|
+
let no_label = opts && opts.no_label || DEFAULT_LABEL.no.i18n;
|
|
3447
3467
|
return build_dialog(shell, message, [{
|
|
3448
3468
|
label: yes_label,
|
|
3449
3469
|
value: "yes",
|
|
@@ -3468,8 +3488,8 @@ function yui_shell_confirm_yesno(shell, message, opts) {
|
|
|
3468
3488
|
* pressed.
|
|
3469
3489
|
***************************************************************/
|
|
3470
3490
|
function yui_shell_confirm_danger(shell, message, opts) {
|
|
3471
|
-
let confirm_label = opts && opts.confirm_label ||
|
|
3472
|
-
let cancel_label = opts && opts.cancel_label ||
|
|
3491
|
+
let confirm_label = opts && opts.confirm_label || DEFAULT_LABEL.delete.i18n;
|
|
3492
|
+
let cancel_label = opts && opts.cancel_label || DEFAULT_LABEL.cancel.i18n;
|
|
3473
3493
|
if (!opts || !opts.type) opts = Object.assign({}, opts, { type: "danger" });
|
|
3474
3494
|
return build_dialog(shell, message, [{
|
|
3475
3495
|
label: confirm_label,
|
|
@@ -3481,9 +3501,9 @@ function yui_shell_confirm_danger(shell, message, opts) {
|
|
|
3481
3501
|
}], opts).then((v) => v === "confirm");
|
|
3482
3502
|
}
|
|
3483
3503
|
function yui_shell_confirm_yesnocancel(shell, message, opts) {
|
|
3484
|
-
let yes_label = opts && opts.yes_label ||
|
|
3485
|
-
let no_label = opts && opts.no_label ||
|
|
3486
|
-
let cancel_label = opts && opts.cancel_label ||
|
|
3504
|
+
let yes_label = opts && opts.yes_label || DEFAULT_LABEL.yes.i18n;
|
|
3505
|
+
let no_label = opts && opts.no_label || DEFAULT_LABEL.no.i18n;
|
|
3506
|
+
let cancel_label = opts && opts.cancel_label || DEFAULT_LABEL.cancel.i18n;
|
|
3487
3507
|
return build_dialog(shell, message, [
|
|
3488
3508
|
{
|
|
3489
3509
|
label: yes_label,
|
|
@@ -59227,6 +59247,7 @@ var PRIVATE_DATA$4 = {
|
|
|
59227
59247
|
__graphs__: [],
|
|
59228
59248
|
_graph_properties: {},
|
|
59229
59249
|
_saved_graph_properties: {},
|
|
59250
|
+
_graphs_writes_owed: {},
|
|
59230
59251
|
yet_showed: false,
|
|
59231
59252
|
edit_mode: false,
|
|
59232
59253
|
operation_mode: null,
|
|
@@ -60922,6 +60943,7 @@ function save_topic_graph_properties(gobj, topic_name) {
|
|
|
60922
60943
|
if (!topic_arrangement_changed(properties, priv._saved_graph_properties[topic_name])) return;
|
|
60923
60944
|
properties.__origin__ = gobj_read_str_attr(gobj_yuno(), "node_uuid");
|
|
60924
60945
|
priv._saved_graph_properties[topic_name] = json_deep_copy(properties);
|
|
60946
|
+
delete priv._graphs_writes_owed[topic_name];
|
|
60925
60947
|
let kw_update = {
|
|
60926
60948
|
treedb_name: priv.treedb_name,
|
|
60927
60949
|
topic_name: "__graphs__",
|
|
@@ -61003,8 +61025,13 @@ function update_history_buttons(gobj) {
|
|
|
61003
61025
|
} else {
|
|
61004
61026
|
disableElements($container, ".EV_HISTORY_UNDO");
|
|
61005
61027
|
set_active_state($container, ".EV_HISTORY_UNDO", false);
|
|
61006
|
-
|
|
61007
|
-
|
|
61028
|
+
if (graphs_write_is_owed(gobj)) {
|
|
61029
|
+
enableElements($container, ".EV_SAVE_GRAPH");
|
|
61030
|
+
set_submit_state($container, ".EV_SAVE_GRAPH", true);
|
|
61031
|
+
} else {
|
|
61032
|
+
disableElements($container, ".EV_SAVE_GRAPH");
|
|
61033
|
+
set_submit_state($container, ".EV_SAVE_GRAPH", false);
|
|
61034
|
+
}
|
|
61008
61035
|
}
|
|
61009
61036
|
} else {
|
|
61010
61037
|
disableElements($container, ".EV_HISTORY_REDO");
|
|
@@ -61961,6 +61988,15 @@ function run_preview_undo(gobj, key) {
|
|
|
61961
61988
|
log_error(`${gobj_short_name(gobj)}: cannot undo the preview: ${e}`);
|
|
61962
61989
|
}
|
|
61963
61990
|
}
|
|
61991
|
+
/************************************************************
|
|
61992
|
+
* Is a `__graphs__` write owed? The host said one did not land
|
|
61993
|
+
* (EV_GRAPHS_WRITE_REFUSED), and no Save has written that topic
|
|
61994
|
+
* since. The Save button stays lit while it is: the history
|
|
61995
|
+
* knows nothing of it, so `canUndo()` alone would put it out.
|
|
61996
|
+
************************************************************/
|
|
61997
|
+
function graphs_write_is_owed(gobj) {
|
|
61998
|
+
return Object.keys(gobj.priv._graphs_writes_owed).length > 0;
|
|
61999
|
+
}
|
|
61964
62000
|
function mark_graph_dirty(gobj) {
|
|
61965
62001
|
let $container = gobj_read_attr(gobj, "$container");
|
|
61966
62002
|
enableElements($container, ".EV_SAVE_GRAPH");
|
|
@@ -65701,6 +65737,7 @@ function ac_clear_data(gobj, event, kw, src) {
|
|
|
65701
65737
|
deselect_node(gobj);
|
|
65702
65738
|
hide_create_popover(gobj);
|
|
65703
65739
|
gobj_write_attr(gobj, "records", {});
|
|
65740
|
+
priv._graphs_writes_owed = {};
|
|
65704
65741
|
priv._nodes_total = 0;
|
|
65705
65742
|
priv._nodes_placed = 0;
|
|
65706
65743
|
priv._fold_model = null;
|
|
@@ -65793,11 +65830,9 @@ function ac_save_graph(gobj, event, kw, src) {
|
|
|
65793
65830
|
disableElements($container, ".EV_SAVE_GRAPH");
|
|
65794
65831
|
set_submit_state($container, ".EV_SAVE_GRAPH", false);
|
|
65795
65832
|
let history = graph_get_plugin(gobj, "history");
|
|
65796
|
-
if (history)
|
|
65797
|
-
history.clear();
|
|
65798
|
-
update_history_buttons(gobj);
|
|
65799
|
-
}
|
|
65833
|
+
if (history) history.clear();
|
|
65800
65834
|
save_geometry(gobj);
|
|
65835
|
+
update_history_buttons(gobj);
|
|
65801
65836
|
}
|
|
65802
65837
|
return 0;
|
|
65803
65838
|
}
|
|
@@ -65820,6 +65855,7 @@ function ac_graphs_write_refused(gobj, event, kw, src) {
|
|
|
65820
65855
|
}
|
|
65821
65856
|
log_warning(`${gobj_short_name(gobj)}: the arrangement of '${topic_name}' was not saved: the next Save writes it again`);
|
|
65822
65857
|
forget_refused_graphs_write(priv._saved_graph_properties, topic_name);
|
|
65858
|
+
priv._graphs_writes_owed[topic_name] = true;
|
|
65823
65859
|
if (priv.edit_mode) mark_graph_dirty(gobj);
|
|
65824
65860
|
return 0;
|
|
65825
65861
|
}
|
|
@@ -68337,6 +68373,7 @@ function treedb_update_node(gobj, treedb_name, topic_name, record, options) {
|
|
|
68337
68373
|
options: options || {}
|
|
68338
68374
|
};
|
|
68339
68375
|
kw.__md_command__ = { topic_name };
|
|
68376
|
+
if (topic_name === "__graphs__") kw.__md_command__.graph_topic = graph_topic_of(record);
|
|
68340
68377
|
let ret = gobj_command(priv.gobj_remote_yuno, command, kw, gobj);
|
|
68341
68378
|
if (ret) {
|
|
68342
68379
|
log_error(ret);
|
|
@@ -68615,7 +68652,7 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
|
|
|
68615
68652
|
case "delete-node":
|
|
68616
68653
|
case "link-nodes":
|
|
68617
68654
|
case "unlink-nodes":
|
|
68618
|
-
if (result < 0 && command === "update-node") graphs_write_refused(gobj, kw_get_str(gobj, kw_command, "topic_name", "", 0),
|
|
68655
|
+
if (result < 0 && command === "update-node") graphs_write_refused(gobj, kw_get_str(gobj, kw_command, "topic_name", "", 0), kw_get_str(gobj, kw_command, "graph_topic", "", 0));
|
|
68619
68656
|
if (result >= 0 && kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") gobj_publish_event(gobj, "EV_RECORD_WRITTEN", {
|
|
68620
68657
|
treedb_name: kw_get_str(gobj, kw_command, "treedb_name", "", 0),
|
|
68621
68658
|
topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
|
|
@@ -68864,29 +68901,35 @@ function ac_update_node(gobj, event, kw, src) {
|
|
|
68864
68901
|
let record = kw.record;
|
|
68865
68902
|
let options = kw.options || {};
|
|
68866
68903
|
if (refuse_if_readonly$1(gobj, event)) {
|
|
68867
|
-
graphs_write_refused(gobj, topic_name, record);
|
|
68904
|
+
graphs_write_refused(gobj, topic_name, graph_topic_of(record));
|
|
68868
68905
|
return -1;
|
|
68869
68906
|
}
|
|
68870
68907
|
if (topic_name === "__graphs__" && !is_connected(gobj)) {
|
|
68871
68908
|
log_warning(`${gobj_short_name(gobj)}: no session, the arrangement was not sent`);
|
|
68872
|
-
graphs_write_refused(gobj, topic_name, record);
|
|
68909
|
+
graphs_write_refused(gobj, topic_name, graph_topic_of(record));
|
|
68873
68910
|
return -1;
|
|
68874
68911
|
}
|
|
68875
68912
|
let ret = treedb_update_node(gobj, treedb_name, topic_name, record, options);
|
|
68876
|
-
if (ret < 0) graphs_write_refused(gobj, topic_name, record);
|
|
68913
|
+
if (ret < 0) graphs_write_refused(gobj, topic_name, graph_topic_of(record));
|
|
68877
68914
|
return ret;
|
|
68878
68915
|
}
|
|
68879
68916
|
/************************************************************
|
|
68917
|
+
* The topic a `__graphs__` record arranges.
|
|
68918
|
+
************************************************************/
|
|
68919
|
+
function graph_topic_of(record) {
|
|
68920
|
+
if (!record || typeof record !== "object") return "";
|
|
68921
|
+
return record.topic || record.id || "";
|
|
68922
|
+
}
|
|
68923
|
+
/************************************************************
|
|
68880
68924
|
* A write of `__graphs__` did not land. The engine
|
|
68881
68925
|
* (C_G6_NODES_TREE) took it for granted when it left -- nothing
|
|
68882
68926
|
* answers it when it lands -- so it is told, and its next Save
|
|
68883
68927
|
* writes the topic again. Other topics are the operator's data:
|
|
68884
68928
|
* the answer's error says what happened to them.
|
|
68885
68929
|
************************************************************/
|
|
68886
|
-
function graphs_write_refused(gobj, topic_name,
|
|
68930
|
+
function graphs_write_refused(gobj, topic_name, topic) {
|
|
68887
68931
|
let priv = gobj.priv;
|
|
68888
68932
|
if (topic_name !== "__graphs__") return;
|
|
68889
|
-
let topic = record && typeof record === "object" ? record.topic || record.id : "";
|
|
68890
68933
|
if (!topic) {
|
|
68891
68934
|
log_error(`${gobj_short_name(gobj)}: a refused __graphs__ write names no topic`);
|
|
68892
68935
|
return;
|
|
@@ -72329,6 +72372,8 @@ var PRIVATE_DATA$1 = {
|
|
|
72329
72372
|
dropped_round: 0,
|
|
72330
72373
|
dropped_write: 0,
|
|
72331
72374
|
reload_after_write: false,
|
|
72375
|
+
refresh_after_write: false,
|
|
72376
|
+
reopen_form: null,
|
|
72332
72377
|
pending_seg: null,
|
|
72333
72378
|
import_plan: null,
|
|
72334
72379
|
import_pane: null,
|
|
@@ -72443,11 +72488,18 @@ function el_attrs(attrs) {
|
|
|
72443
72488
|
return attrs;
|
|
72444
72489
|
}
|
|
72445
72490
|
/***************************************************************
|
|
72446
|
-
* The body stops answering while a write is in flight.
|
|
72491
|
+
* The body stops answering while a write is in flight. For the
|
|
72492
|
+
* keyboard too: `pointer-events` stops the mouse alone, and the
|
|
72493
|
+
* shell's focus trap puts the focus back on the row control that
|
|
72494
|
+
* had it, where Enter or Delete sent an action ST_SAVING does
|
|
72495
|
+
* not declare. `inert` takes the whole body out of reach.
|
|
72447
72496
|
***************************************************************/
|
|
72448
72497
|
function set_busy(gobj, busy) {
|
|
72449
72498
|
let $body = $of(gobj, ".SCHEMA_BODY");
|
|
72450
|
-
if ($body)
|
|
72499
|
+
if ($body) {
|
|
72500
|
+
$body.classList.toggle("SCHEMA_BUSY", !!busy);
|
|
72501
|
+
$body.toggleAttribute("inert", !!busy);
|
|
72502
|
+
}
|
|
72451
72503
|
}
|
|
72452
72504
|
/***************************************************************
|
|
72453
72505
|
* Shorthands for the three panes of the frame.
|
|
@@ -72534,14 +72586,61 @@ function owes_reload(gobj) {
|
|
|
72534
72586
|
let state = gobj_current_state(gobj);
|
|
72535
72587
|
return gobj.priv.reload_on_open && transport_in_session(gobj) && state !== "ST_LOADING" && state !== "ST_SAVING";
|
|
72536
72588
|
}
|
|
72537
|
-
function reload_first(gobj, event) {
|
|
72589
|
+
function reload_first(gobj, event, reopen) {
|
|
72590
|
+
let priv = gobj.priv;
|
|
72538
72591
|
if (!owes_reload(gobj)) return false;
|
|
72539
|
-
|
|
72592
|
+
priv.reload_on_open = false;
|
|
72593
|
+
if (reopen && priv.dialog) {
|
|
72594
|
+
priv.reopen_form = Object.assign(json_deep_copy(reopen), {
|
|
72595
|
+
dialog: priv.dialog,
|
|
72596
|
+
treedb_id: priv.treedb_id
|
|
72597
|
+
});
|
|
72598
|
+
log_warning(`${gobj_short_name(gobj)}: ${event} refused, the schemas shown may be out of date: they are read again first, and the form opens again on them with its changes`);
|
|
72599
|
+
yui_shell_show_error(yui_shell_of(gobj), "the schemas shown may be out of date: they are read again, and the form opens again on them with your changes", { t });
|
|
72600
|
+
request_model(gobj, true);
|
|
72601
|
+
return true;
|
|
72602
|
+
}
|
|
72540
72603
|
log_warning(`${gobj_short_name(gobj)}: ${event} refused, the schemas shown may be out of date: they are read again first`);
|
|
72541
72604
|
yui_shell_show_error(yui_shell_of(gobj), "the schemas shown may be out of date: they are read again, try again when they are in", { t });
|
|
72542
72605
|
request_model(gobj, true);
|
|
72543
72606
|
return true;
|
|
72544
72607
|
}
|
|
72608
|
+
/***************************************************************
|
|
72609
|
+
* The form reload_first() took down, opened again on the model
|
|
72610
|
+
* the load just made, with the operator's changes on top.
|
|
72611
|
+
*
|
|
72612
|
+
* Only where it can mean the same thing: on the treedb it was
|
|
72613
|
+
* opened on, on the screen whose Save it has, and on a record
|
|
72614
|
+
* that is still there. Otherwise it is not opened, and that is
|
|
72615
|
+
* said -- a form opened on another treedb, or on nothing, would
|
|
72616
|
+
* save somewhere the operator never meant.
|
|
72617
|
+
***************************************************************/
|
|
72618
|
+
function reopen_form(gobj, r) {
|
|
72619
|
+
let priv = gobj.priv;
|
|
72620
|
+
let state = gobj_current_state(gobj);
|
|
72621
|
+
let treedb = current_treedb(gobj);
|
|
72622
|
+
let topic = null;
|
|
72623
|
+
let col = null;
|
|
72624
|
+
let fits = false;
|
|
72625
|
+
if (treedb && r.treedb_id === priv.treedb_id) {
|
|
72626
|
+
if (r.form === "column" && state === "ST_COLUMNS") {
|
|
72627
|
+
topic = find_topic(priv.model, priv.treedb_id, r.topic);
|
|
72628
|
+
col = topic && !r.creating ? find_col(priv.model, priv.treedb_id, r.topic, r.col) : null;
|
|
72629
|
+
fits = !!topic && (r.creating || !!col);
|
|
72630
|
+
} else if (r.form === "topic" && state === "ST_TOPICS") {
|
|
72631
|
+
topic = r.creating ? null : find_topic(priv.model, priv.treedb_id, r.topic);
|
|
72632
|
+
fits = r.creating || !!topic;
|
|
72633
|
+
}
|
|
72634
|
+
}
|
|
72635
|
+
if (!fits) {
|
|
72636
|
+
log_warning(`${gobj_short_name(gobj)}: the ${r.form} form was not opened again: what it edited is not on the schemas the reload read (${r.treedb_id} ${r.topic}${r.col ? "." + r.col : ""}, now ${state})`);
|
|
72637
|
+
yui_shell_show_error(yui_shell_of(gobj), "the schemas were read again and what the form was editing is not there any more", { t });
|
|
72638
|
+
return -1;
|
|
72639
|
+
}
|
|
72640
|
+
if (r.form === "column") open_column_form(gobj, topic, col, null, r.changed);
|
|
72641
|
+
else open_topic_form(gobj, treedb, topic, r.changed);
|
|
72642
|
+
return 0;
|
|
72643
|
+
}
|
|
72545
72644
|
function reload_after_move(gobj) {
|
|
72546
72645
|
if (!owes_reload(gobj)) return 0;
|
|
72547
72646
|
gobj.priv.reload_on_open = false;
|
|
@@ -72616,7 +72715,7 @@ function request_model(gobj, keep_written) {
|
|
|
72616
72715
|
priv.records_before = null;
|
|
72617
72716
|
priv.load_round++;
|
|
72618
72717
|
priv.reload_on_open = true;
|
|
72619
|
-
priv.load_error =
|
|
72718
|
+
priv.load_error = "cannot reach the treedb";
|
|
72620
72719
|
if (priv.model) yui_shell_show_error(yui_shell_of(gobj), "cannot reach the treedb", { t });
|
|
72621
72720
|
end_load(gobj);
|
|
72622
72721
|
return -1;
|
|
@@ -72687,7 +72786,7 @@ function build_model(gobj) {
|
|
|
72687
72786
|
* measurement of "changed since" can be measured against.
|
|
72688
72787
|
*
|
|
72689
72788
|
* `written` is forgotten only by an EV_REFRESH (the view's own
|
|
72690
|
-
* Refresh button, or a host that sends one). Since
|
|
72789
|
+
* Refresh button, or a host that sends one). Since 7.23.196 a write moves no
|
|
72691
72790
|
* version, so `written` is the draft chip of what this session
|
|
72692
72791
|
* wrote and no longer half of a version measurement: a reload of
|
|
72693
72792
|
* the reconnect, or of a write that turned out done, forgot the
|
|
@@ -72827,10 +72926,13 @@ function show_notice(gobj, key, detail) {
|
|
|
72827
72926
|
},
|
|
72828
72927
|
t(key)
|
|
72829
72928
|
]));
|
|
72830
|
-
if (detail) $notice.appendChild(createElement2([
|
|
72929
|
+
if (detail && detail !== key) $notice.appendChild(createElement2([
|
|
72831
72930
|
"span",
|
|
72832
|
-
{
|
|
72833
|
-
|
|
72931
|
+
{
|
|
72932
|
+
class: "SCHEMA_NOTICE_DETAIL yui-text-quiet ml-2",
|
|
72933
|
+
i18n: `${detail}`
|
|
72934
|
+
},
|
|
72935
|
+
t(`${detail}`)
|
|
72834
72936
|
]));
|
|
72835
72937
|
}
|
|
72836
72938
|
/***************************************************************
|
|
@@ -73965,6 +74067,55 @@ function read_form($root) {
|
|
|
73965
74067
|
return out;
|
|
73966
74068
|
}
|
|
73967
74069
|
/***************************************************************
|
|
74070
|
+
* A column form as its Save sends it: the fields and the flags.
|
|
74071
|
+
***************************************************************/
|
|
74072
|
+
function column_form_state($form) {
|
|
74073
|
+
let values = read_form($form);
|
|
74074
|
+
values.flag = read_flags($form);
|
|
74075
|
+
return values;
|
|
74076
|
+
}
|
|
74077
|
+
/***************************************************************
|
|
74078
|
+
* The fields the operator CHANGED: those whose value is not the
|
|
74079
|
+
* one the form was opened with.
|
|
74080
|
+
***************************************************************/
|
|
74081
|
+
function form_changes(initial, values) {
|
|
74082
|
+
let changed = {};
|
|
74083
|
+
for (let name of Object.keys(values)) if (JSON.stringify(values[name]) !== JSON.stringify(initial[name])) changed[name] = values[name];
|
|
74084
|
+
return changed;
|
|
74085
|
+
}
|
|
74086
|
+
/***************************************************************
|
|
74087
|
+
* Put changes back into a form just built (reopen_form()). The
|
|
74088
|
+
* flags are drawn again for the type the changes leave, holding
|
|
74089
|
+
* the flags they name, so none of them is hidden by the type.
|
|
74090
|
+
***************************************************************/
|
|
74091
|
+
function apply_form_changes(gobj, $form, changes) {
|
|
74092
|
+
for (let name of Object.keys(changes)) {
|
|
74093
|
+
if (name === "flag") continue;
|
|
74094
|
+
let $control = $form.querySelector(`[data-name="${name}"]`);
|
|
74095
|
+
if (!$control) {
|
|
74096
|
+
log_warning(`${gobj_short_name(gobj)}: a change of '${name}' has no field in the form opened again: not put back`);
|
|
74097
|
+
continue;
|
|
74098
|
+
}
|
|
74099
|
+
if ($control.type === "checkbox") $control.checked = !!changes[name];
|
|
74100
|
+
else $control.value = changes[name];
|
|
74101
|
+
}
|
|
74102
|
+
let $type = $form.querySelector("[data-name=\"type\"]");
|
|
74103
|
+
if ($type && $form.querySelector(".SCHEMA_FLAGS")) {
|
|
74104
|
+
let flags = Array.isArray(changes.flag) ? changes.flag : read_flags($form);
|
|
74105
|
+
redraw_flags(gobj, $form, $type.value, flags);
|
|
74106
|
+
}
|
|
74107
|
+
}
|
|
74108
|
+
/***************************************************************
|
|
74109
|
+
* Draw the flags of a column form again, for `type`, with
|
|
74110
|
+
* `current` checked.
|
|
74111
|
+
***************************************************************/
|
|
74112
|
+
function redraw_flags(gobj, $form, type, current) {
|
|
74113
|
+
let $holder = $form.querySelector(".SCHEMA_FLAGS");
|
|
74114
|
+
let $new = createElement2(flags_field(gobj, type, current));
|
|
74115
|
+
$holder.parentNode.replaceChild($new, $holder);
|
|
74116
|
+
refresh_language($new, t);
|
|
74117
|
+
}
|
|
74118
|
+
/***************************************************************
|
|
73968
74119
|
* The flags of a column, as checkboxes that say what they do.
|
|
73969
74120
|
*
|
|
73970
74121
|
* Grouped the way they act, greyed when they are meaningless on
|
|
@@ -74038,7 +74189,7 @@ function read_flags($root) {
|
|
|
74038
74189
|
* Offering a field that silently does something else is worse
|
|
74039
74190
|
* than not offering it.
|
|
74040
74191
|
***************************************************************/
|
|
74041
|
-
function open_column_form(gobj, topic, col, prefill) {
|
|
74192
|
+
function open_column_form(gobj, topic, col, prefill, changes) {
|
|
74042
74193
|
let priv = gobj.priv;
|
|
74043
74194
|
let record = prefill || col && col.record || {};
|
|
74044
74195
|
let creating = !col;
|
|
@@ -74142,11 +74293,7 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
74142
74293
|
]);
|
|
74143
74294
|
let $type = $form.querySelector("[data-name=\"type\"]");
|
|
74144
74295
|
$type.addEventListener("change", () => {
|
|
74145
|
-
|
|
74146
|
-
let current = read_flags($form);
|
|
74147
|
-
let $new = createElement2(flags_field(gobj, $type.value, current));
|
|
74148
|
-
$holder.parentNode.replaceChild($new, $holder);
|
|
74149
|
-
refresh_language($new, t);
|
|
74296
|
+
redraw_flags(gobj, $form, $type.value, read_flags($form));
|
|
74150
74297
|
});
|
|
74151
74298
|
$form.addEventListener("change", (evt) => {
|
|
74152
74299
|
let $box = evt.target.closest(".SCHEMA_FLAG_BOX");
|
|
@@ -74158,15 +74305,17 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
74158
74305
|
evt.stopPropagation();
|
|
74159
74306
|
close_dialog(gobj);
|
|
74160
74307
|
});
|
|
74308
|
+
let initial = column_form_state($form);
|
|
74309
|
+
if (changes) apply_form_changes(gobj, $form, changes);
|
|
74161
74310
|
$form.querySelector(".SCHEMA_COL_FORM_SAVE").addEventListener("click", (evt) => {
|
|
74162
74311
|
evt.stopPropagation();
|
|
74163
|
-
let values =
|
|
74164
|
-
values.flag = read_flags($form);
|
|
74312
|
+
let values = column_form_state($form);
|
|
74165
74313
|
gobj_send_event(gobj, "EV_SAVE_COLUMN", {
|
|
74166
74314
|
topic: topic.name,
|
|
74167
74315
|
col: creating ? "" : col.name,
|
|
74168
74316
|
creating,
|
|
74169
74317
|
values,
|
|
74318
|
+
changed: creating ? values : form_changes(initial, values),
|
|
74170
74319
|
model_gen
|
|
74171
74320
|
}, gobj);
|
|
74172
74321
|
});
|
|
@@ -74186,7 +74335,7 @@ function stringify_field(value) {
|
|
|
74186
74335
|
* actually has: a pkey naming no column is a topic that does
|
|
74187
74336
|
* not open, and it is the first thing the validator looks for.
|
|
74188
74337
|
***************************************************************/
|
|
74189
|
-
function open_topic_form(gobj, treedb, topic) {
|
|
74338
|
+
function open_topic_form(gobj, treedb, topic, changes) {
|
|
74190
74339
|
let record = topic && topic.record || {};
|
|
74191
74340
|
let creating = !topic;
|
|
74192
74341
|
let col_names = topic ? topic.cols.map((c) => c.name) : [];
|
|
@@ -74281,12 +74430,16 @@ function open_topic_form(gobj, treedb, topic) {
|
|
|
74281
74430
|
evt.stopPropagation();
|
|
74282
74431
|
close_dialog(gobj);
|
|
74283
74432
|
});
|
|
74433
|
+
let initial = read_form($form);
|
|
74434
|
+
if (changes) apply_form_changes(gobj, $form, changes);
|
|
74284
74435
|
$form.querySelector(".SCHEMA_TOPIC_FORM_SAVE").addEventListener("click", (evt) => {
|
|
74285
74436
|
evt.stopPropagation();
|
|
74437
|
+
let values = read_form($form);
|
|
74286
74438
|
gobj_send_event(gobj, "EV_SAVE_TOPIC", {
|
|
74287
74439
|
topic: creating ? "" : topic.name,
|
|
74288
74440
|
creating,
|
|
74289
|
-
values
|
|
74441
|
+
values,
|
|
74442
|
+
changed: creating ? values : form_changes(initial, values),
|
|
74290
74443
|
model_gen
|
|
74291
74444
|
}, gobj);
|
|
74292
74445
|
});
|
|
@@ -75056,20 +75209,28 @@ function transport_dropped(gobj) {
|
|
|
75056
75209
|
function end_load(gobj) {
|
|
75057
75210
|
let priv = gobj.priv;
|
|
75058
75211
|
let seg = priv.pending_seg;
|
|
75212
|
+
let reopen = priv.reopen_form;
|
|
75059
75213
|
priv.pending_seg = null;
|
|
75214
|
+
priv.reopen_form = null;
|
|
75060
75215
|
if (priv.dialog && priv.dialog_gen !== priv.model_gen) {
|
|
75061
|
-
|
|
75216
|
+
if (!reopen || reopen.dialog !== priv.dialog) {
|
|
75217
|
+
reopen = null;
|
|
75218
|
+
log_warning(`${gobj_short_name(gobj)}: a dialog was open on the schemas the load replaced: closed`);
|
|
75219
|
+
yui_shell_show_error(yui_shell_of(gobj), "the schemas were read again: open the dialog again", { t });
|
|
75220
|
+
}
|
|
75062
75221
|
close_dialog(gobj);
|
|
75063
|
-
|
|
75064
|
-
|
|
75222
|
+
} else reopen = null;
|
|
75223
|
+
let ret = 0;
|
|
75065
75224
|
if (priv.model) {
|
|
75066
|
-
if (seg !== null)
|
|
75067
|
-
|
|
75225
|
+
if (seg !== null) ret = apply_seg(gobj, seg);
|
|
75226
|
+
else ret = go(gobj, priv.treedb_id, priv.topic_name, priv.diagram, false);
|
|
75227
|
+
} else {
|
|
75228
|
+
if (seg !== null) adopt_seg(gobj, seg);
|
|
75229
|
+
gobj_change_state(gobj, "ST_IDLE");
|
|
75230
|
+
render(gobj);
|
|
75068
75231
|
}
|
|
75069
|
-
if (
|
|
75070
|
-
|
|
75071
|
-
render(gobj);
|
|
75072
|
-
return 0;
|
|
75232
|
+
if (reopen) reopen_form(gobj, reopen);
|
|
75233
|
+
return ret;
|
|
75073
75234
|
}
|
|
75074
75235
|
/***************************************************************
|
|
75075
75236
|
* The queue is done, or gave up. Either way the model is what
|
|
@@ -75094,7 +75255,11 @@ function end_writes(gobj, error) {
|
|
|
75094
75255
|
render(gobj);
|
|
75095
75256
|
publish_check(gobj);
|
|
75096
75257
|
}
|
|
75097
|
-
|
|
75258
|
+
if (priv.refresh_after_write) {
|
|
75259
|
+
priv.refresh_after_write = false;
|
|
75260
|
+
priv.reload_after_write = false;
|
|
75261
|
+
request_model(gobj, false);
|
|
75262
|
+
} else reload_if_owed(gobj);
|
|
75098
75263
|
return error ? -1 : 0;
|
|
75099
75264
|
}
|
|
75100
75265
|
/***************************************************************
|
|
@@ -75322,7 +75487,7 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
75322
75487
|
return 0;
|
|
75323
75488
|
}
|
|
75324
75489
|
priv.pending--;
|
|
75325
|
-
if (result < 0) priv.load_error = comment ||
|
|
75490
|
+
if (result < 0) priv.load_error = comment || "cannot load the schemas";
|
|
75326
75491
|
else if (priv.records && Array.isArray(priv.records[topic_name])) priv.records[topic_name] = Array.isArray(data) ? data : [];
|
|
75327
75492
|
if (priv.pending > 0) return 0;
|
|
75328
75493
|
if (priv.load_error) {
|
|
@@ -75358,9 +75523,10 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
75358
75523
|
}
|
|
75359
75524
|
if (result < 0) return end_writes(gobj, comment || t("the treedb refused the write"));
|
|
75360
75525
|
priv.save_wrote = true;
|
|
75526
|
+
let record = null;
|
|
75361
75527
|
if (command === "delete-node") forget_record(gobj, topic_name, kw_get_str(gobj, md, "record_id", "", 0));
|
|
75362
75528
|
else {
|
|
75363
|
-
|
|
75529
|
+
record = is_object(data) ? data : Array.isArray(data) && is_object(data[0]) ? data[0] : null;
|
|
75364
75530
|
if (record) patch_record(gobj, topic_name, record);
|
|
75365
75531
|
else {
|
|
75366
75532
|
let not_sent = priv.save_queue.length - 1;
|
|
@@ -75368,20 +75534,22 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
75368
75534
|
if (not_sent > 0) yui_shell_show_error(yui_shell_of(gobj), "the treedb did not describe a write back: the writes after it were not sent", { t });
|
|
75369
75535
|
if (topic_name === T_TOPICS || topic_name === T_COLS) {
|
|
75370
75536
|
let write = priv.save_queue[0];
|
|
75371
|
-
mark_written(gobj, topic_name, write ? write.record : null);
|
|
75537
|
+
mark_written(gobj, topic_name, null, write ? write.record : null);
|
|
75372
75538
|
}
|
|
75373
75539
|
priv.reload_after_write = false;
|
|
75374
75540
|
priv.save_queue = [];
|
|
75375
75541
|
priv.save_return = "";
|
|
75376
75542
|
priv.save_wrote = false;
|
|
75377
75543
|
gobj_publish_event(gobj, "EV_RECORD_WRITTEN", { treedb_name: gobj_read_str_attr(gobj, "treedb_name") });
|
|
75378
|
-
|
|
75544
|
+
let refresh = priv.refresh_after_write;
|
|
75545
|
+
priv.refresh_after_write = false;
|
|
75546
|
+
request_model(gobj, !refresh);
|
|
75379
75547
|
return 0;
|
|
75380
75548
|
}
|
|
75381
75549
|
}
|
|
75382
75550
|
if (topic_name === T_TOPICS || topic_name === T_COLS) {
|
|
75383
75551
|
let write = priv.save_queue[0];
|
|
75384
|
-
mark_written(gobj, topic_name, write ? write.record : null);
|
|
75552
|
+
mark_written(gobj, topic_name, record, write ? write.record : null);
|
|
75385
75553
|
}
|
|
75386
75554
|
priv.save_queue.shift();
|
|
75387
75555
|
return run_next_write(gobj);
|
|
@@ -75438,25 +75606,34 @@ function late_write_done(gobj, command, topic_name, data) {
|
|
|
75438
75606
|
***************************************************************/
|
|
75439
75607
|
function mark_written_record(gobj, topic_name, record) {
|
|
75440
75608
|
let priv = gobj.priv;
|
|
75441
|
-
|
|
75609
|
+
let marked = 0;
|
|
75610
|
+
if (!record) return 0;
|
|
75442
75611
|
if (topic_name === T_TOPICS && typeof record.id === "string" && record.id) {
|
|
75443
75612
|
priv.written[record.id] = true;
|
|
75444
|
-
return;
|
|
75613
|
+
return 1;
|
|
75445
75614
|
}
|
|
75446
|
-
if (topic_name !== T_COLS) return;
|
|
75447
|
-
for (let ref of parse_fkey_ref(record.topics))
|
|
75615
|
+
if (topic_name !== T_COLS) return 0;
|
|
75616
|
+
for (let ref of parse_fkey_ref(record.topics)) {
|
|
75617
|
+
priv.written[ref.id] = true;
|
|
75618
|
+
marked++;
|
|
75619
|
+
}
|
|
75620
|
+
return marked;
|
|
75448
75621
|
}
|
|
75449
75622
|
/***************************************************************
|
|
75450
75623
|
* Remember which topic this write belongs to, which is what
|
|
75451
75624
|
* "its version still has to move" is asked about.
|
|
75625
|
+
*
|
|
75626
|
+
* Asked of the RECORD first: the one the store answered (a new
|
|
75627
|
+
* topic has its id only there), then the one queued (a column
|
|
75628
|
+
* names its topic in its fkey). The screen is the last resort,
|
|
75629
|
+
* and a poor one: an import writes topics the operator is not
|
|
75630
|
+
* on, and from the topics screen there is no topic on it at all.
|
|
75452
75631
|
***************************************************************/
|
|
75453
|
-
function mark_written(gobj, topic_name,
|
|
75632
|
+
function mark_written(gobj, topic_name, answered, queued) {
|
|
75454
75633
|
let priv = gobj.priv;
|
|
75634
|
+
if (mark_written_record(gobj, topic_name, answered) > 0) return;
|
|
75635
|
+
if (mark_written_record(gobj, topic_name, queued) > 0) return;
|
|
75455
75636
|
let topic = current_topic(gobj);
|
|
75456
|
-
if (topic_name === T_TOPICS && record && record.id) {
|
|
75457
|
-
priv.written[record.id] = true;
|
|
75458
|
-
return;
|
|
75459
|
-
}
|
|
75460
75637
|
if (topic) priv.written[topic.id] = true;
|
|
75461
75638
|
}
|
|
75462
75639
|
/***************************************************************
|
|
@@ -75522,6 +75699,21 @@ function ac_refresh$1(gobj, event, kw, src) {
|
|
|
75522
75699
|
return request_model(gobj, false);
|
|
75523
75700
|
}
|
|
75524
75701
|
/***************************************************************
|
|
75702
|
+
* EV_REFRESH while writes are in flight: the view's own Refresh
|
|
75703
|
+
* is busy then, so it is a host's (after a Save, say).
|
|
75704
|
+
*
|
|
75705
|
+
* Run when the writes END (end_writes()), not now. Run now, the
|
|
75706
|
+
* load replaced ST_SAVING and what was still queued was never
|
|
75707
|
+
* sent, with no word: nothing but the end of what is in flight
|
|
75708
|
+
* moves this view out of ST_LOADING or ST_SAVING.
|
|
75709
|
+
***************************************************************/
|
|
75710
|
+
function ac_refresh_after_the_writes(gobj, event, kw, src) {
|
|
75711
|
+
let priv = gobj.priv;
|
|
75712
|
+
log_warning(`${gobj_short_name(gobj)}: ${event} while writes are in flight: the schemas are read again when the writes end`);
|
|
75713
|
+
priv.refresh_after_write = true;
|
|
75714
|
+
return 0;
|
|
75715
|
+
}
|
|
75716
|
+
/***************************************************************
|
|
75525
75717
|
* What a DIALOG sends while the model is being read again: the
|
|
75526
75718
|
* Save of a form left open when the reload started, a
|
|
75527
75719
|
* confirmation, an import. The loading screen took the rest of
|
|
@@ -75696,7 +75888,13 @@ function ac_save_column(gobj, event, kw, src) {
|
|
|
75696
75888
|
let topic = find_topic(priv.model, priv.treedb_id, kw.topic);
|
|
75697
75889
|
let col = kw.creating ? null : find_col(priv.model, priv.treedb_id, kw.topic, kw.col);
|
|
75698
75890
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75699
|
-
if (reload_first(gobj, event
|
|
75891
|
+
if (reload_first(gobj, event, {
|
|
75892
|
+
form: "column",
|
|
75893
|
+
topic: kw.topic,
|
|
75894
|
+
col: kw.col,
|
|
75895
|
+
creating: !!kw.creating,
|
|
75896
|
+
changed: kw.changed || {}
|
|
75897
|
+
})) return -1;
|
|
75700
75898
|
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75701
75899
|
if (!topic || !kw.creating && !col) {
|
|
75702
75900
|
log_error(`${gobj_short_name(gobj)}: ${event} names no column: ${kw.topic}.${kw.col}`);
|
|
@@ -75824,7 +76022,13 @@ function ac_save_topic(gobj, event, kw, src) {
|
|
|
75824
76022
|
let treedb = current_treedb(gobj);
|
|
75825
76023
|
let topic = kw.creating ? null : find_topic(priv.model, priv.treedb_id, kw.topic);
|
|
75826
76024
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75827
|
-
if (reload_first(gobj, event
|
|
76025
|
+
if (reload_first(gobj, event, {
|
|
76026
|
+
form: "topic",
|
|
76027
|
+
topic: kw.topic,
|
|
76028
|
+
col: "",
|
|
76029
|
+
creating: !!kw.creating,
|
|
76030
|
+
changed: kw.changed || {}
|
|
76031
|
+
})) return -1;
|
|
75828
76032
|
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75829
76033
|
if (!treedb || !kw.creating && !topic) {
|
|
75830
76034
|
log_error(`${gobj_short_name(gobj)}: ${event} names no topic: ${kw.topic}`);
|
|
@@ -76287,7 +76491,11 @@ function create_gclass$1(gclass_name) {
|
|
|
76287
76491
|
null
|
|
76288
76492
|
]
|
|
76289
76493
|
])],
|
|
76290
|
-
["ST_SAVING", COMMON.
|
|
76494
|
+
["ST_SAVING", COMMON.filter((a) => a[0] !== "EV_REFRESH").concat([[
|
|
76495
|
+
"EV_REFRESH",
|
|
76496
|
+
ac_refresh_after_the_writes,
|
|
76497
|
+
null
|
|
76498
|
+
]])]
|
|
76291
76499
|
];
|
|
76292
76500
|
const event_types = [
|
|
76293
76501
|
["EV_MT_COMMAND_ANSWER", event_flag_t.EVF_PUBLIC_EVENT],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuneta/gobj-ui",
|
|
3
|
-
"version": "7.25.
|
|
3
|
+
"version": "7.25.17",
|
|
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.
|
|
33
|
+
"@yuneta/gobj-js": "^7.25.3",
|
|
34
34
|
"vite": "^8.2.1",
|
|
35
35
|
"vitest": "^4.1.10"
|
|
36
36
|
},
|