@saltcorn/server 0.7.0-beta.0 → 0.7.0-beta.3
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 +5 -1
- package/markup/admin.js +9 -2
- package/package.json +8 -8
- package/public/saltcorn-builder.css +3 -0
- package/public/saltcorn.js +30 -5
- package/routes/api.js +42 -0
- package/routes/homepage.js +1 -1
- package/routes/plugins.js +4 -1
package/locales/en.json
CHANGED
|
@@ -867,5 +867,9 @@
|
|
|
867
867
|
"Save before going back": "Save before going back",
|
|
868
868
|
"Reload after going back": "Reload after going back",
|
|
869
869
|
"2FA policy": "2FA policy",
|
|
870
|
-
"Steps to go back": "Steps to go back"
|
|
870
|
+
"Steps to go back": "Steps to go back",
|
|
871
|
+
"Place in dropdown": "Place in dropdown",
|
|
872
|
+
"Hide null columns": "Hide null columns",
|
|
873
|
+
"Do not display a column if it contains entirely missing values": "Do not display a column if it contains entirely missing values",
|
|
874
|
+
"Show a warning to users creating a tenant disclaiming warrenty of availability or security": "Show a warning to users creating a tenant disclaiming warrenty of availability or security"
|
|
871
875
|
}
|
package/markup/admin.js
CHANGED
|
@@ -46,14 +46,21 @@ const restore_backup = (csrf, inner, action = `/admin/restore`) =>
|
|
|
46
46
|
encType: "multipart/form-data",
|
|
47
47
|
},
|
|
48
48
|
input({ type: "hidden", name: "_csrf", value: csrf }),
|
|
49
|
-
label(
|
|
49
|
+
label(
|
|
50
|
+
{
|
|
51
|
+
class: "btn-link",
|
|
52
|
+
for: "upload_to_restore",
|
|
53
|
+
style: { cursor: "pointer" },
|
|
54
|
+
},
|
|
55
|
+
inner
|
|
56
|
+
),
|
|
50
57
|
input({
|
|
51
58
|
id: "upload_to_restore",
|
|
52
59
|
class: "d-none",
|
|
53
60
|
name: "file",
|
|
54
61
|
type: "file",
|
|
55
62
|
accept: "application/zip,.zip",
|
|
56
|
-
onchange: "this.form.submit();",
|
|
63
|
+
onchange: "notifyAlert('Restoring backup...', true);this.form.submit();",
|
|
57
64
|
})
|
|
58
65
|
);
|
|
59
66
|
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.7.0-beta.
|
|
3
|
+
"version": "0.7.0-beta.3",
|
|
4
4
|
"description": "Server app for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@saltcorn/base-plugin": "0.7.0-beta.
|
|
10
|
-
"@saltcorn/builder": "0.7.0-beta.
|
|
11
|
-
"@saltcorn/data": "0.7.0-beta.
|
|
12
|
-
"@saltcorn/admin-models": "0.7.0-beta.
|
|
13
|
-
"@saltcorn/markup": "0.7.0-beta.
|
|
14
|
-
"@saltcorn/sbadmin2": "0.7.0-beta.
|
|
9
|
+
"@saltcorn/base-plugin": "0.7.0-beta.3",
|
|
10
|
+
"@saltcorn/builder": "0.7.0-beta.3",
|
|
11
|
+
"@saltcorn/data": "0.7.0-beta.3",
|
|
12
|
+
"@saltcorn/admin-models": "0.7.0-beta.3",
|
|
13
|
+
"@saltcorn/markup": "0.7.0-beta.3",
|
|
14
|
+
"@saltcorn/sbadmin2": "0.7.0-beta.3",
|
|
15
15
|
"@socket.io/cluster-adapter": "^0.1.0",
|
|
16
16
|
"@socket.io/sticky": "^1.0.1",
|
|
17
17
|
"aws-sdk": "^2.1037.0",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"greenlock": "^4.0.4",
|
|
32
32
|
"greenlock-express": "^4.0.3",
|
|
33
33
|
"helmet": "^3.23.3",
|
|
34
|
-
"i18n": "^0.
|
|
34
|
+
"i18n": "^0.14.0",
|
|
35
35
|
"live-plugin-manager": "^0.16.0",
|
|
36
36
|
"moment": "^2.27.0",
|
|
37
37
|
"multer": "^1.4.3",
|
package/public/saltcorn.js
CHANGED
|
@@ -423,7 +423,7 @@ function tristateClick(nm) {
|
|
|
423
423
|
}
|
|
424
424
|
}
|
|
425
425
|
|
|
426
|
-
function notifyAlert(note) {
|
|
426
|
+
function notifyAlert(note, spin) {
|
|
427
427
|
if (Array.isArray(note)) {
|
|
428
428
|
note.forEach(notifyAlert);
|
|
429
429
|
return;
|
|
@@ -438,10 +438,16 @@ function notifyAlert(note) {
|
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
$("#alerts-area")
|
|
441
|
-
.append(`<div class="alert alert-${type} alert-dismissible fade show
|
|
441
|
+
.append(`<div class="alert alert-${type} alert-dismissible fade show ${
|
|
442
|
+
spin ? "d-flex align-items-center" : ""
|
|
443
|
+
}" role="alert">
|
|
442
444
|
${txt}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
+
${
|
|
446
|
+
spin
|
|
447
|
+
? `<div class="spinner-border ms-auto" role="status" aria-hidden="true"></div>`
|
|
448
|
+
: `<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
|
449
|
+
</button>`
|
|
450
|
+
}
|
|
445
451
|
</div>`);
|
|
446
452
|
}
|
|
447
453
|
|
|
@@ -751,14 +757,33 @@ function room_older(viewname, room_id, btn) {
|
|
|
751
757
|
);
|
|
752
758
|
}
|
|
753
759
|
|
|
754
|
-
function fill_formula_btn_click(btn) {
|
|
760
|
+
async function fill_formula_btn_click(btn, k) {
|
|
755
761
|
const formula = decodeURIComponent($(btn).attr("data-formula"));
|
|
762
|
+
const free_vars = JSON.parse(
|
|
763
|
+
decodeURIComponent($(btn).attr("data-formula-free-vars"))
|
|
764
|
+
);
|
|
765
|
+
const table = JSON.parse(
|
|
766
|
+
decodeURIComponent($(btn).attr("data-formula-table"))
|
|
767
|
+
);
|
|
756
768
|
const rec = get_form_record($(btn), true);
|
|
769
|
+
const rec_ids = get_form_record($(btn));
|
|
770
|
+
for (const fv of free_vars) {
|
|
771
|
+
if (fv.includes(".")) {
|
|
772
|
+
const kpath = fv.split(".");
|
|
773
|
+
const [refNm, targetNm] = kpath;
|
|
774
|
+
const reffield = table.fields.find((f) => f.name === refNm);
|
|
775
|
+
const resp = await $.ajax(
|
|
776
|
+
`/api/${reffield.reftable_name}?id=${rec_ids[refNm]}`
|
|
777
|
+
);
|
|
778
|
+
rec[refNm] = resp.success[0];
|
|
779
|
+
}
|
|
780
|
+
}
|
|
757
781
|
const val = new Function(
|
|
758
782
|
`{${Object.keys(rec).join(",")}}`,
|
|
759
783
|
"return " + formula
|
|
760
784
|
)(rec);
|
|
761
785
|
$(btn).closest(".input-group").find("input").val(val);
|
|
786
|
+
if (k) k();
|
|
762
787
|
}
|
|
763
788
|
|
|
764
789
|
/*
|
package/routes/api.js
CHANGED
|
@@ -111,6 +111,48 @@ function accessAllowed(req, user, trigger) {
|
|
|
111
111
|
return role <= trigger.min_role;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
router.get(
|
|
115
|
+
"/:tableName/distinct/:fieldName",
|
|
116
|
+
//passport.authenticate("api-bearer", { session: false }),
|
|
117
|
+
error_catcher(async (req, res, next) => {
|
|
118
|
+
let { tableName, fieldName } = req.params;
|
|
119
|
+
const table = await Table.findOne(
|
|
120
|
+
strictParseInt(tableName)
|
|
121
|
+
? { id: strictParseInt(tableName) }
|
|
122
|
+
: { name: tableName }
|
|
123
|
+
);
|
|
124
|
+
if (!table) {
|
|
125
|
+
res.status(404).json({ error: req.__("Not found") });
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
await passport.authenticate(
|
|
130
|
+
"api-bearer",
|
|
131
|
+
{ session: false },
|
|
132
|
+
async function (err, user, info) {
|
|
133
|
+
if (accessAllowedRead(req, user, table)) {
|
|
134
|
+
const field = (await table.getFields()).find(
|
|
135
|
+
(f) => f.name === fieldName
|
|
136
|
+
);
|
|
137
|
+
if (!field) {
|
|
138
|
+
res.status(404).json({ error: req.__("Not found") });
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
let dvs;
|
|
142
|
+
if (field.is_fkey) {
|
|
143
|
+
dvs = await field.distinct_values();
|
|
144
|
+
} else {
|
|
145
|
+
dvs = await table.distinctValues(fieldName);
|
|
146
|
+
}
|
|
147
|
+
res.json({ success: dvs });
|
|
148
|
+
} else {
|
|
149
|
+
res.status(401).json({ error: req.__("Not authorized") });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
)(req, res, next);
|
|
153
|
+
})
|
|
154
|
+
);
|
|
155
|
+
|
|
114
156
|
/**
|
|
115
157
|
* Select Table rows using GET
|
|
116
158
|
* @name get/:tableName/
|
package/routes/homepage.js
CHANGED
|
@@ -265,7 +265,7 @@ const packTab = (req, packlist) =>
|
|
|
265
265
|
{ class: "pb-3 pt-2 pe-4" },
|
|
266
266
|
p(req.__("Instead of building, get up and running in no time with packs")),
|
|
267
267
|
p(
|
|
268
|
-
{ class: "
|
|
268
|
+
{ class: "fst-italic" },
|
|
269
269
|
req.__(
|
|
270
270
|
"Packs are collections of tables, views and plugins that give you a full application which you can then edit to suit your needs."
|
|
271
271
|
)
|
package/routes/plugins.js
CHANGED
|
@@ -450,6 +450,7 @@ const store_actions_dropdown = (req) =>
|
|
|
450
450
|
{
|
|
451
451
|
class: "dropdown-item",
|
|
452
452
|
href: `/plugins/upgrade`,
|
|
453
|
+
onClick: `notifyAlert('Upgrading plugins...', true)`,
|
|
453
454
|
},
|
|
454
455
|
'<i class="far fa-arrow-alt-circle-up"></i> ' +
|
|
455
456
|
req.__("Upgrade installed plugins")
|
|
@@ -646,7 +647,9 @@ router.get(
|
|
|
646
647
|
error_catcher(async (req, res) => {
|
|
647
648
|
const { plugin } = req.params;
|
|
648
649
|
const filepath = req.params[0];
|
|
649
|
-
const location = getState().plugin_locations[
|
|
650
|
+
const location = getState().plugin_locations[
|
|
651
|
+
plugin.includes("@") ? plugin.split("@")[0] : plugin
|
|
652
|
+
];
|
|
650
653
|
if (location) {
|
|
651
654
|
const safeFile = path
|
|
652
655
|
.normalize(filepath)
|