@yuneta/gobj-ui 7.25.15 → 7.25.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -4
- package/dist/gobj-ui.cjs.js +222 -41
- package/dist/gobj-ui.es.js +222 -41
- package/package.json +2 -2
- package/src/c_g6_nodes_tree.js +37 -4
- package/src/c_yui_schema_editor.js +239 -29
- 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 +152 -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_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
|
}
|
|
@@ -72329,6 +72365,8 @@ var PRIVATE_DATA$1 = {
|
|
|
72329
72365
|
dropped_round: 0,
|
|
72330
72366
|
dropped_write: 0,
|
|
72331
72367
|
reload_after_write: false,
|
|
72368
|
+
refresh_after_write: false,
|
|
72369
|
+
reopen_form: null,
|
|
72332
72370
|
pending_seg: null,
|
|
72333
72371
|
import_plan: null,
|
|
72334
72372
|
import_pane: null,
|
|
@@ -72534,14 +72572,61 @@ function owes_reload(gobj) {
|
|
|
72534
72572
|
let state = gobj_current_state(gobj);
|
|
72535
72573
|
return gobj.priv.reload_on_open && transport_in_session(gobj) && state !== "ST_LOADING" && state !== "ST_SAVING";
|
|
72536
72574
|
}
|
|
72537
|
-
function reload_first(gobj, event) {
|
|
72575
|
+
function reload_first(gobj, event, reopen) {
|
|
72576
|
+
let priv = gobj.priv;
|
|
72538
72577
|
if (!owes_reload(gobj)) return false;
|
|
72539
|
-
|
|
72578
|
+
priv.reload_on_open = false;
|
|
72579
|
+
if (reopen && priv.dialog) {
|
|
72580
|
+
priv.reopen_form = Object.assign(json_deep_copy(reopen), {
|
|
72581
|
+
dialog: priv.dialog,
|
|
72582
|
+
treedb_id: priv.treedb_id
|
|
72583
|
+
});
|
|
72584
|
+
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`);
|
|
72585
|
+
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 });
|
|
72586
|
+
request_model(gobj, true);
|
|
72587
|
+
return true;
|
|
72588
|
+
}
|
|
72540
72589
|
log_warning(`${gobj_short_name(gobj)}: ${event} refused, the schemas shown may be out of date: they are read again first`);
|
|
72541
72590
|
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
72591
|
request_model(gobj, true);
|
|
72543
72592
|
return true;
|
|
72544
72593
|
}
|
|
72594
|
+
/***************************************************************
|
|
72595
|
+
* The form reload_first() took down, opened again on the model
|
|
72596
|
+
* the load just made, with the operator's changes on top.
|
|
72597
|
+
*
|
|
72598
|
+
* Only where it can mean the same thing: on the treedb it was
|
|
72599
|
+
* opened on, on the screen whose Save it has, and on a record
|
|
72600
|
+
* that is still there. Otherwise it is not opened, and that is
|
|
72601
|
+
* said -- a form opened on another treedb, or on nothing, would
|
|
72602
|
+
* save somewhere the operator never meant.
|
|
72603
|
+
***************************************************************/
|
|
72604
|
+
function reopen_form(gobj, r) {
|
|
72605
|
+
let priv = gobj.priv;
|
|
72606
|
+
let state = gobj_current_state(gobj);
|
|
72607
|
+
let treedb = current_treedb(gobj);
|
|
72608
|
+
let topic = null;
|
|
72609
|
+
let col = null;
|
|
72610
|
+
let fits = false;
|
|
72611
|
+
if (treedb && r.treedb_id === priv.treedb_id) {
|
|
72612
|
+
if (r.form === "column" && state === "ST_COLUMNS") {
|
|
72613
|
+
topic = find_topic(priv.model, priv.treedb_id, r.topic);
|
|
72614
|
+
col = topic && !r.creating ? find_col(priv.model, priv.treedb_id, r.topic, r.col) : null;
|
|
72615
|
+
fits = !!topic && (r.creating || !!col);
|
|
72616
|
+
} else if (r.form === "topic" && state === "ST_TOPICS") {
|
|
72617
|
+
topic = r.creating ? null : find_topic(priv.model, priv.treedb_id, r.topic);
|
|
72618
|
+
fits = r.creating || !!topic;
|
|
72619
|
+
}
|
|
72620
|
+
}
|
|
72621
|
+
if (!fits) {
|
|
72622
|
+
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})`);
|
|
72623
|
+
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 });
|
|
72624
|
+
return -1;
|
|
72625
|
+
}
|
|
72626
|
+
if (r.form === "column") open_column_form(gobj, topic, col, null, r.changed);
|
|
72627
|
+
else open_topic_form(gobj, treedb, topic, r.changed);
|
|
72628
|
+
return 0;
|
|
72629
|
+
}
|
|
72545
72630
|
function reload_after_move(gobj) {
|
|
72546
72631
|
if (!owes_reload(gobj)) return 0;
|
|
72547
72632
|
gobj.priv.reload_on_open = false;
|
|
@@ -72687,7 +72772,7 @@ function build_model(gobj) {
|
|
|
72687
72772
|
* measurement of "changed since" can be measured against.
|
|
72688
72773
|
*
|
|
72689
72774
|
* `written` is forgotten only by an EV_REFRESH (the view's own
|
|
72690
|
-
* Refresh button, or a host that sends one). Since
|
|
72775
|
+
* Refresh button, or a host that sends one). Since 7.23.196 a write moves no
|
|
72691
72776
|
* version, so `written` is the draft chip of what this session
|
|
72692
72777
|
* wrote and no longer half of a version measurement: a reload of
|
|
72693
72778
|
* the reconnect, or of a write that turned out done, forgot the
|
|
@@ -73965,6 +74050,55 @@ function read_form($root) {
|
|
|
73965
74050
|
return out;
|
|
73966
74051
|
}
|
|
73967
74052
|
/***************************************************************
|
|
74053
|
+
* A column form as its Save sends it: the fields and the flags.
|
|
74054
|
+
***************************************************************/
|
|
74055
|
+
function column_form_state($form) {
|
|
74056
|
+
let values = read_form($form);
|
|
74057
|
+
values.flag = read_flags($form);
|
|
74058
|
+
return values;
|
|
74059
|
+
}
|
|
74060
|
+
/***************************************************************
|
|
74061
|
+
* The fields the operator CHANGED: those whose value is not the
|
|
74062
|
+
* one the form was opened with.
|
|
74063
|
+
***************************************************************/
|
|
74064
|
+
function form_changes(initial, values) {
|
|
74065
|
+
let changed = {};
|
|
74066
|
+
for (let name of Object.keys(values)) if (JSON.stringify(values[name]) !== JSON.stringify(initial[name])) changed[name] = values[name];
|
|
74067
|
+
return changed;
|
|
74068
|
+
}
|
|
74069
|
+
/***************************************************************
|
|
74070
|
+
* Put changes back into a form just built (reopen_form()). The
|
|
74071
|
+
* flags are drawn again for the type the changes leave, holding
|
|
74072
|
+
* the flags they name, so none of them is hidden by the type.
|
|
74073
|
+
***************************************************************/
|
|
74074
|
+
function apply_form_changes(gobj, $form, changes) {
|
|
74075
|
+
for (let name of Object.keys(changes)) {
|
|
74076
|
+
if (name === "flag") continue;
|
|
74077
|
+
let $control = $form.querySelector(`[data-name="${name}"]`);
|
|
74078
|
+
if (!$control) {
|
|
74079
|
+
log_warning(`${gobj_short_name(gobj)}: a change of '${name}' has no field in the form opened again: not put back`);
|
|
74080
|
+
continue;
|
|
74081
|
+
}
|
|
74082
|
+
if ($control.type === "checkbox") $control.checked = !!changes[name];
|
|
74083
|
+
else $control.value = changes[name];
|
|
74084
|
+
}
|
|
74085
|
+
let $type = $form.querySelector("[data-name=\"type\"]");
|
|
74086
|
+
if ($type && $form.querySelector(".SCHEMA_FLAGS")) {
|
|
74087
|
+
let flags = Array.isArray(changes.flag) ? changes.flag : read_flags($form);
|
|
74088
|
+
redraw_flags(gobj, $form, $type.value, flags);
|
|
74089
|
+
}
|
|
74090
|
+
}
|
|
74091
|
+
/***************************************************************
|
|
74092
|
+
* Draw the flags of a column form again, for `type`, with
|
|
74093
|
+
* `current` checked.
|
|
74094
|
+
***************************************************************/
|
|
74095
|
+
function redraw_flags(gobj, $form, type, current) {
|
|
74096
|
+
let $holder = $form.querySelector(".SCHEMA_FLAGS");
|
|
74097
|
+
let $new = createElement2(flags_field(gobj, type, current));
|
|
74098
|
+
$holder.parentNode.replaceChild($new, $holder);
|
|
74099
|
+
refresh_language($new, t);
|
|
74100
|
+
}
|
|
74101
|
+
/***************************************************************
|
|
73968
74102
|
* The flags of a column, as checkboxes that say what they do.
|
|
73969
74103
|
*
|
|
73970
74104
|
* Grouped the way they act, greyed when they are meaningless on
|
|
@@ -74038,7 +74172,7 @@ function read_flags($root) {
|
|
|
74038
74172
|
* Offering a field that silently does something else is worse
|
|
74039
74173
|
* than not offering it.
|
|
74040
74174
|
***************************************************************/
|
|
74041
|
-
function open_column_form(gobj, topic, col, prefill) {
|
|
74175
|
+
function open_column_form(gobj, topic, col, prefill, changes) {
|
|
74042
74176
|
let priv = gobj.priv;
|
|
74043
74177
|
let record = prefill || col && col.record || {};
|
|
74044
74178
|
let creating = !col;
|
|
@@ -74142,11 +74276,7 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
74142
74276
|
]);
|
|
74143
74277
|
let $type = $form.querySelector("[data-name=\"type\"]");
|
|
74144
74278
|
$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);
|
|
74279
|
+
redraw_flags(gobj, $form, $type.value, read_flags($form));
|
|
74150
74280
|
});
|
|
74151
74281
|
$form.addEventListener("change", (evt) => {
|
|
74152
74282
|
let $box = evt.target.closest(".SCHEMA_FLAG_BOX");
|
|
@@ -74158,15 +74288,17 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
74158
74288
|
evt.stopPropagation();
|
|
74159
74289
|
close_dialog(gobj);
|
|
74160
74290
|
});
|
|
74291
|
+
let initial = column_form_state($form);
|
|
74292
|
+
if (changes) apply_form_changes(gobj, $form, changes);
|
|
74161
74293
|
$form.querySelector(".SCHEMA_COL_FORM_SAVE").addEventListener("click", (evt) => {
|
|
74162
74294
|
evt.stopPropagation();
|
|
74163
|
-
let values =
|
|
74164
|
-
values.flag = read_flags($form);
|
|
74295
|
+
let values = column_form_state($form);
|
|
74165
74296
|
gobj_send_event(gobj, "EV_SAVE_COLUMN", {
|
|
74166
74297
|
topic: topic.name,
|
|
74167
74298
|
col: creating ? "" : col.name,
|
|
74168
74299
|
creating,
|
|
74169
74300
|
values,
|
|
74301
|
+
changed: creating ? values : form_changes(initial, values),
|
|
74170
74302
|
model_gen
|
|
74171
74303
|
}, gobj);
|
|
74172
74304
|
});
|
|
@@ -74186,7 +74318,7 @@ function stringify_field(value) {
|
|
|
74186
74318
|
* actually has: a pkey naming no column is a topic that does
|
|
74187
74319
|
* not open, and it is the first thing the validator looks for.
|
|
74188
74320
|
***************************************************************/
|
|
74189
|
-
function open_topic_form(gobj, treedb, topic) {
|
|
74321
|
+
function open_topic_form(gobj, treedb, topic, changes) {
|
|
74190
74322
|
let record = topic && topic.record || {};
|
|
74191
74323
|
let creating = !topic;
|
|
74192
74324
|
let col_names = topic ? topic.cols.map((c) => c.name) : [];
|
|
@@ -74281,12 +74413,16 @@ function open_topic_form(gobj, treedb, topic) {
|
|
|
74281
74413
|
evt.stopPropagation();
|
|
74282
74414
|
close_dialog(gobj);
|
|
74283
74415
|
});
|
|
74416
|
+
let initial = read_form($form);
|
|
74417
|
+
if (changes) apply_form_changes(gobj, $form, changes);
|
|
74284
74418
|
$form.querySelector(".SCHEMA_TOPIC_FORM_SAVE").addEventListener("click", (evt) => {
|
|
74285
74419
|
evt.stopPropagation();
|
|
74420
|
+
let values = read_form($form);
|
|
74286
74421
|
gobj_send_event(gobj, "EV_SAVE_TOPIC", {
|
|
74287
74422
|
topic: creating ? "" : topic.name,
|
|
74288
74423
|
creating,
|
|
74289
|
-
values
|
|
74424
|
+
values,
|
|
74425
|
+
changed: creating ? values : form_changes(initial, values),
|
|
74290
74426
|
model_gen
|
|
74291
74427
|
}, gobj);
|
|
74292
74428
|
});
|
|
@@ -75056,20 +75192,28 @@ function transport_dropped(gobj) {
|
|
|
75056
75192
|
function end_load(gobj) {
|
|
75057
75193
|
let priv = gobj.priv;
|
|
75058
75194
|
let seg = priv.pending_seg;
|
|
75195
|
+
let reopen = priv.reopen_form;
|
|
75059
75196
|
priv.pending_seg = null;
|
|
75197
|
+
priv.reopen_form = null;
|
|
75060
75198
|
if (priv.dialog && priv.dialog_gen !== priv.model_gen) {
|
|
75061
|
-
|
|
75199
|
+
if (!reopen || reopen.dialog !== priv.dialog) {
|
|
75200
|
+
reopen = null;
|
|
75201
|
+
log_warning(`${gobj_short_name(gobj)}: a dialog was open on the schemas the load replaced: closed`);
|
|
75202
|
+
yui_shell_show_error(yui_shell_of(gobj), "the schemas were read again: open the dialog again", { t });
|
|
75203
|
+
}
|
|
75062
75204
|
close_dialog(gobj);
|
|
75063
|
-
|
|
75064
|
-
|
|
75205
|
+
} else reopen = null;
|
|
75206
|
+
let ret = 0;
|
|
75065
75207
|
if (priv.model) {
|
|
75066
|
-
if (seg !== null)
|
|
75067
|
-
|
|
75208
|
+
if (seg !== null) ret = apply_seg(gobj, seg);
|
|
75209
|
+
else ret = go(gobj, priv.treedb_id, priv.topic_name, priv.diagram, false);
|
|
75210
|
+
} else {
|
|
75211
|
+
if (seg !== null) adopt_seg(gobj, seg);
|
|
75212
|
+
gobj_change_state(gobj, "ST_IDLE");
|
|
75213
|
+
render(gobj);
|
|
75068
75214
|
}
|
|
75069
|
-
if (
|
|
75070
|
-
|
|
75071
|
-
render(gobj);
|
|
75072
|
-
return 0;
|
|
75215
|
+
if (reopen) reopen_form(gobj, reopen);
|
|
75216
|
+
return ret;
|
|
75073
75217
|
}
|
|
75074
75218
|
/***************************************************************
|
|
75075
75219
|
* The queue is done, or gave up. Either way the model is what
|
|
@@ -75094,7 +75238,11 @@ function end_writes(gobj, error) {
|
|
|
75094
75238
|
render(gobj);
|
|
75095
75239
|
publish_check(gobj);
|
|
75096
75240
|
}
|
|
75097
|
-
|
|
75241
|
+
if (priv.refresh_after_write) {
|
|
75242
|
+
priv.refresh_after_write = false;
|
|
75243
|
+
priv.reload_after_write = false;
|
|
75244
|
+
request_model(gobj, false);
|
|
75245
|
+
} else reload_if_owed(gobj);
|
|
75098
75246
|
return error ? -1 : 0;
|
|
75099
75247
|
}
|
|
75100
75248
|
/***************************************************************
|
|
@@ -75375,7 +75523,9 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
75375
75523
|
priv.save_return = "";
|
|
75376
75524
|
priv.save_wrote = false;
|
|
75377
75525
|
gobj_publish_event(gobj, "EV_RECORD_WRITTEN", { treedb_name: gobj_read_str_attr(gobj, "treedb_name") });
|
|
75378
|
-
|
|
75526
|
+
let refresh = priv.refresh_after_write;
|
|
75527
|
+
priv.refresh_after_write = false;
|
|
75528
|
+
request_model(gobj, !refresh);
|
|
75379
75529
|
return 0;
|
|
75380
75530
|
}
|
|
75381
75531
|
}
|
|
@@ -75522,6 +75672,21 @@ function ac_refresh$1(gobj, event, kw, src) {
|
|
|
75522
75672
|
return request_model(gobj, false);
|
|
75523
75673
|
}
|
|
75524
75674
|
/***************************************************************
|
|
75675
|
+
* EV_REFRESH while writes are in flight: the view's own Refresh
|
|
75676
|
+
* is busy then, so it is a host's (after a Save, say).
|
|
75677
|
+
*
|
|
75678
|
+
* Run when the writes END (end_writes()), not now. Run now, the
|
|
75679
|
+
* load replaced ST_SAVING and what was still queued was never
|
|
75680
|
+
* sent, with no word: nothing but the end of what is in flight
|
|
75681
|
+
* moves this view out of ST_LOADING or ST_SAVING.
|
|
75682
|
+
***************************************************************/
|
|
75683
|
+
function ac_refresh_after_the_writes(gobj, event, kw, src) {
|
|
75684
|
+
let priv = gobj.priv;
|
|
75685
|
+
log_warning(`${gobj_short_name(gobj)}: ${event} while writes are in flight: the schemas are read again when the writes end`);
|
|
75686
|
+
priv.refresh_after_write = true;
|
|
75687
|
+
return 0;
|
|
75688
|
+
}
|
|
75689
|
+
/***************************************************************
|
|
75525
75690
|
* What a DIALOG sends while the model is being read again: the
|
|
75526
75691
|
* Save of a form left open when the reload started, a
|
|
75527
75692
|
* confirmation, an import. The loading screen took the rest of
|
|
@@ -75696,7 +75861,13 @@ function ac_save_column(gobj, event, kw, src) {
|
|
|
75696
75861
|
let topic = find_topic(priv.model, priv.treedb_id, kw.topic);
|
|
75697
75862
|
let col = kw.creating ? null : find_col(priv.model, priv.treedb_id, kw.topic, kw.col);
|
|
75698
75863
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75699
|
-
if (reload_first(gobj, event
|
|
75864
|
+
if (reload_first(gobj, event, {
|
|
75865
|
+
form: "column",
|
|
75866
|
+
topic: kw.topic,
|
|
75867
|
+
col: kw.col,
|
|
75868
|
+
creating: !!kw.creating,
|
|
75869
|
+
changed: kw.changed || {}
|
|
75870
|
+
})) return -1;
|
|
75700
75871
|
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75701
75872
|
if (!topic || !kw.creating && !col) {
|
|
75702
75873
|
log_error(`${gobj_short_name(gobj)}: ${event} names no column: ${kw.topic}.${kw.col}`);
|
|
@@ -75824,7 +75995,13 @@ function ac_save_topic(gobj, event, kw, src) {
|
|
|
75824
75995
|
let treedb = current_treedb(gobj);
|
|
75825
75996
|
let topic = kw.creating ? null : find_topic(priv.model, priv.treedb_id, kw.topic);
|
|
75826
75997
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75827
|
-
if (reload_first(gobj, event
|
|
75998
|
+
if (reload_first(gobj, event, {
|
|
75999
|
+
form: "topic",
|
|
76000
|
+
topic: kw.topic,
|
|
76001
|
+
col: "",
|
|
76002
|
+
creating: !!kw.creating,
|
|
76003
|
+
changed: kw.changed || {}
|
|
76004
|
+
})) return -1;
|
|
75828
76005
|
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75829
76006
|
if (!treedb || !kw.creating && !topic) {
|
|
75830
76007
|
log_error(`${gobj_short_name(gobj)}: ${event} names no topic: ${kw.topic}`);
|
|
@@ -76287,7 +76464,11 @@ function create_gclass$1(gclass_name) {
|
|
|
76287
76464
|
null
|
|
76288
76465
|
]
|
|
76289
76466
|
])],
|
|
76290
|
-
["ST_SAVING", COMMON.
|
|
76467
|
+
["ST_SAVING", COMMON.filter((a) => a[0] !== "EV_REFRESH").concat([[
|
|
76468
|
+
"EV_REFRESH",
|
|
76469
|
+
ac_refresh_after_the_writes,
|
|
76470
|
+
null
|
|
76471
|
+
]])]
|
|
76291
76472
|
];
|
|
76292
76473
|
const event_types = [
|
|
76293
76474
|
["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.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/gobj-ui.cjs.js",
|
|
6
6
|
"module": "dist/gobj-ui.es.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@rollup/plugin-terser": "^1.0.0",
|
|
32
32
|
"@vitest/coverage-v8": "^4.1.10",
|
|
33
|
-
"@yuneta/gobj-js": "^7.
|
|
33
|
+
"@yuneta/gobj-js": "^7.25.2",
|
|
34
34
|
"vite": "^8.2.1",
|
|
35
35
|
"vitest": "^4.1.10"
|
|
36
36
|
},
|
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -493,6 +493,7 @@ let PRIVATE_DATA = {
|
|
|
493
493
|
__graphs__: [], // Rows of __graphs__
|
|
494
494
|
_graph_properties: {}, // topic_name → {nodes: {node_id: {x,y,size,...}}}
|
|
495
495
|
_saved_graph_properties: {}, // the same, as the BACKEND has it: what a Save compares against
|
|
496
|
+
_graphs_writes_owed: {}, // topic_name → true: a __graphs__ write the host said did not land
|
|
496
497
|
yet_showed: false,
|
|
497
498
|
edit_mode: false,
|
|
498
499
|
operation_mode: null,
|
|
@@ -3283,6 +3284,9 @@ function save_topic_graph_properties(gobj, topic_name)
|
|
|
3283
3284
|
* The host says when one does NOT land (EV_GRAPHS_WRITE_REFUSED),
|
|
3284
3285
|
* and the next Save writes the topic again. */
|
|
3285
3286
|
priv._saved_graph_properties[topic_name] = json_deep_copy(properties);
|
|
3287
|
+
/* Paid: this is the write that was owed, if one was. Refused
|
|
3288
|
+
* again, EV_GRAPHS_WRITE_REFUSED owes it again. */
|
|
3289
|
+
delete priv._graphs_writes_owed[topic_name];
|
|
3286
3290
|
|
|
3287
3291
|
let kw_update = {
|
|
3288
3292
|
treedb_name: priv.treedb_name,
|
|
@@ -3388,9 +3392,16 @@ function update_history_buttons(gobj)
|
|
|
3388
3392
|
disableElements($container, ".EV_HISTORY_UNDO");
|
|
3389
3393
|
set_active_state($container, ".EV_HISTORY_UNDO", false);
|
|
3390
3394
|
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3395
|
+
/* No more undos: the graph is back to what was loaded
|
|
3396
|
+
* or saved -- unless a write of it did not land. That
|
|
3397
|
+
* one is still owed, and only a Save pays it. */
|
|
3398
|
+
if(graphs_write_is_owed(gobj)) {
|
|
3399
|
+
enableElements($container, ".EV_SAVE_GRAPH");
|
|
3400
|
+
set_submit_state($container, ".EV_SAVE_GRAPH", true);
|
|
3401
|
+
} else {
|
|
3402
|
+
disableElements($container, ".EV_SAVE_GRAPH");
|
|
3403
|
+
set_submit_state($container, ".EV_SAVE_GRAPH", false);
|
|
3404
|
+
}
|
|
3394
3405
|
}
|
|
3395
3406
|
} else {
|
|
3396
3407
|
disableElements($container, ".EV_HISTORY_REDO");
|
|
@@ -4763,6 +4774,17 @@ function run_preview_undo(gobj, key)
|
|
|
4763
4774
|
}
|
|
4764
4775
|
}
|
|
4765
4776
|
|
|
4777
|
+
/************************************************************
|
|
4778
|
+
* Is a `__graphs__` write owed? The host said one did not land
|
|
4779
|
+
* (EV_GRAPHS_WRITE_REFUSED), and no Save has written that topic
|
|
4780
|
+
* since. The Save button stays lit while it is: the history
|
|
4781
|
+
* knows nothing of it, so `canUndo()` alone would put it out.
|
|
4782
|
+
************************************************************/
|
|
4783
|
+
function graphs_write_is_owed(gobj)
|
|
4784
|
+
{
|
|
4785
|
+
return Object.keys(gobj.priv._graphs_writes_owed).length > 0;
|
|
4786
|
+
}
|
|
4787
|
+
|
|
4766
4788
|
function mark_graph_dirty(gobj)
|
|
4767
4789
|
{
|
|
4768
4790
|
let $container = gobj_read_attr(gobj, "$container");
|
|
@@ -10346,6 +10368,11 @@ function ac_clear_data(gobj, event, kw, src)
|
|
|
10346
10368
|
|
|
10347
10369
|
gobj_write_attr(gobj, "records", {});
|
|
10348
10370
|
|
|
10371
|
+
/* A write owed is owed on the arrangement being thrown away: the
|
|
10372
|
+
* reload brings what the backend holds, and that is what the view
|
|
10373
|
+
* will hold. */
|
|
10374
|
+
priv._graphs_writes_owed = {};
|
|
10375
|
+
|
|
10349
10376
|
/* The node counters belong to the data that is going away: a refresh
|
|
10350
10377
|
* that kept them would decide the layout on the previous treedb. */
|
|
10351
10378
|
priv._nodes_total = 0;
|
|
@@ -10495,10 +10522,13 @@ function ac_save_graph(gobj, event, kw, src)
|
|
|
10495
10522
|
let history = graph_get_plugin(gobj, "history");
|
|
10496
10523
|
if(history) {
|
|
10497
10524
|
history.clear();
|
|
10498
|
-
update_history_buttons(gobj);
|
|
10499
10525
|
}
|
|
10500
10526
|
|
|
10501
10527
|
save_geometry(gobj); // Publish an EV_UPDATE_NODE of each node
|
|
10528
|
+
|
|
10529
|
+
/* After the writes: they pay a write owed, and the buttons
|
|
10530
|
+
* are repainted from what is still owed. */
|
|
10531
|
+
update_history_buttons(gobj);
|
|
10502
10532
|
}
|
|
10503
10533
|
|
|
10504
10534
|
return 0;
|
|
@@ -10526,6 +10556,9 @@ function ac_graphs_write_refused(gobj, event, kw, src)
|
|
|
10526
10556
|
log_warning(`${gobj_short_name(gobj)}: the arrangement of '${topic_name}' ` +
|
|
10527
10557
|
`was not saved: the next Save writes it again`);
|
|
10528
10558
|
forget_refused_graphs_write(priv._saved_graph_properties, topic_name);
|
|
10559
|
+
/* Owed until a Save writes it: update_history_buttons() keeps
|
|
10560
|
+
* the Save lit while it is, in edition and on entering it. */
|
|
10561
|
+
priv._graphs_writes_owed[topic_name] = true;
|
|
10529
10562
|
if(priv.edit_mode) {
|
|
10530
10563
|
mark_graph_dirty(gobj);
|
|
10531
10564
|
}
|