@saltcorn/server 0.7.4-beta.0 → 0.7.4-beta.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/locales/en.json +19 -1
- package/locales/it.json +2 -1
- package/locales/ru.json +42 -6
- package/markup/plugin-store.js +5 -5
- package/package.json +7 -7
- package/public/saltcorn-builder.css +75 -0
- package/public/saltcorn.css +4 -0
- package/routes/admin.js +131 -108
- package/routes/fields.js +11 -13
- package/routes/homepage.js +60 -60
- package/routes/menu.js +65 -4
- package/routes/packs.js +4 -4
- package/routes/plugins.js +116 -118
- package/routes/settings.js +3 -3
- package/routes/tables.js +187 -187
- package/routes/tenant.js +27 -27
- package/routes/viewedit.js +68 -68
- package/tests/admin.test.js +1 -1
- package/tests/plugins.test.js +1 -1
- package/tests/viewedit.test.js +1 -1
- package/wrapper.js +57 -55
package/routes/admin.js
CHANGED
|
@@ -154,7 +154,7 @@ const email_form = async (req) => {
|
|
|
154
154
|
return form;
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
const app_files_table = (
|
|
157
|
+
const app_files_table = (files, req) =>
|
|
158
158
|
mkTable(
|
|
159
159
|
[
|
|
160
160
|
{
|
|
@@ -168,7 +168,7 @@ const app_files_table = (file, req) =>
|
|
|
168
168
|
key: (r) => link(`/files/download/${r.id}`, req.__("Download")),
|
|
169
169
|
},
|
|
170
170
|
],
|
|
171
|
-
|
|
171
|
+
files
|
|
172
172
|
);
|
|
173
173
|
|
|
174
174
|
/**
|
|
@@ -365,7 +365,7 @@ router.get(
|
|
|
365
365
|
post_btn(
|
|
366
366
|
"/admin/backup",
|
|
367
367
|
i({ class: "fas fa-download me-2" }) +
|
|
368
|
-
|
|
368
|
+
req.__("Download a backup"),
|
|
369
369
|
req.csrfToken(),
|
|
370
370
|
{
|
|
371
371
|
btnClass: "btn-outline-primary",
|
|
@@ -384,21 +384,21 @@ router.get(
|
|
|
384
384
|
},
|
|
385
385
|
isRoot
|
|
386
386
|
? {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
),
|
|
395
|
-
script(
|
|
396
|
-
domReady(
|
|
397
|
-
`$('#btnBackupNow').prop('disabled', $('#inputauto_backup_frequency').val()==='Never');`
|
|
398
|
-
)
|
|
399
|
-
)
|
|
387
|
+
type: "card",
|
|
388
|
+
title: req.__("Automated backup"),
|
|
389
|
+
contents: div(
|
|
390
|
+
renderForm(backupForm, req.csrfToken()),
|
|
391
|
+
a(
|
|
392
|
+
{ href: "/admin/auto-backup-list" },
|
|
393
|
+
"Restore/download automated backups »"
|
|
400
394
|
),
|
|
401
|
-
|
|
395
|
+
script(
|
|
396
|
+
domReady(
|
|
397
|
+
`$('#btnBackupNow').prop('disabled', $('#inputauto_backup_frequency').val()==='Never');`
|
|
398
|
+
)
|
|
399
|
+
)
|
|
400
|
+
),
|
|
401
|
+
}
|
|
402
402
|
: { type: "blank", contents: "" },
|
|
403
403
|
{
|
|
404
404
|
type: "card",
|
|
@@ -831,47 +831,47 @@ router.get(
|
|
|
831
831
|
th(req.__("Saltcorn version")),
|
|
832
832
|
td(
|
|
833
833
|
packagejson.version +
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
834
|
+
(isRoot && can_update
|
|
835
|
+
? post_btn(
|
|
836
|
+
"/admin/upgrade",
|
|
837
|
+
req.__("Upgrade"),
|
|
838
|
+
req.csrfToken(),
|
|
839
|
+
{
|
|
840
|
+
btnClass: "btn-primary btn-sm",
|
|
841
|
+
formClass: "d-inline",
|
|
842
|
+
}
|
|
843
|
+
)
|
|
844
|
+
: isRoot && is_latest
|
|
845
845
|
? span(
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
846
|
+
{ class: "badge bg-primary ms-2" },
|
|
847
|
+
req.__("Latest")
|
|
848
|
+
) +
|
|
849
|
+
post_btn(
|
|
850
|
+
"/admin/check-for-upgrade",
|
|
851
|
+
req.__("Check for updates"),
|
|
852
|
+
req.csrfToken(),
|
|
853
|
+
{
|
|
854
|
+
btnClass: "btn-primary btn-sm px-1 py-0",
|
|
855
|
+
formClass: "d-inline",
|
|
856
|
+
}
|
|
857
|
+
)
|
|
858
858
|
: "")
|
|
859
859
|
)
|
|
860
860
|
),
|
|
861
861
|
git_commit &&
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
)
|
|
862
|
+
tr(
|
|
863
|
+
th(req.__("git commit")),
|
|
864
|
+
td(
|
|
865
|
+
a(
|
|
866
|
+
{
|
|
867
|
+
href:
|
|
868
|
+
"https://github.com/saltcorn/saltcorn/commit/" +
|
|
869
|
+
git_commit,
|
|
870
|
+
},
|
|
871
|
+
git_commit.substring(0, 6)
|
|
873
872
|
)
|
|
874
|
-
)
|
|
873
|
+
)
|
|
874
|
+
),
|
|
875
875
|
tr(th(req.__("Node.js version")), td(process.version)),
|
|
876
876
|
tr(
|
|
877
877
|
th(req.__("Database")),
|
|
@@ -981,7 +981,7 @@ router.post(
|
|
|
981
981
|
res.attachment(fileName);
|
|
982
982
|
const file = fs.createReadStream(fileName);
|
|
983
983
|
file.on("end", function () {
|
|
984
|
-
fs.unlink(fileName, function () {});
|
|
984
|
+
fs.unlink(fileName, function () { });
|
|
985
985
|
});
|
|
986
986
|
file.pipe(res);
|
|
987
987
|
})
|
|
@@ -1004,7 +1004,7 @@ router.post(
|
|
|
1004
1004
|
);
|
|
1005
1005
|
if (err) req.flash("error", err);
|
|
1006
1006
|
else req.flash("success", req.__("Successfully restored backup"));
|
|
1007
|
-
fs.unlink(newPath, function () {});
|
|
1007
|
+
fs.unlink(newPath, function () { });
|
|
1008
1008
|
res.redirect(`/admin`);
|
|
1009
1009
|
})
|
|
1010
1010
|
);
|
|
@@ -1079,7 +1079,7 @@ const clearAllForm = (req) =>
|
|
|
1079
1079
|
{
|
|
1080
1080
|
type: "Bool",
|
|
1081
1081
|
name: "plugins",
|
|
1082
|
-
label: req.__("
|
|
1082
|
+
label: req.__("Modules"),
|
|
1083
1083
|
default: true,
|
|
1084
1084
|
},
|
|
1085
1085
|
],
|
|
@@ -1149,8 +1149,8 @@ router.post(
|
|
|
1149
1149
|
req.__(
|
|
1150
1150
|
"LetsEncrypt SSL enabled. Restart for changes to take effect."
|
|
1151
1151
|
) +
|
|
1152
|
-
|
|
1153
|
-
|
|
1152
|
+
" " +
|
|
1153
|
+
a({ href: "/admin/system" }, req.__("Restart here"))
|
|
1154
1154
|
);
|
|
1155
1155
|
res.redirect("/useradmin/ssl");
|
|
1156
1156
|
} catch (e) {
|
|
@@ -1221,13 +1221,13 @@ router.get(
|
|
|
1221
1221
|
contents: div(
|
|
1222
1222
|
pass
|
|
1223
1223
|
? div(
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
)
|
|
1224
|
+
{ class: "alert alert-success", role: "alert" },
|
|
1225
|
+
i({ class: "fas fa-check-circle fa-lg me-2" }),
|
|
1226
|
+
h5(
|
|
1227
|
+
{ class: "d-inline" },
|
|
1228
|
+
req.__("No errors detected during configuration check")
|
|
1230
1229
|
)
|
|
1230
|
+
)
|
|
1231
1231
|
: errors.map(mkError)
|
|
1232
1232
|
),
|
|
1233
1233
|
},
|
|
@@ -1241,32 +1241,49 @@ router.get(
|
|
|
1241
1241
|
})
|
|
1242
1242
|
);
|
|
1243
1243
|
|
|
1244
|
-
const
|
|
1245
|
-
|
|
1246
|
-
activeTab
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
function showEntrySelect(type) {
|
|
1257
|
-
const viewNavLin = $("#viewNavLinkID");
|
|
1258
|
-
const pageNavLink = $("#pageNavLinkID");
|
|
1259
|
-
const viewInp = $("#viewInputID");
|
|
1260
|
-
const pageInp = $("#pageInputID");
|
|
1261
|
-
if (type === "page") {
|
|
1262
|
-
swapEntryInputs(pageNavLink, pageInp, viewNavLin, viewInp);
|
|
1244
|
+
const buildDialogScript = () => {
|
|
1245
|
+
return `<script>
|
|
1246
|
+
function swapEntryInputs(activeTab, activeInput, disabledTab, disabledInput) {
|
|
1247
|
+
activeTab.addClass("active");
|
|
1248
|
+
activeInput.removeClass("d-none");
|
|
1249
|
+
activeInput.addClass("d-block");
|
|
1250
|
+
activeInput.attr("name", "entryPoint");
|
|
1251
|
+
disabledTab.removeClass("active");
|
|
1252
|
+
disabledInput.removeClass("d-block");
|
|
1253
|
+
disabledInput.addClass("d-none");
|
|
1254
|
+
disabledInput.removeAttr("name");
|
|
1263
1255
|
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1256
|
+
|
|
1257
|
+
function showEntrySelect(type) {
|
|
1258
|
+
const viewNavLin = $("#viewNavLinkID");
|
|
1259
|
+
const pageNavLink = $("#pageNavLinkID");
|
|
1260
|
+
const viewInp = $("#viewInputID");
|
|
1261
|
+
const pageInp = $("#pageInputID");
|
|
1262
|
+
if (type === "page") {
|
|
1263
|
+
swapEntryInputs(pageNavLink, pageInp, viewNavLin, viewInp);
|
|
1264
|
+
}
|
|
1265
|
+
else if (type === "view") {
|
|
1266
|
+
swapEntryInputs(viewNavLin, viewInp, pageNavLink, pageInp);
|
|
1267
|
+
}
|
|
1268
|
+
$("#entryPointTypeID").attr("value", type);
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
function handleMessages() {
|
|
1272
|
+
notifyAlert("This is still under development and might run longer.")
|
|
1273
|
+
${
|
|
1274
|
+
getState().getConfig("apple_team_id") &&
|
|
1275
|
+
getState().getConfig("apple_team_id") !== "null"
|
|
1276
|
+
? ""
|
|
1277
|
+
: `
|
|
1278
|
+
if ($("#iOSCheckboxId")[0].checked) {
|
|
1279
|
+
notifyAlert(
|
|
1280
|
+
"No 'Apple Team ID' is configured, I will try to build a project for the iOS simulator."
|
|
1281
|
+
);
|
|
1282
|
+
}`
|
|
1283
|
+
}
|
|
1266
1284
|
}
|
|
1267
|
-
|
|
1268
|
-
}
|
|
1269
|
-
</script>`;
|
|
1285
|
+
</script>`;
|
|
1286
|
+
};
|
|
1270
1287
|
|
|
1271
1288
|
router.get(
|
|
1272
1289
|
"/build-mobile-app",
|
|
@@ -1274,8 +1291,6 @@ router.get(
|
|
|
1274
1291
|
error_catcher(async (req, res) => {
|
|
1275
1292
|
const views = await View.find();
|
|
1276
1293
|
const pages = await Page.find();
|
|
1277
|
-
const execBuildMsg =
|
|
1278
|
-
"This is still under development and might run longer.";
|
|
1279
1294
|
|
|
1280
1295
|
send_admin_page({
|
|
1281
1296
|
res,
|
|
@@ -1283,7 +1298,7 @@ router.get(
|
|
|
1283
1298
|
active_sub: "Mobile app",
|
|
1284
1299
|
headers: [
|
|
1285
1300
|
{
|
|
1286
|
-
headerTag:
|
|
1301
|
+
headerTag: buildDialogScript(),
|
|
1287
1302
|
},
|
|
1288
1303
|
],
|
|
1289
1304
|
contents: {
|
|
@@ -1313,13 +1328,13 @@ router.get(
|
|
|
1313
1328
|
{ class: "container ps-2" },
|
|
1314
1329
|
div(
|
|
1315
1330
|
{ class: "row pb-2" },
|
|
1316
|
-
div({ class: "col-sm-4 fw-bold" }, "Entry point"),
|
|
1317
|
-
div({ class: "col-sm-4 fw-bold" }, "Platform"),
|
|
1331
|
+
div({ class: "col-sm-4 fw-bold" }, req.__("Entry point")),
|
|
1332
|
+
div({ class: "col-sm-4 fw-bold" }, req.__("Platform")),
|
|
1318
1333
|
div(
|
|
1319
1334
|
{
|
|
1320
1335
|
class: "col-sm-1 fw-bold d-flex justify-content-center",
|
|
1321
1336
|
},
|
|
1322
|
-
"docker"
|
|
1337
|
+
req.__("docker")
|
|
1323
1338
|
)
|
|
1324
1339
|
),
|
|
1325
1340
|
div(
|
|
@@ -1336,7 +1351,7 @@ router.get(
|
|
|
1336
1351
|
},
|
|
1337
1352
|
div(
|
|
1338
1353
|
{ class: "nav-link active", id: "viewNavLinkID" },
|
|
1339
|
-
"View"
|
|
1354
|
+
req.__("View")
|
|
1340
1355
|
)
|
|
1341
1356
|
),
|
|
1342
1357
|
li(
|
|
@@ -1346,7 +1361,7 @@ router.get(
|
|
|
1346
1361
|
},
|
|
1347
1362
|
div(
|
|
1348
1363
|
{ class: "nav-link", id: "pageNavLinkID" },
|
|
1349
|
-
"Page"
|
|
1364
|
+
req.__("Page")
|
|
1350
1365
|
)
|
|
1351
1366
|
)
|
|
1352
1367
|
),
|
|
@@ -1383,7 +1398,7 @@ router.get(
|
|
|
1383
1398
|
{ class: "container ps-0" },
|
|
1384
1399
|
div(
|
|
1385
1400
|
{ class: "row" },
|
|
1386
|
-
div({ class: "col-sm-8" }, "android"),
|
|
1401
|
+
div({ class: "col-sm-8" }, req.__("android")),
|
|
1387
1402
|
div(
|
|
1388
1403
|
{ class: "col-sm" },
|
|
1389
1404
|
input({
|
|
@@ -1396,7 +1411,7 @@ router.get(
|
|
|
1396
1411
|
),
|
|
1397
1412
|
div(
|
|
1398
1413
|
{ class: "row" },
|
|
1399
|
-
div({ class: "col-sm-8" }, "iOS"),
|
|
1414
|
+
div({ class: "col-sm-8" }, req.__("iOS")),
|
|
1400
1415
|
div(
|
|
1401
1416
|
{ class: "col-sm" },
|
|
1402
1417
|
input({
|
|
@@ -1428,7 +1443,7 @@ router.get(
|
|
|
1428
1443
|
for: "appNameInputId",
|
|
1429
1444
|
class: "form-label fw-bold",
|
|
1430
1445
|
},
|
|
1431
|
-
"App file"
|
|
1446
|
+
req.__("App file")
|
|
1432
1447
|
),
|
|
1433
1448
|
input({
|
|
1434
1449
|
type: "text",
|
|
@@ -1448,7 +1463,7 @@ router.get(
|
|
|
1448
1463
|
for: "serverURLInputId",
|
|
1449
1464
|
class: "form-label fw-bold",
|
|
1450
1465
|
},
|
|
1451
|
-
"Server URL"
|
|
1466
|
+
req.__("Server URL")
|
|
1452
1467
|
),
|
|
1453
1468
|
input({
|
|
1454
1469
|
type: "text",
|
|
@@ -1463,12 +1478,12 @@ router.get(
|
|
|
1463
1478
|
button(
|
|
1464
1479
|
{
|
|
1465
1480
|
type: "submit",
|
|
1466
|
-
onClick: `
|
|
1481
|
+
onClick: `handleMessages(); press_store_button(this);`,
|
|
1467
1482
|
class: "btn btn-warning",
|
|
1468
1483
|
},
|
|
1469
1484
|
i({ class: "fas fa-hammer pe-2" }),
|
|
1470
1485
|
|
|
1471
|
-
"Build mobile app"
|
|
1486
|
+
req.__("Build mobile app")
|
|
1472
1487
|
)
|
|
1473
1488
|
)
|
|
1474
1489
|
),
|
|
@@ -1503,7 +1518,6 @@ router.post(
|
|
|
1503
1518
|
req.flash("error", req.__("Only the android build supports docker."));
|
|
1504
1519
|
return res.redirect("/admin/build-mobile-app");
|
|
1505
1520
|
}
|
|
1506
|
-
if (appFile && !appFile.endsWith(".apk")) appFile = `${appFile}.apk`;
|
|
1507
1521
|
if (!serverURL || serverURL.length == 0) {
|
|
1508
1522
|
serverURL = getState().getConfig("base_url") || "";
|
|
1509
1523
|
}
|
|
@@ -1525,7 +1539,13 @@ router.post(
|
|
|
1525
1539
|
];
|
|
1526
1540
|
if (useDocker) spawnParams.push("-d");
|
|
1527
1541
|
if (androidPlatform) spawnParams.push("-p", "android");
|
|
1528
|
-
if (iOSPlatform)
|
|
1542
|
+
if (iOSPlatform) {
|
|
1543
|
+
spawnParams.push("-p", "ios");
|
|
1544
|
+
const teamId = getState().getConfig("apple_team_id");
|
|
1545
|
+
if (!teamId || teamId === "null") {
|
|
1546
|
+
spawnParams.push("--buildForEmulator");
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1529
1549
|
if (appFile) spawnParams.push("-a", appFile);
|
|
1530
1550
|
if (serverURL) spawnParams.push("-s", serverURL);
|
|
1531
1551
|
const child = spawn("saltcorn", spawnParams, {
|
|
@@ -1543,10 +1563,13 @@ router.post(
|
|
|
1543
1563
|
});
|
|
1544
1564
|
child.on("exit", async function (exitCode, signal) {
|
|
1545
1565
|
if (exitCode === 0) {
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1566
|
+
const files = await Promise.all(
|
|
1567
|
+
fs
|
|
1568
|
+
.readdirSync(appOut)
|
|
1569
|
+
.map(
|
|
1570
|
+
async (outFile) =>
|
|
1571
|
+
await File.from_existing_file(appOut, outFile, req.user.id)
|
|
1572
|
+
)
|
|
1550
1573
|
);
|
|
1551
1574
|
res.sendWrap(req.__(`Admin`), {
|
|
1552
1575
|
above: [
|
|
@@ -1555,7 +1578,7 @@ router.post(
|
|
|
1555
1578
|
title: req.__("Build Result"),
|
|
1556
1579
|
contents: div("The build was successfully"),
|
|
1557
1580
|
},
|
|
1558
|
-
app_files_table(
|
|
1581
|
+
files.length > 0 ? app_files_table(files, req) : "",
|
|
1559
1582
|
],
|
|
1560
1583
|
});
|
|
1561
1584
|
} else
|
package/routes/fields.js
CHANGED
|
@@ -348,13 +348,12 @@ const fieldFlow = (req) =>
|
|
|
348
348
|
// todo sublabel
|
|
349
349
|
input_type: "custom_html",
|
|
350
350
|
attributes: {
|
|
351
|
-
html: `<button type="button" id="test_formula_btn" onclick="test_formula('${
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
)}</button>
|
|
351
|
+
html: `<button type="button" id="test_formula_btn" onclick="test_formula('${table.name
|
|
352
|
+
}', ${JSON.stringify(
|
|
353
|
+
context.stored
|
|
354
|
+
)})" class="btn btn-outline-secondary">${req.__(
|
|
355
|
+
"Test"
|
|
356
|
+
)}</button>
|
|
358
357
|
<div id="test_formula_output"></div>`,
|
|
359
358
|
},
|
|
360
359
|
}),
|
|
@@ -633,8 +632,7 @@ router.post(
|
|
|
633
632
|
result = f(rows[0]);
|
|
634
633
|
}
|
|
635
634
|
res.send(
|
|
636
|
-
`Result of running on row with id=${
|
|
637
|
-
rows[0].id
|
|
635
|
+
`Result of running on row with id=${rows[0].id
|
|
638
636
|
} is: <pre>${JSON.stringify(result)}</pre>`
|
|
639
637
|
);
|
|
640
638
|
} catch (e) {
|
|
@@ -788,22 +786,22 @@ router.post(
|
|
|
788
786
|
field.type === "Key"
|
|
789
787
|
? getState().keyFieldviews
|
|
790
788
|
: field.type === "File"
|
|
791
|
-
|
|
792
|
-
|
|
789
|
+
? getState().fileviews
|
|
790
|
+
: field.type.fieldviews;
|
|
793
791
|
if (!field.type || !fieldviews) {
|
|
794
792
|
res.send("");
|
|
795
793
|
return;
|
|
796
794
|
}
|
|
797
795
|
const fv = fieldviews[fieldview];
|
|
798
796
|
if (!fv && field.type === "Key" && fieldview === "select")
|
|
799
|
-
res.send("
|
|
797
|
+
res.send(`<input readonly class="form-control form-select"></input>`);
|
|
800
798
|
else if (!fv) res.send("");
|
|
801
799
|
else if (fv.isEdit || fv.isFilter)
|
|
802
800
|
res.send(
|
|
803
801
|
fv.run(
|
|
804
802
|
field.name,
|
|
805
803
|
undefined,
|
|
806
|
-
{
|
|
804
|
+
{ readonly: true, ...configuration, ...(field.attributes || {}) },
|
|
807
805
|
"",
|
|
808
806
|
false,
|
|
809
807
|
field
|
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));
|