@saltcorn/server 0.9.6-beta.0 → 0.9.6-beta.10
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 +54 -53
- package/load_plugins.js +5 -1
- package/locales/en.json +15 -1
- package/locales/it.json +3 -2
- package/markup/admin.js +1 -0
- package/markup/forms.js +5 -1
- package/package.json +9 -9
- package/public/saltcorn-common.js +80 -18
- package/public/saltcorn.css +8 -0
- package/public/saltcorn.js +64 -14
- package/routes/actions.js +8 -0
- package/routes/admin.js +51 -51
- package/routes/fields.js +62 -41
- package/routes/index.js +2 -0
- package/routes/pageedit.js +18 -13
- package/routes/plugins.js +6 -1
- package/routes/registry.js +289 -0
- package/routes/tables.js +4 -0
- package/routes/utils.js +5 -2
- package/routes/view.js +1 -1
- package/routes/viewedit.js +11 -7
- package/tests/page.test.js +2 -2
- package/tests/plugins.test.js +2 -0
package/auth/admin.js
CHANGED
|
@@ -99,6 +99,10 @@ const getUserFields = async (req) => {
|
|
|
99
99
|
input_type: "email",
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
+
if (f.name === "role_id") {
|
|
103
|
+
f.fieldview = "role_select";
|
|
104
|
+
await f.fill_fkey_options();
|
|
105
|
+
}
|
|
102
106
|
}
|
|
103
107
|
return userFields;
|
|
104
108
|
};
|
|
@@ -110,65 +114,59 @@ const getUserFields = async (req) => {
|
|
|
110
114
|
* @param {User} user
|
|
111
115
|
* @returns {Promise<Form>}
|
|
112
116
|
*/
|
|
113
|
-
const userForm =
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
117
|
+
const userForm = async (req, user) => {
|
|
118
|
+
const roleField = new Field({
|
|
119
|
+
label: req.__("Role"),
|
|
120
|
+
name: "role_id",
|
|
121
|
+
type: "Key",
|
|
122
|
+
reftable_name: "roles",
|
|
123
|
+
});
|
|
124
|
+
const roles = (await User.get_roles()).filter((r) => r.role !== "public");
|
|
125
|
+
roleField.options = roles.map((r) => ({ label: r.role, value: r.id }));
|
|
126
|
+
const can_reset = getState().getConfig("smtp_host", "") !== "";
|
|
127
|
+
const userFields = await getUserFields(req);
|
|
128
|
+
const form = new Form({
|
|
129
|
+
fields: userFields,
|
|
130
|
+
action: "/useradmin/save",
|
|
131
|
+
submitLabel: user ? req.__("Save") : req.__("Create"),
|
|
132
|
+
});
|
|
133
|
+
if (!user) {
|
|
134
|
+
form.fields.push(
|
|
135
|
+
new Field({
|
|
136
|
+
label: req.__("Set random password"),
|
|
137
|
+
name: "rnd_password",
|
|
138
|
+
type: "Bool",
|
|
139
|
+
default: true,
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
form.fields.push(
|
|
143
|
+
new Field({
|
|
144
|
+
label: req.__("Password"),
|
|
145
|
+
name: "password",
|
|
146
|
+
input_type: "password",
|
|
147
|
+
showIf: { rnd_password: false },
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
can_reset &&
|
|
135
151
|
form.fields.push(
|
|
136
152
|
new Field({
|
|
137
|
-
label: req.__("
|
|
138
|
-
name: "
|
|
153
|
+
label: req.__("Send password reset email"),
|
|
154
|
+
name: "send_pwreset_email",
|
|
139
155
|
type: "Bool",
|
|
140
156
|
default: true,
|
|
157
|
+
showIf: { rnd_password: true },
|
|
141
158
|
})
|
|
142
159
|
);
|
|
143
|
-
form.fields.push(
|
|
144
|
-
new Field({
|
|
145
|
-
label: req.__("Password"),
|
|
146
|
-
name: "password",
|
|
147
|
-
input_type: "password",
|
|
148
|
-
showIf: { rnd_password: false },
|
|
149
|
-
})
|
|
150
|
-
);
|
|
151
|
-
can_reset &&
|
|
152
|
-
form.fields.push(
|
|
153
|
-
new Field({
|
|
154
|
-
label: req.__("Send password reset email"),
|
|
155
|
-
name: "send_pwreset_email",
|
|
156
|
-
type: "Bool",
|
|
157
|
-
default: true,
|
|
158
|
-
showIf: { rnd_password: true },
|
|
159
|
-
})
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
if (user) {
|
|
163
|
-
form.hidden("id");
|
|
164
|
-
form.values = user;
|
|
165
|
-
delete form.values.password;
|
|
166
|
-
} else {
|
|
167
|
-
form.values.role_id = roles[roles.length - 1].id;
|
|
168
|
-
}
|
|
169
|
-
return form;
|
|
170
160
|
}
|
|
171
|
-
)
|
|
161
|
+
if (user) {
|
|
162
|
+
form.hidden("id");
|
|
163
|
+
form.values = user;
|
|
164
|
+
delete form.values.password;
|
|
165
|
+
} else {
|
|
166
|
+
form.values.role_id = roles[roles.length - 1].id;
|
|
167
|
+
}
|
|
168
|
+
return form;
|
|
169
|
+
};
|
|
172
170
|
|
|
173
171
|
/**
|
|
174
172
|
* Dropdown for User Info in left menu
|
|
@@ -531,7 +529,10 @@ router.post(
|
|
|
531
529
|
if (restart_required)
|
|
532
530
|
res.json({
|
|
533
531
|
success: "ok",
|
|
534
|
-
notify:
|
|
532
|
+
notify:
|
|
533
|
+
req.__("Restart required for changes to take effect.") +
|
|
534
|
+
" " +
|
|
535
|
+
a({ href: "/admin/system" }, req.__("Restart here")),
|
|
535
536
|
});
|
|
536
537
|
else res.json({ success: "ok" });
|
|
537
538
|
}
|
package/load_plugins.js
CHANGED
|
@@ -141,7 +141,11 @@ const loadAndSaveNewPlugin = async (
|
|
|
141
141
|
const existing = await Plugin.findOne({ location: loc });
|
|
142
142
|
if (!existing && loc !== plugin.location) {
|
|
143
143
|
await loadAndSaveNewPlugin(
|
|
144
|
-
new Plugin({
|
|
144
|
+
new Plugin({
|
|
145
|
+
name: loc.replace("@saltcorn/", ""),
|
|
146
|
+
location: loc,
|
|
147
|
+
source: "npm",
|
|
148
|
+
}),
|
|
145
149
|
force,
|
|
146
150
|
noSignalOrDB
|
|
147
151
|
);
|
package/locales/en.json
CHANGED
|
@@ -1416,5 +1416,19 @@
|
|
|
1416
1416
|
"Description header": "Description header",
|
|
1417
1417
|
"Lazy load views": "Lazy load views",
|
|
1418
1418
|
"Log IP address": "Log IP address",
|
|
1419
|
-
"Record the request IP address in log messages": "Record the request IP address in log messages"
|
|
1419
|
+
"Record the request IP address in log messages": "Record the request IP address in log messages",
|
|
1420
|
+
"App ID": "App ID",
|
|
1421
|
+
"Build type": "Build type",
|
|
1422
|
+
"debug": "debug",
|
|
1423
|
+
"release": "release",
|
|
1424
|
+
"Keystore File": "Keystore File",
|
|
1425
|
+
"Keystore Alias": "Keystore Alias",
|
|
1426
|
+
"Keystore Password": "Keystore Password",
|
|
1427
|
+
"xcodebuild": "xcodebuild",
|
|
1428
|
+
"Provisioning Profile": "Provisioning Profile",
|
|
1429
|
+
"Registry editor": "Registry editor",
|
|
1430
|
+
"A short name that will be in the page URL": "A short name that will be in the page URL",
|
|
1431
|
+
"A longer description that is not visible but appears in the page header and is indexed by search engines": "A longer description that is not visible but appears in the page header and is indexed by search engines",
|
|
1432
|
+
"User role required to access page": "User role required to access page",
|
|
1433
|
+
"Example: <code>`/view/TheOtherView?id=${id}`</code>": "Example: <code>`/view/TheOtherView?id=${id}`</code>"
|
|
1420
1434
|
}
|
package/locales/it.json
CHANGED
|
@@ -518,5 +518,6 @@
|
|
|
518
518
|
"Save before going back": "Save before going back",
|
|
519
519
|
"Reload after going back": "Reload after going back",
|
|
520
520
|
"Steps to go back": "Steps to go back",
|
|
521
|
-
"%s configuration": "%s configuration"
|
|
522
|
-
|
|
521
|
+
"%s configuration": "%s configuration",
|
|
522
|
+
"The current theme has no user specific settings": "The current theme has no user specific settings"
|
|
523
|
+
}
|
package/markup/admin.js
CHANGED
|
@@ -241,6 +241,7 @@ const send_infoarch_page = (args) => {
|
|
|
241
241
|
{ text: "Pagegroups", href: "/page_group/settings" },
|
|
242
242
|
{ text: "Tags", href: "/tag" },
|
|
243
243
|
{ text: "Diagram", href: "/diagram" },
|
|
244
|
+
{ text: "Registry editor", href: "/registry-editor" },
|
|
244
245
|
],
|
|
245
246
|
...args,
|
|
246
247
|
});
|
package/markup/forms.js
CHANGED
|
@@ -28,10 +28,14 @@ const editRoleForm = ({ url, current_role, roles, req }) =>
|
|
|
28
28
|
{
|
|
29
29
|
action: url,
|
|
30
30
|
method: "post",
|
|
31
|
+
onchange: "saveAndContinue(this)",
|
|
31
32
|
},
|
|
32
33
|
csrfField(req),
|
|
33
34
|
select(
|
|
34
|
-
{
|
|
35
|
+
{
|
|
36
|
+
name: "role",
|
|
37
|
+
class: "w-unset form-select form-select-sm",
|
|
38
|
+
},
|
|
35
39
|
roles.map((role) =>
|
|
36
40
|
option(
|
|
37
41
|
{
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.9.6-beta.
|
|
3
|
+
"version": "0.9.6-beta.10",
|
|
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.6-beta.
|
|
11
|
-
"@saltcorn/builder": "0.9.6-beta.
|
|
12
|
-
"@saltcorn/data": "0.9.6-beta.
|
|
13
|
-
"@saltcorn/admin-models": "0.9.6-beta.
|
|
14
|
-
"@saltcorn/filemanager": "0.9.6-beta.
|
|
15
|
-
"@saltcorn/markup": "0.9.6-beta.
|
|
16
|
-
"@saltcorn/plugins-loader": "0.9.6-beta.
|
|
17
|
-
"@saltcorn/sbadmin2": "0.9.6-beta.
|
|
10
|
+
"@saltcorn/base-plugin": "0.9.6-beta.10",
|
|
11
|
+
"@saltcorn/builder": "0.9.6-beta.10",
|
|
12
|
+
"@saltcorn/data": "0.9.6-beta.10",
|
|
13
|
+
"@saltcorn/admin-models": "0.9.6-beta.10",
|
|
14
|
+
"@saltcorn/filemanager": "0.9.6-beta.10",
|
|
15
|
+
"@saltcorn/markup": "0.9.6-beta.10",
|
|
16
|
+
"@saltcorn/plugins-loader": "0.9.6-beta.10",
|
|
17
|
+
"@saltcorn/sbadmin2": "0.9.6-beta.10",
|
|
18
18
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
19
19
|
"@socket.io/sticky": "^1.0.1",
|
|
20
20
|
"adm-zip": "0.5.10",
|
|
@@ -179,14 +179,19 @@ function apply_showif() {
|
|
|
179
179
|
is_or ? "&_or_field=" + k : ""
|
|
180
180
|
}`;
|
|
181
181
|
};
|
|
182
|
-
const qss = Object.entries(dynwhere.whereParsed).map(kvToQs);
|
|
182
|
+
const qss = Object.entries(dynwhere.whereParsed).map((kv) => kvToQs(kv));
|
|
183
|
+
if (dynwhere.existingValue) {
|
|
184
|
+
qss.push(`id=${dynwhere.existingValue}`);
|
|
185
|
+
qss.push(`_or_field=id`);
|
|
186
|
+
}
|
|
183
187
|
if (dynwhere.dereference) {
|
|
184
188
|
if (Array.isArray(dynwhere.dereference))
|
|
185
189
|
qss.push(...dynwhere.dereference.map((d) => `dereference=${d}`));
|
|
186
190
|
else qss.push(`dereference=${dynwhere.dereference}`);
|
|
187
191
|
}
|
|
188
192
|
const qs = qss.join("&");
|
|
189
|
-
|
|
193
|
+
let current = e.attr("data-selected");
|
|
194
|
+
if (current === "null") current = null;
|
|
190
195
|
e.change(function (ec) {
|
|
191
196
|
e.attr("data-selected", ec.target.value);
|
|
192
197
|
});
|
|
@@ -195,12 +200,14 @@ function apply_showif() {
|
|
|
195
200
|
if (currentOptionsSet === qs) return;
|
|
196
201
|
|
|
197
202
|
const activate = (success, qs) => {
|
|
203
|
+
//re-fetch current, because it may have changed
|
|
204
|
+
let current = e.attr("data-selected");
|
|
205
|
+
if (current === "null") current = null;
|
|
198
206
|
if (e.prop("data-fetch-options-current-set") === qs) return;
|
|
199
207
|
e.empty();
|
|
200
208
|
e.prop("data-fetch-options-current-set", qs);
|
|
201
209
|
const toAppend = [];
|
|
202
|
-
|
|
203
|
-
toAppend.push({ label: dynwhere.neutral_label || "", value: "" });
|
|
210
|
+
|
|
204
211
|
let currentDataOption = undefined;
|
|
205
212
|
const dataOptions = [];
|
|
206
213
|
//console.log(success);
|
|
@@ -231,13 +238,24 @@ function apply_showif() {
|
|
|
231
238
|
? 1
|
|
232
239
|
: -1
|
|
233
240
|
);
|
|
241
|
+
if (!dynwhere.required)
|
|
242
|
+
toAppend.unshift({ label: dynwhere.neutral_label || "", value: "" });
|
|
243
|
+
if (dynwhere.required && dynwhere.placeholder)
|
|
244
|
+
toAppend.unshift({
|
|
245
|
+
disabled: true,
|
|
246
|
+
label: dynwhere.placeholder,
|
|
247
|
+
value: "",
|
|
248
|
+
selected: !current,
|
|
249
|
+
});
|
|
234
250
|
e.html(
|
|
235
251
|
toAppend
|
|
236
252
|
.map(
|
|
237
|
-
({ label, value, selected }) =>
|
|
253
|
+
({ label, value, selected, disabled }) =>
|
|
238
254
|
`<option${selected ? ` selected` : ""}${
|
|
239
|
-
|
|
240
|
-
}
|
|
255
|
+
disabled ? ` disabled` : ""
|
|
256
|
+
}${typeof value !== "undefined" ? ` value="${value}"` : ""}>${
|
|
257
|
+
label || ""
|
|
258
|
+
}</option>`
|
|
241
259
|
)
|
|
242
260
|
.join("")
|
|
243
261
|
);
|
|
@@ -428,7 +446,7 @@ function get_form_record(e_in, select_labels) {
|
|
|
428
446
|
|
|
429
447
|
const e = e_in.viewname
|
|
430
448
|
? $(`form[data-viewname="${e_in.viewname}"]`)
|
|
431
|
-
: e_in.closest(".form-namespace");
|
|
449
|
+
: $(e_in).closest(".form-namespace");
|
|
432
450
|
|
|
433
451
|
const form = $(e).closest("form");
|
|
434
452
|
|
|
@@ -462,6 +480,38 @@ function get_form_record(e_in, select_labels) {
|
|
|
462
480
|
rec[name] = f(rec[name], $this);
|
|
463
481
|
}
|
|
464
482
|
});
|
|
483
|
+
|
|
484
|
+
const joinFieldsStr =
|
|
485
|
+
typeof e_in !== "string" && $(e_in).attr("data-show-if-joinfields");
|
|
486
|
+
if (joinFieldsStr) {
|
|
487
|
+
const joinFields = JSON.parse(decodeURIComponent(joinFieldsStr));
|
|
488
|
+
|
|
489
|
+
const joinVals = $(e_in).prop("data-join-values");
|
|
490
|
+
const kvals = $(e_in).prop("data-join-key-values") || {};
|
|
491
|
+
let differentKeys = false;
|
|
492
|
+
for (const { ref } of joinFields) {
|
|
493
|
+
if (rec[ref] != kvals[ref]) differentKeys = true;
|
|
494
|
+
}
|
|
495
|
+
if (!joinVals || differentKeys) {
|
|
496
|
+
$(e_in).prop("data-join-values", {});
|
|
497
|
+
const keyVals = {};
|
|
498
|
+
for (const { ref, target, refTable } of joinFields) {
|
|
499
|
+
keyVals[ref] = rec[ref];
|
|
500
|
+
$.ajax(`/api/${refTable}?id=${rec[ref]}`, {
|
|
501
|
+
success: (val) => {
|
|
502
|
+
const jvs = $(e_in).prop("data-join-values") || {};
|
|
503
|
+
|
|
504
|
+
jvs[ref] = val.success[0];
|
|
505
|
+
$(e_in).prop("data-join-values", jvs);
|
|
506
|
+
apply_showif();
|
|
507
|
+
},
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
$(e_in).prop("data-join-key-values", keyVals);
|
|
511
|
+
} else if (joinFieldsStr) {
|
|
512
|
+
Object.assign(rec, joinVals);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
465
515
|
return rec;
|
|
466
516
|
}
|
|
467
517
|
function showIfFormulaInputs(e, fml) {
|
|
@@ -1219,7 +1269,13 @@ function restore_old_button(btnId) {
|
|
|
1219
1269
|
btn.removeData("old-text");
|
|
1220
1270
|
}
|
|
1221
1271
|
|
|
1222
|
-
async function common_done(res,
|
|
1272
|
+
async function common_done(res, viewnameOrElem, isWeb = true) {
|
|
1273
|
+
const viewname =
|
|
1274
|
+
typeof viewnameOrElem === "string"
|
|
1275
|
+
? viewnameOrElem
|
|
1276
|
+
: $(viewnameOrElem)
|
|
1277
|
+
.closest("[data-sc-embed-viewname]")
|
|
1278
|
+
.attr("data-sc-embed-viewname");
|
|
1223
1279
|
if (window._sc_loglevel > 4)
|
|
1224
1280
|
console.log("ajax result directives", viewname, res);
|
|
1225
1281
|
const handle = async (element, fn) => {
|
|
@@ -1231,15 +1287,15 @@ async function common_done(res, viewname, isWeb = true) {
|
|
|
1231
1287
|
if (res.row && res.field_names) {
|
|
1232
1288
|
const f = new Function(`viewname, row, {${res.field_names}}`, s);
|
|
1233
1289
|
const evalres = await f(viewname, res.row, res.row);
|
|
1234
|
-
if (evalres) await common_done(evalres,
|
|
1290
|
+
if (evalres) await common_done(evalres, viewnameOrElem, isWeb);
|
|
1235
1291
|
} else if (res.row) {
|
|
1236
1292
|
const f = new Function(`viewname, row`, s);
|
|
1237
1293
|
const evalres = await f(viewname, res.row);
|
|
1238
|
-
if (evalres) await common_done(evalres,
|
|
1294
|
+
if (evalres) await common_done(evalres, viewnameOrElem, isWeb);
|
|
1239
1295
|
} else {
|
|
1240
1296
|
const f = new Function(`viewname`, s);
|
|
1241
1297
|
const evalres = await f(viewname);
|
|
1242
|
-
if (evalres) await common_done(evalres,
|
|
1298
|
+
if (evalres) await common_done(evalres, viewnameOrElem, isWeb);
|
|
1243
1299
|
}
|
|
1244
1300
|
};
|
|
1245
1301
|
if (res.notify) await handle(res.notify, notifyAlert);
|
|
@@ -1252,9 +1308,10 @@ async function common_done(res, viewname, isWeb = true) {
|
|
|
1252
1308
|
notifyAlert({ type: "success", text: text })
|
|
1253
1309
|
);
|
|
1254
1310
|
if (res.set_fields && (viewname || res.set_fields._viewname)) {
|
|
1255
|
-
const form =
|
|
1256
|
-
|
|
1257
|
-
|
|
1311
|
+
const form =
|
|
1312
|
+
typeof viewnameOrElem === "string" || res.set_fields._viewname
|
|
1313
|
+
? $(`form[data-viewname="${res.set_fields._viewname || viewname}"]`)
|
|
1314
|
+
: $(viewnameOrElem).closest("form[data-viewname]");
|
|
1258
1315
|
if (form.length === 0 && set_state_fields) {
|
|
1259
1316
|
// assume this is a filter
|
|
1260
1317
|
set_state_fields(
|
|
@@ -1279,9 +1336,14 @@ async function common_done(res, viewname, isWeb = true) {
|
|
|
1279
1336
|
if (input.attr("type") === "checkbox")
|
|
1280
1337
|
input.prop("checked", res.set_fields[k]);
|
|
1281
1338
|
else input.val(res.set_fields[k]);
|
|
1339
|
+
if (input.attr("data-selected")) {
|
|
1340
|
+
input.attr("data-selected", res.set_fields[k]);
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1282
1343
|
input.trigger("set_form_field");
|
|
1283
1344
|
});
|
|
1284
1345
|
}
|
|
1346
|
+
form.trigger("change");
|
|
1285
1347
|
}
|
|
1286
1348
|
|
|
1287
1349
|
if (res.download) {
|
|
@@ -1440,10 +1502,10 @@ const columnSummary = (col) => {
|
|
|
1440
1502
|
};
|
|
1441
1503
|
|
|
1442
1504
|
function submitWithEmptyAction(form) {
|
|
1443
|
-
var formAction = form.action;
|
|
1444
|
-
form.action
|
|
1505
|
+
var formAction = form.getAttribute("action");
|
|
1506
|
+
form.setAttribute("action", "javascript:void(0)");
|
|
1445
1507
|
form.submit();
|
|
1446
|
-
form.action
|
|
1508
|
+
form.setAttribute("action", formAction);
|
|
1447
1509
|
}
|
|
1448
1510
|
|
|
1449
1511
|
function unique_field_from_rows(
|
package/public/saltcorn.css
CHANGED
package/public/saltcorn.js
CHANGED
|
@@ -236,7 +236,13 @@ function reset_spinners() {
|
|
|
236
236
|
});
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
function view_post(
|
|
239
|
+
function view_post(viewnameOrElem, route, data, onDone, sendState) {
|
|
240
|
+
const viewname =
|
|
241
|
+
typeof viewnameOrElem === "string"
|
|
242
|
+
? viewnameOrElem
|
|
243
|
+
: $(viewnameOrElem)
|
|
244
|
+
.closest("[data-sc-embed-viewname]")
|
|
245
|
+
.attr("data-sc-embed-viewname");
|
|
240
246
|
const query = sendState
|
|
241
247
|
? `?${new URL(get_current_state_url()).searchParams.toString()}`
|
|
242
248
|
: "";
|
|
@@ -254,7 +260,7 @@ function view_post(viewname, route, data, onDone, sendState) {
|
|
|
254
260
|
})
|
|
255
261
|
.done(function (res) {
|
|
256
262
|
if (onDone) onDone(res);
|
|
257
|
-
ajax_done(res,
|
|
263
|
+
ajax_done(res, viewnameOrElem);
|
|
258
264
|
reset_spinners();
|
|
259
265
|
})
|
|
260
266
|
.fail(function (res) {
|
|
@@ -751,6 +757,42 @@ function removeSpinner(elementId, orginalHtml) {
|
|
|
751
757
|
$(`#${elementId}`).html(orginalHtml);
|
|
752
758
|
}
|
|
753
759
|
|
|
760
|
+
function builderMenuChanged(e) {
|
|
761
|
+
const form = $(e);
|
|
762
|
+
const params = {};
|
|
763
|
+
form.serializeArray().forEach((item) => {
|
|
764
|
+
params[item.name] = item.value;
|
|
765
|
+
});
|
|
766
|
+
params.synchedTables = Array.from($("#synched-tbls-select-id")[0].options)
|
|
767
|
+
.filter((option) => !option.hidden)
|
|
768
|
+
.map((option) => option.value);
|
|
769
|
+
const pluginsSelect = $("#included-plugins-select-id")[0];
|
|
770
|
+
params.includedPlugins = Array.from(pluginsSelect.options || []).map(
|
|
771
|
+
(option) => option.value
|
|
772
|
+
);
|
|
773
|
+
const indicator = $(".sc-ajax-indicator");
|
|
774
|
+
indicator.attr("title", "Saving the configuration");
|
|
775
|
+
indicator.attr("style", "display: inline-block;");
|
|
776
|
+
const icon = $(".fa-save, .fa-exclamation-triangle");
|
|
777
|
+
icon.attr("class", "fas fa-save");
|
|
778
|
+
const setErrorIcon = () => {
|
|
779
|
+
icon.attr("class", "fas fa-exclamation-triangle");
|
|
780
|
+
icon.attr("style", "color: #ff0033!important;");
|
|
781
|
+
indicator.attr("title", "Unable to save the configuration");
|
|
782
|
+
};
|
|
783
|
+
$.ajax("/admin/mobile-app/save-config", {
|
|
784
|
+
type: "POST",
|
|
785
|
+
data: params,
|
|
786
|
+
success: function (res) {
|
|
787
|
+
if (res.success) indicator.attr("style", "display: none;");
|
|
788
|
+
else setErrorIcon();
|
|
789
|
+
},
|
|
790
|
+
error: function (res) {
|
|
791
|
+
setErrorIcon();
|
|
792
|
+
},
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
|
|
754
796
|
function poll_mobile_build_finished(outDirName, pollCount, orginalBtnHtml) {
|
|
755
797
|
$.ajax("/admin/build-mobile-app/finished", {
|
|
756
798
|
type: "GET",
|
|
@@ -898,26 +940,32 @@ function move_to_synched() {
|
|
|
898
940
|
const opts = $("#unsynched-tbls-select-id");
|
|
899
941
|
$("#synched-tbls-select-id").removeAttr("selected");
|
|
900
942
|
for (const selected of opts.val()) {
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
943
|
+
$(`[id='${selected}_unsynched_opt']`).remove();
|
|
944
|
+
$("#synched-tbls-select-id").append(
|
|
945
|
+
$("<option>", {
|
|
946
|
+
value: selected,
|
|
947
|
+
label: selected,
|
|
948
|
+
id: `${selected}_synched_opt`,
|
|
949
|
+
})
|
|
950
|
+
);
|
|
907
951
|
}
|
|
952
|
+
$("#buildMobileAppForm").trigger("change");
|
|
908
953
|
}
|
|
909
954
|
|
|
910
955
|
function move_to_unsynched() {
|
|
911
956
|
const opts = $("#synched-tbls-select-id");
|
|
912
957
|
$("#unsynched-tbls-select-id").removeAttr("selected");
|
|
913
958
|
for (const selected of opts.val()) {
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
959
|
+
$(`[id='${selected}_synched_opt']`).remove();
|
|
960
|
+
$("#unsynched-tbls-select-id").append(
|
|
961
|
+
$("<option>", {
|
|
962
|
+
value: selected,
|
|
963
|
+
label: selected,
|
|
964
|
+
id: `${selected}_unsynched_opt`,
|
|
965
|
+
})
|
|
966
|
+
);
|
|
920
967
|
}
|
|
968
|
+
$("#buildMobileAppForm").trigger("change");
|
|
921
969
|
}
|
|
922
970
|
|
|
923
971
|
function move_plugin_to_included() {
|
|
@@ -933,6 +981,7 @@ function move_plugin_to_included() {
|
|
|
933
981
|
})
|
|
934
982
|
);
|
|
935
983
|
}
|
|
984
|
+
$("#buildMobileAppForm").trigger("change");
|
|
936
985
|
}
|
|
937
986
|
|
|
938
987
|
function move_plugin_to_excluded() {
|
|
@@ -948,6 +997,7 @@ function move_plugin_to_excluded() {
|
|
|
948
997
|
})
|
|
949
998
|
);
|
|
950
999
|
}
|
|
1000
|
+
$("#buildMobileAppForm").trigger("change");
|
|
951
1001
|
}
|
|
952
1002
|
|
|
953
1003
|
function toggle_tbl_sync() {
|
package/routes/actions.js
CHANGED
|
@@ -375,6 +375,7 @@ router.get(
|
|
|
375
375
|
|
|
376
376
|
const form = await triggerForm(req, trigger);
|
|
377
377
|
form.values = trigger;
|
|
378
|
+
form.onChange = `saveAndContinue(this)`;
|
|
378
379
|
send_events_page({
|
|
379
380
|
res,
|
|
380
381
|
req,
|
|
@@ -383,6 +384,7 @@ router.get(
|
|
|
383
384
|
contents: {
|
|
384
385
|
type: "card",
|
|
385
386
|
title: req.__("Edit trigger %s", id),
|
|
387
|
+
titleAjaxIndicator: true,
|
|
386
388
|
contents: renderForm(form, req.csrfToken()),
|
|
387
389
|
},
|
|
388
390
|
});
|
|
@@ -464,6 +466,10 @@ router.post(
|
|
|
464
466
|
...form.values.configuration,
|
|
465
467
|
};
|
|
466
468
|
await Trigger.update(trigger.id, form.values); //{configuration: form.values});
|
|
469
|
+
if (req.xhr) {
|
|
470
|
+
res.json({ success: "ok" });
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
467
473
|
req.flash("success", req.__("Action information saved"));
|
|
468
474
|
res.redirect(`/actions/`);
|
|
469
475
|
}
|
|
@@ -668,6 +674,7 @@ router.get(
|
|
|
668
674
|
// get configuration fields
|
|
669
675
|
const cfgFields = await getActionConfigFields(action, table, {
|
|
670
676
|
mode: "trigger",
|
|
677
|
+
when_trigger: trigger.when_trigger,
|
|
671
678
|
});
|
|
672
679
|
// create form
|
|
673
680
|
const form = new Form({
|
|
@@ -720,6 +727,7 @@ router.post(
|
|
|
720
727
|
} else {
|
|
721
728
|
const cfgFields = await getActionConfigFields(action, table, {
|
|
722
729
|
mode: "trigger",
|
|
730
|
+
when_trigger: trigger.when_trigger,
|
|
723
731
|
});
|
|
724
732
|
form = new Form({
|
|
725
733
|
action: `/actions/configure/${id}`,
|