@saltcorn/data 0.7.1-beta.3 → 0.7.2-beta.10
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.map +1 -1
- package/dist/base-plugin/actions.js +5 -1
- package/dist/base-plugin/actions.js.map +1 -1
- package/dist/base-plugin/fieldviews.d.ts +29 -0
- package/dist/base-plugin/fieldviews.d.ts.map +1 -1
- package/dist/base-plugin/fieldviews.js +60 -5
- package/dist/base-plugin/fieldviews.js.map +1 -1
- package/dist/base-plugin/fileviews.d.ts.map +1 -1
- package/dist/base-plugin/fileviews.js +20 -5
- package/dist/base-plugin/fileviews.js.map +1 -1
- package/dist/base-plugin/index.d.ts +309 -84
- package/dist/base-plugin/index.d.ts.map +1 -1
- package/dist/base-plugin/types.d.ts +127 -65
- package/dist/base-plugin/types.d.ts.map +1 -1
- package/dist/base-plugin/types.js +152 -36
- package/dist/base-plugin/types.js.map +1 -1
- package/dist/base-plugin/viewtemplates/edit.d.ts +47 -9
- package/dist/base-plugin/viewtemplates/edit.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/edit.js +266 -113
- package/dist/base-plugin/viewtemplates/edit.js.map +1 -1
- package/dist/base-plugin/viewtemplates/feed.d.ts +14 -1
- package/dist/base-plugin/viewtemplates/feed.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/feed.js +20 -8
- package/dist/base-plugin/viewtemplates/feed.js.map +1 -1
- package/dist/base-plugin/viewtemplates/filter.d.ts +17 -1
- package/dist/base-plugin/viewtemplates/filter.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/filter.js +66 -45
- package/dist/base-plugin/viewtemplates/filter.js.map +1 -1
- package/dist/base-plugin/viewtemplates/list.d.ts +21 -1
- package/dist/base-plugin/viewtemplates/list.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/list.js +63 -40
- package/dist/base-plugin/viewtemplates/list.js.map +1 -1
- package/dist/base-plugin/viewtemplates/listshowlist.d.ts +14 -1
- package/dist/base-plugin/viewtemplates/listshowlist.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/listshowlist.js +15 -4
- package/dist/base-plugin/viewtemplates/listshowlist.js.map +1 -1
- package/dist/base-plugin/viewtemplates/room.d.ts +41 -1
- package/dist/base-plugin/viewtemplates/room.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/room.js +107 -80
- package/dist/base-plugin/viewtemplates/room.js.map +1 -1
- package/dist/base-plugin/viewtemplates/show.d.ts +38 -4
- package/dist/base-plugin/viewtemplates/show.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/show.js +125 -76
- package/dist/base-plugin/viewtemplates/show.js.map +1 -1
- package/dist/base-plugin/viewtemplates/viewable_fields.d.ts +26 -7
- package/dist/base-plugin/viewtemplates/viewable_fields.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/viewable_fields.js +60 -48
- 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 +8 -1
- package/dist/db/connect.js.map +1 -1
- package/dist/db/connect_mobile.d.ts +9 -0
- package/dist/db/connect_mobile.d.ts.map +1 -0
- package/dist/db/connect_mobile.js +15 -0
- package/dist/db/connect_mobile.js.map +1 -0
- package/dist/db/fixtures.d.ts.map +1 -1
- package/dist/db/fixtures.js +6 -1
- package/dist/db/fixtures.js.map +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +16 -2
- package/dist/db/index.js.map +1 -1
- package/dist/db/state.d.ts +214 -52
- package/dist/db/state.d.ts.map +1 -1
- package/dist/db/state.js +115 -104
- package/dist/db/state.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -3
- package/dist/index.js.map +1 -1
- package/dist/migrate.d.ts.map +1 -1
- package/dist/migrate.js +54 -40
- package/dist/migrate.js.map +1 -1
- package/dist/mobile-mocks/db/postgres.d.ts +1 -0
- package/dist/mobile-mocks/db/postgres.d.ts.map +1 -0
- package/dist/mobile-mocks/db/postgres.js +2 -0
- package/dist/mobile-mocks/db/postgres.js.map +1 -0
- package/dist/mobile-mocks/db/sqlite.d.ts +1 -0
- package/dist/mobile-mocks/db/sqlite.d.ts.map +1 -0
- package/dist/mobile-mocks/db/sqlite.js +2 -0
- package/dist/mobile-mocks/db/sqlite.js.map +1 -0
- package/dist/mobile-mocks/models/email.d.ts +1 -0
- package/dist/mobile-mocks/models/email.d.ts.map +1 -0
- package/dist/mobile-mocks/models/email.js +2 -0
- package/dist/mobile-mocks/models/email.js.map +1 -0
- package/dist/mobile-mocks/node/async_hooks.d.ts +4 -0
- package/dist/mobile-mocks/node/async_hooks.d.ts.map +1 -0
- package/dist/mobile-mocks/node/async_hooks.js +8 -0
- package/dist/mobile-mocks/node/async_hooks.js.map +1 -0
- package/dist/mobile-mocks/node/child_process.d.ts +3 -0
- package/dist/mobile-mocks/node/child_process.d.ts.map +1 -0
- package/dist/mobile-mocks/node/child_process.js +6 -0
- package/dist/mobile-mocks/node/child_process.js.map +1 -0
- package/dist/mobile-mocks/node/fs/promises.d.ts +6 -0
- package/dist/mobile-mocks/node/fs/promises.d.ts.map +1 -0
- package/dist/mobile-mocks/node/fs/promises.js +16 -0
- package/dist/mobile-mocks/node/fs/promises.js.map +1 -0
- package/dist/mobile-mocks/node/fs.d.ts +4 -0
- package/dist/mobile-mocks/node/fs.d.ts.map +1 -0
- package/dist/mobile-mocks/node/fs.js +15 -0
- package/dist/mobile-mocks/node/fs.js.map +1 -0
- package/dist/mobile-mocks/node/latest-version.d.ts +2 -0
- package/dist/mobile-mocks/node/latest-version.d.ts.map +1 -0
- package/dist/mobile-mocks/node/latest-version.js +7 -0
- package/dist/mobile-mocks/node/latest-version.js.map +1 -0
- package/dist/mobile-mocks/node/v8.d.ts +3 -0
- package/dist/mobile-mocks/node/v8.d.ts.map +1 -0
- package/dist/mobile-mocks/node/v8.js +8 -0
- package/dist/mobile-mocks/node/v8.js.map +1 -0
- package/dist/mobile-mocks/npm/env-paths.d.ts +6 -0
- package/dist/mobile-mocks/npm/env-paths.d.ts.map +1 -0
- package/dist/mobile-mocks/npm/env-paths.js +9 -0
- package/dist/mobile-mocks/npm/env-paths.js.map +1 -0
- package/dist/mobile-mocks/saltcorn/plugin-testing.d.ts +1 -0
- package/dist/mobile-mocks/saltcorn/plugin-testing.d.ts.map +1 -0
- package/dist/mobile-mocks/saltcorn/plugin-testing.js +2 -0
- package/dist/mobile-mocks/saltcorn/plugin-testing.js.map +1 -0
- package/dist/models/config.d.ts +9 -10
- package/dist/models/config.d.ts.map +1 -1
- package/dist/models/config.js +35 -12
- package/dist/models/config.js.map +1 -1
- package/dist/models/crash.js +5 -1
- package/dist/models/crash.js.map +1 -1
- package/dist/models/discovery.d.ts.map +1 -1
- package/dist/models/discovery.js +5 -1
- package/dist/models/discovery.js.map +1 -1
- package/dist/models/email.d.ts +2 -0
- package/dist/models/email.d.ts.map +1 -1
- package/dist/models/email.js +2 -2
- package/dist/models/email.js.map +1 -1
- package/dist/models/field.d.ts +6 -4
- package/dist/models/field.d.ts.map +1 -1
- package/dist/models/field.js +41 -21
- package/dist/models/field.js.map +1 -1
- package/dist/models/fieldrepeat.d.ts +5 -0
- package/dist/models/fieldrepeat.d.ts.map +1 -1
- package/dist/models/fieldrepeat.js +2 -0
- package/dist/models/fieldrepeat.js.map +1 -1
- package/dist/models/file.d.ts +6 -0
- package/dist/models/file.d.ts.map +1 -1
- package/dist/models/file.js +25 -1
- package/dist/models/file.js.map +1 -1
- package/dist/models/form.d.ts +2 -0
- package/dist/models/form.d.ts.map +1 -1
- package/dist/models/form.js +1 -0
- package/dist/models/form.js.map +1 -1
- package/dist/models/index.d.ts +2 -13
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/layout.d.ts.map +1 -1
- package/dist/models/layout.js +12 -2
- package/dist/models/layout.js.map +1 -1
- package/dist/models/page.d.ts +1 -1
- package/dist/models/page.d.ts.map +1 -1
- package/dist/models/page.js +17 -9
- package/dist/models/page.js.map +1 -1
- package/dist/models/plugin.d.ts +1 -1
- package/dist/models/plugin.d.ts.map +1 -1
- package/dist/models/plugin.js +10 -6
- package/dist/models/plugin.js.map +1 -1
- package/dist/models/scheduler.d.ts.map +1 -1
- package/dist/models/scheduler.js +3 -1
- package/dist/models/scheduler.js.map +1 -1
- package/dist/models/table.d.ts +2 -1
- package/dist/models/table.d.ts.map +1 -1
- package/dist/models/table.js +48 -12
- package/dist/models/table.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 +6 -5
- package/dist/models/trigger.js.map +1 -1
- package/dist/models/user.d.ts +1 -1
- package/dist/models/user.d.ts.map +1 -1
- package/dist/models/user.js +7 -15
- package/dist/models/user.js.map +1 -1
- package/dist/models/view.d.ts +25 -14
- package/dist/models/view.d.ts.map +1 -1
- package/dist/models/view.js +84 -25
- package/dist/models/view.js.map +1 -1
- package/dist/models/workflow.d.ts +1 -0
- package/dist/models/workflow.d.ts.map +1 -1
- package/dist/models/workflow.js +58 -2
- package/dist/models/workflow.js.map +1 -1
- package/dist/package.json +127 -0
- package/dist/plugin-helper.d.ts +19 -14
- package/dist/plugin-helper.d.ts.map +1 -1
- package/dist/plugin-helper.js +158 -80
- package/dist/plugin-helper.js.map +1 -1
- package/dist/plugin-testing.d.ts +1 -0
- package/dist/plugin-testing.d.ts.map +1 -1
- package/dist/plugin-testing.js +84 -1
- package/dist/plugin-testing.js.map +1 -1
- package/dist/tests/actions.test.js +30 -5
- package/dist/tests/actions.test.js.map +1 -1
- package/dist/tests/auxtest.test.js +100 -3
- package/dist/tests/auxtest.test.js.map +1 -1
- package/dist/tests/db.test.d.ts +2 -0
- package/dist/tests/db.test.d.ts.map +1 -0
- package/dist/tests/db.test.js +32 -0
- package/dist/tests/db.test.js.map +1 -0
- package/dist/tests/exact_views.test.js +277 -22
- package/dist/tests/exact_views.test.js.map +1 -1
- package/dist/tests/field.test.js +36 -0
- package/dist/tests/field.test.js.map +1 -1
- package/dist/tests/mocks.d.ts +2 -0
- package/dist/tests/mocks.d.ts.map +1 -1
- package/dist/tests/mocks.js +2 -0
- package/dist/tests/mocks.js.map +1 -1
- package/dist/tests/models.test.js +46 -1
- package/dist/tests/models.test.js.map +1 -1
- package/dist/tests/remote_query_helper.d.ts +341 -0
- package/dist/tests/remote_query_helper.d.ts.map +1 -0
- package/dist/tests/remote_query_helper.js +446 -0
- package/dist/tests/remote_query_helper.js.map +1 -0
- package/dist/tests/state.test.d.ts +2 -0
- package/dist/tests/state.test.d.ts.map +1 -0
- package/dist/tests/state.test.js +78 -0
- package/dist/tests/state.test.js.map +1 -0
- package/dist/tests/table.test.js +19 -0
- package/dist/tests/table.test.js.map +1 -1
- package/dist/tests/view.test.js +29 -0
- package/dist/tests/view.test.js.map +1 -1
- package/dist/tsconfig.json +24 -0
- package/dist/tsconfig.ref.json +9 -0
- package/dist/tsconfig.ref.tsbuildinfo +1 -1
- package/dist/utils.d.ts +3 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +14 -23
- package/dist/utils.js.map +1 -1
- package/dist/webpack.config.d.ts +57 -0
- package/dist/webpack.config.d.ts.map +1 -0
- package/dist/webpack.config.js +75 -0
- package/dist/webpack.config.js.map +1 -0
- package/package.json +39 -15
- package/CHANGELOG.md +0 -8
- package/dist/models/backup.d.ts +0 -9
- package/dist/models/backup.d.ts.map +0 -1
- package/dist/models/backup.js +0 -278
- package/dist/models/backup.js.map +0 -1
- package/dist/models/pack.d.ts +0 -42
- package/dist/models/pack.d.ts.map +0 -1
- package/dist/models/pack.js +0 -419
- package/dist/models/pack.js.map +0 -1
- package/dist/models/tenant.d.ts +0 -17
- package/dist/models/tenant.d.ts.map +0 -1
- package/dist/models/tenant.js +0 -152
- package/dist/models/tenant.js.map +0 -1
- package/dist/tests/backup.test.d.ts +0 -2
- package/dist/tests/backup.test.d.ts.map +0 -1
- package/dist/tests/backup.test.js +0 -101
- package/dist/tests/backup.test.js.map +0 -1
- package/dist/tests/pack.test.d.ts +0 -2
- package/dist/tests/pack.test.d.ts.map +0 -1
- package/dist/tests/pack.test.js +0 -338
- package/dist/tests/pack.test.js.map +0 -1
- package/dist/tests/random.test.d.ts +0 -2
- package/dist/tests/random.test.d.ts.map +0 -1
- package/dist/tests/random.test.js +0 -149
- package/dist/tests/random.test.js.map +0 -1
- package/dist/tests/tenant.test.d.ts +0 -2
- package/dist/tests/tenant.test.d.ts.map +0 -1
- package/dist/tests/tenant.test.js +0 -52
- package/dist/tests/tenant.test.js.map +0 -1
|
@@ -16,12 +16,13 @@ const { text, text_attr } = require("@saltcorn/markup/tags");
|
|
|
16
16
|
const { renderForm } = require("@saltcorn/markup");
|
|
17
17
|
const FieldRepeat = require("../../models/fieldrepeat");
|
|
18
18
|
const { get_expression_function, expressionChecker, } = require("../../models/expression");
|
|
19
|
-
const { InvalidConfiguration } = require("../../utils");
|
|
19
|
+
const { InvalidConfiguration, isNode } = require("../../utils");
|
|
20
20
|
const Library = require("../../models/library");
|
|
21
|
+
const { check_view_columns } = require("../../plugin-testing");
|
|
21
22
|
const { initial_config_all_fields, calcfldViewOptions, calcfldViewConfig, get_parent_views, get_link_view_opts, picked_fields_to_query, stateFieldsToWhere, stateFieldsToQuery, strictParseInt, } = require("../../plugin-helper");
|
|
22
23
|
const { splitUniques, getForm, fill_presets, parse_view_select, get_view_link_query, objToQueryString, } = require("./viewable_fields");
|
|
23
|
-
const { traverse, getStringsForI18n, translateLayout, } = require("../../models/layout");
|
|
24
|
-
const { asyncMap } = require("../../utils");
|
|
24
|
+
const { traverse, getStringsForI18n, translateLayout, traverseSync, } = require("../../models/layout");
|
|
25
|
+
const { asyncMap, isWeb } = require("../../utils");
|
|
25
26
|
/**
|
|
26
27
|
* @param {object} req
|
|
27
28
|
* @returns {Workflow}
|
|
@@ -42,7 +43,7 @@ const configuration_workflow = (req) => new Workflow({
|
|
|
42
43
|
await field.reftable.getFields();
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
|
-
const { field_view_options, handlesTextStyle } = calcfldViewOptions(fields, "edit");
|
|
46
|
+
const { field_view_options, handlesTextStyle, blockDisplay } = calcfldViewOptions(fields, "edit");
|
|
46
47
|
const fieldViewConfigForms = await calcfldViewConfig(fields, true);
|
|
47
48
|
const roles = await User.get_roles();
|
|
48
49
|
const images = await File.find({ mime_super: "image" });
|
|
@@ -115,6 +116,7 @@ const configuration_workflow = (req) => new Workflow({
|
|
|
115
116
|
field_view_options,
|
|
116
117
|
parent_field_list,
|
|
117
118
|
handlesTextStyle,
|
|
119
|
+
blockDisplay,
|
|
118
120
|
roles,
|
|
119
121
|
actions,
|
|
120
122
|
fieldViewConfigForms,
|
|
@@ -185,7 +187,6 @@ const configuration_workflow = (req) => new Workflow({
|
|
|
185
187
|
done_view_opts.push(`${v.name}.${relation.name}`);
|
|
186
188
|
}));
|
|
187
189
|
return new Form({
|
|
188
|
-
blurb: req.__("The view you choose here can be ignored depending on the context of the form, for instance if it appears in a pop-up the redirect will not take place."),
|
|
189
190
|
fields: [
|
|
190
191
|
{
|
|
191
192
|
name: "auto_save",
|
|
@@ -194,24 +195,36 @@ const configuration_workflow = (req) => new Workflow({
|
|
|
194
195
|
type: "Bool",
|
|
195
196
|
},
|
|
196
197
|
{
|
|
197
|
-
name: "
|
|
198
|
-
label:
|
|
199
|
-
sublabel: req.__("This is the view to which the user will be sent when the form is submitted, unless a formula below is true."),
|
|
198
|
+
name: "destination_type",
|
|
199
|
+
label: "Destination type",
|
|
200
200
|
type: "String",
|
|
201
201
|
required: true,
|
|
202
|
+
sublabel: req.__("This is the view to which the user will be sent when the form is submitted. The view you specify here can be ignored depending on the context of the form, for instance if it appears in a pop-up the redirect will not take place."),
|
|
203
|
+
//fieldview: "radio_group",
|
|
202
204
|
attributes: {
|
|
203
|
-
options:
|
|
205
|
+
options: ["View", "Formula", "Back to referer"],
|
|
204
206
|
},
|
|
205
207
|
},
|
|
206
208
|
{
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
name: "view_when_done",
|
|
210
|
+
label: req.__("Destination view"),
|
|
211
|
+
type: "String",
|
|
212
|
+
required: true,
|
|
213
|
+
attributes: {
|
|
214
|
+
options: done_view_opts,
|
|
215
|
+
},
|
|
216
|
+
showIf: { destination_type: "View" },
|
|
210
217
|
},
|
|
211
218
|
new FieldRepeat({
|
|
212
219
|
name: "formula_destinations",
|
|
220
|
+
showIf: { destination_type: "Formula" },
|
|
213
221
|
fields: [
|
|
214
|
-
{
|
|
222
|
+
{
|
|
223
|
+
type: "String",
|
|
224
|
+
name: "expression",
|
|
225
|
+
label: "Formula",
|
|
226
|
+
sublabel: "if this formula evaluates to true, use the following view",
|
|
227
|
+
},
|
|
215
228
|
{
|
|
216
229
|
name: "view",
|
|
217
230
|
label: req.__("View"),
|
|
@@ -268,26 +281,8 @@ const initial_config = initial_config_all_fields(true);
|
|
|
268
281
|
* @param {object} optsTwo.res
|
|
269
282
|
* @returns {Promise<Form>}
|
|
270
283
|
*/
|
|
271
|
-
const run = async (table_id, viewname, {
|
|
272
|
-
|
|
273
|
-
const fields = await table.getFields();
|
|
274
|
-
const { uniques, nonUniques } = splitUniques(fields, state);
|
|
275
|
-
let row = null;
|
|
276
|
-
if (Object.keys(uniques).length > 0) {
|
|
277
|
-
row = await table.getRow(uniques);
|
|
278
|
-
}
|
|
279
|
-
return await render({
|
|
280
|
-
table,
|
|
281
|
-
fields,
|
|
282
|
-
viewname,
|
|
283
|
-
columns,
|
|
284
|
-
layout,
|
|
285
|
-
row,
|
|
286
|
-
req,
|
|
287
|
-
res,
|
|
288
|
-
state,
|
|
289
|
-
auto_save,
|
|
290
|
-
});
|
|
284
|
+
const run = async (table_id, viewname, {}, state, { res, req }, { editQuery }) => {
|
|
285
|
+
return await editQuery(state);
|
|
291
286
|
};
|
|
292
287
|
/**
|
|
293
288
|
* @param {number} table_id
|
|
@@ -299,22 +294,8 @@ const run = async (table_id, viewname, { columns, layout, auto_save }, state, {
|
|
|
299
294
|
* @param {object} extra
|
|
300
295
|
* @returns {Promise<Form[]>}
|
|
301
296
|
*/
|
|
302
|
-
const runMany = async (table_id, viewname, { columns, layout, auto_save }, state, extra) => {
|
|
303
|
-
const table = await
|
|
304
|
-
const fields = await table.getFields();
|
|
305
|
-
const { joinFields, aggregations } = picked_fields_to_query(columns, fields);
|
|
306
|
-
const qstate = await stateFieldsToWhere({ fields, state });
|
|
307
|
-
const q = await stateFieldsToQuery({ state, fields });
|
|
308
|
-
const rows = await table.getJoinedRows({
|
|
309
|
-
where: qstate,
|
|
310
|
-
joinFields,
|
|
311
|
-
aggregations,
|
|
312
|
-
...(extra && extra.limit && { limit: extra.limit }),
|
|
313
|
-
...(extra && extra.offset && { offset: extra.offset }),
|
|
314
|
-
...(extra && extra.orderBy && { orderBy: extra.orderBy }),
|
|
315
|
-
...(extra && extra.orderDesc && { orderDesc: extra.orderDesc }),
|
|
316
|
-
...q,
|
|
317
|
-
});
|
|
297
|
+
const runMany = async (table_id, viewname, { columns, layout, auto_save }, state, extra, { editManyQuery, getRowQuery }) => {
|
|
298
|
+
const { table, fields, rows } = await editManyQuery();
|
|
318
299
|
return await asyncMap(rows, async (row) => {
|
|
319
300
|
const html = await render({
|
|
320
301
|
table,
|
|
@@ -327,6 +308,7 @@ const runMany = async (table_id, viewname, { columns, layout, auto_save }, state
|
|
|
327
308
|
res: extra.res,
|
|
328
309
|
state,
|
|
329
310
|
auto_save,
|
|
311
|
+
getRowQuery,
|
|
330
312
|
});
|
|
331
313
|
return { html, row };
|
|
332
314
|
});
|
|
@@ -341,7 +323,7 @@ const runMany = async (table_id, viewname, { columns, layout, auto_save }, state
|
|
|
341
323
|
* @throws {InvalidConfiguration}
|
|
342
324
|
* @returns {Promise<void>}
|
|
343
325
|
*/
|
|
344
|
-
const transformForm = async ({ form, table, req, row, res }) => {
|
|
326
|
+
const transformForm = async ({ form, table, req, row, res, getRowQuery }) => {
|
|
345
327
|
await traverse(form.layout, {
|
|
346
328
|
action(segment) {
|
|
347
329
|
if (segment.action_name === "Delete") {
|
|
@@ -359,13 +341,53 @@ const transformForm = async ({ form, table, req, row, res }) => {
|
|
|
359
341
|
segment.sourceURL = `/field/show-calculated/${table.name}/${segment.join_field}/${segment.fieldview}?${qs}`;
|
|
360
342
|
},
|
|
361
343
|
async view(segment) {
|
|
344
|
+
//console.log(segment);
|
|
345
|
+
const view_select = parse_view_select(segment.view);
|
|
346
|
+
//console.log({ view_select });
|
|
347
|
+
const view = await View.findOne({ name: view_select.viewname });
|
|
348
|
+
if (!view)
|
|
349
|
+
throw new InvalidConfiguration(`Cannot find embedded view: ${view_select.viewname}`);
|
|
350
|
+
if (view.viewtemplate === "Edit" && view_select.type === "ChildList") {
|
|
351
|
+
const childTable = Table.findOne({ id: view.table_id });
|
|
352
|
+
const childForm = await getForm(childTable, view.name, view.configuration.columns, view.configuration.layout, row?.id, req);
|
|
353
|
+
traverseSync(childForm.layout, {
|
|
354
|
+
field(segment) {
|
|
355
|
+
segment.field_name = `${view_select.field_name}.${segment.field_name}`;
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
const fr = new FieldRepeat({
|
|
359
|
+
name: view_select.field_name,
|
|
360
|
+
label: view_select.field_name,
|
|
361
|
+
fields: childForm.fields,
|
|
362
|
+
layout: childForm.layout,
|
|
363
|
+
metadata: {
|
|
364
|
+
table_id: childTable.id,
|
|
365
|
+
relation: view_select.field_name,
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
if (row?.id) {
|
|
369
|
+
const childRows = getRowQuery
|
|
370
|
+
? await getRowQuery(view.table_id, view_select, row.id)
|
|
371
|
+
: await childTable.getRows({
|
|
372
|
+
[view_select.field_name]: row.id,
|
|
373
|
+
});
|
|
374
|
+
fr.metadata.rows = childRows;
|
|
375
|
+
if (!fr.fields.map((f) => f.name).includes(childTable.pk_name))
|
|
376
|
+
fr.fields.push({
|
|
377
|
+
name: childTable.pk_name,
|
|
378
|
+
input_type: "hidden",
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
form.fields.push(fr);
|
|
382
|
+
segment.type = "field_repeat";
|
|
383
|
+
segment.field_repeat = fr;
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
362
386
|
if (!row) {
|
|
363
387
|
segment.type = "blank";
|
|
364
388
|
segment.contents = "";
|
|
365
389
|
return;
|
|
366
390
|
}
|
|
367
|
-
const view_select = parse_view_select(segment.view);
|
|
368
|
-
const view = await View.findOne({ name: view_select.viewname });
|
|
369
391
|
if (!view)
|
|
370
392
|
throw new InvalidConfiguration(`Edit view incorrectly configured: cannot find embedded view ${view_select.viewname}`);
|
|
371
393
|
let state;
|
|
@@ -405,10 +427,10 @@ const transformForm = async ({ form, table, req, row, res }) => {
|
|
|
405
427
|
* @param {object} opts.res
|
|
406
428
|
* @returns {Promise<Form>}
|
|
407
429
|
*/
|
|
408
|
-
const render = async ({ table, fields, viewname, columns, layout, row, req, state, res, auto_save, }) => {
|
|
409
|
-
const form = await getForm(table, viewname, columns, layout, state.id, req);
|
|
430
|
+
const render = async ({ table, fields, viewname, columns, layout, row, req, state, res, auto_save, destination_type, isRemote, getRowQuery, }) => {
|
|
431
|
+
const form = await getForm(table, viewname, columns, layout, state.id, req, isRemote);
|
|
410
432
|
if (auto_save)
|
|
411
|
-
form.onChange = `saveAndContinue(this)`;
|
|
433
|
+
form.onChange = `saveAndContinue(this, ${!isWeb(req) ? `'${form.action}'` : undefined})`;
|
|
412
434
|
if (row) {
|
|
413
435
|
form.values = row;
|
|
414
436
|
const file_fields = form.fields.filter((f) => f.type === "File");
|
|
@@ -420,6 +442,10 @@ const render = async ({ table, fields, viewname, columns, layout, row, req, stat
|
|
|
420
442
|
}
|
|
421
443
|
form.hidden(table.pk_name);
|
|
422
444
|
}
|
|
445
|
+
if (destination_type === "Back to referer") {
|
|
446
|
+
form.hidden("_referer");
|
|
447
|
+
form.values._referer = req.headers?.referer;
|
|
448
|
+
}
|
|
423
449
|
Object.entries(state).forEach(([k, v]) => {
|
|
424
450
|
const field = form.fields.find((f) => f.name === k);
|
|
425
451
|
if (field && ((field.type && field.type.read) || field.is_fkey)) {
|
|
@@ -434,8 +460,8 @@ const render = async ({ table, fields, viewname, columns, layout, row, req, stat
|
|
|
434
460
|
}
|
|
435
461
|
});
|
|
436
462
|
await form.fill_fkey_options();
|
|
437
|
-
await transformForm({ form, table, req, row, res });
|
|
438
|
-
return renderForm(form, req.csrfToken());
|
|
463
|
+
await transformForm({ form, table, req, row, res, getRowQuery });
|
|
464
|
+
return renderForm(form, !isRemote ? req.csrfToken() : false);
|
|
439
465
|
};
|
|
440
466
|
/**
|
|
441
467
|
* @param {number} table_id
|
|
@@ -454,12 +480,12 @@ const render = async ({ table, fields, viewname, columns, layout, row, req, stat
|
|
|
454
480
|
* @param {string} optsTwo.redirect
|
|
455
481
|
* @returns {Promise<void>}
|
|
456
482
|
*/
|
|
457
|
-
const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_done, formula_destinations, auto_save }, state, body, { res, req, redirect }) => {
|
|
483
|
+
const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_done, formula_destinations, auto_save, destination_type, }, state, body, { res, req, redirect }, { tryInsertQuery, tryUpdateQuery, getRowQuery }, remote) => {
|
|
458
484
|
const table = await Table.findOne({ id: table_id });
|
|
459
485
|
const fields = await table.getFields();
|
|
460
486
|
const form = await getForm(table, viewname, columns, layout, body.id, req);
|
|
461
487
|
if (auto_save)
|
|
462
|
-
form.onChange = `saveAndContinue(this)`;
|
|
488
|
+
form.onChange = `saveAndContinue(this, ${!isWeb(req) ? `'${form.action}'` : undefined})`;
|
|
463
489
|
Object.entries(body).forEach(([k, v]) => {
|
|
464
490
|
const form_field = form.fields.find((f) => f.name === k);
|
|
465
491
|
const tbl_field = fields.find((f) => f.name === k);
|
|
@@ -468,13 +494,21 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
|
|
|
468
494
|
}
|
|
469
495
|
});
|
|
470
496
|
setDateLocales(form, req.getLocale());
|
|
497
|
+
await transformForm({
|
|
498
|
+
form,
|
|
499
|
+
table,
|
|
500
|
+
req,
|
|
501
|
+
row: body[table.pk_name]
|
|
502
|
+
? { [table.pk_name]: body[table.pk_name] }
|
|
503
|
+
: undefined,
|
|
504
|
+
getRowQuery,
|
|
505
|
+
});
|
|
471
506
|
form.validate(body);
|
|
472
507
|
if (form.hasErrors) {
|
|
473
508
|
if (req.xhr)
|
|
474
509
|
res.status(422);
|
|
475
510
|
await form.fill_fkey_options();
|
|
476
|
-
|
|
477
|
-
res.sendWrap(viewname, renderForm(form, req.csrfToken()));
|
|
511
|
+
res.sendWrap(viewname, renderForm(form, req.csrfToken ? req.csrfToken() : false));
|
|
478
512
|
}
|
|
479
513
|
else {
|
|
480
514
|
let row;
|
|
@@ -485,12 +519,22 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
|
|
|
485
519
|
row = { ...use_fixed, ...form.values };
|
|
486
520
|
}
|
|
487
521
|
else {
|
|
488
|
-
row = form.values;
|
|
522
|
+
row = { ...form.values };
|
|
523
|
+
}
|
|
524
|
+
for (const field of form.fields.filter((f) => f.isRepeat)) {
|
|
525
|
+
delete row[field.name];
|
|
489
526
|
}
|
|
490
527
|
const file_fields = form.fields.filter((f) => f.type === "File");
|
|
491
528
|
for (const field of file_fields) {
|
|
492
529
|
if (req.files && req.files[field.name]) {
|
|
493
|
-
|
|
530
|
+
if (!isNode() && !remote) {
|
|
531
|
+
req.flash("error", "The mobile-app supports no local files, please use a remote table.");
|
|
532
|
+
res.sendWrap(viewname, renderForm(form, req.csrfToken ? req.csrfToken() : false));
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
const file = isNode()
|
|
536
|
+
? await File.from_req_files(req.files[field.name], req.user ? req.user.id : null, (field.attributes && +field.attributes.min_role_read) || 1)
|
|
537
|
+
: await File.upload(req.files[field.name]);
|
|
494
538
|
row[field.name] = file.id;
|
|
495
539
|
}
|
|
496
540
|
else {
|
|
@@ -499,77 +543,102 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
|
|
|
499
543
|
}
|
|
500
544
|
const originalID = id;
|
|
501
545
|
if (typeof id === "undefined") {
|
|
502
|
-
const ins_res = await
|
|
546
|
+
const ins_res = await tryInsertQuery(row);
|
|
503
547
|
if (ins_res.success) {
|
|
504
548
|
id = ins_res.success;
|
|
505
549
|
row[pk.name] = id;
|
|
506
550
|
}
|
|
507
551
|
else {
|
|
508
552
|
req.flash("error", text_attr(ins_res.error));
|
|
509
|
-
res.sendWrap(viewname, renderForm(form, req.csrfToken()));
|
|
553
|
+
res.sendWrap(viewname, renderForm(form, req.csrfToken ? req.csrfToken() : false));
|
|
510
554
|
return;
|
|
511
555
|
}
|
|
512
556
|
}
|
|
513
557
|
else {
|
|
514
|
-
const upd_res = await
|
|
558
|
+
const upd_res = await tryUpdateQuery(row, id);
|
|
515
559
|
if (upd_res.error) {
|
|
516
560
|
req.flash("error", text_attr(upd_res.error));
|
|
517
561
|
res.sendWrap(viewname, renderForm(form, req.csrfToken()));
|
|
518
562
|
return;
|
|
519
563
|
}
|
|
520
564
|
}
|
|
521
|
-
|
|
522
|
-
|
|
565
|
+
for (const field of form.fields.filter((f) => f.isRepeat)) {
|
|
566
|
+
const childTable = Table.findOne({ id: field.metadata?.table_id });
|
|
567
|
+
for (const childRow of form.values[field.name]) {
|
|
568
|
+
childRow[field.metadata?.relation] = id;
|
|
569
|
+
if (childRow[childTable.pk_name]) {
|
|
570
|
+
const upd_res = await childTable.tryUpdateRow(childRow, childRow[childTable.pk_name]);
|
|
571
|
+
if (upd_res.error) {
|
|
572
|
+
req.flash("error", text_attr(upd_res.error));
|
|
573
|
+
res.sendWrap(viewname, renderForm(form, req.csrfToken()));
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
const ins_res = await childTable.tryInsertRow(childRow, req.user ? +req.user.id : undefined);
|
|
579
|
+
if (ins_res.error) {
|
|
580
|
+
req.flash("error", text_attr(ins_res.error));
|
|
581
|
+
res.sendWrap(viewname, renderForm(form, req.csrfToken()));
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (req.xhr && !originalID && !req.smr) {
|
|
588
|
+
res.json({ id, view_when_done });
|
|
523
589
|
return;
|
|
524
590
|
}
|
|
525
591
|
if (redirect) {
|
|
526
592
|
res.redirect(redirect);
|
|
527
593
|
return;
|
|
528
594
|
}
|
|
529
|
-
|
|
530
|
-
|
|
595
|
+
let use_view_when_done = view_when_done;
|
|
596
|
+
if (destination_type === "Back to referer" && body._referer) {
|
|
597
|
+
res.redirect(body._referer);
|
|
531
598
|
return;
|
|
532
599
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
600
|
+
else if (destination_type !== "View")
|
|
601
|
+
for (const { view, expression } of formula_destinations || []) {
|
|
602
|
+
if (expression) {
|
|
603
|
+
const f = get_expression_function(expression, fields);
|
|
604
|
+
if (f(row)) {
|
|
605
|
+
use_view_when_done = view;
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
540
608
|
}
|
|
541
609
|
}
|
|
610
|
+
if (!use_view_when_done) {
|
|
611
|
+
res.redirect(`/`);
|
|
612
|
+
return;
|
|
542
613
|
}
|
|
543
614
|
const [viewname_when_done, relation] = use_view_when_done.split(".");
|
|
544
615
|
const nxview = await View.findOne({ name: viewname_when_done });
|
|
545
|
-
//console.log()
|
|
546
616
|
if (!nxview) {
|
|
547
617
|
req.flash("warning", `View "${use_view_when_done}" not found - change "View when done" in "${viewname}" view`);
|
|
548
618
|
res.redirect(`/`);
|
|
549
619
|
}
|
|
550
620
|
else {
|
|
551
621
|
const state_fields = await nxview.get_state_fields();
|
|
622
|
+
let target = `/view/${text(viewname_when_done)}`;
|
|
623
|
+
let query = "";
|
|
552
624
|
if ((nxview.table_id === table_id || relation) &&
|
|
553
625
|
state_fields.some((sf) => sf.name === pk.name)) {
|
|
554
626
|
const get_query = get_view_link_query(fields);
|
|
555
|
-
|
|
627
|
+
query = relation
|
|
556
628
|
? `?${pk.name}=${text(row[relation])}`
|
|
557
629
|
: get_query(row);
|
|
558
|
-
res.redirect(`/view/${text(viewname_when_done)}${query}`);
|
|
559
630
|
}
|
|
560
|
-
|
|
561
|
-
|
|
631
|
+
const redirectPath = `${target}${query}`;
|
|
632
|
+
if (!isWeb(req)) {
|
|
633
|
+
res.json({ redirect: `get${redirectPath}` });
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
res.redirect(redirectPath);
|
|
637
|
+
}
|
|
562
638
|
}
|
|
563
639
|
}
|
|
564
640
|
};
|
|
565
|
-
|
|
566
|
-
* @param {object} opts
|
|
567
|
-
* @param {object} opts.body
|
|
568
|
-
* @param {string} opts.table_id
|
|
569
|
-
* @param {object} opts.req
|
|
570
|
-
* @returns {Promise<boolean>}
|
|
571
|
-
*/
|
|
572
|
-
const authorise_post = async ({ body, table_id, req }) => {
|
|
641
|
+
const doAuthPost = async ({ body, table_id, req }) => {
|
|
573
642
|
const table = await Table.findOne({ id: table_id });
|
|
574
643
|
const user_id = req.user ? req.user.id : null;
|
|
575
644
|
if (table.ownership_field_id && user_id) {
|
|
@@ -592,6 +661,16 @@ const authorise_post = async ({ body, table_id, req }) => {
|
|
|
592
661
|
return true;
|
|
593
662
|
return false;
|
|
594
663
|
};
|
|
664
|
+
/**
|
|
665
|
+
* @param {object} opts
|
|
666
|
+
* @param {object} opts.body
|
|
667
|
+
* @param {string} opts.table_id
|
|
668
|
+
* @param {object} opts.req
|
|
669
|
+
* @returns {Promise<boolean>}
|
|
670
|
+
*/
|
|
671
|
+
const authorise_post = async ({ body, table_id, req }, { authorizePostQuery }) => {
|
|
672
|
+
return await authorizePostQuery(body, table_id);
|
|
673
|
+
};
|
|
595
674
|
module.exports = {
|
|
596
675
|
/** @type {string} */
|
|
597
676
|
name: "Edit",
|
|
@@ -612,20 +691,8 @@ module.exports = {
|
|
|
612
691
|
* @param {...*} opts.rest
|
|
613
692
|
* @returns {Promise<boolean>}
|
|
614
693
|
*/
|
|
615
|
-
authorise_get: async ({ query, table_id, req }) => {
|
|
616
|
-
|
|
617
|
-
if (Object.keys(body).length == 1) {
|
|
618
|
-
const table = await Table.findOne({ id: table_id });
|
|
619
|
-
if (table.ownership_field_id || table.ownership_formula) {
|
|
620
|
-
const fields = await table.getFields();
|
|
621
|
-
const { uniques } = splitUniques(fields, body);
|
|
622
|
-
if (Object.keys(uniques).length > 0) {
|
|
623
|
-
body = await table.getRow(uniques);
|
|
624
|
-
return table.is_owner(req.user, body);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
return authorise_post({ body, table_id, req });
|
|
694
|
+
authorise_get: async ({ query, table_id, req }, { authorizeGetQuery }) => {
|
|
695
|
+
return await authorizeGetQuery(query, table_id);
|
|
629
696
|
},
|
|
630
697
|
/**
|
|
631
698
|
* @param {object} opts
|
|
@@ -635,17 +702,103 @@ module.exports = {
|
|
|
635
702
|
getStringsForI18n({ layout }) {
|
|
636
703
|
return getStringsForI18n(layout);
|
|
637
704
|
},
|
|
638
|
-
|
|
705
|
+
queries: ({ table_id, name, configuration: { columns, default_state, layout, auto_save, destination_type, }, req, res, }) => ({
|
|
706
|
+
async editQuery(state) {
|
|
707
|
+
const table = await Table.findOne({ id: table_id });
|
|
708
|
+
const fields = await table.getFields();
|
|
709
|
+
const { uniques } = splitUniques(fields, state);
|
|
710
|
+
let row = null;
|
|
711
|
+
if (Object.keys(uniques).length > 0) {
|
|
712
|
+
row = await table.getRow(uniques);
|
|
713
|
+
}
|
|
714
|
+
const isRemote = !isWeb(req);
|
|
715
|
+
return await render({
|
|
716
|
+
table,
|
|
717
|
+
fields,
|
|
718
|
+
viewname: name,
|
|
719
|
+
columns,
|
|
720
|
+
layout,
|
|
721
|
+
row,
|
|
722
|
+
req,
|
|
723
|
+
res,
|
|
724
|
+
state,
|
|
725
|
+
auto_save,
|
|
726
|
+
destination_type,
|
|
727
|
+
isRemote,
|
|
728
|
+
});
|
|
729
|
+
},
|
|
730
|
+
async editManyQuery(state) {
|
|
731
|
+
const table = await Table.findOne({ id: table_id });
|
|
732
|
+
const fields = await table.getFields();
|
|
733
|
+
const { joinFields, aggregations } = picked_fields_to_query(columns, fields);
|
|
734
|
+
const qstate = await stateFieldsToWhere({ fields, state });
|
|
735
|
+
const q = await stateFieldsToQuery({ state, fields });
|
|
736
|
+
const rows = await table.getJoinedRows({
|
|
737
|
+
where: qstate,
|
|
738
|
+
joinFields,
|
|
739
|
+
aggregations,
|
|
740
|
+
...(extra && extra.limit && { limit: extra.limit }),
|
|
741
|
+
...(extra && extra.offset && { offset: extra.offset }),
|
|
742
|
+
...(extra && extra.orderBy && { orderBy: extra.orderBy }),
|
|
743
|
+
...(extra && extra.orderDesc && { orderDesc: extra.orderDesc }),
|
|
744
|
+
...q,
|
|
745
|
+
});
|
|
746
|
+
return {
|
|
747
|
+
table,
|
|
748
|
+
fields,
|
|
749
|
+
rows,
|
|
750
|
+
};
|
|
751
|
+
},
|
|
752
|
+
async tryInsertQuery(row) {
|
|
753
|
+
const table = await Table.findOne({ id: table_id });
|
|
754
|
+
const ins_res = await table.tryInsertRow(row, req.user ? +req.user.id : undefined);
|
|
755
|
+
return ins_res;
|
|
756
|
+
},
|
|
757
|
+
async tryUpdateQuery(row, id) {
|
|
758
|
+
const table = await Table.findOne({ id: table_id });
|
|
759
|
+
const upd_res = await table.tryUpdateRow(row, id, req.user ? +req.user.id : undefined);
|
|
760
|
+
return upd_res;
|
|
761
|
+
},
|
|
762
|
+
async authorizePostQuery(body, table_id /*overwrites*/) {
|
|
763
|
+
return await doAuthPost({ body, table_id, req });
|
|
764
|
+
},
|
|
765
|
+
async authorizeGetQuery(query, table_id) {
|
|
766
|
+
let body = query || {};
|
|
767
|
+
if (Object.keys(body).length == 1) {
|
|
768
|
+
const table = await Table.findOne({ id: table_id });
|
|
769
|
+
if (table.ownership_field_id || table.ownership_formula) {
|
|
770
|
+
const fields = await table.getFields();
|
|
771
|
+
const { uniques } = splitUniques(fields, body);
|
|
772
|
+
if (Object.keys(uniques).length > 0) {
|
|
773
|
+
body = await table.getRow(uniques);
|
|
774
|
+
return table.is_owner(req.user, body);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return doAuthPost({ body, table_id, req });
|
|
779
|
+
},
|
|
780
|
+
async getRowQuery(table_id, view_select, row_id) {
|
|
781
|
+
const childTable = Table.findOne({ id: table_id });
|
|
782
|
+
return await childTable.getRows({
|
|
783
|
+
[view_select.field_name]: row_id,
|
|
784
|
+
});
|
|
785
|
+
},
|
|
786
|
+
}),
|
|
787
|
+
configCheck: async (view) => {
|
|
788
|
+
const { name, configuration: { view_when_done, destination_type, formula_destinations }, } = view;
|
|
639
789
|
const errs = [];
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
790
|
+
if (destination_type !== "Back to referer") {
|
|
791
|
+
const vwd = await View.findOne({
|
|
792
|
+
name: (view_when_done || "").split(".")[0],
|
|
793
|
+
});
|
|
794
|
+
if (!vwd)
|
|
795
|
+
errs.push(`In View ${name}, view when done ${view_when_done} not found`);
|
|
796
|
+
for (const { expression } of formula_destinations || []) {
|
|
797
|
+
if (expression)
|
|
798
|
+
expressionChecker(expression, `In View ${name}, destination formula ${expression} error: `, errs);
|
|
799
|
+
}
|
|
648
800
|
}
|
|
801
|
+
errs.push(...(await check_view_columns(view, view.configuration.columns)));
|
|
649
802
|
return errs;
|
|
650
803
|
},
|
|
651
804
|
};
|