@saltcorn/server 0.9.3-beta.4 → 0.9.3-beta.5
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/testhelp.js +32 -0
- package/help/Eligible Formula.tmd +69 -0
- package/locales/en.json +45 -2
- package/markup/admin.js +1 -0
- package/package.json +9 -8
- package/public/saltcorn-common.js +16 -0
- package/public/saltcorn.css +3 -0
- package/public/saltcorn.js +13 -0
- package/routes/admin.js +11 -1
- package/routes/common_lists.js +66 -3
- package/routes/index.js +4 -0
- package/routes/packs.js +13 -0
- package/routes/page.js +125 -51
- package/routes/page_group.js +378 -0
- package/routes/page_groupedit.js +678 -0
- package/routes/pageedit.js +37 -18
- package/routes/utils.js +19 -0
- package/tests/admin.test.js +1 -0
- package/tests/page_group.test.js +366 -0
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
const Router = require("express-promise-router");
|
|
2
|
+
|
|
3
|
+
const PageGroup = require("@saltcorn/data/models/page_group");
|
|
4
|
+
const PageGroupMember = require("@saltcorn/data/models/page_group_member");
|
|
5
|
+
const Page = require("@saltcorn/data/models/page");
|
|
6
|
+
const Form = require("@saltcorn/data/models/form");
|
|
7
|
+
const User = require("@saltcorn/data/models/user");
|
|
8
|
+
const { div, a, code, span, br } = require("@saltcorn/markup/tags");
|
|
9
|
+
const {
|
|
10
|
+
renderForm,
|
|
11
|
+
mkTable,
|
|
12
|
+
post_btn,
|
|
13
|
+
post_delete_btn,
|
|
14
|
+
link,
|
|
15
|
+
} = require("@saltcorn/markup");
|
|
16
|
+
const { add_to_menu } = require("@saltcorn/admin-models/models/pack");
|
|
17
|
+
const { error_catcher, isAdmin, setRole } = require("./utils.js");
|
|
18
|
+
const { getState } = require("@saltcorn/data/db/state");
|
|
19
|
+
|
|
20
|
+
const router = new Router();
|
|
21
|
+
module.exports = router;
|
|
22
|
+
|
|
23
|
+
const groupPropsForm = async (req, isNew) => {
|
|
24
|
+
const roles = await User.get_roles();
|
|
25
|
+
const pages = await Page.find();
|
|
26
|
+
const groups = await PageGroup.find();
|
|
27
|
+
return new Form({
|
|
28
|
+
action: "/page_groupedit/edit-properties",
|
|
29
|
+
...(isNew
|
|
30
|
+
? {}
|
|
31
|
+
: {
|
|
32
|
+
onChange: `saveAndContinue(this, (res) => {
|
|
33
|
+
history.replaceState(null, '', res.responseJSON.row.name);
|
|
34
|
+
});`,
|
|
35
|
+
}),
|
|
36
|
+
noSubmitButton: !isNew,
|
|
37
|
+
fields: [
|
|
38
|
+
{
|
|
39
|
+
name: "name",
|
|
40
|
+
label: req.__("Name"),
|
|
41
|
+
type: "String",
|
|
42
|
+
required: true,
|
|
43
|
+
validator(s, whole) {
|
|
44
|
+
if (s.length < 1) return req.__("Missing name");
|
|
45
|
+
if (pages.find((p) => p.name === s))
|
|
46
|
+
return req.__("A page with this name already exists");
|
|
47
|
+
if (
|
|
48
|
+
groups.find((g) =>
|
|
49
|
+
!isNew ? g.name === s && g.id !== +whole.id : g.name === s
|
|
50
|
+
)
|
|
51
|
+
) {
|
|
52
|
+
return req.__("A page group with this name already exists");
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
sublabel: req.__("A short name that will be in your URL"),
|
|
56
|
+
attributes: { autofocus: true },
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "description",
|
|
60
|
+
label: req.__("Description"),
|
|
61
|
+
type: "String",
|
|
62
|
+
sublabel: req.__("A longer description"),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "min_role",
|
|
66
|
+
label: req.__("Minimum role"),
|
|
67
|
+
sublabel: req.__("Role required to access page"),
|
|
68
|
+
input_type: "select",
|
|
69
|
+
options: roles.map((r) => ({ value: r.id, label: r.role })),
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const memberForm = async (action, req, groupName, pageValidator) => {
|
|
76
|
+
const pageOptions = (await Page.find()).map((p) => p.name);
|
|
77
|
+
return new Form({
|
|
78
|
+
action,
|
|
79
|
+
fields: [
|
|
80
|
+
{
|
|
81
|
+
name: "page_name",
|
|
82
|
+
label: req.__("Page"),
|
|
83
|
+
sublabel: req.__("Page to be served"),
|
|
84
|
+
type: "String",
|
|
85
|
+
required: true,
|
|
86
|
+
validator: pageValidator,
|
|
87
|
+
attributes: {
|
|
88
|
+
options: pageOptions,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "description",
|
|
93
|
+
label: req.__("Description"),
|
|
94
|
+
type: "String",
|
|
95
|
+
sublabel: req.__("A description of the group member"),
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "eligible_formula",
|
|
99
|
+
label: req.__("Eligible Formula"),
|
|
100
|
+
sublabel:
|
|
101
|
+
req.__("Formula to determine if this page should be served.") +
|
|
102
|
+
br() +
|
|
103
|
+
span(
|
|
104
|
+
"Variables in scope: ",
|
|
105
|
+
[
|
|
106
|
+
"width",
|
|
107
|
+
"height",
|
|
108
|
+
"innerWidth",
|
|
109
|
+
"innerHeight",
|
|
110
|
+
"user",
|
|
111
|
+
"locale",
|
|
112
|
+
"device",
|
|
113
|
+
]
|
|
114
|
+
.map((f) => code(f))
|
|
115
|
+
.join(", ")
|
|
116
|
+
),
|
|
117
|
+
help: {
|
|
118
|
+
topic: "Eligible Formula",
|
|
119
|
+
},
|
|
120
|
+
type: "String",
|
|
121
|
+
required: true,
|
|
122
|
+
class: "validate-expression",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
additionalButtons: [
|
|
126
|
+
{
|
|
127
|
+
label: req.__("Cancel"),
|
|
128
|
+
class: "btn btn-primary",
|
|
129
|
+
onclick: `cancelMemberEdit('${groupName}');`,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const editMemberForm = async (member, req) => {
|
|
136
|
+
const group = PageGroup.findOne({ id: member.page_group_id });
|
|
137
|
+
const validator = (s, whole) => {
|
|
138
|
+
const page = Page.findOne({ name: s });
|
|
139
|
+
if (group.members.find((m) => m.page_id === page.id && +whole.id !== m.id))
|
|
140
|
+
return req.__("A member with this page already exists");
|
|
141
|
+
};
|
|
142
|
+
return await memberForm(
|
|
143
|
+
`/page_groupedit/edit-member/${member.id}`,
|
|
144
|
+
req,
|
|
145
|
+
group.name,
|
|
146
|
+
validator
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const addMemberForm = async (group, req) => {
|
|
151
|
+
const groupPages = await group.loadPages();
|
|
152
|
+
const validator = (s) => {
|
|
153
|
+
if (groupPages.find((page) => page.name === s))
|
|
154
|
+
return req.__("A member with this page already exists");
|
|
155
|
+
};
|
|
156
|
+
return await memberForm(
|
|
157
|
+
`/page_groupedit/add-member/${group.name}`,
|
|
158
|
+
req,
|
|
159
|
+
group.name,
|
|
160
|
+
validator
|
|
161
|
+
);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const wrapGroup = (contents, req) => {
|
|
165
|
+
return {
|
|
166
|
+
above: [
|
|
167
|
+
{
|
|
168
|
+
type: "breadcrumbs",
|
|
169
|
+
crumbs: [
|
|
170
|
+
{ text: req.__("Page Groups"), href: "/pageedit" },
|
|
171
|
+
{ text: req.__("Create") },
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: "card",
|
|
176
|
+
title: req.__("New"),
|
|
177
|
+
contents,
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const wrapMember = (contents, req, pageGroup, pageMember) => {
|
|
184
|
+
const memberCrumb = (pageId) => {
|
|
185
|
+
const page = Page.findOne({ id: pageId });
|
|
186
|
+
return page ? { text: page.name, href: `/page/${page.name}` } : {};
|
|
187
|
+
};
|
|
188
|
+
return {
|
|
189
|
+
above: [
|
|
190
|
+
{
|
|
191
|
+
type: "breadcrumbs",
|
|
192
|
+
crumbs: [
|
|
193
|
+
{ text: req.__("Pages"), href: "/pageedit" },
|
|
194
|
+
{ text: pageGroup.name, href: `/page_groupedit/${pageGroup.name}` },
|
|
195
|
+
pageMember
|
|
196
|
+
? memberCrumb(pageMember.page_id)
|
|
197
|
+
: { text: req.__("add-member") },
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
type: "card",
|
|
202
|
+
title: pageMember
|
|
203
|
+
? req.__("edit member of %s", pageGroup.name)
|
|
204
|
+
: req.__("add member to %s", pageGroup.name),
|
|
205
|
+
contents,
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const pageGroupMembers = async (pageGroup, req) => {
|
|
212
|
+
const db = require("@saltcorn/data/db");
|
|
213
|
+
const pages = !db.isSQLite
|
|
214
|
+
? await Page.find({
|
|
215
|
+
id: { in: pageGroup.members.map((r) => r.page_id) },
|
|
216
|
+
})
|
|
217
|
+
: await Page.find();
|
|
218
|
+
const pageIdToName = pages.reduce((acc, page) => {
|
|
219
|
+
acc[page.id] = page.name;
|
|
220
|
+
return acc;
|
|
221
|
+
}, {});
|
|
222
|
+
let members = pageGroup.sortedMembers();
|
|
223
|
+
const upDownBtns = (r, req) => {
|
|
224
|
+
if (members.length <= 1) return "";
|
|
225
|
+
else
|
|
226
|
+
return div(
|
|
227
|
+
{ class: "container" },
|
|
228
|
+
div(
|
|
229
|
+
{ class: "row" },
|
|
230
|
+
div(
|
|
231
|
+
{ class: "col-1" },
|
|
232
|
+
r.sequence !== members[0].sequence
|
|
233
|
+
? post_btn(
|
|
234
|
+
`/page_groupedit/move-member/${r.id}/Up`,
|
|
235
|
+
`<i class="fa fa-arrow-up"></i>`,
|
|
236
|
+
req.csrfToken(),
|
|
237
|
+
{
|
|
238
|
+
small: true,
|
|
239
|
+
ajax: true,
|
|
240
|
+
reload_on_done: true,
|
|
241
|
+
btnClass: "btn btn-secondary btn-sm me-1",
|
|
242
|
+
req,
|
|
243
|
+
formClass: "d-inline",
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
: ""
|
|
247
|
+
),
|
|
248
|
+
div(
|
|
249
|
+
{ class: "col-1" },
|
|
250
|
+
r.sequence !== members[members.length - 1].sequence
|
|
251
|
+
? post_btn(
|
|
252
|
+
`/page_groupedit/move-member/${r.id}/Down`,
|
|
253
|
+
`<i class="fa fa-arrow-down"></i>`,
|
|
254
|
+
req.csrfToken(),
|
|
255
|
+
{
|
|
256
|
+
small: true,
|
|
257
|
+
ajax: true,
|
|
258
|
+
reload_on_done: true,
|
|
259
|
+
btnClass: "btn btn-secondary btn-sm me-1",
|
|
260
|
+
req,
|
|
261
|
+
formClass: "d-inline",
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
: ""
|
|
265
|
+
)
|
|
266
|
+
)
|
|
267
|
+
);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
return mkTable(
|
|
271
|
+
[
|
|
272
|
+
{
|
|
273
|
+
label: req.__("Page"),
|
|
274
|
+
key: (r) =>
|
|
275
|
+
link(`/page/${pageIdToName[r.page_id]}`, pageIdToName[r.page_id]),
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
label: "",
|
|
279
|
+
key: (r) => upDownBtns(r, req),
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
label: req.__("Edit"),
|
|
283
|
+
key: (member) =>
|
|
284
|
+
link(`/page_groupedit/edit-member/${member.id}`, req.__("Edit")),
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
label: req.__("Delete"),
|
|
288
|
+
key: (member) =>
|
|
289
|
+
post_delete_btn(
|
|
290
|
+
`/page_groupedit/remove-member/${member.id}`,
|
|
291
|
+
req,
|
|
292
|
+
req.__("Member %s", member.sequence)
|
|
293
|
+
),
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
members,
|
|
297
|
+
{
|
|
298
|
+
hover: true,
|
|
299
|
+
}
|
|
300
|
+
);
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* load a form to create a new page group
|
|
305
|
+
*/
|
|
306
|
+
router.get(
|
|
307
|
+
"/new",
|
|
308
|
+
isAdmin,
|
|
309
|
+
error_catcher(async (req, res) => {
|
|
310
|
+
const form = await groupPropsForm(req, true);
|
|
311
|
+
res.sendWrap(
|
|
312
|
+
req.__(`New page group`),
|
|
313
|
+
wrapGroup(renderForm(form, req.csrfToken()), req)
|
|
314
|
+
);
|
|
315
|
+
})
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* load the page group editor
|
|
320
|
+
*/
|
|
321
|
+
router.get(
|
|
322
|
+
"/:page_groupname",
|
|
323
|
+
isAdmin,
|
|
324
|
+
error_catcher(async (req, res) => {
|
|
325
|
+
const { page_groupname } = req.params;
|
|
326
|
+
const pageGroup = PageGroup.findOne({ name: page_groupname });
|
|
327
|
+
const propertiesForm = await groupPropsForm(req);
|
|
328
|
+
propertiesForm.hidden("id");
|
|
329
|
+
propertiesForm.values = pageGroup;
|
|
330
|
+
res.sendWrap(req.__("%s edit", page_groupname), {
|
|
331
|
+
above: [
|
|
332
|
+
{
|
|
333
|
+
type: "breadcrumbs",
|
|
334
|
+
crumbs: [
|
|
335
|
+
{ text: req.__("Pages"), href: "/pageedit" },
|
|
336
|
+
{
|
|
337
|
+
text: pageGroup.name,
|
|
338
|
+
href: `/page/${page_groupname}`,
|
|
339
|
+
pageGroupLink: true,
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
type: "card",
|
|
345
|
+
title: req.__("Members"),
|
|
346
|
+
contents: div(
|
|
347
|
+
await pageGroupMembers(pageGroup, req),
|
|
348
|
+
a(
|
|
349
|
+
{
|
|
350
|
+
href: `/page_groupedit/add-member/${pageGroup.name}`,
|
|
351
|
+
class: "btn btn-primary",
|
|
352
|
+
},
|
|
353
|
+
req.__("Add member")
|
|
354
|
+
)
|
|
355
|
+
),
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
type: "card",
|
|
359
|
+
title: req.__("Edit group properties"),
|
|
360
|
+
titleAjaxIndicator: true,
|
|
361
|
+
contents: div(renderForm(propertiesForm, req.csrfToken())),
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
});
|
|
365
|
+
})
|
|
366
|
+
);
|
|
367
|
+
/**
|
|
368
|
+
* edit the properties of a page group
|
|
369
|
+
*/
|
|
370
|
+
router.post(
|
|
371
|
+
"/edit-properties",
|
|
372
|
+
isAdmin,
|
|
373
|
+
error_catcher(async (req, res) => {
|
|
374
|
+
const form = await groupPropsForm(req, !req.body.id);
|
|
375
|
+
form.hidden("id");
|
|
376
|
+
form.validate(req.body);
|
|
377
|
+
if (form.hasErrors) {
|
|
378
|
+
if (!req.xhr) {
|
|
379
|
+
// from new
|
|
380
|
+
res.sendWrap(
|
|
381
|
+
req.__(`Pagegroup attributes`),
|
|
382
|
+
wrapGroup(renderForm(form, req.csrfToken()), req)
|
|
383
|
+
);
|
|
384
|
+
} else {
|
|
385
|
+
// from edit
|
|
386
|
+
const error = form.errorSummary;
|
|
387
|
+
getState().log(2, `POST /page_groupedit/edit-properties: '${error}'`);
|
|
388
|
+
res.status(400).json({ notify: { type: "danger", text: error } });
|
|
389
|
+
}
|
|
390
|
+
} else {
|
|
391
|
+
const { id, ...row } = form.values;
|
|
392
|
+
if (+id) {
|
|
393
|
+
await PageGroup.update(id, row);
|
|
394
|
+
res.json({ success: "ok", row });
|
|
395
|
+
} else {
|
|
396
|
+
const pageGroup = await PageGroup.create(row);
|
|
397
|
+
res.redirect(`/page_groupedit/${pageGroup.name}`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
})
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* load a form to add a member to a group
|
|
405
|
+
*/
|
|
406
|
+
router.get(
|
|
407
|
+
"/add-member/:page_groupname",
|
|
408
|
+
isAdmin,
|
|
409
|
+
error_catcher(async (req, res) => {
|
|
410
|
+
const { page_groupname } = req.params;
|
|
411
|
+
const group = PageGroup.findOne({ name: page_groupname });
|
|
412
|
+
if (!group) {
|
|
413
|
+
req.flash("error", req.__("Page group %s not found", page_groupname));
|
|
414
|
+
res.redirect(`/page_groupedit/${page_groupname}`);
|
|
415
|
+
} else {
|
|
416
|
+
const form = await addMemberForm(group, req);
|
|
417
|
+
res.sendWrap(
|
|
418
|
+
req.__(`%s add-member`, group.name),
|
|
419
|
+
wrapMember(renderForm(form, req.csrfToken()), req, group)
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
})
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* add a member to a group
|
|
427
|
+
*/
|
|
428
|
+
router.post(
|
|
429
|
+
"/add-member/:page_groupname",
|
|
430
|
+
isAdmin,
|
|
431
|
+
error_catcher(async (req, res) => {
|
|
432
|
+
const { page_groupname } = req.params;
|
|
433
|
+
const group = PageGroup.findOne({ name: page_groupname });
|
|
434
|
+
if (!group) {
|
|
435
|
+
req.flash("error", req.__("Page group %s not found", page_groupname));
|
|
436
|
+
res.redirect(`/page_groupedit/${page_groupname}`);
|
|
437
|
+
}
|
|
438
|
+
const form = await addMemberForm(group, req);
|
|
439
|
+
form.validate(req.body);
|
|
440
|
+
if (form.hasErrors) {
|
|
441
|
+
res.sendWrap(
|
|
442
|
+
req.__(`%s add-member`, group.name),
|
|
443
|
+
wrapMember(renderForm(form, req.csrfToken()), req, group)
|
|
444
|
+
);
|
|
445
|
+
} else {
|
|
446
|
+
const { page_name, eligible_formula, description } = form.values;
|
|
447
|
+
const page = Page.findOne({ name: page_name });
|
|
448
|
+
if (!page) {
|
|
449
|
+
req.flash("error", req.__("Page %s not found", page_name));
|
|
450
|
+
res.sendWrap(
|
|
451
|
+
req.__(`%s add-member`, group.name),
|
|
452
|
+
wrapMember(renderForm(form, req.csrfToken()), req, group)
|
|
453
|
+
);
|
|
454
|
+
} else {
|
|
455
|
+
await group.addMember({
|
|
456
|
+
page_id: page.id,
|
|
457
|
+
eligible_formula,
|
|
458
|
+
description: description || "",
|
|
459
|
+
});
|
|
460
|
+
req.flash("success", req.__("Added member"));
|
|
461
|
+
res.redirect(`/page_groupedit/${page_groupname}`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
})
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* move a group-member up/dowm
|
|
469
|
+
*/
|
|
470
|
+
router.post(
|
|
471
|
+
"/move-member/:member_id/:mode",
|
|
472
|
+
isAdmin,
|
|
473
|
+
error_catcher(async (req, res) => {
|
|
474
|
+
const { member_id, mode } = req.params;
|
|
475
|
+
try {
|
|
476
|
+
const member = PageGroupMember.findOne({ id: member_id });
|
|
477
|
+
const pageGroup = PageGroup.findOne({ id: member.page_group_id });
|
|
478
|
+
await pageGroup.moveMember(member, mode);
|
|
479
|
+
res.json({ success: "ok" });
|
|
480
|
+
} catch (error) {
|
|
481
|
+
getState().log(2, `POST /page_groupedit/move-member: '${error.message}'`);
|
|
482
|
+
res.status(400).json({ error: error.message || error });
|
|
483
|
+
}
|
|
484
|
+
})
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* load a form to edit a group-member
|
|
489
|
+
*/
|
|
490
|
+
router.get(
|
|
491
|
+
"/edit-member/:member_id",
|
|
492
|
+
isAdmin,
|
|
493
|
+
error_catcher(async (req, res) => {
|
|
494
|
+
const { member_id } = req.params;
|
|
495
|
+
const member = PageGroupMember.findOne({ id: member_id });
|
|
496
|
+
if (!member) {
|
|
497
|
+
req.flash("error", req.__("member %s does not exist", member_id));
|
|
498
|
+
return res.redirect("/pageedit");
|
|
499
|
+
}
|
|
500
|
+
const group = PageGroup.findOne({ id: member.page_group_id });
|
|
501
|
+
if (!group) {
|
|
502
|
+
req.flash(
|
|
503
|
+
"error",
|
|
504
|
+
req.__("Page group %s not found", member.page_group_id)
|
|
505
|
+
);
|
|
506
|
+
return res.redirect("/pageedit");
|
|
507
|
+
}
|
|
508
|
+
const page = Page.findOne({ id: member.page_id });
|
|
509
|
+
if (!page) {
|
|
510
|
+
req.flash("error", req.__("Page %s not found", member.page_id));
|
|
511
|
+
return res.redirect(`/page_groupedit/${group.name}`);
|
|
512
|
+
}
|
|
513
|
+
const form = await editMemberForm(member, req);
|
|
514
|
+
form.hidden("id");
|
|
515
|
+
form.values = { ...member, page_name: page.name };
|
|
516
|
+
|
|
517
|
+
res.sendWrap(
|
|
518
|
+
req.__(`%s edit-member`, member.name || member.id),
|
|
519
|
+
wrapMember(renderForm(form, req.csrfToken()), req, group, member)
|
|
520
|
+
);
|
|
521
|
+
})
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* edit a member of a group
|
|
526
|
+
*/
|
|
527
|
+
router.post(
|
|
528
|
+
"/edit-member/:member_id",
|
|
529
|
+
isAdmin,
|
|
530
|
+
error_catcher(async (req, res) => {
|
|
531
|
+
const { member_id } = req.params;
|
|
532
|
+
const member = PageGroupMember.findOne({ id: member_id });
|
|
533
|
+
const group = PageGroup.findOne({ id: member.page_group_id });
|
|
534
|
+
const form = await editMemberForm(member, req);
|
|
535
|
+
form.hidden("id");
|
|
536
|
+
form.validate(req.body);
|
|
537
|
+
if (form.hasErrors) {
|
|
538
|
+
res.sendWrap(
|
|
539
|
+
req.__(`%s edit-member`, member.name || member.id),
|
|
540
|
+
wrapMember(renderForm(form, req.csrfToken()), req, group, member)
|
|
541
|
+
);
|
|
542
|
+
} else {
|
|
543
|
+
const { id, page_name, eligible_formula, description } = form.values;
|
|
544
|
+
const page = Page.findOne({ name: page_name });
|
|
545
|
+
if (!page) {
|
|
546
|
+
req.flash("error", req.__("Page %s not found", page_name));
|
|
547
|
+
res.redirect(`/page_groupedit/${group.name}`);
|
|
548
|
+
} else
|
|
549
|
+
await PageGroupMember.update(id, {
|
|
550
|
+
page_group_id: group.id,
|
|
551
|
+
page_id: page.id,
|
|
552
|
+
eligible_formula,
|
|
553
|
+
description: description || "",
|
|
554
|
+
});
|
|
555
|
+
req.flash("success", req.__("Updated member"));
|
|
556
|
+
res.redirect(`/page_groupedit/${group.name}`);
|
|
557
|
+
}
|
|
558
|
+
})
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* delete a group
|
|
563
|
+
*/
|
|
564
|
+
router.post(
|
|
565
|
+
"/delete/:group_id",
|
|
566
|
+
isAdmin,
|
|
567
|
+
error_catcher(async (req, res) => {
|
|
568
|
+
const { group_id } = req.params;
|
|
569
|
+
const group = PageGroup.findOne({ id: group_id });
|
|
570
|
+
if (!group) {
|
|
571
|
+
req.flash("error", req.__("Page group %s not found", group_id));
|
|
572
|
+
res.redirect("/pageedit");
|
|
573
|
+
} else {
|
|
574
|
+
await group.delete();
|
|
575
|
+
req.flash("success", req.__("Deleted page group %s", group_id));
|
|
576
|
+
res.redirect("/pageedit");
|
|
577
|
+
}
|
|
578
|
+
})
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* delete a group-member
|
|
583
|
+
*/
|
|
584
|
+
router.post(
|
|
585
|
+
"/remove-member/:member_id",
|
|
586
|
+
isAdmin,
|
|
587
|
+
error_catcher(async (req, res) => {
|
|
588
|
+
const { member_id } = req.params;
|
|
589
|
+
const member = PageGroupMember.findOne({ id: member_id });
|
|
590
|
+
if (!member) {
|
|
591
|
+
req.flash("error", req.__("Page group member %s not found", member_id));
|
|
592
|
+
res.redirect("/pageedit");
|
|
593
|
+
} else {
|
|
594
|
+
const group = PageGroup.findOne({ id: member.page_group_id });
|
|
595
|
+
if (!group) {
|
|
596
|
+
req.flash(
|
|
597
|
+
"error",
|
|
598
|
+
req.__("Page group %s not found", member.page_group_id)
|
|
599
|
+
);
|
|
600
|
+
res.redirect("/pageedit");
|
|
601
|
+
} else {
|
|
602
|
+
try {
|
|
603
|
+
await group.removeMember(member_id);
|
|
604
|
+
req.flash(
|
|
605
|
+
"success",
|
|
606
|
+
req.__("Removed member %s", member.name || member_id)
|
|
607
|
+
);
|
|
608
|
+
res.redirect(`/page_groupedit/${group.name}`);
|
|
609
|
+
} catch (e) {
|
|
610
|
+
req.flash("error", e.message);
|
|
611
|
+
res.redirect(`/page_groupedit/${group.name}`);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
})
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* clone a group
|
|
620
|
+
*/
|
|
621
|
+
router.post(
|
|
622
|
+
"/clone/:id",
|
|
623
|
+
isAdmin,
|
|
624
|
+
error_catcher(async (req, res) => {
|
|
625
|
+
const { id } = req.params;
|
|
626
|
+
const group = PageGroup.findOne({ id });
|
|
627
|
+
if (!group) {
|
|
628
|
+
req.flash("error", req.__("Page group %s not found", id));
|
|
629
|
+
res.redirect("/pageedit");
|
|
630
|
+
} else {
|
|
631
|
+
const copy = await group.clone();
|
|
632
|
+
req.flash("success", req.__("Cloned page group %s", group.name));
|
|
633
|
+
res.redirect(`/page_groupedit/${copy.name}`);
|
|
634
|
+
}
|
|
635
|
+
})
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* add a pagegroup-link to the menu
|
|
640
|
+
*/
|
|
641
|
+
router.post(
|
|
642
|
+
"/add-to-menu/:id",
|
|
643
|
+
isAdmin,
|
|
644
|
+
error_catcher(async (req, res) => {
|
|
645
|
+
const { id } = req.params;
|
|
646
|
+
const group = PageGroup.findOne({ id });
|
|
647
|
+
if (!group) {
|
|
648
|
+
req.flash("error", req.__("Page group %s not found", id));
|
|
649
|
+
res.redirect("/pageedit");
|
|
650
|
+
} else {
|
|
651
|
+
await add_to_menu({
|
|
652
|
+
label: group.name,
|
|
653
|
+
type: "Page", // TODO PageGroup
|
|
654
|
+
min_role: group.min_role,
|
|
655
|
+
pagename: group.name,
|
|
656
|
+
});
|
|
657
|
+
req.flash(
|
|
658
|
+
"success",
|
|
659
|
+
req.__(
|
|
660
|
+
"Page %s added to menu. Adjust access permissions in Settings » Menu",
|
|
661
|
+
group.name
|
|
662
|
+
)
|
|
663
|
+
);
|
|
664
|
+
res.redirect(`/pageedit`);
|
|
665
|
+
}
|
|
666
|
+
})
|
|
667
|
+
);
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* set the role of a group
|
|
671
|
+
*/
|
|
672
|
+
router.post(
|
|
673
|
+
"/setrole/:id",
|
|
674
|
+
isAdmin,
|
|
675
|
+
error_catcher(async (req, res) => {
|
|
676
|
+
await setRole(req, res, PageGroup);
|
|
677
|
+
})
|
|
678
|
+
);
|