@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.
@@ -3437,8 +3437,28 @@ function build_dialog(shell, message, buttons, opts) {
3437
3437
  if ($primary) $primary.focus();
3438
3438
  });
3439
3439
  }
3440
+ /***************************************************************
3441
+ * The labels a confirmation shows when the caller names none.
3442
+ *
3443
+ * They are i18n KEYS, lower-case like every key: a button
3444
+ * translates its label with the app's t() -- its text, its title
3445
+ * and its aria-label. Until 7.25.16 they were "OK", "Yes", "No",
3446
+ * "Delete" and "Cancel", keys that no locale carries, so a dialog
3447
+ * that took the defaults read in English in every language.
3448
+ *
3449
+ * Written as `i18n:` entries so the validate-locales script of a
3450
+ * consumer finds them when it scans this module: an app that
3451
+ * mounts these dialogs must define the five keys.
3452
+ ***************************************************************/
3453
+ var DEFAULT_LABEL = Object.freeze({
3454
+ ok: Object.freeze({ i18n: "ok" }),
3455
+ yes: Object.freeze({ i18n: "yes" }),
3456
+ no: Object.freeze({ i18n: "no" }),
3457
+ delete: Object.freeze({ i18n: "delete" }),
3458
+ cancel: Object.freeze({ i18n: "cancel" })
3459
+ });
3440
3460
  function yui_shell_confirm_ok(shell, message, opts) {
3441
- let label = opts && opts.ok_label || "OK";
3461
+ let label = opts && opts.ok_label || DEFAULT_LABEL.ok.i18n;
3442
3462
  if (!opts || !opts.type) opts = Object.assign({}, opts, { type: "success" });
3443
3463
  return build_dialog(shell, message, [{
3444
3464
  label,
@@ -3447,8 +3467,8 @@ function yui_shell_confirm_ok(shell, message, opts) {
3447
3467
  }], opts).then(() => void 0);
3448
3468
  }
3449
3469
  function yui_shell_confirm_yesno(shell, message, opts) {
3450
- let yes_label = opts && opts.yes_label || "Yes";
3451
- let no_label = opts && opts.no_label || "No";
3470
+ let yes_label = opts && opts.yes_label || DEFAULT_LABEL.yes.i18n;
3471
+ let no_label = opts && opts.no_label || DEFAULT_LABEL.no.i18n;
3452
3472
  return build_dialog(shell, message, [{
3453
3473
  label: yes_label,
3454
3474
  value: "yes",
@@ -3473,8 +3493,8 @@ function yui_shell_confirm_yesno(shell, message, opts) {
3473
3493
  * pressed.
3474
3494
  ***************************************************************/
3475
3495
  function yui_shell_confirm_danger(shell, message, opts) {
3476
- let confirm_label = opts && opts.confirm_label || "Delete";
3477
- let cancel_label = opts && opts.cancel_label || "Cancel";
3496
+ let confirm_label = opts && opts.confirm_label || DEFAULT_LABEL.delete.i18n;
3497
+ let cancel_label = opts && opts.cancel_label || DEFAULT_LABEL.cancel.i18n;
3478
3498
  if (!opts || !opts.type) opts = Object.assign({}, opts, { type: "danger" });
3479
3499
  return build_dialog(shell, message, [{
3480
3500
  label: confirm_label,
@@ -3486,9 +3506,9 @@ function yui_shell_confirm_danger(shell, message, opts) {
3486
3506
  }], opts).then((v) => v === "confirm");
3487
3507
  }
3488
3508
  function yui_shell_confirm_yesnocancel(shell, message, opts) {
3489
- let yes_label = opts && opts.yes_label || "Yes";
3490
- let no_label = opts && opts.no_label || "No";
3491
- let cancel_label = opts && opts.cancel_label || "Cancel";
3509
+ let yes_label = opts && opts.yes_label || DEFAULT_LABEL.yes.i18n;
3510
+ let no_label = opts && opts.no_label || DEFAULT_LABEL.no.i18n;
3511
+ let cancel_label = opts && opts.cancel_label || DEFAULT_LABEL.cancel.i18n;
3492
3512
  return build_dialog(shell, message, [
3493
3513
  {
3494
3514
  label: yes_label,
@@ -59232,6 +59252,7 @@ var PRIVATE_DATA$4 = {
59232
59252
  __graphs__: [],
59233
59253
  _graph_properties: {},
59234
59254
  _saved_graph_properties: {},
59255
+ _graphs_writes_owed: {},
59235
59256
  yet_showed: false,
59236
59257
  edit_mode: false,
59237
59258
  operation_mode: null,
@@ -60927,6 +60948,7 @@ function save_topic_graph_properties(gobj, topic_name) {
60927
60948
  if (!topic_arrangement_changed(properties, priv._saved_graph_properties[topic_name])) return;
60928
60949
  properties.__origin__ = (0, _yuneta_gobj_js.gobj_read_str_attr)((0, _yuneta_gobj_js.gobj_yuno)(), "node_uuid");
60929
60950
  priv._saved_graph_properties[topic_name] = (0, _yuneta_gobj_js.json_deep_copy)(properties);
60951
+ delete priv._graphs_writes_owed[topic_name];
60930
60952
  let kw_update = {
60931
60953
  treedb_name: priv.treedb_name,
60932
60954
  topic_name: "__graphs__",
@@ -61008,8 +61030,13 @@ function update_history_buttons(gobj) {
61008
61030
  } else {
61009
61031
  disableElements($container, ".EV_HISTORY_UNDO");
61010
61032
  set_active_state($container, ".EV_HISTORY_UNDO", false);
61011
- disableElements($container, ".EV_SAVE_GRAPH");
61012
- set_submit_state($container, ".EV_SAVE_GRAPH", false);
61033
+ if (graphs_write_is_owed(gobj)) {
61034
+ enableElements($container, ".EV_SAVE_GRAPH");
61035
+ set_submit_state($container, ".EV_SAVE_GRAPH", true);
61036
+ } else {
61037
+ disableElements($container, ".EV_SAVE_GRAPH");
61038
+ set_submit_state($container, ".EV_SAVE_GRAPH", false);
61039
+ }
61013
61040
  }
61014
61041
  } else {
61015
61042
  disableElements($container, ".EV_HISTORY_REDO");
@@ -61966,6 +61993,15 @@ function run_preview_undo(gobj, key) {
61966
61993
  (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot undo the preview: ${e}`);
61967
61994
  }
61968
61995
  }
61996
+ /************************************************************
61997
+ * Is a `__graphs__` write owed? The host said one did not land
61998
+ * (EV_GRAPHS_WRITE_REFUSED), and no Save has written that topic
61999
+ * since. The Save button stays lit while it is: the history
62000
+ * knows nothing of it, so `canUndo()` alone would put it out.
62001
+ ************************************************************/
62002
+ function graphs_write_is_owed(gobj) {
62003
+ return Object.keys(gobj.priv._graphs_writes_owed).length > 0;
62004
+ }
61969
62005
  function mark_graph_dirty(gobj) {
61970
62006
  let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
61971
62007
  enableElements($container, ".EV_SAVE_GRAPH");
@@ -65706,6 +65742,7 @@ function ac_clear_data(gobj, event, kw, src) {
65706
65742
  deselect_node(gobj);
65707
65743
  hide_create_popover(gobj);
65708
65744
  (0, _yuneta_gobj_js.gobj_write_attr)(gobj, "records", {});
65745
+ priv._graphs_writes_owed = {};
65709
65746
  priv._nodes_total = 0;
65710
65747
  priv._nodes_placed = 0;
65711
65748
  priv._fold_model = null;
@@ -65798,11 +65835,9 @@ function ac_save_graph(gobj, event, kw, src) {
65798
65835
  disableElements($container, ".EV_SAVE_GRAPH");
65799
65836
  set_submit_state($container, ".EV_SAVE_GRAPH", false);
65800
65837
  let history = graph_get_plugin(gobj, "history");
65801
- if (history) {
65802
- history.clear();
65803
- update_history_buttons(gobj);
65804
- }
65838
+ if (history) history.clear();
65805
65839
  save_geometry(gobj);
65840
+ update_history_buttons(gobj);
65806
65841
  }
65807
65842
  return 0;
65808
65843
  }
@@ -65825,6 +65860,7 @@ function ac_graphs_write_refused(gobj, event, kw, src) {
65825
65860
  }
65826
65861
  (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: the arrangement of '${topic_name}' was not saved: the next Save writes it again`);
65827
65862
  forget_refused_graphs_write(priv._saved_graph_properties, topic_name);
65863
+ priv._graphs_writes_owed[topic_name] = true;
65828
65864
  if (priv.edit_mode) mark_graph_dirty(gobj);
65829
65865
  return 0;
65830
65866
  }
@@ -68342,6 +68378,7 @@ function treedb_update_node(gobj, treedb_name, topic_name, record, options) {
68342
68378
  options: options || {}
68343
68379
  };
68344
68380
  kw.__md_command__ = { topic_name };
68381
+ if (topic_name === "__graphs__") kw.__md_command__.graph_topic = graph_topic_of(record);
68345
68382
  let ret = (0, _yuneta_gobj_js.gobj_command)(priv.gobj_remote_yuno, command, kw, gobj);
68346
68383
  if (ret) {
68347
68384
  (0, _yuneta_gobj_js.log_error)(ret);
@@ -68620,7 +68657,7 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
68620
68657
  case "delete-node":
68621
68658
  case "link-nodes":
68622
68659
  case "unlink-nodes":
68623
- if (result < 0 && command === "update-node") graphs_write_refused(gobj, (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0), (0, _yuneta_gobj_js.kw_get_dict)(gobj, kw_command, "record", {}, 0));
68660
+ if (result < 0 && command === "update-node") graphs_write_refused(gobj, (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0), (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "graph_topic", "", 0));
68624
68661
  if (result >= 0 && (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_RECORD_WRITTEN", {
68625
68662
  treedb_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "treedb_name", "", 0),
68626
68663
  topic_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0),
@@ -68869,29 +68906,35 @@ function ac_update_node(gobj, event, kw, src) {
68869
68906
  let record = kw.record;
68870
68907
  let options = kw.options || {};
68871
68908
  if (refuse_if_readonly$1(gobj, event)) {
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
  if (topic_name === "__graphs__" && !is_connected(gobj)) {
68876
68913
  (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no session, the arrangement was not sent`);
68877
- graphs_write_refused(gobj, topic_name, record);
68914
+ graphs_write_refused(gobj, topic_name, graph_topic_of(record));
68878
68915
  return -1;
68879
68916
  }
68880
68917
  let ret = treedb_update_node(gobj, treedb_name, topic_name, record, options);
68881
- if (ret < 0) graphs_write_refused(gobj, topic_name, record);
68918
+ if (ret < 0) graphs_write_refused(gobj, topic_name, graph_topic_of(record));
68882
68919
  return ret;
68883
68920
  }
68884
68921
  /************************************************************
68922
+ * The topic a `__graphs__` record arranges.
68923
+ ************************************************************/
68924
+ function graph_topic_of(record) {
68925
+ if (!record || typeof record !== "object") return "";
68926
+ return record.topic || record.id || "";
68927
+ }
68928
+ /************************************************************
68885
68929
  * A write of `__graphs__` did not land. The engine
68886
68930
  * (C_G6_NODES_TREE) took it for granted when it left -- nothing
68887
68931
  * answers it when it lands -- so it is told, and its next Save
68888
68932
  * writes the topic again. Other topics are the operator's data:
68889
68933
  * the answer's error says what happened to them.
68890
68934
  ************************************************************/
68891
- function graphs_write_refused(gobj, topic_name, record) {
68935
+ function graphs_write_refused(gobj, topic_name, topic) {
68892
68936
  let priv = gobj.priv;
68893
68937
  if (topic_name !== "__graphs__") return;
68894
- let topic = record && typeof record === "object" ? record.topic || record.id : "";
68895
68938
  if (!topic) {
68896
68939
  (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: a refused __graphs__ write names no topic`);
68897
68940
  return;
@@ -72334,6 +72377,8 @@ var PRIVATE_DATA$1 = {
72334
72377
  dropped_round: 0,
72335
72378
  dropped_write: 0,
72336
72379
  reload_after_write: false,
72380
+ refresh_after_write: false,
72381
+ reopen_form: null,
72337
72382
  pending_seg: null,
72338
72383
  import_plan: null,
72339
72384
  import_pane: null,
@@ -72448,11 +72493,18 @@ function el_attrs(attrs) {
72448
72493
  return attrs;
72449
72494
  }
72450
72495
  /***************************************************************
72451
- * The body stops answering while a write is in flight.
72496
+ * The body stops answering while a write is in flight. For the
72497
+ * keyboard too: `pointer-events` stops the mouse alone, and the
72498
+ * shell's focus trap puts the focus back on the row control that
72499
+ * had it, where Enter or Delete sent an action ST_SAVING does
72500
+ * not declare. `inert` takes the whole body out of reach.
72452
72501
  ***************************************************************/
72453
72502
  function set_busy(gobj, busy) {
72454
72503
  let $body = $of(gobj, ".SCHEMA_BODY");
72455
- if ($body) $body.classList.toggle("SCHEMA_BUSY", !!busy);
72504
+ if ($body) {
72505
+ $body.classList.toggle("SCHEMA_BUSY", !!busy);
72506
+ $body.toggleAttribute("inert", !!busy);
72507
+ }
72456
72508
  }
72457
72509
  /***************************************************************
72458
72510
  * Shorthands for the three panes of the frame.
@@ -72539,14 +72591,61 @@ function owes_reload(gobj) {
72539
72591
  let state = (0, _yuneta_gobj_js.gobj_current_state)(gobj);
72540
72592
  return gobj.priv.reload_on_open && transport_in_session(gobj) && state !== "ST_LOADING" && state !== "ST_SAVING";
72541
72593
  }
72542
- function reload_first(gobj, event) {
72594
+ function reload_first(gobj, event, reopen) {
72595
+ let priv = gobj.priv;
72543
72596
  if (!owes_reload(gobj)) return false;
72544
- gobj.priv.reload_on_open = false;
72597
+ priv.reload_on_open = false;
72598
+ if (reopen && priv.dialog) {
72599
+ priv.reopen_form = Object.assign((0, _yuneta_gobj_js.json_deep_copy)(reopen), {
72600
+ dialog: priv.dialog,
72601
+ treedb_id: priv.treedb_id
72602
+ });
72603
+ (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.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`);
72604
+ 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: i18next.t });
72605
+ request_model(gobj, true);
72606
+ return true;
72607
+ }
72545
72608
  (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} refused, the schemas shown may be out of date: they are read again first`);
72546
72609
  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: i18next.t });
72547
72610
  request_model(gobj, true);
72548
72611
  return true;
72549
72612
  }
72613
+ /***************************************************************
72614
+ * The form reload_first() took down, opened again on the model
72615
+ * the load just made, with the operator's changes on top.
72616
+ *
72617
+ * Only where it can mean the same thing: on the treedb it was
72618
+ * opened on, on the screen whose Save it has, and on a record
72619
+ * that is still there. Otherwise it is not opened, and that is
72620
+ * said -- a form opened on another treedb, or on nothing, would
72621
+ * save somewhere the operator never meant.
72622
+ ***************************************************************/
72623
+ function reopen_form(gobj, r) {
72624
+ let priv = gobj.priv;
72625
+ let state = (0, _yuneta_gobj_js.gobj_current_state)(gobj);
72626
+ let treedb = current_treedb(gobj);
72627
+ let topic = null;
72628
+ let col = null;
72629
+ let fits = false;
72630
+ if (treedb && r.treedb_id === priv.treedb_id) {
72631
+ if (r.form === "column" && state === "ST_COLUMNS") {
72632
+ topic = find_topic(priv.model, priv.treedb_id, r.topic);
72633
+ col = topic && !r.creating ? find_col(priv.model, priv.treedb_id, r.topic, r.col) : null;
72634
+ fits = !!topic && (r.creating || !!col);
72635
+ } else if (r.form === "topic" && state === "ST_TOPICS") {
72636
+ topic = r.creating ? null : find_topic(priv.model, priv.treedb_id, r.topic);
72637
+ fits = r.creating || !!topic;
72638
+ }
72639
+ }
72640
+ if (!fits) {
72641
+ (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.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})`);
72642
+ 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: i18next.t });
72643
+ return -1;
72644
+ }
72645
+ if (r.form === "column") open_column_form(gobj, topic, col, null, r.changed);
72646
+ else open_topic_form(gobj, treedb, topic, r.changed);
72647
+ return 0;
72648
+ }
72550
72649
  function reload_after_move(gobj) {
72551
72650
  if (!owes_reload(gobj)) return 0;
72552
72651
  gobj.priv.reload_on_open = false;
@@ -72621,7 +72720,7 @@ function request_model(gobj, keep_written) {
72621
72720
  priv.records_before = null;
72622
72721
  priv.load_round++;
72623
72722
  priv.reload_on_open = true;
72624
- priv.load_error = (0, i18next.t)("cannot reach the treedb");
72723
+ priv.load_error = "cannot reach the treedb";
72625
72724
  if (priv.model) yui_shell_show_error(yui_shell_of(gobj), "cannot reach the treedb", { t: i18next.t });
72626
72725
  end_load(gobj);
72627
72726
  return -1;
@@ -72692,7 +72791,7 @@ function build_model(gobj) {
72692
72791
  * measurement of "changed since" can be measured against.
72693
72792
  *
72694
72793
  * `written` is forgotten only by an EV_REFRESH (the view's own
72695
- * Refresh button, or a host that sends one). Since M36 a write moves no
72794
+ * Refresh button, or a host that sends one). Since 7.23.196 a write moves no
72696
72795
  * version, so `written` is the draft chip of what this session
72697
72796
  * wrote and no longer half of a version measurement: a reload of
72698
72797
  * the reconnect, or of a write that turned out done, forgot the
@@ -72832,10 +72931,13 @@ function show_notice(gobj, key, detail) {
72832
72931
  },
72833
72932
  (0, i18next.t)(key)
72834
72933
  ]));
72835
- if (detail) $notice.appendChild((0, _yuneta_gobj_js.createElement2)([
72934
+ if (detail && detail !== key) $notice.appendChild((0, _yuneta_gobj_js.createElement2)([
72836
72935
  "span",
72837
- { class: "SCHEMA_NOTICE_DETAIL yui-text-quiet ml-2" },
72838
- `${detail}`
72936
+ {
72937
+ class: "SCHEMA_NOTICE_DETAIL yui-text-quiet ml-2",
72938
+ i18n: `${detail}`
72939
+ },
72940
+ (0, i18next.t)(`${detail}`)
72839
72941
  ]));
72840
72942
  }
72841
72943
  /***************************************************************
@@ -73970,6 +74072,55 @@ function read_form($root) {
73970
74072
  return out;
73971
74073
  }
73972
74074
  /***************************************************************
74075
+ * A column form as its Save sends it: the fields and the flags.
74076
+ ***************************************************************/
74077
+ function column_form_state($form) {
74078
+ let values = read_form($form);
74079
+ values.flag = read_flags($form);
74080
+ return values;
74081
+ }
74082
+ /***************************************************************
74083
+ * The fields the operator CHANGED: those whose value is not the
74084
+ * one the form was opened with.
74085
+ ***************************************************************/
74086
+ function form_changes(initial, values) {
74087
+ let changed = {};
74088
+ for (let name of Object.keys(values)) if (JSON.stringify(values[name]) !== JSON.stringify(initial[name])) changed[name] = values[name];
74089
+ return changed;
74090
+ }
74091
+ /***************************************************************
74092
+ * Put changes back into a form just built (reopen_form()). The
74093
+ * flags are drawn again for the type the changes leave, holding
74094
+ * the flags they name, so none of them is hidden by the type.
74095
+ ***************************************************************/
74096
+ function apply_form_changes(gobj, $form, changes) {
74097
+ for (let name of Object.keys(changes)) {
74098
+ if (name === "flag") continue;
74099
+ let $control = $form.querySelector(`[data-name="${name}"]`);
74100
+ if (!$control) {
74101
+ (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: a change of '${name}' has no field in the form opened again: not put back`);
74102
+ continue;
74103
+ }
74104
+ if ($control.type === "checkbox") $control.checked = !!changes[name];
74105
+ else $control.value = changes[name];
74106
+ }
74107
+ let $type = $form.querySelector("[data-name=\"type\"]");
74108
+ if ($type && $form.querySelector(".SCHEMA_FLAGS")) {
74109
+ let flags = Array.isArray(changes.flag) ? changes.flag : read_flags($form);
74110
+ redraw_flags(gobj, $form, $type.value, flags);
74111
+ }
74112
+ }
74113
+ /***************************************************************
74114
+ * Draw the flags of a column form again, for `type`, with
74115
+ * `current` checked.
74116
+ ***************************************************************/
74117
+ function redraw_flags(gobj, $form, type, current) {
74118
+ let $holder = $form.querySelector(".SCHEMA_FLAGS");
74119
+ let $new = (0, _yuneta_gobj_js.createElement2)(flags_field(gobj, type, current));
74120
+ $holder.parentNode.replaceChild($new, $holder);
74121
+ (0, _yuneta_gobj_js.refresh_language)($new, i18next.t);
74122
+ }
74123
+ /***************************************************************
73973
74124
  * The flags of a column, as checkboxes that say what they do.
73974
74125
  *
73975
74126
  * Grouped the way they act, greyed when they are meaningless on
@@ -74043,7 +74194,7 @@ function read_flags($root) {
74043
74194
  * Offering a field that silently does something else is worse
74044
74195
  * than not offering it.
74045
74196
  ***************************************************************/
74046
- function open_column_form(gobj, topic, col, prefill) {
74197
+ function open_column_form(gobj, topic, col, prefill, changes) {
74047
74198
  let priv = gobj.priv;
74048
74199
  let record = prefill || col && col.record || {};
74049
74200
  let creating = !col;
@@ -74147,11 +74298,7 @@ function open_column_form(gobj, topic, col, prefill) {
74147
74298
  ]);
74148
74299
  let $type = $form.querySelector("[data-name=\"type\"]");
74149
74300
  $type.addEventListener("change", () => {
74150
- let $holder = $form.querySelector(".SCHEMA_FLAGS");
74151
- let current = read_flags($form);
74152
- let $new = (0, _yuneta_gobj_js.createElement2)(flags_field(gobj, $type.value, current));
74153
- $holder.parentNode.replaceChild($new, $holder);
74154
- (0, _yuneta_gobj_js.refresh_language)($new, i18next.t);
74301
+ redraw_flags(gobj, $form, $type.value, read_flags($form));
74155
74302
  });
74156
74303
  $form.addEventListener("change", (evt) => {
74157
74304
  let $box = evt.target.closest(".SCHEMA_FLAG_BOX");
@@ -74163,15 +74310,17 @@ function open_column_form(gobj, topic, col, prefill) {
74163
74310
  evt.stopPropagation();
74164
74311
  close_dialog(gobj);
74165
74312
  });
74313
+ let initial = column_form_state($form);
74314
+ if (changes) apply_form_changes(gobj, $form, changes);
74166
74315
  $form.querySelector(".SCHEMA_COL_FORM_SAVE").addEventListener("click", (evt) => {
74167
74316
  evt.stopPropagation();
74168
- let values = read_form($form);
74169
- values.flag = read_flags($form);
74317
+ let values = column_form_state($form);
74170
74318
  (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SAVE_COLUMN", {
74171
74319
  topic: topic.name,
74172
74320
  col: creating ? "" : col.name,
74173
74321
  creating,
74174
74322
  values,
74323
+ changed: creating ? values : form_changes(initial, values),
74175
74324
  model_gen
74176
74325
  }, gobj);
74177
74326
  });
@@ -74191,7 +74340,7 @@ function stringify_field(value) {
74191
74340
  * actually has: a pkey naming no column is a topic that does
74192
74341
  * not open, and it is the first thing the validator looks for.
74193
74342
  ***************************************************************/
74194
- function open_topic_form(gobj, treedb, topic) {
74343
+ function open_topic_form(gobj, treedb, topic, changes) {
74195
74344
  let record = topic && topic.record || {};
74196
74345
  let creating = !topic;
74197
74346
  let col_names = topic ? topic.cols.map((c) => c.name) : [];
@@ -74286,12 +74435,16 @@ function open_topic_form(gobj, treedb, topic) {
74286
74435
  evt.stopPropagation();
74287
74436
  close_dialog(gobj);
74288
74437
  });
74438
+ let initial = read_form($form);
74439
+ if (changes) apply_form_changes(gobj, $form, changes);
74289
74440
  $form.querySelector(".SCHEMA_TOPIC_FORM_SAVE").addEventListener("click", (evt) => {
74290
74441
  evt.stopPropagation();
74442
+ let values = read_form($form);
74291
74443
  (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SAVE_TOPIC", {
74292
74444
  topic: creating ? "" : topic.name,
74293
74445
  creating,
74294
- values: read_form($form),
74446
+ values,
74447
+ changed: creating ? values : form_changes(initial, values),
74295
74448
  model_gen
74296
74449
  }, gobj);
74297
74450
  });
@@ -75061,20 +75214,28 @@ function transport_dropped(gobj) {
75061
75214
  function end_load(gobj) {
75062
75215
  let priv = gobj.priv;
75063
75216
  let seg = priv.pending_seg;
75217
+ let reopen = priv.reopen_form;
75064
75218
  priv.pending_seg = null;
75219
+ priv.reopen_form = null;
75065
75220
  if (priv.dialog && priv.dialog_gen !== priv.model_gen) {
75066
- (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: a dialog was open on the schemas the load replaced: closed`);
75221
+ if (!reopen || reopen.dialog !== priv.dialog) {
75222
+ reopen = null;
75223
+ (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: a dialog was open on the schemas the load replaced: closed`);
75224
+ yui_shell_show_error(yui_shell_of(gobj), "the schemas were read again: open the dialog again", { t: i18next.t });
75225
+ }
75067
75226
  close_dialog(gobj);
75068
- yui_shell_show_error(yui_shell_of(gobj), "the schemas were read again: open the dialog again", { t: i18next.t });
75069
- }
75227
+ } else reopen = null;
75228
+ let ret = 0;
75070
75229
  if (priv.model) {
75071
- if (seg !== null) return apply_seg(gobj, seg);
75072
- return go(gobj, priv.treedb_id, priv.topic_name, priv.diagram, false);
75230
+ if (seg !== null) ret = apply_seg(gobj, seg);
75231
+ else ret = go(gobj, priv.treedb_id, priv.topic_name, priv.diagram, false);
75232
+ } else {
75233
+ if (seg !== null) adopt_seg(gobj, seg);
75234
+ (0, _yuneta_gobj_js.gobj_change_state)(gobj, "ST_IDLE");
75235
+ render(gobj);
75073
75236
  }
75074
- if (seg !== null) adopt_seg(gobj, seg);
75075
- (0, _yuneta_gobj_js.gobj_change_state)(gobj, "ST_IDLE");
75076
- render(gobj);
75077
- return 0;
75237
+ if (reopen) reopen_form(gobj, reopen);
75238
+ return ret;
75078
75239
  }
75079
75240
  /***************************************************************
75080
75241
  * The queue is done, or gave up. Either way the model is what
@@ -75099,7 +75260,11 @@ function end_writes(gobj, error) {
75099
75260
  render(gobj);
75100
75261
  publish_check(gobj);
75101
75262
  }
75102
- reload_if_owed(gobj);
75263
+ if (priv.refresh_after_write) {
75264
+ priv.refresh_after_write = false;
75265
+ priv.reload_after_write = false;
75266
+ request_model(gobj, false);
75267
+ } else reload_if_owed(gobj);
75103
75268
  return error ? -1 : 0;
75104
75269
  }
75105
75270
  /***************************************************************
@@ -75327,7 +75492,7 @@ function ac_mt_command_answer(gobj, event, kw, src) {
75327
75492
  return 0;
75328
75493
  }
75329
75494
  priv.pending--;
75330
- if (result < 0) priv.load_error = comment || (0, i18next.t)("cannot load the schemas");
75495
+ if (result < 0) priv.load_error = comment || "cannot load the schemas";
75331
75496
  else if (priv.records && Array.isArray(priv.records[topic_name])) priv.records[topic_name] = Array.isArray(data) ? data : [];
75332
75497
  if (priv.pending > 0) return 0;
75333
75498
  if (priv.load_error) {
@@ -75363,9 +75528,10 @@ function ac_mt_command_answer(gobj, event, kw, src) {
75363
75528
  }
75364
75529
  if (result < 0) return end_writes(gobj, comment || (0, i18next.t)("the treedb refused the write"));
75365
75530
  priv.save_wrote = true;
75531
+ let record = null;
75366
75532
  if (command === "delete-node") forget_record(gobj, topic_name, (0, _yuneta_gobj_js.kw_get_str)(gobj, md, "record_id", "", 0));
75367
75533
  else {
75368
- let record = (0, _yuneta_gobj_js.is_object)(data) ? data : Array.isArray(data) && (0, _yuneta_gobj_js.is_object)(data[0]) ? data[0] : null;
75534
+ record = (0, _yuneta_gobj_js.is_object)(data) ? data : Array.isArray(data) && (0, _yuneta_gobj_js.is_object)(data[0]) ? data[0] : null;
75369
75535
  if (record) patch_record(gobj, topic_name, record);
75370
75536
  else {
75371
75537
  let not_sent = priv.save_queue.length - 1;
@@ -75373,20 +75539,22 @@ function ac_mt_command_answer(gobj, event, kw, src) {
75373
75539
  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: i18next.t });
75374
75540
  if (topic_name === T_TOPICS || topic_name === T_COLS) {
75375
75541
  let write = priv.save_queue[0];
75376
- mark_written(gobj, topic_name, write ? write.record : null);
75542
+ mark_written(gobj, topic_name, null, write ? write.record : null);
75377
75543
  }
75378
75544
  priv.reload_after_write = false;
75379
75545
  priv.save_queue = [];
75380
75546
  priv.save_return = "";
75381
75547
  priv.save_wrote = false;
75382
75548
  (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_RECORD_WRITTEN", { treedb_name: (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "treedb_name") });
75383
- request_model(gobj, true);
75549
+ let refresh = priv.refresh_after_write;
75550
+ priv.refresh_after_write = false;
75551
+ request_model(gobj, !refresh);
75384
75552
  return 0;
75385
75553
  }
75386
75554
  }
75387
75555
  if (topic_name === T_TOPICS || topic_name === T_COLS) {
75388
75556
  let write = priv.save_queue[0];
75389
- mark_written(gobj, topic_name, write ? write.record : null);
75557
+ mark_written(gobj, topic_name, record, write ? write.record : null);
75390
75558
  }
75391
75559
  priv.save_queue.shift();
75392
75560
  return run_next_write(gobj);
@@ -75443,25 +75611,34 @@ function late_write_done(gobj, command, topic_name, data) {
75443
75611
  ***************************************************************/
75444
75612
  function mark_written_record(gobj, topic_name, record) {
75445
75613
  let priv = gobj.priv;
75446
- if (!record) return;
75614
+ let marked = 0;
75615
+ if (!record) return 0;
75447
75616
  if (topic_name === T_TOPICS && typeof record.id === "string" && record.id) {
75448
75617
  priv.written[record.id] = true;
75449
- return;
75618
+ return 1;
75450
75619
  }
75451
- if (topic_name !== T_COLS) return;
75452
- for (let ref of parse_fkey_ref(record.topics)) priv.written[ref.id] = true;
75620
+ if (topic_name !== T_COLS) return 0;
75621
+ for (let ref of parse_fkey_ref(record.topics)) {
75622
+ priv.written[ref.id] = true;
75623
+ marked++;
75624
+ }
75625
+ return marked;
75453
75626
  }
75454
75627
  /***************************************************************
75455
75628
  * Remember which topic this write belongs to, which is what
75456
75629
  * "its version still has to move" is asked about.
75630
+ *
75631
+ * Asked of the RECORD first: the one the store answered (a new
75632
+ * topic has its id only there), then the one queued (a column
75633
+ * names its topic in its fkey). The screen is the last resort,
75634
+ * and a poor one: an import writes topics the operator is not
75635
+ * on, and from the topics screen there is no topic on it at all.
75457
75636
  ***************************************************************/
75458
- function mark_written(gobj, topic_name, record) {
75637
+ function mark_written(gobj, topic_name, answered, queued) {
75459
75638
  let priv = gobj.priv;
75639
+ if (mark_written_record(gobj, topic_name, answered) > 0) return;
75640
+ if (mark_written_record(gobj, topic_name, queued) > 0) return;
75460
75641
  let topic = current_topic(gobj);
75461
- if (topic_name === T_TOPICS && record && record.id) {
75462
- priv.written[record.id] = true;
75463
- return;
75464
- }
75465
75642
  if (topic) priv.written[topic.id] = true;
75466
75643
  }
75467
75644
  /***************************************************************
@@ -75527,6 +75704,21 @@ function ac_refresh$1(gobj, event, kw, src) {
75527
75704
  return request_model(gobj, false);
75528
75705
  }
75529
75706
  /***************************************************************
75707
+ * EV_REFRESH while writes are in flight: the view's own Refresh
75708
+ * is busy then, so it is a host's (after a Save, say).
75709
+ *
75710
+ * Run when the writes END (end_writes()), not now. Run now, the
75711
+ * load replaced ST_SAVING and what was still queued was never
75712
+ * sent, with no word: nothing but the end of what is in flight
75713
+ * moves this view out of ST_LOADING or ST_SAVING.
75714
+ ***************************************************************/
75715
+ function ac_refresh_after_the_writes(gobj, event, kw, src) {
75716
+ let priv = gobj.priv;
75717
+ (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} while writes are in flight: the schemas are read again when the writes end`);
75718
+ priv.refresh_after_write = true;
75719
+ return 0;
75720
+ }
75721
+ /***************************************************************
75530
75722
  * What a DIALOG sends while the model is being read again: the
75531
75723
  * Save of a form left open when the reload started, a
75532
75724
  * confirmation, an import. The loading screen took the rest of
@@ -75701,7 +75893,13 @@ function ac_save_column(gobj, event, kw, src) {
75701
75893
  let topic = find_topic(priv.model, priv.treedb_id, kw.topic);
75702
75894
  let col = kw.creating ? null : find_col(priv.model, priv.treedb_id, kw.topic, kw.col);
75703
75895
  if (refuse_if_readonly(gobj, event)) return -1;
75704
- if (reload_first(gobj, event)) return -1;
75896
+ if (reload_first(gobj, event, {
75897
+ form: "column",
75898
+ topic: kw.topic,
75899
+ col: kw.col,
75900
+ creating: !!kw.creating,
75901
+ changed: kw.changed || {}
75902
+ })) return -1;
75705
75903
  if (built_on_a_replaced_model(gobj, event, kw)) return -1;
75706
75904
  if (!topic || !kw.creating && !col) {
75707
75905
  (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} names no column: ${kw.topic}.${kw.col}`);
@@ -75829,7 +76027,13 @@ function ac_save_topic(gobj, event, kw, src) {
75829
76027
  let treedb = current_treedb(gobj);
75830
76028
  let topic = kw.creating ? null : find_topic(priv.model, priv.treedb_id, kw.topic);
75831
76029
  if (refuse_if_readonly(gobj, event)) return -1;
75832
- if (reload_first(gobj, event)) return -1;
76030
+ if (reload_first(gobj, event, {
76031
+ form: "topic",
76032
+ topic: kw.topic,
76033
+ col: "",
76034
+ creating: !!kw.creating,
76035
+ changed: kw.changed || {}
76036
+ })) return -1;
75833
76037
  if (built_on_a_replaced_model(gobj, event, kw)) return -1;
75834
76038
  if (!treedb || !kw.creating && !topic) {
75835
76039
  (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} names no topic: ${kw.topic}`);
@@ -76292,7 +76496,11 @@ function create_gclass$1(gclass_name) {
76292
76496
  null
76293
76497
  ]
76294
76498
  ])],
76295
- ["ST_SAVING", COMMON.slice()]
76499
+ ["ST_SAVING", COMMON.filter((a) => a[0] !== "EV_REFRESH").concat([[
76500
+ "EV_REFRESH",
76501
+ ac_refresh_after_the_writes,
76502
+ null
76503
+ ]])]
76296
76504
  ];
76297
76505
  const event_types = [
76298
76506
  ["EV_MT_COMMAND_ANSWER", _yuneta_gobj_js.event_flag_t.EVF_PUBLIC_EVENT],