@yuneta/gobj-ui 7.23.138 → 7.23.139
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 +109 -16
- package/dist/gobj-ui.es.js +109 -16
- package/package.json +1 -1
- package/src/c_yui_treedb_topics.css +25 -0
- package/src/c_yui_treedb_topics.js +82 -10
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -21798,7 +21798,7 @@ var attrs_table$6 = [
|
|
|
21798
21798
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "tabs_style", 0, "is-toggle is-fullwidth", "Bulma tab styling"),
|
|
21799
21799
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "with_cards_landing", 0, false, "Land on a grid of topic cards (list->detail): a card opens its table, with the tabs bar + a back-to-grid button. Off = tabs only (legacy)."),
|
|
21800
21800
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "readonly", 0, false, "The whole treedb is read-only: every topic opens without its write affordances and the write events are refused. Set it when this yuno is not the MASTER of the treedb's tranger -- only the master can write, and the yuno answers 'READ-ONLY' to a write since SDK 7.13.0 (ask `treedb-info`)"),
|
|
21801
|
-
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "card_action_routes", 0, null, "
|
|
21801
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "card_action_routes", 0, null, "Hash-route templates {info, table, graph} with a {topic} placeholder (host-supplied, route-agnostic). Present ⇒ cards show the info and table icons, and `graph` without its `/{topic}` is the toolbar's graph button (the card has no graph icon: its topic segment is a focus); absent ⇒ a single card that opens the table."),
|
|
21802
21802
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "landing_routes", 0, null, "Host-supplied hashes for the two landing sub-views {cards, schema}; the toggle navigates to them so the landing is URL-addressable (ROUTING.md). Absent ⇒ toggle flips in-view only (legacy)."),
|
|
21803
21803
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "base_route", 0, "", "This view's base route (host-supplied); used to declare its sub-routes (topics / info / schema) to the site map (ROUTING.md contributor)."),
|
|
21804
21804
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "source_url", 0, "", "The backend this view browses (host-supplied, typically the wss url of the connection), shown in the toolbar. A tab label names the TREEDB, and the same treedb name lives on more than one node, so the node has to be readable somewhere -- and a tab is too narrow to carry a url. Empty ⇒ nothing is shown."),
|
|
@@ -22221,13 +22221,103 @@ function card_action_anchor(logical_class, icon, i18n_key, href) {
|
|
|
22221
22221
|
];
|
|
22222
22222
|
}
|
|
22223
22223
|
/************************************************************
|
|
22224
|
+
* What a topic card says about its topic, from its desc alone
|
|
22225
|
+
* (no request): its version and how many columns it has, the
|
|
22226
|
+
* topics it hangs FROM (its fkeys) and the ones that hang from
|
|
22227
|
+
* it (its hooks). The names are DATA and are not translated;
|
|
22228
|
+
* each label carries its key. Lists are cut with an ellipsis,
|
|
22229
|
+
* whole in the title.
|
|
22230
|
+
************************************************************/
|
|
22231
|
+
function topic_card_meta(desc) {
|
|
22232
|
+
if (!(0, _yuneta_gobj_js.is_object)(desc)) return [];
|
|
22233
|
+
let cols = (0, _yuneta_gobj_js.is_array)(desc.cols) ? desc.cols : [];
|
|
22234
|
+
let n_cols = 0;
|
|
22235
|
+
let parents = [];
|
|
22236
|
+
let children = [];
|
|
22237
|
+
for (let col of cols) {
|
|
22238
|
+
if (!col || !col.id || col.id.charAt(0) === "_") continue;
|
|
22239
|
+
n_cols++;
|
|
22240
|
+
if ((0, _yuneta_gobj_js.is_object)(col.fkey)) {
|
|
22241
|
+
for (let t_name of Object.keys(col.fkey)) if (!parents.includes(t_name)) parents.push(t_name);
|
|
22242
|
+
}
|
|
22243
|
+
if ((0, _yuneta_gobj_js.is_object)(col.hook)) {
|
|
22244
|
+
for (let t_name of Object.keys(col.hook)) if (!children.includes(t_name)) children.push(t_name);
|
|
22245
|
+
}
|
|
22246
|
+
}
|
|
22247
|
+
let meta = [];
|
|
22248
|
+
let head = [];
|
|
22249
|
+
if (desc.topic_version !== void 0 && desc.topic_version !== null && desc.topic_version !== "") head.push([
|
|
22250
|
+
"span",
|
|
22251
|
+
{
|
|
22252
|
+
class: "TREEDB_TOPIC_CARD_VERSION",
|
|
22253
|
+
title: (0, i18next.t)("version"),
|
|
22254
|
+
"data-i18n-title": "version"
|
|
22255
|
+
},
|
|
22256
|
+
`v${desc.topic_version}`
|
|
22257
|
+
]);
|
|
22258
|
+
head.push([
|
|
22259
|
+
"span",
|
|
22260
|
+
{ class: "TREEDB_TOPIC_CARD_COLS" },
|
|
22261
|
+
[[
|
|
22262
|
+
"span",
|
|
22263
|
+
{},
|
|
22264
|
+
`${n_cols}`
|
|
22265
|
+
], [
|
|
22266
|
+
"span",
|
|
22267
|
+
{ i18n: "columns" },
|
|
22268
|
+
"columns"
|
|
22269
|
+
]]
|
|
22270
|
+
]);
|
|
22271
|
+
meta.push([
|
|
22272
|
+
"div",
|
|
22273
|
+
{ class: "TREEDB_TOPIC_CARD_META" },
|
|
22274
|
+
head
|
|
22275
|
+
]);
|
|
22276
|
+
let relation = (cls, key, arrow, names) => {
|
|
22277
|
+
let list = names.join(", ");
|
|
22278
|
+
return [
|
|
22279
|
+
"div",
|
|
22280
|
+
{
|
|
22281
|
+
class: `TREEDB_TOPIC_CARD_REL ${cls}`,
|
|
22282
|
+
title: list
|
|
22283
|
+
},
|
|
22284
|
+
[
|
|
22285
|
+
[
|
|
22286
|
+
"span",
|
|
22287
|
+
{
|
|
22288
|
+
class: "TREEDB_TOPIC_CARD_REL_ARROW",
|
|
22289
|
+
"aria-hidden": "true"
|
|
22290
|
+
},
|
|
22291
|
+
arrow
|
|
22292
|
+
],
|
|
22293
|
+
[
|
|
22294
|
+
"span",
|
|
22295
|
+
{
|
|
22296
|
+
class: "TREEDB_TOPIC_CARD_REL_LABEL",
|
|
22297
|
+
i18n: key
|
|
22298
|
+
},
|
|
22299
|
+
key
|
|
22300
|
+
],
|
|
22301
|
+
[
|
|
22302
|
+
"span",
|
|
22303
|
+
{ class: "TREEDB_TOPIC_CARD_REL_LIST" },
|
|
22304
|
+
list
|
|
22305
|
+
]
|
|
22306
|
+
]
|
|
22307
|
+
];
|
|
22308
|
+
};
|
|
22309
|
+
if (parents.length) meta.push(relation("TREEDB_TOPIC_CARD_PARENTS", "parents", "↑", parents));
|
|
22310
|
+
if (children.length) meta.push(relation("TREEDB_TOPIC_CARD_CHILDREN", "children", "↓", children));
|
|
22311
|
+
return meta;
|
|
22312
|
+
}
|
|
22313
|
+
/************************************************************
|
|
22224
22314
|
* Add one topic card to the cards-landing grid (list->detail).
|
|
22225
22315
|
* With `card_action_routes` (host-supplied templates) the card
|
|
22226
22316
|
* shows three hash-routed icons — info / table / graph. Without,
|
|
22227
22317
|
* it falls back to a single card that opens the table (same id
|
|
22228
22318
|
* contract as the tab, `<gobj>?<topic>`).
|
|
22229
22319
|
************************************************************/
|
|
22230
|
-
function add_topic_card(gobj, id, text, icon) {
|
|
22320
|
+
function add_topic_card(gobj, id, text, icon, desc) {
|
|
22231
22321
|
let $grid = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container").querySelector(".TREEDB_TOPICS_LANDING .yui-nav-cards");
|
|
22232
22322
|
if (!$grid) return;
|
|
22233
22323
|
let routes = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "card_action_routes");
|
|
@@ -22270,25 +22360,28 @@ function add_topic_card(gobj, id, text, icon) {
|
|
|
22270
22360
|
let actions = [];
|
|
22271
22361
|
if (routes.info) actions.push(card_action_anchor("TREEDB_CARD_INFO", "yi-circle-info", "info", fill(routes.info)));
|
|
22272
22362
|
if (routes.table) actions.push(card_action_anchor("TREEDB_CARD_TABLE", "yi-table", "table", fill(routes.table)));
|
|
22273
|
-
if (routes.graph) actions.push(card_action_anchor("TREEDB_CARD_GRAPH", "yi-hexagon-nodes", "graph", fill(routes.graph)));
|
|
22274
22363
|
let $card = (0, _yuneta_gobj_js.createElement2)([
|
|
22275
22364
|
"div",
|
|
22276
22365
|
{
|
|
22277
22366
|
class: "TREEDB_TOPIC_CARD",
|
|
22278
22367
|
"data-topic": topic
|
|
22279
22368
|
},
|
|
22280
|
-
[
|
|
22281
|
-
|
|
22282
|
-
|
|
22283
|
-
|
|
22284
|
-
|
|
22285
|
-
|
|
22286
|
-
|
|
22287
|
-
|
|
22288
|
-
|
|
22289
|
-
|
|
22290
|
-
|
|
22291
|
-
|
|
22369
|
+
[
|
|
22370
|
+
[
|
|
22371
|
+
"span",
|
|
22372
|
+
{
|
|
22373
|
+
class: "TREEDB_TOPIC_CARD_NAME",
|
|
22374
|
+
i18n: text
|
|
22375
|
+
},
|
|
22376
|
+
text
|
|
22377
|
+
],
|
|
22378
|
+
...topic_card_meta(desc),
|
|
22379
|
+
[
|
|
22380
|
+
"div",
|
|
22381
|
+
{ class: "TREEDB_TOPIC_CARD_ACTIONS" },
|
|
22382
|
+
actions
|
|
22383
|
+
]
|
|
22384
|
+
]
|
|
22292
22385
|
]);
|
|
22293
22386
|
if (gobj.priv._selected_card_topic === topic) $card.classList.add("is-selected");
|
|
22294
22387
|
$card.addEventListener("click", function() {
|
|
@@ -22641,7 +22734,7 @@ function process_treedb_descs$1(gobj) {
|
|
|
22641
22734
|
let id = `${(0, _yuneta_gobj_js.gobj_name)(gobj)}?${desc.topic_name}`;
|
|
22642
22735
|
let gobj_topic_form = (0, _yuneta_gobj_js.gobj_create_service)(id, "C_YUI_TREEDB_TOPIC_WITH_FORM", kw_topic_form, gobj);
|
|
22643
22736
|
add_tab(gobj, gobj_topic_form, id, key, "yi-table");
|
|
22644
|
-
add_topic_card(gobj, id, key, "yi-table");
|
|
22737
|
+
add_topic_card(gobj, id, key, "yi-table", desc);
|
|
22645
22738
|
(0, _yuneta_gobj_js.gobj_start)(gobj_topic_form);
|
|
22646
22739
|
}
|
|
22647
22740
|
let href = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "last_selection");
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -21793,7 +21793,7 @@ var attrs_table$6 = [
|
|
|
21793
21793
|
SDATA(data_type_t.DTP_STRING, "tabs_style", 0, "is-toggle is-fullwidth", "Bulma tab styling"),
|
|
21794
21794
|
SDATA(data_type_t.DTP_BOOLEAN, "with_cards_landing", 0, false, "Land on a grid of topic cards (list->detail): a card opens its table, with the tabs bar + a back-to-grid button. Off = tabs only (legacy)."),
|
|
21795
21795
|
SDATA(data_type_t.DTP_BOOLEAN, "readonly", 0, false, "The whole treedb is read-only: every topic opens without its write affordances and the write events are refused. Set it when this yuno is not the MASTER of the treedb's tranger -- only the master can write, and the yuno answers 'READ-ONLY' to a write since SDK 7.13.0 (ask `treedb-info`)"),
|
|
21796
|
-
SDATA(data_type_t.DTP_JSON, "card_action_routes", 0, null, "
|
|
21796
|
+
SDATA(data_type_t.DTP_JSON, "card_action_routes", 0, null, "Hash-route templates {info, table, graph} with a {topic} placeholder (host-supplied, route-agnostic). Present ⇒ cards show the info and table icons, and `graph` without its `/{topic}` is the toolbar's graph button (the card has no graph icon: its topic segment is a focus); absent ⇒ a single card that opens the table."),
|
|
21797
21797
|
SDATA(data_type_t.DTP_JSON, "landing_routes", 0, null, "Host-supplied hashes for the two landing sub-views {cards, schema}; the toggle navigates to them so the landing is URL-addressable (ROUTING.md). Absent ⇒ toggle flips in-view only (legacy)."),
|
|
21798
21798
|
SDATA(data_type_t.DTP_STRING, "base_route", 0, "", "This view's base route (host-supplied); used to declare its sub-routes (topics / info / schema) to the site map (ROUTING.md contributor)."),
|
|
21799
21799
|
SDATA(data_type_t.DTP_STRING, "source_url", 0, "", "The backend this view browses (host-supplied, typically the wss url of the connection), shown in the toolbar. A tab label names the TREEDB, and the same treedb name lives on more than one node, so the node has to be readable somewhere -- and a tab is too narrow to carry a url. Empty ⇒ nothing is shown."),
|
|
@@ -22216,13 +22216,103 @@ function card_action_anchor(logical_class, icon, i18n_key, href) {
|
|
|
22216
22216
|
];
|
|
22217
22217
|
}
|
|
22218
22218
|
/************************************************************
|
|
22219
|
+
* What a topic card says about its topic, from its desc alone
|
|
22220
|
+
* (no request): its version and how many columns it has, the
|
|
22221
|
+
* topics it hangs FROM (its fkeys) and the ones that hang from
|
|
22222
|
+
* it (its hooks). The names are DATA and are not translated;
|
|
22223
|
+
* each label carries its key. Lists are cut with an ellipsis,
|
|
22224
|
+
* whole in the title.
|
|
22225
|
+
************************************************************/
|
|
22226
|
+
function topic_card_meta(desc) {
|
|
22227
|
+
if (!is_object(desc)) return [];
|
|
22228
|
+
let cols = is_array(desc.cols) ? desc.cols : [];
|
|
22229
|
+
let n_cols = 0;
|
|
22230
|
+
let parents = [];
|
|
22231
|
+
let children = [];
|
|
22232
|
+
for (let col of cols) {
|
|
22233
|
+
if (!col || !col.id || col.id.charAt(0) === "_") continue;
|
|
22234
|
+
n_cols++;
|
|
22235
|
+
if (is_object(col.fkey)) {
|
|
22236
|
+
for (let t_name of Object.keys(col.fkey)) if (!parents.includes(t_name)) parents.push(t_name);
|
|
22237
|
+
}
|
|
22238
|
+
if (is_object(col.hook)) {
|
|
22239
|
+
for (let t_name of Object.keys(col.hook)) if (!children.includes(t_name)) children.push(t_name);
|
|
22240
|
+
}
|
|
22241
|
+
}
|
|
22242
|
+
let meta = [];
|
|
22243
|
+
let head = [];
|
|
22244
|
+
if (desc.topic_version !== void 0 && desc.topic_version !== null && desc.topic_version !== "") head.push([
|
|
22245
|
+
"span",
|
|
22246
|
+
{
|
|
22247
|
+
class: "TREEDB_TOPIC_CARD_VERSION",
|
|
22248
|
+
title: t("version"),
|
|
22249
|
+
"data-i18n-title": "version"
|
|
22250
|
+
},
|
|
22251
|
+
`v${desc.topic_version}`
|
|
22252
|
+
]);
|
|
22253
|
+
head.push([
|
|
22254
|
+
"span",
|
|
22255
|
+
{ class: "TREEDB_TOPIC_CARD_COLS" },
|
|
22256
|
+
[[
|
|
22257
|
+
"span",
|
|
22258
|
+
{},
|
|
22259
|
+
`${n_cols}`
|
|
22260
|
+
], [
|
|
22261
|
+
"span",
|
|
22262
|
+
{ i18n: "columns" },
|
|
22263
|
+
"columns"
|
|
22264
|
+
]]
|
|
22265
|
+
]);
|
|
22266
|
+
meta.push([
|
|
22267
|
+
"div",
|
|
22268
|
+
{ class: "TREEDB_TOPIC_CARD_META" },
|
|
22269
|
+
head
|
|
22270
|
+
]);
|
|
22271
|
+
let relation = (cls, key, arrow, names) => {
|
|
22272
|
+
let list = names.join(", ");
|
|
22273
|
+
return [
|
|
22274
|
+
"div",
|
|
22275
|
+
{
|
|
22276
|
+
class: `TREEDB_TOPIC_CARD_REL ${cls}`,
|
|
22277
|
+
title: list
|
|
22278
|
+
},
|
|
22279
|
+
[
|
|
22280
|
+
[
|
|
22281
|
+
"span",
|
|
22282
|
+
{
|
|
22283
|
+
class: "TREEDB_TOPIC_CARD_REL_ARROW",
|
|
22284
|
+
"aria-hidden": "true"
|
|
22285
|
+
},
|
|
22286
|
+
arrow
|
|
22287
|
+
],
|
|
22288
|
+
[
|
|
22289
|
+
"span",
|
|
22290
|
+
{
|
|
22291
|
+
class: "TREEDB_TOPIC_CARD_REL_LABEL",
|
|
22292
|
+
i18n: key
|
|
22293
|
+
},
|
|
22294
|
+
key
|
|
22295
|
+
],
|
|
22296
|
+
[
|
|
22297
|
+
"span",
|
|
22298
|
+
{ class: "TREEDB_TOPIC_CARD_REL_LIST" },
|
|
22299
|
+
list
|
|
22300
|
+
]
|
|
22301
|
+
]
|
|
22302
|
+
];
|
|
22303
|
+
};
|
|
22304
|
+
if (parents.length) meta.push(relation("TREEDB_TOPIC_CARD_PARENTS", "parents", "↑", parents));
|
|
22305
|
+
if (children.length) meta.push(relation("TREEDB_TOPIC_CARD_CHILDREN", "children", "↓", children));
|
|
22306
|
+
return meta;
|
|
22307
|
+
}
|
|
22308
|
+
/************************************************************
|
|
22219
22309
|
* Add one topic card to the cards-landing grid (list->detail).
|
|
22220
22310
|
* With `card_action_routes` (host-supplied templates) the card
|
|
22221
22311
|
* shows three hash-routed icons — info / table / graph. Without,
|
|
22222
22312
|
* it falls back to a single card that opens the table (same id
|
|
22223
22313
|
* contract as the tab, `<gobj>?<topic>`).
|
|
22224
22314
|
************************************************************/
|
|
22225
|
-
function add_topic_card(gobj, id, text, icon) {
|
|
22315
|
+
function add_topic_card(gobj, id, text, icon, desc) {
|
|
22226
22316
|
let $grid = gobj_read_attr(gobj, "$container").querySelector(".TREEDB_TOPICS_LANDING .yui-nav-cards");
|
|
22227
22317
|
if (!$grid) return;
|
|
22228
22318
|
let routes = gobj_read_attr(gobj, "card_action_routes");
|
|
@@ -22265,25 +22355,28 @@ function add_topic_card(gobj, id, text, icon) {
|
|
|
22265
22355
|
let actions = [];
|
|
22266
22356
|
if (routes.info) actions.push(card_action_anchor("TREEDB_CARD_INFO", "yi-circle-info", "info", fill(routes.info)));
|
|
22267
22357
|
if (routes.table) actions.push(card_action_anchor("TREEDB_CARD_TABLE", "yi-table", "table", fill(routes.table)));
|
|
22268
|
-
if (routes.graph) actions.push(card_action_anchor("TREEDB_CARD_GRAPH", "yi-hexagon-nodes", "graph", fill(routes.graph)));
|
|
22269
22358
|
let $card = createElement2([
|
|
22270
22359
|
"div",
|
|
22271
22360
|
{
|
|
22272
22361
|
class: "TREEDB_TOPIC_CARD",
|
|
22273
22362
|
"data-topic": topic
|
|
22274
22363
|
},
|
|
22275
|
-
[
|
|
22276
|
-
|
|
22277
|
-
|
|
22278
|
-
|
|
22279
|
-
|
|
22280
|
-
|
|
22281
|
-
|
|
22282
|
-
|
|
22283
|
-
|
|
22284
|
-
|
|
22285
|
-
|
|
22286
|
-
|
|
22364
|
+
[
|
|
22365
|
+
[
|
|
22366
|
+
"span",
|
|
22367
|
+
{
|
|
22368
|
+
class: "TREEDB_TOPIC_CARD_NAME",
|
|
22369
|
+
i18n: text
|
|
22370
|
+
},
|
|
22371
|
+
text
|
|
22372
|
+
],
|
|
22373
|
+
...topic_card_meta(desc),
|
|
22374
|
+
[
|
|
22375
|
+
"div",
|
|
22376
|
+
{ class: "TREEDB_TOPIC_CARD_ACTIONS" },
|
|
22377
|
+
actions
|
|
22378
|
+
]
|
|
22379
|
+
]
|
|
22287
22380
|
]);
|
|
22288
22381
|
if (gobj.priv._selected_card_topic === topic) $card.classList.add("is-selected");
|
|
22289
22382
|
$card.addEventListener("click", function() {
|
|
@@ -22636,7 +22729,7 @@ function process_treedb_descs$1(gobj) {
|
|
|
22636
22729
|
let id = `${gobj_name(gobj)}?${desc.topic_name}`;
|
|
22637
22730
|
let gobj_topic_form = gobj_create_service(id, "C_YUI_TREEDB_TOPIC_WITH_FORM", kw_topic_form, gobj);
|
|
22638
22731
|
add_tab(gobj, gobj_topic_form, id, key, "yi-table");
|
|
22639
|
-
add_topic_card(gobj, id, key, "yi-table");
|
|
22732
|
+
add_topic_card(gobj, id, key, "yi-table", desc);
|
|
22640
22733
|
gobj_start(gobj_topic_form);
|
|
22641
22734
|
}
|
|
22642
22735
|
let href = gobj_read_str_attr(gobj, "last_selection");
|
package/package.json
CHANGED
|
@@ -36,6 +36,31 @@
|
|
|
36
36
|
line-height: 1.2;
|
|
37
37
|
word-break: break-word;
|
|
38
38
|
}
|
|
39
|
+
/* What the card says about its topic: version + columns, then the
|
|
40
|
+
* topics it hangs from and the ones hanging from it. Muted and small,
|
|
41
|
+
* under the name; a long list is cut, whole in the title. The spans
|
|
42
|
+
* are spaced by `gap` because createElement2 trims text nodes. */
|
|
43
|
+
.TREEDB_TOPIC_CARD_META,
|
|
44
|
+
.TREEDB_TOPIC_CARD_REL {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: baseline;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
gap: 0.3rem;
|
|
49
|
+
max-width: 100%;
|
|
50
|
+
font-size: 0.75rem;
|
|
51
|
+
color: var(--bulma-text-weak, #7a7a7a);
|
|
52
|
+
white-space: nowrap;
|
|
53
|
+
}
|
|
54
|
+
.TREEDB_TOPIC_CARD_COLS {
|
|
55
|
+
display: inline-flex;
|
|
56
|
+
gap: 0.25rem;
|
|
57
|
+
}
|
|
58
|
+
.TREEDB_TOPIC_CARD_REL_LIST {
|
|
59
|
+
min-width: 0;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
text-overflow: ellipsis;
|
|
62
|
+
color: var(--bulma-text, inherit);
|
|
63
|
+
}
|
|
39
64
|
.TREEDB_TOPIC_CARD_ACTIONS {
|
|
40
65
|
display: flex;
|
|
41
66
|
justify-content: center;
|
|
@@ -84,7 +84,7 @@ SDATA(data_type_t.DTP_BOOLEAN, "system", 0, false, "Manage system t
|
|
|
84
84
|
SDATA(data_type_t.DTP_STRING, "tabs_style", 0, "is-toggle is-fullwidth", "Bulma tab styling"),
|
|
85
85
|
SDATA(data_type_t.DTP_BOOLEAN, "with_cards_landing",0, false, "Land on a grid of topic cards (list->detail): a card opens its table, with the tabs bar + a back-to-grid button. Off = tabs only (legacy)."),
|
|
86
86
|
SDATA(data_type_t.DTP_BOOLEAN, "readonly", 0, false, "The whole treedb is read-only: every topic opens without its write affordances and the write events are refused. Set it when this yuno is not the MASTER of the treedb's tranger -- only the master can write, and the yuno answers 'READ-ONLY' to a write since SDK 7.13.0 (ask `treedb-info`)"),
|
|
87
|
-
SDATA(data_type_t.DTP_JSON, "card_action_routes",0, null, "
|
|
87
|
+
SDATA(data_type_t.DTP_JSON, "card_action_routes",0, null, "Hash-route templates {info, table, graph} with a {topic} placeholder (host-supplied, route-agnostic). Present ⇒ cards show the info and table icons, and `graph` without its `/{topic}` is the toolbar's graph button (the card has no graph icon: its topic segment is a focus); absent ⇒ a single card that opens the table."),
|
|
88
88
|
SDATA(data_type_t.DTP_JSON, "landing_routes", 0, null, "Host-supplied hashes for the two landing sub-views {cards, schema}; the toggle navigates to them so the landing is URL-addressable (ROUTING.md). Absent ⇒ toggle flips in-view only (legacy)."),
|
|
89
89
|
SDATA(data_type_t.DTP_STRING, "base_route", 0, "", "This view's base route (host-supplied); used to declare its sub-routes (topics / info / schema) to the site map (ROUTING.md contributor)."),
|
|
90
90
|
SDATA(data_type_t.DTP_STRING, "source_url", 0, "", "The backend this view browses (host-supplied, typically the wss url of the connection), shown in the toolbar. A tab label names the TREEDB, and the same treedb name lives on more than one node, so the node has to be readable somewhere -- and a tab is too narrow to carry a url. Empty ⇒ nothing is shown."),
|
|
@@ -599,6 +599,74 @@ function card_action_anchor(logical_class, icon, i18n_key, href)
|
|
|
599
599
|
]];
|
|
600
600
|
}
|
|
601
601
|
|
|
602
|
+
/************************************************************
|
|
603
|
+
* What a topic card says about its topic, from its desc alone
|
|
604
|
+
* (no request): its version and how many columns it has, the
|
|
605
|
+
* topics it hangs FROM (its fkeys) and the ones that hang from
|
|
606
|
+
* it (its hooks). The names are DATA and are not translated;
|
|
607
|
+
* each label carries its key. Lists are cut with an ellipsis,
|
|
608
|
+
* whole in the title.
|
|
609
|
+
************************************************************/
|
|
610
|
+
function topic_card_meta(desc)
|
|
611
|
+
{
|
|
612
|
+
if(!is_object(desc)) {
|
|
613
|
+
return [];
|
|
614
|
+
}
|
|
615
|
+
let cols = is_array(desc.cols)? desc.cols : [];
|
|
616
|
+
let n_cols = 0;
|
|
617
|
+
let parents = [];
|
|
618
|
+
let children = [];
|
|
619
|
+
for(let col of cols) {
|
|
620
|
+
if(!col || !col.id || col.id.charAt(0) === "_") {
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
n_cols++;
|
|
624
|
+
if(is_object(col.fkey)) {
|
|
625
|
+
for(let t_name of Object.keys(col.fkey)) {
|
|
626
|
+
if(!parents.includes(t_name)) {
|
|
627
|
+
parents.push(t_name);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if(is_object(col.hook)) {
|
|
632
|
+
for(let t_name of Object.keys(col.hook)) {
|
|
633
|
+
if(!children.includes(t_name)) {
|
|
634
|
+
children.push(t_name);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
let meta = [];
|
|
641
|
+
let head = [];
|
|
642
|
+
if(desc.topic_version !== undefined && desc.topic_version !== null && desc.topic_version !== "") {
|
|
643
|
+
head.push(['span', {class: 'TREEDB_TOPIC_CARD_VERSION',
|
|
644
|
+
title: t('version'), 'data-i18n-title': 'version'},
|
|
645
|
+
`v${desc.topic_version}`]);
|
|
646
|
+
}
|
|
647
|
+
head.push(['span', {class: 'TREEDB_TOPIC_CARD_COLS'}, [
|
|
648
|
+
['span', {}, `${n_cols}`],
|
|
649
|
+
['span', {i18n: 'columns'}, 'columns']
|
|
650
|
+
]]);
|
|
651
|
+
meta.push(['div', {class: 'TREEDB_TOPIC_CARD_META'}, head]);
|
|
652
|
+
|
|
653
|
+
let relation = (cls, key, arrow, names) => {
|
|
654
|
+
let list = names.join(", ");
|
|
655
|
+
return ['div', {class: `TREEDB_TOPIC_CARD_REL ${cls}`, title: list}, [
|
|
656
|
+
['span', {class: 'TREEDB_TOPIC_CARD_REL_ARROW', 'aria-hidden': 'true'}, arrow],
|
|
657
|
+
['span', {class: 'TREEDB_TOPIC_CARD_REL_LABEL', i18n: key}, key],
|
|
658
|
+
['span', {class: 'TREEDB_TOPIC_CARD_REL_LIST'}, list]
|
|
659
|
+
]];
|
|
660
|
+
};
|
|
661
|
+
if(parents.length) {
|
|
662
|
+
meta.push(relation('TREEDB_TOPIC_CARD_PARENTS', 'parents', '↑', parents));
|
|
663
|
+
}
|
|
664
|
+
if(children.length) {
|
|
665
|
+
meta.push(relation('TREEDB_TOPIC_CARD_CHILDREN', 'children', '↓', children));
|
|
666
|
+
}
|
|
667
|
+
return meta;
|
|
668
|
+
}
|
|
669
|
+
|
|
602
670
|
/************************************************************
|
|
603
671
|
* Add one topic card to the cards-landing grid (list->detail).
|
|
604
672
|
* With `card_action_routes` (host-supplied templates) the card
|
|
@@ -606,7 +674,7 @@ function card_action_anchor(logical_class, icon, i18n_key, href)
|
|
|
606
674
|
* it falls back to a single card that opens the table (same id
|
|
607
675
|
* contract as the tab, `<gobj>?<topic>`).
|
|
608
676
|
************************************************************/
|
|
609
|
-
function add_topic_card(gobj, id, text, icon)
|
|
677
|
+
function add_topic_card(gobj, id, text, icon, desc)
|
|
610
678
|
{
|
|
611
679
|
let $container = gobj_read_attr(gobj, "$container");
|
|
612
680
|
let $grid = $container.querySelector(".TREEDB_TOPICS_LANDING .yui-nav-cards");
|
|
@@ -635,9 +703,16 @@ function add_topic_card(gobj, id, text, icon)
|
|
|
635
703
|
return;
|
|
636
704
|
}
|
|
637
705
|
|
|
638
|
-
/*
|
|
639
|
-
*
|
|
640
|
-
*
|
|
706
|
+
/* Two-icon card: info / table, real hash anchors. {topic} in each
|
|
707
|
+
* template is the raw topic name (identifier-safe, matching the
|
|
708
|
+
* tab/host `<base_route>/<topic>` convention).
|
|
709
|
+
*
|
|
710
|
+
* NO graph icon any more. Its route was `<graph>/<topic>`, and that
|
|
711
|
+
* segment is a FOCUS: every way into the graph from a card arrived
|
|
712
|
+
* with that topic highlighted, over whatever the reader had left
|
|
713
|
+
* there. The graph is one button in the toolbar now, with no topic
|
|
714
|
+
* (routes.graph still feeds it), and the room goes to what the card
|
|
715
|
+
* can say about its topic. */
|
|
641
716
|
let topic = id.indexOf("?") >= 0 ? id.split("?")[1] : id;
|
|
642
717
|
let fill = (tpl) => String(tpl || "").replace("{topic}", topic);
|
|
643
718
|
|
|
@@ -650,14 +725,11 @@ function add_topic_card(gobj, id, text, icon)
|
|
|
650
725
|
actions.push(card_action_anchor(
|
|
651
726
|
"TREEDB_CARD_TABLE", "yi-table", "table", fill(routes.table)));
|
|
652
727
|
}
|
|
653
|
-
if(routes.graph) {
|
|
654
|
-
actions.push(card_action_anchor(
|
|
655
|
-
"TREEDB_CARD_GRAPH", "yi-hexagon-nodes", "graph", fill(routes.graph)));
|
|
656
|
-
}
|
|
657
728
|
|
|
658
729
|
let $card = createElement2(
|
|
659
730
|
['div', {class: 'TREEDB_TOPIC_CARD', 'data-topic': topic}, [
|
|
660
731
|
['span', {class: 'TREEDB_TOPIC_CARD_NAME', i18n: text}, text],
|
|
732
|
+
...topic_card_meta(desc),
|
|
661
733
|
['div', {class: 'TREEDB_TOPIC_CARD_ACTIONS'}, actions]
|
|
662
734
|
]]
|
|
663
735
|
);
|
|
@@ -1087,7 +1159,7 @@ function process_treedb_descs(gobj)
|
|
|
1087
1159
|
|
|
1088
1160
|
// TODO get icon from remote config
|
|
1089
1161
|
add_tab(gobj, gobj_topic_form, id, key, "yi-table");
|
|
1090
|
-
add_topic_card(gobj, id, key, "yi-table");
|
|
1162
|
+
add_topic_card(gobj, id, key, "yi-table", desc);
|
|
1091
1163
|
|
|
1092
1164
|
gobj_start(gobj_topic_form);
|
|
1093
1165
|
}
|