@yuneta/gobj-ui 7.0.1 → 7.2.0
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 +56 -0
- package/dist/gobj-ui.cjs.js +504 -101
- package/dist/gobj-ui.es.js +504 -101
- package/package.json +2 -2
- package/src/c_g6_nodes_tree.js +113 -0
- package/src/c_yui_treedb_graph.js +93 -2
- package/src/c_yui_treedb_topic_with_form.js +265 -20
package/dist/gobj-ui.es.js
CHANGED
|
@@ -11012,7 +11012,7 @@ function ac_expand_collapsed(gobj, event, kw, src) {
|
|
|
11012
11012
|
/************************************************************
|
|
11013
11013
|
* EV_SEARCH { text }
|
|
11014
11014
|
************************************************************/
|
|
11015
|
-
function ac_search(gobj, event, kw, src) {
|
|
11015
|
+
function ac_search$1(gobj, event, kw, src) {
|
|
11016
11016
|
let priv = gobj.priv;
|
|
11017
11017
|
priv.search = (kw.text || "").trim().toLowerCase();
|
|
11018
11018
|
render_tree(gobj);
|
|
@@ -11161,7 +11161,7 @@ function create_gclass$10(gclass_name) {
|
|
|
11161
11161
|
],
|
|
11162
11162
|
[
|
|
11163
11163
|
"EV_SEARCH",
|
|
11164
|
-
ac_search,
|
|
11164
|
+
ac_search$1,
|
|
11165
11165
|
null
|
|
11166
11166
|
],
|
|
11167
11167
|
[
|
|
@@ -16217,6 +16217,9 @@ var attrs_table$5 = [
|
|
|
16217
16217
|
SDATA(data_type_t.DTP_BOOLEAN, "with_refresh_button", 0, true, "Button toolbar REFRESH"),
|
|
16218
16218
|
SDATA(data_type_t.DTP_BOOLEAN, "with_search_button", 0, true, "Button toolbar SEARCH"),
|
|
16219
16219
|
SDATA(data_type_t.DTP_BOOLEAN, "with_schema_button", 0, true, "Button toolbar SCHEMA (show the topic's desc)"),
|
|
16220
|
+
SDATA(data_type_t.DTP_BOOLEAN, "with_columns_button", 0, true, "Button toolbar COLUMNS (choose which columns the table shows)"),
|
|
16221
|
+
SDATA(data_type_t.DTP_BOOLEAN, "with_export_button", 0, true, "Button toolbar EXPORT (download as CSV what the table holds)"),
|
|
16222
|
+
SDATA(data_type_t.DTP_BOOLEAN, "with_header_filters", 0, true, "Per-column filter box in the table header, on the columns a text/number match means something (not hooks, fkeys or json)"),
|
|
16220
16223
|
SDATA(data_type_t.DTP_BOOLEAN, "with_in_row_edit_icons", 0, true, "Add a last column with internal EDIT/DELETE icon"),
|
|
16221
16224
|
SDATA(data_type_t.DTP_BOOLEAN, "editable", 0, false, "Edit state"),
|
|
16222
16225
|
SDATA(data_type_t.DTP_BOOLEAN, "with_checkbox", 0, true, "Auxiliary first column to select rows"),
|
|
@@ -16509,6 +16512,8 @@ function build_ui$5(gobj) {
|
|
|
16509
16512
|
let with_refresh_button = gobj_read_bool_attr(gobj, "with_refresh_button");
|
|
16510
16513
|
let with_search_button = gobj_read_bool_attr(gobj, "with_search_button");
|
|
16511
16514
|
let with_schema_button = gobj_read_bool_attr(gobj, "with_schema_button");
|
|
16515
|
+
let with_columns_button = gobj_read_bool_attr(gobj, "with_columns_button");
|
|
16516
|
+
let with_export_button = gobj_read_bool_attr(gobj, "with_export_button");
|
|
16512
16517
|
if (with_search_button) {
|
|
16513
16518
|
let search_id = `${toolbar_id}_search`;
|
|
16514
16519
|
let $search_box = createElement2([
|
|
@@ -16529,17 +16534,7 @@ function build_ui$5(gobj) {
|
|
|
16529
16534
|
let $search_input = $search_box.querySelector(`#${search_id}`);
|
|
16530
16535
|
attach_clear($search_box, $search_input);
|
|
16531
16536
|
if ($search_input) $search_input.addEventListener("input", (event) => {
|
|
16532
|
-
|
|
16533
|
-
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
16534
|
-
if (!tabulator) return;
|
|
16535
|
-
if (searchText) tabulator.setFilter(function(data) {
|
|
16536
|
-
return Object.entries(data).some(([key, val]) => {
|
|
16537
|
-
if (key.startsWith("_")) return false;
|
|
16538
|
-
if (val === null || val === void 0) return false;
|
|
16539
|
-
return String(val).toLowerCase().includes(searchText);
|
|
16540
|
-
});
|
|
16541
|
-
});
|
|
16542
|
-
else tabulator.clearFilter();
|
|
16537
|
+
gobj_send_event(gobj, "EV_SEARCH", { text: event.target.value.trim() }, gobj);
|
|
16543
16538
|
});
|
|
16544
16539
|
$view_toolbar.appendChild($search_box);
|
|
16545
16540
|
}
|
|
@@ -16593,6 +16588,58 @@ function build_ui$5(gobj) {
|
|
|
16593
16588
|
]);
|
|
16594
16589
|
$view_toolbar.appendChild($schema);
|
|
16595
16590
|
}
|
|
16591
|
+
if (with_columns_button) {
|
|
16592
|
+
let $columns = createElement2([
|
|
16593
|
+
"button",
|
|
16594
|
+
{
|
|
16595
|
+
class: "TREEDB_TABLE_COLUMNS button mr-1",
|
|
16596
|
+
title: t("choose the columns to show"),
|
|
16597
|
+
"data-i18n-title": "choose the columns to show",
|
|
16598
|
+
"aria-label": t("columns"),
|
|
16599
|
+
"data-i18n-aria-label": "columns"
|
|
16600
|
+
},
|
|
16601
|
+
[["i", { class: "yi-table" }], [
|
|
16602
|
+
"span",
|
|
16603
|
+
{
|
|
16604
|
+
class: "is-hidden-mobile",
|
|
16605
|
+
i18n: "columns",
|
|
16606
|
+
style: "padding-left:5px;"
|
|
16607
|
+
},
|
|
16608
|
+
"columns"
|
|
16609
|
+
]],
|
|
16610
|
+
{ "click": (event) => {
|
|
16611
|
+
event.stopPropagation();
|
|
16612
|
+
gobj_send_event(gobj, "EV_OPEN_COLUMNS", {}, gobj);
|
|
16613
|
+
} }
|
|
16614
|
+
]);
|
|
16615
|
+
$view_toolbar.appendChild($columns);
|
|
16616
|
+
}
|
|
16617
|
+
if (with_export_button) {
|
|
16618
|
+
let $export = createElement2([
|
|
16619
|
+
"button",
|
|
16620
|
+
{
|
|
16621
|
+
class: "TREEDB_TABLE_EXPORT button mr-1",
|
|
16622
|
+
title: t("download the rows loaded in this table as csv"),
|
|
16623
|
+
"data-i18n-title": "download the rows loaded in this table as csv",
|
|
16624
|
+
"aria-label": t("export"),
|
|
16625
|
+
"data-i18n-aria-label": "export"
|
|
16626
|
+
},
|
|
16627
|
+
[["i", { class: "yi-download" }], [
|
|
16628
|
+
"span",
|
|
16629
|
+
{
|
|
16630
|
+
class: "is-hidden-mobile",
|
|
16631
|
+
i18n: "export",
|
|
16632
|
+
style: "padding-left:5px;"
|
|
16633
|
+
},
|
|
16634
|
+
"export"
|
|
16635
|
+
]],
|
|
16636
|
+
{ "click": (event) => {
|
|
16637
|
+
event.stopPropagation();
|
|
16638
|
+
gobj_send_event(gobj, "EV_EXPORT_TABLE", {}, gobj);
|
|
16639
|
+
} }
|
|
16640
|
+
]);
|
|
16641
|
+
$view_toolbar.appendChild($export);
|
|
16642
|
+
}
|
|
16596
16643
|
let table_id = gobj_read_str_attr(gobj, "table_id");
|
|
16597
16644
|
let $container = createElement2([
|
|
16598
16645
|
"div",
|
|
@@ -16681,6 +16728,7 @@ function col_title_formatter(gobj, col) {
|
|
|
16681
16728
|
function create_tabulator(gobj) {
|
|
16682
16729
|
let table_id = gobj_read_str_attr(gobj, "table_id");
|
|
16683
16730
|
let desc = gobj_read_attr(gobj, "desc");
|
|
16731
|
+
let with_header_filters = gobj_read_bool_attr(gobj, "with_header_filters");
|
|
16684
16732
|
let columns = [];
|
|
16685
16733
|
let with_checkbox = gobj_read_bool_attr(gobj, "with_checkbox");
|
|
16686
16734
|
let with_radio = gobj_read_bool_attr(gobj, "with_radio");
|
|
@@ -16724,6 +16772,46 @@ function create_tabulator(gobj) {
|
|
|
16724
16772
|
col_id: cell.getField()
|
|
16725
16773
|
}, gobj);
|
|
16726
16774
|
}
|
|
16775
|
+
const FILTERABLE = [
|
|
16776
|
+
"string",
|
|
16777
|
+
"integer",
|
|
16778
|
+
"real",
|
|
16779
|
+
"rowid",
|
|
16780
|
+
"uuid",
|
|
16781
|
+
"qualified",
|
|
16782
|
+
"email",
|
|
16783
|
+
"url",
|
|
16784
|
+
"tel",
|
|
16785
|
+
"id",
|
|
16786
|
+
"hex",
|
|
16787
|
+
"currency",
|
|
16788
|
+
"percent"
|
|
16789
|
+
];
|
|
16790
|
+
function fkey_matches(term, value) {
|
|
16791
|
+
if (term === "" || term === null || term === void 0) return true;
|
|
16792
|
+
if (value === null || value === void 0) return false;
|
|
16793
|
+
return (typeof value === "string" ? value : JSON.stringify(value)).toLowerCase().includes(String(term).toLowerCase());
|
|
16794
|
+
}
|
|
16795
|
+
function apply_header_filter(colDef, field_desc) {
|
|
16796
|
+
switch (field_desc.type) {
|
|
16797
|
+
case "boolean":
|
|
16798
|
+
colDef.headerFilter = "tickCross";
|
|
16799
|
+
colDef.headerFilterParams = { tristate: true };
|
|
16800
|
+
break;
|
|
16801
|
+
case "enum":
|
|
16802
|
+
colDef.headerFilter = "list";
|
|
16803
|
+
colDef.headerFilterParams = {
|
|
16804
|
+
values: field_desc.enum_list || [],
|
|
16805
|
+
clearable: true
|
|
16806
|
+
};
|
|
16807
|
+
break;
|
|
16808
|
+
case "fkey":
|
|
16809
|
+
colDef.headerFilter = "input";
|
|
16810
|
+
colDef.headerFilterFunc = fkey_matches;
|
|
16811
|
+
break;
|
|
16812
|
+
default: if (FILTERABLE.includes(field_desc.type)) colDef.headerFilter = "input";
|
|
16813
|
+
}
|
|
16814
|
+
}
|
|
16727
16815
|
for (let i = 0; i < desc.cols.length; i++) {
|
|
16728
16816
|
let col = desc.cols[i];
|
|
16729
16817
|
if (!col.id || col.id[0] === "_") continue;
|
|
@@ -16804,6 +16892,7 @@ function create_tabulator(gobj) {
|
|
|
16804
16892
|
hozAlign,
|
|
16805
16893
|
formatter: colFormatter
|
|
16806
16894
|
};
|
|
16895
|
+
if (with_header_filters) apply_header_filter(colDef, field_desc);
|
|
16807
16896
|
if (vertAlign) colDef.vertAlign = vertAlign;
|
|
16808
16897
|
if (formatterParams) colDef.formatterParams = formatterParams;
|
|
16809
16898
|
if (cellClick) colDef.cellClick = cellClick;
|
|
@@ -18013,6 +18102,125 @@ function ac_show_schema(gobj, event, kw, src) {
|
|
|
18013
18102
|
return 0;
|
|
18014
18103
|
}
|
|
18015
18104
|
/************************************************************
|
|
18105
|
+
* Filter the loaded rows by a term matched against every non-internal
|
|
18106
|
+
* field. `clearFilter()` with no argument drops only THIS filter: the
|
|
18107
|
+
* per-column header filters are a separate layer and survive, so a
|
|
18108
|
+
* cleared search box does not silently undo them.
|
|
18109
|
+
************************************************************/
|
|
18110
|
+
function ac_search(gobj, event, kw, src) {
|
|
18111
|
+
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
18112
|
+
if (!tabulator) {
|
|
18113
|
+
log_error(`${gobj_short_name(gobj)}: no table to search`);
|
|
18114
|
+
return -1;
|
|
18115
|
+
}
|
|
18116
|
+
let term = (kw && kw.text || "").toLowerCase();
|
|
18117
|
+
if (!term) {
|
|
18118
|
+
tabulator.clearFilter();
|
|
18119
|
+
return 0;
|
|
18120
|
+
}
|
|
18121
|
+
tabulator.setFilter(function(data) {
|
|
18122
|
+
return Object.entries(data).some(([key, val]) => {
|
|
18123
|
+
if (key.startsWith("_")) return false;
|
|
18124
|
+
if (val === null || val === void 0) return false;
|
|
18125
|
+
return String(val).toLowerCase().includes(term);
|
|
18126
|
+
});
|
|
18127
|
+
});
|
|
18128
|
+
return 0;
|
|
18129
|
+
}
|
|
18130
|
+
/************************************************************
|
|
18131
|
+
* Which columns the table shows: one checkbox per column, the current
|
|
18132
|
+
* visibility ticked. The internal columns (`_check_box_state_`,
|
|
18133
|
+
* `_operation`) are not offered — they are chrome, not data.
|
|
18134
|
+
************************************************************/
|
|
18135
|
+
function ac_open_columns(gobj, event, kw, src) {
|
|
18136
|
+
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
18137
|
+
if (!tabulator) {
|
|
18138
|
+
log_error(`${gobj_short_name(gobj)}: no table, no columns to choose`);
|
|
18139
|
+
return -1;
|
|
18140
|
+
}
|
|
18141
|
+
let shell = yui_shell_of(gobj);
|
|
18142
|
+
if (!shell) {
|
|
18143
|
+
log_error(`${gobj_short_name(gobj)}: no shell, cannot open the column chooser`);
|
|
18144
|
+
return -1;
|
|
18145
|
+
}
|
|
18146
|
+
let $list = createElement2(["div", { class: "TREEDB_COLUMNS_LIST" }]);
|
|
18147
|
+
let columns = tabulator.getColumns();
|
|
18148
|
+
for (let i = 0; i < columns.length; i++) {
|
|
18149
|
+
let column = columns[i];
|
|
18150
|
+
let field = column.getField();
|
|
18151
|
+
if (!field || field[0] === "_") continue;
|
|
18152
|
+
let $cb = createElement2(["input", {
|
|
18153
|
+
type: "checkbox",
|
|
18154
|
+
class: "mr-2"
|
|
18155
|
+
}]);
|
|
18156
|
+
$cb.checked = column.isVisible();
|
|
18157
|
+
$cb.addEventListener("change", () => {
|
|
18158
|
+
gobj_send_event(gobj, "EV_TOGGLE_COLUMN", {
|
|
18159
|
+
field,
|
|
18160
|
+
visible: $cb.checked
|
|
18161
|
+
}, gobj);
|
|
18162
|
+
});
|
|
18163
|
+
$list.appendChild(createElement2([
|
|
18164
|
+
"label",
|
|
18165
|
+
{ class: "checkbox is-block mb-1 TREEDB_COLUMN_ITEM" },
|
|
18166
|
+
[$cb, [
|
|
18167
|
+
"span",
|
|
18168
|
+
{ class: "ml-2" },
|
|
18169
|
+
column.getDefinition().title || field
|
|
18170
|
+
]]
|
|
18171
|
+
]));
|
|
18172
|
+
}
|
|
18173
|
+
yui_shell_show_modal(shell, $list, {
|
|
18174
|
+
dialog: true,
|
|
18175
|
+
logical_class: "TREEDB_COLUMNS_DIALOG",
|
|
18176
|
+
title_prefix: gobj_read_str_attr(gobj, "topic_name"),
|
|
18177
|
+
title: "columns",
|
|
18178
|
+
t
|
|
18179
|
+
});
|
|
18180
|
+
return 0;
|
|
18181
|
+
}
|
|
18182
|
+
/************************************************************
|
|
18183
|
+
* Show / hide one column.
|
|
18184
|
+
************************************************************/
|
|
18185
|
+
function ac_toggle_column(gobj, event, kw, src) {
|
|
18186
|
+
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
18187
|
+
let field = kw && kw.field || "";
|
|
18188
|
+
if (!tabulator || !field) {
|
|
18189
|
+
log_error(`${gobj_short_name(gobj)}: no column '${field}' to toggle`);
|
|
18190
|
+
return -1;
|
|
18191
|
+
}
|
|
18192
|
+
try {
|
|
18193
|
+
if (kw.visible) tabulator.showColumn(field);
|
|
18194
|
+
else tabulator.hideColumn(field);
|
|
18195
|
+
} catch (e) {
|
|
18196
|
+
log_error(`${gobj_short_name(gobj)}: cannot toggle column '${field}': ${e}`);
|
|
18197
|
+
return -1;
|
|
18198
|
+
}
|
|
18199
|
+
return 0;
|
|
18200
|
+
}
|
|
18201
|
+
/************************************************************
|
|
18202
|
+
* Download what the table HOLDS as CSV: the loaded rows, the visible
|
|
18203
|
+
* columns, search and header filters applied — which is what the reader
|
|
18204
|
+
* is looking at. Not the topic: a server-side dump of every node is not
|
|
18205
|
+
* something this view can stream.
|
|
18206
|
+
************************************************************/
|
|
18207
|
+
function ac_export_table(gobj, event, kw, src) {
|
|
18208
|
+
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
18209
|
+
if (!tabulator) {
|
|
18210
|
+
log_error(`${gobj_short_name(gobj)}: no table to export`);
|
|
18211
|
+
return -1;
|
|
18212
|
+
}
|
|
18213
|
+
let name = `${gobj_read_str_attr(gobj, "treedb_name")}-${gobj_read_str_attr(gobj, "topic_name")}.csv`;
|
|
18214
|
+
name = name.replace(/[^\w.\-]+/g, "_");
|
|
18215
|
+
try {
|
|
18216
|
+
tabulator.download("csv", name);
|
|
18217
|
+
} catch (e) {
|
|
18218
|
+
log_error(`${gobj_short_name(gobj)}: CSV export failed: ${e}`);
|
|
18219
|
+
return -1;
|
|
18220
|
+
}
|
|
18221
|
+
return 0;
|
|
18222
|
+
}
|
|
18223
|
+
/************************************************************
|
|
18016
18224
|
* {
|
|
18017
18225
|
* href: href
|
|
18018
18226
|
* }
|
|
@@ -18136,6 +18344,26 @@ function create_gclass$5(gclass_name) {
|
|
|
18136
18344
|
ac_show_schema,
|
|
18137
18345
|
null
|
|
18138
18346
|
],
|
|
18347
|
+
[
|
|
18348
|
+
"EV_SEARCH",
|
|
18349
|
+
ac_search,
|
|
18350
|
+
null
|
|
18351
|
+
],
|
|
18352
|
+
[
|
|
18353
|
+
"EV_OPEN_COLUMNS",
|
|
18354
|
+
ac_open_columns,
|
|
18355
|
+
null
|
|
18356
|
+
],
|
|
18357
|
+
[
|
|
18358
|
+
"EV_TOGGLE_COLUMN",
|
|
18359
|
+
ac_toggle_column,
|
|
18360
|
+
null
|
|
18361
|
+
],
|
|
18362
|
+
[
|
|
18363
|
+
"EV_EXPORT_TABLE",
|
|
18364
|
+
ac_export_table,
|
|
18365
|
+
null
|
|
18366
|
+
],
|
|
18139
18367
|
[
|
|
18140
18368
|
"EV_SHOW",
|
|
18141
18369
|
ac_show$4,
|
|
@@ -18166,6 +18394,10 @@ function create_gclass$5(gclass_name) {
|
|
|
18166
18394
|
["EV_CHANGE_LOCALE", 0],
|
|
18167
18395
|
["EV_REFRESH", 0],
|
|
18168
18396
|
["EV_SHOW_SCHEMA", 0],
|
|
18397
|
+
["EV_SEARCH", 0],
|
|
18398
|
+
["EV_OPEN_COLUMNS", 0],
|
|
18399
|
+
["EV_TOGGLE_COLUMN", 0],
|
|
18400
|
+
["EV_EXPORT_TABLE", 0],
|
|
18169
18401
|
["EV_CREATE_RECORD", event_flag_t.EVF_OUTPUT_EVENT],
|
|
18170
18402
|
["EV_UPDATE_RECORD", event_flag_t.EVF_OUTPUT_EVENT],
|
|
18171
18403
|
["EV_DELETE_RECORD", event_flag_t.EVF_OUTPUT_EVENT],
|
|
@@ -18527,101 +18759,140 @@ function make_toolbar(gobj) {
|
|
|
18527
18759
|
gobj.priv;
|
|
18528
18760
|
let modes = gobj_read_attr(gobj, "operation_modes");
|
|
18529
18761
|
if (gobj_read_bool_attr(gobj, "readonly")) modes = modes.filter((mode) => mode !== "edition");
|
|
18762
|
+
let left_items = [
|
|
18763
|
+
[
|
|
18764
|
+
"span",
|
|
18765
|
+
{
|
|
18766
|
+
class: "GRAPH_LAYOUT_LABEL is-hidden-mobile",
|
|
18767
|
+
style: "padding-right:5px;",
|
|
18768
|
+
i18n: "layout"
|
|
18769
|
+
},
|
|
18770
|
+
"layout"
|
|
18771
|
+
],
|
|
18772
|
+
[
|
|
18773
|
+
"div",
|
|
18774
|
+
{ class: "select" },
|
|
18775
|
+
[["select", { class: "GRAPH_LAYOUT_SELECT" }]],
|
|
18776
|
+
{ change: (evt) => {
|
|
18777
|
+
evt.stopPropagation();
|
|
18778
|
+
gobj_send_event(gobj, "EV_SET_LAYOUT", { layout: evt.target.value }, gobj);
|
|
18779
|
+
} }
|
|
18780
|
+
],
|
|
18781
|
+
[
|
|
18782
|
+
"span",
|
|
18783
|
+
{
|
|
18784
|
+
class: "GRAPH_MODE_LABEL is-hidden-mobile",
|
|
18785
|
+
style: "padding-left:10px; padding-right:5px;",
|
|
18786
|
+
i18n: "operation mode"
|
|
18787
|
+
},
|
|
18788
|
+
"operation mode"
|
|
18789
|
+
],
|
|
18790
|
+
[
|
|
18791
|
+
"div",
|
|
18792
|
+
{ class: "select" },
|
|
18793
|
+
[[
|
|
18794
|
+
"select",
|
|
18795
|
+
{ class: "GRAPH_MODE_SELECT" },
|
|
18796
|
+
modes.map((item) => [
|
|
18797
|
+
"option",
|
|
18798
|
+
{},
|
|
18799
|
+
item
|
|
18800
|
+
])
|
|
18801
|
+
]],
|
|
18802
|
+
{ change: (evt) => {
|
|
18803
|
+
evt.stopPropagation();
|
|
18804
|
+
gobj_send_event(gobj, "EV_SET_OPERATION_MODE", { operation_mode: evt.target.value }, gobj);
|
|
18805
|
+
} }
|
|
18806
|
+
],
|
|
18807
|
+
[
|
|
18808
|
+
"button",
|
|
18809
|
+
{ class: "GRAPH_REFRESH button" },
|
|
18810
|
+
[["i", { class: "yi-arrows-rotate" }], [
|
|
18811
|
+
"span",
|
|
18812
|
+
{
|
|
18813
|
+
class: "is-hidden-mobile",
|
|
18814
|
+
style: "padding-left:5px;",
|
|
18815
|
+
i18n: "refresh"
|
|
18816
|
+
},
|
|
18817
|
+
"refresh"
|
|
18818
|
+
]],
|
|
18819
|
+
{ click: (evt) => {
|
|
18820
|
+
evt.stopPropagation();
|
|
18821
|
+
gobj_send_event(gobj, "EV_REFRESH_TREEDB", { evt }, gobj);
|
|
18822
|
+
} }
|
|
18823
|
+
],
|
|
18824
|
+
[
|
|
18825
|
+
"button",
|
|
18826
|
+
{
|
|
18827
|
+
class: "button ml-2 TREEDB_JSON_BTN",
|
|
18828
|
+
title: t("raw json"),
|
|
18829
|
+
"aria-label": t("raw json"),
|
|
18830
|
+
"data-i18n-title": "raw json",
|
|
18831
|
+
"data-i18n-aria-label": "raw json"
|
|
18832
|
+
},
|
|
18833
|
+
[["i", { class: "yi-eye" }], [
|
|
18834
|
+
"span",
|
|
18835
|
+
{
|
|
18836
|
+
class: "is-hidden-mobile",
|
|
18837
|
+
style: "padding-left:5px;",
|
|
18838
|
+
i18n: "raw json"
|
|
18839
|
+
},
|
|
18840
|
+
"raw json"
|
|
18841
|
+
]],
|
|
18842
|
+
{ click: (evt) => {
|
|
18843
|
+
evt.stopPropagation();
|
|
18844
|
+
gobj_send_event(gobj, "EV_OPEN_JSON", {}, gobj);
|
|
18845
|
+
} }
|
|
18846
|
+
]
|
|
18847
|
+
];
|
|
18848
|
+
let center_items = [[
|
|
18849
|
+
"div",
|
|
18850
|
+
{
|
|
18851
|
+
class: "GRAPH_FIND control has-icons-left",
|
|
18852
|
+
style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
|
|
18853
|
+
},
|
|
18854
|
+
[["input", {
|
|
18855
|
+
class: "GRAPH_FIND_INPUT input",
|
|
18856
|
+
type: "text",
|
|
18857
|
+
placeholder: t("search"),
|
|
18858
|
+
"data-i18n-placeholder": "search",
|
|
18859
|
+
"aria-label": t("search"),
|
|
18860
|
+
"data-i18n-aria-label": "search"
|
|
18861
|
+
}], [
|
|
18862
|
+
"span",
|
|
18863
|
+
{ class: "icon is-left" },
|
|
18864
|
+
[["i", { class: "yi-magnifying-glass" }]]
|
|
18865
|
+
]],
|
|
18866
|
+
{ input: (evt) => {
|
|
18867
|
+
evt.stopPropagation();
|
|
18868
|
+
gobj_send_event(gobj, "EV_FIND_NODES", { text: evt.target.value.trim() }, gobj);
|
|
18869
|
+
} }
|
|
18870
|
+
], [
|
|
18871
|
+
"div",
|
|
18872
|
+
{
|
|
18873
|
+
class: "GRAPH_FIND_RESULT is-hidden is-flex is-align-items-center",
|
|
18874
|
+
style: "gap:.3rem; margin-right:.5rem; font-size:.85rem;"
|
|
18875
|
+
},
|
|
18876
|
+
[[
|
|
18877
|
+
"span",
|
|
18878
|
+
{ class: "GRAPH_FIND_COUNT" },
|
|
18879
|
+
""
|
|
18880
|
+
], [
|
|
18881
|
+
"span",
|
|
18882
|
+
{ i18n: "matches" },
|
|
18883
|
+
"matches"
|
|
18884
|
+
]]
|
|
18885
|
+
]];
|
|
18530
18886
|
const $toolbar_header = yui_toolbar({}, [
|
|
18531
18887
|
[
|
|
18532
18888
|
"div",
|
|
18533
18889
|
{ class: "yui-horizontal-toolbar-section left" },
|
|
18534
|
-
|
|
18535
|
-
[
|
|
18536
|
-
"span",
|
|
18537
|
-
{
|
|
18538
|
-
class: "GRAPH_LAYOUT_LABEL is-hidden-mobile",
|
|
18539
|
-
style: "padding-right:5px;",
|
|
18540
|
-
i18n: "layout"
|
|
18541
|
-
},
|
|
18542
|
-
"layout"
|
|
18543
|
-
],
|
|
18544
|
-
[
|
|
18545
|
-
"div",
|
|
18546
|
-
{ class: "select" },
|
|
18547
|
-
[["select", { class: "GRAPH_LAYOUT_SELECT" }]],
|
|
18548
|
-
{ change: (evt) => {
|
|
18549
|
-
evt.stopPropagation();
|
|
18550
|
-
gobj_send_event(gobj, "EV_SET_LAYOUT", { layout: evt.target.value }, gobj);
|
|
18551
|
-
} }
|
|
18552
|
-
],
|
|
18553
|
-
[
|
|
18554
|
-
"span",
|
|
18555
|
-
{
|
|
18556
|
-
class: "GRAPH_MODE_LABEL is-hidden-mobile",
|
|
18557
|
-
style: "padding-left:10px; padding-right:5px;",
|
|
18558
|
-
i18n: "operation mode"
|
|
18559
|
-
},
|
|
18560
|
-
"operation mode"
|
|
18561
|
-
],
|
|
18562
|
-
[
|
|
18563
|
-
"div",
|
|
18564
|
-
{ class: "select" },
|
|
18565
|
-
[[
|
|
18566
|
-
"select",
|
|
18567
|
-
{ class: "GRAPH_MODE_SELECT" },
|
|
18568
|
-
modes.map((item) => [
|
|
18569
|
-
"option",
|
|
18570
|
-
{},
|
|
18571
|
-
item
|
|
18572
|
-
])
|
|
18573
|
-
]],
|
|
18574
|
-
{ change: (evt) => {
|
|
18575
|
-
evt.stopPropagation();
|
|
18576
|
-
gobj_send_event(gobj, "EV_SET_OPERATION_MODE", { operation_mode: evt.target.value }, gobj);
|
|
18577
|
-
} }
|
|
18578
|
-
],
|
|
18579
|
-
[
|
|
18580
|
-
"button",
|
|
18581
|
-
{ class: "GRAPH_REFRESH button" },
|
|
18582
|
-
[["i", { class: "yi-arrows-rotate" }], [
|
|
18583
|
-
"span",
|
|
18584
|
-
{
|
|
18585
|
-
class: "is-hidden-mobile",
|
|
18586
|
-
style: "padding-left:5px;",
|
|
18587
|
-
i18n: "refresh"
|
|
18588
|
-
},
|
|
18589
|
-
"refresh"
|
|
18590
|
-
]],
|
|
18591
|
-
{ click: (evt) => {
|
|
18592
|
-
evt.stopPropagation();
|
|
18593
|
-
gobj_send_event(gobj, "EV_REFRESH_TREEDB", { evt }, gobj);
|
|
18594
|
-
} }
|
|
18595
|
-
],
|
|
18596
|
-
[
|
|
18597
|
-
"button",
|
|
18598
|
-
{
|
|
18599
|
-
class: "button ml-2 TREEDB_JSON_BTN",
|
|
18600
|
-
title: t("raw json"),
|
|
18601
|
-
"aria-label": t("raw json"),
|
|
18602
|
-
"data-i18n-title": "raw json",
|
|
18603
|
-
"data-i18n-aria-label": "raw json"
|
|
18604
|
-
},
|
|
18605
|
-
[["i", { class: "yi-eye" }], [
|
|
18606
|
-
"span",
|
|
18607
|
-
{
|
|
18608
|
-
class: "is-hidden-mobile",
|
|
18609
|
-
style: "padding-left:5px;",
|
|
18610
|
-
i18n: "raw json"
|
|
18611
|
-
},
|
|
18612
|
-
"raw json"
|
|
18613
|
-
]],
|
|
18614
|
-
{ click: (evt) => {
|
|
18615
|
-
evt.stopPropagation();
|
|
18616
|
-
gobj_send_event(gobj, "EV_OPEN_JSON", {}, gobj);
|
|
18617
|
-
} }
|
|
18618
|
-
]
|
|
18619
|
-
]
|
|
18890
|
+
left_items
|
|
18620
18891
|
],
|
|
18621
18892
|
[
|
|
18622
18893
|
"div",
|
|
18623
18894
|
{ class: "yui-horizontal-toolbar-section center" },
|
|
18624
|
-
|
|
18895
|
+
center_items
|
|
18625
18896
|
],
|
|
18626
18897
|
[
|
|
18627
18898
|
"div",
|
|
@@ -19553,6 +19824,33 @@ function ac_set_operation_mode$1(gobj, event, kw, src) {
|
|
|
19553
19824
|
* tree, which centres + highlights that topic's nodes (deferring
|
|
19554
19825
|
* until its data is loaded).
|
|
19555
19826
|
************************************************************/
|
|
19827
|
+
/************************************************************
|
|
19828
|
+
* Forward the find down to the graph child.
|
|
19829
|
+
************************************************************/
|
|
19830
|
+
function ac_find_nodes$1(gobj, event, kw, src) {
|
|
19831
|
+
let priv = gobj.priv;
|
|
19832
|
+
if (priv.gobj_nodes_tree) gobj_send_event(priv.gobj_nodes_tree, "EV_FIND_NODES", { text: kw && kw.text || "" }, gobj);
|
|
19833
|
+
return 0;
|
|
19834
|
+
}
|
|
19835
|
+
/************************************************************
|
|
19836
|
+
* How many nodes the term matched, from the graph child. Zero with a
|
|
19837
|
+
* term typed is an ANSWER and is shown; an empty box shows nothing.
|
|
19838
|
+
************************************************************/
|
|
19839
|
+
function ac_find_result(gobj, event, kw, src) {
|
|
19840
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
19841
|
+
if (!$container) return 0;
|
|
19842
|
+
let $result = $container.querySelector(".GRAPH_FIND_RESULT");
|
|
19843
|
+
let $count = $container.querySelector(".GRAPH_FIND_COUNT");
|
|
19844
|
+
if (!$result || !$count) return 0;
|
|
19845
|
+
if (!(kw && kw.term || "")) {
|
|
19846
|
+
$result.classList.add("is-hidden");
|
|
19847
|
+
$count.textContent = "";
|
|
19848
|
+
return 0;
|
|
19849
|
+
}
|
|
19850
|
+
$count.textContent = String(kw && kw.matches || 0);
|
|
19851
|
+
$result.classList.remove("is-hidden");
|
|
19852
|
+
return 0;
|
|
19853
|
+
}
|
|
19556
19854
|
function ac_set_focus_topic(gobj, event, kw, src) {
|
|
19557
19855
|
let priv = gobj.priv;
|
|
19558
19856
|
if (priv.gobj_nodes_tree) gobj_send_event(priv.gobj_nodes_tree, "EV_FOCUS_TOPIC", { topic: kw && kw.topic }, gobj);
|
|
@@ -19718,6 +20016,16 @@ function create_gclass$4(gclass_name) {
|
|
|
19718
20016
|
ac_set_focus_topic,
|
|
19719
20017
|
null
|
|
19720
20018
|
],
|
|
20019
|
+
[
|
|
20020
|
+
"EV_FIND_NODES",
|
|
20021
|
+
ac_find_nodes$1,
|
|
20022
|
+
null
|
|
20023
|
+
],
|
|
20024
|
+
[
|
|
20025
|
+
"EV_FIND_RESULT",
|
|
20026
|
+
ac_find_result,
|
|
20027
|
+
null
|
|
20028
|
+
],
|
|
19721
20029
|
[
|
|
19722
20030
|
"EV_SHOW",
|
|
19723
20031
|
ac_show$3,
|
|
@@ -19759,6 +20067,8 @@ function create_gclass$4(gclass_name) {
|
|
|
19759
20067
|
["EV_SET_LAYOUT", 0],
|
|
19760
20068
|
["EV_SET_OPERATION_MODE", 0],
|
|
19761
20069
|
["EV_SET_FOCUS_TOPIC", 0],
|
|
20070
|
+
["EV_FIND_NODES", 0],
|
|
20071
|
+
["EV_FIND_RESULT", 0],
|
|
19762
20072
|
["EV_OPERATION_MODE_CHANGED", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
19763
20073
|
["EV_RECORD_WRITTEN", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
19764
20074
|
["EV_SHOW", 0],
|
|
@@ -52424,7 +52734,8 @@ var PRIVATE_DATA$1 = {
|
|
|
52424
52734
|
_link_saved_styles: [],
|
|
52425
52735
|
_focus_topic: null,
|
|
52426
52736
|
_focus_ids: [],
|
|
52427
|
-
_pending_focus_topic: null
|
|
52737
|
+
_pending_focus_topic: null,
|
|
52738
|
+
_pending_find: null
|
|
52428
52739
|
};
|
|
52429
52740
|
var __gclass__$1 = null;
|
|
52430
52741
|
/******************************
|
|
@@ -53598,6 +53909,67 @@ function graph_focus_topic(gobj, topic) {
|
|
|
53598
53909
|
log_error(`${gobj_short_name(gobj)}: focus topic apply failed: ${e}`);
|
|
53599
53910
|
}
|
|
53600
53911
|
}
|
|
53912
|
+
/************************************************************
|
|
53913
|
+
* Find the nodes whose name, id or topic contains `term`, highlight
|
|
53914
|
+
* them with the same amber 'active' state the topic focus uses, and
|
|
53915
|
+
* centre the viewport on them. Returns how many matched, which is the
|
|
53916
|
+
* half the toolbar needs: a search that finds nothing must SAY so,
|
|
53917
|
+
* because a graph that did not move is also what a graph looks like
|
|
53918
|
+
* when the match is off-screen.
|
|
53919
|
+
*
|
|
53920
|
+
* It shares the highlight slot with graph_focus_topic on purpose —
|
|
53921
|
+
* two amber sets at once would say nothing about either. An empty
|
|
53922
|
+
* term clears it. Matching reads the node's LABEL and not only its
|
|
53923
|
+
* id: on a topic keyed by rowid or by a qualified path, the id is a
|
|
53924
|
+
* counter and the name a human knows is elsewhere (see node_label).
|
|
53925
|
+
************************************************************/
|
|
53926
|
+
function graph_find_nodes(gobj, term) {
|
|
53927
|
+
let priv = gobj.priv;
|
|
53928
|
+
let graph = priv.graph;
|
|
53929
|
+
if (!graph || !priv.graph_rendered) {
|
|
53930
|
+
priv._pending_find = term;
|
|
53931
|
+
return 0;
|
|
53932
|
+
}
|
|
53933
|
+
let data = {};
|
|
53934
|
+
try {
|
|
53935
|
+
data = graph.getData() || {};
|
|
53936
|
+
} catch (e) {
|
|
53937
|
+
log_error(`${gobj_short_name(gobj)}: graph.getData() failed: ${e}`);
|
|
53938
|
+
return 0;
|
|
53939
|
+
}
|
|
53940
|
+
let nodes = is_array(data.nodes) ? data.nodes : [];
|
|
53941
|
+
let states = {};
|
|
53942
|
+
for (let id of priv._focus_ids || []) states[id] = [];
|
|
53943
|
+
let ids = [];
|
|
53944
|
+
if (!empty_string(term)) {
|
|
53945
|
+
let needle = String(term).toLowerCase();
|
|
53946
|
+
for (let n of nodes) {
|
|
53947
|
+
if (!n || !n.data) continue;
|
|
53948
|
+
let record = n.data.record || {};
|
|
53949
|
+
let label = "";
|
|
53950
|
+
try {
|
|
53951
|
+
label = node_label(n.data.desc || {}, record) || "";
|
|
53952
|
+
} catch (e) {
|
|
53953
|
+
label = "";
|
|
53954
|
+
}
|
|
53955
|
+
if ([
|
|
53956
|
+
label,
|
|
53957
|
+
record.id,
|
|
53958
|
+
n.data.topic_name
|
|
53959
|
+
].filter((v) => typeof v === "string").join(" ").toLowerCase().includes(needle)) ids.push(n.id);
|
|
53960
|
+
}
|
|
53961
|
+
for (let id of ids) states[id] = ["active"];
|
|
53962
|
+
}
|
|
53963
|
+
priv._focus_ids = ids;
|
|
53964
|
+
priv._focus_topic = null;
|
|
53965
|
+
try {
|
|
53966
|
+
if (typeof graph.setElementState === "function") graph.setElementState(states);
|
|
53967
|
+
if (ids.length && typeof graph.focusElement === "function") graph.focusElement(ids);
|
|
53968
|
+
} catch (e) {
|
|
53969
|
+
log_error(`${gobj_short_name(gobj)}: find apply failed: ${e}`);
|
|
53970
|
+
}
|
|
53971
|
+
return ids.length;
|
|
53972
|
+
}
|
|
53601
53973
|
async function graph_zoom_in(gobj) {
|
|
53602
53974
|
let graph = gobj.priv.graph;
|
|
53603
53975
|
const z = graph.getZoom();
|
|
@@ -55892,6 +56264,11 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
55892
56264
|
priv._pending_focus_topic = null;
|
|
55893
56265
|
graph_focus_topic(gobj, ft);
|
|
55894
56266
|
}
|
|
56267
|
+
if (priv._pending_find !== null) {
|
|
56268
|
+
let term = priv._pending_find;
|
|
56269
|
+
priv._pending_find = null;
|
|
56270
|
+
publish_find_result(gobj, term, graph_find_nodes(gobj, term));
|
|
56271
|
+
}
|
|
55895
56272
|
});
|
|
55896
56273
|
});
|
|
55897
56274
|
});
|
|
@@ -56108,6 +56485,25 @@ function ac_focus_topic(gobj, event, kw, src) {
|
|
|
56108
56485
|
graph_focus_topic(gobj, kw && kw.topic);
|
|
56109
56486
|
return 0;
|
|
56110
56487
|
}
|
|
56488
|
+
/************************************************************
|
|
56489
|
+
* Tell whoever asked how many nodes the term matched. The count is
|
|
56490
|
+
* the answer to the question the box asks; without it "nothing moved"
|
|
56491
|
+
* and "nothing matched" look the same.
|
|
56492
|
+
************************************************************/
|
|
56493
|
+
function publish_find_result(gobj, term, matches) {
|
|
56494
|
+
gobj_publish_event(gobj, "EV_FIND_RESULT", {
|
|
56495
|
+
term,
|
|
56496
|
+
matches
|
|
56497
|
+
});
|
|
56498
|
+
}
|
|
56499
|
+
/************************************************************
|
|
56500
|
+
*
|
|
56501
|
+
************************************************************/
|
|
56502
|
+
function ac_find_nodes(gobj, event, kw, src) {
|
|
56503
|
+
let term = kw && kw.text || "";
|
|
56504
|
+
publish_find_result(gobj, term, graph_find_nodes(gobj, term));
|
|
56505
|
+
return 0;
|
|
56506
|
+
}
|
|
56111
56507
|
function ac_center(gobj, event, kw, src) {
|
|
56112
56508
|
graph_center(gobj);
|
|
56113
56509
|
return 0;
|
|
@@ -56409,6 +56805,11 @@ function create_gclass$1(gclass_name) {
|
|
|
56409
56805
|
ac_focus_topic,
|
|
56410
56806
|
null
|
|
56411
56807
|
],
|
|
56808
|
+
[
|
|
56809
|
+
"EV_FIND_NODES",
|
|
56810
|
+
ac_find_nodes,
|
|
56811
|
+
null
|
|
56812
|
+
],
|
|
56412
56813
|
[
|
|
56413
56814
|
"EV_CENTER",
|
|
56414
56815
|
ac_center,
|
|
@@ -56492,6 +56893,8 @@ function create_gclass$1(gclass_name) {
|
|
|
56492
56893
|
["EV_ZOOM_RESET", 0],
|
|
56493
56894
|
["EV_AUTO_FIT", 0],
|
|
56494
56895
|
["EV_FOCUS_TOPIC", 0],
|
|
56896
|
+
["EV_FIND_NODES", 0],
|
|
56897
|
+
["EV_FIND_RESULT", event_flag_t.EVF_OUTPUT_EVENT],
|
|
56495
56898
|
["EV_CENTER", 0],
|
|
56496
56899
|
["EV_FULLSCREEN", 0],
|
|
56497
56900
|
["EV_SET_LAYOUT", 0],
|