@saltcorn/data 0.9.4-beta.8 → 0.9.4
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/base-plugin/actions.d.ts +137 -71
- package/dist/base-plugin/actions.d.ts.map +1 -1
- package/dist/base-plugin/actions.js +105 -22
- package/dist/base-plugin/actions.js.map +1 -1
- package/dist/base-plugin/fieldviews.d.ts.map +1 -1
- package/dist/base-plugin/fieldviews.js +19 -9
- package/dist/base-plugin/fieldviews.js.map +1 -1
- package/dist/base-plugin/fileviews.d.ts +13 -0
- package/dist/base-plugin/fileviews.js +42 -2
- package/dist/base-plugin/fileviews.js.map +1 -1
- package/dist/base-plugin/index.d.ts +208 -204
- package/dist/base-plugin/index.d.ts.map +1 -1
- package/dist/base-plugin/types.d.ts.map +1 -1
- package/dist/base-plugin/types.js +25 -10
- package/dist/base-plugin/types.js.map +1 -1
- package/dist/base-plugin/viewtemplates/edit.d.ts +4 -1
- package/dist/base-plugin/viewtemplates/edit.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/edit.js +181 -81
- package/dist/base-plugin/viewtemplates/edit.js.map +1 -1
- package/dist/base-plugin/viewtemplates/feed.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/feed.js +4 -1
- package/dist/base-plugin/viewtemplates/feed.js.map +1 -1
- package/dist/base-plugin/viewtemplates/filter.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/filter.js +89 -7
- package/dist/base-plugin/viewtemplates/filter.js.map +1 -1
- package/dist/base-plugin/viewtemplates/list.d.ts +3 -2
- package/dist/base-plugin/viewtemplates/list.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/list.js +274 -38
- package/dist/base-plugin/viewtemplates/list.js.map +1 -1
- package/dist/base-plugin/viewtemplates/show.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/show.js +116 -56
- package/dist/base-plugin/viewtemplates/show.js.map +1 -1
- package/dist/base-plugin/viewtemplates/viewable_fields.d.ts +4 -3
- package/dist/base-plugin/viewtemplates/viewable_fields.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/viewable_fields.js +173 -57
- package/dist/base-plugin/viewtemplates/viewable_fields.js.map +1 -1
- package/dist/db/connect.d.ts.map +1 -1
- package/dist/db/connect.js +20 -0
- package/dist/db/connect.js.map +1 -1
- package/dist/db/fixtures.d.ts.map +1 -1
- package/dist/db/fixtures.js +196 -30
- package/dist/db/fixtures.js.map +1 -1
- package/dist/db/state.d.ts +5 -0
- package/dist/db/state.d.ts.map +1 -1
- package/dist/db/state.js +20 -0
- package/dist/db/state.js.map +1 -1
- package/dist/migrate.d.ts +1 -0
- package/dist/migrate.d.ts.map +1 -1
- package/dist/migrate.js +6 -3
- package/dist/migrate.js.map +1 -1
- package/dist/migrations/202402071125.d.ts +2 -0
- package/dist/migrations/202402071125.d.ts.map +1 -0
- package/dist/migrations/202402071125.js +4 -0
- package/dist/migrations/202402071125.js.map +1 -0
- package/dist/models/config.d.ts.map +1 -1
- package/dist/models/config.js +27 -0
- package/dist/models/config.js.map +1 -1
- package/dist/models/email.d.ts.map +1 -1
- package/dist/models/email.js +6 -2
- package/dist/models/email.js.map +1 -1
- package/dist/models/field.d.ts +1 -1
- package/dist/models/field.d.ts.map +1 -1
- package/dist/models/field.js +4 -4
- package/dist/models/field.js.map +1 -1
- package/dist/models/file.d.ts +2 -0
- package/dist/models/file.d.ts.map +1 -1
- package/dist/models/file.js +9 -0
- package/dist/models/file.js.map +1 -1
- package/dist/models/index.d.ts +1 -1
- package/dist/models/internal/query.d.ts +6 -0
- package/dist/models/internal/query.d.ts.map +1 -0
- package/dist/models/internal/query.js +86 -0
- package/dist/models/internal/query.js.map +1 -0
- package/dist/models/page.d.ts.map +1 -1
- package/dist/models/page.js +4 -0
- package/dist/models/page.js.map +1 -1
- package/dist/models/page_group.d.ts +1 -0
- package/dist/models/page_group.d.ts.map +1 -1
- package/dist/models/page_group.js +1 -0
- package/dist/models/page_group.js.map +1 -1
- package/dist/models/table.d.ts +18 -4
- package/dist/models/table.d.ts.map +1 -1
- package/dist/models/table.js +84 -52
- package/dist/models/table.js.map +1 -1
- package/dist/models/tag_entry.d.ts.map +1 -1
- package/dist/models/tag_entry.js +9 -0
- package/dist/models/tag_entry.js.map +1 -1
- package/dist/models/trigger.d.ts +3 -3
- package/dist/models/trigger.d.ts.map +1 -1
- package/dist/models/trigger.js +69 -7
- package/dist/models/trigger.js.map +1 -1
- package/dist/models/user.d.ts.map +1 -1
- package/dist/models/user.js +5 -4
- package/dist/models/user.js.map +1 -1
- package/dist/models/view.d.ts +1 -0
- package/dist/models/view.d.ts.map +1 -1
- package/dist/models/view.js +6 -0
- package/dist/models/view.js.map +1 -1
- package/dist/plugin-helper.d.ts +7 -19
- package/dist/plugin-helper.d.ts.map +1 -1
- package/dist/plugin-helper.js +79 -70
- package/dist/plugin-helper.js.map +1 -1
- package/dist/tests/actions.test.js +143 -2
- package/dist/tests/actions.test.js.map +1 -1
- package/dist/tests/auth.test.js +101 -1
- package/dist/tests/auth.test.js.map +1 -1
- package/dist/tests/auxtest.test.js +4 -0
- package/dist/tests/auxtest.test.js.map +1 -1
- package/dist/tests/calc.test.js +20 -0
- package/dist/tests/calc.test.js.map +1 -1
- package/dist/tests/edit.test.js +558 -0
- package/dist/tests/edit.test.js.map +1 -1
- package/dist/tests/filter.test.d.ts +2 -0
- package/dist/tests/filter.test.d.ts.map +1 -0
- package/dist/tests/filter.test.js +438 -0
- package/dist/tests/filter.test.js.map +1 -0
- package/dist/tests/list.test.d.ts +2 -0
- package/dist/tests/list.test.d.ts.map +1 -0
- package/dist/tests/list.test.js +903 -0
- package/dist/tests/list.test.js.map +1 -0
- package/dist/tests/show.test.d.ts +2 -0
- package/dist/tests/show.test.d.ts.map +1 -0
- package/dist/tests/show.test.js +325 -0
- package/dist/tests/show.test.js.map +1 -0
- package/dist/tests/table.test.js +213 -56
- package/dist/tests/table.test.js.map +1 -1
- package/dist/tests/table_history.test.js +51 -0
- package/dist/tests/table_history.test.js.map +1 -1
- package/dist/tests/tag.test.js +1 -1
- package/dist/tests/tag.test.js.map +1 -1
- package/dist/tests/view.test.js +16 -2
- package/dist/tests/view.test.js.map +1 -1
- package/dist/utils.d.ts +2 -17
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +19 -32
- package/dist/utils.js.map +1 -1
- package/package.json +8 -7
|
@@ -20,10 +20,10 @@ const { text, text_attr, script, domReady, div, button, i, pre, } = require("@sa
|
|
|
20
20
|
const { renderForm } = require("@saltcorn/markup");
|
|
21
21
|
const FieldRepeat = require("../../models/fieldrepeat");
|
|
22
22
|
const { get_expression_function, expressionChecker, eval_expression, freeVariables, freeVariablesInInterpolation, } = require("../../models/expression");
|
|
23
|
-
const { InvalidConfiguration, isNode, isOfflineMode, mergeIntoWhere, dollarizeObject, getSessionId, } = require("../../utils");
|
|
23
|
+
const { InvalidConfiguration, isNode, isOfflineMode, mergeIntoWhere, dollarizeObject, getSessionId, interpolate, } = require("../../utils");
|
|
24
24
|
const Library = require("../../models/library");
|
|
25
25
|
const { check_view_columns } = require("../../plugin-testing");
|
|
26
|
-
const { initial_config_all_fields, calcfldViewOptions, calcfldViewConfig, get_parent_views, picked_fields_to_query, stateFieldsToWhere, stateFieldsToQuery, getActionConfigFields, run_action_column, add_free_variables_to_joinfields, readState, stateToQueryString, pathToState,
|
|
26
|
+
const { initial_config_all_fields, calcfldViewOptions, calcfldViewConfig, get_parent_views, picked_fields_to_query, stateFieldsToWhere, stateFieldsToQuery, getActionConfigFields, run_action_column, add_free_variables_to_joinfields, readState, stateToQueryString, pathToState, displayType, } = require("../../plugin-helper");
|
|
27
27
|
const { splitUniques, getForm, fill_presets, parse_view_select, get_view_link_query, objToQueryString, action_url, action_link, view_linker, } = require("./viewable_fields");
|
|
28
28
|
const { traverse, getStringsForI18n, translateLayout, traverseSync, } = require("../../models/layout");
|
|
29
29
|
const { asyncMap, isWeb, removeEmptyStrings } = require("../../utils");
|
|
@@ -31,6 +31,7 @@ const { extractFromLayout } = require("../../diagram/node_extract_utils");
|
|
|
31
31
|
const db = require("../../db");
|
|
32
32
|
const { prepare_update_row } = require("../../web-mobile-commons");
|
|
33
33
|
const _ = require("underscore");
|
|
34
|
+
const { Relation, RelationType } = require("@saltcorn/common-code");
|
|
34
35
|
const builtInActions = [
|
|
35
36
|
"Save",
|
|
36
37
|
"SaveAndContinue",
|
|
@@ -73,6 +74,7 @@ const configuration_workflow = (req) => new Workflow({
|
|
|
73
74
|
const triggerActions = [];
|
|
74
75
|
(await Trigger.find({
|
|
75
76
|
when_trigger: { or: ["API call", "Never"] },
|
|
77
|
+
table_id: null,
|
|
76
78
|
})).forEach((tr) => {
|
|
77
79
|
actions.push(tr.name);
|
|
78
80
|
triggerActions.push(tr.name);
|
|
@@ -141,7 +143,7 @@ const configuration_workflow = (req) => new Workflow({
|
|
|
141
143
|
field_view_options.remember = ["edit"];
|
|
142
144
|
}
|
|
143
145
|
const library = (await Library.find({})).filter((l) => l.suitableFor("edit"));
|
|
144
|
-
const myviewrow =
|
|
146
|
+
const myviewrow = View.findOne({ name: context.viewname });
|
|
145
147
|
const { parent_field_list } = await table.get_parent_relations(true, true);
|
|
146
148
|
const pages = await Page.find();
|
|
147
149
|
const groups = (await PageGroup.find()).map((g) => ({
|
|
@@ -376,12 +378,6 @@ const setDateLocales = (form, locale) => {
|
|
|
376
378
|
}
|
|
377
379
|
});
|
|
378
380
|
};
|
|
379
|
-
/**
|
|
380
|
-
* check if a relation path has a CHildList structure
|
|
381
|
-
*/
|
|
382
|
-
const isChildListPath = (viewSelect, subView) => viewSelect.type === "RelationPath" &&
|
|
383
|
-
relationTypeFromPath(subView, viewSelect.path, viewSelect.sourcetable) ===
|
|
384
|
-
"ChildList";
|
|
385
381
|
/**
|
|
386
382
|
* update viewSelect so that it looks like a normal ChildList
|
|
387
383
|
*/
|
|
@@ -469,7 +465,18 @@ const runMany = async (table_id, viewname, { columns, layout, auto_save, split_p
|
|
|
469
465
|
* @returns {Promise<void>}
|
|
470
466
|
*/
|
|
471
467
|
const transformForm = async ({ form, table, req, row, res, getRowQuery, viewname, optionsQuery, }) => {
|
|
468
|
+
let pseudo_row = {};
|
|
469
|
+
if (!row) {
|
|
470
|
+
table.fields.forEach((f) => {
|
|
471
|
+
pseudo_row[f.name] = undefined;
|
|
472
|
+
});
|
|
473
|
+
}
|
|
472
474
|
await traverse(form.layout, {
|
|
475
|
+
container(segment) {
|
|
476
|
+
if (segment.click_action) {
|
|
477
|
+
segment.url = `javascript:view_post('${viewname}', 'run_action', {click_action: '${segment.click_action}', ...get_form_record({viewname: '${viewname}'}) })`;
|
|
478
|
+
}
|
|
479
|
+
},
|
|
473
480
|
async action(segment) {
|
|
474
481
|
if (segment.action_style === "on_page_load") {
|
|
475
482
|
//TODO check segment.min_role
|
|
@@ -481,11 +488,11 @@ const transformForm = async ({ form, table, req, row, res, getRowQuery, viewname
|
|
|
481
488
|
try {
|
|
482
489
|
const actionResult = await run_action_column({
|
|
483
490
|
col: { ...segment },
|
|
484
|
-
referrer: req
|
|
491
|
+
referrer: req?.get?.("Referrer"),
|
|
485
492
|
req,
|
|
486
493
|
res,
|
|
487
494
|
table,
|
|
488
|
-
row,
|
|
495
|
+
row: row || pseudo_row,
|
|
489
496
|
});
|
|
490
497
|
segment.type = "blank";
|
|
491
498
|
segment.style = {};
|
|
@@ -527,25 +534,19 @@ const transformForm = async ({ form, table, req, row, res, getRowQuery, viewname
|
|
|
527
534
|
segment.sourceURL = `/field/show-calculated/${table.name}/${segment.join_field}/${segment.fieldview}?${qs}`;
|
|
528
535
|
},
|
|
529
536
|
tabs(segment) {
|
|
537
|
+
const to_delete = new Set();
|
|
530
538
|
(segment.showif || []).forEach((sif, ix) => {
|
|
531
539
|
if (sif) {
|
|
532
|
-
const showit = eval_expression(sif, row ||
|
|
533
|
-
if (!showit)
|
|
534
|
-
|
|
535
|
-
segment.contents.splice(ix, 1);
|
|
536
|
-
}
|
|
540
|
+
const showit = eval_expression(sif, row || pseudo_row, req.user);
|
|
541
|
+
if (!showit)
|
|
542
|
+
to_delete.add(ix);
|
|
537
543
|
}
|
|
538
544
|
});
|
|
545
|
+
segment.titles = segment.titles.filter((v, ix) => !to_delete.has(ix));
|
|
546
|
+
segment.contents = segment.contents.filter((v, ix) => !to_delete.has(ix));
|
|
539
547
|
(segment.titles || []).forEach((t, ix) => {
|
|
540
548
|
if (typeof t === "string" && t.includes("{{")) {
|
|
541
|
-
|
|
542
|
-
interpolate: /\{\{([^#].+?)\}\}/g,
|
|
543
|
-
});
|
|
544
|
-
segment.titles[ix] = template({
|
|
545
|
-
user: req.user,
|
|
546
|
-
row,
|
|
547
|
-
...(row || {}),
|
|
548
|
-
});
|
|
549
|
+
segment.titles[ix] = interpolate(t, row, req.user);
|
|
549
550
|
}
|
|
550
551
|
});
|
|
551
552
|
},
|
|
@@ -568,11 +569,17 @@ const transformForm = async ({ form, table, req, row, res, getRowQuery, viewname
|
|
|
568
569
|
const view = View.findOne({ name: view_select.viewname });
|
|
569
570
|
if (!view)
|
|
570
571
|
throw new InvalidConfiguration(`Cannot find embedded view: ${view_select.viewname}`);
|
|
571
|
-
|
|
572
|
+
// check if the relation path matches a ChildList relations
|
|
573
|
+
let childListRelPath = false;
|
|
574
|
+
if (segment.relation && view.table_id) {
|
|
575
|
+
const targetTbl = Table.findOne({ id: view.table_id });
|
|
576
|
+
const relation = new Relation(segment.relation, targetTbl.name, displayType(await view.get_state_fields()));
|
|
577
|
+
childListRelPath = relation.type === RelationType.CHILD_LIST;
|
|
578
|
+
}
|
|
572
579
|
// Edit-in-edit
|
|
573
580
|
if (view.viewtemplate === "Edit" &&
|
|
574
|
-
(view_select.type === "ChildList" ||
|
|
575
|
-
if (
|
|
581
|
+
(view_select.type === "ChildList" || childListRelPath)) {
|
|
582
|
+
if (childListRelPath)
|
|
576
583
|
updateViewSelect(view_select);
|
|
577
584
|
const childTable = Table.findOne({ id: view.table_id });
|
|
578
585
|
const childForm = await getForm(childTable, view.name, view.configuration.columns, view.configuration.layout, row?.id, req, !isWeb(req));
|
|
@@ -619,42 +626,51 @@ const transformForm = async ({ form, table, req, row, res, getRowQuery, viewname
|
|
|
619
626
|
segment.field_repeat = fr;
|
|
620
627
|
return;
|
|
621
628
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
629
|
+
let state = {};
|
|
630
|
+
if (view_select.type === "RelationPath" && view.table_id) {
|
|
631
|
+
const targetTbl = Table.findOne({ id: view.table_id });
|
|
632
|
+
if (targetTbl) {
|
|
633
|
+
const relation = new Relation(segment.relation, targetTbl.name, displayType(await view.get_state_fields()));
|
|
634
|
+
const type = relation.type;
|
|
635
|
+
if (!row && type !== RelationType.INDEPENDENT) {
|
|
636
|
+
segment.type = "blank";
|
|
637
|
+
segment.contents = "";
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
state = pathToState(relation, (k) => row[k]);
|
|
641
|
+
}
|
|
630
642
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
643
|
+
else {
|
|
644
|
+
const isIndependent = view_select.type === "Independent";
|
|
645
|
+
// legacy none check ?
|
|
646
|
+
if (!row && !isIndependent) {
|
|
647
|
+
segment.type = "blank";
|
|
648
|
+
segment.contents = "";
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
if (!view)
|
|
652
|
+
throw new InvalidConfiguration(`Edit view incorrectly configured: cannot find embedded view ${view_select.viewname}`);
|
|
653
|
+
switch (view_select.type) {
|
|
654
|
+
case "Own":
|
|
655
|
+
state = { id: row.id };
|
|
656
|
+
break;
|
|
657
|
+
case "Independent":
|
|
658
|
+
state = {};
|
|
659
|
+
break;
|
|
660
|
+
case "ChildList":
|
|
661
|
+
case "OneToOneShow":
|
|
662
|
+
state = { [view_select.field_name]: row.id };
|
|
663
|
+
break;
|
|
664
|
+
case "ParentShow":
|
|
665
|
+
state = { id: row[view_select.field_name] };
|
|
666
|
+
break;
|
|
638
667
|
}
|
|
639
|
-
case "Own":
|
|
640
|
-
state = { id: row.id };
|
|
641
|
-
break;
|
|
642
|
-
case "Independent":
|
|
643
|
-
state = {};
|
|
644
|
-
break;
|
|
645
|
-
case "ChildList":
|
|
646
|
-
case "OneToOneShow":
|
|
647
|
-
state = { [view_select.field_name]: row.id };
|
|
648
|
-
break;
|
|
649
|
-
case "ParentShow":
|
|
650
|
-
state = { id: row[view_select.field_name] };
|
|
651
|
-
break;
|
|
652
668
|
}
|
|
653
669
|
const extra_state = segment.extra_state_fml
|
|
654
670
|
? eval_expression(segment.extra_state_fml, {
|
|
655
671
|
...dollarizeObject(req.query),
|
|
656
672
|
session_id: getSessionId(req),
|
|
657
|
-
...(row ||
|
|
673
|
+
...(row || pseudo_row),
|
|
658
674
|
}, req.user)
|
|
659
675
|
: {};
|
|
660
676
|
const qs = stateToQueryString({ ...state, ...extra_state });
|
|
@@ -818,6 +834,8 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
|
|
|
818
834
|
fixed,
|
|
819
835
|
auto_save,
|
|
820
836
|
}, { req, res }, body, { getRowQuery, saveFileQuery, optionsQuery, getRowByIdQuery }, remote);
|
|
837
|
+
const view = View.findOne({ name: viewname });
|
|
838
|
+
const pagetitle = { title: viewname, no_menu: view?.attributes?.no_menu };
|
|
821
839
|
if (prepResult) {
|
|
822
840
|
let { form, row, pk, id } = prepResult;
|
|
823
841
|
const cancel = body._cancel;
|
|
@@ -850,7 +868,7 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
|
|
|
850
868
|
}
|
|
851
869
|
else {
|
|
852
870
|
req.flash("error", text_attr(ins_upd_error));
|
|
853
|
-
res.sendWrap(
|
|
871
|
+
res.sendWrap(pagetitle, renderForm(form, req.csrfToken()));
|
|
854
872
|
}
|
|
855
873
|
return;
|
|
856
874
|
}
|
|
@@ -858,8 +876,15 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
|
|
|
858
876
|
for (const field of form.fields.filter((f) => f.isRepeat)) {
|
|
859
877
|
const view_select = parse_view_select(field.metadata.view, field.metadata.relation_path);
|
|
860
878
|
const childView = View.findOne({ name: view_select.viewname });
|
|
861
|
-
if (
|
|
862
|
-
|
|
879
|
+
if (!childView)
|
|
880
|
+
throw new InvalidConfiguration(`Cannot find embedded view: ${view_select.viewname}`);
|
|
881
|
+
if (field.metadata.relation_path &&
|
|
882
|
+
view_select.type === "RelationPath") {
|
|
883
|
+
const targetTbl = Table.findOne({ id: childView.table_id });
|
|
884
|
+
const relation = new Relation(field.metadata.relation_path, targetTbl.name, displayType(await childView.get_state_fields()));
|
|
885
|
+
if (relation.type === RelationType.CHILD_LIST)
|
|
886
|
+
updateViewSelect(view_select);
|
|
887
|
+
}
|
|
863
888
|
const childTable = Table.findOne({ id: field.metadata?.table_id });
|
|
864
889
|
const submitted_row_ids = new Set((form.values[field.name] || []).map((srow) => `${srow[childTable.pk_name]}`));
|
|
865
890
|
const childFields = new Set(childTable.fields.map((f) => f.name));
|
|
@@ -876,7 +901,7 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
|
|
|
876
901
|
const upd_res = await childTable.tryUpdateRow(childRow, childRow[childTable.pk_name], req.user || { role_id: 100 });
|
|
877
902
|
if (upd_res.error) {
|
|
878
903
|
req.flash("error", text_attr(upd_res.error));
|
|
879
|
-
res.sendWrap(
|
|
904
|
+
res.sendWrap(pagetitle, renderForm(form, req.csrfToken()));
|
|
880
905
|
return;
|
|
881
906
|
}
|
|
882
907
|
}
|
|
@@ -884,7 +909,7 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
|
|
|
884
909
|
const ins_res = await childTable.tryInsertRow(childRow, req.user || { role_id: 100 });
|
|
885
910
|
if (ins_res.error) {
|
|
886
911
|
req.flash("error", text_attr(ins_res.error));
|
|
887
|
-
res.sendWrap(
|
|
912
|
+
res.sendWrap(pagetitle, renderForm(form, req.csrfToken()));
|
|
888
913
|
return;
|
|
889
914
|
}
|
|
890
915
|
else if (ins_res.success) {
|
|
@@ -1025,6 +1050,56 @@ const doAuthPost = async ({ body, table_id, req }) => {
|
|
|
1025
1050
|
const authorise_post = async ({ body, table_id, req }, { authorizePostQuery }) => {
|
|
1026
1051
|
return await authorizePostQuery(body, table_id);
|
|
1027
1052
|
};
|
|
1053
|
+
const openDataStream = async (tableId, viewName, id, fieldName, fieldView, user, configuration, targetOpts) => {
|
|
1054
|
+
const table = Table.findOne({ id: tableId });
|
|
1055
|
+
const field = table.getField(fieldName);
|
|
1056
|
+
if (!field)
|
|
1057
|
+
throw new InvalidConfiguration(`Field ${fieldName} not found`);
|
|
1058
|
+
if (field.type === "File") {
|
|
1059
|
+
const cfgCol = configuration.columns.find((col) => col.fieldview === fieldView && col.field_name === fieldName);
|
|
1060
|
+
const fileView = getState().fileviews[fieldView];
|
|
1061
|
+
if (!fileView)
|
|
1062
|
+
throw new InvalidConfiguration(`File view ${fieldView} not found`);
|
|
1063
|
+
return await fileView.openDataStream(tableId, id, fieldName, user, cfgCol.configuration, targetOpts);
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
// TODO is owner check
|
|
1067
|
+
const authorizeDataStream = async (view, id, fieldName, user, targetOpts) => {
|
|
1068
|
+
if (!user || user.role_id > view.min_role)
|
|
1069
|
+
return false;
|
|
1070
|
+
else {
|
|
1071
|
+
const table = Table.findOne({ id: view.table_id });
|
|
1072
|
+
if (!table || user.role_id > table.min_role_write)
|
|
1073
|
+
return false;
|
|
1074
|
+
else {
|
|
1075
|
+
const field = table.getField(fieldName);
|
|
1076
|
+
if (field.type === "File") {
|
|
1077
|
+
if (targetOpts?.oldTarget) {
|
|
1078
|
+
// continue old file ?
|
|
1079
|
+
const file = await File.findOne(targetOpts.oldTarget);
|
|
1080
|
+
if (file)
|
|
1081
|
+
return file.min_role_read >= user.role_id;
|
|
1082
|
+
}
|
|
1083
|
+
else if (id) {
|
|
1084
|
+
// continue file of existing row ?
|
|
1085
|
+
const row = await table.getRow({ [table.pk_name]: id });
|
|
1086
|
+
const fileCol = row[fieldName];
|
|
1087
|
+
if (fileCol) {
|
|
1088
|
+
const file = await File.findOne(row[fieldName]);
|
|
1089
|
+
if (file)
|
|
1090
|
+
return file.min_role_read >= user.role_id;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
// stream is new or the file does not exist
|
|
1094
|
+
return true;
|
|
1095
|
+
}
|
|
1096
|
+
else {
|
|
1097
|
+
// only files for now
|
|
1098
|
+
return false;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1028
1103
|
/**
|
|
1029
1104
|
* @param {number} table_id
|
|
1030
1105
|
* @param {*} viewname
|
|
@@ -1135,7 +1210,8 @@ const prepare = async (viewname, table, fields, { columns, layout, fixed, auto_s
|
|
|
1135
1210
|
if (req.xhr)
|
|
1136
1211
|
res.status(422);
|
|
1137
1212
|
await form.fill_fkey_options(false, optionsQuery, req.user);
|
|
1138
|
-
|
|
1213
|
+
const view = View.findOne({ name: viewname });
|
|
1214
|
+
res.sendWrap({ title: viewname, no_menu: view?.attributes?.no_menu }, renderForm(form, req.csrfToken ? req.csrfToken() : false));
|
|
1139
1215
|
return null;
|
|
1140
1216
|
}
|
|
1141
1217
|
let row;
|
|
@@ -1158,7 +1234,7 @@ const prepare = async (viewname, table, fields, { columns, layout, fixed, auto_s
|
|
|
1158
1234
|
}
|
|
1159
1235
|
const file_fields = form.fields.filter((f) => f.type === "File");
|
|
1160
1236
|
for (const field of file_fields) {
|
|
1161
|
-
if (!field.fieldviewObj?.isEdit)
|
|
1237
|
+
if (!field.fieldviewObj?.isEdit || field.fieldviewObj?.isStream)
|
|
1162
1238
|
continue;
|
|
1163
1239
|
if (field.fieldviewObj?.setsFileId) {
|
|
1164
1240
|
//do nothing
|
|
@@ -1327,6 +1403,8 @@ module.exports = {
|
|
|
1327
1403
|
run,
|
|
1328
1404
|
runMany,
|
|
1329
1405
|
runPost,
|
|
1406
|
+
openDataStream,
|
|
1407
|
+
authorizeDataStream,
|
|
1330
1408
|
get_state_fields,
|
|
1331
1409
|
initial_config,
|
|
1332
1410
|
/** @type {boolean} */
|
|
@@ -1349,7 +1427,7 @@ module.exports = {
|
|
|
1349
1427
|
getStringsForI18n({ layout }) {
|
|
1350
1428
|
return getStringsForI18n(layout);
|
|
1351
1429
|
},
|
|
1352
|
-
queries: ({ table_id, name, configuration: { columns, default_state, layout, auto_save, split_paste, destination_type, }, req, res, }) => ({
|
|
1430
|
+
queries: ({ table_id, name, configuration: { columns, default_state, layout, auto_save, split_paste, destination_type, fixed, }, req, res, }) => ({
|
|
1353
1431
|
async editQuery(state, mobileReferrer) {
|
|
1354
1432
|
const table = Table.findOne({ id: table_id });
|
|
1355
1433
|
const fields = table.getFields();
|
|
@@ -1497,17 +1575,46 @@ module.exports = {
|
|
|
1497
1575
|
});
|
|
1498
1576
|
},
|
|
1499
1577
|
async actionQuery() {
|
|
1500
|
-
const { rndid, _csrf, onchange_action, onchange_field, ...body } = req.body;
|
|
1578
|
+
const { rndid, _csrf, onchange_action, onchange_field, click_action, ...body } = req.body;
|
|
1501
1579
|
const table = Table.findOne({ id: table_id });
|
|
1502
|
-
|
|
1580
|
+
let row = body.id
|
|
1503
1581
|
? await table.getRow({ id: body.id }, {
|
|
1504
1582
|
forPublic: !req.user,
|
|
1505
1583
|
forUser: req.user,
|
|
1506
1584
|
})
|
|
1507
|
-
:
|
|
1508
|
-
|
|
1585
|
+
: {};
|
|
1586
|
+
table.fields.forEach((f) => {
|
|
1587
|
+
if (!f?.validate)
|
|
1588
|
+
return;
|
|
1589
|
+
const valres = f.validate(body);
|
|
1590
|
+
if ("success" in valres)
|
|
1591
|
+
row[f.name] = valres.success;
|
|
1592
|
+
});
|
|
1593
|
+
const use_fixed = await fill_presets(table, req, fixed);
|
|
1594
|
+
row = { ...use_fixed, ...row };
|
|
1509
1595
|
try {
|
|
1510
|
-
if (
|
|
1596
|
+
if (click_action) {
|
|
1597
|
+
let container;
|
|
1598
|
+
traverseSync(layout, {
|
|
1599
|
+
container(segment) {
|
|
1600
|
+
if (segment.click_action === click_action)
|
|
1601
|
+
container = segment;
|
|
1602
|
+
},
|
|
1603
|
+
});
|
|
1604
|
+
if (!container)
|
|
1605
|
+
return { json: { error: "Action not found" } };
|
|
1606
|
+
const trigger = Trigger.findOne({ name: click_action });
|
|
1607
|
+
const result = await trigger.runWithoutRow({
|
|
1608
|
+
table,
|
|
1609
|
+
Table,
|
|
1610
|
+
req,
|
|
1611
|
+
row,
|
|
1612
|
+
referrer: req?.get?.("Referrer"),
|
|
1613
|
+
user: req.user,
|
|
1614
|
+
});
|
|
1615
|
+
return { json: { success: "ok", ...(result || {}) } };
|
|
1616
|
+
}
|
|
1617
|
+
else if (onchange_action && !rndid) {
|
|
1511
1618
|
const fldCol = columns.find((c) => c.field_name === onchange_field &&
|
|
1512
1619
|
c.onchange_action === onchange_action);
|
|
1513
1620
|
if (!fldCol)
|
|
@@ -1518,6 +1625,7 @@ module.exports = {
|
|
|
1518
1625
|
Table,
|
|
1519
1626
|
req,
|
|
1520
1627
|
row,
|
|
1628
|
+
referrer: req?.get?.("Referrer"),
|
|
1521
1629
|
user: req.user,
|
|
1522
1630
|
});
|
|
1523
1631
|
return { json: { success: "ok", ...(result || {}) } };
|
|
@@ -1530,7 +1638,7 @@ module.exports = {
|
|
|
1530
1638
|
table,
|
|
1531
1639
|
row,
|
|
1532
1640
|
res,
|
|
1533
|
-
referrer: req
|
|
1641
|
+
referrer: req?.get?.("Referrer"),
|
|
1534
1642
|
});
|
|
1535
1643
|
//console.log("result", result);
|
|
1536
1644
|
return { json: { success: "ok", ...(result || {}) } };
|
|
@@ -1601,18 +1709,10 @@ module.exports = {
|
|
|
1601
1709
|
where: { [tbl.pk_name]: state[tbl.pk_name] },
|
|
1602
1710
|
joinFields,
|
|
1603
1711
|
});
|
|
1604
|
-
|
|
1605
|
-
interpolate: /\{\{([^#].+?)\}\}/g,
|
|
1606
|
-
});
|
|
1607
|
-
let t = template({ row, ...row });
|
|
1608
|
-
return t;
|
|
1712
|
+
return interpolate(title, row);
|
|
1609
1713
|
}
|
|
1610
1714
|
else {
|
|
1611
|
-
|
|
1612
|
-
interpolate: /\{\{([^#].+?)\}\}/g,
|
|
1613
|
-
});
|
|
1614
|
-
let t = template({ row: null });
|
|
1615
|
-
return t;
|
|
1715
|
+
return interpolate(title, null);
|
|
1616
1716
|
}
|
|
1617
1717
|
},
|
|
1618
1718
|
configCheck: async (view) => {
|
|
@@ -1620,7 +1720,7 @@ module.exports = {
|
|
|
1620
1720
|
const errs = [];
|
|
1621
1721
|
const warnings = [];
|
|
1622
1722
|
if (!destination_type || destination_type === "View") {
|
|
1623
|
-
const vwd =
|
|
1723
|
+
const vwd = View.findOne({
|
|
1624
1724
|
name: (view_when_done || "").split(".")[0],
|
|
1625
1725
|
});
|
|
1626
1726
|
if (!vwd)
|