@saltcorn/data 0.6.1-beta.0 → 0.6.1
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/base-plugin/actions.js +172 -1
- package/base-plugin/fieldviews.js +63 -0
- package/base-plugin/fileviews.js +41 -0
- package/base-plugin/index.js +35 -0
- package/base-plugin/types.js +345 -9
- package/base-plugin/viewtemplates/edit.js +107 -0
- package/base-plugin/viewtemplates/feed.js +46 -0
- package/base-plugin/viewtemplates/filter.js +43 -0
- package/base-plugin/viewtemplates/list.js +73 -1
- package/base-plugin/viewtemplates/listshowlist.js +54 -3
- package/base-plugin/viewtemplates/room.js +100 -0
- package/base-plugin/viewtemplates/show.js +86 -0
- package/base-plugin/viewtemplates/viewable_fields.js +124 -0
- package/contracts.js +58 -0
- package/db/connect.js +13 -5
- package/db/db.test.js +0 -154
- package/db/fixtures.js +13 -1
- package/db/index.js +42 -3
- package/db/reset_schema.js +11 -0
- package/db/state.js +105 -36
- package/index.js +13 -0
- package/migrate.js +4 -1
- package/models/backup.js +78 -0
- package/models/config.js +113 -22
- package/models/crash.js +44 -0
- package/models/discovery.js +13 -11
- package/models/email.js +17 -0
- package/models/eventlog.js +51 -0
- package/models/expression.js +49 -1
- package/models/field.js +88 -9
- package/models/fieldrepeat.js +33 -0
- package/models/file.js +23 -4
- package/models/form.js +34 -0
- package/models/index.js +42 -0
- package/models/layout.js +33 -0
- package/models/library.js +44 -0
- package/models/pack.js +88 -0
- package/models/page.js +13 -3
- package/models/plugin.js +9 -2
- package/models/random.js +36 -0
- package/models/role.js +36 -0
- package/models/scheduler.js +28 -0
- package/models/table.js +34 -15
- package/models/table_constraints.js +44 -0
- package/models/tenant.js +46 -9
- package/models/trigger.js +24 -11
- package/models/user.js +33 -8
- package/models/view.js +89 -8
- package/models/workflow.js +31 -0
- package/package.json +7 -5
- package/plugin-helper.js +102 -44
- package/plugin-testing.js +4 -0
- package/tests/exact_views.test.js +5 -5
- package/utils.js +4 -0
- package/db/internal.js +0 -229
- package/db/multi-tenant.js +0 -24
- package/db/pg.js +0 -374
- package/db/single-tenant.js +0 -8
- package/db/sqlite.js +0 -280
- package/db/tenants.js +0 -6
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-data
|
|
3
|
+
* @module base-plugin/viewtemplates/edit
|
|
4
|
+
* @subcategory base-plugin
|
|
5
|
+
*/
|
|
1
6
|
const Field = require("../../models/field");
|
|
2
7
|
const File = require("../../models/file");
|
|
3
8
|
const Table = require("../../models/table");
|
|
@@ -37,6 +42,10 @@ const {
|
|
|
37
42
|
} = require("../../models/layout");
|
|
38
43
|
const { asyncMap } = require("../../utils");
|
|
39
44
|
|
|
45
|
+
/**
|
|
46
|
+
* @param {object} req
|
|
47
|
+
* @returns {Workflow}
|
|
48
|
+
*/
|
|
40
49
|
const configuration_workflow = (req) =>
|
|
41
50
|
new Workflow({
|
|
42
51
|
steps: [
|
|
@@ -240,6 +249,14 @@ const configuration_workflow = (req) =>
|
|
|
240
249
|
},
|
|
241
250
|
],
|
|
242
251
|
});
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @param {*} table_id
|
|
255
|
+
* @param {*} viewname
|
|
256
|
+
* @param {object} opts
|
|
257
|
+
* @param {*} opts.columns
|
|
258
|
+
* @returns {Promise<object[]>}
|
|
259
|
+
*/
|
|
243
260
|
const get_state_fields = async (table_id, viewname, { columns }) => [
|
|
244
261
|
{
|
|
245
262
|
name: "id",
|
|
@@ -248,6 +265,10 @@ const get_state_fields = async (table_id, viewname, { columns }) => [
|
|
|
248
265
|
},
|
|
249
266
|
];
|
|
250
267
|
|
|
268
|
+
/**
|
|
269
|
+
* @param {Form} form
|
|
270
|
+
* @param {string} locale
|
|
271
|
+
*/
|
|
251
272
|
const setDateLocales = (form, locale) => {
|
|
252
273
|
form.fields.forEach((f) => {
|
|
253
274
|
if (f.type && f.type.name === "Date") {
|
|
@@ -256,8 +277,21 @@ const setDateLocales = (form, locale) => {
|
|
|
256
277
|
});
|
|
257
278
|
};
|
|
258
279
|
|
|
280
|
+
/** @type {function} */
|
|
259
281
|
const initial_config = initial_config_all_fields(true);
|
|
260
282
|
|
|
283
|
+
/**
|
|
284
|
+
* @param {number} table_id
|
|
285
|
+
* @param {string} viewname
|
|
286
|
+
* @param {object} optsOne
|
|
287
|
+
* @param {*} optsOne.columns
|
|
288
|
+
* @param {*} optsOne.layout
|
|
289
|
+
* @param {string} state
|
|
290
|
+
* @param {object} optsTwo
|
|
291
|
+
* @param {object} optsTwo.req
|
|
292
|
+
* @param {object} optsTwo.res
|
|
293
|
+
* @returns {Promise<Form>}
|
|
294
|
+
*/
|
|
261
295
|
const run = async (
|
|
262
296
|
table_id,
|
|
263
297
|
viewname,
|
|
@@ -284,6 +318,17 @@ const run = async (
|
|
|
284
318
|
state,
|
|
285
319
|
});
|
|
286
320
|
};
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @param {number} table_id
|
|
324
|
+
* @param {string} viewname
|
|
325
|
+
* @param {object} opts
|
|
326
|
+
* @param {*} opts.columns
|
|
327
|
+
* @param {*} opts.layout
|
|
328
|
+
* @param {State} state
|
|
329
|
+
* @param {object} extra
|
|
330
|
+
* @returns {Promise<Form[]>}
|
|
331
|
+
*/
|
|
287
332
|
const runMany = async (
|
|
288
333
|
table_id,
|
|
289
334
|
viewname,
|
|
@@ -323,6 +368,16 @@ const runMany = async (
|
|
|
323
368
|
});
|
|
324
369
|
};
|
|
325
370
|
|
|
371
|
+
/**
|
|
372
|
+
* @param {object} opts
|
|
373
|
+
* @param {Form} opts.form
|
|
374
|
+
* @param {Table} opts.table
|
|
375
|
+
* @param {object} opts.req
|
|
376
|
+
* @param {object} opts.row
|
|
377
|
+
* @param {object} opts.res
|
|
378
|
+
* @throws {InvalidConfiguration}
|
|
379
|
+
* @returns {Promise<void>}
|
|
380
|
+
*/
|
|
326
381
|
const transformForm = async ({ form, table, req, row, res }) => {
|
|
327
382
|
await traverse(form.layout, {
|
|
328
383
|
action(segment) {
|
|
@@ -371,6 +426,19 @@ const transformForm = async ({ form, table, req, row, res }) => {
|
|
|
371
426
|
setDateLocales(form, req.getLocale());
|
|
372
427
|
};
|
|
373
428
|
|
|
429
|
+
/**
|
|
430
|
+
* @param {object} opts
|
|
431
|
+
* @param {Table} opts.table
|
|
432
|
+
* @param {Fields[]} opts.fields
|
|
433
|
+
* @param {string} opts.viewname
|
|
434
|
+
* @param {object[]} opts.columns
|
|
435
|
+
* @param {Layout} opts.layout
|
|
436
|
+
* @param {object} opts.row
|
|
437
|
+
* @param {object} opts.req
|
|
438
|
+
* @param {object} opts.state
|
|
439
|
+
* @param {object} opts.res
|
|
440
|
+
* @returns {Promise<Form>}
|
|
441
|
+
*/
|
|
374
442
|
const render = async ({
|
|
375
443
|
table,
|
|
376
444
|
fields,
|
|
@@ -413,6 +481,23 @@ const render = async ({
|
|
|
413
481
|
return renderForm(form, req.csrfToken());
|
|
414
482
|
};
|
|
415
483
|
|
|
484
|
+
/**
|
|
485
|
+
* @param {number} table_id
|
|
486
|
+
* @param {string} viewname
|
|
487
|
+
* @param {object} optsOne
|
|
488
|
+
* @param {object[]} optsOne.columns
|
|
489
|
+
* @param {Layout} optsOne.layout
|
|
490
|
+
* @param {object} optsOne.fixed
|
|
491
|
+
* @param {boolean} optsOne.view_when_done
|
|
492
|
+
* @param {object[]} optsOne.formula_destinations
|
|
493
|
+
* @param {object} state
|
|
494
|
+
* @param {*} body
|
|
495
|
+
* @param {object} optsTwo
|
|
496
|
+
* @param {object} optsTwo.res
|
|
497
|
+
* @param {object} optsTwo.req
|
|
498
|
+
* @param {string} optsTwo.redirect
|
|
499
|
+
* @returns {Promise<void>}
|
|
500
|
+
*/
|
|
416
501
|
const runPost = async (
|
|
417
502
|
table_id,
|
|
418
503
|
viewname,
|
|
@@ -526,6 +611,14 @@ const runPost = async (
|
|
|
526
611
|
}
|
|
527
612
|
}
|
|
528
613
|
};
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* @param {object} opts
|
|
617
|
+
* @param {object} opts.body
|
|
618
|
+
* @param {string} opts.table_id
|
|
619
|
+
* @param {object} opts.req
|
|
620
|
+
* @returns {Promise<boolean>}
|
|
621
|
+
*/
|
|
529
622
|
const authorise_post = async ({ body, table_id, req }) => {
|
|
530
623
|
const table = await Table.findOne({ id: table_id });
|
|
531
624
|
const user_id = req.user ? req.user.id : null;
|
|
@@ -540,7 +633,9 @@ const authorise_post = async ({ body, table_id, req }) => {
|
|
|
540
633
|
return false;
|
|
541
634
|
};
|
|
542
635
|
module.exports = {
|
|
636
|
+
/** @type {string} */
|
|
543
637
|
name: "Edit",
|
|
638
|
+
/** @type {string} */
|
|
544
639
|
description: "Form for creating a new row or editing existing rows",
|
|
545
640
|
configuration_workflow,
|
|
546
641
|
run,
|
|
@@ -548,10 +643,22 @@ module.exports = {
|
|
|
548
643
|
runPost,
|
|
549
644
|
get_state_fields,
|
|
550
645
|
initial_config,
|
|
646
|
+
/** @type {boolean} */
|
|
551
647
|
display_state_form: false,
|
|
552
648
|
authorise_post,
|
|
649
|
+
/**
|
|
650
|
+
* @param {object} opts
|
|
651
|
+
* @param {object} opts.query
|
|
652
|
+
* @param {...*} opts.rest
|
|
653
|
+
* @returns {Promise<boolean>}
|
|
654
|
+
*/
|
|
553
655
|
authorise_get: async ({ query, ...rest }) =>
|
|
554
656
|
authorise_post({ body: query, ...rest }),
|
|
657
|
+
/**
|
|
658
|
+
* @param {object} opts
|
|
659
|
+
* @param {Layout} opts.layout
|
|
660
|
+
* @returns {string[]}
|
|
661
|
+
*/
|
|
555
662
|
getStringsForI18n({ layout }) {
|
|
556
663
|
return getStringsForI18n(layout);
|
|
557
664
|
},
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-data
|
|
3
|
+
* @module base-plugin/viewtemplates/feed
|
|
4
|
+
* @subcategory base-plugin
|
|
5
|
+
*/
|
|
1
6
|
const Field = require("../../models/field");
|
|
2
7
|
const Table = require("../../models/table");
|
|
3
8
|
const Form = require("../../models/form");
|
|
@@ -19,6 +24,10 @@ const {
|
|
|
19
24
|
const { InvalidConfiguration } = require("../../utils");
|
|
20
25
|
const { getState } = require("../../db/state");
|
|
21
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @param {object} req
|
|
29
|
+
* @returns {Workflow}
|
|
30
|
+
*/
|
|
22
31
|
const configuration_workflow = (req) =>
|
|
23
32
|
new Workflow({
|
|
24
33
|
steps: [
|
|
@@ -218,6 +227,13 @@ const configuration_workflow = (req) =>
|
|
|
218
227
|
],
|
|
219
228
|
});
|
|
220
229
|
|
|
230
|
+
/**
|
|
231
|
+
* @param {number} table_id
|
|
232
|
+
* @param {*} viewname
|
|
233
|
+
* @param {object} opts
|
|
234
|
+
* @param {*} opts.show_view
|
|
235
|
+
* @returns {Promise<Field>}
|
|
236
|
+
*/
|
|
221
237
|
const get_state_fields = async (table_id, viewname, { show_view }) => {
|
|
222
238
|
const table_fields = await Field.find({ table_id });
|
|
223
239
|
return table_fields
|
|
@@ -228,6 +244,28 @@ const get_state_fields = async (table_id, viewname, { show_view }) => {
|
|
|
228
244
|
return sf;
|
|
229
245
|
});
|
|
230
246
|
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @param {number} table_id
|
|
250
|
+
* @param {string} viewname
|
|
251
|
+
* @param {object} opts
|
|
252
|
+
* @param {string} opts.show_view
|
|
253
|
+
* @param {name} opts.order_field
|
|
254
|
+
* @param {boolean} opts.descending
|
|
255
|
+
* @param {string} [opts.view_to_create]
|
|
256
|
+
* @param {string} opts.create_view_display
|
|
257
|
+
* @param {boolean} opts.in_card
|
|
258
|
+
* @param {string} opts.masonry_columns
|
|
259
|
+
* @param {number} [opts.rows_per_page = 20]
|
|
260
|
+
* @param {boolean} opts.hide_pagination
|
|
261
|
+
* @param {string} [opts.create_view_label]
|
|
262
|
+
* @param {string} [opts.create_view_location]
|
|
263
|
+
* @param {boolean} opts.always_create_view
|
|
264
|
+
* @param {*} opts.cols
|
|
265
|
+
* @param {object} state
|
|
266
|
+
* @param {*} extraArgs
|
|
267
|
+
* @returns {Promise<div>}
|
|
268
|
+
*/
|
|
231
269
|
const run = async (
|
|
232
270
|
table_id,
|
|
233
271
|
viewname,
|
|
@@ -374,13 +412,21 @@ const run = async (
|
|
|
374
412
|
};
|
|
375
413
|
|
|
376
414
|
module.exports = {
|
|
415
|
+
/** @type {string} */
|
|
377
416
|
name: "Feed",
|
|
417
|
+
/** @type {string} */
|
|
378
418
|
description:
|
|
379
419
|
"Show multiple rows by displaying a chosen view for each row, stacked or in columns",
|
|
380
420
|
configuration_workflow,
|
|
381
421
|
run,
|
|
382
422
|
get_state_fields,
|
|
423
|
+
/** @type {boolean} */
|
|
383
424
|
display_state_form: false,
|
|
425
|
+
/**
|
|
426
|
+
* @param {object} opts
|
|
427
|
+
* @param {*} opts.create_view_label
|
|
428
|
+
* @returns {string[]|Object[]}
|
|
429
|
+
*/
|
|
384
430
|
getStringsForI18n({ create_view_label }) {
|
|
385
431
|
if (create_view_label) return [create_view_label];
|
|
386
432
|
else return [];
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-data
|
|
3
|
+
* @module base-plugin/viewtemplates/filter
|
|
4
|
+
* @subcategory base-plugin
|
|
5
|
+
*/
|
|
1
6
|
const User = require("../../models/user");
|
|
2
7
|
const View = require("../../models/view");
|
|
3
8
|
const Table = require("../../models/table");
|
|
@@ -26,6 +31,9 @@ const { InvalidConfiguration } = require("../../utils");
|
|
|
26
31
|
const { jsexprToWhere } = require("../../models/expression");
|
|
27
32
|
const Library = require("../../models/library");
|
|
28
33
|
|
|
34
|
+
/**
|
|
35
|
+
* @returns {Workflow}
|
|
36
|
+
*/
|
|
29
37
|
const configuration_workflow = () =>
|
|
30
38
|
new Workflow({
|
|
31
39
|
steps: [
|
|
@@ -80,10 +88,26 @@ const configuration_workflow = () =>
|
|
|
80
88
|
},
|
|
81
89
|
],
|
|
82
90
|
});
|
|
91
|
+
|
|
92
|
+
/** @returns {object[]} */
|
|
83
93
|
const get_state_fields = () => [];
|
|
84
94
|
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @returns {Promise<object>}
|
|
98
|
+
*/
|
|
85
99
|
const initial_config = async () => ({ layout: {}, columns: [] });
|
|
86
100
|
|
|
101
|
+
/**
|
|
102
|
+
* @param {number} table_id
|
|
103
|
+
* @param {string} viewname
|
|
104
|
+
* @param {object} opts
|
|
105
|
+
* @param {object[]} opts.columns
|
|
106
|
+
* @param {object} opts.layout
|
|
107
|
+
* @param {object} state
|
|
108
|
+
* @param {object} extra
|
|
109
|
+
* @returns {Promise<Layout>}
|
|
110
|
+
*/
|
|
87
111
|
const run = async (table_id, viewname, { columns, layout }, state, extra) => {
|
|
88
112
|
//console.log(columns);
|
|
89
113
|
//console.log(layout);
|
|
@@ -251,17 +275,36 @@ const run = async (table_id, viewname, { columns, layout }, state, extra) => {
|
|
|
251
275
|
return renderLayout({ blockDispatch, layout, role });
|
|
252
276
|
};
|
|
253
277
|
|
|
278
|
+
/**
|
|
279
|
+
* @param {object|undefined} x
|
|
280
|
+
* @param {object|undefined} y
|
|
281
|
+
* @returns {object}
|
|
282
|
+
*/
|
|
254
283
|
const or_if_undef = (x, y) => (typeof x === "undefined" ? y : x);
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @param {string} x
|
|
287
|
+
* @param {string} y
|
|
288
|
+
* @returns {boolean}
|
|
289
|
+
*/
|
|
255
290
|
const eq_string = (x, y) => `${x}` === `${y}`;
|
|
256
291
|
module.exports = {
|
|
292
|
+
/** @type {string} */
|
|
257
293
|
name: "Filter",
|
|
294
|
+
/** @type {string} */
|
|
258
295
|
description:
|
|
259
296
|
"Elements that limit the rows shown in other views on the same page. Filter views do not show any rows on their own.",
|
|
260
297
|
get_state_fields,
|
|
261
298
|
configuration_workflow,
|
|
262
299
|
run,
|
|
263
300
|
initial_config,
|
|
301
|
+
/** @type {boolean} */
|
|
264
302
|
display_state_form: false,
|
|
303
|
+
/**
|
|
304
|
+
* @param {object} opts
|
|
305
|
+
* @param {*} opts.layout
|
|
306
|
+
* @returns {string[]}
|
|
307
|
+
*/
|
|
265
308
|
getStringsForI18n({ layout }) {
|
|
266
309
|
return getStringsForI18n(layout);
|
|
267
310
|
},
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-data
|
|
3
|
+
* @module base-plugin/viewtemplates/list
|
|
4
|
+
* @subcategory base-plugin
|
|
5
|
+
*/
|
|
1
6
|
const Field = require("../../models/field");
|
|
2
7
|
const FieldRepeat = require("../../models/fieldrepeat");
|
|
3
8
|
const Table = require("../../models/table");
|
|
@@ -31,6 +36,10 @@ const db = require("../../db");
|
|
|
31
36
|
const { get_existing_views } = require("../../models/discovery");
|
|
32
37
|
const { InvalidConfiguration } = require("../../utils");
|
|
33
38
|
|
|
39
|
+
/**
|
|
40
|
+
* @param {object} context
|
|
41
|
+
* @returns {Promise<void>}
|
|
42
|
+
*/
|
|
34
43
|
const create_db_view = async (context) => {
|
|
35
44
|
const table = await Table.findOne({ id: context.table_id });
|
|
36
45
|
const fields = await table.getFields();
|
|
@@ -54,6 +63,13 @@ const create_db_view = async (context) => {
|
|
|
54
63
|
await db.query(`create or replace view ${sql_view_name} as ${sql};`);
|
|
55
64
|
};
|
|
56
65
|
|
|
66
|
+
/**
|
|
67
|
+
* @param {*} table_id
|
|
68
|
+
* @param {string} viewname
|
|
69
|
+
* @param {object} opts
|
|
70
|
+
* @param {*} opts.default_state
|
|
71
|
+
* @returns {Promise<void>}
|
|
72
|
+
*/
|
|
57
73
|
const on_delete = async (table_id, viewname, { default_state }) => {
|
|
58
74
|
if (!db.isSQLite) {
|
|
59
75
|
const sqlviews = (await get_existing_views()).map((v) => v.table_name);
|
|
@@ -66,6 +82,10 @@ const on_delete = async (table_id, viewname, { default_state }) => {
|
|
|
66
82
|
}
|
|
67
83
|
};
|
|
68
84
|
|
|
85
|
+
/**
|
|
86
|
+
* @param {object} req
|
|
87
|
+
* @returns {Workflow}
|
|
88
|
+
*/
|
|
69
89
|
const configuration_workflow = (req) =>
|
|
70
90
|
new Workflow({
|
|
71
91
|
onDone: async (ctx) => {
|
|
@@ -261,6 +281,14 @@ const configuration_workflow = (req) =>
|
|
|
261
281
|
},
|
|
262
282
|
],
|
|
263
283
|
});
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @param {string} table_id
|
|
287
|
+
* @param {*} viewname
|
|
288
|
+
* @param {object} opts
|
|
289
|
+
* @param {object[]} opts.columns
|
|
290
|
+
* @returns {function}
|
|
291
|
+
*/
|
|
264
292
|
const get_state_fields = async (table_id, viewname, { columns }) => {
|
|
265
293
|
const table_fields = await Field.find({ table_id });
|
|
266
294
|
var state_fields = [];
|
|
@@ -281,8 +309,23 @@ const get_state_fields = async (table_id, viewname, { columns }) => {
|
|
|
281
309
|
return state_fields;
|
|
282
310
|
};
|
|
283
311
|
|
|
312
|
+
/** @type {function} */
|
|
284
313
|
const initial_config = initial_config_all_fields(false);
|
|
285
314
|
|
|
315
|
+
/**
|
|
316
|
+
* @param {string|number} table_id
|
|
317
|
+
* @param {string} viewname
|
|
318
|
+
* @param {object} opts
|
|
319
|
+
* @param {object[]} opts.columns
|
|
320
|
+
* @param {string} [opts.view_to_create]
|
|
321
|
+
* @param {string} opts.create_view_display
|
|
322
|
+
* @param {string} [opts.create_view_label]
|
|
323
|
+
* @param {object} [opts.default_state]
|
|
324
|
+
* @param {string} [opts.create_view_location]
|
|
325
|
+
* @param {object} [stateWithId]
|
|
326
|
+
* @param {object} extraOpts
|
|
327
|
+
* @returns {Promise<*>}
|
|
328
|
+
*/
|
|
286
329
|
const run = async (
|
|
287
330
|
table_id,
|
|
288
331
|
viewname,
|
|
@@ -429,6 +472,18 @@ const run = async (
|
|
|
429
472
|
return istop ? create_link_div + tableHtml : tableHtml + create_link_div;
|
|
430
473
|
};
|
|
431
474
|
|
|
475
|
+
/**
|
|
476
|
+
* @param {number} table_id
|
|
477
|
+
* @param {*} viewname
|
|
478
|
+
* @param {object} optsOne
|
|
479
|
+
* @param {object[]} optsOne.columns
|
|
480
|
+
* @param {*} optsOne.layout
|
|
481
|
+
* @param {object} body
|
|
482
|
+
* @param {object} optsTwo
|
|
483
|
+
* @param {object} optsTwo.req
|
|
484
|
+
* @param {*} optsTwo.res
|
|
485
|
+
* @returns {Promise<object>}
|
|
486
|
+
*/
|
|
432
487
|
const run_action = async (
|
|
433
488
|
table_id,
|
|
434
489
|
viewname,
|
|
@@ -468,23 +523,40 @@ const run_action = async (
|
|
|
468
523
|
};
|
|
469
524
|
|
|
470
525
|
module.exports = {
|
|
526
|
+
/** @type {string} */
|
|
471
527
|
name: "List",
|
|
528
|
+
/** @type {string} */
|
|
472
529
|
description:
|
|
473
|
-
"Display multiple rows from a table in a grid with columns you specify",
|
|
530
|
+
"Display multiple rows from a table in a grid with columns you specify",
|
|
474
531
|
configuration_workflow,
|
|
475
532
|
run,
|
|
533
|
+
/** @type {string} */
|
|
476
534
|
view_quantity: "Many",
|
|
477
535
|
get_state_fields,
|
|
478
536
|
initial_config,
|
|
479
537
|
on_delete,
|
|
480
538
|
routes: { run_action },
|
|
539
|
+
/**
|
|
540
|
+
* @param {object} opts
|
|
541
|
+
* @returns {boolean}
|
|
542
|
+
*/
|
|
481
543
|
display_state_form: (opts) =>
|
|
482
544
|
!(opts && opts.default_state && opts.default_state._omit_state_form),
|
|
545
|
+
/**
|
|
546
|
+
* @param {object} opts
|
|
547
|
+
* @returns {boolean}
|
|
548
|
+
*/
|
|
483
549
|
default_state_form: ({ default_state }) => {
|
|
484
550
|
if (!default_state) return default_state;
|
|
485
551
|
const { _omit_state_form, _create_db_view, ...ds } = default_state;
|
|
486
552
|
return ds && removeDefaultColor(removeEmptyStrings(ds));
|
|
487
553
|
},
|
|
554
|
+
/**
|
|
555
|
+
* @param {object} opts
|
|
556
|
+
* @param {*} opts.columns
|
|
557
|
+
* @param {*} opts.create_view_label
|
|
558
|
+
* @returns {string[]}
|
|
559
|
+
*/
|
|
488
560
|
getStringsForI18n({ columns, create_view_label }) {
|
|
489
561
|
const strings = [];
|
|
490
562
|
const maybeAdd = (s) => {
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category saltcorn-data
|
|
3
|
+
* @module base-plugin/viewtemplates/listshowlist
|
|
4
|
+
* @subcategory base-plugin
|
|
5
|
+
*/
|
|
1
6
|
const Table = require("../../models/table");
|
|
2
7
|
const Form = require("../../models/form");
|
|
3
8
|
const View = require("../../models/view");
|
|
@@ -12,6 +17,10 @@ const {
|
|
|
12
17
|
const { splitUniques } = require("./viewable_fields");
|
|
13
18
|
const { InvalidConfiguration } = require("../../utils");
|
|
14
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @param {object} req
|
|
22
|
+
* @returns {Workflow}
|
|
23
|
+
*/
|
|
15
24
|
const configuration_workflow = (req) =>
|
|
16
25
|
new Workflow({
|
|
17
26
|
steps: [
|
|
@@ -58,6 +67,19 @@ const configuration_workflow = (req) =>
|
|
|
58
67
|
options: show_view_opts,
|
|
59
68
|
},
|
|
60
69
|
},
|
|
70
|
+
{
|
|
71
|
+
name: "list_width",
|
|
72
|
+
label: req.__("List width"),
|
|
73
|
+
sublabel: req.__(
|
|
74
|
+
"Number of columns (1-12) allocated to the list view"
|
|
75
|
+
),
|
|
76
|
+
type: "Integer",
|
|
77
|
+
default: 6,
|
|
78
|
+
attributes: {
|
|
79
|
+
min: 1,
|
|
80
|
+
max: 12,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
61
83
|
{
|
|
62
84
|
name: "_omit_state_form",
|
|
63
85
|
label: req.__("Omit search form"),
|
|
@@ -106,6 +128,14 @@ const configuration_workflow = (req) =>
|
|
|
106
128
|
],
|
|
107
129
|
});
|
|
108
130
|
|
|
131
|
+
/**
|
|
132
|
+
* @param {*} table_id
|
|
133
|
+
* @param {*} viewname
|
|
134
|
+
* @param {object} opts
|
|
135
|
+
* @param {string} opts.list_view
|
|
136
|
+
* @param {*} opts.show_view
|
|
137
|
+
* @returns {Promise<object[]>}
|
|
138
|
+
*/
|
|
109
139
|
const get_state_fields = async (
|
|
110
140
|
table_id,
|
|
111
141
|
viewname,
|
|
@@ -125,10 +155,21 @@ const get_state_fields = async (
|
|
|
125
155
|
} else return [id];
|
|
126
156
|
};
|
|
127
157
|
|
|
158
|
+
/**
|
|
159
|
+
* @param {string} table_id
|
|
160
|
+
* @param {string} viewname
|
|
161
|
+
* @param {object} opts
|
|
162
|
+
* @param {string} opts.list_view
|
|
163
|
+
* @param {string} opts.show_view
|
|
164
|
+
* @param {object} opts.subtables
|
|
165
|
+
* @param {*} state
|
|
166
|
+
* @param {*} extraArgs
|
|
167
|
+
* @returns {Promise<div>}
|
|
168
|
+
*/
|
|
128
169
|
const run = async (
|
|
129
170
|
table_id,
|
|
130
171
|
viewname,
|
|
131
|
-
{ list_view, show_view, subtables },
|
|
172
|
+
{ list_view, show_view, list_width, subtables },
|
|
132
173
|
state,
|
|
133
174
|
extraArgs
|
|
134
175
|
) => {
|
|
@@ -219,10 +260,11 @@ const run = async (
|
|
|
219
260
|
? [h6(Object.keys(reltbls)[0]), reltbls[Object.keys(reltbls)[0]]]
|
|
220
261
|
: tabs(reltbls);
|
|
221
262
|
if (lresp) {
|
|
263
|
+
if (list_width === 12) return lresp;
|
|
222
264
|
return div(
|
|
223
265
|
{ class: "row" },
|
|
224
|
-
div({ class:
|
|
225
|
-
div({ class:
|
|
266
|
+
div({ class: `col-sm-${list_width || 6}` }, lresp),
|
|
267
|
+
div({ class: `col-sm-${12 - (list_width || 6)}` }, sresp, relTblResp)
|
|
226
268
|
);
|
|
227
269
|
} else {
|
|
228
270
|
return div(sresp, relTblResp);
|
|
@@ -230,12 +272,21 @@ const run = async (
|
|
|
230
272
|
};
|
|
231
273
|
|
|
232
274
|
module.exports = {
|
|
275
|
+
/** @type {string} */
|
|
233
276
|
name: "ListShowList",
|
|
277
|
+
/** @type {string} */
|
|
234
278
|
description:
|
|
235
279
|
"Combine an optional list view on the left with displays on the right of a single selected row, with views of related rows from different tables underneath",
|
|
236
280
|
configuration_workflow,
|
|
237
281
|
run,
|
|
238
282
|
get_state_fields,
|
|
283
|
+
/**
|
|
284
|
+
|
|
285
|
+
* @param {object} opts
|
|
286
|
+
* @param {string} opts.list_view
|
|
287
|
+
* @param {boolean} opts._omit_state_form
|
|
288
|
+
* @returns {boolean}
|
|
289
|
+
*/
|
|
239
290
|
display_state_form: ({ list_view, _omit_state_form }) =>
|
|
240
291
|
!!list_view && !_omit_state_form,
|
|
241
292
|
};
|