@saltcorn/data 0.6.1-beta.2 → 0.6.2-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/base-plugin/fieldviews.js +33 -28
- package/base-plugin/types.js +223 -94
- package/base-plugin/viewtemplates/edit.js +33 -26
- package/base-plugin/viewtemplates/filter.js +62 -15
- package/base-plugin/viewtemplates/list.js +16 -16
- package/base-plugin/viewtemplates/room.js +24 -22
- package/base-plugin/viewtemplates/show.js +26 -26
- package/base-plugin/viewtemplates/viewable_fields.js +26 -26
- package/db/index.js +6 -3
- package/models/expression.js +37 -25
- package/models/field.js +18 -12
- package/models/file.js +9 -2
- package/models/form.js +7 -6
- package/models/page.js +5 -1
- package/models/table.js +10 -2
- package/models/view.js +26 -22
- package/package.json +12 -7
- package/plugin-helper.js +31 -11
- package/tests/calc.test.js +22 -0
package/package.json
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/data",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2-beta.1",
|
|
4
4
|
"description": "Data models for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "jest --runInBand"
|
|
7
|
+
"test": "jest --runInBand",
|
|
8
|
+
"tsc": "echo \"Error: no TypeScript support yet\"",
|
|
9
|
+
"clean": "echo \"Error: no TypeScript support yet\""
|
|
8
10
|
},
|
|
9
11
|
"author": "Tom Nielsen",
|
|
10
12
|
"license": "MIT",
|
|
11
13
|
"main": "index.js",
|
|
12
14
|
"optionalDependencies": {
|
|
13
|
-
"@saltcorn/postgres": "0.6.
|
|
14
|
-
"@saltcorn/sqlite": "0.6.
|
|
15
|
+
"@saltcorn/postgres": "0.6.2-beta.1",
|
|
16
|
+
"@saltcorn/sqlite": "0.6.2-beta.1"
|
|
15
17
|
},
|
|
16
18
|
"dependencies": {
|
|
17
|
-
"@saltcorn/markup": "0.6.
|
|
18
|
-
"@saltcorn/db-common": "0.6.
|
|
19
|
+
"@saltcorn/markup": "0.6.2-beta.1",
|
|
20
|
+
"@saltcorn/db-common": "0.6.2-beta.1",
|
|
19
21
|
"acorn": "^8.0.3",
|
|
20
22
|
"adm-zip": "0.5.5",
|
|
21
23
|
"astring": "^1.4.3",
|
|
@@ -47,7 +49,10 @@
|
|
|
47
49
|
"jest": "^25.1.0"
|
|
48
50
|
},
|
|
49
51
|
"jest": {
|
|
50
|
-
"testEnvironment": "node"
|
|
52
|
+
"testEnvironment": "node",
|
|
53
|
+
"moduleNameMapper": {
|
|
54
|
+
"@saltcorn/sqlite/(.*)": "@saltcorn/sqlite/dist/$1"
|
|
55
|
+
}
|
|
51
56
|
},
|
|
52
57
|
"publishConfig": {
|
|
53
58
|
"access": "public"
|
package/plugin-helper.js
CHANGED
|
@@ -112,16 +112,19 @@ const stateToQueryString = contract(
|
|
|
112
112
|
*/
|
|
113
113
|
const calcfldViewOptions = contract(
|
|
114
114
|
is.fun(
|
|
115
|
-
[is.array(is.class("Field")), is.
|
|
115
|
+
[is.array(is.class("Field")), is.str],
|
|
116
116
|
is.obj({ field_view_options: is.objVals(is.array(is.str)) })
|
|
117
117
|
),
|
|
118
|
-
(fields,
|
|
119
|
-
|
|
118
|
+
(fields, mode) => {
|
|
119
|
+
const isEdit = mode === "edit";
|
|
120
|
+
const isFilter = mode === "filter";
|
|
121
|
+
let fvs = {};
|
|
120
122
|
const handlesTextStyle = {};
|
|
121
123
|
fields.forEach((f) => {
|
|
122
124
|
handlesTextStyle[f.name] = [];
|
|
123
125
|
if (f.type === "File") {
|
|
124
|
-
if (!isEdit
|
|
126
|
+
if (!isEdit && !isFilter)
|
|
127
|
+
fvs[f.name] = Object.keys(getState().fileviews);
|
|
125
128
|
else fvs[f.name] = ["upload"];
|
|
126
129
|
} else if (f.type === "Key") {
|
|
127
130
|
if (isEdit) fvs[f.name] = Object.keys(getState().keyFieldviews);
|
|
@@ -129,7 +132,7 @@ const calcfldViewOptions = contract(
|
|
|
129
132
|
if (f.reftable && f.reftable.fields) {
|
|
130
133
|
const { field_view_options } = calcfldViewOptions(
|
|
131
134
|
f.reftable.fields,
|
|
132
|
-
|
|
135
|
+
mode
|
|
133
136
|
);
|
|
134
137
|
for (const jf of f.reftable.fields) {
|
|
135
138
|
fvs[`${f.name}.${jf.name}`] = field_view_options[jf.name];
|
|
@@ -142,15 +145,20 @@ const calcfldViewOptions = contract(
|
|
|
142
145
|
});
|
|
143
146
|
} else if (f.type && f.type.fieldviews) {
|
|
144
147
|
const tfvs = Object.entries(f.type.fieldviews).filter(([k, fv]) =>
|
|
145
|
-
f.calculated ? !fv.isEdit : !fv.isEdit || isEdit
|
|
148
|
+
f.calculated ? !fv.isEdit : !fv.isEdit || isEdit || isFilter
|
|
146
149
|
);
|
|
147
150
|
let tfvs_ordered = [];
|
|
148
151
|
if (isEdit) {
|
|
149
152
|
tfvs_ordered = [
|
|
150
153
|
...tfvs.filter(([k, fv]) => fv.isEdit),
|
|
151
|
-
...tfvs.filter(([k, fv]) => !fv.isEdit),
|
|
154
|
+
...tfvs.filter(([k, fv]) => !fv.isEdit && !fv.isFilter),
|
|
152
155
|
];
|
|
153
|
-
} else
|
|
156
|
+
} else if (isFilter) {
|
|
157
|
+
tfvs_ordered = [
|
|
158
|
+
...tfvs.filter(([k, fv]) => fv.isFilter),
|
|
159
|
+
...tfvs.filter(([k, fv]) => fv.isEdit),
|
|
160
|
+
];
|
|
161
|
+
} else tfvs_ordered = tfvs.filter(([k, fv]) => !fv.isFilter);
|
|
154
162
|
fvs[f.name] = tfvs_ordered.map(([k, fv]) => {
|
|
155
163
|
if (fv && fv.handlesTextStyle) handlesTextStyle[f.name].push(k);
|
|
156
164
|
return k;
|
|
@@ -323,7 +331,7 @@ const field_picker_fields = contract(
|
|
|
323
331
|
}
|
|
324
332
|
}
|
|
325
333
|
const fldOptions = fields.map((f) => f.name);
|
|
326
|
-
const { field_view_options } = calcfldViewOptions(fields,
|
|
334
|
+
const { field_view_options } = calcfldViewOptions(fields, "show");
|
|
327
335
|
const fieldViewConfigForms = await calcfldViewConfig(fields, false);
|
|
328
336
|
const fvConfigFields = [];
|
|
329
337
|
for (const [field_name, fvOptFields] of Object.entries(
|
|
@@ -954,6 +962,14 @@ const stateFieldsToWhere = contract(
|
|
|
954
962
|
const dfield = fields.find((fld) => fld.name == datefield);
|
|
955
963
|
if (dfield)
|
|
956
964
|
addOrCreateList(qstate, datefield, { lt: new Date(v), equal: true });
|
|
965
|
+
} else if (k.startsWith("_gte_")) {
|
|
966
|
+
const datefield = db.sqlsanitize(k.replace("_gte_", ""));
|
|
967
|
+
const dfield = fields.find((fld) => fld.name == datefield);
|
|
968
|
+
if (dfield) addOrCreateList(qstate, datefield, { gt: v, equal: true });
|
|
969
|
+
} else if (k.startsWith("_lte_")) {
|
|
970
|
+
const datefield = db.sqlsanitize(k.replace("_lte_", ""));
|
|
971
|
+
const dfield = fields.find((fld) => fld.name == datefield);
|
|
972
|
+
if (dfield) addOrCreateList(qstate, datefield, { lt: v, equal: true });
|
|
957
973
|
} else if (
|
|
958
974
|
field &&
|
|
959
975
|
field.type.name === "String" &&
|
|
@@ -964,7 +980,9 @@ const stateFieldsToWhere = contract(
|
|
|
964
980
|
} else if (field && field.type.name === "Bool" && state[k] === "?") {
|
|
965
981
|
// omit
|
|
966
982
|
} else if (field && field.type && field.type.read)
|
|
967
|
-
qstate[k] =
|
|
983
|
+
qstate[k] = Array.isArray(v)
|
|
984
|
+
? { or: v.map(field.type.read) }
|
|
985
|
+
: field.type.read(v);
|
|
968
986
|
else if (field) qstate[k] = v;
|
|
969
987
|
else if (k.includes(".")) {
|
|
970
988
|
const kpath = k.split(".");
|
|
@@ -1124,7 +1142,9 @@ const readState = (state, fields, req) => {
|
|
|
1124
1142
|
fields.forEach((f) => {
|
|
1125
1143
|
const current = state[f.name];
|
|
1126
1144
|
if (typeof current !== "undefined") {
|
|
1127
|
-
if (
|
|
1145
|
+
if (Array.isArray(current) && f.type.read) {
|
|
1146
|
+
state[f.name] = current.map(f.type.read);
|
|
1147
|
+
} else if (f.type.read) state[f.name] = f.type.read(current);
|
|
1128
1148
|
else if (typeof current === "string" && current.startsWith("Preset:")) {
|
|
1129
1149
|
const preset = f.presets[current.replace("Preset:", "")];
|
|
1130
1150
|
state[f.name] = preset(req);
|
package/tests/calc.test.js
CHANGED
|
@@ -7,6 +7,7 @@ const {
|
|
|
7
7
|
get_expression_function,
|
|
8
8
|
transform_for_async,
|
|
9
9
|
expressionValidator,
|
|
10
|
+
jsexprToWhere,
|
|
10
11
|
} = require("../models/expression");
|
|
11
12
|
|
|
12
13
|
getState().registerPlugin("base", require("../base-plugin"));
|
|
@@ -219,3 +220,24 @@ describe("expressions", () => {
|
|
|
219
220
|
expect(expressionValidator("2+")).toBe("Unexpected end of input");
|
|
220
221
|
});
|
|
221
222
|
});
|
|
223
|
+
describe("jsexprToWhere", () => {
|
|
224
|
+
it("translates equality", () => {
|
|
225
|
+
expect(jsexprToWhere("foo==4")).toEqual({ foo: 4 });
|
|
226
|
+
});
|
|
227
|
+
it("translates equal to col", () => {
|
|
228
|
+
expect(jsexprToWhere("foo==bar").foo.description).toBe("bar");
|
|
229
|
+
});
|
|
230
|
+
it("translates context", () => {
|
|
231
|
+
expect(jsexprToWhere("foo==$bar", { bar: 5 })).toEqual({ foo: 5 });
|
|
232
|
+
});
|
|
233
|
+
it("translates context", () => {
|
|
234
|
+
const w = jsexprToWhere("$father !== null && married_to === $father", {
|
|
235
|
+
father: "1",
|
|
236
|
+
});
|
|
237
|
+
expect(w).toEqual({ married_to: "1", not: { eq: ["1", null] } });
|
|
238
|
+
});
|
|
239
|
+
it("translates context", () => {
|
|
240
|
+
const w = jsexprToWhere("$father !== null && married_to === $father", {});
|
|
241
|
+
expect(w).toEqual({ married_to: null, not: { eq: [null, null] } });
|
|
242
|
+
});
|
|
243
|
+
});
|