@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 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 = contract(
114
- is.fun(
115
- [is.obj({}), is.maybe(is.class("User"))],
116
- is.promise(is.class("Form"))
117
- ),
118
- async (req, user) => {
119
- const roleField = new Field({
120
- label: req.__("Role"),
121
- name: "role_id",
122
- type: "Key",
123
- reftable_name: "roles",
124
- });
125
- const roles = (await User.get_roles()).filter((r) => r.role !== "public");
126
- roleField.options = roles.map((r) => ({ label: r.role, value: r.id }));
127
- const can_reset = getState().getConfig("smtp_host", "") !== "";
128
- const userFields = await getUserFields(req);
129
- const form = new Form({
130
- fields: [roleField, ...userFields],
131
- action: "/useradmin/save",
132
- submitLabel: user ? req.__("Save") : req.__("Create"),
133
- });
134
- if (!user) {
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.__("Set random password"),
138
- name: "rnd_password",
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: req.__("Restart required for changes to take effect."),
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({ name: loc, location: loc, source: "npm" }),
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
- { name: "role", onchange: "form.submit()" },
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.0",
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.0",
11
- "@saltcorn/builder": "0.9.6-beta.0",
12
- "@saltcorn/data": "0.9.6-beta.0",
13
- "@saltcorn/admin-models": "0.9.6-beta.0",
14
- "@saltcorn/filemanager": "0.9.6-beta.0",
15
- "@saltcorn/markup": "0.9.6-beta.0",
16
- "@saltcorn/plugins-loader": "0.9.6-beta.0",
17
- "@saltcorn/sbadmin2": "0.9.6-beta.0",
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
- var current = e.attr("data-selected");
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
- if (!dynwhere.required)
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
- typeof value !== "undefined" ? ` value="${value}"` : ""
240
- }>${label || ""}</option>`
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, viewname, isWeb = true) {
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, viewname, isWeb);
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, viewname, isWeb);
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, viewname, isWeb);
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
- `form[data-viewname="${res.set_fields._viewname || viewname}"]`
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 = "javascript:void(0)";
1505
+ var formAction = form.getAttribute("action");
1506
+ form.setAttribute("action", "javascript:void(0)");
1445
1507
  form.submit();
1446
- form.action = formAction;
1508
+ form.setAttribute("action", formAction);
1447
1509
  }
1448
1510
 
1449
1511
  function unique_field_from_rows(
@@ -506,3 +506,11 @@ tr[onclick] {
506
506
  .modal-header {
507
507
  justify-content: space-between;
508
508
  }
509
+
510
+ ul.katetree {
511
+ list-style-type: none;
512
+ }
513
+
514
+ ul.katetree details ul {
515
+ list-style-type: none;
516
+ }
@@ -236,7 +236,13 @@ function reset_spinners() {
236
236
  });
237
237
  }
238
238
 
239
- function view_post(viewname, route, data, onDone, sendState) {
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, viewname);
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
- const jUnsOpt = $(`[id='${selected}_unsynched_opt']`);
902
- jUnsOpt.attr("hidden", "true");
903
- jUnsOpt.removeAttr("selected");
904
- const jSynOpt = $(`[id='${selected}_synched_opt']`);
905
- jSynOpt.removeAttr("hidden");
906
- jSynOpt.removeAttr("selected");
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
- const jSynOpt = $(`[id='${selected}_synched_opt']`);
915
- jSynOpt.attr("hidden", "true");
916
- jSynOpt.removeAttr("selected");
917
- const jUnsOpt = $(`[id='${selected}_unsynched_opt']`);
918
- jUnsOpt.removeAttr("hidden");
919
- jUnsOpt.removeAttr("selected");
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}`,