@yuneta/gobj-ui 7.23.185 → 7.23.187
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/dist/gobj-ui.cjs.js +201 -43
- package/dist/gobj-ui.es.js +202 -44
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +105 -39
- package/src/c_yui_schema_editor.js +3 -1
- package/src/c_yui_treedb_topics.js +81 -11
- package/src/graph_save_plan.js +108 -0
- package/src/graph_save_plan.test.js +146 -0
- package/src/yui_icons.css +9 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -23714,7 +23714,7 @@ function build_ui$6(gobj) {
|
|
|
23714
23714
|
[[
|
|
23715
23715
|
"span",
|
|
23716
23716
|
{ class: "icon" },
|
|
23717
|
-
[yui_toolbar_icon("yi-
|
|
23717
|
+
[yui_toolbar_icon("yi-compass-drafting")]
|
|
23718
23718
|
], [
|
|
23719
23719
|
"span",
|
|
23720
23720
|
{ i18n: "schema" },
|
|
@@ -23725,6 +23725,29 @@ function build_ui$6(gobj) {
|
|
|
23725
23725
|
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_LANDING_VIEW", {}, gobj);
|
|
23726
23726
|
} }
|
|
23727
23727
|
],
|
|
23728
|
+
[
|
|
23729
|
+
"button",
|
|
23730
|
+
{
|
|
23731
|
+
class: "button TREEDB_SCHEMA_JSON_BTN is-hidden",
|
|
23732
|
+
title: (0, i18next.t)("schema json"),
|
|
23733
|
+
"aria-label": (0, i18next.t)("schema json"),
|
|
23734
|
+
"data-i18n-title": "schema json",
|
|
23735
|
+
"data-i18n-aria-label": "schema json"
|
|
23736
|
+
},
|
|
23737
|
+
[[
|
|
23738
|
+
"span",
|
|
23739
|
+
{ class: "icon" },
|
|
23740
|
+
[yui_toolbar_icon("yi-code")]
|
|
23741
|
+
], [
|
|
23742
|
+
"span",
|
|
23743
|
+
{ i18n: "schema json" },
|
|
23744
|
+
"schema json"
|
|
23745
|
+
]],
|
|
23746
|
+
{ click: (evt) => {
|
|
23747
|
+
evt.stopPropagation();
|
|
23748
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_OPEN_SCHEMA_JSON", {}, gobj);
|
|
23749
|
+
} }
|
|
23750
|
+
],
|
|
23728
23751
|
[
|
|
23729
23752
|
"div",
|
|
23730
23753
|
{
|
|
@@ -24168,6 +24191,7 @@ function show_topics_landing(gobj) {
|
|
|
24168
24191
|
let $info = $container.querySelector(".TREEDB_TOPIC_INFO");
|
|
24169
24192
|
let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
|
|
24170
24193
|
let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
|
|
24194
|
+
let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
|
|
24171
24195
|
if ($tabs) $tabs.classList.add("is-hidden");
|
|
24172
24196
|
if ($sub) $sub.classList.add("is-hidden");
|
|
24173
24197
|
if ($info) $info.classList.add("is-hidden");
|
|
@@ -24177,6 +24201,7 @@ function show_topics_landing(gobj) {
|
|
|
24177
24201
|
$toggle.classList.remove("is-hidden");
|
|
24178
24202
|
$toggle.classList.toggle("is-primary", schema_mode);
|
|
24179
24203
|
}
|
|
24204
|
+
if ($schema_json) $schema_json.classList.toggle("is-hidden", !schema_mode);
|
|
24180
24205
|
if (schema_mode) {
|
|
24181
24206
|
if ($landing) $landing.classList.add("is-hidden");
|
|
24182
24207
|
if ($schema) $schema.classList.remove("is-hidden");
|
|
@@ -24246,9 +24271,11 @@ function show_topic_detail(gobj) {
|
|
|
24246
24271
|
let $info = $container.querySelector(".TREEDB_TOPIC_INFO");
|
|
24247
24272
|
let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
|
|
24248
24273
|
let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
|
|
24274
|
+
let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
|
|
24249
24275
|
if ($landing) $landing.classList.add("is-hidden");
|
|
24250
24276
|
if ($schema) $schema.classList.add("is-hidden");
|
|
24251
24277
|
if ($info) $info.classList.add("is-hidden");
|
|
24278
|
+
if ($schema_json) $schema_json.classList.add("is-hidden");
|
|
24252
24279
|
if ($toggle) $toggle.classList.add("is-hidden");
|
|
24253
24280
|
if ($tabs) $tabs.classList.remove("is-hidden");
|
|
24254
24281
|
if ($sub) $sub.classList.remove("is-hidden");
|
|
@@ -24289,8 +24316,10 @@ function show_topic_info(gobj, topic) {
|
|
|
24289
24316
|
let $schema = $container.querySelector(".TREEDB_TOPICS_SCHEMA");
|
|
24290
24317
|
let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
|
|
24291
24318
|
let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
|
|
24319
|
+
let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
|
|
24292
24320
|
if ($landing) $landing.classList.add("is-hidden");
|
|
24293
24321
|
if ($schema) $schema.classList.add("is-hidden");
|
|
24322
|
+
if ($schema_json) $schema_json.classList.add("is-hidden");
|
|
24294
24323
|
if ($toggle) $toggle.classList.add("is-hidden");
|
|
24295
24324
|
if ($tabs) $tabs.classList.add("is-hidden");
|
|
24296
24325
|
if ($sub) $sub.classList.add("is-hidden");
|
|
@@ -24565,7 +24594,7 @@ function register_sub_routes$1(gobj) {
|
|
|
24565
24594
|
if ((0, _yuneta_gobj_js.is_object)((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "landing_routes"))) nodes.push({
|
|
24566
24595
|
route: base + "/schema",
|
|
24567
24596
|
label: "schema",
|
|
24568
|
-
icon: "yi-
|
|
24597
|
+
icon: "yi-compass-drafting",
|
|
24569
24598
|
gclass: "C_YUI_TREEDB_SCHEMA"
|
|
24570
24599
|
});
|
|
24571
24600
|
if ((0, _yuneta_gobj_js.is_object)(descs)) for (let topic of Object.keys(descs)) {
|
|
@@ -24708,10 +24737,11 @@ function is_mobile$2() {
|
|
|
24708
24737
|
* whole service (lazy drill). CHILD model: the viewer publishes
|
|
24709
24738
|
* EV_EXPAND_PATH to us.
|
|
24710
24739
|
************************************************************/
|
|
24711
|
-
function open_json_viewer$1(gobj) {
|
|
24740
|
+
function open_json_viewer$1(gobj, opts) {
|
|
24712
24741
|
let priv = gobj.priv;
|
|
24742
|
+
let schema = !!(opts && opts.schema);
|
|
24713
24743
|
if (priv.json_win || priv.json_modal) {
|
|
24714
|
-
request_print_tranger$1(gobj, "");
|
|
24744
|
+
if (!schema) request_print_tranger$1(gobj, "");
|
|
24715
24745
|
return;
|
|
24716
24746
|
}
|
|
24717
24747
|
if (!(0, _yuneta_gobj_js.gclass_find_by_name)("C_YUI_JSON")) {
|
|
@@ -24721,7 +24751,10 @@ function open_json_viewer$1(gobj) {
|
|
|
24721
24751
|
}
|
|
24722
24752
|
let mobile = is_mobile$2();
|
|
24723
24753
|
let shell = yui_shell_of(gobj);
|
|
24724
|
-
let jv = (0, _yuneta_gobj_js.gobj_create_service)(`treedb-topics-json-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(gobj))}`, "C_YUI_JSON", {
|
|
24754
|
+
let jv = (0, _yuneta_gobj_js.gobj_create_service)(`treedb-topics-json-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(gobj))}`, "C_YUI_JSON", {
|
|
24755
|
+
subscriber: gobj,
|
|
24756
|
+
json_data: schema ? (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "descs") : null
|
|
24757
|
+
}, gobj);
|
|
24725
24758
|
if (!jv) {
|
|
24726
24759
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot create the JSON viewer`);
|
|
24727
24760
|
return;
|
|
@@ -24739,7 +24772,7 @@ function open_json_viewer$1(gobj) {
|
|
|
24739
24772
|
dialog: true,
|
|
24740
24773
|
logical_class: "TREEDB_JSON_SHEET",
|
|
24741
24774
|
title_prefix: priv.treedb_name,
|
|
24742
|
-
title: "raw json",
|
|
24775
|
+
title: schema ? "schema json" : "raw json",
|
|
24743
24776
|
t: i18next.t,
|
|
24744
24777
|
on_close: () => {
|
|
24745
24778
|
if ((0, _yuneta_gobj_js.gobj_is_destroying)(gobj)) return;
|
|
@@ -24761,8 +24794,8 @@ function open_json_viewer$1(gobj) {
|
|
|
24761
24794
|
height: 620,
|
|
24762
24795
|
logical_class: "TREEDB_JSON_WINDOW",
|
|
24763
24796
|
title_prefix: priv.treedb_name,
|
|
24764
|
-
title: "raw json",
|
|
24765
|
-
icon: "yi-eye",
|
|
24797
|
+
title: schema ? "schema json" : "raw json",
|
|
24798
|
+
icon: schema ? "yi-code" : "yi-eye",
|
|
24766
24799
|
body: $box,
|
|
24767
24800
|
manager: null,
|
|
24768
24801
|
on_close: () => {
|
|
@@ -24777,7 +24810,7 @@ function open_json_viewer$1(gobj) {
|
|
|
24777
24810
|
}
|
|
24778
24811
|
(0, _yuneta_gobj_js.gobj_start)(priv.json_win);
|
|
24779
24812
|
}
|
|
24780
|
-
request_print_tranger$1(gobj, "");
|
|
24813
|
+
if (!schema) request_print_tranger$1(gobj, "");
|
|
24781
24814
|
}
|
|
24782
24815
|
/************************************************************
|
|
24783
24816
|
* Close the JSON viewer (user dismiss / teardown).
|
|
@@ -25371,6 +25404,19 @@ function ac_open_json$1(gobj, event, kw, src) {
|
|
|
25371
25404
|
return 0;
|
|
25372
25405
|
}
|
|
25373
25406
|
/********************************************
|
|
25407
|
+
* The schema, as the json it is: the `descs` the schema graph is
|
|
25408
|
+
* drawing. Same viewer and same host as the tranger's raw json --
|
|
25409
|
+
* one at a time, so it closes whatever was open first.
|
|
25410
|
+
********************************************/
|
|
25411
|
+
function ac_open_schema_json(gobj, event, kw, src) {
|
|
25412
|
+
if (!(0, _yuneta_gobj_js.is_object)((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "descs"))) {
|
|
25413
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: schema json with no descs`);
|
|
25414
|
+
return -1;
|
|
25415
|
+
}
|
|
25416
|
+
open_json_viewer$1(gobj, { schema: true });
|
|
25417
|
+
return 0;
|
|
25418
|
+
}
|
|
25419
|
+
/********************************************
|
|
25374
25420
|
* Open the graph where the reader left it: its last visited
|
|
25375
25421
|
* route under the graph's base -- `<graph>/<topic>` when a topic
|
|
25376
25422
|
* was focused there -- or the bare base when the graph was never
|
|
@@ -25504,6 +25550,11 @@ function create_gclass$6(gclass_name) {
|
|
|
25504
25550
|
ac_open_json$1,
|
|
25505
25551
|
null
|
|
25506
25552
|
],
|
|
25553
|
+
[
|
|
25554
|
+
"EV_OPEN_SCHEMA_JSON",
|
|
25555
|
+
ac_open_schema_json,
|
|
25556
|
+
null
|
|
25557
|
+
],
|
|
25507
25558
|
[
|
|
25508
25559
|
"EV_OPEN_GRAPH",
|
|
25509
25560
|
ac_open_graph,
|
|
@@ -25576,6 +25627,7 @@ function create_gclass$6(gclass_name) {
|
|
|
25576
25627
|
["EV_RECORD_WRITTEN", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT | _yuneta_gobj_js.event_flag_t.EVF_NO_WARN_SUBS],
|
|
25577
25628
|
["EV_REFRESH_TOPIC", 0],
|
|
25578
25629
|
["EV_OPEN_JSON", 0],
|
|
25630
|
+
["EV_OPEN_SCHEMA_JSON", 0],
|
|
25579
25631
|
["EV_OPEN_GRAPH", 0],
|
|
25580
25632
|
["EV_EXPAND_PATH", 0],
|
|
25581
25633
|
["EV_JSON_CLOSED", 0],
|
|
@@ -30260,6 +30312,88 @@ function register_c_yui_treedb_topic_with_form() {
|
|
|
30260
30312
|
return create_gclass$5(GCLASS_NAME$5);
|
|
30261
30313
|
}
|
|
30262
30314
|
//#endregion
|
|
30315
|
+
//#region src/graph_save_plan.js
|
|
30316
|
+
/***********************************************************************
|
|
30317
|
+
* graph_save_plan.js
|
|
30318
|
+
*
|
|
30319
|
+
* Which topics a Save of the graph has to write, and which it
|
|
30320
|
+
* must leave alone.
|
|
30321
|
+
*
|
|
30322
|
+
* The arrangement of a treedb graph lives in `__graphs__`, ONE
|
|
30323
|
+
* record per topic. The Save collected every topic the view had
|
|
30324
|
+
* loaded and wrote all of them, whatever had moved: on a treedb
|
|
30325
|
+
* of five topics, dragging one card appended five records, four
|
|
30326
|
+
* of them saying exactly what the record under them said. The
|
|
30327
|
+
* store is append-only, so those four are there for ever.
|
|
30328
|
+
*
|
|
30329
|
+
* This module is the decision, and nothing else: no G6, no DOM,
|
|
30330
|
+
* no gobj. Give it what the view is holding and what the backend
|
|
30331
|
+
* already has, and it answers which topics differ.
|
|
30332
|
+
*
|
|
30333
|
+
* Two things it deliberately does NOT do:
|
|
30334
|
+
*
|
|
30335
|
+
* - It does not ask the history plugin. The Save button lights
|
|
30336
|
+
* from two places -- `history.canUndo()` for what G6 records
|
|
30337
|
+
* (a move, a resize) and `mark_graph_dirty()` for what it does
|
|
30338
|
+
* not (a colour, a pill, a per-topic default) -- so the undo
|
|
30339
|
+
* stack is not the list of what changed, and reading it as one
|
|
30340
|
+
* would silently drop half the changes. A value comparison
|
|
30341
|
+
* sees both, and keeps working through undo, redo and a
|
|
30342
|
+
* history that was just cleared.
|
|
30343
|
+
*
|
|
30344
|
+
* - It does not compare `__origin__`. That key is the node_uuid
|
|
30345
|
+
* of whoever wrote the record, bookkeeping about the write and
|
|
30346
|
+
* not about the arrangement; comparing it would make every
|
|
30347
|
+
* topic differ the first time a second browser saved, and the
|
|
30348
|
+
* record it forces would say nothing new.
|
|
30349
|
+
*
|
|
30350
|
+
* Copyright (c) 2026, ArtGins.
|
|
30351
|
+
* All Rights Reserved.
|
|
30352
|
+
***********************************************************************/
|
|
30353
|
+
/***************************************************************
|
|
30354
|
+
* The properties as they are worth comparing: everything
|
|
30355
|
+
* except who wrote them.
|
|
30356
|
+
***************************************************************/
|
|
30357
|
+
function arrangement_of(properties) {
|
|
30358
|
+
if (!(0, _yuneta_gobj_js.is_object)(properties)) return {};
|
|
30359
|
+
let out = {};
|
|
30360
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
30361
|
+
if (key === "__origin__") continue;
|
|
30362
|
+
out[key] = value;
|
|
30363
|
+
}
|
|
30364
|
+
return out;
|
|
30365
|
+
}
|
|
30366
|
+
/***************************************************************
|
|
30367
|
+
* TRUE when the arrangement the view holds for `topic_name`
|
|
30368
|
+
* is not the one the backend already has.
|
|
30369
|
+
*
|
|
30370
|
+
* A topic with no saved record has never been written, so
|
|
30371
|
+
* anything it holds is a change -- and an EMPTY arrangement
|
|
30372
|
+
* is not: a topic the view loaded and nobody ever arranged
|
|
30373
|
+
* has nothing to say, and saying it would create a record
|
|
30374
|
+
* that means "no layout".
|
|
30375
|
+
***************************************************************/
|
|
30376
|
+
function topic_arrangement_changed(live, saved) {
|
|
30377
|
+
let a = arrangement_of(live);
|
|
30378
|
+
if (!saved) return Object.keys(a).length > 0;
|
|
30379
|
+
return !(0, _yuneta_gobj_js.json_is_identical)(a, arrangement_of(saved));
|
|
30380
|
+
}
|
|
30381
|
+
/***************************************************************
|
|
30382
|
+
* The topics a Save has to write.
|
|
30383
|
+
*
|
|
30384
|
+
* live {topic_name: properties} what the view holds
|
|
30385
|
+
* saved {topic_name: properties} what the backend has
|
|
30386
|
+
*
|
|
30387
|
+
* Returns their names, in the order the view holds them.
|
|
30388
|
+
***************************************************************/
|
|
30389
|
+
function plan_graph_saves(live, saved) {
|
|
30390
|
+
let plan = [];
|
|
30391
|
+
if (!(0, _yuneta_gobj_js.is_object)(live)) return plan;
|
|
30392
|
+
let have = (0, _yuneta_gobj_js.is_object)(saved) ? saved : {};
|
|
30393
|
+
for (const [topic_name, properties] of Object.entries(live)) if (topic_arrangement_changed(properties, have[topic_name])) plan.push(topic_name);
|
|
30394
|
+
return plan;
|
|
30395
|
+
}
|
|
30396
|
+
//#endregion
|
|
30263
30397
|
//#region src/treedb_node_label.js
|
|
30264
30398
|
/***********************************************************************
|
|
30265
30399
|
* treedb_node_label.js
|
|
@@ -58487,6 +58621,7 @@ var PRIVATE_DATA$4 = {
|
|
|
58487
58621
|
graph: null,
|
|
58488
58622
|
__graphs__: [],
|
|
58489
58623
|
_graph_properties: {},
|
|
58624
|
+
_saved_graph_properties: {},
|
|
58490
58625
|
yet_showed: false,
|
|
58491
58626
|
edit_mode: false,
|
|
58492
58627
|
operation_mode: null,
|
|
@@ -58737,7 +58872,7 @@ function build_graph$1(gobj) {
|
|
|
58737
58872
|
container: priv.$container,
|
|
58738
58873
|
animation: false,
|
|
58739
58874
|
autoResize: false,
|
|
58740
|
-
zoomRange: [.
|
|
58875
|
+
zoomRange: [.02, 4],
|
|
58741
58876
|
node: {
|
|
58742
58877
|
palette: {
|
|
58743
58878
|
type: "group",
|
|
@@ -59993,6 +60128,7 @@ function draw_link(gobj, child_topic, child_id, source_col, fkey, verbose) {
|
|
|
59993
60128
|
parent_topic,
|
|
59994
60129
|
parent_id,
|
|
59995
60130
|
hook_name,
|
|
60131
|
+
child_topic,
|
|
59996
60132
|
child_id,
|
|
59997
60133
|
is_tree
|
|
59998
60134
|
});
|
|
@@ -60072,11 +60208,15 @@ function clear_link(gobj, child_topic, child_id, source_col, fkey, verbose) {
|
|
|
60072
60208
|
function build_graph_properties(gobj) {
|
|
60073
60209
|
let priv = gobj.priv;
|
|
60074
60210
|
priv._graph_properties = {};
|
|
60211
|
+
priv._saved_graph_properties = {};
|
|
60075
60212
|
for (let i = 0; i < priv.__graphs__.length; i++) {
|
|
60076
60213
|
let rec = priv.__graphs__[i];
|
|
60077
60214
|
if (!rec.active || !rec.topic) continue;
|
|
60078
60215
|
let props = rec.properties;
|
|
60079
|
-
if ((0, _yuneta_gobj_js.is_object)(props))
|
|
60216
|
+
if ((0, _yuneta_gobj_js.is_object)(props)) {
|
|
60217
|
+
priv._graph_properties[rec.topic] = props;
|
|
60218
|
+
priv._saved_graph_properties[rec.topic] = (0, _yuneta_gobj_js.json_deep_copy)(props);
|
|
60219
|
+
}
|
|
60080
60220
|
}
|
|
60081
60221
|
}
|
|
60082
60222
|
/************************************************************
|
|
@@ -60161,35 +60301,22 @@ function save_geometry(gobj) {
|
|
|
60161
60301
|
}
|
|
60162
60302
|
const edges = graph.getData().edges;
|
|
60163
60303
|
for (let i = 0; i < edges.length; i++) update_edge_geometry(gobj, edges[i].id);
|
|
60164
|
-
let
|
|
60165
|
-
for (
|
|
60166
|
-
properties.__origin__ = origin;
|
|
60167
|
-
let kw_update = {
|
|
60168
|
-
treedb_name: priv.treedb_name,
|
|
60169
|
-
topic_name: "__graphs__",
|
|
60170
|
-
record: {
|
|
60171
|
-
id: topic_name,
|
|
60172
|
-
topic: topic_name,
|
|
60173
|
-
active: true,
|
|
60174
|
-
properties
|
|
60175
|
-
},
|
|
60176
|
-
options: {
|
|
60177
|
-
list_dict: true,
|
|
60178
|
-
autolink: false,
|
|
60179
|
-
create: true
|
|
60180
|
-
}
|
|
60181
|
-
};
|
|
60182
|
-
(0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_UPDATE_NODE", kw_update);
|
|
60183
|
-
}
|
|
60304
|
+
let plan = plan_graph_saves(priv._graph_properties, priv._saved_graph_properties);
|
|
60305
|
+
for (let i = 0; i < plan.length; i++) save_topic_graph_properties(gobj, plan[i]);
|
|
60184
60306
|
}
|
|
60185
60307
|
/************************************************************
|
|
60186
60308
|
* Save __graphs__ properties for a single topic to backend.
|
|
60309
|
+
*
|
|
60310
|
+
* The ONE door to `__graphs__`: a caller that knows a topic moved
|
|
60311
|
+
* says so, and this decides whether the backend needs telling.
|
|
60187
60312
|
************************************************************/
|
|
60188
60313
|
function save_topic_graph_properties(gobj, topic_name) {
|
|
60189
60314
|
let priv = gobj.priv;
|
|
60190
60315
|
let properties = priv._graph_properties[topic_name];
|
|
60191
60316
|
if (!properties) return;
|
|
60317
|
+
if (!topic_arrangement_changed(properties, priv._saved_graph_properties[topic_name])) return;
|
|
60192
60318
|
properties.__origin__ = (0, _yuneta_gobj_js.gobj_read_str_attr)((0, _yuneta_gobj_js.gobj_yuno)(), "node_uuid");
|
|
60319
|
+
priv._saved_graph_properties[topic_name] = (0, _yuneta_gobj_js.json_deep_copy)(properties);
|
|
60193
60320
|
let kw_update = {
|
|
60194
60321
|
treedb_name: priv.treedb_name,
|
|
60195
60322
|
topic_name: "__graphs__",
|
|
@@ -60508,7 +60635,7 @@ async function graph_fit_selection(gobj, ids) {
|
|
|
60508
60635
|
let bw = Math.max(1, maxx - minx);
|
|
60509
60636
|
let bh = Math.max(1, maxy - miny);
|
|
60510
60637
|
let zoom = Math.min(vw / bw, vh / bh);
|
|
60511
|
-
let range = graph.getZoomRange() || [.
|
|
60638
|
+
let range = graph.getZoomRange() || [.02, 4];
|
|
60512
60639
|
zoom = Math.max(range[0], Math.min(range[1], zoom));
|
|
60513
60640
|
await graph.zoomTo(zoom);
|
|
60514
60641
|
await graph.focusElement(ids);
|
|
@@ -63245,16 +63372,14 @@ function refresh_html_nodes_theme(gobj, theme) {
|
|
|
63245
63372
|
function refresh_default_edges_theme(gobj, theme) {
|
|
63246
63373
|
let graph = gobj.priv.graph;
|
|
63247
63374
|
if (!graph) return;
|
|
63248
|
-
let dark = theme === "dark";
|
|
63249
63375
|
let edges = graph.getData().edges || [];
|
|
63250
63376
|
let updates = [];
|
|
63251
63377
|
for (let i = 0; i < edges.length; i++) {
|
|
63252
63378
|
let d = edges[i].data || {};
|
|
63253
63379
|
if (!d.themed_default) continue;
|
|
63254
|
-
let stroke = d.is_tree ? dark ? "#22a7c2" : "#0e7490" : dark ? "#8b94a3" : "#6b7280";
|
|
63255
63380
|
updates.push({
|
|
63256
63381
|
id: edges[i].id,
|
|
63257
|
-
style: { stroke }
|
|
63382
|
+
style: { stroke: default_edge_stroke(gobj, d, theme) }
|
|
63258
63383
|
});
|
|
63259
63384
|
}
|
|
63260
63385
|
if (updates.length > 0) graph.updateEdgeData(updates);
|
|
@@ -63826,21 +63951,54 @@ function apply_edge_properties(gobj, edge_id, lineWidth, stroke, scope) {
|
|
|
63826
63951
|
deselect_edge(gobj);
|
|
63827
63952
|
}
|
|
63828
63953
|
/************************************************************
|
|
63954
|
+
* The colour a link is DRAWN in: the colour of the two knobs it
|
|
63955
|
+
* joins.
|
|
63956
|
+
*
|
|
63957
|
+
* Both ends of a link wear the CHILD topic's colour -- the
|
|
63958
|
+
* parent's hook port is painted with the colour of whatever may
|
|
63959
|
+
* hang there, and the child's fkey port with its own (see
|
|
63960
|
+
* build_ports) -- so the line between them has one obvious
|
|
63961
|
+
* colour, and a reader follows a link by its hue instead of
|
|
63962
|
+
* tracing a grey thread across the canvas.
|
|
63963
|
+
*
|
|
63964
|
+
* It goes through port_rim(): the FILL of a port says which
|
|
63965
|
+
* topic, and a line on the canvas is a graphical object that
|
|
63966
|
+
* needs 3:1 against it, which that mix clears in both themes
|
|
63967
|
+
* (9.11 dark, 3.80 light) while keeping the hue. So a link is
|
|
63968
|
+
* drawn in exactly the colour of the rim of the two knobs it
|
|
63969
|
+
* ends on.
|
|
63970
|
+
*
|
|
63971
|
+
* The containment/tree relation (parent and child of the same
|
|
63972
|
+
* topic) is no longer marked by a teal of its own -- it is that
|
|
63973
|
+
* topic's colour like any other link, and what still tells it
|
|
63974
|
+
* apart is its WIDTH.
|
|
63975
|
+
*
|
|
63976
|
+
* A topic with no colour, or an edge of a graph with no schema
|
|
63977
|
+
* yet, keeps the neutral grey this used to give everything.
|
|
63978
|
+
************************************************************/
|
|
63979
|
+
function default_edge_stroke(gobj, d, theme) {
|
|
63980
|
+
let priv = gobj.priv;
|
|
63981
|
+
let desc = (0, _yuneta_gobj_js.is_object)(priv.descs) ? priv.descs[d.child_topic] : null;
|
|
63982
|
+
if (desc && desc.color) return port_rim(desc.color, theme);
|
|
63983
|
+
let dark = theme === "dark";
|
|
63984
|
+
return d.is_tree ? dark ? "#22a7c2" : "#0e7490" : dark ? "#8b94a3" : "#6b7280";
|
|
63985
|
+
}
|
|
63986
|
+
/************************************************************
|
|
63829
63987
|
* The style an edge INHERITS, before anything saved for the
|
|
63830
63988
|
* edge itself: its hook's default in the parent topic, else the
|
|
63831
63989
|
* parent topic's default for every edge, else the library's.
|
|
63832
63990
|
*
|
|
63833
|
-
* The library's:
|
|
63834
|
-
*
|
|
63835
|
-
*
|
|
63836
|
-
* library's, so a theme toggle re-themes it and leaves
|
|
63837
|
-
* one alone.
|
|
63991
|
+
* The library's: the colour of the ports it joins (see
|
|
63992
|
+
* default_edge_stroke), and a wider line for the
|
|
63993
|
+
* containment/tree relation. `themed_default` says the colour is
|
|
63994
|
+
* still the library's, so a theme toggle re-themes it and leaves
|
|
63995
|
+
* a chosen one alone.
|
|
63838
63996
|
************************************************************/
|
|
63839
63997
|
function edge_inherited_style_of(gobj, d) {
|
|
63840
|
-
let
|
|
63998
|
+
let priv = gobj.priv;
|
|
63841
63999
|
let style = {
|
|
63842
64000
|
lineWidth: d.is_tree ? 2 : 1.6,
|
|
63843
|
-
stroke: d.
|
|
64001
|
+
stroke: default_edge_stroke(gobj, d, priv.theme),
|
|
63844
64002
|
themed_default: true
|
|
63845
64003
|
};
|
|
63846
64004
|
let defs = topic_defaults_of(gobj, d.parent_topic);
|
|
@@ -71661,7 +71819,7 @@ function render_toolbar(gobj) {
|
|
|
71661
71819
|
]);
|
|
71662
71820
|
let $right = [];
|
|
71663
71821
|
if (priv.treedb_id && has_model) {
|
|
71664
|
-
$right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-
|
|
71822
|
+
$right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-compass-drafting", priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
|
|
71665
71823
|
$right.push(toolbar_button("SCHEMA_VALIDATE_BTN", "yi-square-check", "check", "EV_VALIDATE", false));
|
|
71666
71824
|
$right.push(toolbar_button("SCHEMA_EXPORT_BTN", "yi-download", "export", "EV_EXPORT", false));
|
|
71667
71825
|
if (!readonly) $right.push(toolbar_button("SCHEMA_IMPORT_BTN", "yi-upload", "import", "EV_IMPORT", false));
|