@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
package/routes/page.js
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const Router = require("express-promise-router");
|
|
8
|
+
const { UAParser } = require("ua-parser-js");
|
|
8
9
|
|
|
9
10
|
const Page = require("@saltcorn/data/models/page");
|
|
11
|
+
const PageGroup = require("@saltcorn/data/models/page_group");
|
|
10
12
|
const Trigger = require("@saltcorn/data/models/trigger");
|
|
11
|
-
const
|
|
12
|
-
const { getState } = require("@saltcorn/data/db/state");
|
|
13
|
+
const { getState, features } = require("@saltcorn/data/db/state");
|
|
13
14
|
const {
|
|
14
15
|
error_catcher,
|
|
15
16
|
scan_for_page_title,
|
|
@@ -18,6 +19,7 @@ const {
|
|
|
18
19
|
} = require("../routes/utils.js");
|
|
19
20
|
const { isTest } = require("@saltcorn/data/utils");
|
|
20
21
|
const { add_edit_bar } = require("../markup/admin.js");
|
|
22
|
+
const { script, domReady } = require("@saltcorn/markup/tags");
|
|
21
23
|
const { traverseSync } = require("@saltcorn/data/models/layout");
|
|
22
24
|
const { run_action_column } = require("@saltcorn/data/plugin-helper");
|
|
23
25
|
const db = require("@saltcorn/data/db");
|
|
@@ -32,56 +34,134 @@ const db = require("@saltcorn/data/db");
|
|
|
32
34
|
const router = new Router();
|
|
33
35
|
module.exports = router;
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
const findPageOrGroup = (pagename) => {
|
|
38
|
+
const page = Page.findOne({ name: pagename });
|
|
39
|
+
if (page) return { page, pageGroup: null };
|
|
40
|
+
else {
|
|
41
|
+
const pageGroup = PageGroup.findOne({ name: pagename });
|
|
42
|
+
if (pageGroup) return { page: null, pageGroup };
|
|
43
|
+
else return { page: null, pageGroup: null };
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const runPage = async (page, req, res, tic) => {
|
|
48
|
+
const role = req.user && req.user.id ? req.user.role_id : 100;
|
|
49
|
+
if (role <= page.min_role) {
|
|
50
|
+
const contents = await page.run(req.query, { res, req });
|
|
51
|
+
const title = scan_for_page_title(contents, page.title);
|
|
52
|
+
const tock = new Date();
|
|
53
|
+
const ms = tock.getTime() - tic.getTime();
|
|
54
|
+
if (!isTest())
|
|
55
|
+
Trigger.emitEvent("PageLoad", null, req.user, {
|
|
56
|
+
text: req.__("Page '%s' was loaded", page.name),
|
|
57
|
+
type: "page",
|
|
58
|
+
name: page.name,
|
|
59
|
+
render_time: ms,
|
|
60
|
+
});
|
|
61
|
+
if (contents.html_file) await sendHtmlFile(req, res, contents.html_file);
|
|
62
|
+
else
|
|
63
|
+
res.sendWrap(
|
|
64
|
+
{
|
|
65
|
+
title,
|
|
66
|
+
description: page.description,
|
|
67
|
+
bodyClass: "page_" + db.sqlsanitize(page.name),
|
|
68
|
+
no_menu: page.attributes?.no_menu,
|
|
69
|
+
} || `${page.name} page`,
|
|
70
|
+
add_edit_bar({
|
|
71
|
+
role,
|
|
72
|
+
title: page.name,
|
|
73
|
+
what: req.__("Page"),
|
|
74
|
+
url: `/pageedit/edit/${encodeURIComponent(page.name)}`,
|
|
75
|
+
contents,
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
} else {
|
|
79
|
+
getState().log(2, `Page ${page.name} not authorized`);
|
|
80
|
+
res.status(404).sendWrap(` page`, req.__("Page %s not found", page.name));
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const uaDevice = (req) => {
|
|
85
|
+
const uaParser = new UAParser(req.headers["user-agent"]);
|
|
86
|
+
const device = uaParser.getDevice();
|
|
87
|
+
if (!device.type) return "web";
|
|
88
|
+
else return device.type;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const screenInfoFromCfg = (req) => {
|
|
92
|
+
const device = uaDevice(req);
|
|
93
|
+
const uaScreenInfos = getState().getConfig("user_agent_screen_infos", {});
|
|
94
|
+
return { device, ...uaScreenInfos[device] };
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const runPageGroup = async (pageGroup, req, res, tic) => {
|
|
98
|
+
const role = req.user && req.user.id ? req.user.role_id : 100;
|
|
99
|
+
if (role <= pageGroup.min_role) {
|
|
100
|
+
if (pageGroup.members.length === 0) {
|
|
101
|
+
getState().log(2, `Pagegroup ${pageGroup.name} has no members`);
|
|
102
|
+
res
|
|
103
|
+
.status(400)
|
|
104
|
+
.sendWrap(
|
|
105
|
+
` page`,
|
|
106
|
+
req.__("Pagegroup %s has no members", pageGroup.name)
|
|
107
|
+
);
|
|
108
|
+
} else {
|
|
109
|
+
let screenInfos = null;
|
|
110
|
+
if (req.cookies["_sc_screen_info_"]) {
|
|
111
|
+
screenInfos = JSON.parse(req.cookies["_sc_screen_info_"]);
|
|
112
|
+
screenInfos.device = uaDevice(req);
|
|
113
|
+
} else {
|
|
114
|
+
const strategy = getState().getConfig(
|
|
115
|
+
"missing_screen_info_strategy",
|
|
116
|
+
"guess_from_user_agent"
|
|
117
|
+
);
|
|
118
|
+
if (strategy === "guess_from_user_agent")
|
|
119
|
+
screenInfos = screenInfoFromCfg(req);
|
|
120
|
+
else if (strategy === "reload" && req.query.is_reload !== "true") {
|
|
121
|
+
return res.sendWrap(
|
|
122
|
+
script(
|
|
123
|
+
domReady(`
|
|
124
|
+
setScreenInfoCookie();
|
|
125
|
+
window.location = updateQueryStringParameter(window.location.href, "is_reload", true);`)
|
|
126
|
+
)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const eligiblePage = await pageGroup.getEligiblePage(
|
|
131
|
+
screenInfos,
|
|
132
|
+
req.user ? req.user : { role_id: features.public_user_role },
|
|
133
|
+
req.getLocale()
|
|
134
|
+
);
|
|
135
|
+
if (eligiblePage) await runPage(eligiblePage, req, res, tic);
|
|
136
|
+
else {
|
|
137
|
+
getState().log(2, `Pagegroup ${pageGroup.name} has no eligible page`);
|
|
138
|
+
res
|
|
139
|
+
.status(404)
|
|
140
|
+
.sendWrap(` page`, req.__("%s has no eligible page", pageGroup.name));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
getState().log(2, `Pagegroup ${pageGroup.name} not authorized`);
|
|
145
|
+
res
|
|
146
|
+
.status(404)
|
|
147
|
+
.sendWrap(` page`, req.__("Pagegroup %s not found", pageGroup.name));
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
41
151
|
router.get(
|
|
42
152
|
"/:pagename",
|
|
43
153
|
error_catcher(async (req, res) => {
|
|
44
154
|
const { pagename } = req.params;
|
|
45
|
-
|
|
46
|
-
state.log(3, `Route /page/${pagename} user=${req.user?.id}`);
|
|
155
|
+
getState().log(3, `Route /page/${pagename} user=${req.user?.id}`);
|
|
47
156
|
const tic = new Date();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const title = scan_for_page_title(contents, db_page.title);
|
|
54
|
-
const tock = new Date();
|
|
55
|
-
const ms = tock.getTime() - tic.getTime();
|
|
56
|
-
if (!isTest())
|
|
57
|
-
Trigger.emitEvent("PageLoad", null, req.user, {
|
|
58
|
-
text: req.__("Page '%s' was loaded", pagename),
|
|
59
|
-
type: "page",
|
|
60
|
-
name: pagename,
|
|
61
|
-
render_time: ms,
|
|
62
|
-
});
|
|
63
|
-
if (contents.html_file) await sendHtmlFile(req, res, contents.html_file);
|
|
64
|
-
else
|
|
65
|
-
res.sendWrap(
|
|
66
|
-
{
|
|
67
|
-
title,
|
|
68
|
-
description: db_page.description,
|
|
69
|
-
bodyClass: "page_" + db.sqlsanitize(pagename),
|
|
70
|
-
no_menu: db_page.attributes?.no_menu,
|
|
71
|
-
} || `${pagename} page`,
|
|
72
|
-
add_edit_bar({
|
|
73
|
-
role,
|
|
74
|
-
title: db_page.name,
|
|
75
|
-
what: req.__("Page"),
|
|
76
|
-
url: `/pageedit/edit/${encodeURIComponent(db_page.name)}`,
|
|
77
|
-
contents,
|
|
78
|
-
})
|
|
79
|
-
);
|
|
80
|
-
} else {
|
|
81
|
-
if (db_page && !req.user) {
|
|
157
|
+
const { page, pageGroup } = findPageOrGroup(pagename);
|
|
158
|
+
if (page) await runPage(page, req, res, tic);
|
|
159
|
+
else if (pageGroup) await runPageGroup(pageGroup, req, res, tic);
|
|
160
|
+
else {
|
|
161
|
+
if ((page || pageGroup) && !req.user) {
|
|
82
162
|
res.redirect(`/auth/login?dest=${encodeURIComponent(req.originalUrl)}`);
|
|
83
163
|
} else {
|
|
84
|
-
|
|
164
|
+
getState().log(2, `Page ${pagename} not found or not authorized`);
|
|
85
165
|
res
|
|
86
166
|
.status(404)
|
|
87
167
|
.sendWrap(`${pagename} page`, req.__("Page %s not found", pagename));
|
|
@@ -105,12 +185,6 @@ router.post(
|
|
|
105
185
|
})
|
|
106
186
|
);
|
|
107
187
|
|
|
108
|
-
/**
|
|
109
|
-
* @name post/:pagename/action/:rndid
|
|
110
|
-
* @function
|
|
111
|
-
* @memberof module:routes/page~pageRouter
|
|
112
|
-
* @function
|
|
113
|
-
*/
|
|
114
188
|
router.post(
|
|
115
189
|
"/:pagename/action/:rndid",
|
|
116
190
|
error_catcher(async (req, res) => {
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
const Router = require("express-promise-router");
|
|
2
|
+
|
|
3
|
+
const Form = require("@saltcorn/data/models/form");
|
|
4
|
+
const { error_catcher, isAdmin } = require("./utils.js");
|
|
5
|
+
const { send_infoarch_page } = require("../markup/admin.js");
|
|
6
|
+
const { getState } = require("@saltcorn/data/db/state");
|
|
7
|
+
const { a, div, i, p } = require("@saltcorn/markup/tags");
|
|
8
|
+
const {
|
|
9
|
+
renderForm,
|
|
10
|
+
link,
|
|
11
|
+
post_delete_btn,
|
|
12
|
+
mkTable,
|
|
13
|
+
} = require("@saltcorn/markup");
|
|
14
|
+
|
|
15
|
+
const router = new Router();
|
|
16
|
+
module.exports = router;
|
|
17
|
+
|
|
18
|
+
const deviceTypes = [
|
|
19
|
+
"mobile",
|
|
20
|
+
"tablet",
|
|
21
|
+
"console",
|
|
22
|
+
"smarttv",
|
|
23
|
+
"wearable",
|
|
24
|
+
"web",
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const deviceForm = (req, deviceValidator, device) => {
|
|
28
|
+
const sizeValidator = (v) => {
|
|
29
|
+
const n = +v;
|
|
30
|
+
if (isNaN(n)) return req.__("Not a number");
|
|
31
|
+
if (n < 0) return req.__("Must be positive");
|
|
32
|
+
};
|
|
33
|
+
return new Form({
|
|
34
|
+
action: `/page_group/settings/${
|
|
35
|
+
!device ? "add-device" : `edit-device/${device}`
|
|
36
|
+
}`,
|
|
37
|
+
fields: [
|
|
38
|
+
{
|
|
39
|
+
name: "device",
|
|
40
|
+
input_type: "select",
|
|
41
|
+
type: "String",
|
|
42
|
+
options: ["mobile", "tablet", "console", "smarttv", "wearable", "web"],
|
|
43
|
+
required: true,
|
|
44
|
+
validator: deviceValidator,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "width",
|
|
48
|
+
label: req.__("width"),
|
|
49
|
+
type: "String",
|
|
50
|
+
required: true,
|
|
51
|
+
validator: sizeValidator,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "height",
|
|
55
|
+
label: req.__("height"),
|
|
56
|
+
type: "String",
|
|
57
|
+
required: true,
|
|
58
|
+
validator: sizeValidator,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "innerWidth",
|
|
62
|
+
label: req.__("innerWidth"),
|
|
63
|
+
type: "String",
|
|
64
|
+
required: true,
|
|
65
|
+
validator: sizeValidator,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "innerHeight",
|
|
69
|
+
label: req.__("innerHeight"),
|
|
70
|
+
type: "String",
|
|
71
|
+
required: true,
|
|
72
|
+
validator: sizeValidator,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
additionalButtons: [
|
|
76
|
+
{
|
|
77
|
+
label: device ? req.__("Close") : req.__("Cancel"),
|
|
78
|
+
class: "btn btn-primary",
|
|
79
|
+
onclick: "location.href='/page_group/settings'",
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const loadDeviceConfigs = () => {
|
|
86
|
+
const cfg = getState().getConfig("user_agent_screen_infos", {});
|
|
87
|
+
const deviceConfigs = deviceTypes
|
|
88
|
+
.filter((device) => cfg[device])
|
|
89
|
+
.map((device) => ({
|
|
90
|
+
device,
|
|
91
|
+
...cfg[device],
|
|
92
|
+
}));
|
|
93
|
+
return deviceConfigs;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const pageGroupSettingsForm = (req) => {
|
|
97
|
+
return new Form({
|
|
98
|
+
action: "/page_group/settings/config",
|
|
99
|
+
noSubmitButton: true,
|
|
100
|
+
onChange: `saveAndContinue(this)`,
|
|
101
|
+
fields: [
|
|
102
|
+
{
|
|
103
|
+
name: "missing_screen_info_strategy",
|
|
104
|
+
label: req.__("Missing screen info"),
|
|
105
|
+
sublabel: req.__(
|
|
106
|
+
"What to do if no screen info is given. Reload with parmeters or guess it from the user-agent."
|
|
107
|
+
),
|
|
108
|
+
type: "String",
|
|
109
|
+
input_type: "select",
|
|
110
|
+
options: [
|
|
111
|
+
{
|
|
112
|
+
label: req.__("Guess from user agent"),
|
|
113
|
+
value: "guess_from_user_agent",
|
|
114
|
+
},
|
|
115
|
+
{ label: req.__("Reload"), value: "reload" },
|
|
116
|
+
],
|
|
117
|
+
required: true,
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* load the screen-info table
|
|
125
|
+
*/
|
|
126
|
+
router.get(
|
|
127
|
+
"/settings",
|
|
128
|
+
isAdmin,
|
|
129
|
+
error_catcher(async (req, res) => {
|
|
130
|
+
const deviceConfigs = loadDeviceConfigs();
|
|
131
|
+
const pgForm = pageGroupSettingsForm(req);
|
|
132
|
+
pgForm.values.missing_screen_info_strategy = getState().getConfig(
|
|
133
|
+
"missing_screen_info_strategy",
|
|
134
|
+
"guess_from_user_agent"
|
|
135
|
+
);
|
|
136
|
+
send_infoarch_page({
|
|
137
|
+
res,
|
|
138
|
+
req,
|
|
139
|
+
active_sub: "Pagegroups",
|
|
140
|
+
contents: [
|
|
141
|
+
{
|
|
142
|
+
type: "card",
|
|
143
|
+
title: req.__("User Agent screen infos"),
|
|
144
|
+
contents: [
|
|
145
|
+
p(
|
|
146
|
+
req.__(
|
|
147
|
+
"This screen infos are used when the browser does not send them. " +
|
|
148
|
+
"With 'Missing screen info' set to 'Guess from user agent', the user agent gets mapped to a device with the following values."
|
|
149
|
+
)
|
|
150
|
+
),
|
|
151
|
+
mkTable(
|
|
152
|
+
[
|
|
153
|
+
{
|
|
154
|
+
label: "Device",
|
|
155
|
+
key: (r) =>
|
|
156
|
+
link(
|
|
157
|
+
`/page_group/settings/edit-device/${r.device}`,
|
|
158
|
+
r.device
|
|
159
|
+
),
|
|
160
|
+
},
|
|
161
|
+
{ label: "width", key: (r) => r.width },
|
|
162
|
+
{ label: "height", key: (r) => r.height },
|
|
163
|
+
{ label: "innerWidth", key: (r) => r.innerWidth },
|
|
164
|
+
{ label: "innerHeight", key: (r) => r.innerHeight },
|
|
165
|
+
{
|
|
166
|
+
label: req.__("Delete"),
|
|
167
|
+
key: (r) =>
|
|
168
|
+
post_delete_btn(
|
|
169
|
+
`/page_group/settings/remove-device/${r.device}`,
|
|
170
|
+
req,
|
|
171
|
+
r.device
|
|
172
|
+
),
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
deviceConfigs,
|
|
176
|
+
{}
|
|
177
|
+
),
|
|
178
|
+
div(
|
|
179
|
+
a(
|
|
180
|
+
{
|
|
181
|
+
href: "settings/add-device",
|
|
182
|
+
class: "btn btn-primary mt-1 me-3",
|
|
183
|
+
},
|
|
184
|
+
i({ class: "fas fa-plus-square me-1" }),
|
|
185
|
+
req.__("Add screen info")
|
|
186
|
+
)
|
|
187
|
+
),
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
{
|
|
192
|
+
type: "card",
|
|
193
|
+
title: req.__("Page Group settings"),
|
|
194
|
+
contents: [renderForm(pgForm, req.csrfToken())],
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
})
|
|
199
|
+
);
|
|
200
|
+
/**
|
|
201
|
+
* load a form to add a screen-info to the config
|
|
202
|
+
*/
|
|
203
|
+
router.get(
|
|
204
|
+
"/settings/add-device",
|
|
205
|
+
isAdmin,
|
|
206
|
+
error_catcher(async (req, res) => {
|
|
207
|
+
send_infoarch_page({
|
|
208
|
+
res,
|
|
209
|
+
req,
|
|
210
|
+
active_sub: "Pagegroups",
|
|
211
|
+
contents: {
|
|
212
|
+
type: "card",
|
|
213
|
+
title: req.__("Add screen info"),
|
|
214
|
+
contents: [
|
|
215
|
+
renderForm(
|
|
216
|
+
deviceForm(req, () => {}),
|
|
217
|
+
req.csrfToken()
|
|
218
|
+
),
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
})
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* add a screen-info to the config
|
|
227
|
+
*/
|
|
228
|
+
router.post(
|
|
229
|
+
"/settings/add-device",
|
|
230
|
+
isAdmin,
|
|
231
|
+
error_catcher(async (req, res) => {
|
|
232
|
+
const cfg = getState().getConfig("user_agent_screen_infos", {});
|
|
233
|
+
const validator = (v) => {
|
|
234
|
+
if (cfg[v]) return req.__("Device already exists");
|
|
235
|
+
};
|
|
236
|
+
const form = deviceForm(req, validator);
|
|
237
|
+
form.validate(req.body);
|
|
238
|
+
if (form.hasErrors) {
|
|
239
|
+
send_infoarch_page({
|
|
240
|
+
res,
|
|
241
|
+
req,
|
|
242
|
+
active_sub: "Pagegroups",
|
|
243
|
+
contents: {
|
|
244
|
+
type: "card",
|
|
245
|
+
title: req.__("Add screen info"),
|
|
246
|
+
contents: [renderForm(form, req.csrfToken())],
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
} else {
|
|
250
|
+
const { device, width, height, innerWidth, innerHeight } = form.values;
|
|
251
|
+
const newCfg = {
|
|
252
|
+
...cfg,
|
|
253
|
+
[device]: { width, height, innerWidth, innerHeight },
|
|
254
|
+
};
|
|
255
|
+
await getState().setConfig("user_agent_screen_infos", newCfg);
|
|
256
|
+
req.flash("success", req.__("Screen info added"));
|
|
257
|
+
res.redirect("/page_group/settings");
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* remove a screen-info from the config
|
|
264
|
+
*/
|
|
265
|
+
router.post(
|
|
266
|
+
"/settings/remove-device/:device",
|
|
267
|
+
isAdmin,
|
|
268
|
+
error_catcher(async (req, res) => {
|
|
269
|
+
const { device } = req.params;
|
|
270
|
+
const cfg = getState().getConfig("user_agent_screen_infos", {});
|
|
271
|
+
const newCfg = { ...cfg };
|
|
272
|
+
delete newCfg[device];
|
|
273
|
+
await getState().setConfig("user_agent_screen_infos", newCfg);
|
|
274
|
+
req.flash("success", req.__("Screen info removed"));
|
|
275
|
+
res.redirect("/page_group/settings");
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* load a form to edit a screen-info
|
|
281
|
+
*/
|
|
282
|
+
router.get(
|
|
283
|
+
"/settings/edit-device/:device",
|
|
284
|
+
isAdmin,
|
|
285
|
+
error_catcher(async (req, res) => {
|
|
286
|
+
const { device } = req.params;
|
|
287
|
+
const cfg = getState().getConfig("user_agent_screen_infos", {});
|
|
288
|
+
const deviceCfg = cfg[device];
|
|
289
|
+
const form = deviceForm(req, () => {}, device);
|
|
290
|
+
form.values = { device, ...deviceCfg };
|
|
291
|
+
send_infoarch_page({
|
|
292
|
+
res,
|
|
293
|
+
req,
|
|
294
|
+
active_sub: "Pagegroups",
|
|
295
|
+
contents: {
|
|
296
|
+
type: "card",
|
|
297
|
+
title: req.__("Edit screen info"),
|
|
298
|
+
contents: [renderForm(form, req.csrfToken())],
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
})
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* edit a screen-info
|
|
306
|
+
*/
|
|
307
|
+
router.post(
|
|
308
|
+
"/settings/edit-device/:device",
|
|
309
|
+
isAdmin,
|
|
310
|
+
error_catcher(async (req, res) => {
|
|
311
|
+
const { device } = req.params;
|
|
312
|
+
const cfg = getState().getConfig("user_agent_screen_infos", {});
|
|
313
|
+
const validator = (v) => {
|
|
314
|
+
if (cfg[v] && v !== device) return req.__("Device already exists");
|
|
315
|
+
};
|
|
316
|
+
const form = deviceForm(req, validator, device);
|
|
317
|
+
const deviceCfg = cfg[device];
|
|
318
|
+
form.values = { device, ...deviceCfg };
|
|
319
|
+
form.validate(req.body);
|
|
320
|
+
if (form.hasErrors) {
|
|
321
|
+
send_infoarch_page({
|
|
322
|
+
res,
|
|
323
|
+
req,
|
|
324
|
+
active_sub: "Pagegroups",
|
|
325
|
+
contents: {
|
|
326
|
+
type: "card",
|
|
327
|
+
title: req.__("Edit device"),
|
|
328
|
+
contents: [renderForm(form, req.csrfToken())],
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
} else {
|
|
332
|
+
const { width, height, innerWidth, innerHeight } = form.values;
|
|
333
|
+
const newCfg = {
|
|
334
|
+
...cfg,
|
|
335
|
+
[form.values.device]: { width, height, innerWidth, innerHeight },
|
|
336
|
+
};
|
|
337
|
+
if (device !== form.values.device) delete newCfg[device];
|
|
338
|
+
await getState().setConfig("user_agent_screen_infos", newCfg);
|
|
339
|
+
req.flash("success", req.__("Screen info saved"));
|
|
340
|
+
res.redirect("/page_group/settings");
|
|
341
|
+
}
|
|
342
|
+
})
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* save the missing_screen_info_strategy
|
|
347
|
+
* This configures what to do if no screen info is given (reload or guess from user-agent)
|
|
348
|
+
*/
|
|
349
|
+
router.post(
|
|
350
|
+
"/settings/config",
|
|
351
|
+
isAdmin,
|
|
352
|
+
error_catcher(async (req, res) => {
|
|
353
|
+
const form = pageGroupSettingsForm(req);
|
|
354
|
+
form.validate(req.body);
|
|
355
|
+
if (form.hasErrors) {
|
|
356
|
+
send_infoarch_page({
|
|
357
|
+
res,
|
|
358
|
+
req,
|
|
359
|
+
active_sub: "Pagegroups",
|
|
360
|
+
contents: {
|
|
361
|
+
type: "card",
|
|
362
|
+
title: req.__("Page Group settings"),
|
|
363
|
+
contents: [renderForm(form, req.csrfToken())],
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
} else {
|
|
367
|
+
const { missing_screen_info_strategy } = form.values;
|
|
368
|
+
await getState().setConfig(
|
|
369
|
+
"missing_screen_info_strategy",
|
|
370
|
+
missing_screen_info_strategy
|
|
371
|
+
);
|
|
372
|
+
req.flash("success", req.__("Settings saved"));
|
|
373
|
+
res.redirect("/page_group/settings");
|
|
374
|
+
}
|
|
375
|
+
})
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
// perhaps another service to omit endless reload loops here
|