@yuneta/gobj-ui 7.23.53 → 7.23.55
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 +128 -13
- package/dist/gobj-ui.es.js +128 -13
- package/package.json +1 -1
- package/src/c_yui_form.js +49 -1
- package/src/c_yui_treedb_topic_with_form.js +148 -17
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -6356,6 +6356,7 @@ var attrs_table$16 = [
|
|
|
6356
6356
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "pkey", 0, "id", "Primary key field name, used by form_mode"),
|
|
6357
6357
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "topic_name", 0, "", "Treedb topic name: labels use the i18n cascade '<topic>.<col>' -> '<col>' -> header (like table headers)"),
|
|
6358
6358
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "editable", 0, false, "Default is editable, set false to readonly"),
|
|
6359
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "readonly", 0, false, "Show EVERY field read-only, whatever its schema says: a record being LOOKED at, not edited. Independent of `editable`, which drives the TABLE rendering; this one drives the FORM"),
|
|
6359
6360
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "selectable", 0, true, "Rows selectable with 'click' (BAD with editable=true)"),
|
|
6360
6361
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "with_checkbox", 0, false, "Show a first column with checkbox to select rows"),
|
|
6361
6362
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "with_rownum", 0, false, "Print first column with row number"),
|
|
@@ -6759,7 +6760,7 @@ function build_form_field_conf(gobj, field_desc) {
|
|
|
6759
6760
|
placeholder: "",
|
|
6760
6761
|
options: [],
|
|
6761
6762
|
extras: {},
|
|
6762
|
-
readonly: !field_desc.is_writable,
|
|
6763
|
+
readonly: (0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "readonly") || !field_desc.is_writable,
|
|
6763
6764
|
required: field_desc.is_required,
|
|
6764
6765
|
hidden: field_desc.is_hidden,
|
|
6765
6766
|
default_value: field_desc.default_value
|
|
@@ -7514,10 +7515,41 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
|
|
|
7514
7515
|
$extend.dataset.form_tag = tag;
|
|
7515
7516
|
$extend.dataset.form_input_type = inputType;
|
|
7516
7517
|
$extend.classList.add("yui-form-data-input");
|
|
7518
|
+
apply_readonly_to_control(readonly, tag, $extend);
|
|
7517
7519
|
}
|
|
7518
7520
|
return $element;
|
|
7519
7521
|
}
|
|
7520
7522
|
/******************************************************************
|
|
7523
|
+
* `readonly` is an attribute of a TEXT control and of nothing else.
|
|
7524
|
+
*
|
|
7525
|
+
* A `<select>` ignores it. So does a checkbox, and so does a radio:
|
|
7526
|
+
* the browser accepts the attribute, stores it, and lets the reader
|
|
7527
|
+
* change the value anyway. Only `disabled` stops them, and tom-select
|
|
7528
|
+
* is a widget of its own that has to be told through its API.
|
|
7529
|
+
*
|
|
7530
|
+
* Which is why a col that is not `writable` used to render an
|
|
7531
|
+
* EDITABLE select: the field was built read-only, correctly, and the
|
|
7532
|
+
* three controls that cannot be read-only said nothing about it.
|
|
7533
|
+
*
|
|
7534
|
+
* `disabled` is safe here: the record is collected by reading each
|
|
7535
|
+
* marked control's value, never by submitting the form, so a disabled
|
|
7536
|
+
* control is still read -- unlike in a native submit, where it would
|
|
7537
|
+
* be dropped.
|
|
7538
|
+
******************************************************************/
|
|
7539
|
+
function apply_readonly_to_control(readonly, tag, $extend) {
|
|
7540
|
+
if (!readonly) return;
|
|
7541
|
+
switch (tag) {
|
|
7542
|
+
case "select":
|
|
7543
|
+
case "checkbox":
|
|
7544
|
+
case "radio":
|
|
7545
|
+
$extend.setAttribute("disabled", "disabled");
|
|
7546
|
+
break;
|
|
7547
|
+
case "select2":
|
|
7548
|
+
$extend.setAttribute("disabled", "disabled");
|
|
7549
|
+
if ($extend.tom_select) $extend.tom_select.disable();
|
|
7550
|
+
}
|
|
7551
|
+
}
|
|
7552
|
+
/******************************************************************
|
|
7521
7553
|
* Create coordinates
|
|
7522
7554
|
******************************************************************/
|
|
7523
7555
|
function create_coordinates(gobj, attrs) {
|
|
@@ -24126,6 +24158,13 @@ function create_tabulator(gobj) {
|
|
|
24126
24158
|
tabulator.on("dataFiltered", function(filters, rows) {
|
|
24127
24159
|
update_rowcount(Array.isArray(rows) ? rows.length : void 0);
|
|
24128
24160
|
});
|
|
24161
|
+
tabulator.on("rowClick", function(e, row) {
|
|
24162
|
+
if ((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "editable")) return;
|
|
24163
|
+
let $cell = e.target ? e.target.closest(".tabulator-cell") : null;
|
|
24164
|
+
let field = $cell ? $cell.getAttribute("tabulator-field") : null;
|
|
24165
|
+
if (field && cell_has_its_own_action(gobj, field)) return;
|
|
24166
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SHOW_RECORD", { index: row.getPosition() }, gobj);
|
|
24167
|
+
});
|
|
24129
24168
|
tabulator.on("rowSelected", function(row) {
|
|
24130
24169
|
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SELECT_ROWS", { rows: [row.getData()] }, gobj);
|
|
24131
24170
|
});
|
|
@@ -24301,10 +24340,25 @@ function transform__treedb_value_2_table_value(gobj, col, value, row, field) {
|
|
|
24301
24340
|
return value;
|
|
24302
24341
|
}
|
|
24303
24342
|
/************************************************************
|
|
24304
|
-
* Build the form template from desc.cols:
|
|
24305
|
-
*
|
|
24306
|
-
*
|
|
24307
|
-
*
|
|
24343
|
+
* Build the form template from desc.cols: EVERY field of the
|
|
24344
|
+
* record, the ones that cannot be written included.
|
|
24345
|
+
*
|
|
24346
|
+
* They used to be dropped, and a record was then shown as the
|
|
24347
|
+
* handful of its fields somebody may type: an asset opened as
|
|
24348
|
+
* its id alone, with its type, its size, its date and where it
|
|
24349
|
+
* came from -- everything a person opens an asset to read --
|
|
24350
|
+
* nowhere on screen. What a form is for is READING a record;
|
|
24351
|
+
* writing it is one of the two things you can do next.
|
|
24352
|
+
*
|
|
24353
|
+
* C_YUI_FORM renders a col that is not `writable` read-only on
|
|
24354
|
+
* its own (`build_form_field_conf`), so this is the whole of
|
|
24355
|
+
* it. What must NOT follow is sending them back:
|
|
24356
|
+
* `transform__form_record_2_treedb_record()` drops them, and
|
|
24357
|
+
* the reason is written there.
|
|
24358
|
+
*
|
|
24359
|
+
* Still out: hooks (a hook is not a field of the record, it is
|
|
24360
|
+
* the children hanging off it), hidden cols, and the `_`
|
|
24361
|
+
* scaffolding the table adds.
|
|
24308
24362
|
************************************************************/
|
|
24309
24363
|
function build_form_template(gobj) {
|
|
24310
24364
|
let desc = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "desc");
|
|
@@ -24314,7 +24368,6 @@ function build_form_template(gobj) {
|
|
|
24314
24368
|
const field_desc = (0, _yuneta_gobj_js.treedb_get_field_desc)(col);
|
|
24315
24369
|
if (field_desc.is_hidden) continue;
|
|
24316
24370
|
if (field_desc.type === "hook") continue;
|
|
24317
|
-
if (!field_desc.is_writable && field_desc.type !== "fkey" && col.id !== desc.pkey) continue;
|
|
24318
24371
|
template.push(col);
|
|
24319
24372
|
}
|
|
24320
24373
|
return template;
|
|
@@ -24362,6 +24415,8 @@ function open_form_dialog(gobj, mode, record) {
|
|
|
24362
24415
|
let rid = record ? String(record[pkey] ?? "") : "";
|
|
24363
24416
|
title = (0, i18next.t)(topic_name) + ((0, _yuneta_gobj_js.empty_string)(rid) ? "" : " — " + rid);
|
|
24364
24417
|
}
|
|
24418
|
+
let view_only = mode === "view";
|
|
24419
|
+
let form_mode = view_only ? "update" : mode;
|
|
24365
24420
|
let $body = (0, _yuneta_gobj_js.createElement2)([
|
|
24366
24421
|
"div",
|
|
24367
24422
|
{
|
|
@@ -24375,12 +24430,13 @@ function open_form_dialog(gobj, mode, record) {
|
|
|
24375
24430
|
template: build_form_template(gobj),
|
|
24376
24431
|
record,
|
|
24377
24432
|
fkey_options: build_fkey_options(gobj),
|
|
24378
|
-
form_mode
|
|
24379
|
-
|
|
24433
|
+
form_mode,
|
|
24434
|
+
readonly: view_only,
|
|
24435
|
+
...(view_only ? READONLY_FORM_TOOLBAR : form_plan.form_toolbar) ? { toolbar: view_only ? READONLY_FORM_TOOLBAR.slice() : form_plan.form_toolbar } : {},
|
|
24380
24436
|
render_mode: "edit",
|
|
24381
24437
|
pkey: desc.pkey || "id",
|
|
24382
24438
|
topic_name,
|
|
24383
|
-
editable: !form_plan.readonly,
|
|
24439
|
+
editable: !form_plan.readonly && !view_only,
|
|
24384
24440
|
$parent: $body
|
|
24385
24441
|
}, gobj);
|
|
24386
24442
|
priv.form = form;
|
|
@@ -24665,6 +24721,39 @@ function show_edit_form(gobj, row, index) {
|
|
|
24665
24721
|
open_form_dialog(gobj, pkey_is_rowid(gobj) ? "create" : "update", row);
|
|
24666
24722
|
}
|
|
24667
24723
|
/************************************************************
|
|
24724
|
+
* Does a click on this column already mean something else?
|
|
24725
|
+
*
|
|
24726
|
+
* The `_` columns are the table's own scaffolding (the selection
|
|
24727
|
+
* checkbox, the Op buttons); a hook opens its children and a col
|
|
24728
|
+
* holding a json document opens it in a viewer. Anything else is
|
|
24729
|
+
* plain data, and a click on it means "show me this record".
|
|
24730
|
+
************************************************************/
|
|
24731
|
+
var CELL_WITH_ACTION = [
|
|
24732
|
+
"hook",
|
|
24733
|
+
"object",
|
|
24734
|
+
"dict",
|
|
24735
|
+
"template",
|
|
24736
|
+
"array",
|
|
24737
|
+
"list",
|
|
24738
|
+
"coordinates",
|
|
24739
|
+
"blob",
|
|
24740
|
+
"gbuffer"
|
|
24741
|
+
];
|
|
24742
|
+
function cell_has_its_own_action(gobj, field) {
|
|
24743
|
+
if (!field || field.charAt(0) === "_") return true;
|
|
24744
|
+
let col = get_schema_col(gobj, field);
|
|
24745
|
+
if (!col) return false;
|
|
24746
|
+
const field_desc = (0, _yuneta_gobj_js.treedb_get_field_desc)(col);
|
|
24747
|
+
return CELL_WITH_ACTION.includes(field_desc.type) || CELL_WITH_ACTION.includes(field_desc.real_type);
|
|
24748
|
+
}
|
|
24749
|
+
/************************************************************
|
|
24750
|
+
* Show a record to be READ: every field, none of them editable.
|
|
24751
|
+
* What a row click opens while the table is not in edition mode.
|
|
24752
|
+
************************************************************/
|
|
24753
|
+
function show_view_form(gobj, row) {
|
|
24754
|
+
open_form_dialog(gobj, "view", row);
|
|
24755
|
+
}
|
|
24756
|
+
/************************************************************
|
|
24668
24757
|
* Show the edit "create" form to a new record
|
|
24669
24758
|
* internally called from the top toolbar +New button
|
|
24670
24759
|
************************************************************/
|
|
@@ -24687,14 +24776,16 @@ function get_schema_col(gobj, id) {
|
|
|
24687
24776
|
* operation: "create" "update"
|
|
24688
24777
|
************************************************************/
|
|
24689
24778
|
function transform__form_record_2_treedb_record(gobj, kw, operation) {
|
|
24779
|
+
let pkey = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "desc").pkey || "id";
|
|
24690
24780
|
let row = {};
|
|
24691
24781
|
for (let field_name of Object.keys(kw)) {
|
|
24692
24782
|
if ((0, _yuneta_gobj_js.empty_string)(field_name)) continue;
|
|
24693
24783
|
let col = get_schema_col(gobj, field_name);
|
|
24694
|
-
if (col)
|
|
24695
|
-
|
|
24696
|
-
|
|
24697
|
-
|
|
24784
|
+
if (!col) continue;
|
|
24785
|
+
const field_desc = (0, _yuneta_gobj_js.treedb_get_field_desc)(col);
|
|
24786
|
+
if (!field_desc.is_writable && field_desc.type !== "fkey" && col.id !== pkey) continue;
|
|
24787
|
+
let value = kw[field_name];
|
|
24788
|
+
row[field_name] = transform__form_value_2_treedb_value(gobj, col, value, operation);
|
|
24698
24789
|
}
|
|
24699
24790
|
return row;
|
|
24700
24791
|
}
|
|
@@ -25593,6 +25684,24 @@ function ac_open_columns(gobj, event, kw, src) {
|
|
|
25593
25684
|
return 0;
|
|
25594
25685
|
}
|
|
25595
25686
|
/************************************************************
|
|
25687
|
+
* A row was clicked outside edition mode: open the record to be read.
|
|
25688
|
+
************************************************************/
|
|
25689
|
+
function ac_show_record(gobj, event, kw, src) {
|
|
25690
|
+
let tabulator = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "tabulator");
|
|
25691
|
+
let index = kw ? kw.index : void 0;
|
|
25692
|
+
if (!tabulator || typeof index !== "number") {
|
|
25693
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no row ${index} to show`);
|
|
25694
|
+
return -1;
|
|
25695
|
+
}
|
|
25696
|
+
let row = tabulator.getRowFromPosition(index);
|
|
25697
|
+
if (!row) {
|
|
25698
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: row ${index} is gone`);
|
|
25699
|
+
return -1;
|
|
25700
|
+
}
|
|
25701
|
+
show_view_form(gobj, row.getData());
|
|
25702
|
+
return 0;
|
|
25703
|
+
}
|
|
25704
|
+
/************************************************************
|
|
25596
25705
|
* The reader picked another page size: remember it, so coming back to
|
|
25597
25706
|
* this topic opens where they left it instead of at 200.
|
|
25598
25707
|
************************************************************/
|
|
@@ -25817,6 +25926,11 @@ function create_gclass$5(gclass_name) {
|
|
|
25817
25926
|
ac_page_size_changed,
|
|
25818
25927
|
null
|
|
25819
25928
|
],
|
|
25929
|
+
[
|
|
25930
|
+
"EV_SHOW_RECORD",
|
|
25931
|
+
ac_show_record,
|
|
25932
|
+
null
|
|
25933
|
+
],
|
|
25820
25934
|
[
|
|
25821
25935
|
"EV_TOGGLE_COLUMN",
|
|
25822
25936
|
ac_toggle_column,
|
|
@@ -25868,6 +25982,7 @@ function create_gclass$5(gclass_name) {
|
|
|
25868
25982
|
["EV_SEARCH", 0],
|
|
25869
25983
|
["EV_OPEN_COLUMNS", 0],
|
|
25870
25984
|
["EV_PAGE_SIZE_CHANGED", 0],
|
|
25985
|
+
["EV_SHOW_RECORD", 0],
|
|
25871
25986
|
["EV_TOGGLE_COLUMN", 0],
|
|
25872
25987
|
["EV_EXPORT_TABLE", 0],
|
|
25873
25988
|
["EV_CREATE_RECORD", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT],
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -6351,6 +6351,7 @@ var attrs_table$16 = [
|
|
|
6351
6351
|
SDATA(data_type_t.DTP_STRING, "pkey", 0, "id", "Primary key field name, used by form_mode"),
|
|
6352
6352
|
SDATA(data_type_t.DTP_STRING, "topic_name", 0, "", "Treedb topic name: labels use the i18n cascade '<topic>.<col>' -> '<col>' -> header (like table headers)"),
|
|
6353
6353
|
SDATA(data_type_t.DTP_BOOLEAN, "editable", 0, false, "Default is editable, set false to readonly"),
|
|
6354
|
+
SDATA(data_type_t.DTP_BOOLEAN, "readonly", 0, false, "Show EVERY field read-only, whatever its schema says: a record being LOOKED at, not edited. Independent of `editable`, which drives the TABLE rendering; this one drives the FORM"),
|
|
6354
6355
|
SDATA(data_type_t.DTP_BOOLEAN, "selectable", 0, true, "Rows selectable with 'click' (BAD with editable=true)"),
|
|
6355
6356
|
SDATA(data_type_t.DTP_BOOLEAN, "with_checkbox", 0, false, "Show a first column with checkbox to select rows"),
|
|
6356
6357
|
SDATA(data_type_t.DTP_BOOLEAN, "with_rownum", 0, false, "Print first column with row number"),
|
|
@@ -6754,7 +6755,7 @@ function build_form_field_conf(gobj, field_desc) {
|
|
|
6754
6755
|
placeholder: "",
|
|
6755
6756
|
options: [],
|
|
6756
6757
|
extras: {},
|
|
6757
|
-
readonly: !field_desc.is_writable,
|
|
6758
|
+
readonly: gobj_read_bool_attr(gobj, "readonly") || !field_desc.is_writable,
|
|
6758
6759
|
required: field_desc.is_required,
|
|
6759
6760
|
hidden: field_desc.is_hidden,
|
|
6760
6761
|
default_value: field_desc.default_value
|
|
@@ -7509,10 +7510,41 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
|
|
|
7509
7510
|
$extend.dataset.form_tag = tag;
|
|
7510
7511
|
$extend.dataset.form_input_type = inputType;
|
|
7511
7512
|
$extend.classList.add("yui-form-data-input");
|
|
7513
|
+
apply_readonly_to_control(readonly, tag, $extend);
|
|
7512
7514
|
}
|
|
7513
7515
|
return $element;
|
|
7514
7516
|
}
|
|
7515
7517
|
/******************************************************************
|
|
7518
|
+
* `readonly` is an attribute of a TEXT control and of nothing else.
|
|
7519
|
+
*
|
|
7520
|
+
* A `<select>` ignores it. So does a checkbox, and so does a radio:
|
|
7521
|
+
* the browser accepts the attribute, stores it, and lets the reader
|
|
7522
|
+
* change the value anyway. Only `disabled` stops them, and tom-select
|
|
7523
|
+
* is a widget of its own that has to be told through its API.
|
|
7524
|
+
*
|
|
7525
|
+
* Which is why a col that is not `writable` used to render an
|
|
7526
|
+
* EDITABLE select: the field was built read-only, correctly, and the
|
|
7527
|
+
* three controls that cannot be read-only said nothing about it.
|
|
7528
|
+
*
|
|
7529
|
+
* `disabled` is safe here: the record is collected by reading each
|
|
7530
|
+
* marked control's value, never by submitting the form, so a disabled
|
|
7531
|
+
* control is still read -- unlike in a native submit, where it would
|
|
7532
|
+
* be dropped.
|
|
7533
|
+
******************************************************************/
|
|
7534
|
+
function apply_readonly_to_control(readonly, tag, $extend) {
|
|
7535
|
+
if (!readonly) return;
|
|
7536
|
+
switch (tag) {
|
|
7537
|
+
case "select":
|
|
7538
|
+
case "checkbox":
|
|
7539
|
+
case "radio":
|
|
7540
|
+
$extend.setAttribute("disabled", "disabled");
|
|
7541
|
+
break;
|
|
7542
|
+
case "select2":
|
|
7543
|
+
$extend.setAttribute("disabled", "disabled");
|
|
7544
|
+
if ($extend.tom_select) $extend.tom_select.disable();
|
|
7545
|
+
}
|
|
7546
|
+
}
|
|
7547
|
+
/******************************************************************
|
|
7516
7548
|
* Create coordinates
|
|
7517
7549
|
******************************************************************/
|
|
7518
7550
|
function create_coordinates(gobj, attrs) {
|
|
@@ -24121,6 +24153,13 @@ function create_tabulator(gobj) {
|
|
|
24121
24153
|
tabulator.on("dataFiltered", function(filters, rows) {
|
|
24122
24154
|
update_rowcount(Array.isArray(rows) ? rows.length : void 0);
|
|
24123
24155
|
});
|
|
24156
|
+
tabulator.on("rowClick", function(e, row) {
|
|
24157
|
+
if (gobj_read_bool_attr(gobj, "editable")) return;
|
|
24158
|
+
let $cell = e.target ? e.target.closest(".tabulator-cell") : null;
|
|
24159
|
+
let field = $cell ? $cell.getAttribute("tabulator-field") : null;
|
|
24160
|
+
if (field && cell_has_its_own_action(gobj, field)) return;
|
|
24161
|
+
gobj_send_event(gobj, "EV_SHOW_RECORD", { index: row.getPosition() }, gobj);
|
|
24162
|
+
});
|
|
24124
24163
|
tabulator.on("rowSelected", function(row) {
|
|
24125
24164
|
gobj_send_event(gobj, "EV_SELECT_ROWS", { rows: [row.getData()] }, gobj);
|
|
24126
24165
|
});
|
|
@@ -24296,10 +24335,25 @@ function transform__treedb_value_2_table_value(gobj, col, value, row, field) {
|
|
|
24296
24335
|
return value;
|
|
24297
24336
|
}
|
|
24298
24337
|
/************************************************************
|
|
24299
|
-
* Build the form template from desc.cols:
|
|
24300
|
-
*
|
|
24301
|
-
*
|
|
24302
|
-
*
|
|
24338
|
+
* Build the form template from desc.cols: EVERY field of the
|
|
24339
|
+
* record, the ones that cannot be written included.
|
|
24340
|
+
*
|
|
24341
|
+
* They used to be dropped, and a record was then shown as the
|
|
24342
|
+
* handful of its fields somebody may type: an asset opened as
|
|
24343
|
+
* its id alone, with its type, its size, its date and where it
|
|
24344
|
+
* came from -- everything a person opens an asset to read --
|
|
24345
|
+
* nowhere on screen. What a form is for is READING a record;
|
|
24346
|
+
* writing it is one of the two things you can do next.
|
|
24347
|
+
*
|
|
24348
|
+
* C_YUI_FORM renders a col that is not `writable` read-only on
|
|
24349
|
+
* its own (`build_form_field_conf`), so this is the whole of
|
|
24350
|
+
* it. What must NOT follow is sending them back:
|
|
24351
|
+
* `transform__form_record_2_treedb_record()` drops them, and
|
|
24352
|
+
* the reason is written there.
|
|
24353
|
+
*
|
|
24354
|
+
* Still out: hooks (a hook is not a field of the record, it is
|
|
24355
|
+
* the children hanging off it), hidden cols, and the `_`
|
|
24356
|
+
* scaffolding the table adds.
|
|
24303
24357
|
************************************************************/
|
|
24304
24358
|
function build_form_template(gobj) {
|
|
24305
24359
|
let desc = gobj_read_attr(gobj, "desc");
|
|
@@ -24309,7 +24363,6 @@ function build_form_template(gobj) {
|
|
|
24309
24363
|
const field_desc = treedb_get_field_desc(col);
|
|
24310
24364
|
if (field_desc.is_hidden) continue;
|
|
24311
24365
|
if (field_desc.type === "hook") continue;
|
|
24312
|
-
if (!field_desc.is_writable && field_desc.type !== "fkey" && col.id !== desc.pkey) continue;
|
|
24313
24366
|
template.push(col);
|
|
24314
24367
|
}
|
|
24315
24368
|
return template;
|
|
@@ -24357,6 +24410,8 @@ function open_form_dialog(gobj, mode, record) {
|
|
|
24357
24410
|
let rid = record ? String(record[pkey] ?? "") : "";
|
|
24358
24411
|
title = t(topic_name) + (empty_string(rid) ? "" : " — " + rid);
|
|
24359
24412
|
}
|
|
24413
|
+
let view_only = mode === "view";
|
|
24414
|
+
let form_mode = view_only ? "update" : mode;
|
|
24360
24415
|
let $body = createElement2([
|
|
24361
24416
|
"div",
|
|
24362
24417
|
{
|
|
@@ -24370,12 +24425,13 @@ function open_form_dialog(gobj, mode, record) {
|
|
|
24370
24425
|
template: build_form_template(gobj),
|
|
24371
24426
|
record,
|
|
24372
24427
|
fkey_options: build_fkey_options(gobj),
|
|
24373
|
-
form_mode
|
|
24374
|
-
|
|
24428
|
+
form_mode,
|
|
24429
|
+
readonly: view_only,
|
|
24430
|
+
...(view_only ? READONLY_FORM_TOOLBAR : form_plan.form_toolbar) ? { toolbar: view_only ? READONLY_FORM_TOOLBAR.slice() : form_plan.form_toolbar } : {},
|
|
24375
24431
|
render_mode: "edit",
|
|
24376
24432
|
pkey: desc.pkey || "id",
|
|
24377
24433
|
topic_name,
|
|
24378
|
-
editable: !form_plan.readonly,
|
|
24434
|
+
editable: !form_plan.readonly && !view_only,
|
|
24379
24435
|
$parent: $body
|
|
24380
24436
|
}, gobj);
|
|
24381
24437
|
priv.form = form;
|
|
@@ -24660,6 +24716,39 @@ function show_edit_form(gobj, row, index) {
|
|
|
24660
24716
|
open_form_dialog(gobj, pkey_is_rowid(gobj) ? "create" : "update", row);
|
|
24661
24717
|
}
|
|
24662
24718
|
/************************************************************
|
|
24719
|
+
* Does a click on this column already mean something else?
|
|
24720
|
+
*
|
|
24721
|
+
* The `_` columns are the table's own scaffolding (the selection
|
|
24722
|
+
* checkbox, the Op buttons); a hook opens its children and a col
|
|
24723
|
+
* holding a json document opens it in a viewer. Anything else is
|
|
24724
|
+
* plain data, and a click on it means "show me this record".
|
|
24725
|
+
************************************************************/
|
|
24726
|
+
var CELL_WITH_ACTION = [
|
|
24727
|
+
"hook",
|
|
24728
|
+
"object",
|
|
24729
|
+
"dict",
|
|
24730
|
+
"template",
|
|
24731
|
+
"array",
|
|
24732
|
+
"list",
|
|
24733
|
+
"coordinates",
|
|
24734
|
+
"blob",
|
|
24735
|
+
"gbuffer"
|
|
24736
|
+
];
|
|
24737
|
+
function cell_has_its_own_action(gobj, field) {
|
|
24738
|
+
if (!field || field.charAt(0) === "_") return true;
|
|
24739
|
+
let col = get_schema_col(gobj, field);
|
|
24740
|
+
if (!col) return false;
|
|
24741
|
+
const field_desc = treedb_get_field_desc(col);
|
|
24742
|
+
return CELL_WITH_ACTION.includes(field_desc.type) || CELL_WITH_ACTION.includes(field_desc.real_type);
|
|
24743
|
+
}
|
|
24744
|
+
/************************************************************
|
|
24745
|
+
* Show a record to be READ: every field, none of them editable.
|
|
24746
|
+
* What a row click opens while the table is not in edition mode.
|
|
24747
|
+
************************************************************/
|
|
24748
|
+
function show_view_form(gobj, row) {
|
|
24749
|
+
open_form_dialog(gobj, "view", row);
|
|
24750
|
+
}
|
|
24751
|
+
/************************************************************
|
|
24663
24752
|
* Show the edit "create" form to a new record
|
|
24664
24753
|
* internally called from the top toolbar +New button
|
|
24665
24754
|
************************************************************/
|
|
@@ -24682,14 +24771,16 @@ function get_schema_col(gobj, id) {
|
|
|
24682
24771
|
* operation: "create" "update"
|
|
24683
24772
|
************************************************************/
|
|
24684
24773
|
function transform__form_record_2_treedb_record(gobj, kw, operation) {
|
|
24774
|
+
let pkey = gobj_read_attr(gobj, "desc").pkey || "id";
|
|
24685
24775
|
let row = {};
|
|
24686
24776
|
for (let field_name of Object.keys(kw)) {
|
|
24687
24777
|
if (empty_string(field_name)) continue;
|
|
24688
24778
|
let col = get_schema_col(gobj, field_name);
|
|
24689
|
-
if (col)
|
|
24690
|
-
|
|
24691
|
-
|
|
24692
|
-
|
|
24779
|
+
if (!col) continue;
|
|
24780
|
+
const field_desc = treedb_get_field_desc(col);
|
|
24781
|
+
if (!field_desc.is_writable && field_desc.type !== "fkey" && col.id !== pkey) continue;
|
|
24782
|
+
let value = kw[field_name];
|
|
24783
|
+
row[field_name] = transform__form_value_2_treedb_value(gobj, col, value, operation);
|
|
24693
24784
|
}
|
|
24694
24785
|
return row;
|
|
24695
24786
|
}
|
|
@@ -25588,6 +25679,24 @@ function ac_open_columns(gobj, event, kw, src) {
|
|
|
25588
25679
|
return 0;
|
|
25589
25680
|
}
|
|
25590
25681
|
/************************************************************
|
|
25682
|
+
* A row was clicked outside edition mode: open the record to be read.
|
|
25683
|
+
************************************************************/
|
|
25684
|
+
function ac_show_record(gobj, event, kw, src) {
|
|
25685
|
+
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
25686
|
+
let index = kw ? kw.index : void 0;
|
|
25687
|
+
if (!tabulator || typeof index !== "number") {
|
|
25688
|
+
log_error(`${gobj_short_name(gobj)}: no row ${index} to show`);
|
|
25689
|
+
return -1;
|
|
25690
|
+
}
|
|
25691
|
+
let row = tabulator.getRowFromPosition(index);
|
|
25692
|
+
if (!row) {
|
|
25693
|
+
log_error(`${gobj_short_name(gobj)}: row ${index} is gone`);
|
|
25694
|
+
return -1;
|
|
25695
|
+
}
|
|
25696
|
+
show_view_form(gobj, row.getData());
|
|
25697
|
+
return 0;
|
|
25698
|
+
}
|
|
25699
|
+
/************************************************************
|
|
25591
25700
|
* The reader picked another page size: remember it, so coming back to
|
|
25592
25701
|
* this topic opens where they left it instead of at 200.
|
|
25593
25702
|
************************************************************/
|
|
@@ -25812,6 +25921,11 @@ function create_gclass$5(gclass_name) {
|
|
|
25812
25921
|
ac_page_size_changed,
|
|
25813
25922
|
null
|
|
25814
25923
|
],
|
|
25924
|
+
[
|
|
25925
|
+
"EV_SHOW_RECORD",
|
|
25926
|
+
ac_show_record,
|
|
25927
|
+
null
|
|
25928
|
+
],
|
|
25815
25929
|
[
|
|
25816
25930
|
"EV_TOGGLE_COLUMN",
|
|
25817
25931
|
ac_toggle_column,
|
|
@@ -25863,6 +25977,7 @@ function create_gclass$5(gclass_name) {
|
|
|
25863
25977
|
["EV_SEARCH", 0],
|
|
25864
25978
|
["EV_OPEN_COLUMNS", 0],
|
|
25865
25979
|
["EV_PAGE_SIZE_CHANGED", 0],
|
|
25980
|
+
["EV_SHOW_RECORD", 0],
|
|
25866
25981
|
["EV_TOGGLE_COLUMN", 0],
|
|
25867
25982
|
["EV_EXPORT_TABLE", 0],
|
|
25868
25983
|
["EV_CREATE_RECORD", event_flag_t.EVF_OUTPUT_EVENT],
|
package/package.json
CHANGED
package/src/c_yui_form.js
CHANGED
|
@@ -99,6 +99,7 @@ SDATA(data_type_t.DTP_STRING, "render_mode", 0, "exec", "'exec' interpre
|
|
|
99
99
|
SDATA(data_type_t.DTP_STRING, "pkey", 0, "id", "Primary key field name, used by form_mode"),
|
|
100
100
|
SDATA(data_type_t.DTP_STRING, "topic_name", 0, "", "Treedb topic name: labels use the i18n cascade '<topic>.<col>' -> '<col>' -> header (like table headers)"),
|
|
101
101
|
SDATA(data_type_t.DTP_BOOLEAN, "editable", 0, false, "Default is editable, set false to readonly"),
|
|
102
|
+
SDATA(data_type_t.DTP_BOOLEAN, "readonly", 0, false, "Show EVERY field read-only, whatever its schema says: a record being LOOKED at, not edited. Independent of `editable`, which drives the TABLE rendering; this one drives the FORM"),
|
|
102
103
|
SDATA(data_type_t.DTP_BOOLEAN, "selectable", 0, true, "Rows selectable with 'click' (BAD with editable=true)"),
|
|
103
104
|
SDATA(data_type_t.DTP_BOOLEAN, "with_checkbox", 0, false, "Show a first column with checkbox to select rows"),
|
|
104
105
|
SDATA(data_type_t.DTP_BOOLEAN, "with_rownum", 0, false, "Print first column with row number"),
|
|
@@ -586,7 +587,10 @@ function build_form_field_conf(gobj, field_desc)
|
|
|
586
587
|
|
|
587
588
|
options: [], // select,select2,radio options
|
|
588
589
|
extras: {}, // extra html input/textarea attributes
|
|
589
|
-
|
|
590
|
+
/* A form opened to LOOK at a record has no editable field, and
|
|
591
|
+
* that is a property of the opening, not of the schema: the same
|
|
592
|
+
* col is writable when the same form is opened to edit. */
|
|
593
|
+
readonly: gobj_read_bool_attr(gobj, "readonly") || !field_desc.is_writable,
|
|
590
594
|
required: field_desc.is_required,
|
|
591
595
|
hidden: field_desc.is_hidden,
|
|
592
596
|
default_value: field_desc.default_value,
|
|
@@ -1445,11 +1449,55 @@ function create_form_field(
|
|
|
1445
1449
|
$extend.dataset.form_tag = tag;
|
|
1446
1450
|
$extend.dataset.form_input_type = inputType;
|
|
1447
1451
|
$extend.classList.add('yui-form-data-input');
|
|
1452
|
+
|
|
1453
|
+
apply_readonly_to_control(readonly, tag, $extend);
|
|
1448
1454
|
}
|
|
1449
1455
|
|
|
1450
1456
|
return $element;
|
|
1451
1457
|
}
|
|
1452
1458
|
|
|
1459
|
+
/******************************************************************
|
|
1460
|
+
* `readonly` is an attribute of a TEXT control and of nothing else.
|
|
1461
|
+
*
|
|
1462
|
+
* A `<select>` ignores it. So does a checkbox, and so does a radio:
|
|
1463
|
+
* the browser accepts the attribute, stores it, and lets the reader
|
|
1464
|
+
* change the value anyway. Only `disabled` stops them, and tom-select
|
|
1465
|
+
* is a widget of its own that has to be told through its API.
|
|
1466
|
+
*
|
|
1467
|
+
* Which is why a col that is not `writable` used to render an
|
|
1468
|
+
* EDITABLE select: the field was built read-only, correctly, and the
|
|
1469
|
+
* three controls that cannot be read-only said nothing about it.
|
|
1470
|
+
*
|
|
1471
|
+
* `disabled` is safe here: the record is collected by reading each
|
|
1472
|
+
* marked control's value, never by submitting the form, so a disabled
|
|
1473
|
+
* control is still read -- unlike in a native submit, where it would
|
|
1474
|
+
* be dropped.
|
|
1475
|
+
******************************************************************/
|
|
1476
|
+
function apply_readonly_to_control(readonly, tag, $extend)
|
|
1477
|
+
{
|
|
1478
|
+
if(!readonly) {
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
switch(tag) {
|
|
1483
|
+
case 'select':
|
|
1484
|
+
case 'checkbox':
|
|
1485
|
+
case 'radio':
|
|
1486
|
+
$extend.setAttribute("disabled", "disabled");
|
|
1487
|
+
break;
|
|
1488
|
+
case 'select2':
|
|
1489
|
+
$extend.setAttribute("disabled", "disabled");
|
|
1490
|
+
if($extend.tom_select) {
|
|
1491
|
+
$extend.tom_select.disable();
|
|
1492
|
+
}
|
|
1493
|
+
break;
|
|
1494
|
+
default:
|
|
1495
|
+
/* A text control already carries `readonly`, which is the
|
|
1496
|
+
* better of the two: it stays selectable and copyable. */
|
|
1497
|
+
break;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1453
1501
|
|
|
1454
1502
|
/******************************************************************
|
|
1455
1503
|
* Create coordinates
|
|
@@ -91,7 +91,7 @@ import {row_matches} from "./yui_row_search.js";
|
|
|
91
91
|
|
|
92
92
|
import {t} from "i18next";
|
|
93
93
|
|
|
94
|
-
import {plan_treedb_writes} from "./treedb_write_plan.js";
|
|
94
|
+
import {plan_treedb_writes, READONLY_FORM_TOOLBAR} from "./treedb_write_plan.js";
|
|
95
95
|
import {delete_impact} from "./delete_impact.js";
|
|
96
96
|
|
|
97
97
|
import "./c_yui_treedb_topic_with_form.css";
|
|
@@ -1680,6 +1680,31 @@ function create_tabulator(gobj)
|
|
|
1680
1680
|
tabulator.on("dataFiltered", function(filters, rows) {
|
|
1681
1681
|
update_rowcount(Array.isArray(rows)? rows.length : undefined);
|
|
1682
1682
|
});
|
|
1683
|
+
/* A click on a row, while the table is NOT in edition mode, OPENS the
|
|
1684
|
+
* record to be read. It used to do nothing at all: selection is driven
|
|
1685
|
+
* by the checkbox column and editing by the pencil, so the biggest
|
|
1686
|
+
* target on screen was the one thing that answered nothing.
|
|
1687
|
+
*
|
|
1688
|
+
* Only outside edition mode: in it a click starts editing a cell, and
|
|
1689
|
+
* the pencil already opens the same record to be written.
|
|
1690
|
+
*
|
|
1691
|
+
* Cells that carry an action of their own are left alone -- a json
|
|
1692
|
+
* preview opens its viewer, a hook opens its children, the Op buttons
|
|
1693
|
+
* edit and delete -- and the question is asked of the SCHEMA rather
|
|
1694
|
+
* than of the markup, so a new formatter does not silently start
|
|
1695
|
+
* opening two things at once. */
|
|
1696
|
+
tabulator.on("rowClick", function(e, row) {
|
|
1697
|
+
if(gobj_read_bool_attr(gobj, "editable")) {
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
let $cell = e.target? e.target.closest(".tabulator-cell") : null;
|
|
1701
|
+
let field = $cell? $cell.getAttribute("tabulator-field") : null;
|
|
1702
|
+
if(field && cell_has_its_own_action(gobj, field)) {
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
gobj_send_event(gobj, "EV_SHOW_RECORD", {index: row.getPosition()}, gobj);
|
|
1706
|
+
});
|
|
1707
|
+
|
|
1683
1708
|
tabulator.on("rowSelected", function(row) {
|
|
1684
1709
|
gobj_send_event(gobj, "EV_SELECT_ROWS", {rows: [row.getData()]}, gobj);
|
|
1685
1710
|
});
|
|
@@ -1930,10 +1955,25 @@ function transform__treedb_value_2_table_value(gobj, col, value, row, field)
|
|
|
1930
1955
|
}
|
|
1931
1956
|
|
|
1932
1957
|
/************************************************************
|
|
1933
|
-
* Build the form template from desc.cols:
|
|
1934
|
-
*
|
|
1935
|
-
*
|
|
1936
|
-
*
|
|
1958
|
+
* Build the form template from desc.cols: EVERY field of the
|
|
1959
|
+
* record, the ones that cannot be written included.
|
|
1960
|
+
*
|
|
1961
|
+
* They used to be dropped, and a record was then shown as the
|
|
1962
|
+
* handful of its fields somebody may type: an asset opened as
|
|
1963
|
+
* its id alone, with its type, its size, its date and where it
|
|
1964
|
+
* came from -- everything a person opens an asset to read --
|
|
1965
|
+
* nowhere on screen. What a form is for is READING a record;
|
|
1966
|
+
* writing it is one of the two things you can do next.
|
|
1967
|
+
*
|
|
1968
|
+
* C_YUI_FORM renders a col that is not `writable` read-only on
|
|
1969
|
+
* its own (`build_form_field_conf`), so this is the whole of
|
|
1970
|
+
* it. What must NOT follow is sending them back:
|
|
1971
|
+
* `transform__form_record_2_treedb_record()` drops them, and
|
|
1972
|
+
* the reason is written there.
|
|
1973
|
+
*
|
|
1974
|
+
* Still out: hooks (a hook is not a field of the record, it is
|
|
1975
|
+
* the children hanging off it), hidden cols, and the `_`
|
|
1976
|
+
* scaffolding the table adds.
|
|
1937
1977
|
************************************************************/
|
|
1938
1978
|
function build_form_template(gobj)
|
|
1939
1979
|
{
|
|
@@ -1950,10 +1990,6 @@ function build_form_template(gobj)
|
|
|
1950
1990
|
if(field_desc.type === "hook") {
|
|
1951
1991
|
continue; // hooks don't appear in forms
|
|
1952
1992
|
}
|
|
1953
|
-
if(!field_desc.is_writable &&
|
|
1954
|
-
field_desc.type !== "fkey" && col.id !== desc.pkey) {
|
|
1955
|
-
continue;
|
|
1956
|
-
}
|
|
1957
1993
|
template.push(col);
|
|
1958
1994
|
}
|
|
1959
1995
|
return template;
|
|
@@ -2023,6 +2059,14 @@ function open_form_dialog(gobj, mode, record)
|
|
|
2023
2059
|
title = t(topic_name) + (empty_string(rid) ? "" : " — " + rid);
|
|
2024
2060
|
}
|
|
2025
2061
|
|
|
2062
|
+
/* "view" is an "update" that writes nothing: same title, same pkey
|
|
2063
|
+
* handling (readonly), every field read-only and the write half of
|
|
2064
|
+
* the toolbar gone. It is what a row click opens when the table is
|
|
2065
|
+
* NOT in edition mode -- reading a record is the ordinary thing to
|
|
2066
|
+
* want, and until now a click on a row did nothing at all. */
|
|
2067
|
+
let view_only = (mode === "view");
|
|
2068
|
+
let form_mode = view_only? "update" : mode;
|
|
2069
|
+
|
|
2026
2070
|
/* A flex column so the hosted form takes the dialog height: fields
|
|
2027
2071
|
* scroll internally and the form's bottom toolbar stays visible. */
|
|
2028
2072
|
let $body = createElement2(
|
|
@@ -2038,19 +2082,22 @@ function open_form_dialog(gobj, mode, record)
|
|
|
2038
2082
|
template: build_form_template(gobj),
|
|
2039
2083
|
record: record,
|
|
2040
2084
|
fkey_options: build_fkey_options(gobj),
|
|
2041
|
-
form_mode:
|
|
2085
|
+
form_mode: form_mode,
|
|
2086
|
+
readonly: view_only,
|
|
2042
2087
|
/* A read-only topic still OPENS its form -- looking at a record
|
|
2043
2088
|
* is the point of a replica -- with the cells not editable and
|
|
2044
2089
|
* the write half of the toolbar gone. A null plan leaves the
|
|
2045
2090
|
* form's own default alone. */
|
|
2046
|
-
...(
|
|
2091
|
+
...((view_only? READONLY_FORM_TOOLBAR : form_plan.form_toolbar)?
|
|
2092
|
+
{toolbar: view_only? READONLY_FORM_TOOLBAR.slice()
|
|
2093
|
+
: form_plan.form_toolbar} : {}),
|
|
2047
2094
|
/* Editing the raw topic record: structured cols
|
|
2048
2095
|
* (template / table / coordinates) are raw JSON editors,
|
|
2049
2096
|
* not interpreted into sub-widgets (the pre-merge behaviour). */
|
|
2050
2097
|
render_mode: "edit",
|
|
2051
2098
|
pkey: desc.pkey || "id",
|
|
2052
2099
|
topic_name: topic_name,
|
|
2053
|
-
editable: !form_plan.readonly,
|
|
2100
|
+
editable: !form_plan.readonly && !view_only,
|
|
2054
2101
|
$parent: $body
|
|
2055
2102
|
},
|
|
2056
2103
|
gobj
|
|
@@ -2446,6 +2493,42 @@ function show_edit_form(gobj, row, index)
|
|
|
2446
2493
|
open_form_dialog(gobj, mode, row);
|
|
2447
2494
|
}
|
|
2448
2495
|
|
|
2496
|
+
/************************************************************
|
|
2497
|
+
* Does a click on this column already mean something else?
|
|
2498
|
+
*
|
|
2499
|
+
* The `_` columns are the table's own scaffolding (the selection
|
|
2500
|
+
* checkbox, the Op buttons); a hook opens its children and a col
|
|
2501
|
+
* holding a json document opens it in a viewer. Anything else is
|
|
2502
|
+
* plain data, and a click on it means "show me this record".
|
|
2503
|
+
************************************************************/
|
|
2504
|
+
const CELL_WITH_ACTION = [
|
|
2505
|
+
"hook", "object", "dict", "template", "array", "list",
|
|
2506
|
+
"coordinates", "blob", "gbuffer"
|
|
2507
|
+
];
|
|
2508
|
+
|
|
2509
|
+
function cell_has_its_own_action(gobj, field)
|
|
2510
|
+
{
|
|
2511
|
+
if(!field || field.charAt(0) === '_') {
|
|
2512
|
+
return true;
|
|
2513
|
+
}
|
|
2514
|
+
let col = get_schema_col(gobj, field);
|
|
2515
|
+
if(!col) {
|
|
2516
|
+
return false;
|
|
2517
|
+
}
|
|
2518
|
+
const field_desc = treedb_get_field_desc(col);
|
|
2519
|
+
return CELL_WITH_ACTION.includes(field_desc.type) ||
|
|
2520
|
+
CELL_WITH_ACTION.includes(field_desc.real_type);
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
/************************************************************
|
|
2524
|
+
* Show a record to be READ: every field, none of them editable.
|
|
2525
|
+
* What a row click opens while the table is not in edition mode.
|
|
2526
|
+
************************************************************/
|
|
2527
|
+
function show_view_form(gobj, row)
|
|
2528
|
+
{
|
|
2529
|
+
open_form_dialog(gobj, "view", row);
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2449
2532
|
/************************************************************
|
|
2450
2533
|
* Show the edit "create" form to a new record
|
|
2451
2534
|
* internally called from the top toolbar +New button
|
|
@@ -2476,6 +2559,8 @@ function get_schema_col(gobj, id)
|
|
|
2476
2559
|
************************************************************/
|
|
2477
2560
|
function transform__form_record_2_treedb_record(gobj, kw, operation)
|
|
2478
2561
|
{
|
|
2562
|
+
let desc = gobj_read_attr(gobj, "desc");
|
|
2563
|
+
let pkey = desc.pkey || "id";
|
|
2479
2564
|
let row = {};
|
|
2480
2565
|
|
|
2481
2566
|
for(let field_name of Object.keys(kw)) {
|
|
@@ -2483,12 +2568,33 @@ function transform__form_record_2_treedb_record(gobj, kw, operation)
|
|
|
2483
2568
|
continue;
|
|
2484
2569
|
}
|
|
2485
2570
|
let col = get_schema_col(gobj, field_name);
|
|
2486
|
-
if(col) {
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2571
|
+
if(!col) {
|
|
2572
|
+
continue;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
/* The form SHOWS every field and sends back only what the topic
|
|
2576
|
+
* accepts: the writable cols, the fkeys (a link is edited by
|
|
2577
|
+
* linking) and the pkey, which is not written but is what
|
|
2578
|
+
* ADDRESSES the record.
|
|
2579
|
+
*
|
|
2580
|
+
* It matters because `treedb_update_node()` does not check
|
|
2581
|
+
* `writable` -- it writes any col it is handed -- so a read-only
|
|
2582
|
+
* field travelling back is written with whatever the form made of
|
|
2583
|
+
* it, and the fields that describe a record are exactly the ones
|
|
2584
|
+
* that do not survive a round trip through a widget: `t` is an
|
|
2585
|
+
* integer rendered as a date. Nothing would look wrong until the
|
|
2586
|
+
* stored timestamp had moved.
|
|
2587
|
+
*/
|
|
2588
|
+
const field_desc = treedb_get_field_desc(col);
|
|
2589
|
+
if(!field_desc.is_writable &&
|
|
2590
|
+
field_desc.type !== "fkey" && col.id !== pkey) {
|
|
2591
|
+
continue;
|
|
2491
2592
|
}
|
|
2593
|
+
|
|
2594
|
+
let value = kw[field_name];
|
|
2595
|
+
row[field_name] = transform__form_value_2_treedb_value(
|
|
2596
|
+
gobj, col, value, operation
|
|
2597
|
+
);
|
|
2492
2598
|
}
|
|
2493
2599
|
return row;
|
|
2494
2600
|
}
|
|
@@ -3773,6 +3879,29 @@ function ac_open_columns(gobj, event, kw, src)
|
|
|
3773
3879
|
return 0;
|
|
3774
3880
|
}
|
|
3775
3881
|
|
|
3882
|
+
/************************************************************
|
|
3883
|
+
* A row was clicked outside edition mode: open the record to be read.
|
|
3884
|
+
************************************************************/
|
|
3885
|
+
function ac_show_record(gobj, event, kw, src)
|
|
3886
|
+
{
|
|
3887
|
+
let tabulator = gobj_read_attr(gobj, "tabulator");
|
|
3888
|
+
let index = kw? kw.index : undefined;
|
|
3889
|
+
if(!tabulator || typeof index !== "number") {
|
|
3890
|
+
log_error(`${gobj_short_name(gobj)}: no row ${index} to show`);
|
|
3891
|
+
return -1;
|
|
3892
|
+
}
|
|
3893
|
+
|
|
3894
|
+
let row = tabulator.getRowFromPosition(index);
|
|
3895
|
+
if(!row) {
|
|
3896
|
+
log_error(`${gobj_short_name(gobj)}: row ${index} is gone`);
|
|
3897
|
+
return -1;
|
|
3898
|
+
}
|
|
3899
|
+
|
|
3900
|
+
show_view_form(gobj, row.getData());
|
|
3901
|
+
|
|
3902
|
+
return 0;
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3776
3905
|
/************************************************************
|
|
3777
3906
|
* The reader picked another page size: remember it, so coming back to
|
|
3778
3907
|
* this topic opens where they left it instead of at 200.
|
|
@@ -3933,6 +4062,7 @@ function create_gclass(gclass_name)
|
|
|
3933
4062
|
["EV_SEARCH", ac_search, null],
|
|
3934
4063
|
["EV_OPEN_COLUMNS", ac_open_columns, null],
|
|
3935
4064
|
["EV_PAGE_SIZE_CHANGED", ac_page_size_changed, null],
|
|
4065
|
+
["EV_SHOW_RECORD", ac_show_record, null],
|
|
3936
4066
|
["EV_TOGGLE_COLUMN", ac_toggle_column, null],
|
|
3937
4067
|
["EV_EXPORT_TABLE", ac_export_table, null],
|
|
3938
4068
|
["EV_SHOW", ac_show, null],
|
|
@@ -3974,6 +4104,7 @@ function create_gclass(gclass_name)
|
|
|
3974
4104
|
["EV_SEARCH", 0],
|
|
3975
4105
|
["EV_OPEN_COLUMNS", 0],
|
|
3976
4106
|
["EV_PAGE_SIZE_CHANGED", 0],
|
|
4107
|
+
["EV_SHOW_RECORD", 0],
|
|
3977
4108
|
["EV_TOGGLE_COLUMN", 0],
|
|
3978
4109
|
["EV_EXPORT_TABLE", 0],
|
|
3979
4110
|
|