@yuneta/gobj-ui 6.1.0 → 6.1.1
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 -1
- package/dist/gobj-ui.cjs.js +232 -77
- package/dist/gobj-ui.es.js +232 -77
- package/package.json +1 -1
- package/src/c_yui_schema_editor.js +119 -33
- package/src/schema_descs.js +14 -6
- package/src/schema_descs.test.js +25 -0
- package/src/schema_import.js +17 -6
- package/src/schema_import.test.js +21 -0
- package/src/schema_model.js +26 -0
- package/src/schema_model.test.js +25 -0
- package/src/schema_to_c.js +22 -8
- package/src/schema_to_c.test.js +47 -0
- package/src/schema_write_options.js +60 -0
- package/src/schema_write_options.test.js +65 -0
- package/src/yui_icons.css +14 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -20574,6 +20574,22 @@ function build_schema_model(records) {
|
|
|
20574
20574
|
};
|
|
20575
20575
|
}
|
|
20576
20576
|
/***************************************************************
|
|
20577
|
+
* Is there a value here at all?
|
|
20578
|
+
*
|
|
20579
|
+
* The store answers a `blob` column that was never set with an
|
|
20580
|
+
* EMPTY COLLECTION, not with nothing: `enum: {}`, `hook: {}`,
|
|
20581
|
+
* `default: {}`. Read as "a value", those turn every export into
|
|
20582
|
+
* a schema full of empty objects — and `'hook': {}` in a literal
|
|
20583
|
+
* is a hook with no mapping, which is a link the treedb builds
|
|
20584
|
+
* and nothing writes.
|
|
20585
|
+
***************************************************************/
|
|
20586
|
+
function is_empty_value(value) {
|
|
20587
|
+
if (value === null || value === void 0 || value === "") return true;
|
|
20588
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
20589
|
+
if (typeof value === "object") return Object.keys(value).length === 0;
|
|
20590
|
+
return false;
|
|
20591
|
+
}
|
|
20592
|
+
/***************************************************************
|
|
20577
20593
|
* The fields of a column that are DECLARED as one thing and
|
|
20578
20594
|
* STORED as another.
|
|
20579
20595
|
*
|
|
@@ -20911,6 +20927,7 @@ var COL_STORAGE_FIELDS = [
|
|
|
20911
20927
|
"value",
|
|
20912
20928
|
"topics",
|
|
20913
20929
|
"order",
|
|
20930
|
+
"_geometry",
|
|
20914
20931
|
"__md_treedb__"
|
|
20915
20932
|
];
|
|
20916
20933
|
var TOPIC_STORAGE_FIELDS = [
|
|
@@ -20919,6 +20936,7 @@ var TOPIC_STORAGE_FIELDS = [
|
|
|
20919
20936
|
"treedbs",
|
|
20920
20937
|
"cols",
|
|
20921
20938
|
"order",
|
|
20939
|
+
"_geometry",
|
|
20922
20940
|
"__md_treedb__"
|
|
20923
20941
|
];
|
|
20924
20942
|
var COL_JSON_FIELDS = [
|
|
@@ -20942,13 +20960,16 @@ function col_desc(col) {
|
|
|
20942
20960
|
let desc = {};
|
|
20943
20961
|
for (let [key, value] of Object.entries(record)) {
|
|
20944
20962
|
if (COL_STORAGE_FIELDS.indexOf(key) >= 0) continue;
|
|
20945
|
-
if (value
|
|
20946
|
-
|
|
20963
|
+
if (is_empty_value(value)) continue;
|
|
20964
|
+
let read = COL_JSON_FIELDS.indexOf(key) >= 0 ? as_json(value) : value;
|
|
20965
|
+
if (is_empty_value(read)) continue;
|
|
20966
|
+
desc[key] = read;
|
|
20947
20967
|
}
|
|
20948
20968
|
desc.id = col.name;
|
|
20949
20969
|
desc.flag = col_flags(record);
|
|
20950
20970
|
let hook = col_hook(record);
|
|
20951
|
-
if (hook) desc.hook = hook;
|
|
20971
|
+
if (hook && !is_empty_value(hook)) desc.hook = hook;
|
|
20972
|
+
else delete desc.hook;
|
|
20952
20973
|
let e = col_enum(record);
|
|
20953
20974
|
if (e.length > 0) desc.enum = e;
|
|
20954
20975
|
return desc;
|
|
@@ -20966,7 +20987,7 @@ function topic_descs(treedb) {
|
|
|
20966
20987
|
let desc = {};
|
|
20967
20988
|
for (let [key, value] of Object.entries(record)) {
|
|
20968
20989
|
if (TOPIC_STORAGE_FIELDS.indexOf(key) >= 0) continue;
|
|
20969
|
-
if (value
|
|
20990
|
+
if (is_empty_value(value)) continue;
|
|
20970
20991
|
desc[key] = value;
|
|
20971
20992
|
}
|
|
20972
20993
|
desc.topic_name = topic.name;
|
|
@@ -21023,6 +21044,7 @@ var COL_SKIP = [
|
|
|
21023
21044
|
"value",
|
|
21024
21045
|
"topics",
|
|
21025
21046
|
"order",
|
|
21047
|
+
"_geometry",
|
|
21026
21048
|
"__md_treedb__"
|
|
21027
21049
|
];
|
|
21028
21050
|
var TOPIC_SKIP = [
|
|
@@ -21031,6 +21053,7 @@ var TOPIC_SKIP = [
|
|
|
21031
21053
|
"treedbs",
|
|
21032
21054
|
"cols",
|
|
21033
21055
|
"order",
|
|
21056
|
+
"_geometry",
|
|
21034
21057
|
"__md_treedb__"
|
|
21035
21058
|
];
|
|
21036
21059
|
var JSON_FIELDS$1 = [
|
|
@@ -21084,8 +21107,10 @@ function schema_to_json(treedb) {
|
|
|
21084
21107
|
let jn_topic = { id: topic.name };
|
|
21085
21108
|
for (let [key, value] of Object.entries(record)) {
|
|
21086
21109
|
if (TOPIC_SKIP.indexOf(key) >= 0) continue;
|
|
21087
|
-
if (value
|
|
21088
|
-
|
|
21110
|
+
if (is_empty_value(value)) continue;
|
|
21111
|
+
let read = JSON_FIELDS$1.indexOf(key) >= 0 ? as_json(value) : value;
|
|
21112
|
+
if (is_empty_value(read)) continue;
|
|
21113
|
+
jn_topic[key] = read;
|
|
21089
21114
|
}
|
|
21090
21115
|
if (jn_topic.topic_version !== void 0) jn_topic.topic_version = version(jn_topic.topic_version);
|
|
21091
21116
|
let pkey2s = topic_pkey2s(record);
|
|
@@ -21098,14 +21123,17 @@ function schema_to_json(treedb) {
|
|
|
21098
21123
|
let jn_col = {};
|
|
21099
21124
|
for (let [key, value] of Object.entries(col_record)) {
|
|
21100
21125
|
if (COL_SKIP.indexOf(key) >= 0) continue;
|
|
21101
|
-
if (value
|
|
21102
|
-
|
|
21126
|
+
if (is_empty_value(value)) continue;
|
|
21127
|
+
let read = JSON_FIELDS$1.indexOf(key) >= 0 ? as_json(value) : value;
|
|
21128
|
+
if (is_empty_value(read)) continue;
|
|
21129
|
+
jn_col[key] = read;
|
|
21103
21130
|
}
|
|
21104
21131
|
let flags = col_flags(col_record);
|
|
21105
21132
|
if (flags.length > 0) jn_col.flag = flags;
|
|
21106
21133
|
else delete jn_col.flag;
|
|
21107
21134
|
let hook = col_hook(col_record);
|
|
21108
|
-
if (hook) jn_col.hook = hook;
|
|
21135
|
+
if (hook && !is_empty_value(hook)) jn_col.hook = hook;
|
|
21136
|
+
else delete jn_col.hook;
|
|
21109
21137
|
let e = col_enum(col_record);
|
|
21110
21138
|
if (e.length > 0) jn_col.enum = e;
|
|
21111
21139
|
let ordered_col = {};
|
|
@@ -21290,7 +21318,7 @@ function same_value(field, a, b) {
|
|
|
21290
21318
|
list = list.filter((f) => typeof f === "string" && f.length > 0).sort();
|
|
21291
21319
|
return JSON.stringify(list);
|
|
21292
21320
|
}
|
|
21293
|
-
if (v
|
|
21321
|
+
if (is_empty_value(v)) return "";
|
|
21294
21322
|
if (typeof v === "object") return JSON.stringify(v);
|
|
21295
21323
|
return String(v);
|
|
21296
21324
|
};
|
|
@@ -21303,8 +21331,10 @@ function incoming_col_fields(col) {
|
|
|
21303
21331
|
let out = {};
|
|
21304
21332
|
for (let field of COL_FIELDS) {
|
|
21305
21333
|
let value = col ? col[field] : void 0;
|
|
21306
|
-
if (value
|
|
21307
|
-
|
|
21334
|
+
if (is_empty_value(value)) continue;
|
|
21335
|
+
let read = JSON_FIELDS.indexOf(field) >= 0 ? as_json(value) : value;
|
|
21336
|
+
if (is_empty_value(read)) continue;
|
|
21337
|
+
out[field] = read;
|
|
21308
21338
|
}
|
|
21309
21339
|
if (Array.isArray(out.flag)) out.flag = out.flag.filter((f) => typeof f === "string" && f.length > 0);
|
|
21310
21340
|
else if (typeof out.flag === "string" && out.flag) out.flag = [out.flag];
|
|
@@ -21317,14 +21347,17 @@ function stored_col_fields(record) {
|
|
|
21317
21347
|
let out = {};
|
|
21318
21348
|
for (let field of COL_FIELDS) {
|
|
21319
21349
|
let value = record ? record[field] : void 0;
|
|
21320
|
-
if (value
|
|
21321
|
-
|
|
21350
|
+
if (is_empty_value(value)) continue;
|
|
21351
|
+
let read = JSON_FIELDS.indexOf(field) >= 0 ? as_json(value) : value;
|
|
21352
|
+
if (is_empty_value(read)) continue;
|
|
21353
|
+
out[field] = read;
|
|
21322
21354
|
}
|
|
21323
21355
|
let flags = col_flags(record);
|
|
21324
21356
|
if (flags.length > 0) out.flag = flags;
|
|
21325
21357
|
else delete out.flag;
|
|
21326
21358
|
let hook = col_hook(record);
|
|
21327
|
-
if (hook) out.hook = hook;
|
|
21359
|
+
if (hook && !is_empty_value(hook)) out.hook = hook;
|
|
21360
|
+
else delete out.hook;
|
|
21328
21361
|
let e = col_enum(record);
|
|
21329
21362
|
if (e.length > 0) out.enum = e;
|
|
21330
21363
|
return out;
|
|
@@ -21949,6 +21982,61 @@ function toggle_flag(current, name, on) {
|
|
|
21949
21982
|
return out;
|
|
21950
21983
|
}
|
|
21951
21984
|
//#endregion
|
|
21985
|
+
//#region src/schema_write_options.js
|
|
21986
|
+
/***********************************************************************
|
|
21987
|
+
* schema_write_options.js
|
|
21988
|
+
*
|
|
21989
|
+
* The OPTIONS a schema write travels with, and why each one.
|
|
21990
|
+
*
|
|
21991
|
+
* Three words decide whether a write does what it says, and all
|
|
21992
|
+
* three are easy to get wrong in a way that succeeds:
|
|
21993
|
+
*
|
|
21994
|
+
* `create` a node that is not there yet is written by
|
|
21995
|
+
* `update-node` with this, not by `create-node`. The
|
|
21996
|
+
* two are not the same call: only the update path
|
|
21997
|
+
* carries `autolink`, and without a link a new column
|
|
21998
|
+
* belongs to no topic.
|
|
21999
|
+
*
|
|
22000
|
+
* `autolink` turns the fkey carried IN THE RECORD into a link.
|
|
22001
|
+
* It rewrites the node's links from the fkey fields
|
|
22002
|
+
* the record has — so on a PARTIAL update, which
|
|
22003
|
+
* carries none, it reads that as "no parents" and
|
|
22004
|
+
* UNLINKS the node. Raising a topic's version with it
|
|
22005
|
+
* on detached that topic from its treedb, and the
|
|
22006
|
+
* write returned success. It goes with a create,
|
|
22007
|
+
* where the record carries its fkey, and with nothing
|
|
22008
|
+
* else.
|
|
22009
|
+
*
|
|
22010
|
+
* `force` a delete of a node something points at. A column is
|
|
22011
|
+
* pointed at by the topic that owns it, which is not
|
|
22012
|
+
* a reason to refuse.
|
|
22013
|
+
*
|
|
22014
|
+
* Pure and tested, because the cost of getting it wrong is a
|
|
22015
|
+
* store that has to be repaired by hand, and nothing in the
|
|
22016
|
+
* answer says it happened.
|
|
22017
|
+
*
|
|
22018
|
+
* Copyright (c) 2026, ArtGins.
|
|
22019
|
+
* All Rights Reserved.
|
|
22020
|
+
***********************************************************************/
|
|
22021
|
+
/***************************************************************
|
|
22022
|
+
* write_command(op) -> the treedb command that performs it
|
|
22023
|
+
***************************************************************/
|
|
22024
|
+
function write_command(op) {
|
|
22025
|
+
return op === "delete" ? "delete-node" : "update-node";
|
|
22026
|
+
}
|
|
22027
|
+
/***************************************************************
|
|
22028
|
+
* write_options(op) -> the options it travels with
|
|
22029
|
+
***************************************************************/
|
|
22030
|
+
function write_options(op) {
|
|
22031
|
+
if (op === "delete") return { force: true };
|
|
22032
|
+
if (op === "create") return {
|
|
22033
|
+
list_dict: true,
|
|
22034
|
+
create: true,
|
|
22035
|
+
autolink: true
|
|
22036
|
+
};
|
|
22037
|
+
return { list_dict: true };
|
|
22038
|
+
}
|
|
22039
|
+
//#endregion
|
|
21952
22040
|
//#region src/c_yui_schema_editor.js
|
|
21953
22041
|
/***********************************************************************
|
|
21954
22042
|
* c_yui_schema_editor.js
|
|
@@ -22268,10 +22356,12 @@ function remote_command(gobj, command, kw) {
|
|
|
22268
22356
|
service: treedb_name,
|
|
22269
22357
|
treedb_name
|
|
22270
22358
|
}, kw || {});
|
|
22271
|
-
full_kw.__md_command__ =
|
|
22359
|
+
full_kw.__md_command__ = {
|
|
22272
22360
|
purpose: PURPOSE,
|
|
22273
|
-
|
|
22274
|
-
|
|
22361
|
+
topic_name: kw && kw.topic_name || "",
|
|
22362
|
+
record_id: kw && kw.record_id || ""
|
|
22363
|
+
};
|
|
22364
|
+
delete full_kw.record_id;
|
|
22275
22365
|
let ret = gobj_command(remote, command, full_kw, gobj);
|
|
22276
22366
|
if (ret) {
|
|
22277
22367
|
log_error(ret);
|
|
@@ -22520,9 +22610,9 @@ function render_toolbar(gobj) {
|
|
|
22520
22610
|
let $right = [];
|
|
22521
22611
|
if (priv.treedb_id && has_model) {
|
|
22522
22612
|
$right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-hexagon-nodes", priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
|
|
22523
|
-
$right.push(toolbar_button("SCHEMA_VALIDATE_BTN", "yi-
|
|
22524
|
-
$right.push(toolbar_button("SCHEMA_EXPORT_BTN", "yi-
|
|
22525
|
-
if (!readonly) $right.push(toolbar_button("SCHEMA_IMPORT_BTN", "yi-
|
|
22613
|
+
$right.push(toolbar_button("SCHEMA_VALIDATE_BTN", "yi-square-check", "check", "EV_VALIDATE", false));
|
|
22614
|
+
$right.push(toolbar_button("SCHEMA_EXPORT_BTN", "yi-download", "export", "EV_EXPORT", false));
|
|
22615
|
+
if (!readonly) $right.push(toolbar_button("SCHEMA_IMPORT_BTN", "yi-upload", "import", "EV_IMPORT", false));
|
|
22526
22616
|
}
|
|
22527
22617
|
if (priv.topic_name && !readonly && !priv.diagram) $right.push(toolbar_button("SCHEMA_ADD_COL_BTN", "yi-plus", "new column", "EV_ADD_COLUMN", false));
|
|
22528
22618
|
if (priv.treedb_id && !priv.topic_name && !readonly && !priv.diagram) $right.push(toolbar_button("SCHEMA_ADD_TOPIC_BTN", "yi-plus", "new topic", "EV_ADD_TOPIC", false));
|
|
@@ -22725,13 +22815,16 @@ function render_topics(gobj, $body) {
|
|
|
22725
22815
|
return;
|
|
22726
22816
|
}
|
|
22727
22817
|
let readonly = is_readonly(gobj);
|
|
22818
|
+
let twice = repeated_names(treedb.topics);
|
|
22728
22819
|
let $rows = [];
|
|
22729
22820
|
for (let topic of treedb.topics) {
|
|
22730
22821
|
let pending = priv.written[topic.id] && String(priv.baseline[topic.id]) === String(topic.topic_version);
|
|
22822
|
+
let ambiguous = !!twice[topic.name];
|
|
22823
|
+
let address = ambiguous ? topic.id : topic.name;
|
|
22731
22824
|
let $actions = [];
|
|
22732
22825
|
if (!readonly) {
|
|
22733
|
-
$actions.push(row_icon(gobj, "SCHEMA_TOPIC_EDIT", "yi-pen", "edit topic", "EV_EDIT_TOPIC", { topic:
|
|
22734
|
-
$actions.push(row_icon(gobj, "SCHEMA_TOPIC_DELETE", "yi-trash", "delete topic", "EV_DELETE_TOPIC", { topic:
|
|
22826
|
+
$actions.push(row_icon(gobj, "SCHEMA_TOPIC_EDIT", "yi-pen", "edit topic", "EV_EDIT_TOPIC", { topic: address }));
|
|
22827
|
+
$actions.push(row_icon(gobj, "SCHEMA_TOPIC_DELETE", "yi-trash", "delete topic", "EV_DELETE_TOPIC", { topic: address }));
|
|
22735
22828
|
}
|
|
22736
22829
|
$rows.push([
|
|
22737
22830
|
"tr",
|
|
@@ -22744,22 +22837,38 @@ function render_topics(gobj, $body) {
|
|
|
22744
22837
|
[
|
|
22745
22838
|
"td",
|
|
22746
22839
|
{ class: "SCHEMA_TOPIC_NAME" },
|
|
22747
|
-
[
|
|
22748
|
-
|
|
22749
|
-
|
|
22750
|
-
|
|
22751
|
-
|
|
22752
|
-
|
|
22753
|
-
|
|
22754
|
-
|
|
22755
|
-
|
|
22756
|
-
|
|
22757
|
-
|
|
22758
|
-
|
|
22759
|
-
|
|
22760
|
-
|
|
22761
|
-
|
|
22762
|
-
|
|
22840
|
+
[
|
|
22841
|
+
[
|
|
22842
|
+
"span",
|
|
22843
|
+
{ class: "has-text-weight-semibold" },
|
|
22844
|
+
`${topic.name}`
|
|
22845
|
+
],
|
|
22846
|
+
topic.system_topic ? [
|
|
22847
|
+
"span",
|
|
22848
|
+
{
|
|
22849
|
+
class: "SCHEMA_TOPIC_SYSTEM tag is-light ml-2",
|
|
22850
|
+
i18n: "system"
|
|
22851
|
+
},
|
|
22852
|
+
t("system")
|
|
22853
|
+
] : [
|
|
22854
|
+
"span",
|
|
22855
|
+
{},
|
|
22856
|
+
""
|
|
22857
|
+
],
|
|
22858
|
+
ambiguous ? [
|
|
22859
|
+
"div",
|
|
22860
|
+
{ class: "SCHEMA_TOPIC_ID is-size-7 has-text-grey" },
|
|
22861
|
+
[[
|
|
22862
|
+
"code",
|
|
22863
|
+
{},
|
|
22864
|
+
`${topic.id}`
|
|
22865
|
+
]]
|
|
22866
|
+
] : [
|
|
22867
|
+
"span",
|
|
22868
|
+
{},
|
|
22869
|
+
""
|
|
22870
|
+
]
|
|
22871
|
+
]
|
|
22763
22872
|
],
|
|
22764
22873
|
[
|
|
22765
22874
|
"td",
|
|
@@ -22793,12 +22902,12 @@ function render_topics(gobj, $body) {
|
|
|
22793
22902
|
{
|
|
22794
22903
|
click: (evt) => {
|
|
22795
22904
|
if (evt.target.closest(".SCHEMA_TOPIC_ACTIONS")) return;
|
|
22796
|
-
gobj_send_event(gobj, "EV_SELECT_TOPIC", { topic:
|
|
22905
|
+
gobj_send_event(gobj, "EV_SELECT_TOPIC", { topic: address }, gobj);
|
|
22797
22906
|
},
|
|
22798
22907
|
keydown: (evt) => {
|
|
22799
22908
|
if (evt.key !== "Enter" && evt.key !== " ") return;
|
|
22800
22909
|
evt.preventDefault();
|
|
22801
|
-
gobj_send_event(gobj, "EV_SELECT_TOPIC", { topic:
|
|
22910
|
+
gobj_send_event(gobj, "EV_SELECT_TOPIC", { topic: address }, gobj);
|
|
22802
22911
|
}
|
|
22803
22912
|
}
|
|
22804
22913
|
]);
|
|
@@ -22887,6 +22996,26 @@ function row_icon(gobj, logical, icon, key, event, kw) {
|
|
|
22887
22996
|
];
|
|
22888
22997
|
}
|
|
22889
22998
|
/***************************************************************
|
|
22999
|
+
* Which names appear more than once.
|
|
23000
|
+
*
|
|
23001
|
+
* A store can hold TWO GENERATIONS of the same schema: the
|
|
23002
|
+
* projector never deletes, so a treedb re-keyed by a newer SDK
|
|
23003
|
+
* keeps its old rowid-keyed rows next to the qualified ones, and
|
|
23004
|
+
* both are children of the same treedb with the same name. Drawn
|
|
23005
|
+
* as two identical rows that behave differently, that reads as a
|
|
23006
|
+
* bug in the editor; drawn with what tells them apart, it reads
|
|
23007
|
+
* as what it is.
|
|
23008
|
+
***************************************************************/
|
|
23009
|
+
function repeated_names(list) {
|
|
23010
|
+
let seen = {};
|
|
23011
|
+
let twice = {};
|
|
23012
|
+
for (let entry of list) {
|
|
23013
|
+
if (seen[entry.name]) twice[entry.name] = true;
|
|
23014
|
+
seen[entry.name] = true;
|
|
23015
|
+
}
|
|
23016
|
+
return twice;
|
|
23017
|
+
}
|
|
23018
|
+
/***************************************************************
|
|
22890
23019
|
* ST_COLUMNS — the columns of one topic, in schema order.
|
|
22891
23020
|
*
|
|
22892
23021
|
* The order is a FIELD (`order`), so the rows are draggable and
|
|
@@ -22912,8 +23041,9 @@ function render_columns(gobj, $body) {
|
|
|
22912
23041
|
]);
|
|
22913
23042
|
let $banner = version_banner(gobj, topic);
|
|
22914
23043
|
if ($banner) $wrap.appendChild($banner);
|
|
23044
|
+
let twice = repeated_names(topic.cols);
|
|
22915
23045
|
let $rows = [];
|
|
22916
|
-
for (let i = 0; i < topic.cols.length; i++) $rows.push(column_row(gobj, topic, topic.cols[i], i, readonly));
|
|
23046
|
+
for (let i = 0; i < topic.cols.length; i++) $rows.push(column_row(gobj, topic, topic.cols[i], i, readonly, twice));
|
|
22917
23047
|
let $table = createElement2([
|
|
22918
23048
|
"div",
|
|
22919
23049
|
{
|
|
@@ -23034,7 +23164,7 @@ function version_banner(gobj, topic) {
|
|
|
23034
23164
|
[[
|
|
23035
23165
|
"span",
|
|
23036
23166
|
{ class: "icon" },
|
|
23037
|
-
[["i", { class: "yi-
|
|
23167
|
+
[["i", { class: "yi-chevron-up" }]]
|
|
23038
23168
|
], [
|
|
23039
23169
|
"span",
|
|
23040
23170
|
{ i18n: "raise" },
|
|
@@ -23055,8 +23185,10 @@ function version_banner(gobj, topic) {
|
|
|
23055
23185
|
* Yuneta event is plain JSON, so a DOM node never travels in
|
|
23056
23186
|
* one.
|
|
23057
23187
|
***************************************************************/
|
|
23058
|
-
function column_row(gobj, topic, col, index, readonly) {
|
|
23188
|
+
function column_row(gobj, topic, col, index, readonly, twice) {
|
|
23059
23189
|
let record = col.record || {};
|
|
23190
|
+
let ambiguous = !!(twice && twice[col.name]);
|
|
23191
|
+
let address = ambiguous ? col.id : col.name;
|
|
23060
23192
|
let flags = col_flags(record);
|
|
23061
23193
|
let hook = col_hook(record);
|
|
23062
23194
|
let is_pkey = col.name === (topic.pkey || "id");
|
|
@@ -23068,13 +23200,13 @@ function column_row(gobj, topic, col, index, readonly) {
|
|
|
23068
23200
|
];
|
|
23069
23201
|
});
|
|
23070
23202
|
let link = "";
|
|
23071
|
-
if (hook) link = "→ " + Object.keys(hook).join(", ");
|
|
23203
|
+
if (hook && !is_empty_value(hook)) link = "→ " + Object.keys(hook).join(", ");
|
|
23072
23204
|
else if (flags.indexOf("fkey") >= 0) link = "↖";
|
|
23073
23205
|
let $actions = [];
|
|
23074
23206
|
if (!readonly) {
|
|
23075
|
-
$actions.push(row_icon(gobj, "SCHEMA_COL_EDIT", "yi-pen", "edit column", "EV_EDIT_COLUMN", { col:
|
|
23076
|
-
$actions.push(row_icon(gobj, "SCHEMA_COL_DUPLICATE", "yi-copy", "duplicate column", "EV_DUPLICATE_COLUMN", { col:
|
|
23077
|
-
$actions.push(row_icon(gobj, "SCHEMA_COL_DELETE", "yi-trash", "delete column", "EV_DELETE_COLUMN", { col:
|
|
23207
|
+
$actions.push(row_icon(gobj, "SCHEMA_COL_EDIT", "yi-pen", "edit column", "EV_EDIT_COLUMN", { col: address }));
|
|
23208
|
+
$actions.push(row_icon(gobj, "SCHEMA_COL_DUPLICATE", "yi-copy", "duplicate column", "EV_DUPLICATE_COLUMN", { col: address }));
|
|
23209
|
+
$actions.push(row_icon(gobj, "SCHEMA_COL_DELETE", "yi-trash", "delete column", "EV_DELETE_COLUMN", { col: address }));
|
|
23078
23210
|
}
|
|
23079
23211
|
let $row = createElement2([
|
|
23080
23212
|
"tr",
|
|
@@ -23096,22 +23228,38 @@ function column_row(gobj, topic, col, index, readonly) {
|
|
|
23096
23228
|
[
|
|
23097
23229
|
"td",
|
|
23098
23230
|
{ class: "SCHEMA_COL_NAME" },
|
|
23099
|
-
[
|
|
23100
|
-
|
|
23101
|
-
|
|
23102
|
-
|
|
23103
|
-
|
|
23104
|
-
|
|
23105
|
-
|
|
23106
|
-
|
|
23107
|
-
|
|
23108
|
-
|
|
23109
|
-
|
|
23110
|
-
|
|
23111
|
-
|
|
23112
|
-
|
|
23113
|
-
|
|
23114
|
-
|
|
23231
|
+
[
|
|
23232
|
+
[
|
|
23233
|
+
"code",
|
|
23234
|
+
{},
|
|
23235
|
+
`${col.name}`
|
|
23236
|
+
],
|
|
23237
|
+
ambiguous ? [
|
|
23238
|
+
"span",
|
|
23239
|
+
{ class: "SCHEMA_COL_ID is-size-7 has-text-grey ml-2" },
|
|
23240
|
+
[[
|
|
23241
|
+
"code",
|
|
23242
|
+
{},
|
|
23243
|
+
`${col.id}`
|
|
23244
|
+
]]
|
|
23245
|
+
] : [
|
|
23246
|
+
"span",
|
|
23247
|
+
{},
|
|
23248
|
+
""
|
|
23249
|
+
],
|
|
23250
|
+
is_pkey ? [
|
|
23251
|
+
"span",
|
|
23252
|
+
{
|
|
23253
|
+
class: "SCHEMA_COL_PKEY tag is-info is-light ml-2",
|
|
23254
|
+
i18n: "pkey"
|
|
23255
|
+
},
|
|
23256
|
+
t("pkey")
|
|
23257
|
+
] : [
|
|
23258
|
+
"span",
|
|
23259
|
+
{},
|
|
23260
|
+
""
|
|
23261
|
+
]
|
|
23262
|
+
]
|
|
23115
23263
|
],
|
|
23116
23264
|
[
|
|
23117
23265
|
"td",
|
|
@@ -23154,7 +23302,7 @@ function column_row(gobj, topic, col, index, readonly) {
|
|
|
23154
23302
|
if (!readonly) wire_row_drag(gobj, $row);
|
|
23155
23303
|
$row.addEventListener("dblclick", (evt) => {
|
|
23156
23304
|
if (readonly || evt.target.closest(".SCHEMA_COL_ACTIONS")) return;
|
|
23157
|
-
gobj_send_event(gobj, "EV_EDIT_COLUMN", { col:
|
|
23305
|
+
gobj_send_event(gobj, "EV_EDIT_COLUMN", { col: address }, gobj);
|
|
23158
23306
|
});
|
|
23159
23307
|
return $row;
|
|
23160
23308
|
}
|
|
@@ -23491,7 +23639,8 @@ function open_column_form(gobj, topic, col, prefill) {
|
|
|
23491
23639
|
let record = prefill || col && col.record || {};
|
|
23492
23640
|
let creating = !col;
|
|
23493
23641
|
let type = record.type || "string";
|
|
23494
|
-
let hook = col_hook(record)
|
|
23642
|
+
let hook = col_hook(record);
|
|
23643
|
+
if (is_empty_value(hook)) hook = {};
|
|
23495
23644
|
let hook_topic = Object.keys(hook)[0] || "";
|
|
23496
23645
|
let hook_col = hook_topic ? hook[hook_topic] : "";
|
|
23497
23646
|
let treedb = current_treedb(gobj);
|
|
@@ -23641,7 +23790,7 @@ function open_topic_form(gobj, treedb, topic) {
|
|
|
23641
23790
|
[
|
|
23642
23791
|
field("SCHEMA_TOPIC_FORM_NAME", "value", "topic", text_input("value", creating ? "" : topic.name, t("topic name"), !creating), creating ? "" : "a topic is keyed by its whole path: renaming it is creating another one"),
|
|
23643
23792
|
field("SCHEMA_TOPIC_FORM_PKEY", "pkey", "pkey", creating ? text_input("pkey", "id", "id") : select_input("pkey", record.pkey || "id", col_names.length > 0 ? col_names : [record.pkey || "id"])),
|
|
23644
|
-
field("SCHEMA_TOPIC_FORM_PKEY2S", "pkey2s", "secondary keys", text_input("pkey2s", stringify_field(record.pkey2s), ""), "the column a record is
|
|
23793
|
+
field("SCHEMA_TOPIC_FORM_PKEY2S", "pkey2s", "secondary keys", text_input("pkey2s", stringify_field(record.pkey2s), ""), "the column a record is known by when its key is composed"),
|
|
23645
23794
|
field("SCHEMA_TOPIC_FORM_SYSTEM_FLAG", "system_flag", "system flag", text_input("system_flag", record.system_flag || "sf_string_key", "")),
|
|
23646
23795
|
field("SCHEMA_TOPIC_FORM_TKEY", "tkey", "time key", text_input("tkey", record.tkey, "")),
|
|
23647
23796
|
field("SCHEMA_TOPIC_FORM_VERSION", "topic_version", "version", number_input("topic_version", record.topic_version === void 0 ? 1 : record.topic_version), "raising it is what publishes a change of the columns"),
|
|
@@ -24056,7 +24205,7 @@ function open_import(gobj, treedb) {
|
|
|
24056
24205
|
[[
|
|
24057
24206
|
"span",
|
|
24058
24207
|
{ class: "icon" },
|
|
24059
|
-
[["i", { class: "yi-
|
|
24208
|
+
[["i", { class: "yi-upload" }]]
|
|
24060
24209
|
], [
|
|
24061
24210
|
"span",
|
|
24062
24211
|
{ i18n: "import" },
|
|
@@ -24321,10 +24470,12 @@ function run_next_write(gobj) {
|
|
|
24321
24470
|
let priv = gobj.priv;
|
|
24322
24471
|
if (priv.save_queue.length === 0) return end_writes(gobj, "");
|
|
24323
24472
|
let write = priv.save_queue[0];
|
|
24324
|
-
|
|
24473
|
+
let command = write_command(write.op);
|
|
24474
|
+
let options = write_options(write.op);
|
|
24475
|
+
if (remote_command(gobj, command, {
|
|
24325
24476
|
topic_name: write.topic_name,
|
|
24326
24477
|
record: write.record,
|
|
24327
|
-
options
|
|
24478
|
+
options,
|
|
24328
24479
|
record_id: write.record.id || ""
|
|
24329
24480
|
}) < 0) return end_writes(gobj, t("cannot reach the treedb"));
|
|
24330
24481
|
return 0;
|
|
@@ -24379,7 +24530,8 @@ function column_record(gobj, topic, col, values) {
|
|
|
24379
24530
|
record.header = values.header || "";
|
|
24380
24531
|
record.type = values.type || "string";
|
|
24381
24532
|
record.flag = flags;
|
|
24382
|
-
|
|
24533
|
+
if (String(values.fillspace).trim() !== "") record.fillspace = Number(values.fillspace);
|
|
24534
|
+
else if (!creating) record.fillspace = "";
|
|
24383
24535
|
record.placeholder = values.placeholder || "";
|
|
24384
24536
|
record.description = values.description || "";
|
|
24385
24537
|
record.default = values.default || "";
|
|
@@ -24477,7 +24629,7 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
24477
24629
|
let __command__ = msg_iev_get_stack(gobj, kw, "command_stack", true);
|
|
24478
24630
|
let command = kw_get_str(gobj, __command__, "command", "", 0);
|
|
24479
24631
|
let kw_command = kw_get_dict(gobj, __command__, "kw", {}, 0);
|
|
24480
|
-
let md =
|
|
24632
|
+
let md = is_object(kw_command.__md_command__) ? kw_command.__md_command__ : kw_command;
|
|
24481
24633
|
if (kw_get_str(gobj, md, "purpose", "", 0) !== PURPOSE) return 0;
|
|
24482
24634
|
if (command === "nodes") {
|
|
24483
24635
|
let topic_name = kw_get_str(gobj, md, "topic_name", "", 0);
|
|
@@ -24494,11 +24646,11 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
24494
24646
|
build_model(gobj);
|
|
24495
24647
|
return go(gobj, priv.treedb_id, priv.topic_name, priv.diagram, false);
|
|
24496
24648
|
}
|
|
24497
|
-
if (command === "
|
|
24498
|
-
let topic_name = kw_get_str(gobj,
|
|
24649
|
+
if (command === "update-node" || command === "delete-node") {
|
|
24650
|
+
let topic_name = kw_get_str(gobj, md, "topic_name", "", 0);
|
|
24499
24651
|
if (result < 0) return end_writes(gobj, comment || t("the treedb refused the write"));
|
|
24500
24652
|
priv.save_wrote = true;
|
|
24501
|
-
if (command === "delete-node") forget_record(gobj, topic_name, kw_get_str(gobj,
|
|
24653
|
+
if (command === "delete-node") forget_record(gobj, topic_name, kw_get_str(gobj, md, "record_id", "", 0));
|
|
24502
24654
|
else {
|
|
24503
24655
|
let record = is_object(data) ? data : Array.isArray(data) && is_object(data[0]) ? data[0] : null;
|
|
24504
24656
|
if (record) patch_record(gobj, topic_name, record);
|
|
@@ -24509,7 +24661,10 @@ function ac_mt_command_answer(gobj, event, kw, src) {
|
|
|
24509
24661
|
return 0;
|
|
24510
24662
|
}
|
|
24511
24663
|
}
|
|
24512
|
-
if (topic_name === T_TOPICS || topic_name === T_COLS)
|
|
24664
|
+
if (topic_name === T_TOPICS || topic_name === T_COLS) {
|
|
24665
|
+
let write = priv.save_queue[0];
|
|
24666
|
+
mark_written(gobj, topic_name, write ? write.record : null);
|
|
24667
|
+
}
|
|
24513
24668
|
priv.save_queue.shift();
|
|
24514
24669
|
return run_next_write(gobj);
|
|
24515
24670
|
}
|
|
@@ -24902,7 +25057,7 @@ function ac_preview_import(gobj, event, kw, src) {
|
|
|
24902
25057
|
writes: [],
|
|
24903
25058
|
summary: {},
|
|
24904
25059
|
conflicts: [{
|
|
24905
|
-
code: "that is not
|
|
25060
|
+
code: "that is not json",
|
|
24906
25061
|
topic: "",
|
|
24907
25062
|
col: ""
|
|
24908
25063
|
}]
|