@saltcorn/server 0.7.2-beta.0 → 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/app.js +64 -9
- package/auth/routes.js +37 -13
- package/load_plugins.js +39 -27
- package/locales/da.json +1 -1
- package/locales/de.json +155 -155
- package/locales/en.json +25 -4
- package/locales/it.json +3 -2
- package/locales/ru.json +73 -28
- package/locales/zh.json +3 -3
- package/markup/admin.js +25 -9
- package/package.json +11 -8
- package/public/saltcorn-common.js +544 -0
- package/public/saltcorn.css +61 -0
- package/public/saltcorn.js +15 -476
- package/restart_watcher.js +1 -1
- package/routes/admin.js +159 -38
- package/routes/api.js +36 -1
- package/routes/edit.js +2 -1
- package/routes/eventlog.js +30 -30
- package/routes/fields.js +18 -0
- package/routes/files.js +7 -20
- package/routes/homepage.js +35 -7
- package/routes/menu.js +11 -7
- package/routes/tables.js +1 -1
- package/routes/tenant.js +13 -10
- package/routes/viewedit.js +10 -1
- package/serve.js +15 -1
- package/tests/admin.test.js +72 -1
- package/tests/clientjs.test.js +1 -0
- package/tests/viewedit.test.js +94 -0
- package/wrapper.js +56 -12
package/routes/homepage.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Default Home Page (Wellcome page)
|
|
3
|
+
* Opens for new site without any data
|
|
2
4
|
* @category server
|
|
3
5
|
* @module routes/homepage
|
|
4
6
|
* @subcategory routes
|
|
@@ -10,11 +12,11 @@ const View = require("@saltcorn/data/models/view");
|
|
|
10
12
|
const User = require("@saltcorn/data/models/user");
|
|
11
13
|
const File = require("@saltcorn/data/models/file");
|
|
12
14
|
const Page = require("@saltcorn/data/models/page");
|
|
13
|
-
const { link,
|
|
14
|
-
const {
|
|
15
|
+
const { link, mkTable } = require("@saltcorn/markup");
|
|
16
|
+
const { div, a, p, i } = require("@saltcorn/markup/tags");
|
|
15
17
|
const Table = require("@saltcorn/data/models/table");
|
|
16
18
|
const { fetch_available_packs } = require("@saltcorn/admin-models/models/pack");
|
|
17
|
-
const { restore_backup } = require("../markup/admin");
|
|
19
|
+
// const { restore_backup } = require("../markup/admin");
|
|
18
20
|
const { get_latest_npm_version } = require("@saltcorn/data/models/config");
|
|
19
21
|
const packagejson = require("../package.json");
|
|
20
22
|
const Trigger = require("@saltcorn/data/models/trigger");
|
|
@@ -22,6 +24,7 @@ const { fileUploadForm } = require("../markup/forms");
|
|
|
22
24
|
const { get_base_url } = require("./utils.js");
|
|
23
25
|
|
|
24
26
|
/**
|
|
27
|
+
* Tables List
|
|
25
28
|
* @param {*} tables
|
|
26
29
|
* @param {object} req
|
|
27
30
|
* @returns {Table}
|
|
@@ -39,6 +42,7 @@ const tableTable = (tables, req) =>
|
|
|
39
42
|
);
|
|
40
43
|
|
|
41
44
|
/**
|
|
45
|
+
* Tables Card
|
|
42
46
|
* @param {*} tables
|
|
43
47
|
* @param {object} req
|
|
44
48
|
* @returns {object}
|
|
@@ -68,6 +72,7 @@ const tableCard = (tables, req) => ({
|
|
|
68
72
|
});
|
|
69
73
|
|
|
70
74
|
/**
|
|
75
|
+
* Views List
|
|
71
76
|
* @param {*} views
|
|
72
77
|
* @param {object} req
|
|
73
78
|
* @returns {Table}
|
|
@@ -89,6 +94,7 @@ const viewTable = (views, req) =>
|
|
|
89
94
|
);
|
|
90
95
|
|
|
91
96
|
/**
|
|
97
|
+
* Views Card
|
|
92
98
|
* @param {*} views
|
|
93
99
|
* @param {object} req
|
|
94
100
|
* @returns {object}
|
|
@@ -120,6 +126,7 @@ const viewCard = (views, req) => ({
|
|
|
120
126
|
});
|
|
121
127
|
|
|
122
128
|
/**
|
|
129
|
+
* Pages List
|
|
123
130
|
* @param {*} pages
|
|
124
131
|
* @param {object} req
|
|
125
132
|
* @returns {Table}
|
|
@@ -141,6 +148,7 @@ const pageTable = (pages, req) =>
|
|
|
141
148
|
);
|
|
142
149
|
|
|
143
150
|
/**
|
|
151
|
+
* Page Card
|
|
144
152
|
* @param {*} pages
|
|
145
153
|
* @param {object} req
|
|
146
154
|
* @returns {object}
|
|
@@ -173,13 +181,14 @@ const pageCard = (pages, req) => ({
|
|
|
173
181
|
});
|
|
174
182
|
|
|
175
183
|
/**
|
|
184
|
+
* Files Tab
|
|
176
185
|
* @param {object} req
|
|
177
186
|
* @returns {Promise<div>}
|
|
178
187
|
*/
|
|
179
188
|
const filesTab = async (req) => {
|
|
180
189
|
const files = await File.find({}, { orderBy: "filename", cached: true });
|
|
181
190
|
return div(
|
|
182
|
-
files.length
|
|
191
|
+
files.length === 0
|
|
183
192
|
? p(req.__("No files"))
|
|
184
193
|
: mkTable(
|
|
185
194
|
[
|
|
@@ -197,7 +206,10 @@ const filesTab = async (req) => {
|
|
|
197
206
|
};
|
|
198
207
|
|
|
199
208
|
/**
|
|
209
|
+
* Users Tab
|
|
200
210
|
* @param {object} req
|
|
211
|
+
* @param users
|
|
212
|
+
* @param roleMap
|
|
201
213
|
* @returns {Promise<div>}
|
|
202
214
|
*/
|
|
203
215
|
const usersTab = async (req, users, roleMap) => {
|
|
@@ -221,7 +233,9 @@ const usersTab = async (req, users, roleMap) => {
|
|
|
221
233
|
};
|
|
222
234
|
|
|
223
235
|
/**
|
|
236
|
+
* Actions (Triggers) Tab
|
|
224
237
|
* @param {object} req
|
|
238
|
+
* @param triggers
|
|
225
239
|
* @returns {Promise<div>}
|
|
226
240
|
*/
|
|
227
241
|
const actionsTab = async (req, triggers) => {
|
|
@@ -234,7 +248,7 @@ const actionsTab = async (req, triggers) => {
|
|
|
234
248
|
{ class: "mt-2 pe-2" },
|
|
235
249
|
i(req.__("Triggers run actions in response to events."))
|
|
236
250
|
),
|
|
237
|
-
triggers.length
|
|
251
|
+
triggers.length === 0
|
|
238
252
|
? p(req.__("No triggers"))
|
|
239
253
|
: mkTable(
|
|
240
254
|
[
|
|
@@ -260,6 +274,12 @@ const actionsTab = async (req, triggers) => {
|
|
|
260
274
|
)
|
|
261
275
|
);
|
|
262
276
|
};
|
|
277
|
+
/**
|
|
278
|
+
* Plugins and Packs Tab
|
|
279
|
+
* @param req
|
|
280
|
+
* @param packlist
|
|
281
|
+
* @returns {*}
|
|
282
|
+
*/
|
|
263
283
|
const packTab = (req, packlist) =>
|
|
264
284
|
div(
|
|
265
285
|
{ class: "pb-3 pt-2 pe-4" },
|
|
@@ -286,7 +306,11 @@ const packTab = (req, packlist) =>
|
|
|
286
306
|
req.__("Go to pack store »")
|
|
287
307
|
)
|
|
288
308
|
);
|
|
289
|
-
|
|
309
|
+
/**
|
|
310
|
+
* Help Card
|
|
311
|
+
* @param req
|
|
312
|
+
* @returns {*}
|
|
313
|
+
*/
|
|
290
314
|
const helpCard = (req) =>
|
|
291
315
|
div(
|
|
292
316
|
{ class: "pb-3 pt-2 pe-4" },
|
|
@@ -321,6 +345,7 @@ const helpCard = (req) =>
|
|
|
321
345
|
);
|
|
322
346
|
|
|
323
347
|
/**
|
|
348
|
+
* Wellcome page
|
|
324
349
|
* @param {object} req
|
|
325
350
|
* @returns {Promise<object>}
|
|
326
351
|
*/
|
|
@@ -393,6 +418,7 @@ const welcome_page = async (req) => {
|
|
|
393
418
|
};
|
|
394
419
|
|
|
395
420
|
/**
|
|
421
|
+
* No Views logged in
|
|
396
422
|
* @param {object} req
|
|
397
423
|
* @param {object} res
|
|
398
424
|
* @returns {Promise<void>}
|
|
@@ -423,6 +449,7 @@ const no_views_logged_in = async (req, res) => {
|
|
|
423
449
|
};
|
|
424
450
|
|
|
425
451
|
/**
|
|
452
|
+
* Get Config respounce
|
|
426
453
|
* @param {number} role_id
|
|
427
454
|
* @param {object} res
|
|
428
455
|
* @param {object} req
|
|
@@ -430,6 +457,7 @@ const no_views_logged_in = async (req, res) => {
|
|
|
430
457
|
*/
|
|
431
458
|
const get_config_response = async (role_id, res, req) => {
|
|
432
459
|
const modernCfg = getState().getConfig("home_page_by_role", false);
|
|
460
|
+
// predefined roles
|
|
433
461
|
const legacy_role = { 10: "public", 8: "user", 4: "staff", 1: "admin" }[
|
|
434
462
|
role_id
|
|
435
463
|
];
|
|
@@ -472,7 +500,7 @@ module.exports =
|
|
|
472
500
|
const hasUsers = await User.nonEmpty();
|
|
473
501
|
if (!hasUsers) {
|
|
474
502
|
res.redirect("/auth/create_first_user");
|
|
475
|
-
return;
|
|
503
|
+
// return;
|
|
476
504
|
} else res.redirect("/auth/login");
|
|
477
505
|
} else {
|
|
478
506
|
await no_views_logged_in(req, res);
|
package/routes/menu.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Menu Editor
|
|
2
3
|
* @category server
|
|
3
4
|
* @module routes/menu
|
|
4
5
|
* @subcategory routes
|
|
@@ -6,18 +7,18 @@
|
|
|
6
7
|
|
|
7
8
|
const Router = require("express-promise-router");
|
|
8
9
|
|
|
9
|
-
const Field = require("@saltcorn/data/models/field");
|
|
10
|
+
//const Field = require("@saltcorn/data/models/field");
|
|
10
11
|
const Form = require("@saltcorn/data/models/form");
|
|
11
|
-
const { isAdmin,
|
|
12
|
+
const { isAdmin, error_catcher } = require("./utils.js");
|
|
12
13
|
const { getState } = require("@saltcorn/data/db/state");
|
|
13
|
-
const File = require("@saltcorn/data/models/file");
|
|
14
|
+
//const File = require("@saltcorn/data/models/file");
|
|
14
15
|
const User = require("@saltcorn/data/models/user");
|
|
15
16
|
const View = require("@saltcorn/data/models/view");
|
|
16
17
|
const Page = require("@saltcorn/data/models/page");
|
|
17
18
|
const { save_menu_items } = require("@saltcorn/data/models/config");
|
|
18
19
|
const db = require("@saltcorn/data/db");
|
|
19
20
|
|
|
20
|
-
const {
|
|
21
|
+
const { renderForm } = require("@saltcorn/markup");
|
|
21
22
|
const { script, domReady, div, ul } = require("@saltcorn/markup/tags");
|
|
22
23
|
const { send_infoarch_page } = require("../markup/admin.js");
|
|
23
24
|
const Table = require("@saltcorn/data/models/table");
|
|
@@ -33,7 +34,7 @@ const router = new Router();
|
|
|
33
34
|
module.exports = router;
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
+
* Menu Form
|
|
37
38
|
* @param {object} req
|
|
38
39
|
* @returns {Promise<Form>}
|
|
39
40
|
*/
|
|
@@ -246,9 +247,11 @@ const menuForm = async (req) => {
|
|
|
246
247
|
//create -- new
|
|
247
248
|
|
|
248
249
|
/**
|
|
250
|
+
* Menu Editor Script
|
|
249
251
|
* @param {object[]} menu_items
|
|
250
252
|
* @returns {string}
|
|
251
253
|
*/
|
|
254
|
+
// todo move to file the content of menuEditorScript
|
|
252
255
|
const menuEditorScript = (menu_items) => `
|
|
253
256
|
var iconPickerOptions = {searchText: "Search icon...", labelHeader: "{0}/{1}"};
|
|
254
257
|
let lastState;
|
|
@@ -262,7 +265,7 @@ const menuEditorScript = (menu_items) => `
|
|
|
262
265
|
}
|
|
263
266
|
var sortableListOptions = {
|
|
264
267
|
placeholderCss: {'background-color': "#cccccc"},
|
|
265
|
-
onChange: ajax_save_menu
|
|
268
|
+
onChange: ajax_save_menu
|
|
266
269
|
};
|
|
267
270
|
editor = new MenuEditor('myEditor',
|
|
268
271
|
{
|
|
@@ -285,7 +288,7 @@ const menuEditorScript = (menu_items) => `
|
|
|
285
288
|
editor.update();
|
|
286
289
|
ajax_save_menu(true);
|
|
287
290
|
location.reload();
|
|
288
|
-
});
|
|
291
|
+
});
|
|
289
292
|
// Calling the add method
|
|
290
293
|
$('#btnAdd').click(function(){
|
|
291
294
|
editor.add();
|
|
@@ -360,6 +363,7 @@ router.get(
|
|
|
360
363
|
})
|
|
361
364
|
);
|
|
362
365
|
/**
|
|
366
|
+
* jQME to Menu
|
|
363
367
|
* @param {object[]} menu_items
|
|
364
368
|
* @returns {object[]}
|
|
365
369
|
*/
|
package/routes/tables.js
CHANGED
package/routes/tenant.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Tenant(s) Route
|
|
2
3
|
* @category server
|
|
3
4
|
* @module routes/tenant
|
|
4
5
|
* @subcategory routes
|
|
@@ -36,22 +37,23 @@ const {
|
|
|
36
37
|
code,
|
|
37
38
|
} = require("@saltcorn/markup/tags");
|
|
38
39
|
const db = require("@saltcorn/data/db");
|
|
39
|
-
const url = require("url");
|
|
40
|
+
//const url = require("url");
|
|
40
41
|
const { loadAllPlugins, loadAndSaveNewPlugin } = require("../load_plugins");
|
|
41
42
|
const { isAdmin, error_catcher } = require("./utils.js");
|
|
42
43
|
const User = require("@saltcorn/data/models/user");
|
|
43
44
|
const File = require("@saltcorn/data/models/file");
|
|
44
45
|
const {
|
|
45
46
|
send_infoarch_page,
|
|
46
|
-
send_admin_page,
|
|
47
|
+
//send_admin_page,
|
|
47
48
|
config_fields_form,
|
|
48
49
|
save_config_from_form,
|
|
49
50
|
} = require("../markup/admin.js");
|
|
50
51
|
const { getConfig } = require("@saltcorn/data/models/config");
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
// todo add button backup / restore for particular tenant (available in admin tenants screens)
|
|
53
|
+
//const {
|
|
54
|
+
// create_backup,
|
|
55
|
+
// restore,
|
|
56
|
+
//} = require("@saltcorn/admin-models/models/backup");
|
|
55
57
|
|
|
56
58
|
/**
|
|
57
59
|
* @type {object}
|
|
@@ -116,6 +118,7 @@ const is_ip_address = (hostname) => {
|
|
|
116
118
|
};
|
|
117
119
|
|
|
118
120
|
/**
|
|
121
|
+
* Create tenant screen runnning
|
|
119
122
|
* @name get/create
|
|
120
123
|
* @function
|
|
121
124
|
* @memberof module:routes/tenant~tenantRouter
|
|
@@ -146,6 +149,7 @@ router.get(
|
|
|
146
149
|
)
|
|
147
150
|
);
|
|
148
151
|
let create_tenant_warning = "";
|
|
152
|
+
// todo add custom create tenant warning message
|
|
149
153
|
if (getState().getConfig("create_tenant_warning"))
|
|
150
154
|
create_tenant_warning = div(
|
|
151
155
|
{
|
|
@@ -200,9 +204,8 @@ const getNewURL = (req, subdomain) => {
|
|
|
200
204
|
if (hosts.length > 1) ports = `:${hosts[1]}`;
|
|
201
205
|
}
|
|
202
206
|
const hostname = req.hostname;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
return newurl;
|
|
207
|
+
// return newurl
|
|
208
|
+
return `${req.protocol}://${subdomain}.${hostname}${ports}/`;
|
|
206
209
|
};
|
|
207
210
|
|
|
208
211
|
/**
|
|
@@ -307,7 +310,7 @@ router.post(
|
|
|
307
310
|
);
|
|
308
311
|
|
|
309
312
|
/**
|
|
310
|
-
* List tenants
|
|
313
|
+
* List tenants ( on /tenant/list)
|
|
311
314
|
* @name get/list
|
|
312
315
|
* @function
|
|
313
316
|
* @memberof module:routes/tenant~tenantRouter
|
package/routes/viewedit.js
CHANGED
|
@@ -586,11 +586,11 @@ router.get(
|
|
|
586
586
|
view.configuration && Object.keys(view.configuration).length > 0;
|
|
587
587
|
const wfres = await configFlow.run(
|
|
588
588
|
{
|
|
589
|
+
...view.configuration,
|
|
589
590
|
id: hasConfig ? view.id : undefined,
|
|
590
591
|
table_id: view.table_id,
|
|
591
592
|
exttable_name: view.exttable_name,
|
|
592
593
|
viewname: name,
|
|
593
|
-
...view.configuration,
|
|
594
594
|
},
|
|
595
595
|
req
|
|
596
596
|
);
|
|
@@ -775,3 +775,12 @@ router.post(
|
|
|
775
775
|
res.redirect("/viewedit");
|
|
776
776
|
})
|
|
777
777
|
);
|
|
778
|
+
|
|
779
|
+
router.post(
|
|
780
|
+
"/test/inserter",
|
|
781
|
+
isAdmin,
|
|
782
|
+
error_catcher(async (req, res) => {
|
|
783
|
+
const view = await View.create(req.body);
|
|
784
|
+
res.json({ view });
|
|
785
|
+
})
|
|
786
|
+
);
|
package/serve.js
CHANGED
|
@@ -43,6 +43,7 @@ const {
|
|
|
43
43
|
eachTenant,
|
|
44
44
|
getAllTenants,
|
|
45
45
|
} = require("@saltcorn/admin-models/models/tenant");
|
|
46
|
+
const { auto_backup_now } = require("@saltcorn/admin-models/models/backup");
|
|
46
47
|
|
|
47
48
|
// helpful https://gist.github.com/jpoehls/2232358
|
|
48
49
|
/**
|
|
@@ -135,7 +136,13 @@ const onMessageFromWorker =
|
|
|
135
136
|
//console.log("worker msg", typeof msg, msg);
|
|
136
137
|
if (msg === "Start" && !masterState.started) {
|
|
137
138
|
masterState.started = true;
|
|
138
|
-
runScheduler({
|
|
139
|
+
runScheduler({
|
|
140
|
+
port,
|
|
141
|
+
watchReaper,
|
|
142
|
+
disableScheduler,
|
|
143
|
+
eachTenant,
|
|
144
|
+
auto_backup_now,
|
|
145
|
+
});
|
|
139
146
|
require("./systemd")({ port });
|
|
140
147
|
return true;
|
|
141
148
|
} else if (msg === "RestartServer") {
|
|
@@ -261,6 +268,13 @@ module.exports =
|
|
|
261
268
|
});
|
|
262
269
|
} else {
|
|
263
270
|
await nonGreenlockWorkerSetup(appargs, port);
|
|
271
|
+
runScheduler({
|
|
272
|
+
port,
|
|
273
|
+
watchReaper,
|
|
274
|
+
disableScheduler,
|
|
275
|
+
eachTenant,
|
|
276
|
+
auto_backup_now,
|
|
277
|
+
});
|
|
264
278
|
}
|
|
265
279
|
Trigger.emitEvent("Startup");
|
|
266
280
|
} else {
|
package/tests/admin.test.js
CHANGED
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
respondJsonWith,
|
|
13
13
|
} = require("../auth/testhelp");
|
|
14
14
|
const db = require("@saltcorn/data/db");
|
|
15
|
+
const { sleep } = require("@saltcorn/data/tests/mocks");
|
|
15
16
|
const fs = require("fs").promises;
|
|
16
17
|
const File = require("@saltcorn/data/models/file");
|
|
17
18
|
const User = require("@saltcorn/data/models/user");
|
|
@@ -30,7 +31,12 @@ beforeAll(async () => {
|
|
|
30
31
|
4
|
|
31
32
|
);
|
|
32
33
|
});
|
|
33
|
-
|
|
34
|
+
|
|
35
|
+
afterAll(async () => {
|
|
36
|
+
await sleep(200);
|
|
37
|
+
db.close();
|
|
38
|
+
});
|
|
39
|
+
|
|
34
40
|
const adminPageContains = (specs) =>
|
|
35
41
|
it("adminPageContains " + specs.map((s) => s[1]).join(","), async () => {
|
|
36
42
|
const app = await getApp({ disableCsrf: true });
|
|
@@ -456,6 +462,71 @@ describe("actions", () => {
|
|
|
456
462
|
.expect(toRedirect("/actions/"));
|
|
457
463
|
});
|
|
458
464
|
});
|
|
465
|
+
describe("localizer", () => {
|
|
466
|
+
itShouldRedirectUnauthToLogin("/site-structure/localizer");
|
|
467
|
+
itShouldRedirectUnauthToLogin("/site-structure/localizer/add-lang");
|
|
468
|
+
it("redirects site struct to menu", async () => {
|
|
469
|
+
const app = await getApp({ disableCsrf: true });
|
|
470
|
+
const loginCookie = await getAdminLoginCookie();
|
|
471
|
+
await request(app)
|
|
472
|
+
.get("/site-structure")
|
|
473
|
+
.set("Cookie", loginCookie)
|
|
474
|
+
.expect(toRedirect("/menu"));
|
|
475
|
+
});
|
|
476
|
+
it("shows languages", async () => {
|
|
477
|
+
const app = await getApp({ disableCsrf: true });
|
|
478
|
+
const loginCookie = await getAdminLoginCookie();
|
|
479
|
+
await request(app)
|
|
480
|
+
.get("/site-structure/localizer")
|
|
481
|
+
.set("Cookie", loginCookie)
|
|
482
|
+
.expect(toInclude("Languages"));
|
|
483
|
+
});
|
|
484
|
+
it("shows add language form", async () => {
|
|
485
|
+
const app = await getApp({ disableCsrf: true });
|
|
486
|
+
const loginCookie = await getAdminLoginCookie();
|
|
487
|
+
await request(app)
|
|
488
|
+
.get("/site-structure/localizer/add-lang")
|
|
489
|
+
.set("Cookie", loginCookie)
|
|
490
|
+
.expect(toInclude("Locale identifier short code"));
|
|
491
|
+
});
|
|
492
|
+
it("add language", async () => {
|
|
493
|
+
const app = await getApp({ disableCsrf: true });
|
|
494
|
+
const loginCookie = await getAdminLoginCookie();
|
|
495
|
+
await request(app)
|
|
496
|
+
.post("/site-structure/localizer/save-lang")
|
|
497
|
+
.set("Cookie", loginCookie)
|
|
498
|
+
.send("name=dansk")
|
|
499
|
+
.send("locale=da")
|
|
500
|
+
.expect(toRedirect("/site-structure/localizer/edit/da"));
|
|
501
|
+
});
|
|
502
|
+
it("shows new in languages", async () => {
|
|
503
|
+
const app = await getApp({ disableCsrf: true });
|
|
504
|
+
const loginCookie = await getAdminLoginCookie();
|
|
505
|
+
await request(app)
|
|
506
|
+
.get("/site-structure/localizer")
|
|
507
|
+
.set("Cookie", loginCookie)
|
|
508
|
+
.expect(toInclude("dansk"));
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
it("shows edit language form", async () => {
|
|
512
|
+
const app = await getApp({ disableCsrf: true });
|
|
513
|
+
const loginCookie = await getAdminLoginCookie();
|
|
514
|
+
await request(app)
|
|
515
|
+
.get("/site-structure/localizer/edit/da")
|
|
516
|
+
.set("Cookie", loginCookie)
|
|
517
|
+
.expect(toInclude("Hello world"));
|
|
518
|
+
});
|
|
519
|
+
it("set string language", async () => {
|
|
520
|
+
const app = await getApp({ disableCsrf: true });
|
|
521
|
+
const loginCookie = await getAdminLoginCookie();
|
|
522
|
+
await request(app)
|
|
523
|
+
.post("/site-structure/localizer/save-string/da/Hello%20world")
|
|
524
|
+
.set("Cookie", loginCookie)
|
|
525
|
+
.send("value=Hej+verden")
|
|
526
|
+
.expect(toRedirect("/site-structure/localizer/edit/da"));
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
|
|
459
530
|
/**
|
|
460
531
|
* Pages tests
|
|
461
532
|
*/
|
package/tests/clientjs.test.js
CHANGED
package/tests/viewedit.test.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
toInclude,
|
|
9
9
|
toNotInclude,
|
|
10
10
|
resetToFixtures,
|
|
11
|
+
succeedJsonWith,
|
|
11
12
|
} = require("../auth/testhelp");
|
|
12
13
|
const db = require("@saltcorn/data/db");
|
|
13
14
|
const View = require("@saltcorn/data/models/view");
|
|
@@ -371,3 +372,96 @@ describe("viewedit new Show", () => {
|
|
|
371
372
|
.expect(toRedirect("/viewedit"));
|
|
372
373
|
});
|
|
373
374
|
});
|
|
375
|
+
describe("Library", () => {
|
|
376
|
+
it("should save new from builder", async () => {
|
|
377
|
+
const loginCookie = await getAdminLoginCookie();
|
|
378
|
+
const app = await getApp({ disableCsrf: true });
|
|
379
|
+
await request(app)
|
|
380
|
+
.post("/library/savefrombuilder/")
|
|
381
|
+
.set("Cookie", loginCookie)
|
|
382
|
+
.send({
|
|
383
|
+
layout: {
|
|
384
|
+
columns: [],
|
|
385
|
+
layout: {
|
|
386
|
+
type: "card",
|
|
387
|
+
contents: {
|
|
388
|
+
above: [
|
|
389
|
+
null,
|
|
390
|
+
{
|
|
391
|
+
besides: [
|
|
392
|
+
{
|
|
393
|
+
above: [
|
|
394
|
+
null,
|
|
395
|
+
{
|
|
396
|
+
type: "blank",
|
|
397
|
+
contents: "Hello world",
|
|
398
|
+
block: false,
|
|
399
|
+
inline: false,
|
|
400
|
+
textStyle: "",
|
|
401
|
+
isFormula: {},
|
|
402
|
+
labelFor: "",
|
|
403
|
+
style: {},
|
|
404
|
+
font: "",
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
above: [
|
|
410
|
+
null,
|
|
411
|
+
{
|
|
412
|
+
type: "blank",
|
|
413
|
+
contents: "Bye bye",
|
|
414
|
+
block: false,
|
|
415
|
+
inline: false,
|
|
416
|
+
textStyle: "",
|
|
417
|
+
isFormula: {},
|
|
418
|
+
labelFor: "",
|
|
419
|
+
style: {},
|
|
420
|
+
font: "",
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
},
|
|
424
|
+
],
|
|
425
|
+
breakpoints: ["", ""],
|
|
426
|
+
style: {},
|
|
427
|
+
widths: [6, 6],
|
|
428
|
+
},
|
|
429
|
+
],
|
|
430
|
+
},
|
|
431
|
+
title: "header",
|
|
432
|
+
style: {},
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
icon: "far fa-angry",
|
|
436
|
+
name: "ShinyCard",
|
|
437
|
+
})
|
|
438
|
+
.set("Content-Type", "application/json")
|
|
439
|
+
.set("Accept", "application/json")
|
|
440
|
+
.expect(succeedJsonWith(() => true));
|
|
441
|
+
});
|
|
442
|
+
it("shows library with item", async () => {
|
|
443
|
+
const app = await getApp({ disableCsrf: true });
|
|
444
|
+
const loginCookie = await getAdminLoginCookie();
|
|
445
|
+
await request(app)
|
|
446
|
+
.get("/library/list")
|
|
447
|
+
.set("Cookie", loginCookie)
|
|
448
|
+
.expect(toInclude("ShinyCard"));
|
|
449
|
+
});
|
|
450
|
+
it("deletes in library", async () => {
|
|
451
|
+
const app = await getApp({ disableCsrf: true });
|
|
452
|
+
const loginCookie = await getAdminLoginCookie();
|
|
453
|
+
await request(app)
|
|
454
|
+
.post("/library/delete/1")
|
|
455
|
+
.set("Cookie", loginCookie)
|
|
456
|
+
.expect(toRedirect("/library/list"));
|
|
457
|
+
});
|
|
458
|
+
it("shows empty library", async () => {
|
|
459
|
+
const app = await getApp({ disableCsrf: true });
|
|
460
|
+
const loginCookie = await getAdminLoginCookie();
|
|
461
|
+
await request(app)
|
|
462
|
+
.get("/library/list")
|
|
463
|
+
.set("Cookie", loginCookie)
|
|
464
|
+
.expect(toInclude("Library"))
|
|
465
|
+
.expect(toNotInclude("ShinyCard"))
|
|
466
|
+
});
|
|
467
|
+
});
|