@saltcorn/server 0.9.1-beta.3 → 0.9.1-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/help/Extra state formula.tmd +9 -0
- package/package.json +8 -8
- package/public/saltcorn-common.js +53 -12
- package/public/saltcorn.css +1 -0
- package/routes/fields.js +24 -0
- package/tests/fields.test.js +37 -1
- package/tests/table.test.js +5 -1
|
@@ -33,6 +33,9 @@ must be enclosed in quotes (single, double or
|
|
|
33
33
|
[backtick](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals))).
|
|
34
34
|
You can also as the value use a more complex JavaScript expression.
|
|
35
35
|
|
|
36
|
+
For examples of how you can use these values for greater than/less than,
|
|
37
|
+
or-conditions or case insensitivity, see [here](https://saltcorn.github.io/saltcorn/classes/_saltcorn_data.models.Table-1.html#md:querying-table-rows).
|
|
38
|
+
|
|
36
39
|
You can refer to the logged in user using the variable name user.
|
|
37
40
|
This is an object and you must use the dot to access user fields,
|
|
38
41
|
e.g. user.id for the logged in users id. A very common scenario
|
|
@@ -60,3 +63,9 @@ in this case the table {{srcTable.name}}:
|
|
|
60
63
|
|
|
61
64
|
{{# } }}
|
|
62
65
|
|
|
66
|
+
The state values from the query string can also be accessed, by preceeding the
|
|
67
|
+
variable name by a dollar sign (in pages and Show views). For instance if your URL ends in `?id=45&foo=1`,
|
|
68
|
+
you can access the value of `foo` (here 1) as `$foo`. In Filter views, there is no
|
|
69
|
+
underlying row and the purpose of the view is fundamentally to manipulate the state
|
|
70
|
+
so the state in extra state formulae is accessed without dollar sign; in the
|
|
71
|
+
previous example `foo` instead of `$foo`.
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.9.1-beta.
|
|
3
|
+
"version": "0.9.1-beta.5",
|
|
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.1-beta.
|
|
11
|
-
"@saltcorn/builder": "0.9.1-beta.
|
|
12
|
-
"@saltcorn/data": "0.9.1-beta.
|
|
13
|
-
"@saltcorn/admin-models": "0.9.1-beta.
|
|
14
|
-
"@saltcorn/filemanager": "0.9.1-beta.
|
|
15
|
-
"@saltcorn/markup": "0.9.1-beta.
|
|
16
|
-
"@saltcorn/sbadmin2": "0.9.1-beta.
|
|
10
|
+
"@saltcorn/base-plugin": "0.9.1-beta.5",
|
|
11
|
+
"@saltcorn/builder": "0.9.1-beta.5",
|
|
12
|
+
"@saltcorn/data": "0.9.1-beta.5",
|
|
13
|
+
"@saltcorn/admin-models": "0.9.1-beta.5",
|
|
14
|
+
"@saltcorn/filemanager": "0.9.1-beta.5",
|
|
15
|
+
"@saltcorn/markup": "0.9.1-beta.5",
|
|
16
|
+
"@saltcorn/sbadmin2": "0.9.1-beta.5",
|
|
17
17
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
18
18
|
"@socket.io/sticky": "^1.0.1",
|
|
19
19
|
"adm-zip": "0.5.10",
|
|
@@ -285,9 +285,13 @@ function apply_showif() {
|
|
|
285
285
|
.closest(".form-namespace")
|
|
286
286
|
.find("input[name=_columndef]");
|
|
287
287
|
try {
|
|
288
|
-
const
|
|
289
|
-
def
|
|
290
|
-
|
|
288
|
+
const defval = $def.val();
|
|
289
|
+
const def =
|
|
290
|
+
typeof defval === "undefined" ? undefined : JSON.parse(defval);
|
|
291
|
+
if (def) {
|
|
292
|
+
def[k] = v;
|
|
293
|
+
$def.val(JSON.stringify(def));
|
|
294
|
+
}
|
|
291
295
|
} catch (e) {
|
|
292
296
|
console.error("Invalid json", e);
|
|
293
297
|
}
|
|
@@ -393,21 +397,26 @@ function get_form_record(e_in, select_labels) {
|
|
|
393
397
|
}
|
|
394
398
|
|
|
395
399
|
e.find("input[name],select[name],textarea[name]").each(function () {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
400
|
+
const $this = $(this);
|
|
401
|
+
const name = $this.attr("data-fieldname") || $this.attr("name");
|
|
402
|
+
if (select_labels && $this.prop("tagName").toLowerCase() === "select")
|
|
403
|
+
rec[name] = $this.find("option:selected").text();
|
|
404
|
+
else if ($this.prop("type") === "checkbox")
|
|
405
|
+
rec[name] = $this.prop("checked");
|
|
406
|
+
else if ($this.prop("type") === "radio" && !$this.prop("checked")) {
|
|
407
|
+
//do nothing
|
|
408
|
+
} else rec[name] = $this.val();
|
|
402
409
|
});
|
|
403
410
|
return rec;
|
|
404
411
|
}
|
|
405
412
|
function showIfFormulaInputs(e, fml) {
|
|
406
413
|
const rec = get_form_record(e);
|
|
407
414
|
try {
|
|
408
|
-
return new Function(
|
|
409
|
-
|
|
410
|
-
|
|
415
|
+
return new Function(
|
|
416
|
+
"row",
|
|
417
|
+
`{${Object.keys(rec).join(",")}}`,
|
|
418
|
+
"return " + fml
|
|
419
|
+
)(rec, rec);
|
|
411
420
|
} catch (e) {
|
|
412
421
|
throw new Error(`Error in evaluating showIf formula ${fml}: ${e.message}`);
|
|
413
422
|
}
|
|
@@ -1380,3 +1389,35 @@ function check_saltcorn_notifications() {
|
|
|
1380
1389
|
}
|
|
1381
1390
|
});
|
|
1382
1391
|
}
|
|
1392
|
+
|
|
1393
|
+
function disable_inactive_tab_inputs(id) {
|
|
1394
|
+
setTimeout(() => {
|
|
1395
|
+
const isAccordion = $(`#${id}`).hasClass("accordion");
|
|
1396
|
+
const iterElem = isAccordion
|
|
1397
|
+
? `#${id} div.accordion-item .accordion-button`
|
|
1398
|
+
: `#${id} li a`;
|
|
1399
|
+
$(iterElem).each(function () {
|
|
1400
|
+
const isActive = isAccordion
|
|
1401
|
+
? !$(this).hasClass("collapsed")
|
|
1402
|
+
: $(this).hasClass("active");
|
|
1403
|
+
const target = isAccordion
|
|
1404
|
+
? $(this).attr("data-bs-target")
|
|
1405
|
+
: $(this).attr("href");
|
|
1406
|
+
if (isActive) {
|
|
1407
|
+
//activate previously disabled
|
|
1408
|
+
$(target)
|
|
1409
|
+
.find("[disabled-by-tab]")
|
|
1410
|
+
.prop("disabled", false)
|
|
1411
|
+
.removeAttr("disabled-by-tab");
|
|
1412
|
+
} else {
|
|
1413
|
+
//disable all input
|
|
1414
|
+
$(target)
|
|
1415
|
+
.find(
|
|
1416
|
+
"input:not(:disabled), textarea:not(:disabled), button:not(:disabled), select:not(:disabled)"
|
|
1417
|
+
)
|
|
1418
|
+
.prop("disabled", true)
|
|
1419
|
+
.attr("disabled-by-tab", "1");
|
|
1420
|
+
}
|
|
1421
|
+
});
|
|
1422
|
+
}, 100);
|
|
1423
|
+
}
|
package/public/saltcorn.css
CHANGED
package/routes/fields.js
CHANGED
|
@@ -996,6 +996,30 @@ router.post(
|
|
|
996
996
|
result = row[field.name];
|
|
997
997
|
} else if (field.stored) {
|
|
998
998
|
const f = get_async_expression_function(formula, fields);
|
|
999
|
+
//are there join fields in formula?
|
|
1000
|
+
const joinFields = {};
|
|
1001
|
+
add_free_variables_to_joinfields(
|
|
1002
|
+
freeVariables(formula),
|
|
1003
|
+
joinFields,
|
|
1004
|
+
table.fields
|
|
1005
|
+
);
|
|
1006
|
+
for (const { target, ref, through, rename_object } of Object.values(
|
|
1007
|
+
joinFields
|
|
1008
|
+
)) {
|
|
1009
|
+
const jf = table.getField(ref);
|
|
1010
|
+
const jtable = Table.findOne(jf.reftable_name);
|
|
1011
|
+
const jrow = await jtable.getRow({ [jtable.pk_name]: row[ref] });
|
|
1012
|
+
row[ref] = jrow;
|
|
1013
|
+
if (through) {
|
|
1014
|
+
const jf2 = jtable.getField(through);
|
|
1015
|
+
const jtable2 = Table.findOne(jf2.reftable_name);
|
|
1016
|
+
const jrow2 = await jtable2.getRow({
|
|
1017
|
+
[jtable2.pk_name]: jrow[through],
|
|
1018
|
+
});
|
|
1019
|
+
row[ref][through] = jrow2;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
|
|
999
1023
|
result = await f(row);
|
|
1000
1024
|
} else {
|
|
1001
1025
|
const f = get_expression_function(formula, fields);
|
package/tests/fields.test.js
CHANGED
|
@@ -364,7 +364,43 @@ describe("Field Endpoints", () => {
|
|
|
364
364
|
await request(app)
|
|
365
365
|
.post("/field/show-calculated/books/pagesp1/show")
|
|
366
366
|
.set("Cookie", loginCookie)
|
|
367
|
-
.expect((r) => +r.body >
|
|
367
|
+
.expect((r) => +r.body > 2);
|
|
368
|
+
});
|
|
369
|
+
it("should show calculated with single joinfield", async () => {
|
|
370
|
+
const loginCookie = await getAdminLoginCookie();
|
|
371
|
+
const table = Table.findOne({ name: "patients" });
|
|
372
|
+
await Field.create({
|
|
373
|
+
table,
|
|
374
|
+
label: "pagesp1",
|
|
375
|
+
type: "Integer",
|
|
376
|
+
calculated: true,
|
|
377
|
+
stored: true,
|
|
378
|
+
expression: "favbook.pages+1",
|
|
379
|
+
});
|
|
380
|
+
const app = await getApp({ disableCsrf: true });
|
|
381
|
+
|
|
382
|
+
await request(app)
|
|
383
|
+
.post("/field/show-calculated/patients/pagesp1/show")
|
|
384
|
+
.set("Cookie", loginCookie)
|
|
385
|
+
.expect((r) => +r.body > 2);
|
|
386
|
+
});
|
|
387
|
+
it("should show calculated with double joinfield", async () => {
|
|
388
|
+
const loginCookie = await getAdminLoginCookie();
|
|
389
|
+
const table = Table.findOne({ name: "readings" });
|
|
390
|
+
await Field.create({
|
|
391
|
+
table,
|
|
392
|
+
label: "pagesp1",
|
|
393
|
+
type: "Integer",
|
|
394
|
+
calculated: true,
|
|
395
|
+
stored: true,
|
|
396
|
+
expression: "patient_id.favbook.pages+1",
|
|
397
|
+
});
|
|
398
|
+
const app = await getApp({ disableCsrf: true });
|
|
399
|
+
|
|
400
|
+
await request(app)
|
|
401
|
+
.post("/field/show-calculated/readings/pagesp1/show")
|
|
402
|
+
.set("Cookie", loginCookie)
|
|
403
|
+
.expect((r) => +r.body > 2);
|
|
368
404
|
});
|
|
369
405
|
});
|
|
370
406
|
|
package/tests/table.test.js
CHANGED
|
@@ -17,8 +17,12 @@ const db = require("@saltcorn/data/db");
|
|
|
17
17
|
const User = require("@saltcorn/data/models/user");
|
|
18
18
|
const { plugin_with_routes } = require("@saltcorn/data/tests/mocks");
|
|
19
19
|
const { getState } = require("@saltcorn/data/db/state");
|
|
20
|
+
const { sleep } = require("@saltcorn/data/utils");
|
|
20
21
|
|
|
21
|
-
afterAll(
|
|
22
|
+
afterAll(async () => {
|
|
23
|
+
await sleep(200);
|
|
24
|
+
await db.close();
|
|
25
|
+
});
|
|
22
26
|
beforeAll(async () => {
|
|
23
27
|
await resetToFixtures();
|
|
24
28
|
});
|