@saltcorn/server 0.9.4-beta.6 → 0.9.4-beta.8
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 +7 -1
- package/package.json +8 -8
- package/public/saltcorn-builder.css +19 -1
- package/public/saltcorn.js +1 -1
- package/routes/fields.js +11 -2
- package/routes/files.js +3 -1
- package/routes/list.js +5 -0
- package/routes/tables.js +12 -1
- package/routes/view.js +10 -2
- package/routes/viewedit.js +20 -0
- package/tests/viewedit.test.js +0 -21
package/locales/en.json
CHANGED
|
@@ -1348,5 +1348,11 @@
|
|
|
1348
1348
|
"Pagegroup": "Pagegroup",
|
|
1349
1349
|
"Pagegroup %s has no members": "Pagegroup %s has no members",
|
|
1350
1350
|
"Remove border": "Remove border",
|
|
1351
|
-
"No lines between tables": "No lines between tables"
|
|
1351
|
+
"No lines between tables": "No lines between tables",
|
|
1352
|
+
"Use this to restrict your field to a list of options (separated by commas). For instance, enter <kbd class=\"fst-normal\">Red, Green, Blue</kbd> here if the permissible values are Red, Green and Blue. Leave blank if the string can hold any value.": "Use this to restrict your field to a list of options (separated by commas). For instance, enter <kbd class=\"fst-normal\">Red, Green, Blue</kbd> here if the permissible values are Red, Green and Blue. Leave blank if the string can hold any value.",
|
|
1353
|
+
"Page description": "Page description",
|
|
1354
|
+
"Some view patterns accept interpolations. Ex: <code>{{ name }}</code> or <code>{{ row ? `Edit ${row.name}` : `New person` }}</code>": "Some view patterns accept interpolations. Ex: <code>{{ name }}</code> or <code>{{ row ? `Edit ${row.name}` : `New person` }}</code>",
|
|
1355
|
+
"For search engines. Some view patterns accept interpolations.": "For search engines. Some view patterns accept interpolations.",
|
|
1356
|
+
"Files cache TTL (minutes)": "Files cache TTL (minutes)",
|
|
1357
|
+
"Cache-control max-age for files.": "Cache-control max-age for files."
|
|
1352
1358
|
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.9.4-beta.
|
|
3
|
+
"version": "0.9.4-beta.8",
|
|
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
9
|
"@aws-sdk/client-s3": "^3.451.0",
|
|
10
|
-
"@saltcorn/base-plugin": "0.9.4-beta.
|
|
11
|
-
"@saltcorn/builder": "0.9.4-beta.
|
|
12
|
-
"@saltcorn/data": "0.9.4-beta.
|
|
13
|
-
"@saltcorn/admin-models": "0.9.4-beta.
|
|
14
|
-
"@saltcorn/filemanager": "0.9.4-beta.
|
|
15
|
-
"@saltcorn/markup": "0.9.4-beta.
|
|
16
|
-
"@saltcorn/sbadmin2": "0.9.4-beta.
|
|
10
|
+
"@saltcorn/base-plugin": "0.9.4-beta.8",
|
|
11
|
+
"@saltcorn/builder": "0.9.4-beta.8",
|
|
12
|
+
"@saltcorn/data": "0.9.4-beta.8",
|
|
13
|
+
"@saltcorn/admin-models": "0.9.4-beta.8",
|
|
14
|
+
"@saltcorn/filemanager": "0.9.4-beta.8",
|
|
15
|
+
"@saltcorn/markup": "0.9.4-beta.8",
|
|
16
|
+
"@saltcorn/sbadmin2": "0.9.4-beta.8",
|
|
17
17
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
18
18
|
"@socket.io/sticky": "^1.0.1",
|
|
19
19
|
"adm-zip": "0.5.10",
|
|
@@ -54,16 +54,34 @@ div.builder-embed-view {
|
|
|
54
54
|
rgba(0, 0, 0, 0) 100%
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
|
+
|
|
58
|
+
.builder-left-enlarged div.toolbox-card.componets-and-library-accordion {
|
|
59
|
+
width: 13.35rem;
|
|
60
|
+
padding-right: 1rem;
|
|
61
|
+
margin-bottom: 1rem;
|
|
62
|
+
}
|
|
63
|
+
|
|
57
64
|
div.toolbox-card {
|
|
58
65
|
width: 9.2rem;
|
|
59
66
|
padding-right: 1rem;
|
|
60
67
|
margin-bottom: 1rem;
|
|
61
68
|
}
|
|
62
|
-
|
|
69
|
+
|
|
70
|
+
.builder-left-enlarged div.wrap-builder-elem {
|
|
71
|
+
width: 33%;
|
|
72
|
+
height: 4rem;
|
|
73
|
+
position: relative;
|
|
74
|
+
}
|
|
75
|
+
.builder-left-shrunk div.wrap-builder-elem {
|
|
63
76
|
width: 50%;
|
|
64
77
|
height: 4rem;
|
|
65
78
|
position: relative;
|
|
66
79
|
}
|
|
80
|
+
|
|
81
|
+
.builder-left-enlarged div.toolbox-card div.wrap-builder-elem:nth-child(2) {
|
|
82
|
+
border-right: 1px solid #bcbcbc;
|
|
83
|
+
}
|
|
84
|
+
|
|
67
85
|
div.toolbox-card div.wrap-builder-elem:nth-child(1) {
|
|
68
86
|
border-right: 1px solid #bcbcbc;
|
|
69
87
|
}
|
package/public/saltcorn.js
CHANGED
|
@@ -687,7 +687,7 @@ function make_unique_field(
|
|
|
687
687
|
);
|
|
688
688
|
}
|
|
689
689
|
function test_formula(tablename, stored) {
|
|
690
|
-
var formula = $("input[name=expression]").val();
|
|
690
|
+
var formula = $("input[name=expression],textarea[name=expression]").val();
|
|
691
691
|
ajax_post(`/field/test-formula`, {
|
|
692
692
|
data: { formula, tablename, stored },
|
|
693
693
|
success: (data) => {
|
package/routes/fields.js
CHANGED
|
@@ -479,6 +479,8 @@ const fieldFlow = (req) =>
|
|
|
479
479
|
// todo sublabel
|
|
480
480
|
type: "String",
|
|
481
481
|
class: "validate-expression",
|
|
482
|
+
fieldview: "textarea",
|
|
483
|
+
attributes: { rows: 2 },
|
|
482
484
|
validator: expressionValidator,
|
|
483
485
|
showIf: { expression_type: "JavaScript expression" },
|
|
484
486
|
}),
|
|
@@ -978,7 +980,7 @@ router.post(
|
|
|
978
980
|
const reftable = Table.findOne({ name: field.reftable_name });
|
|
979
981
|
if (!oldRow[ref]) break;
|
|
980
982
|
if (role > reftable.min_role_read) {
|
|
981
|
-
res.
|
|
983
|
+
res.status401.send("");
|
|
982
984
|
return;
|
|
983
985
|
}
|
|
984
986
|
const q = { [reftable.pk_name]: oldRow[ref] };
|
|
@@ -991,7 +993,14 @@ router.post(
|
|
|
991
993
|
}
|
|
992
994
|
if (oldRow) {
|
|
993
995
|
const value = oldRow[kpath[kpath.length - 1]];
|
|
994
|
-
|
|
996
|
+
//TODO run fieldview
|
|
997
|
+
res.send(
|
|
998
|
+
typeof value === "string"
|
|
999
|
+
? value
|
|
1000
|
+
: value?.toString
|
|
1001
|
+
? value.toString()
|
|
1002
|
+
: `${value}`
|
|
1003
|
+
);
|
|
995
1004
|
return;
|
|
996
1005
|
}
|
|
997
1006
|
}
|
package/routes/files.js
CHANGED
|
@@ -205,7 +205,8 @@ router.get(
|
|
|
205
205
|
) {
|
|
206
206
|
res.type(file.mimetype);
|
|
207
207
|
const cacheability = file.min_role_read === 100 ? "public" : "private";
|
|
208
|
-
|
|
208
|
+
const maxAge = getState().getConfig("files_cache_maxage", 86400);
|
|
209
|
+
res.set("Cache-Control", `${cacheability}, max-age=${maxAge}`);
|
|
209
210
|
if (file.s3_store) s3storage.serveObject(file, res, false);
|
|
210
211
|
else res.sendFile(file.location);
|
|
211
212
|
} else {
|
|
@@ -565,6 +566,7 @@ const files_settings_form = async (req) => {
|
|
|
565
566
|
field_names: [
|
|
566
567
|
"min_role_upload",
|
|
567
568
|
"file_accept_filter_default",
|
|
569
|
+
"files_cache_maxage",
|
|
568
570
|
"file_upload_debug",
|
|
569
571
|
"file_upload_limit",
|
|
570
572
|
"file_upload_timeout",
|
package/routes/list.js
CHANGED
|
@@ -161,6 +161,11 @@ const typeToGridType = (t, field) => {
|
|
|
161
161
|
jsgField.formatterParams = {
|
|
162
162
|
inputFormat: "iso",
|
|
163
163
|
};
|
|
164
|
+
|
|
165
|
+
if (field.attributes?.day_only) {
|
|
166
|
+
jsgField.editorParams = { dayOnly: true };
|
|
167
|
+
jsgField.formatter = "__isoDateFormatter";
|
|
168
|
+
}
|
|
164
169
|
} else if (t.name === "Color") {
|
|
165
170
|
jsgField.editor = "__colorEditor";
|
|
166
171
|
jsgField.formatter = "__colorFormatter";
|
package/routes/tables.js
CHANGED
|
@@ -59,6 +59,7 @@ const { tablesList, viewsList } = require("./common_lists");
|
|
|
59
59
|
const {
|
|
60
60
|
InvalidConfiguration,
|
|
61
61
|
removeAllWhiteSpace,
|
|
62
|
+
comparingCaseInsensitive,
|
|
62
63
|
} = require("@saltcorn/data/utils");
|
|
63
64
|
const { EOL } = require("os");
|
|
64
65
|
|
|
@@ -714,6 +715,7 @@ router.get(
|
|
|
714
715
|
...new Set(child_relations.map(({ table }) => table.name)),
|
|
715
716
|
];
|
|
716
717
|
const triggers = table.id ? Trigger.find({ table_id: table.id }) : [];
|
|
718
|
+
triggers.sort(comparingCaseInsensitive("name"));
|
|
717
719
|
let fieldCard;
|
|
718
720
|
if (fields.length === 0) {
|
|
719
721
|
fieldCard = [
|
|
@@ -785,7 +787,16 @@ router.get(
|
|
|
785
787
|
triggers.length
|
|
786
788
|
? req.__("Table triggers: ") +
|
|
787
789
|
triggers
|
|
788
|
-
.map((t) =>
|
|
790
|
+
.map((t) =>
|
|
791
|
+
link(
|
|
792
|
+
`/actions/configure/${
|
|
793
|
+
t.id
|
|
794
|
+
}?on_done_redirect=${encodeURIComponent(
|
|
795
|
+
`table/${table.name}`
|
|
796
|
+
)}`,
|
|
797
|
+
t.name
|
|
798
|
+
)
|
|
799
|
+
)
|
|
789
800
|
.join(", ") +
|
|
790
801
|
"<br>"
|
|
791
802
|
: "",
|
package/routes/view.js
CHANGED
|
@@ -74,8 +74,9 @@ router.get(
|
|
|
74
74
|
let title =
|
|
75
75
|
isModal && view.attributes?.popup_title
|
|
76
76
|
? view.attributes?.popup_title
|
|
77
|
-
:
|
|
78
|
-
|
|
77
|
+
: view.attributes?.page_title ||
|
|
78
|
+
scan_for_page_title(contents0, view.name); //legacy
|
|
79
|
+
if ((title || "").includes("{{")) {
|
|
79
80
|
title = await view.interpolate_title_string(title, query);
|
|
80
81
|
}
|
|
81
82
|
if (isModal && view.attributes?.popup_width)
|
|
@@ -89,6 +90,13 @@ router.get(
|
|
|
89
90
|
res.set("SaltcornModalSaveIndicator", `true`);
|
|
90
91
|
if (isModal && view.attributes?.popup_link_out)
|
|
91
92
|
res.set("SaltcornModalLinkOut", `true`);
|
|
93
|
+
if (view.attributes?.page_description) {
|
|
94
|
+
let description = view.attributes?.page_description;
|
|
95
|
+
if ((description || "").includes("{{")) {
|
|
96
|
+
description = await view.interpolate_title_string(description, query);
|
|
97
|
+
}
|
|
98
|
+
title = { title, description };
|
|
99
|
+
}
|
|
92
100
|
const tock = new Date();
|
|
93
101
|
const ms = tock.getTime() - tic.getTime();
|
|
94
102
|
if (!isTest())
|
package/routes/viewedit.js
CHANGED
|
@@ -182,6 +182,26 @@ const viewForm = async (req, tableOptions, roles, pages, values) => {
|
|
|
182
182
|
required: true,
|
|
183
183
|
options: roles.map((r) => ({ value: r.id, label: r.role })),
|
|
184
184
|
}),
|
|
185
|
+
new Field({
|
|
186
|
+
name: "page_title",
|
|
187
|
+
label: req.__("Page title"),
|
|
188
|
+
type: "String",
|
|
189
|
+
parent_field: "attributes",
|
|
190
|
+
tab: "View settings",
|
|
191
|
+
sublabel: req.__(
|
|
192
|
+
"Some view patterns accept interpolations. Ex: <code>{{ name }}</code> or <code>{{ row ? `Edit ${row.name}` : `New person` }}</code>"
|
|
193
|
+
),
|
|
194
|
+
}),
|
|
195
|
+
new Field({
|
|
196
|
+
name: "page_description",
|
|
197
|
+
label: req.__("Page description"),
|
|
198
|
+
type: "String",
|
|
199
|
+
parent_field: "attributes",
|
|
200
|
+
tab: "View settings",
|
|
201
|
+
sublabel: req.__(
|
|
202
|
+
"For search engines. Some view patterns accept interpolations."
|
|
203
|
+
),
|
|
204
|
+
}),
|
|
185
205
|
new Field({
|
|
186
206
|
name: "default_render_page",
|
|
187
207
|
label: req.__("Show on page"),
|
package/tests/viewedit.test.js
CHANGED
|
@@ -360,27 +360,6 @@ describe("viewedit new Show", () => {
|
|
|
360
360
|
.send("columns=" + encodeURIComponent(JSON.stringify(columns)))
|
|
361
361
|
.send("layout=" + encodeURIComponent(JSON.stringify(layout)))
|
|
362
362
|
.set("Cookie", loginCookie)
|
|
363
|
-
.expect(toInclude("Set page title"));
|
|
364
|
-
});
|
|
365
|
-
it("save new view page title", async () => {
|
|
366
|
-
const loginCookie = await getAdminLoginCookie();
|
|
367
|
-
const table = Table.findOne({ name: "books" });
|
|
368
|
-
|
|
369
|
-
const ctx = encodeURIComponent(
|
|
370
|
-
JSON.stringify({
|
|
371
|
-
table_id: table.id,
|
|
372
|
-
viewname: "mybook",
|
|
373
|
-
layout,
|
|
374
|
-
columns,
|
|
375
|
-
})
|
|
376
|
-
);
|
|
377
|
-
|
|
378
|
-
const app = await getApp({ disableCsrf: true });
|
|
379
|
-
await request(app)
|
|
380
|
-
.post("/viewedit/config/mybook")
|
|
381
|
-
.send("contextEnc=" + ctx)
|
|
382
|
-
.send("stepName=Set+page+title")
|
|
383
|
-
.set("Cookie", loginCookie)
|
|
384
363
|
.expect(toRedirect("/viewedit"));
|
|
385
364
|
});
|
|
386
365
|
it("should show new view", async () => {
|