@yuneta/gobj-ui 7.23.194 → 7.23.196
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 +11 -10
- package/dist/gobj-ui.cjs.js +179 -175
- package/dist/gobj-ui.es.js +179 -175
- package/package.json +1 -1
- package/src/c_yui_form.js +10 -16
- package/src/c_yui_schema_editor.js +57 -122
- package/src/c_yui_treedb_topic_with_form.js +17 -15
- package/src/form_time_value.js +46 -0
- package/src/form_time_value.test.js +23 -0
- package/src/schema_validate.js +5 -17
- package/src/schema_validate.test.js +4 -24
- package/src/schema_version_bump.test.js +14 -71
- package/src/table_cell_text.js +53 -0
- package/src/table_cell_text.test.js +39 -0
package/README.md
CHANGED
|
@@ -2003,16 +2003,17 @@ columns**, each in its declared `order`, with the storage composed underneath
|
|
|
2003
2003
|
the qualified id, the fkey to the parent, the place among the siblings, and the
|
|
2004
2004
|
versions that publish the change.
|
|
2005
2005
|
|
|
2006
|
-
**
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2006
|
+
**An edit here is a draft** (7.23.196, with the SDK's M36 design). A write moves
|
|
2007
|
+
no version and reaches no treedb. The HOST publishes it with `C_TREEDB`'s
|
|
2008
|
+
`save-schema`, which raises the `topic_version` of each topic that changed
|
|
2009
|
+
(the one that regenerates `topic_cols.json`) and the `schema_version` (the one
|
|
2010
|
+
that makes the schema file win over the literal), once, and puts it in use with
|
|
2011
|
+
`apply-schema` and a restart of the owning yuno. Until 7.23.195 every write
|
|
2012
|
+
here raised both numbers, so an edit half made was already the schema of the
|
|
2013
|
+
next start. The topic list marks what this session wrote and has not saved,
|
|
2014
|
+
and the column screen says so in a banner; the host sends `EV_REFRESH` after a
|
|
2015
|
+
save, and the reload forgets the drafts. The export (C literal and JSON) warns
|
|
2016
|
+
while there are drafts: the literal carries the versions a save publishes.
|
|
2016
2017
|
|
|
2017
2018
|
What the screens offer:
|
|
2018
2019
|
|
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -7310,6 +7310,39 @@ function json_diff_rows(doc_a, doc_b) {
|
|
|
7310
7310
|
return rows;
|
|
7311
7311
|
}
|
|
7312
7312
|
//#endregion
|
|
7313
|
+
//#region src/form_time_value.js
|
|
7314
|
+
/****************************************************************************
|
|
7315
|
+
* form_time_value.js
|
|
7316
|
+
*
|
|
7317
|
+
* A treedb `time` / `now` column is an epoch in SECONDS, and a form
|
|
7318
|
+
* shows it in a `datetime-local` input. These two convert between
|
|
7319
|
+
* them, and they must be each other's inverse: a writable time
|
|
7320
|
+
* column travels back on EVERY save of the record.
|
|
7321
|
+
*
|
|
7322
|
+
* Copyright (c) 2026, ArtGins.
|
|
7323
|
+
* All Rights Reserved.
|
|
7324
|
+
****************************************************************************/
|
|
7325
|
+
/************************************************************
|
|
7326
|
+
* A Date -> the value of a `datetime-local` input, in local time,
|
|
7327
|
+
* WITH seconds: the input is built with `step: 1`, which is what
|
|
7328
|
+
* lets it hold them. Written as "YYYY-MM-DDTHH:mm" it lost them on
|
|
7329
|
+
* every save of any field (M26 of the 2026-09-21 review).
|
|
7330
|
+
************************************************************/
|
|
7331
|
+
function date_to_datetime_local(value) {
|
|
7332
|
+
if (!(value instanceof Date) || isNaN(value.getTime())) return "";
|
|
7333
|
+
let pad = (n) => String(n).padStart(2, "0");
|
|
7334
|
+
return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}T${pad(value.getHours())}:${pad(value.getMinutes())}:${pad(value.getSeconds())}`;
|
|
7335
|
+
}
|
|
7336
|
+
/************************************************************
|
|
7337
|
+
* The value of a `datetime-local` input -> epoch in seconds
|
|
7338
|
+
************************************************************/
|
|
7339
|
+
function datetime_local_to_epoch(value) {
|
|
7340
|
+
if (!value) return null;
|
|
7341
|
+
const date = new Date(value);
|
|
7342
|
+
if (isNaN(date.getTime())) return null;
|
|
7343
|
+
return Math.floor(date.getTime() / 1e3);
|
|
7344
|
+
}
|
|
7345
|
+
//#endregion
|
|
7313
7346
|
//#region src/c_yui_form.js
|
|
7314
7347
|
/***********************************************************************
|
|
7315
7348
|
* c_yui_form.js
|
|
@@ -8322,6 +8355,7 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
|
|
|
8322
8355
|
type: inputType,
|
|
8323
8356
|
placeholder
|
|
8324
8357
|
};
|
|
8358
|
+
if (inputType === "datetime-local") attrs.step = 1;
|
|
8325
8359
|
Object.assign(attrs, extras);
|
|
8326
8360
|
if (readonly) attrs.readonly = "";
|
|
8327
8361
|
else if (required) attrs.required = "";
|
|
@@ -9022,8 +9056,7 @@ function get_form_values(gobj, $form) {
|
|
|
9022
9056
|
case "input":
|
|
9023
9057
|
switch (input_type) {
|
|
9024
9058
|
case "datetime-local":
|
|
9025
|
-
|
|
9026
|
-
value = Math.floor(date.getTime() / 1e3);
|
|
9059
|
+
value = datetime_local_to_epoch($input.value);
|
|
9027
9060
|
break;
|
|
9028
9061
|
default: value = getInputValue($input);
|
|
9029
9062
|
}
|
|
@@ -9186,10 +9219,7 @@ function set_form_values(gobj, template, $form, record) {
|
|
|
9186
9219
|
case "input":
|
|
9187
9220
|
switch (input_type) {
|
|
9188
9221
|
case "datetime-local":
|
|
9189
|
-
|
|
9190
|
-
let pad = (n) => String(n).padStart(2, "0");
|
|
9191
|
-
$input.value = `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}T${pad(value.getHours())}:${pad(value.getMinutes())}`;
|
|
9192
|
-
} else $input.value = "";
|
|
9222
|
+
$input.value = date_to_datetime_local(value);
|
|
9193
9223
|
break;
|
|
9194
9224
|
case "color":
|
|
9195
9225
|
$input.value = convertColor(value);
|
|
@@ -26481,6 +26511,58 @@ function delete_impact(desc, records) {
|
|
|
26481
26511
|
return out;
|
|
26482
26512
|
}
|
|
26483
26513
|
//#endregion
|
|
26514
|
+
//#region src/table_cell_text.js
|
|
26515
|
+
/****************************************************************************
|
|
26516
|
+
* table_cell_text.js
|
|
26517
|
+
*
|
|
26518
|
+
* What a treedb table cell hands Tabulator.
|
|
26519
|
+
*
|
|
26520
|
+
* Tabulator assigns a formatter's STRING result with `innerHTML`
|
|
26521
|
+
* (only its own `plaintext` formatter escapes), so a record's text
|
|
26522
|
+
* returned as a string is parsed as markup: `a<b and c>d` showed
|
|
26523
|
+
* as `ad`, and a field holding `<img src=x onerror=...>` ran it in
|
|
26524
|
+
* the operator's browser (M31 of the 2026-09-21 review). Record
|
|
26525
|
+
* data goes in as a TEXT NODE, and a cell built around it as DOM,
|
|
26526
|
+
* never as an HTML string with the data interpolated.
|
|
26527
|
+
*
|
|
26528
|
+
* Pure but for the `document` it is handed, so it is tested
|
|
26529
|
+
* without one.
|
|
26530
|
+
*
|
|
26531
|
+
* Copyright (c) 2026, ArtGins.
|
|
26532
|
+
* All Rights Reserved.
|
|
26533
|
+
****************************************************************************/
|
|
26534
|
+
/************************************************************
|
|
26535
|
+
* A value shown as text, whatever characters it holds
|
|
26536
|
+
************************************************************/
|
|
26537
|
+
function cell_text(value, doc = globalThis.document) {
|
|
26538
|
+
if (value === null || value === void 0) return "";
|
|
26539
|
+
return doc.createTextNode(String(value));
|
|
26540
|
+
}
|
|
26541
|
+
/************************************************************
|
|
26542
|
+
* The hook cell, as a createElement2 spec: the row id is an
|
|
26543
|
+
* attribute VALUE, never text spliced into markup (an id holding
|
|
26544
|
+
* a `"` cut the attribute and lost the rest of the id)
|
|
26545
|
+
************************************************************/
|
|
26546
|
+
function hook_cell_spec(row_id, col_id, items, title, title_key) {
|
|
26547
|
+
return [
|
|
26548
|
+
"a",
|
|
26549
|
+
{
|
|
26550
|
+
class: "HOOK_CELL hook_cell",
|
|
26551
|
+
title,
|
|
26552
|
+
"data-i18n-title": title_key,
|
|
26553
|
+
"aria-label": title,
|
|
26554
|
+
"data-i18n-aria-label": title_key,
|
|
26555
|
+
"data-row_id": String(row_id),
|
|
26556
|
+
"data-col_id": String(col_id)
|
|
26557
|
+
},
|
|
26558
|
+
[["span", { class: "icon yi-eye" }], [
|
|
26559
|
+
"u",
|
|
26560
|
+
{ class: "HOOK_CELL_COUNT" },
|
|
26561
|
+
`[ ${items} ]`
|
|
26562
|
+
]]
|
|
26563
|
+
];
|
|
26564
|
+
}
|
|
26565
|
+
//#endregion
|
|
26484
26566
|
//#region src/c_yui_treedb_topic_with_form.js
|
|
26485
26567
|
/***********************************************************************
|
|
26486
26568
|
* c_yui_treedb_topic_with_form.js
|
|
@@ -27907,18 +27989,8 @@ function transform__treedb_value_2_table_value(gobj, col, value, row, field) {
|
|
|
27907
27989
|
break;
|
|
27908
27990
|
case "hook":
|
|
27909
27991
|
let items = (0, _yuneta_gobj_js.treedb_hook_data_size)(value);
|
|
27910
|
-
if (items > 0)
|
|
27911
|
-
|
|
27912
|
-
value = [
|
|
27913
|
-
"<a class=\"hook_cell\" ",
|
|
27914
|
-
`title="${hook_title}" aria-label="${hook_title}" `,
|
|
27915
|
-
`data-row_id="${row.id}" `,
|
|
27916
|
-
`data-col_id="${col.id}" > `,
|
|
27917
|
-
"<span style=\"\" class=\"icon yi-eye\"></span>",
|
|
27918
|
-
`<span>[ <u>${items}</u> ]</span>`,
|
|
27919
|
-
"</a>"
|
|
27920
|
-
].join("");
|
|
27921
|
-
} else value = "";
|
|
27992
|
+
if (items > 0) value = (0, _yuneta_gobj_js.createElement2)(hook_cell_spec(row.id, col.id, items, (0, i18next.t)("show linked records"), "show linked records"));
|
|
27993
|
+
else value = "";
|
|
27922
27994
|
break;
|
|
27923
27995
|
case "file":
|
|
27924
27996
|
case "fkey":
|
|
@@ -27944,7 +28016,7 @@ function transform__treedb_value_2_table_value(gobj, col, value, row, field) {
|
|
|
27944
28016
|
value = /* @__PURE__ */ new Date(value * 1e3);
|
|
27945
28017
|
const rawLocale = navigator.language;
|
|
27946
28018
|
const userLocale = typeof rawLocale === "string" && rawLocale && rawLocale !== "undefined" ? rawLocale : void 0;
|
|
27947
|
-
|
|
28019
|
+
const formatter = new Intl.DateTimeFormat(userLocale, {
|
|
27948
28020
|
day: "numeric",
|
|
27949
28021
|
month: "short",
|
|
27950
28022
|
year: "numeric",
|
|
@@ -27952,7 +28024,12 @@ function transform__treedb_value_2_table_value(gobj, col, value, row, field) {
|
|
|
27952
28024
|
minute: "2-digit",
|
|
27953
28025
|
second: "2-digit",
|
|
27954
28026
|
hour12: true
|
|
27955
|
-
})
|
|
28027
|
+
});
|
|
28028
|
+
value = (0, _yuneta_gobj_js.createElement2)([
|
|
28029
|
+
"span",
|
|
28030
|
+
{ class: "is-size-7" },
|
|
28031
|
+
formatter.format(value)
|
|
28032
|
+
]);
|
|
27956
28033
|
}
|
|
27957
28034
|
break;
|
|
27958
28035
|
case "color": break;
|
|
@@ -27964,6 +28041,7 @@ function transform__treedb_value_2_table_value(gobj, col, value, row, field) {
|
|
|
27964
28041
|
(0, _yuneta_gobj_js.log_error)(`transform__treedb_value_2_table_value() unexpected object value for field '${field}' (type='${field_desc.type}', real_type='${field_desc.real_type}'): ${JSON.stringify(value)}, topic ${priv.topic_name}`);
|
|
27965
28042
|
value = JSON.stringify(value);
|
|
27966
28043
|
}
|
|
28044
|
+
if (typeof value === "string" && value !== "") value = cell_text(value);
|
|
27967
28045
|
return value;
|
|
27968
28046
|
}
|
|
27969
28047
|
/************************************************************
|
|
@@ -70085,10 +70163,11 @@ function register_c_yui_treedb_schema() {
|
|
|
70085
70163
|
* operator drew does nothing at all. Restarting on
|
|
70086
70164
|
* this is an outage with no gain.
|
|
70087
70165
|
* `warning` the schema opens and something is not what it looks
|
|
70088
|
-
* like
|
|
70089
|
-
*
|
|
70090
|
-
*
|
|
70091
|
-
*
|
|
70166
|
+
* like.
|
|
70167
|
+
*
|
|
70168
|
+
* A version is not checked here: an edit is a DRAFT and moves no
|
|
70169
|
+
* version, and C_TREEDB's save-schema raises the versions of what
|
|
70170
|
+
* changed when it publishes it.
|
|
70092
70171
|
*
|
|
70093
70172
|
* Every `code` is an i18n key: the caller renders, this decides.
|
|
70094
70173
|
*
|
|
@@ -70135,9 +70214,6 @@ var FKEY_TYPES = [
|
|
|
70135
70214
|
***************************************************************/
|
|
70136
70215
|
function validate_schema(treedb, options) {
|
|
70137
70216
|
let findings = [];
|
|
70138
|
-
let opts = options || {};
|
|
70139
|
-
let written = Array.isArray(opts.written_topics) ? opts.written_topics : [];
|
|
70140
|
-
let baseline = opts.baseline || {};
|
|
70141
70217
|
if (!treedb || !Array.isArray(treedb.topics)) return findings;
|
|
70142
70218
|
let add = (severity, code, topic, col, detail) => {
|
|
70143
70219
|
findings.push({
|
|
@@ -70158,10 +70234,6 @@ function validate_schema(treedb, options) {
|
|
|
70158
70234
|
let pkey = topic.pkey || "id";
|
|
70159
70235
|
if (col_names.indexOf(pkey) < 0) add("error", "pkey names no column", topic.name, "", pkey);
|
|
70160
70236
|
for (let pkey2 of topic_pkey2s(topic.record)) if (col_names.indexOf(pkey2) < 0) add("error", "pkey2 names no column", topic.name, "", pkey2);
|
|
70161
|
-
if (written.indexOf(topic.id) >= 0) {
|
|
70162
|
-
let before = baseline[topic.id];
|
|
70163
|
-
if (before !== void 0 && String(before) === String(topic.topic_version)) add("warning", "topic version not bumped", topic.name, "", String(topic.topic_version));
|
|
70164
|
-
}
|
|
70165
70237
|
for (let col of topic.cols) {
|
|
70166
70238
|
let flags = col_flags(col.record);
|
|
70167
70239
|
let type = col.record ? col.record.type : "";
|
|
@@ -71430,13 +71502,15 @@ function write_options(op) {
|
|
|
71430
71502
|
* fkey, the order of a new sibling, the version that publishes
|
|
71431
71503
|
* the change.
|
|
71432
71504
|
*
|
|
71433
|
-
*
|
|
71434
|
-
*
|
|
71435
|
-
*
|
|
71436
|
-
*
|
|
71437
|
-
* the
|
|
71438
|
-
*
|
|
71439
|
-
*
|
|
71505
|
+
* AN EDIT IS A DRAFT. A write here moves no version and reaches no
|
|
71506
|
+
* treedb: the host SAVES it (C_TREEDB's save-schema raises the
|
|
71507
|
+
* topic_version of what changed and the schema_version, once) and
|
|
71508
|
+
* APPLIES it (apply-schema + a restart of the owning yuno). Until
|
|
71509
|
+
* the owner's design of M36 (2026-09-21 review) every write here
|
|
71510
|
+
* raised both versions, so an edit half made was already the
|
|
71511
|
+
* schema of the next start. The topic list marks what this session
|
|
71512
|
+
* wrote and has not saved; the host's EV_REFRESH after a save is
|
|
71513
|
+
* what forgets it.
|
|
71440
71514
|
*
|
|
71441
71515
|
* WHAT ELSE IS HERE, and why each is here and not somewhere else:
|
|
71442
71516
|
*
|
|
@@ -71781,16 +71855,20 @@ function start_measuring(gobj) {
|
|
|
71781
71855
|
for (let treedb of priv.model.treedbs) for (let topic of treedb.topics) priv.baseline[topic.id] = topic.topic_version;
|
|
71782
71856
|
}
|
|
71783
71857
|
/***************************************************************
|
|
71784
|
-
* "This topic was written
|
|
71858
|
+
* "This topic was written in this session and is not saved."
|
|
71859
|
+
*
|
|
71860
|
+
* An edit is a DRAFT: it moves no version and reaches no treedb
|
|
71861
|
+
* until the host saves it (C_TREEDB's save-schema, which raises the
|
|
71862
|
+
* versions of what changed) -- and the save makes the host send
|
|
71863
|
+
* EV_REFRESH, whose reload is what forgets the drafts.
|
|
71785
71864
|
*
|
|
71786
|
-
* ONE predicate, because it is asked in
|
|
71787
|
-
* list draws a chip with it
|
|
71788
|
-
* and
|
|
71865
|
+
* ONE predicate, because it is asked in three places -- the topic
|
|
71866
|
+
* list draws a chip with it, the column view a banner, the export
|
|
71867
|
+
* a warning -- and copies of a rule are how they drift.
|
|
71789
71868
|
***************************************************************/
|
|
71790
|
-
function
|
|
71791
|
-
if (!topic || !written
|
|
71792
|
-
|
|
71793
|
-
return String(baseline[topic.id]) === String(topic.topic_version);
|
|
71869
|
+
function topic_is_draft(written, topic) {
|
|
71870
|
+
if (!topic || !written) return false;
|
|
71871
|
+
return written[topic.id] ? true : false;
|
|
71794
71872
|
}
|
|
71795
71873
|
/***************************************************************
|
|
71796
71874
|
* Say what the whole store would be refused for.
|
|
@@ -72232,7 +72310,7 @@ function render_topics(gobj, $body) {
|
|
|
72232
72310
|
let twice = repeated_names(treedb.topics);
|
|
72233
72311
|
let $rows = [];
|
|
72234
72312
|
for (let topic of treedb.topics) {
|
|
72235
|
-
let pending =
|
|
72313
|
+
let pending = topic_is_draft(priv.written, topic);
|
|
72236
72314
|
let ambiguous = !!twice[topic.name];
|
|
72237
72315
|
let address = ambiguous ? topic.id : topic.name;
|
|
72238
72316
|
let $actions = [];
|
|
@@ -72467,7 +72545,7 @@ function render_columns(gobj, $body) {
|
|
|
72467
72545
|
{ class: "SCHEMA_COLUMNS p-3" },
|
|
72468
72546
|
[]
|
|
72469
72547
|
]);
|
|
72470
|
-
let $banner =
|
|
72548
|
+
let $banner = draft_banner(gobj, topic);
|
|
72471
72549
|
if ($banner) $wrap.appendChild($banner);
|
|
72472
72550
|
let twice = repeated_names(topic.cols);
|
|
72473
72551
|
let $rows = [];
|
|
@@ -72545,66 +72623,37 @@ function render_columns(gobj, $body) {
|
|
|
72545
72623
|
(0, _yuneta_gobj_js.refresh_language)($wrap, i18next.t);
|
|
72546
72624
|
}
|
|
72547
72625
|
/***************************************************************
|
|
72548
|
-
* "This topic
|
|
72626
|
+
* "This topic has changes that are not saved."
|
|
72549
72627
|
*
|
|
72550
|
-
*
|
|
72551
|
-
*
|
|
72552
|
-
*
|
|
72553
|
-
*
|
|
72554
|
-
*
|
|
72628
|
+
* A draft, not an error: the edit is in __system__ and moves no
|
|
72629
|
+
* version, so the treedb does not see it until the host saves it
|
|
72630
|
+
* (and applies it). The banner says so and offers nothing -- the
|
|
72631
|
+
* save is the host's, one level up, because it publishes the whole
|
|
72632
|
+
* treedb and not one topic.
|
|
72555
72633
|
***************************************************************/
|
|
72556
|
-
function
|
|
72634
|
+
function draft_banner(gobj, topic) {
|
|
72557
72635
|
let priv = gobj.priv;
|
|
72558
|
-
if (!
|
|
72636
|
+
if (!topic_is_draft(priv.written, topic)) return null;
|
|
72559
72637
|
if (is_readonly(gobj)) return null;
|
|
72560
|
-
|
|
72638
|
+
return (0, _yuneta_gobj_js.createElement2)([
|
|
72561
72639
|
"div",
|
|
72562
72640
|
{
|
|
72563
|
-
class: "
|
|
72641
|
+
class: "SCHEMA_DRAFT_BANNER notification is-warning is-light p-3 mb-3 is-flex is-align-items-center",
|
|
72564
72642
|
style: "gap:.5rem;"
|
|
72565
72643
|
},
|
|
72566
|
-
[
|
|
72567
|
-
|
|
72568
|
-
|
|
72569
|
-
|
|
72570
|
-
|
|
72571
|
-
|
|
72572
|
-
|
|
72573
|
-
"
|
|
72574
|
-
|
|
72575
|
-
|
|
72576
|
-
|
|
72577
|
-
|
|
72578
|
-
(0, i18next.t)("version not raised")
|
|
72579
|
-
],
|
|
72580
|
-
[
|
|
72581
|
-
"button",
|
|
72582
|
-
{
|
|
72583
|
-
class: "SCHEMA_VERSION_BUMP button is-warning",
|
|
72584
|
-
type: "button",
|
|
72585
|
-
style: "margin-left:auto;",
|
|
72586
|
-
title: (0, i18next.t)("raise the version"),
|
|
72587
|
-
"aria-label": (0, i18next.t)("raise the version"),
|
|
72588
|
-
"data-i18n-title": "raise the version",
|
|
72589
|
-
"data-i18n-aria-label": "raise the version"
|
|
72590
|
-
},
|
|
72591
|
-
[[
|
|
72592
|
-
"span",
|
|
72593
|
-
{ class: "icon" },
|
|
72594
|
-
[["i", { class: "yi-circle-up" }]]
|
|
72595
|
-
], [
|
|
72596
|
-
"span",
|
|
72597
|
-
{ i18n: "raise" },
|
|
72598
|
-
(0, i18next.t)("raise")
|
|
72599
|
-
]]
|
|
72600
|
-
]
|
|
72601
|
-
]
|
|
72644
|
+
[[
|
|
72645
|
+
"span",
|
|
72646
|
+
{ class: "icon" },
|
|
72647
|
+
[["i", { class: "yi-triangle-exclamation" }]]
|
|
72648
|
+
], [
|
|
72649
|
+
"span",
|
|
72650
|
+
{
|
|
72651
|
+
class: "SCHEMA_DRAFT_TEXT is-size-7",
|
|
72652
|
+
i18n: "unsaved schema changes: save to publish them"
|
|
72653
|
+
},
|
|
72654
|
+
(0, i18next.t)("unsaved schema changes: save to publish them")
|
|
72655
|
+
]]
|
|
72602
72656
|
]);
|
|
72603
|
-
$banner.querySelector(".SCHEMA_VERSION_BUMP").addEventListener("click", (evt) => {
|
|
72604
|
-
evt.stopPropagation();
|
|
72605
|
-
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_BUMP_VERSION", { topic: topic.name }, gobj);
|
|
72606
|
-
});
|
|
72607
|
-
return $banner;
|
|
72608
72657
|
}
|
|
72609
72658
|
/***************************************************************
|
|
72610
72659
|
* One column, as a row. The drag events carry INDEXES in the
|
|
@@ -73473,6 +73522,8 @@ function open_report(gobj, findings, treedb_id) {
|
|
|
73473
73522
|
* as a download, which a published page cannot start anyway.
|
|
73474
73523
|
***************************************************************/
|
|
73475
73524
|
function open_export(gobj, treedb) {
|
|
73525
|
+
let priv = gobj.priv;
|
|
73526
|
+
let drafts = treedb.topics.some((topic) => topic_is_draft(priv.written, topic));
|
|
73476
73527
|
let c_text = schema_to_c(treedb);
|
|
73477
73528
|
let json_text = JSON.stringify(schema_to_json(treedb), null, 4);
|
|
73478
73529
|
let $content = (0, _yuneta_gobj_js.createElement2)([
|
|
@@ -73526,13 +73577,29 @@ function open_export(gobj, treedb) {
|
|
|
73526
73577
|
},
|
|
73527
73578
|
(0, i18next.t)("an edit made here works and lives in no source: this is what to paste back")
|
|
73528
73579
|
],
|
|
73580
|
+
drafts ? [
|
|
73581
|
+
"p",
|
|
73582
|
+
{
|
|
73583
|
+
class: "SCHEMA_EXPORT_DRAFTS notification is-warning is-light p-2 mb-2 is-size-7",
|
|
73584
|
+
i18n: "unsaved changes: save first, so the literal carries the versions that publish it"
|
|
73585
|
+
},
|
|
73586
|
+
(0, i18next.t)("unsaved changes: save first, so the literal carries the versions that publish it")
|
|
73587
|
+
] : [
|
|
73588
|
+
"span",
|
|
73589
|
+
{},
|
|
73590
|
+
""
|
|
73591
|
+
],
|
|
73529
73592
|
[
|
|
73530
73593
|
"textarea",
|
|
73531
73594
|
{
|
|
73532
73595
|
class: "SCHEMA_EXPORT_TEXT textarea is-small is-family-monospace",
|
|
73533
73596
|
rows: "18",
|
|
73534
73597
|
readonly: "readonly",
|
|
73535
|
-
spellcheck: "false"
|
|
73598
|
+
spellcheck: "false",
|
|
73599
|
+
title: (0, i18next.t)("schema"),
|
|
73600
|
+
"data-i18n-title": "schema",
|
|
73601
|
+
"aria-label": (0, i18next.t)("schema"),
|
|
73602
|
+
"data-i18n-aria-label": "schema"
|
|
73536
73603
|
},
|
|
73537
73604
|
c_text
|
|
73538
73605
|
],
|
|
@@ -73546,7 +73613,11 @@ function open_export(gobj, treedb) {
|
|
|
73546
73613
|
"button",
|
|
73547
73614
|
{
|
|
73548
73615
|
class: "SCHEMA_EXPORT_COPY button",
|
|
73549
|
-
type: "button"
|
|
73616
|
+
type: "button",
|
|
73617
|
+
title: (0, i18next.t)("copy"),
|
|
73618
|
+
"data-i18n-title": "copy",
|
|
73619
|
+
"aria-label": (0, i18next.t)("copy"),
|
|
73620
|
+
"data-i18n-aria-label": "copy"
|
|
73550
73621
|
},
|
|
73551
73622
|
[[
|
|
73552
73623
|
"span",
|
|
@@ -73881,52 +73952,6 @@ function open_orphans(gobj) {
|
|
|
73881
73952
|
* Writing
|
|
73882
73953
|
***************************/
|
|
73883
73954
|
/***************************************************************
|
|
73884
|
-
* THE TWO VERSIONS A SCHEMA EDIT HAS TO RAISE, and why both.
|
|
73885
|
-
*
|
|
73886
|
-
* `topic_version` is what publishes a change of a topic's
|
|
73887
|
-
* columns: leave it and the persisted `topic_cols.json` masks
|
|
73888
|
-
* the edit, the restart succeeds and nothing moved.
|
|
73889
|
-
*
|
|
73890
|
-
* `schema_version` is what publishes the schema as a whole —
|
|
73891
|
-
* "the stored one wins on ties, and the incoming one has to be
|
|
73892
|
-
* strictly newer to take over" (c_treedb.c). It is safe to
|
|
73893
|
-
* raise: re-projection from C compares `c_schema_version`, the
|
|
73894
|
-
* version of the LITERAL, precisely so that an edit made here
|
|
73895
|
-
* survives every start until a newer literal arrives.
|
|
73896
|
-
*
|
|
73897
|
-
* So every write that changes a schema carries both, and the
|
|
73898
|
-
* operator is never asked to remember either.
|
|
73899
|
-
***************************************************************/
|
|
73900
|
-
function version_writes(gobj, topic) {
|
|
73901
|
-
let treedb = current_treedb(gobj);
|
|
73902
|
-
let writes = [];
|
|
73903
|
-
if (topic) {
|
|
73904
|
-
let version = Number(topic.topic_version);
|
|
73905
|
-
if (!isFinite(version)) version = 0;
|
|
73906
|
-
writes.push({
|
|
73907
|
-
op: "update",
|
|
73908
|
-
topic_name: T_TOPICS,
|
|
73909
|
-
record: {
|
|
73910
|
-
id: topic.id,
|
|
73911
|
-
topic_version: version + 1
|
|
73912
|
-
}
|
|
73913
|
-
});
|
|
73914
|
-
}
|
|
73915
|
-
if (treedb) {
|
|
73916
|
-
let version = Number(treedb.schema_version);
|
|
73917
|
-
if (!isFinite(version)) version = 0;
|
|
73918
|
-
writes.push({
|
|
73919
|
-
op: "update",
|
|
73920
|
-
topic_name: T_TREEDBS,
|
|
73921
|
-
record: {
|
|
73922
|
-
id: treedb.id,
|
|
73923
|
-
schema_version: version + 1
|
|
73924
|
-
}
|
|
73925
|
-
});
|
|
73926
|
-
}
|
|
73927
|
-
return writes;
|
|
73928
|
-
}
|
|
73929
|
-
/***************************************************************
|
|
73930
73955
|
* WHERE THE COLUMNS WERE before this session started moving them.
|
|
73931
73956
|
*
|
|
73932
73957
|
* A drag is a WRITE: the order is a field of the column, so the drop
|
|
@@ -74385,7 +74410,7 @@ function ac_save_column(gobj, event, kw, src) {
|
|
|
74385
74410
|
op: kw.creating ? "create" : "update",
|
|
74386
74411
|
topic_name: T_COLS,
|
|
74387
74412
|
record: column_record(gobj, topic, col, values)
|
|
74388
|
-
}]
|
|
74413
|
+
}]);
|
|
74389
74414
|
}
|
|
74390
74415
|
function ac_delete_column(gobj, event, kw, src) {
|
|
74391
74416
|
let priv = gobj.priv;
|
|
@@ -74436,7 +74461,7 @@ function ac_move_column(gobj, event, kw, src) {
|
|
|
74436
74461
|
};
|
|
74437
74462
|
});
|
|
74438
74463
|
if (writes.length === 0) return 0;
|
|
74439
|
-
return queue_writes(gobj, writes
|
|
74464
|
+
return queue_writes(gobj, writes);
|
|
74440
74465
|
}
|
|
74441
74466
|
/***************************************************************
|
|
74442
74467
|
* Put the columns back where they were before the dragging
|
|
@@ -74456,7 +74481,7 @@ function ac_undo_order(gobj, event, kw, src) {
|
|
|
74456
74481
|
return 0;
|
|
74457
74482
|
}
|
|
74458
74483
|
delete priv.order_undo[topic.id];
|
|
74459
|
-
return queue_writes(gobj, writes
|
|
74484
|
+
return queue_writes(gobj, writes);
|
|
74460
74485
|
}
|
|
74461
74486
|
/***************************************************************
|
|
74462
74487
|
* Editing a topic.
|
|
@@ -74509,7 +74534,7 @@ function ac_save_topic(gobj, event, kw, src) {
|
|
|
74509
74534
|
op: kw.creating ? "create" : "update",
|
|
74510
74535
|
topic_name: T_TOPICS,
|
|
74511
74536
|
record: topic_record(gobj, treedb, topic, values)
|
|
74512
|
-
}]
|
|
74537
|
+
}]);
|
|
74513
74538
|
}
|
|
74514
74539
|
function ac_delete_topic(gobj, event, kw, src) {
|
|
74515
74540
|
let priv = gobj.priv;
|
|
@@ -74526,20 +74551,6 @@ function ac_delete_topic(gobj, event, kw, src) {
|
|
|
74526
74551
|
return 0;
|
|
74527
74552
|
}
|
|
74528
74553
|
/***************************************************************
|
|
74529
|
-
* Raising a version by hand: what the banner offers when
|
|
74530
|
-
* something else wrote the topic and left its version alone.
|
|
74531
|
-
***************************************************************/
|
|
74532
|
-
function ac_bump_version(gobj, event, kw, src) {
|
|
74533
|
-
let priv = gobj.priv;
|
|
74534
|
-
let topic = find_topic(priv.model, priv.treedb_id, kw.topic);
|
|
74535
|
-
if (refuse_if_readonly(gobj, event)) return -1;
|
|
74536
|
-
if (!topic) {
|
|
74537
|
-
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} names no topic: ${kw.topic}`);
|
|
74538
|
-
return -1;
|
|
74539
|
-
}
|
|
74540
|
-
return queue_writes(gobj, version_writes(gobj, topic));
|
|
74541
|
-
}
|
|
74542
|
-
/***************************************************************
|
|
74543
74554
|
* Deleting a leftover.
|
|
74544
74555
|
***************************************************************/
|
|
74545
74556
|
function ac_delete_orphan(gobj, event, kw, src) {
|
|
@@ -74688,11 +74699,10 @@ function ac_confirmed(gobj, event, kw, src) {
|
|
|
74688
74699
|
topic_name: T_TOPICS,
|
|
74689
74700
|
record: { id: topic.id }
|
|
74690
74701
|
});
|
|
74691
|
-
return queue_writes(gobj, writes
|
|
74702
|
+
return queue_writes(gobj, writes);
|
|
74692
74703
|
}
|
|
74693
74704
|
if (kw.what === "column") {
|
|
74694
|
-
let
|
|
74695
|
-
let col = topic ? find_col(priv.model, priv.treedb_id, kw.topic, kw.col) : null;
|
|
74705
|
+
let col = find_topic(priv.model, priv.treedb_id, kw.topic) ? find_col(priv.model, priv.treedb_id, kw.topic, kw.col) : null;
|
|
74696
74706
|
if (!col) {
|
|
74697
74707
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} names no column: ${kw.col}`);
|
|
74698
74708
|
return -1;
|
|
@@ -74701,7 +74711,7 @@ function ac_confirmed(gobj, event, kw, src) {
|
|
|
74701
74711
|
op: "delete",
|
|
74702
74712
|
topic_name: T_COLS,
|
|
74703
74713
|
record: { id: col.id }
|
|
74704
|
-
}]
|
|
74714
|
+
}]);
|
|
74705
74715
|
}
|
|
74706
74716
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} of nothing this view asked about: ${kw.what}`);
|
|
74707
74717
|
return -1;
|
|
@@ -74890,11 +74900,6 @@ function create_gclass$1(gclass_name) {
|
|
|
74890
74900
|
"EV_UNDO_ORDER",
|
|
74891
74901
|
ac_undo_order,
|
|
74892
74902
|
null
|
|
74893
|
-
],
|
|
74894
|
-
[
|
|
74895
|
-
"EV_BUMP_VERSION",
|
|
74896
|
-
ac_bump_version,
|
|
74897
|
-
null
|
|
74898
74903
|
]
|
|
74899
74904
|
])],
|
|
74900
74905
|
["ST_SAVING", COMMON.slice()]
|
|
@@ -74923,7 +74928,6 @@ function create_gclass$1(gclass_name) {
|
|
|
74923
74928
|
["EV_SAVE_COLUMN", 0],
|
|
74924
74929
|
["EV_MOVE_COLUMN", 0],
|
|
74925
74930
|
["EV_UNDO_ORDER", 0],
|
|
74926
|
-
["EV_BUMP_VERSION", 0],
|
|
74927
74931
|
["EV_VALIDATE", 0],
|
|
74928
74932
|
["EV_EXPORT", 0],
|
|
74929
74933
|
["EV_IMPORT", 0],
|