@saltcorn/server 0.7.3 → 0.7.4-beta.2
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/auth/admin.js +2 -1
- package/auth/routes.js +80 -92
- package/errors.js +51 -48
- package/locales/en.json +47 -2
- package/locales/it.json +2 -1
- package/locales/ru.json +42 -6
- package/locales/zh.json +1 -1
- package/markup/admin.js +15 -1
- package/markup/plugin-store.js +5 -5
- package/package.json +7 -7
- package/public/jquery-menu-editor.min.js +1 -1
- package/public/saltcorn-builder.css +75 -0
- package/public/saltcorn-common.js +24 -9
- package/public/saltcorn.css +28 -1
- package/public/saltcorn.js +9 -7
- package/routes/actions.js +2 -39
- package/routes/admin.js +375 -90
- package/routes/api.js +9 -1
- package/routes/common_lists.js +419 -0
- package/routes/fields.js +34 -19
- package/routes/homepage.js +60 -60
- package/routes/index.js +4 -0
- package/routes/menu.js +65 -4
- package/routes/packs.js +4 -4
- package/routes/page.js +5 -1
- package/routes/pageedit.js +13 -98
- package/routes/plugins.js +116 -118
- package/routes/settings.js +3 -3
- package/routes/tables.js +158 -193
- package/routes/tag_entries.js +173 -0
- package/routes/tags.js +266 -0
- package/routes/tenant.js +27 -27
- package/routes/utils.js +4 -0
- package/routes/view.js +18 -1
- package/routes/viewedit.js +22 -132
- package/serve.js +54 -38
- package/tests/admin.test.js +1 -1
- package/tests/api.test.js +17 -0
- package/tests/clientjs.test.js +11 -1
- package/tests/plugins.test.js +1 -1
- package/tests/viewedit.test.js +1 -1
- package/wrapper.js +57 -55
package/routes/homepage.js
CHANGED
|
@@ -54,9 +54,9 @@ const tableCard = (tables, req) => ({
|
|
|
54
54
|
contents:
|
|
55
55
|
(tables.length <= 1
|
|
56
56
|
? p(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
{ class: "mt-2 pe-2" },
|
|
58
|
+
i(req.__("Tables organise data by fields and rows."))
|
|
59
|
+
)
|
|
60
60
|
: "") + tableTable(tables, req),
|
|
61
61
|
bodyClass: "py-0 pe-0",
|
|
62
62
|
footer: div(
|
|
@@ -107,13 +107,13 @@ const viewCard = (views, req) => ({
|
|
|
107
107
|
contents:
|
|
108
108
|
(views.length <= 1
|
|
109
109
|
? p(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
)
|
|
110
|
+
{ class: "mt-2 pe-2" },
|
|
111
|
+
i(
|
|
112
|
+
req.__(
|
|
113
|
+
"Views display data from tables. A view is a view pattern applied to a table, with configuration."
|
|
115
114
|
)
|
|
116
115
|
)
|
|
116
|
+
)
|
|
117
117
|
: "") +
|
|
118
118
|
(views.length > 0 ? viewTable(views, req) : p(req.__("No views"))),
|
|
119
119
|
|
|
@@ -160,13 +160,13 @@ const pageCard = (pages, req) => ({
|
|
|
160
160
|
contents:
|
|
161
161
|
(pages.length <= 1
|
|
162
162
|
? p(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
)
|
|
163
|
+
{ class: "mt-2 pe-2" },
|
|
164
|
+
i(
|
|
165
|
+
req.__(
|
|
166
|
+
"Pages are the web pages of your application built with a drag-and-drop builder. They have static content, and by embedding views, dynamic content."
|
|
168
167
|
)
|
|
169
168
|
)
|
|
169
|
+
)
|
|
170
170
|
: "") +
|
|
171
171
|
(pages.length > 0
|
|
172
172
|
? pageTable(pages, req)
|
|
@@ -191,16 +191,16 @@ const filesTab = async (req) => {
|
|
|
191
191
|
files.length === 0
|
|
192
192
|
? p(req.__("No files"))
|
|
193
193
|
: mkTable(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
194
|
+
[
|
|
195
|
+
{
|
|
196
|
+
label: req.__("Filename"),
|
|
197
|
+
key: (r) => link(`/files/serve/${r.id}`, r.filename),
|
|
198
|
+
},
|
|
199
|
+
{ label: req.__("Size (KiB)"), key: "size_kb", align: "right" },
|
|
200
|
+
{ label: req.__("Media type"), key: (r) => r.mimetype },
|
|
201
|
+
],
|
|
202
|
+
files
|
|
203
|
+
),
|
|
204
204
|
fileUploadForm(req)
|
|
205
205
|
);
|
|
206
206
|
};
|
|
@@ -244,30 +244,30 @@ const actionsTab = async (req, triggers) => {
|
|
|
244
244
|
return div(
|
|
245
245
|
{ class: "pb-3" },
|
|
246
246
|
triggers.length <= 1 &&
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
247
|
+
p(
|
|
248
|
+
{ class: "mt-2 pe-2" },
|
|
249
|
+
i(req.__("Triggers run actions in response to events."))
|
|
250
|
+
),
|
|
251
251
|
triggers.length === 0
|
|
252
252
|
? p(req.__("No triggers"))
|
|
253
253
|
: mkTable(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
254
|
+
[
|
|
255
|
+
{ label: req.__("Name"), key: "name" },
|
|
256
|
+
{ label: req.__("Action"), key: "action" },
|
|
257
|
+
{
|
|
258
|
+
label: req.__("Table or Channel"),
|
|
259
|
+
key: (r) => r.table_name || r.channel,
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
label: req.__("When"),
|
|
263
|
+
key: (a) =>
|
|
264
|
+
a.when_trigger === "API call"
|
|
265
|
+
? `API: ${base_url}api/action/${a.name}`
|
|
266
|
+
: a.when_trigger,
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
triggers
|
|
270
|
+
),
|
|
271
271
|
a(
|
|
272
272
|
{ href: "/actions/new", class: "btn btn-secondary my-3" },
|
|
273
273
|
req.__("Add trigger")
|
|
@@ -385,15 +385,15 @@ const welcome_page = async (req) => {
|
|
|
385
385
|
tabContents:
|
|
386
386
|
triggers.length > 0
|
|
387
387
|
? {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
388
|
+
Triggers: await actionsTab(req, triggers),
|
|
389
|
+
Files: await filesTab(req),
|
|
390
|
+
Packs: packTab(req, packlist),
|
|
391
|
+
}
|
|
392
392
|
: {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
393
|
+
Packs: packTab(req, packlist),
|
|
394
|
+
Triggers: await actionsTab(req, triggers),
|
|
395
|
+
Files: await filesTab(req),
|
|
396
|
+
},
|
|
397
397
|
},
|
|
398
398
|
{
|
|
399
399
|
type: "card",
|
|
@@ -403,13 +403,13 @@ const welcome_page = async (req) => {
|
|
|
403
403
|
tabContents:
|
|
404
404
|
users.length > 4
|
|
405
405
|
? {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
406
|
+
Users: await usersTab(req, users, roleMap),
|
|
407
|
+
Help: helpCard(req),
|
|
408
|
+
}
|
|
409
409
|
: {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
410
|
+
Help: helpCard(req),
|
|
411
|
+
Users: await usersTab(req, users, roleMap),
|
|
412
|
+
},
|
|
413
413
|
},
|
|
414
414
|
],
|
|
415
415
|
},
|
|
@@ -440,8 +440,8 @@ const no_views_logged_in = async (req, res) => {
|
|
|
440
440
|
packagejson.version,
|
|
441
441
|
latest
|
|
442
442
|
) +
|
|
443
|
-
|
|
444
|
-
|
|
443
|
+
" " +
|
|
444
|
+
a({ href: "/admin/system" }, req.__("Upgrade here"))
|
|
445
445
|
);
|
|
446
446
|
|
|
447
447
|
res.sendWrap(req.__("Hello"), await welcome_page(req));
|
package/routes/index.js
CHANGED
|
@@ -70,6 +70,8 @@ const auth = require("../auth/routes");
|
|
|
70
70
|
const useradmin = require("../auth/admin");
|
|
71
71
|
const roleadmin = require("../auth/roleadmin");
|
|
72
72
|
const scapi = require("./scapi");
|
|
73
|
+
const tags = require("./tags");
|
|
74
|
+
const tagentries = require("./tag_entries");
|
|
73
75
|
|
|
74
76
|
module.exports =
|
|
75
77
|
/**
|
|
@@ -106,4 +108,6 @@ module.exports =
|
|
|
106
108
|
app.use("/useradmin", useradmin);
|
|
107
109
|
app.use("/roleadmin", roleadmin);
|
|
108
110
|
app.use("/scapi", scapi);
|
|
111
|
+
app.use("/tag", tags);
|
|
112
|
+
app.use("/tag-entries", tagentries);
|
|
109
113
|
};
|
package/routes/menu.js
CHANGED
|
@@ -22,6 +22,9 @@ const { renderForm } = require("@saltcorn/markup");
|
|
|
22
22
|
const { script, domReady, div, ul } = require("@saltcorn/markup/tags");
|
|
23
23
|
const { send_infoarch_page } = require("../markup/admin.js");
|
|
24
24
|
const Table = require("@saltcorn/data/models/table");
|
|
25
|
+
const Trigger = require("@saltcorn/data/models/trigger");
|
|
26
|
+
const { run_action_column } = require("@saltcorn/data/plugin-helper");
|
|
27
|
+
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* @type {object}
|
|
@@ -61,6 +64,18 @@ const menuForm = async (req) => {
|
|
|
61
64
|
dynSectionFieldOptions[table.name].push(field.name);
|
|
62
65
|
}
|
|
63
66
|
}
|
|
67
|
+
const stateActions = getState().actions;
|
|
68
|
+
const actions = [
|
|
69
|
+
...Object.entries(stateActions)
|
|
70
|
+
.filter(([k, v]) => !v.requireRow && !v.disableInBuilder)
|
|
71
|
+
.map(([k, v]) => k),
|
|
72
|
+
];
|
|
73
|
+
const triggers = await Trigger.find({
|
|
74
|
+
when_trigger: { or: ["API call", "Never"] },
|
|
75
|
+
});
|
|
76
|
+
triggers.forEach((tr) => {
|
|
77
|
+
actions.push(tr.name);
|
|
78
|
+
});
|
|
64
79
|
|
|
65
80
|
return new Form({
|
|
66
81
|
action: "/menu/",
|
|
@@ -92,6 +107,7 @@ const menuForm = async (req) => {
|
|
|
92
107
|
"Dynamic",
|
|
93
108
|
"Search",
|
|
94
109
|
"Separator",
|
|
110
|
+
"Action"
|
|
95
111
|
],
|
|
96
112
|
},
|
|
97
113
|
{
|
|
@@ -101,7 +117,7 @@ const menuForm = async (req) => {
|
|
|
101
117
|
input_type: "text",
|
|
102
118
|
required: true,
|
|
103
119
|
showIf: {
|
|
104
|
-
type: ["View", "Page", "Link", "Header", "Dynamic", "Search"],
|
|
120
|
+
type: ["View", "Page", "Link", "Header", "Dynamic", "Search", "Action"],
|
|
105
121
|
},
|
|
106
122
|
},
|
|
107
123
|
{
|
|
@@ -111,7 +127,7 @@ const menuForm = async (req) => {
|
|
|
111
127
|
attributes: {
|
|
112
128
|
html: `<button type="button" id="myEditor_icon" class="btn btn-outline-secondary"></button>`,
|
|
113
129
|
},
|
|
114
|
-
showIf: { type: ["View", "Page", "Link", "Header"] },
|
|
130
|
+
showIf: { type: ["View", "Page", "Link", "Header", "Action"] },
|
|
115
131
|
},
|
|
116
132
|
{
|
|
117
133
|
name: "icon",
|
|
@@ -149,6 +165,17 @@ const menuForm = async (req) => {
|
|
|
149
165
|
attributes: { options: views.map((r) => r.select_option) },
|
|
150
166
|
showIf: { type: "View" },
|
|
151
167
|
},
|
|
168
|
+
{
|
|
169
|
+
name: "action_name",
|
|
170
|
+
label: req.__("Action"),
|
|
171
|
+
type: "String",
|
|
172
|
+
class: "item-menu",
|
|
173
|
+
required: true,
|
|
174
|
+
attributes: {
|
|
175
|
+
options: actions,
|
|
176
|
+
},
|
|
177
|
+
showIf: { type: "Action" },
|
|
178
|
+
},
|
|
152
179
|
{
|
|
153
180
|
name: "dyn_table",
|
|
154
181
|
label: req.__("Table"),
|
|
@@ -217,7 +244,7 @@ const menuForm = async (req) => {
|
|
|
217
244
|
class: "item-menu",
|
|
218
245
|
type: "String",
|
|
219
246
|
required: true,
|
|
220
|
-
showIf: { type: ["View", "Page", "Link", "Header", "Dynamic"] },
|
|
247
|
+
showIf: { type: ["View", "Page", "Link", "Header", "Dynamic", "Action"] },
|
|
221
248
|
attributes: {
|
|
222
249
|
options: [
|
|
223
250
|
{ name: "", label: "Link" },
|
|
@@ -239,7 +266,7 @@ const menuForm = async (req) => {
|
|
|
239
266
|
{
|
|
240
267
|
name: "location",
|
|
241
268
|
label: req.__("Location"),
|
|
242
|
-
showIf: { type: ["View", "Page", "Link", "Header", "Dynamic"] },
|
|
269
|
+
showIf: { type: ["View", "Page", "Link", "Header", "Dynamic", "Action"] },
|
|
243
270
|
sublabel: req.__("Not all themes support all locations"),
|
|
244
271
|
class: "item-menu",
|
|
245
272
|
type: "String",
|
|
@@ -404,3 +431,37 @@ router.post(
|
|
|
404
431
|
res.json({ success: true });
|
|
405
432
|
})
|
|
406
433
|
);
|
|
434
|
+
|
|
435
|
+
router.post(
|
|
436
|
+
"/runaction/:name",
|
|
437
|
+
error_catcher(async (req, res) => {
|
|
438
|
+
const { name } = req.params;
|
|
439
|
+
const role = (req.user || {}).role_id || 10;
|
|
440
|
+
const state = getState();
|
|
441
|
+
const menu_items = state.getConfig("menu_items");
|
|
442
|
+
let menu_item;
|
|
443
|
+
const search = items =>
|
|
444
|
+
items
|
|
445
|
+
.filter((item) => role <= +item.min_role)
|
|
446
|
+
.forEach(item => {
|
|
447
|
+
if (item.type === "Action" && item.action_name === name)
|
|
448
|
+
menu_item = item;
|
|
449
|
+
else if (item.subitems)
|
|
450
|
+
search(item.subitems);
|
|
451
|
+
})
|
|
452
|
+
search(menu_items);
|
|
453
|
+
if (menu_item)
|
|
454
|
+
try {
|
|
455
|
+
const result = await run_action_column({
|
|
456
|
+
col: menu_item,
|
|
457
|
+
referrer: req.get("Referrer"),
|
|
458
|
+
req,
|
|
459
|
+
});
|
|
460
|
+
res.json({ success: "ok", ...(result || {}) });
|
|
461
|
+
} catch (e) {
|
|
462
|
+
res.status(400).json({ error: e.message || e });
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
else res.status(404).json({ error: "Action not found" });
|
|
466
|
+
})
|
|
467
|
+
);
|
package/routes/packs.js
CHANGED
|
@@ -116,7 +116,7 @@ router.get(
|
|
|
116
116
|
type: "breadcrumbs",
|
|
117
117
|
crumbs: [
|
|
118
118
|
{ text: req.__("Settings") },
|
|
119
|
-
{ text: req.__("
|
|
119
|
+
{ text: req.__("Modules"), href: "/plugins" },
|
|
120
120
|
{ text: req.__("Create pack") },
|
|
121
121
|
],
|
|
122
122
|
},
|
|
@@ -184,7 +184,7 @@ router.post(
|
|
|
184
184
|
type: "breadcrumbs",
|
|
185
185
|
crumbs: [
|
|
186
186
|
{ text: req.__("Settings") },
|
|
187
|
-
{ text: req.__("
|
|
187
|
+
{ text: req.__("Modules"), href: "/plugins" },
|
|
188
188
|
{ text: req.__("Create pack") },
|
|
189
189
|
],
|
|
190
190
|
},
|
|
@@ -242,7 +242,7 @@ router.get(
|
|
|
242
242
|
type: "breadcrumbs",
|
|
243
243
|
crumbs: [
|
|
244
244
|
{ text: req.__("Settings") },
|
|
245
|
-
{ text: req.__("
|
|
245
|
+
{ text: req.__("Modules"), href: "/plugins" },
|
|
246
246
|
{ text: req.__("Install pack") },
|
|
247
247
|
],
|
|
248
248
|
},
|
|
@@ -293,7 +293,7 @@ router.post(
|
|
|
293
293
|
type: "breadcrumbs",
|
|
294
294
|
crumbs: [
|
|
295
295
|
{ text: req.__("Settings") },
|
|
296
|
-
{ text: req.__("
|
|
296
|
+
{ text: req.__("Modules"), href: "/plugins" },
|
|
297
297
|
{ text: req.__("Install pack") },
|
|
298
298
|
],
|
|
299
299
|
},
|
package/routes/page.js
CHANGED
|
@@ -36,6 +36,8 @@ router.get(
|
|
|
36
36
|
"/:pagename",
|
|
37
37
|
error_catcher(async (req, res) => {
|
|
38
38
|
const { pagename } = req.params;
|
|
39
|
+
const state = getState();
|
|
40
|
+
state.log(3, `Route /page/${pagename} user=${req.user?.id}`);
|
|
39
41
|
|
|
40
42
|
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
41
43
|
const db_page = await Page.findOne({ name: pagename });
|
|
@@ -56,10 +58,12 @@ router.get(
|
|
|
56
58
|
contents,
|
|
57
59
|
})
|
|
58
60
|
);
|
|
59
|
-
} else
|
|
61
|
+
} else {
|
|
62
|
+
state.log(2, `Page $pagename} not found or not authorized`);
|
|
60
63
|
res
|
|
61
64
|
.status(404)
|
|
62
65
|
.sendWrap(`${pagename} page`, req.__("Page %s not found", pagename));
|
|
66
|
+
}
|
|
63
67
|
})
|
|
64
68
|
);
|
|
65
69
|
|
package/routes/pageedit.js
CHANGED
|
@@ -19,6 +19,7 @@ const Trigger = require("@saltcorn/data/models/trigger");
|
|
|
19
19
|
const { getViews, traverseSync } = require("@saltcorn/data/models/layout");
|
|
20
20
|
const { add_to_menu } = require("@saltcorn/admin-models/models/pack");
|
|
21
21
|
const db = require("@saltcorn/data/db");
|
|
22
|
+
const { getPageList } = require("./common_lists");
|
|
22
23
|
|
|
23
24
|
const { isAdmin, error_catcher } = require("./utils.js");
|
|
24
25
|
const {
|
|
@@ -32,7 +33,6 @@ const {
|
|
|
32
33
|
settingsDropdown,
|
|
33
34
|
} = require("@saltcorn/markup");
|
|
34
35
|
const { getActionConfigFields } = require("@saltcorn/data/plugin-helper");
|
|
35
|
-
const { editRoleForm, wizardCardTitle } = require("../markup/forms.js");
|
|
36
36
|
const Library = require("@saltcorn/data/models/library");
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -45,61 +45,6 @@ const Library = require("@saltcorn/data/models/library");
|
|
|
45
45
|
const router = new Router();
|
|
46
46
|
module.exports = router;
|
|
47
47
|
|
|
48
|
-
/**
|
|
49
|
-
* @param {object} page
|
|
50
|
-
* @param {*} roles
|
|
51
|
-
* @param {object} req
|
|
52
|
-
* @returns {Form}
|
|
53
|
-
*/
|
|
54
|
-
const editPageRoleForm = (page, roles, req) =>
|
|
55
|
-
editRoleForm({
|
|
56
|
-
url: `/pageedit/setrole/${page.id}`,
|
|
57
|
-
current_role: page.min_role,
|
|
58
|
-
roles,
|
|
59
|
-
req,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* @param {object} page
|
|
64
|
-
* @param {object} req
|
|
65
|
-
* @returns {string}
|
|
66
|
-
*/
|
|
67
|
-
const page_dropdown = (page, req) =>
|
|
68
|
-
settingsDropdown(`dropdownMenuButton${page.id}`, [
|
|
69
|
-
a(
|
|
70
|
-
{
|
|
71
|
-
class: "dropdown-item",
|
|
72
|
-
href: `/page/${encodeURIComponent(page.name)}`,
|
|
73
|
-
},
|
|
74
|
-
'<i class="fas fa-running"></i> ' + req.__("Run")
|
|
75
|
-
),
|
|
76
|
-
a(
|
|
77
|
-
{
|
|
78
|
-
class: "dropdown-item",
|
|
79
|
-
href: `/pageedit/edit-properties/${encodeURIComponent(page.name)}`,
|
|
80
|
-
},
|
|
81
|
-
'<i class="fas fa-edit"></i> ' + req.__("Edit properties")
|
|
82
|
-
),
|
|
83
|
-
post_dropdown_item(
|
|
84
|
-
`/pageedit/add-to-menu/${page.id}`,
|
|
85
|
-
'<i class="fas fa-bars"></i> ' + req.__("Add to menu"),
|
|
86
|
-
req
|
|
87
|
-
),
|
|
88
|
-
post_dropdown_item(
|
|
89
|
-
`/pageedit/clone/${page.id}`,
|
|
90
|
-
'<i class="far fa-copy"></i> ' + req.__("Duplicate"),
|
|
91
|
-
req
|
|
92
|
-
),
|
|
93
|
-
div({ class: "dropdown-divider" }),
|
|
94
|
-
post_dropdown_item(
|
|
95
|
-
`/pageedit/delete/${page.id}`,
|
|
96
|
-
'<i class="far fa-trash-alt"></i> ' + req.__("Delete"),
|
|
97
|
-
req,
|
|
98
|
-
true,
|
|
99
|
-
page.name
|
|
100
|
-
),
|
|
101
|
-
]);
|
|
102
|
-
|
|
103
48
|
/**
|
|
104
49
|
*
|
|
105
50
|
* @param {object} req
|
|
@@ -180,7 +125,8 @@ const pageBuilderData = async (req, context) => {
|
|
|
180
125
|
const fixed_state_fields = {};
|
|
181
126
|
for (const view of views) {
|
|
182
127
|
fixed_state_fields[view.name] = [];
|
|
183
|
-
const table = Table.findOne(
|
|
128
|
+
const table = Table.findOne(view.table_id || view.exttable_name);
|
|
129
|
+
|
|
184
130
|
const fs = await view.get_state_fields();
|
|
185
131
|
for (const frec of fs) {
|
|
186
132
|
const f = new Field(frec);
|
|
@@ -228,46 +174,6 @@ const pageBuilderData = async (req, context) => {
|
|
|
228
174
|
};
|
|
229
175
|
};
|
|
230
176
|
|
|
231
|
-
/**
|
|
232
|
-
* @param {*} rows
|
|
233
|
-
* @param {*} roles
|
|
234
|
-
* @param {object} req
|
|
235
|
-
* @returns {div}
|
|
236
|
-
*/
|
|
237
|
-
const getPageList = (rows, roles, req) => {
|
|
238
|
-
return div(
|
|
239
|
-
mkTable(
|
|
240
|
-
[
|
|
241
|
-
{
|
|
242
|
-
label: req.__("Name"),
|
|
243
|
-
key: (r) => link(`/page/${r.name}`, r.name),
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
label: req.__("Role to access"),
|
|
247
|
-
key: (row) => editPageRoleForm(row, roles, req),
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
label: req.__("Edit"),
|
|
251
|
-
key: (r) => link(`/pageedit/edit/${r.name}`, req.__("Edit")),
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
label: "",
|
|
255
|
-
key: (r) => page_dropdown(r, req),
|
|
256
|
-
},
|
|
257
|
-
],
|
|
258
|
-
rows,
|
|
259
|
-
{ hover: true }
|
|
260
|
-
),
|
|
261
|
-
a(
|
|
262
|
-
{
|
|
263
|
-
href: `/pageedit/new`,
|
|
264
|
-
class: "btn btn-primary",
|
|
265
|
-
},
|
|
266
|
-
req.__("Create page")
|
|
267
|
-
)
|
|
268
|
-
);
|
|
269
|
-
};
|
|
270
|
-
|
|
271
177
|
/**
|
|
272
178
|
* Root pages configuration Form
|
|
273
179
|
* Allows to configure root page for each role
|
|
@@ -327,7 +233,16 @@ router.get(
|
|
|
327
233
|
type: "card",
|
|
328
234
|
title: req.__("Your pages"),
|
|
329
235
|
class: "mt-0",
|
|
330
|
-
contents:
|
|
236
|
+
contents: div(
|
|
237
|
+
getPageList(pages, roles, req),
|
|
238
|
+
a(
|
|
239
|
+
{
|
|
240
|
+
href: `/pageedit/new`,
|
|
241
|
+
class: "btn btn-primary",
|
|
242
|
+
},
|
|
243
|
+
req.__("Create page")
|
|
244
|
+
)
|
|
245
|
+
),
|
|
331
246
|
},
|
|
332
247
|
{
|
|
333
248
|
type: "card",
|