@yuneta/gobj-ui 7.25.8 → 7.25.9
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 +34 -6
- package/dist/gobj-ui.cjs.js +168 -43
- package/dist/gobj-ui.es.js +168 -43
- package/package.json +1 -1
- package/src/c_yui_schema_editor.js +217 -46
- package/src/schema_editor_reload.wiring.test.js +321 -7
- package/src/shell_modals.js +8 -4
- package/src/shell_toast_once.test.js +42 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -3057,6 +3057,8 @@ function show_notification(shell, kind, message, opts) {
|
|
|
3057
3057
|
},
|
|
3058
3058
|
[["button", {
|
|
3059
3059
|
class: "TOAST_CLOSE delete",
|
|
3060
|
+
title: t("close"),
|
|
3061
|
+
"data-i18n-title": "close",
|
|
3060
3062
|
"aria-label": t("close"),
|
|
3061
3063
|
"data-i18n-aria-label": "close"
|
|
3062
3064
|
}], [
|
|
@@ -3180,6 +3182,8 @@ function yui_shell_show_modal(shell, content, opts) {
|
|
|
3180
3182
|
{
|
|
3181
3183
|
class: "MODAL_CLOSE yui-dialog-x",
|
|
3182
3184
|
type: "button",
|
|
3185
|
+
title: t("close"),
|
|
3186
|
+
"data-i18n-title": "close",
|
|
3183
3187
|
"aria-label": t("close"),
|
|
3184
3188
|
"data-i18n-aria-label": "close"
|
|
3185
3189
|
},
|
|
@@ -3201,6 +3205,8 @@ function yui_shell_show_modal(shell, content, opts) {
|
|
|
3201
3205
|
]];
|
|
3202
3206
|
if (with_close) modal_children.push(["button", {
|
|
3203
3207
|
class: "MODAL_CLOSE modal-close is-large",
|
|
3208
|
+
title: t("close"),
|
|
3209
|
+
"data-i18n-title": "close",
|
|
3204
3210
|
"aria-label": t("close"),
|
|
3205
3211
|
"data-i18n-aria-label": "close"
|
|
3206
3212
|
}]);
|
|
@@ -3355,6 +3361,8 @@ function build_dialog(shell, message, buttons, opts) {
|
|
|
3355
3361
|
]);
|
|
3356
3362
|
$card_children.push(["button", {
|
|
3357
3363
|
class: "CONFIRM_CLOSE delete yui-confirm-x",
|
|
3364
|
+
title: t("close"),
|
|
3365
|
+
"data-i18n-title": "close",
|
|
3358
3366
|
"aria-label": t("close"),
|
|
3359
3367
|
"data-i18n-aria-label": "close"
|
|
3360
3368
|
}], [
|
|
@@ -72168,7 +72176,9 @@ var attrs_table$1 = [
|
|
|
72168
72176
|
];
|
|
72169
72177
|
var PRIVATE_DATA$1 = {
|
|
72170
72178
|
records: null,
|
|
72179
|
+
records_before: null,
|
|
72171
72180
|
model: null,
|
|
72181
|
+
model_gen: 0,
|
|
72172
72182
|
pending: 0,
|
|
72173
72183
|
load_error: "",
|
|
72174
72184
|
load_round: 0,
|
|
@@ -72183,6 +72193,7 @@ var PRIVATE_DATA$1 = {
|
|
|
72183
72193
|
order_undo: null,
|
|
72184
72194
|
diagram_gobj: null,
|
|
72185
72195
|
dialog: null,
|
|
72196
|
+
dialog_gen: 0,
|
|
72186
72197
|
save_queue: null,
|
|
72187
72198
|
save_return: "",
|
|
72188
72199
|
save_wrote: false,
|
|
@@ -72343,6 +72354,29 @@ function refuse_if_readonly(gobj, event) {
|
|
|
72343
72354
|
yui_shell_show_error(yui_shell_of(gobj), "the treedb is read-only", { t });
|
|
72344
72355
|
return true;
|
|
72345
72356
|
}
|
|
72357
|
+
/***************************************************************
|
|
72358
|
+
* A decision taken on a model a load has since REPLACED: the Save
|
|
72359
|
+
* of a form, a confirmation, an import. Each carries the
|
|
72360
|
+
* `model_gen` it was built on (a number, not the model: a kw is
|
|
72361
|
+
* dumped by the machine trace).
|
|
72362
|
+
*
|
|
72363
|
+
* Refused, and said. A column form sends every field it shows, so
|
|
72364
|
+
* its Save after a reload wrote the OLD record over the newer one
|
|
72365
|
+
* (fourth independent review, probe A3); a form whose column the
|
|
72366
|
+
* reload removed answered "names no column" for ever. end_load()
|
|
72367
|
+
* closes such a dialog when the load lands; this is the same rule
|
|
72368
|
+
* for whatever arrives anyway -- a stale screen, a confirmation
|
|
72369
|
+
* that was up, a keyboard.
|
|
72370
|
+
*
|
|
72371
|
+
* A kw with no stamp is not a dialog's and is not asked.
|
|
72372
|
+
***************************************************************/
|
|
72373
|
+
function built_on_a_replaced_model(gobj, event, kw) {
|
|
72374
|
+
let priv = gobj.priv;
|
|
72375
|
+
if (!kw || kw.model_gen === void 0 || kw.model_gen === priv.model_gen) return false;
|
|
72376
|
+
log_warning(`${gobj_short_name(gobj)}: ${event} refused, it was decided on the schemas a reload replaced`);
|
|
72377
|
+
yui_shell_show_error(yui_shell_of(gobj), "the schemas were read again: open the dialog again", { t });
|
|
72378
|
+
return true;
|
|
72379
|
+
}
|
|
72346
72380
|
/***************************
|
|
72347
72381
|
* The model
|
|
72348
72382
|
***************************/
|
|
@@ -72357,7 +72391,11 @@ function refuse_if_readonly(gobj, event) {
|
|
|
72357
72391
|
* and the toolbar stops answering: left up, a click on a card, on
|
|
72358
72392
|
* Back or on the drawing answered "Event NOT DEFINED in state
|
|
72359
72393
|
* ST_LOADING" and was lost (third independent review). A dialog
|
|
72360
|
-
* left open is answered in ST_LOADING instead (ac_wait_for_the_load)
|
|
72394
|
+
* left open is answered in ST_LOADING instead (ac_wait_for_the_load),
|
|
72395
|
+
* and a load that LANDS closes it (end_load()): it was built on the
|
|
72396
|
+
* model the load replaced, and its Save sends every field it shows.
|
|
72397
|
+
* An import plan is forgotten here for the same reason: it is a list
|
|
72398
|
+
* of writes computed against the model going away.
|
|
72361
72399
|
*
|
|
72362
72400
|
* `keep_written`: a load the host did not ask for -- the reconnect,
|
|
72363
72401
|
* a write that turned out done -- keeps what this session wrote.
|
|
@@ -72367,12 +72405,16 @@ function refuse_if_readonly(gobj, event) {
|
|
|
72367
72405
|
* is not even asked): the records the model was built on are put
|
|
72368
72406
|
* back (emptied, the next write patched them into a model with no
|
|
72369
72407
|
* treedb), the round is spent so a request that did leave is
|
|
72370
|
-
* stale, and the session back asks again.
|
|
72408
|
+
* stale, and the session back asks again. A load that left and
|
|
72409
|
+
* FAILED keeps them the same way (`records_before`,
|
|
72410
|
+
* ac_mt_command_answer()).
|
|
72371
72411
|
***************************************************************/
|
|
72372
72412
|
function request_model(gobj, keep_written) {
|
|
72373
72413
|
let priv = gobj.priv;
|
|
72374
72414
|
if (!gobj_read_pointer_attr(gobj, "gobj_remote_yuno")) return -1;
|
|
72415
|
+
forget_import_plan(gobj);
|
|
72375
72416
|
let previous = priv.records;
|
|
72417
|
+
priv.records_before = previous;
|
|
72376
72418
|
priv.records = {
|
|
72377
72419
|
treedbs: [],
|
|
72378
72420
|
topics: [],
|
|
@@ -72398,6 +72440,7 @@ function request_model(gobj, keep_written) {
|
|
|
72398
72440
|
}
|
|
72399
72441
|
if (left < 3) {
|
|
72400
72442
|
priv.records = previous;
|
|
72443
|
+
priv.records_before = null;
|
|
72401
72444
|
priv.load_round++;
|
|
72402
72445
|
priv.reload_on_open = true;
|
|
72403
72446
|
priv.load_error = t("cannot reach the treedb");
|
|
@@ -72493,9 +72536,10 @@ function start_measuring(gobj) {
|
|
|
72493
72536
|
* until the host saves it (C_TREEDB's save-schema, which raises the
|
|
72494
72537
|
* versions of what changed). Two sources say a topic is one, and
|
|
72495
72538
|
* they are kept APART because they are forgotten differently:
|
|
72496
|
-
* - `written`: what THIS session wrote
|
|
72497
|
-
*
|
|
72498
|
-
*
|
|
72539
|
+
* - `written`: what THIS session wrote. Only a load the HOST asked
|
|
72540
|
+
* for forgets it (its EV_REFRESH, which a Save sends); the
|
|
72541
|
+
* reconnect's reload, the one owed after a write and a late
|
|
72542
|
+
* write's keep it (start_measuring(), request_model());
|
|
72499
72543
|
* - `host_ids`: what the host said last (EV_DRAFTS), replaced WHOLE
|
|
72500
72544
|
* by the next EV_DRAFTS. Folded into `written`, a topic the host
|
|
72501
72545
|
* named once stayed a draft after the Save that published it.
|
|
@@ -72663,6 +72707,8 @@ function render_toolbar(gobj) {
|
|
|
72663
72707
|
let readonly = is_readonly(gobj);
|
|
72664
72708
|
let has_model = !!priv.model;
|
|
72665
72709
|
let on_a_treedb = state !== "ST_IDLE" && state !== "ST_EMPTY";
|
|
72710
|
+
let treedb_here = on_a_treedb && !!current_treedb(gobj);
|
|
72711
|
+
let topic_here = treedb_here && !!current_topic(gobj);
|
|
72666
72712
|
let in_flight = state === "ST_SAVING" || state === "ST_LOADING";
|
|
72667
72713
|
let $left = [];
|
|
72668
72714
|
if (priv.treedb_id && on_a_treedb) $left.push([
|
|
@@ -72738,17 +72784,17 @@ function render_toolbar(gobj) {
|
|
|
72738
72784
|
$trail
|
|
72739
72785
|
]);
|
|
72740
72786
|
let $right = [];
|
|
72741
|
-
if (priv.treedb_id && has_model &&
|
|
72787
|
+
if (priv.treedb_id && has_model && treedb_here) {
|
|
72742
72788
|
$right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-compass-drafting", priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
|
|
72743
72789
|
$right.push(toolbar_button("SCHEMA_VALIDATE_BTN", "yi-square-check", "check", "EV_VALIDATE", false));
|
|
72744
72790
|
$right.push(toolbar_button("SCHEMA_EXPORT_BTN", "yi-download", "export", "EV_EXPORT", false));
|
|
72745
72791
|
if (!readonly) $right.push(toolbar_button("SCHEMA_IMPORT_BTN", "yi-upload", "import", "EV_IMPORT", false));
|
|
72746
72792
|
}
|
|
72747
|
-
if (priv.topic_name && !readonly && !priv.diagram &&
|
|
72793
|
+
if (priv.topic_name && !readonly && !priv.diagram && topic_here) {
|
|
72748
72794
|
if (undo_order_writes(gobj, current_topic(gobj)).length > 0) $right.push(toolbar_button("SCHEMA_UNDO_ORDER_BTN", "yi-arrow-rotate-left", "undo the order", "EV_UNDO_ORDER", false));
|
|
72749
72795
|
$right.push(toolbar_button("SCHEMA_ADD_COL_BTN", "yi-plus", "new column", "EV_ADD_COLUMN", false));
|
|
72750
72796
|
}
|
|
72751
|
-
if (priv.treedb_id && !priv.topic_name && !readonly && !priv.diagram &&
|
|
72797
|
+
if (priv.treedb_id && !priv.topic_name && !readonly && !priv.diagram && treedb_here) $right.push(toolbar_button("SCHEMA_ADD_TOPIC_BTN", "yi-plus", "new topic", "EV_ADD_TOPIC", false));
|
|
72752
72798
|
$right.push(toolbar_button("SCHEMA_REFRESH_BTN", "yi-arrows-rotate", "refresh", "EV_REFRESH", state === "ST_LOADING"));
|
|
72753
72799
|
let $bar = createElement2([
|
|
72754
72800
|
"div",
|
|
@@ -73568,6 +73614,7 @@ function close_dialog(gobj) {
|
|
|
73568
73614
|
function open_dialog(gobj, $content, title, logical, title_prefix) {
|
|
73569
73615
|
let priv = gobj.priv;
|
|
73570
73616
|
close_dialog(gobj);
|
|
73617
|
+
priv.dialog_gen = priv.model_gen;
|
|
73571
73618
|
priv.dialog = yui_shell_show_modal(yui_shell_of(gobj), $content, {
|
|
73572
73619
|
dialog: true,
|
|
73573
73620
|
title,
|
|
@@ -73614,11 +73661,28 @@ function name_control($spec, label) {
|
|
|
73614
73661
|
$spec[1]["aria-label"] = t(label);
|
|
73615
73662
|
$spec[1]["data-i18n-aria-label"] = label;
|
|
73616
73663
|
}
|
|
73664
|
+
if (!$spec[1].title) {
|
|
73665
|
+
$spec[1].title = t(label);
|
|
73666
|
+
$spec[1]["data-i18n-title"] = label;
|
|
73667
|
+
}
|
|
73617
73668
|
return true;
|
|
73618
73669
|
}
|
|
73619
73670
|
for (let child of $spec[2] || []) if (name_control(child, label)) return true;
|
|
73620
73671
|
return false;
|
|
73621
73672
|
}
|
|
73673
|
+
/***************************************************************
|
|
73674
|
+
* The four attributes that NAME a control -- a title and an
|
|
73675
|
+
* aria-label, each with the key a language change re-translates
|
|
73676
|
+
* it by. A visible label is not a name (CLAUDE.md).
|
|
73677
|
+
***************************************************************/
|
|
73678
|
+
function name_attrs(key, attrs) {
|
|
73679
|
+
return Object.assign({
|
|
73680
|
+
title: t(key),
|
|
73681
|
+
"data-i18n-title": key,
|
|
73682
|
+
"aria-label": t(key),
|
|
73683
|
+
"data-i18n-aria-label": key
|
|
73684
|
+
}, attrs);
|
|
73685
|
+
}
|
|
73622
73686
|
function field(logical, name, label, $control, help) {
|
|
73623
73687
|
name_control($control, label);
|
|
73624
73688
|
return [
|
|
@@ -73795,7 +73859,7 @@ function read_flags($root) {
|
|
|
73795
73859
|
* than not offering it.
|
|
73796
73860
|
***************************************************************/
|
|
73797
73861
|
function open_column_form(gobj, topic, col, prefill) {
|
|
73798
|
-
gobj.priv;
|
|
73862
|
+
let priv = gobj.priv;
|
|
73799
73863
|
let record = prefill || col && col.record || {};
|
|
73800
73864
|
let creating = !col;
|
|
73801
73865
|
let type = record.type || "string";
|
|
@@ -73805,6 +73869,7 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
73805
73869
|
let hook_col = hook_topic ? hook[hook_topic] : "";
|
|
73806
73870
|
let treedb = current_treedb(gobj);
|
|
73807
73871
|
let sibling_topics = treedb ? treedb.topics.map((x) => x.name) : [];
|
|
73872
|
+
let model_gen = priv.model_gen;
|
|
73808
73873
|
let $form = createElement2([
|
|
73809
73874
|
"div",
|
|
73810
73875
|
{ class: "SCHEMA_COL_FORM box" },
|
|
@@ -73867,10 +73932,10 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
73867
73932
|
},
|
|
73868
73933
|
[[
|
|
73869
73934
|
"button",
|
|
73870
|
-
{
|
|
73935
|
+
name_attrs("cancel", {
|
|
73871
73936
|
class: "SCHEMA_COL_FORM_CANCEL button",
|
|
73872
73937
|
type: "button"
|
|
73873
|
-
},
|
|
73938
|
+
}),
|
|
73874
73939
|
[[
|
|
73875
73940
|
"span",
|
|
73876
73941
|
{ i18n: "cancel" },
|
|
@@ -73878,10 +73943,10 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
73878
73943
|
]]
|
|
73879
73944
|
], [
|
|
73880
73945
|
"button",
|
|
73881
|
-
{
|
|
73946
|
+
name_attrs("save", {
|
|
73882
73947
|
class: "SCHEMA_COL_FORM_SAVE button is-primary",
|
|
73883
73948
|
type: "button"
|
|
73884
|
-
},
|
|
73949
|
+
}),
|
|
73885
73950
|
[[
|
|
73886
73951
|
"span",
|
|
73887
73952
|
{ class: "icon" },
|
|
@@ -73921,7 +73986,8 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
73921
73986
|
topic: topic.name,
|
|
73922
73987
|
col: creating ? "" : col.name,
|
|
73923
73988
|
creating,
|
|
73924
|
-
values
|
|
73989
|
+
values,
|
|
73990
|
+
model_gen
|
|
73925
73991
|
}, gobj);
|
|
73926
73992
|
});
|
|
73927
73993
|
open_dialog(gobj, $form, creating ? "new column" : "edit column", "SCHEMA_COL_FORM_DIALOG", creating ? topic.name : `${topic.name}.${col.name}`);
|
|
@@ -73944,6 +74010,7 @@ function open_topic_form(gobj, treedb, topic) {
|
|
|
73944
74010
|
let record = topic && topic.record || {};
|
|
73945
74011
|
let creating = !topic;
|
|
73946
74012
|
let col_names = topic ? topic.cols.map((c) => c.name) : [];
|
|
74013
|
+
let model_gen = gobj.priv.model_gen;
|
|
73947
74014
|
let $form = createElement2([
|
|
73948
74015
|
"div",
|
|
73949
74016
|
{ class: "SCHEMA_TOPIC_FORM box" },
|
|
@@ -74002,10 +74069,10 @@ function open_topic_form(gobj, treedb, topic) {
|
|
|
74002
74069
|
},
|
|
74003
74070
|
[[
|
|
74004
74071
|
"button",
|
|
74005
|
-
{
|
|
74072
|
+
name_attrs("cancel", {
|
|
74006
74073
|
class: "SCHEMA_TOPIC_FORM_CANCEL button",
|
|
74007
74074
|
type: "button"
|
|
74008
|
-
},
|
|
74075
|
+
}),
|
|
74009
74076
|
[[
|
|
74010
74077
|
"span",
|
|
74011
74078
|
{ i18n: "cancel" },
|
|
@@ -74013,10 +74080,10 @@ function open_topic_form(gobj, treedb, topic) {
|
|
|
74013
74080
|
]]
|
|
74014
74081
|
], [
|
|
74015
74082
|
"button",
|
|
74016
|
-
{
|
|
74083
|
+
name_attrs("save", {
|
|
74017
74084
|
class: "SCHEMA_TOPIC_FORM_SAVE button is-primary",
|
|
74018
74085
|
type: "button"
|
|
74019
|
-
},
|
|
74086
|
+
}),
|
|
74020
74087
|
[[
|
|
74021
74088
|
"span",
|
|
74022
74089
|
{ class: "icon" },
|
|
@@ -74039,7 +74106,8 @@ function open_topic_form(gobj, treedb, topic) {
|
|
|
74039
74106
|
gobj_send_event(gobj, "EV_SAVE_TOPIC", {
|
|
74040
74107
|
topic: creating ? "" : topic.name,
|
|
74041
74108
|
creating,
|
|
74042
|
-
values: read_form($form)
|
|
74109
|
+
values: read_form($form),
|
|
74110
|
+
model_gen
|
|
74043
74111
|
}, gobj);
|
|
74044
74112
|
});
|
|
74045
74113
|
open_dialog(gobj, $form, creating ? "new topic" : "edit topic", "SCHEMA_TOPIC_FORM_DIALOG", creating ? treedb.id : `${treedb.id}.${topic.name}`);
|
|
@@ -74319,6 +74387,7 @@ function copy_text(gobj, $text) {
|
|
|
74319
74387
|
* plan itself, so what is confirmed is what runs.
|
|
74320
74388
|
***************************************************************/
|
|
74321
74389
|
function open_import(gobj, treedb) {
|
|
74390
|
+
let model_gen = gobj.priv.model_gen;
|
|
74322
74391
|
let $content = createElement2([
|
|
74323
74392
|
"div",
|
|
74324
74393
|
{ class: "SCHEMA_IMPORT box" },
|
|
@@ -74333,12 +74402,12 @@ function open_import(gobj, treedb) {
|
|
|
74333
74402
|
],
|
|
74334
74403
|
[
|
|
74335
74404
|
"textarea",
|
|
74336
|
-
{
|
|
74405
|
+
name_attrs("schema", {
|
|
74337
74406
|
class: "SCHEMA_IMPORT_TEXT textarea is-small is-family-monospace",
|
|
74338
74407
|
rows: "12",
|
|
74339
74408
|
spellcheck: "false",
|
|
74340
74409
|
placeholder: "{\"id\": \"...\", \"schema_version\": \"1\", \"topics\": []}"
|
|
74341
|
-
},
|
|
74410
|
+
}),
|
|
74342
74411
|
""
|
|
74343
74412
|
],
|
|
74344
74413
|
[
|
|
@@ -74371,10 +74440,10 @@ function open_import(gobj, treedb) {
|
|
|
74371
74440
|
[
|
|
74372
74441
|
[
|
|
74373
74442
|
"button",
|
|
74374
|
-
{
|
|
74443
|
+
name_attrs("cancel", {
|
|
74375
74444
|
class: "SCHEMA_IMPORT_CANCEL button",
|
|
74376
74445
|
type: "button"
|
|
74377
|
-
},
|
|
74446
|
+
}),
|
|
74378
74447
|
[[
|
|
74379
74448
|
"span",
|
|
74380
74449
|
{ i18n: "cancel" },
|
|
@@ -74383,10 +74452,10 @@ function open_import(gobj, treedb) {
|
|
|
74383
74452
|
],
|
|
74384
74453
|
[
|
|
74385
74454
|
"button",
|
|
74386
|
-
{
|
|
74455
|
+
name_attrs("preview", {
|
|
74387
74456
|
class: "SCHEMA_IMPORT_PREVIEW button",
|
|
74388
74457
|
type: "button"
|
|
74389
|
-
},
|
|
74458
|
+
}),
|
|
74390
74459
|
[[
|
|
74391
74460
|
"span",
|
|
74392
74461
|
{ class: "icon" },
|
|
@@ -74399,11 +74468,11 @@ function open_import(gobj, treedb) {
|
|
|
74399
74468
|
],
|
|
74400
74469
|
[
|
|
74401
74470
|
"button",
|
|
74402
|
-
{
|
|
74471
|
+
name_attrs("import", {
|
|
74403
74472
|
class: "SCHEMA_IMPORT_RUN button is-warning",
|
|
74404
74473
|
type: "button",
|
|
74405
74474
|
disabled: "disabled"
|
|
74406
|
-
},
|
|
74475
|
+
}),
|
|
74407
74476
|
[[
|
|
74408
74477
|
"span",
|
|
74409
74478
|
{ class: "icon" },
|
|
@@ -74430,18 +74499,31 @@ function open_import(gobj, treedb) {
|
|
|
74430
74499
|
evt.stopPropagation();
|
|
74431
74500
|
gobj_send_event(gobj, "EV_PREVIEW_IMPORT", {
|
|
74432
74501
|
text: $text.value,
|
|
74433
|
-
prune: $prune.checked
|
|
74502
|
+
prune: $prune.checked,
|
|
74503
|
+
model_gen
|
|
74434
74504
|
}, gobj);
|
|
74435
74505
|
});
|
|
74436
74506
|
$run.addEventListener("click", (evt) => {
|
|
74437
74507
|
evt.stopPropagation();
|
|
74438
|
-
gobj_send_event(gobj, "EV_APPLY_IMPORT", {}, gobj);
|
|
74508
|
+
gobj_send_event(gobj, "EV_APPLY_IMPORT", { model_gen }, gobj);
|
|
74439
74509
|
});
|
|
74440
74510
|
gobj.priv.import_pane = $plan_pane;
|
|
74441
74511
|
gobj.priv.import_run = $run;
|
|
74442
74512
|
open_dialog(gobj, $content, "import", "SCHEMA_IMPORT_DIALOG", treedb.id);
|
|
74443
74513
|
}
|
|
74444
74514
|
/***************************************************************
|
|
74515
|
+
* The plan is a list of writes computed against the model shown:
|
|
74516
|
+
* a load replaces the model, so the plan goes with it and the
|
|
74517
|
+
* dialog, if it stays up (a load that failed keeps the model),
|
|
74518
|
+
* asks for a Preview again.
|
|
74519
|
+
***************************************************************/
|
|
74520
|
+
function forget_import_plan(gobj) {
|
|
74521
|
+
let priv = gobj.priv;
|
|
74522
|
+
priv.import_plan = null;
|
|
74523
|
+
clear(priv.import_pane);
|
|
74524
|
+
if (priv.import_run) priv.import_run.disabled = true;
|
|
74525
|
+
}
|
|
74526
|
+
/***************************************************************
|
|
74445
74527
|
* The plan, drawn where the paste is: one line per write, the
|
|
74446
74528
|
* deletions apart and counted, because they are what the
|
|
74447
74529
|
* operator is being asked about.
|
|
@@ -74568,7 +74650,8 @@ function open_orphans(gobj) {
|
|
|
74568
74650
|
{ class: "SCHEMA_ORPHAN_ACTIONS has-text-right" },
|
|
74569
74651
|
readonly ? [] : [row_icon(gobj, "SCHEMA_ORPHAN_DELETE", "yi-trash", "delete", "EV_DELETE_ORPHAN", {
|
|
74570
74652
|
kind,
|
|
74571
|
-
id: entry.id
|
|
74653
|
+
id: entry.id,
|
|
74654
|
+
model_gen: priv.model_gen
|
|
74572
74655
|
})]
|
|
74573
74656
|
]
|
|
74574
74657
|
]
|
|
@@ -74740,6 +74823,10 @@ function transport_dropped(gobj) {
|
|
|
74740
74823
|
priv.load_round++;
|
|
74741
74824
|
priv.pending = 0;
|
|
74742
74825
|
priv.load_error = "";
|
|
74826
|
+
if (priv.records_before) {
|
|
74827
|
+
priv.records = priv.records_before;
|
|
74828
|
+
priv.records_before = null;
|
|
74829
|
+
}
|
|
74743
74830
|
return end_load(gobj);
|
|
74744
74831
|
}
|
|
74745
74832
|
return 0;
|
|
@@ -74750,11 +74837,22 @@ function transport_dropped(gobj) {
|
|
|
74750
74837
|
* in flight (ac_show() kept it), or the one it had. Without a
|
|
74751
74838
|
* model there is no screen to go to: the position is kept for the
|
|
74752
74839
|
* next load, and the editor says why it is empty.
|
|
74840
|
+
*
|
|
74841
|
+
* A dialog built on the model this load REPLACED is closed, and the
|
|
74842
|
+
* operator told to open it again: it shows the old record, and its
|
|
74843
|
+
* Save would write every field of it over the newer one. A load
|
|
74844
|
+
* that failed or never left replaced nothing (`model_gen` did not
|
|
74845
|
+
* move), and the dialog stays with what was typed.
|
|
74753
74846
|
***************************************************************/
|
|
74754
74847
|
function end_load(gobj) {
|
|
74755
74848
|
let priv = gobj.priv;
|
|
74756
74849
|
let seg = priv.pending_seg;
|
|
74757
74850
|
priv.pending_seg = null;
|
|
74851
|
+
if (priv.dialog && priv.dialog_gen !== priv.model_gen) {
|
|
74852
|
+
log_warning(`${gobj_short_name(gobj)}: a dialog was open on the schemas the load replaced: closed`);
|
|
74853
|
+
close_dialog(gobj);
|
|
74854
|
+
yui_shell_show_error(yui_shell_of(gobj), "the schemas were read again: open the dialog again", { t });
|
|
74855
|
+
}
|
|
74758
74856
|
if (priv.model) {
|
|
74759
74857
|
if (seg !== null) return apply_seg(gobj, seg);
|
|
74760
74858
|
return go(gobj, priv.treedb_id, priv.topic_name, priv.diagram, false);
|
|
@@ -74970,10 +75068,20 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
74970
75068
|
else if (priv.records && Array.isArray(priv.records[topic_name])) priv.records[topic_name] = Array.isArray(data) ? data : [];
|
|
74971
75069
|
if (priv.pending > 0) return 0;
|
|
74972
75070
|
if (priv.load_error) {
|
|
75071
|
+
if (priv.model) {
|
|
75072
|
+
log_warning(`${gobj_short_name(gobj)}: the schemas could not be read again (${priv.load_error}): the previous ones stay`);
|
|
75073
|
+
priv.records = priv.records_before;
|
|
75074
|
+
priv.records_before = null;
|
|
75075
|
+
priv.reload_on_open = true;
|
|
75076
|
+
yui_shell_show_error(yui_shell_of(gobj), "cannot read the schemas again: the previous ones stay", { t });
|
|
75077
|
+
return end_load(gobj);
|
|
75078
|
+
}
|
|
74973
75079
|
priv.model = null;
|
|
74974
75080
|
return end_load(gobj);
|
|
74975
75081
|
}
|
|
74976
75082
|
priv.order_undo = {};
|
|
75083
|
+
priv.records_before = null;
|
|
75084
|
+
priv.model_gen++;
|
|
74977
75085
|
build_model(gobj);
|
|
74978
75086
|
start_measuring(gobj);
|
|
74979
75087
|
return end_load(gobj);
|
|
@@ -74995,11 +75103,14 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
74995
75103
|
let record = is_object(data) ? data : Array.isArray(data) && is_object(data[0]) ? data[0] : null;
|
|
74996
75104
|
if (record) patch_record(gobj, topic_name, record);
|
|
74997
75105
|
else {
|
|
74998
|
-
|
|
75106
|
+
let not_sent = priv.save_queue.length - 1;
|
|
75107
|
+
log_warning(`${gobj_short_name(gobj)}: '${command}' answered no record` + (not_sent > 0 ? `: ${not_sent} write(s) after it were not sent` : ""));
|
|
75108
|
+
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 });
|
|
74999
75109
|
if (topic_name === T_TOPICS || topic_name === T_COLS) {
|
|
75000
75110
|
let write = priv.save_queue[0];
|
|
75001
75111
|
mark_written(gobj, topic_name, write ? write.record : null);
|
|
75002
75112
|
}
|
|
75113
|
+
priv.reload_after_write = false;
|
|
75003
75114
|
priv.save_queue = [];
|
|
75004
75115
|
priv.save_return = "";
|
|
75005
75116
|
priv.save_wrote = false;
|
|
@@ -75057,8 +75168,14 @@ function late_write_done(gobj, command, topic_name, data) {
|
|
|
75057
75168
|
/***************************************************************
|
|
75058
75169
|
* The topic a record written belongs to, read off the RECORD and
|
|
75059
75170
|
* not off the screen: a write answered late may be about a topic
|
|
75060
|
-
* the operator has left. A column names its topic in its fkey
|
|
75061
|
-
*
|
|
75171
|
+
* the operator has left. A column names its topic in its fkey; a
|
|
75172
|
+
* topic is its own id.
|
|
75173
|
+
*
|
|
75174
|
+
* The fkey is read with parse_fkey_ref(), because the store answers
|
|
75175
|
+
* in list_dict -- `[{topic_name, id, hook_name}]` -- and not in the
|
|
75176
|
+
* `topics^<topic id>^cols` strings this view writes. Split as a
|
|
75177
|
+
* string, every production answer marked nothing (fourth independent
|
|
75178
|
+
* review, probe C).
|
|
75062
75179
|
***************************************************************/
|
|
75063
75180
|
function mark_written_record(gobj, topic_name, record) {
|
|
75064
75181
|
let priv = gobj.priv;
|
|
@@ -75068,11 +75185,7 @@ function mark_written_record(gobj, topic_name, record) {
|
|
|
75068
75185
|
return;
|
|
75069
75186
|
}
|
|
75070
75187
|
if (topic_name !== T_COLS) return;
|
|
75071
|
-
let
|
|
75072
|
-
for (let ref of refs) {
|
|
75073
|
-
let parts = String(ref).split("^");
|
|
75074
|
-
if (parts.length >= 2 && parts[1]) priv.written[parts[1]] = true;
|
|
75075
|
-
}
|
|
75188
|
+
for (let ref of parse_fkey_ref(record.topics)) priv.written[ref.id] = true;
|
|
75076
75189
|
}
|
|
75077
75190
|
/***************************************************************
|
|
75078
75191
|
* Remember which topic this write belongs to, which is what
|
|
@@ -75156,14 +75269,19 @@ function ac_refresh$1(gobj, event, kw, src) {
|
|
|
75156
75269
|
* operator can still reach, and what it asks is computed against
|
|
75157
75270
|
* a model the answers in the air are about to replace.
|
|
75158
75271
|
*
|
|
75159
|
-
* Refused, and SAID
|
|
75160
|
-
*
|
|
75161
|
-
*
|
|
75162
|
-
*
|
|
75272
|
+
* Refused, and SAID. Undeclared, it answered "Event NOT DEFINED
|
|
75273
|
+
* in state ST_LOADING" and the edit was gone with no word (third
|
|
75274
|
+
* independent review).
|
|
75275
|
+
*
|
|
75276
|
+
* And NOT "try again": the same Save, once the load was in, sent
|
|
75277
|
+
* the form built on the old model -- every field of the old record
|
|
75278
|
+
* over the newer one (fourth independent review). The load that
|
|
75279
|
+
* lands closes such a dialog (end_load()); one that fails leaves it
|
|
75280
|
+
* up, on the model it was built on.
|
|
75163
75281
|
***************************************************************/
|
|
75164
75282
|
function ac_wait_for_the_load(gobj, event, kw, src) {
|
|
75165
75283
|
log_warning(`${gobj_short_name(gobj)}: ${event} refused, the schemas are loading`);
|
|
75166
|
-
yui_shell_show_error(yui_shell_of(gobj), "the schemas are loading:
|
|
75284
|
+
yui_shell_show_error(yui_shell_of(gobj), "the schemas are loading: wait for them", { t });
|
|
75167
75285
|
return -1;
|
|
75168
75286
|
}
|
|
75169
75287
|
/***************************************************************
|
|
@@ -75229,6 +75347,7 @@ function ac_show_orphans(gobj, event, kw, src) {
|
|
|
75229
75347
|
* to feed.
|
|
75230
75348
|
***************************************************************/
|
|
75231
75349
|
function confirm_then(gobj, message, detail, kw) {
|
|
75350
|
+
kw = Object.assign({ model_gen: gobj.priv.model_gen }, kw);
|
|
75232
75351
|
yui_shell_confirm_danger(yui_shell_of(gobj), message, {
|
|
75233
75352
|
t,
|
|
75234
75353
|
detail
|
|
@@ -75290,6 +75409,7 @@ function ac_save_column(gobj, event, kw, src) {
|
|
|
75290
75409
|
let topic = find_topic(priv.model, priv.treedb_id, kw.topic);
|
|
75291
75410
|
let col = kw.creating ? null : find_col(priv.model, priv.treedb_id, kw.topic, kw.col);
|
|
75292
75411
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75412
|
+
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75293
75413
|
if (!topic || !kw.creating && !col) {
|
|
75294
75414
|
log_error(`${gobj_short_name(gobj)}: ${event} names no column: ${kw.topic}.${kw.col}`);
|
|
75295
75415
|
return -1;
|
|
@@ -75411,6 +75531,7 @@ function ac_save_topic(gobj, event, kw, src) {
|
|
|
75411
75531
|
let treedb = current_treedb(gobj);
|
|
75412
75532
|
let topic = kw.creating ? null : find_topic(priv.model, priv.treedb_id, kw.topic);
|
|
75413
75533
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75534
|
+
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75414
75535
|
if (!treedb || !kw.creating && !topic) {
|
|
75415
75536
|
log_error(`${gobj_short_name(gobj)}: ${event} names no topic: ${kw.topic}`);
|
|
75416
75537
|
return -1;
|
|
@@ -75453,6 +75574,7 @@ function ac_delete_topic(gobj, event, kw, src) {
|
|
|
75453
75574
|
***************************************************************/
|
|
75454
75575
|
function ac_delete_orphan(gobj, event, kw, src) {
|
|
75455
75576
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75577
|
+
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75456
75578
|
if (empty_string(kw.id)) {
|
|
75457
75579
|
log_error(`${gobj_short_name(gobj)}: ${event} names nothing`);
|
|
75458
75580
|
return -1;
|
|
@@ -75509,6 +75631,7 @@ function ac_preview_import(gobj, event, kw, src) {
|
|
|
75509
75631
|
let priv = gobj.priv;
|
|
75510
75632
|
let treedb = current_treedb(gobj);
|
|
75511
75633
|
let incoming = null;
|
|
75634
|
+
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75512
75635
|
if (!treedb) {
|
|
75513
75636
|
log_error(`${gobj_short_name(gobj)}: ${event} with no treedb open`);
|
|
75514
75637
|
return -1;
|
|
@@ -75536,6 +75659,7 @@ function ac_preview_import(gobj, event, kw, src) {
|
|
|
75536
75659
|
function ac_apply_import(gobj, event, kw, src) {
|
|
75537
75660
|
let plan = gobj.priv.import_plan;
|
|
75538
75661
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75662
|
+
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75539
75663
|
if (!plan || plan.writes.length === 0) {
|
|
75540
75664
|
log_error(`${gobj_short_name(gobj)}: ${event} with no plan to run`);
|
|
75541
75665
|
return -1;
|
|
@@ -75578,6 +75702,7 @@ function run_import(gobj) {
|
|
|
75578
75702
|
function ac_confirmed(gobj, event, kw, src) {
|
|
75579
75703
|
let priv = gobj.priv;
|
|
75580
75704
|
if (refuse_if_readonly(gobj, event)) return -1;
|
|
75705
|
+
if (built_on_a_replaced_model(gobj, event, kw)) return -1;
|
|
75581
75706
|
if (kw.what === "import") return run_import(gobj);
|
|
75582
75707
|
if (kw.what === "topic") {
|
|
75583
75708
|
let topic = find_topic(priv.model, priv.treedb_id, kw.topic);
|