@saltcorn/server 0.8.6-beta.9 → 0.8.7-beta.0
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/auth/admin.js +2 -2
- package/auth/routes.js +7 -7
- package/load_plugins.js +4 -3
- package/locales/en.json +7 -1
- package/markup/admin.js +1 -1
- package/package.json +9 -9
- package/public/cm_modes/handlebars.js +70 -0
- package/public/cm_modes/htmlmixed.js +153 -0
- package/routes/actions.js +10 -3
- package/routes/admin.js +111 -21
- package/routes/api.js +6 -6
- package/routes/delete.js +1 -1
- package/routes/edit.js +1 -1
- package/routes/fields.js +30 -22
- package/routes/list.js +6 -6
- package/routes/menu.js +1 -1
- package/routes/plugins.js +12 -12
- package/routes/tables.js +33 -26
- package/routes/view.js +2 -2
- package/routes/viewedit.js +4 -5
- package/s3storage.js +1 -0
- package/serve.js +26 -2
- package/tests/api.test.js +1 -1
- package/tests/auth.test.js +4 -4
- package/tests/crud.test.js +7 -7
- package/tests/fields.test.js +10 -10
- package/tests/files.test.js +1 -1
- package/tests/kittens.test.js +1 -1
- package/tests/table.test.js +4 -4
- package/tests/view.test.js +4 -4
- package/tests/viewedit.test.js +8 -8
package/auth/admin.js
CHANGED
|
@@ -54,7 +54,7 @@ module.exports = router;
|
|
|
54
54
|
* @returns {Promise<object>}
|
|
55
55
|
*/
|
|
56
56
|
const getUserFields = async (req) => {
|
|
57
|
-
const userTable =
|
|
57
|
+
const userTable = Table.findOne({ name: "users" });
|
|
58
58
|
const userFields = (await userTable.getFields()).filter(
|
|
59
59
|
(f) => !f.calculated && f.name !== "id"
|
|
60
60
|
);
|
|
@@ -795,7 +795,7 @@ router.get(
|
|
|
795
795
|
const contents = [];
|
|
796
796
|
for (const table of tables) {
|
|
797
797
|
if (table.external) continue;
|
|
798
|
-
const fields =
|
|
798
|
+
const fields = table.getFields();
|
|
799
799
|
const ownership_opts = await table.ownership_options();
|
|
800
800
|
const form = new Form({
|
|
801
801
|
action: "/table",
|
package/auth/routes.js
CHANGED
|
@@ -467,7 +467,7 @@ const default_signup_form = async (req) => {
|
|
|
467
467
|
const form = loginForm(req, true);
|
|
468
468
|
const new_user_form = getState().getConfig("new_user_form", "");
|
|
469
469
|
if (!new_user_form) {
|
|
470
|
-
const userTable =
|
|
470
|
+
const userTable = Table.findOne({ name: "users" });
|
|
471
471
|
const userFields = await userTable.getFields();
|
|
472
472
|
|
|
473
473
|
for (const f of userFields) {
|
|
@@ -631,8 +631,8 @@ const getNewUserForm = async (new_user_view_name, req, askEmail) => {
|
|
|
631
631
|
const view = await View.findOne({ name: new_user_view_name });
|
|
632
632
|
if (!view)
|
|
633
633
|
throw new InvalidConfiguration("New user form view does not exist");
|
|
634
|
-
const table =
|
|
635
|
-
const fields =
|
|
634
|
+
const table = Table.findOne({ name: "users" });
|
|
635
|
+
const fields = table.getFields();
|
|
636
636
|
const { columns, layout } = view.configuration;
|
|
637
637
|
|
|
638
638
|
const tfields = (columns || [])
|
|
@@ -776,8 +776,8 @@ router.post(
|
|
|
776
776
|
|
|
777
777
|
signup_login_with_user(u, req, res);
|
|
778
778
|
} catch (e) {
|
|
779
|
-
const table =
|
|
780
|
-
const fields =
|
|
779
|
+
const table = Table.findOne({ name: "users" });
|
|
780
|
+
const fields = table.getFields();
|
|
781
781
|
form.hasErrors = true;
|
|
782
782
|
const unique_field_error = fields.find(
|
|
783
783
|
(f) =>
|
|
@@ -833,8 +833,8 @@ router.post(
|
|
|
833
833
|
|
|
834
834
|
signup_login_with_user(u, req, res);
|
|
835
835
|
} catch (e) {
|
|
836
|
-
const table =
|
|
837
|
-
const fields =
|
|
836
|
+
const table = Table.findOne({ name: "users" });
|
|
837
|
+
const fields = table.getFields();
|
|
838
838
|
form.hasErrors = true;
|
|
839
839
|
const unique_field_error = fields.find(
|
|
840
840
|
(f) =>
|
package/load_plugins.js
CHANGED
|
@@ -209,13 +209,14 @@ const loadAndSaveNewPlugin = async (plugin, force, noSignalOrDB) => {
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
if (version) plugin.version = version;
|
|
212
|
-
if (!noSignalOrDB)
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
if (!noSignalOrDB) {
|
|
213
|
+
await plugin.upsert();
|
|
214
|
+
getState().processSend({
|
|
215
215
|
installPlugin: plugin,
|
|
216
216
|
tenant: db.getTenantSchema(),
|
|
217
217
|
force,
|
|
218
218
|
});
|
|
219
|
+
}
|
|
219
220
|
};
|
|
220
221
|
|
|
221
222
|
module.exports = {
|
package/locales/en.json
CHANGED
|
@@ -1167,5 +1167,11 @@
|
|
|
1167
1167
|
"Migrations": "Migrations",
|
|
1168
1168
|
"Tag Entries": "Tag Entries",
|
|
1169
1169
|
"Not a valid field name": "Not a valid field name",
|
|
1170
|
-
"Set a default value for missing data": "Set a default value for missing data"
|
|
1170
|
+
"Set a default value for missing data": "Set a default value for missing data",
|
|
1171
|
+
"Table triggers: ": "Table triggers: ",
|
|
1172
|
+
"App name": "App name",
|
|
1173
|
+
"App icon": "App icon",
|
|
1174
|
+
"Splash Page": "Splash Page",
|
|
1175
|
+
"App version": "App version",
|
|
1176
|
+
"Forgot password?": "Forgot password?"
|
|
1171
1177
|
}
|
package/markup/admin.js
CHANGED
|
@@ -328,7 +328,7 @@ const send_admin_page = (args) => {
|
|
|
328
328
|
*/
|
|
329
329
|
const viewAttributes = async (key) => {
|
|
330
330
|
const [v, table_name] = configTypes[key].type.split(" ");
|
|
331
|
-
const table =
|
|
331
|
+
const table = Table.findOne({ name: table_name });
|
|
332
332
|
const views = await View.find({ table_id: table.id });
|
|
333
333
|
return {
|
|
334
334
|
options: views.map((v) => {
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7-beta.0",
|
|
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.8.
|
|
10
|
-
"@saltcorn/builder": "0.8.
|
|
11
|
-
"@saltcorn/data": "0.8.
|
|
12
|
-
"@saltcorn/admin-models": "0.8.
|
|
13
|
-
"@saltcorn/filemanager": "0.8.
|
|
14
|
-
"@saltcorn/markup": "0.8.
|
|
15
|
-
"@saltcorn/sbadmin2": "0.8.
|
|
9
|
+
"@saltcorn/base-plugin": "0.8.7-beta.0",
|
|
10
|
+
"@saltcorn/builder": "0.8.7-beta.0",
|
|
11
|
+
"@saltcorn/data": "0.8.7-beta.0",
|
|
12
|
+
"@saltcorn/admin-models": "0.8.7-beta.0",
|
|
13
|
+
"@saltcorn/filemanager": "0.8.7-beta.0",
|
|
14
|
+
"@saltcorn/markup": "0.8.7-beta.0",
|
|
15
|
+
"@saltcorn/sbadmin2": "0.8.7-beta.0",
|
|
16
16
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
17
17
|
"@socket.io/sticky": "^1.0.1",
|
|
18
18
|
"adm-zip": "0.5.10",
|
|
19
|
-
"aws-sdk": "^2.
|
|
19
|
+
"aws-sdk": "^2.1386.0",
|
|
20
20
|
"connect-flash": "^0.1.1",
|
|
21
21
|
"connect-pg-simple": "^6.1.0",
|
|
22
22
|
"content-disposition": "^0.5.3",
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
2
|
+
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
|
|
3
|
+
|
|
4
|
+
(function(mod) {
|
|
5
|
+
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
6
|
+
mod(require("../../lib/codemirror"), require("../../addon/mode/simple"), require("../../addon/mode/multiplex"));
|
|
7
|
+
else if (typeof define == "function" && define.amd) // AMD
|
|
8
|
+
define(["../../lib/codemirror", "../../addon/mode/simple", "../../addon/mode/multiplex"], mod);
|
|
9
|
+
else // Plain browser env
|
|
10
|
+
mod(CodeMirror);
|
|
11
|
+
})(function(CodeMirror) {
|
|
12
|
+
"use strict";
|
|
13
|
+
|
|
14
|
+
CodeMirror.defineSimpleMode("handlebars-tags", {
|
|
15
|
+
start: [
|
|
16
|
+
{ regex: /\{\{\{/, push: "handlebars_raw", token: "tag" },
|
|
17
|
+
{ regex: /\{\{!--/, push: "dash_comment", token: "comment" },
|
|
18
|
+
{ regex: /\{\{!/, push: "comment", token: "comment" },
|
|
19
|
+
{ regex: /\{\{/, push: "handlebars", token: "tag" }
|
|
20
|
+
],
|
|
21
|
+
handlebars_raw: [
|
|
22
|
+
{ regex: /\}\}\}/, pop: true, token: "tag" },
|
|
23
|
+
],
|
|
24
|
+
handlebars: [
|
|
25
|
+
{ regex: /\}\}/, pop: true, token: "tag" },
|
|
26
|
+
|
|
27
|
+
// Double and single quotes
|
|
28
|
+
{ regex: /"(?:[^\\"]|\\.)*"?/, token: "string" },
|
|
29
|
+
{ regex: /'(?:[^\\']|\\.)*'?/, token: "string" },
|
|
30
|
+
|
|
31
|
+
// Handlebars keywords
|
|
32
|
+
{ regex: />|[#\/]([A-Za-z_]\w*)/, token: "keyword" },
|
|
33
|
+
{ regex: /(?:else|this)\b/, token: "keyword" },
|
|
34
|
+
|
|
35
|
+
// Numeral
|
|
36
|
+
{ regex: /\d+/i, token: "number" },
|
|
37
|
+
|
|
38
|
+
// Atoms like = and .
|
|
39
|
+
{ regex: /=|~|@|true|false/, token: "atom" },
|
|
40
|
+
|
|
41
|
+
// Paths
|
|
42
|
+
{ regex: /(?:\.\.\/)*(?:[A-Za-z_][\w\.]*)+/, token: "variable-2" }
|
|
43
|
+
],
|
|
44
|
+
dash_comment: [
|
|
45
|
+
{ regex: /--\}\}/, pop: true, token: "comment" },
|
|
46
|
+
|
|
47
|
+
// Commented code
|
|
48
|
+
{ regex: /./, token: "comment"}
|
|
49
|
+
],
|
|
50
|
+
comment: [
|
|
51
|
+
{ regex: /\}\}/, pop: true, token: "comment" },
|
|
52
|
+
{ regex: /./, token: "comment" }
|
|
53
|
+
],
|
|
54
|
+
meta: {
|
|
55
|
+
blockCommentStart: "{{--",
|
|
56
|
+
blockCommentEnd: "--}}"
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
CodeMirror.defineMode("handlebars", function(config, parserConfig) {
|
|
61
|
+
var handlebars = CodeMirror.getMode(config, "handlebars-tags");
|
|
62
|
+
if (!parserConfig || !parserConfig.base) return handlebars;
|
|
63
|
+
return CodeMirror.multiplexingMode(
|
|
64
|
+
CodeMirror.getMode(config, parserConfig.base),
|
|
65
|
+
{open: "{{", close: /\}\}\}?/, mode: handlebars, parseDelimiters: true}
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
CodeMirror.defineMIME("text/x-handlebars-template", "handlebars");
|
|
70
|
+
});
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
2
|
+
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
|
|
3
|
+
|
|
4
|
+
(function(mod) {
|
|
5
|
+
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
6
|
+
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
|
|
7
|
+
else if (typeof define == "function" && define.amd) // AMD
|
|
8
|
+
define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
|
|
9
|
+
else // Plain browser env
|
|
10
|
+
mod(CodeMirror);
|
|
11
|
+
})(function(CodeMirror) {
|
|
12
|
+
"use strict";
|
|
13
|
+
|
|
14
|
+
var defaultTags = {
|
|
15
|
+
script: [
|
|
16
|
+
["lang", /(javascript|babel)/i, "javascript"],
|
|
17
|
+
["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i, "javascript"],
|
|
18
|
+
["type", /./, "text/plain"],
|
|
19
|
+
[null, null, "javascript"]
|
|
20
|
+
],
|
|
21
|
+
style: [
|
|
22
|
+
["lang", /^css$/i, "css"],
|
|
23
|
+
["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
|
|
24
|
+
["type", /./, "text/plain"],
|
|
25
|
+
[null, null, "css"]
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function maybeBackup(stream, pat, style) {
|
|
30
|
+
var cur = stream.current(), close = cur.search(pat);
|
|
31
|
+
if (close > -1) {
|
|
32
|
+
stream.backUp(cur.length - close);
|
|
33
|
+
} else if (cur.match(/<\/?$/)) {
|
|
34
|
+
stream.backUp(cur.length);
|
|
35
|
+
if (!stream.match(pat, false)) stream.match(cur);
|
|
36
|
+
}
|
|
37
|
+
return style;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
var attrRegexpCache = {};
|
|
41
|
+
function getAttrRegexp(attr) {
|
|
42
|
+
var regexp = attrRegexpCache[attr];
|
|
43
|
+
if (regexp) return regexp;
|
|
44
|
+
return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getAttrValue(text, attr) {
|
|
48
|
+
var match = text.match(getAttrRegexp(attr))
|
|
49
|
+
return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : ""
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getTagRegexp(tagName, anchored) {
|
|
53
|
+
return new RegExp((anchored ? "^" : "") + "<\/\\s*" + tagName + "\\s*>", "i");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function addTags(from, to) {
|
|
57
|
+
for (var tag in from) {
|
|
58
|
+
var dest = to[tag] || (to[tag] = []);
|
|
59
|
+
var source = from[tag];
|
|
60
|
+
for (var i = source.length - 1; i >= 0; i--)
|
|
61
|
+
dest.unshift(source[i])
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function findMatchingMode(tagInfo, tagText) {
|
|
66
|
+
for (var i = 0; i < tagInfo.length; i++) {
|
|
67
|
+
var spec = tagInfo[i];
|
|
68
|
+
if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
|
|
73
|
+
var htmlMode = CodeMirror.getMode(config, {
|
|
74
|
+
name: "xml",
|
|
75
|
+
htmlMode: true,
|
|
76
|
+
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
|
|
77
|
+
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag,
|
|
78
|
+
allowMissingTagName: parserConfig.allowMissingTagName,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
var tags = {};
|
|
82
|
+
var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
|
|
83
|
+
addTags(defaultTags, tags);
|
|
84
|
+
if (configTags) addTags(configTags, tags);
|
|
85
|
+
if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
|
|
86
|
+
tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
|
|
87
|
+
|
|
88
|
+
function html(stream, state) {
|
|
89
|
+
var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName
|
|
90
|
+
if (tag && !/[<>\s\/]/.test(stream.current()) &&
|
|
91
|
+
(tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) &&
|
|
92
|
+
tags.hasOwnProperty(tagName)) {
|
|
93
|
+
state.inTag = tagName + " "
|
|
94
|
+
} else if (state.inTag && tag && />$/.test(stream.current())) {
|
|
95
|
+
var inTag = /^([\S]+) (.*)/.exec(state.inTag)
|
|
96
|
+
state.inTag = null
|
|
97
|
+
var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2])
|
|
98
|
+
var mode = CodeMirror.getMode(config, modeSpec)
|
|
99
|
+
var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false);
|
|
100
|
+
state.token = function (stream, state) {
|
|
101
|
+
if (stream.match(endTagA, false)) {
|
|
102
|
+
state.token = html;
|
|
103
|
+
state.localState = state.localMode = null;
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
|
|
107
|
+
};
|
|
108
|
+
state.localMode = mode;
|
|
109
|
+
state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, "", ""));
|
|
110
|
+
} else if (state.inTag) {
|
|
111
|
+
state.inTag += stream.current()
|
|
112
|
+
if (stream.eol()) state.inTag += " "
|
|
113
|
+
}
|
|
114
|
+
return style;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
startState: function () {
|
|
119
|
+
var state = CodeMirror.startState(htmlMode);
|
|
120
|
+
return {token: html, inTag: null, localMode: null, localState: null, htmlState: state};
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
copyState: function (state) {
|
|
124
|
+
var local;
|
|
125
|
+
if (state.localState) {
|
|
126
|
+
local = CodeMirror.copyState(state.localMode, state.localState);
|
|
127
|
+
}
|
|
128
|
+
return {token: state.token, inTag: state.inTag,
|
|
129
|
+
localMode: state.localMode, localState: local,
|
|
130
|
+
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
token: function (stream, state) {
|
|
134
|
+
return state.token(stream, state);
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
indent: function (state, textAfter, line) {
|
|
138
|
+
if (!state.localMode || /^\s*<\//.test(textAfter))
|
|
139
|
+
return htmlMode.indent(state.htmlState, textAfter, line);
|
|
140
|
+
else if (state.localMode.indent)
|
|
141
|
+
return state.localMode.indent(state.localState, textAfter, line);
|
|
142
|
+
else
|
|
143
|
+
return CodeMirror.Pass;
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
innerMode: function (state) {
|
|
147
|
+
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}, "xml", "javascript", "css");
|
|
151
|
+
|
|
152
|
+
CodeMirror.defineMIME("text/html", "htmlmixed");
|
|
153
|
+
});
|
package/routes/actions.js
CHANGED
|
@@ -171,6 +171,13 @@ const triggerForm = async (req, trigger) => {
|
|
|
171
171
|
required: true,
|
|
172
172
|
options: Trigger.when_options.map((t) => ({ value: t, label: t })),
|
|
173
173
|
sublabel: req.__("Event type which runs the trigger"),
|
|
174
|
+
attributes: {
|
|
175
|
+
explainers: {
|
|
176
|
+
Often: "Every 5 minutes",
|
|
177
|
+
Never:
|
|
178
|
+
"Not scheduled but can be run as an action from a button click",
|
|
179
|
+
},
|
|
180
|
+
},
|
|
174
181
|
},
|
|
175
182
|
{
|
|
176
183
|
name: "table_id",
|
|
@@ -457,7 +464,7 @@ router.get(
|
|
|
457
464
|
} else {
|
|
458
465
|
// get table related to trigger
|
|
459
466
|
const table = trigger.table_id
|
|
460
|
-
?
|
|
467
|
+
? Table.findOne({ id: trigger.table_id })
|
|
461
468
|
: null;
|
|
462
469
|
// get configuration fields
|
|
463
470
|
const cfgFields = await getActionConfigFields(action, table);
|
|
@@ -502,7 +509,7 @@ router.post(
|
|
|
502
509
|
const trigger = await Trigger.findOne({ id });
|
|
503
510
|
const action = getState().actions[trigger.action];
|
|
504
511
|
const table = trigger.table_id
|
|
505
|
-
?
|
|
512
|
+
? Table.findOne({ id: trigger.table_id })
|
|
506
513
|
: null;
|
|
507
514
|
const cfgFields = await getActionConfigFields(action, table);
|
|
508
515
|
const form = new Form({
|
|
@@ -588,7 +595,7 @@ router.get(
|
|
|
588
595
|
};
|
|
589
596
|
let table, row;
|
|
590
597
|
if (trigger.table_id) {
|
|
591
|
-
table =
|
|
598
|
+
table = Table.findOne({ id: trigger.table_id });
|
|
592
599
|
row = await table.getRow({});
|
|
593
600
|
}
|
|
594
601
|
try {
|
package/routes/admin.js
CHANGED
|
@@ -954,12 +954,14 @@ router.post(
|
|
|
954
954
|
isAdmin,
|
|
955
955
|
error_catcher(async (req, res) => {
|
|
956
956
|
if (db.getTenantSchema() === db.connectObj.default_schema) {
|
|
957
|
-
if (process.send)
|
|
957
|
+
if (process.send) getState().processSend("RestartServer");
|
|
958
958
|
else process.exit(0);
|
|
959
959
|
} else {
|
|
960
960
|
await restart_tenant(loadAllPlugins);
|
|
961
|
-
|
|
962
|
-
|
|
961
|
+
getState().processSend({
|
|
962
|
+
restart_tenant: true,
|
|
963
|
+
tenant: db.getTenantSchema(),
|
|
964
|
+
});
|
|
963
965
|
req.flash("success", req.__("Restart complete"));
|
|
964
966
|
res.redirect("/admin");
|
|
965
967
|
}
|
|
@@ -984,13 +986,13 @@ router.post(
|
|
|
984
986
|
"npm",
|
|
985
987
|
["install", "-g", "@saltcorn/cli@latest", "--unsafe"],
|
|
986
988
|
{
|
|
987
|
-
stdio: ["ignore", "pipe",
|
|
989
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
988
990
|
}
|
|
989
991
|
);
|
|
990
992
|
child.stdout.on("data", (data) => {
|
|
991
993
|
res.write(data);
|
|
992
994
|
});
|
|
993
|
-
child.stderr
|
|
995
|
+
child.stderr?.on("data", (data) => {
|
|
994
996
|
res.write(data);
|
|
995
997
|
});
|
|
996
998
|
child.on("exit", function (code, signal) {
|
|
@@ -1000,7 +1002,7 @@ router.post(
|
|
|
1000
1002
|
)
|
|
1001
1003
|
);
|
|
1002
1004
|
setTimeout(() => {
|
|
1003
|
-
|
|
1005
|
+
getState().processSend("RestartServer");
|
|
1004
1006
|
process.exit(0);
|
|
1005
1007
|
}, 100);
|
|
1006
1008
|
});
|
|
@@ -1385,6 +1387,9 @@ router.get(
|
|
|
1385
1387
|
error_catcher(async (req, res) => {
|
|
1386
1388
|
const views = await View.find();
|
|
1387
1389
|
const pages = await Page.find();
|
|
1390
|
+
const images = (await File.find({ mime_super: "image" })).filter((image) =>
|
|
1391
|
+
image.filename?.endsWith(".png")
|
|
1392
|
+
);
|
|
1388
1393
|
|
|
1389
1394
|
send_admin_page({
|
|
1390
1395
|
res,
|
|
@@ -1462,7 +1467,7 @@ router.get(
|
|
|
1462
1467
|
// select entry-view
|
|
1463
1468
|
select(
|
|
1464
1469
|
{
|
|
1465
|
-
class: "form-
|
|
1470
|
+
class: "form-select",
|
|
1466
1471
|
name: "entryPoint",
|
|
1467
1472
|
id: "viewInputID",
|
|
1468
1473
|
},
|
|
@@ -1475,14 +1480,14 @@ router.get(
|
|
|
1475
1480
|
// select entry-page
|
|
1476
1481
|
select(
|
|
1477
1482
|
{
|
|
1478
|
-
class: "form-
|
|
1483
|
+
class: "form-select d-none",
|
|
1479
1484
|
id: "pageInputID",
|
|
1480
1485
|
},
|
|
1481
1486
|
pages
|
|
1482
1487
|
.map((page) =>
|
|
1483
1488
|
option({ value: page.name }, page.name)
|
|
1484
1489
|
)
|
|
1485
|
-
.join("
|
|
1490
|
+
.join("")
|
|
1486
1491
|
)
|
|
1487
1492
|
),
|
|
1488
1493
|
div(
|
|
@@ -1528,28 +1533,51 @@ router.get(
|
|
|
1528
1533
|
})
|
|
1529
1534
|
)
|
|
1530
1535
|
),
|
|
1536
|
+
// app name
|
|
1531
1537
|
div(
|
|
1532
1538
|
{ class: "row pb-2" },
|
|
1533
1539
|
div(
|
|
1534
1540
|
{ class: "col-sm-8" },
|
|
1535
1541
|
label(
|
|
1536
1542
|
{
|
|
1537
|
-
for: "
|
|
1543
|
+
for: "appFileInputId",
|
|
1538
1544
|
class: "form-label fw-bold",
|
|
1539
1545
|
},
|
|
1540
|
-
req.__("App
|
|
1546
|
+
req.__("App name")
|
|
1541
1547
|
),
|
|
1542
1548
|
input({
|
|
1543
1549
|
type: "text",
|
|
1544
1550
|
class: "form-control",
|
|
1545
|
-
name: "
|
|
1546
|
-
id: "
|
|
1547
|
-
placeholder: "
|
|
1551
|
+
name: "appName",
|
|
1552
|
+
id: "appNameInputId",
|
|
1553
|
+
placeholder: "SaltcornMobileApp",
|
|
1548
1554
|
})
|
|
1549
1555
|
)
|
|
1550
1556
|
),
|
|
1557
|
+
// app version
|
|
1551
1558
|
div(
|
|
1552
|
-
{ class: "row pb-
|
|
1559
|
+
{ class: "row pb-2" },
|
|
1560
|
+
div(
|
|
1561
|
+
{ class: "col-sm-8" },
|
|
1562
|
+
label(
|
|
1563
|
+
{
|
|
1564
|
+
for: "appVersionInputId",
|
|
1565
|
+
class: "form-label fw-bold",
|
|
1566
|
+
},
|
|
1567
|
+
req.__("App version")
|
|
1568
|
+
),
|
|
1569
|
+
input({
|
|
1570
|
+
type: "text",
|
|
1571
|
+
class: "form-control",
|
|
1572
|
+
name: "appVersion",
|
|
1573
|
+
id: "appVersionInputId",
|
|
1574
|
+
placeholder: "1.0.0",
|
|
1575
|
+
})
|
|
1576
|
+
)
|
|
1577
|
+
),
|
|
1578
|
+
// server url
|
|
1579
|
+
div(
|
|
1580
|
+
{ class: "row pb-2" },
|
|
1553
1581
|
div(
|
|
1554
1582
|
{ class: "col-sm-8" },
|
|
1555
1583
|
label(
|
|
@@ -1568,6 +1596,60 @@ router.get(
|
|
|
1568
1596
|
})
|
|
1569
1597
|
)
|
|
1570
1598
|
),
|
|
1599
|
+
// app icon
|
|
1600
|
+
div(
|
|
1601
|
+
{ class: "row pb-2" },
|
|
1602
|
+
div(
|
|
1603
|
+
{ class: "col-sm-8" },
|
|
1604
|
+
label(
|
|
1605
|
+
{
|
|
1606
|
+
for: "appIconInputId",
|
|
1607
|
+
class: "form-label fw-bold",
|
|
1608
|
+
},
|
|
1609
|
+
req.__("App icon")
|
|
1610
|
+
),
|
|
1611
|
+
select(
|
|
1612
|
+
{
|
|
1613
|
+
class: "form-select",
|
|
1614
|
+
name: "appIcon",
|
|
1615
|
+
id: "appIconInputId",
|
|
1616
|
+
},
|
|
1617
|
+
[
|
|
1618
|
+
option({ value: "" }, ""),
|
|
1619
|
+
...images.map((image) =>
|
|
1620
|
+
option({ value: image.location }, image.filename)
|
|
1621
|
+
),
|
|
1622
|
+
].join("")
|
|
1623
|
+
)
|
|
1624
|
+
)
|
|
1625
|
+
),
|
|
1626
|
+
div(
|
|
1627
|
+
{ class: "row pb-3" },
|
|
1628
|
+
div(
|
|
1629
|
+
{ class: "col-sm-8" },
|
|
1630
|
+
label(
|
|
1631
|
+
{
|
|
1632
|
+
for: "splashPageInputId",
|
|
1633
|
+
class: "form-label fw-bold",
|
|
1634
|
+
},
|
|
1635
|
+
req.__("Splash Page")
|
|
1636
|
+
),
|
|
1637
|
+
select(
|
|
1638
|
+
{
|
|
1639
|
+
class: "form-select",
|
|
1640
|
+
name: "splashPage",
|
|
1641
|
+
id: "splashPageInputId",
|
|
1642
|
+
},
|
|
1643
|
+
[
|
|
1644
|
+
option({ value: "" }, ""),
|
|
1645
|
+
...pages.map((page) =>
|
|
1646
|
+
option({ value: page.name }, page.name)
|
|
1647
|
+
),
|
|
1648
|
+
].join("")
|
|
1649
|
+
)
|
|
1650
|
+
)
|
|
1651
|
+
),
|
|
1652
|
+
|
|
1571
1653
|
div(
|
|
1572
1654
|
// TODO only for some tables?
|
|
1573
1655
|
{ class: "row pb-2" },
|
|
@@ -1686,8 +1768,11 @@ router.post(
|
|
|
1686
1768
|
androidPlatform,
|
|
1687
1769
|
iOSPlatform,
|
|
1688
1770
|
useDocker,
|
|
1689
|
-
|
|
1771
|
+
appName,
|
|
1772
|
+
appVersion,
|
|
1773
|
+
appIcon,
|
|
1690
1774
|
serverURL,
|
|
1775
|
+
splashPage,
|
|
1691
1776
|
allowOfflineMode,
|
|
1692
1777
|
} = req.body;
|
|
1693
1778
|
if (!androidPlatform && !iOSPlatform) {
|
|
@@ -1734,8 +1819,11 @@ router.post(
|
|
|
1734
1819
|
spawnParams.push("--buildForEmulator");
|
|
1735
1820
|
}
|
|
1736
1821
|
}
|
|
1737
|
-
if (
|
|
1822
|
+
if (appName) spawnParams.push("--appName", appName);
|
|
1823
|
+
if (appVersion) spawnParams.push("--appVersion", appVersion);
|
|
1824
|
+
if (appIcon) spawnParams.push("--appIcon", appIcon);
|
|
1738
1825
|
if (serverURL) spawnParams.push("-s", serverURL);
|
|
1826
|
+
if (splashPage) spawnParams.push("--splashPage", splashPage);
|
|
1739
1827
|
if (allowOfflineMode) spawnParams.push("--allowOfflineMode");
|
|
1740
1828
|
if (
|
|
1741
1829
|
db.is_it_multi_tenant() &&
|
|
@@ -1816,7 +1904,7 @@ router.post(
|
|
|
1816
1904
|
await View.delete({});
|
|
1817
1905
|
}
|
|
1818
1906
|
//user fields
|
|
1819
|
-
const users =
|
|
1907
|
+
const users = Table.findOne({ name: "users" });
|
|
1820
1908
|
const userfields = await users.getFields();
|
|
1821
1909
|
for (const f of userfields) {
|
|
1822
1910
|
if (f.is_fkey) {
|
|
@@ -1837,7 +1925,7 @@ router.post(
|
|
|
1837
1925
|
table_id: table.id,
|
|
1838
1926
|
});
|
|
1839
1927
|
await table.update({ ownership_field_id: null });
|
|
1840
|
-
const fields =
|
|
1928
|
+
const fields = table.getFields();
|
|
1841
1929
|
for (const f of fields) {
|
|
1842
1930
|
if (f.is_fkey) {
|
|
1843
1931
|
await f.delete();
|
|
@@ -1880,14 +1968,16 @@ router.post(
|
|
|
1880
1968
|
await getState().refresh();
|
|
1881
1969
|
}
|
|
1882
1970
|
if (form.values.users) {
|
|
1883
|
-
const users1 =
|
|
1971
|
+
const users1 = Table.findOne({ name: "users" });
|
|
1884
1972
|
const userfields1 = await users1.getFields();
|
|
1885
1973
|
|
|
1886
1974
|
for (const f of userfields1) {
|
|
1887
1975
|
if (f.name !== "email" && f.name !== "id") await f.delete();
|
|
1888
1976
|
}
|
|
1889
1977
|
await db.deleteWhere("users");
|
|
1890
|
-
await db.deleteWhere("_sc_roles", {
|
|
1978
|
+
await db.deleteWhere("_sc_roles", {
|
|
1979
|
+
not: { id: { in: [1, 40, 80, 100] } },
|
|
1980
|
+
});
|
|
1891
1981
|
if (db.reset_sequence) await db.reset_sequence("users");
|
|
1892
1982
|
req.logout(function (err) {
|
|
1893
1983
|
if (req.session.destroy)
|