@saltcorn/server 0.7.3-beta.7 → 0.7.4-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/auth/admin.js CHANGED
@@ -381,7 +381,8 @@ router.post(
381
381
  } else {
382
382
  await save_config_from_form(form);
383
383
  req.flash("success", req.__("User settings updated"));
384
- res.redirect("/useradmin/settings");
384
+ if (!req.xhr) res.redirect("/useradmin/settings");
385
+ else res.json({ success: "ok" });
385
386
  }
386
387
  })
387
388
  );
@@ -530,7 +531,7 @@ router.get(
530
531
  send_users_page({
531
532
  res,
532
533
  req,
533
- active_sub: "Settings",
534
+ active_sub: "SSL",
534
535
  contents: {
535
536
  type: "card",
536
537
  title: req.__("Authentication settings"),
@@ -556,7 +557,7 @@ router.post(
556
557
  send_users_page({
557
558
  res,
558
559
  req,
559
- active_sub: "Settings",
560
+ active_sub: "SSL",
560
561
  contents: {
561
562
  type: "card",
562
563
  title: req.__("Authentication settings"),
@@ -572,7 +573,9 @@ router.post(
572
573
  " " +
573
574
  a({ href: "/admin/system" }, req.__("Restart here"))
574
575
  );
575
- res.redirect("/useradmin/ssl");
576
+ if (!req.xhr) {
577
+ res.redirect("/useradmin/ssl");
578
+ } else res.json({ success: "ok" });
576
579
  }
577
580
  })
578
581
  );
@@ -690,7 +693,8 @@ router.post(
690
693
  } = form.values;
691
694
  if (id) {
692
695
  try {
693
- await db.update("users", { email, role_id, ...rest }, id);
696
+ const u = await User.findOne({ id });
697
+ await u.update({ email, role_id, ...rest });
694
698
  req.flash("success", req.__(`User %s saved`, email));
695
699
  } catch (e) {
696
700
  req.flash("error", req.__(`Error editing user: %s`, e.message));
package/auth/routes.js CHANGED
@@ -199,8 +199,7 @@ const getAuthLinks = (current, noMethods) => {
199
199
  return links;
200
200
  };
201
201
 
202
- const loginWithJwt = async (req, res) => {
203
- const { email, password } = req.query;
202
+ const loginWithJwt = async (email, password, res) => {
204
203
  const user = await User.findOne({ email });
205
204
  if (user && user.checkPassword(password)) {
206
205
  const now = new Date();
@@ -208,7 +207,13 @@ const loginWithJwt = async (req, res) => {
208
207
  const token = jwt.sign(
209
208
  {
210
209
  sub: email,
211
- role_id: user.role_id,
210
+ user: {
211
+ id: user.id,
212
+ email: user.email,
213
+ role_id: user.role_id,
214
+ language: user.language ? user.language : "en",
215
+ disabled: user.disabled,
216
+ },
212
217
  iss: "saltcorn@saltcorn",
213
218
  aud: "saltcorn-mobile-app",
214
219
  iat: now.valueOf(),
@@ -217,6 +222,10 @@ const loginWithJwt = async (req, res) => {
217
222
  );
218
223
  if (!user.last_mobile_login) await user.updateLastMobileLogin(now);
219
224
  res.json(token);
225
+ } else {
226
+ res.json({
227
+ alerts: [{ type: "danger", msg: "Incorrect user or password" }],
228
+ });
220
229
  }
221
230
  };
222
231
 
@@ -900,8 +909,8 @@ router.post(
900
909
  } else {
901
910
  const u = await User.create({ email, password });
902
911
  await send_verification_email(u, req);
903
-
904
- signup_login_with_user(u, req, res);
912
+ if (req.smr) await loginWithJwt(email, password, res);
913
+ else signup_login_with_user(u, req, res);
905
914
  }
906
915
  }
907
916
  })
@@ -1008,7 +1017,8 @@ router.get(
1008
1017
  error_catcher(async (req, res, next) => {
1009
1018
  const { method } = req.params;
1010
1019
  if (method === "jwt") {
1011
- await loginWithJwt(req, res);
1020
+ const { email, password } = req.query;
1021
+ await loginWithJwt(email, password, res);
1012
1022
  } else {
1013
1023
  const auth = getState().auth_methods[method];
1014
1024
  if (auth) {
package/errors.js CHANGED
@@ -7,55 +7,58 @@ const { pre, p, text, h3 } = require("@saltcorn/markup/tags");
7
7
  const Crash = require("@saltcorn/data/models/crash");
8
8
  const { getState } = require("@saltcorn/data/db/state");
9
9
 
10
- module.exports =
11
- /**
12
- *
13
- * @param {object} err
14
- * @param {object} req
15
- * @param {object} res
16
- * @param {*} next
17
- * @returns {Promise<void>}
18
- */
19
- async function (err, req, res, next) {
20
- if (!req.__) req.__ = (s) => s;
10
+ module.exports =
11
+ /**
12
+ *
13
+ * @param {object} err
14
+ * @param {object} req
15
+ * @param {object} res
16
+ * @param {*} next
17
+ * @returns {Promise<void>}
18
+ */
19
+ async function (err, req, res, next) {
20
+ if (!req.__) req.__ = (s) => s;
21
21
 
22
- const devmode = getState().getConfig("development_mode", false);
23
- const log_sql = getState().getConfig("log_sql", false);
24
- const role = (req.user || {}).role_id || 10;
25
- if (err.message && err.message.includes("invalid csrf token")) {
26
- console.error(err.message);
22
+ const devmode = getState().getConfig("development_mode", false);
23
+ const log_sql = getState().getConfig("log_sql", false);
24
+ const role = (req.user || {}).role_id || 10;
25
+ if (err.message && err.message.includes("invalid csrf token")) {
26
+ console.error(err.message);
27
27
 
28
- req.flash("error", req.__("Invalid form data, try again"));
29
- if (req.url && req.url.includes("/auth/login")) res.redirect("/auth/login");
30
- else res.redirect("/");
31
- return;
32
- }
33
- const code = err.httpCode || 500;
34
- const headline = err.headline || "An error occurred";
35
- const severity = err.severity || 2;
36
- const createCrash = severity <= 3;
37
- console.error(err.stack);
38
- if (!(devmode && log_sql) && createCrash) await Crash.create(err, req);
28
+ req.flash("error", req.__("Invalid form data, try again"));
29
+ if (req.url && req.url.includes("/auth/login"))
30
+ res.redirect("/auth/login");
31
+ else res.redirect("/");
32
+ return;
33
+ }
34
+ const code = err.httpCode || 500;
35
+ const headline = err.headline || "An error occurred";
36
+ const severity = err.severity || 2;
37
+ const createCrash = severity <= 3;
38
+ //console.error(err.stack);
39
+ if (!(devmode && log_sql) && createCrash) await Crash.create(err, req);
39
40
 
40
- if (req.xhr) {
41
- res
42
- .status(code)
43
- .send(
44
- devmode || role === 1 ? text(err.message) : req.__("An error occurred")
45
- );
46
- } else
47
- res
48
- .status(code)
49
- .sendWrap(
50
- req.__(headline),
51
- devmode ? pre(text(err.stack)) : h3(req.__(headline)),
52
- role === 1 && !devmode ? pre(text(err.message)) : "",
53
- createCrash
54
- ? p(
55
- req.__(
56
- `A report has been logged and a team of bug-squashing squirrels has been dispatched to deal with the situation.`
41
+ if (req.xhr) {
42
+ res
43
+ .status(code)
44
+ .send(
45
+ devmode || role === 1
46
+ ? text(err.message)
47
+ : req.__("An error occurred")
48
+ );
49
+ } else
50
+ res
51
+ .status(code)
52
+ .sendWrap(
53
+ req.__(headline),
54
+ devmode ? pre(text(err.stack)) : h3(req.__(headline)),
55
+ role === 1 && !devmode ? pre(text(err.message)) : "",
56
+ createCrash
57
+ ? p(
58
+ req.__(
59
+ `A report has been logged and a team of bug-squashing squirrels has been dispatched to deal with the situation.`
60
+ )
57
61
  )
58
- )
59
- : ""
60
- );
61
- };
62
+ : ""
63
+ );
64
+ };
package/locales/en.json CHANGED
@@ -920,5 +920,33 @@
920
920
  "Download automated backup": "Download automated backup",
921
921
  "Restoring automated backup": "Restoring automated backup",
922
922
  "No errors detected during configuration check": "No errors detected during configuration check",
923
- "%s view - %s on %s": "%s view - %s on %s"
923
+ "%s view - %s on %s": "%s view - %s on %s",
924
+ "Please select at least one platform (android or iOS).": "Please select at least one platform (android or iOS).",
925
+ "Back": "Back",
926
+ "Periodic snapshots enabled": "Periodic snapshots enabled",
927
+ "Snapshot will be made every hour if there are changes": "Snapshot will be made every hour if there are changes",
928
+ "Snapshots": "Snapshots",
929
+ "Snapshot settings updated": "Snapshot settings updated",
930
+ "Download snapshots": "Download snapshots",
931
+ "Snapshot successful": "Snapshot successful",
932
+ "System logging verbosity": "System logging verbosity",
933
+ "Destination URL Formula": "Destination URL Formula",
934
+ "Pattern": "Pattern",
935
+ "View pattern": "View pattern",
936
+ "The view pattern sets the foundation of how the view relates to the table and the behaviour of the view": "The view pattern sets the foundation of how the view relates to the table and the behaviour of the view",
937
+ "Views display data from tables. A view is a view pattern applied to a table, with configuration.": "Views display data from tables. A view is a view pattern applied to a table, with configuration.",
938
+ "Modules": "Modules",
939
+ "Module installation and control": "Module installation and control",
940
+ "Module store": "Module store",
941
+ "Module": "Module",
942
+ "View patterns": "View patterns",
943
+ "%s module information": "%s module information",
944
+ "Upgrade installed modules": "Upgrade installed modules",
945
+ "Add another module": "Add another module",
946
+ "Add module": "Add module",
947
+ "Module name": "Module name",
948
+ "Source of module for install. Few options:npm - download from npm repository,local - get from local file system,github - download from github,git - get from git": "Source of module for install. Few options:npm - download from npm repository,local - get from local file system,github - download from github,git - get from git",
949
+ "Version of module, latest is default value": "Version of module, latest is default value",
950
+ "For npm - name of npm package, e.g. @saltcorn/html or saltcorn-gantt, check at npmjs.com, for local - absolute path to module folder in file system, e.g. C:\\gitsrc\\any-bootstrap-theme\\, for github - name of github project.": "For npm - name of npm package, e.g. @saltcorn/html or saltcorn-gantt, check at npmjs.com, for local - absolute path to module folder in file system, e.g. C:\\gitsrc\\any-bootstrap-theme\\, for github - name of github project.",
951
+ "Modules up-to-date": "Modules up-to-date"
924
952
  }
package/locales/it.json CHANGED
@@ -478,5 +478,6 @@
478
478
  "Generate": "Generate",
479
479
  "Two-factor authentication": "Two-factor authentication",
480
480
  "Two-factor authentication is disabled": "Two-factor authentication is disabled",
481
- "Enable TWA": "Enable TWA"
481
+ "Enable TWA": "Enable TWA",
482
+ "Modules": "Modules"
482
483
  }
package/locales/ru.json CHANGED
@@ -26,7 +26,7 @@
26
26
  "ID": "ID",
27
27
  "Email": "Email",
28
28
  "Role": "Роль",
29
- "View": "Посмотреть",
29
+ "View": "Представление",
30
30
  "Delete": "Удалить",
31
31
  "Add user": "Создать пользователя",
32
32
  "New user": "Новый пользователь",
@@ -783,15 +783,51 @@
783
783
  "Disable TWA": "Отключить TWA",
784
784
  "Enable TWA": "Включить TWA",
785
785
  "Deleted all rows": "Удалены все строки",
786
- "Use this link: <a href=\"%s\">%s</a> to revisit your application at any time.": "В дальнешем используйте ссылку: <a href=\"%s\">%s</a> для входа в созданное приложение.",
786
+ "Use this link: <a href=\"%s\">%s</a> to revisit your application at any time.": "В дальнейшем используйте ссылку: <a href=\"%s\">%s</a> для входа в созданное приложение.",
787
787
  "To login to a previously created application, go to: ": "Чтобы авторизоваться в ранее созданном приложении, перейдите по ссылке: ",
788
788
  "Has channels?": "Связано с каналом?",
789
789
  "Menu, search, languages and tenants": "Меню, поиск, языки и подсайты(тенанты)",
790
790
  "Images and other files for download": "Изображения и другие файлы для загрузки",
791
791
  "Channels to create events for. Separate by comma; leave blank for all": "Каналы, для которых создаются собятия. Разделяются ; Не заполняйте, чтобы использовать события для всех каналов",
792
792
  "Event Name": "Имя события",
793
- "Plugins (Extensions) Store endpoint": "Plugins (Extensions) Store endpoint",
794
- "Packs Store endpoint": "Packs Store endpoint",
795
- "The endpoint of plugins store.": "The endpoint of plugins store.",
796
- "The endpoint of packs store.": "The endpoint of packs store."
793
+ "Plugins (Extensions) Store endpoint": "Адрес (endpoint) магазина плагинов",
794
+ "Packs Store endpoint": "Адрес (endpoint) магазина паков",
795
+ "The endpoint of plugins store.": "Адрес (endpoint) магазина плагинов.",
796
+ "The endpoint of packs store.": "Адрес (endpoint) магазина паков.",
797
+ "Modules": "Модули",
798
+ "Frequency": "Регулярность",
799
+ "Destination": "Местоположение",
800
+ "Directory": "Папка",
801
+ "Expiration in days": "Срок хранения (в днях)",
802
+ "Delete old backup files in this directory after the set number of days": "Старые резервные копии в этой папке будут удалять после истечения срока хранения ",
803
+ "Backup settings updated": "Настройки резервного копирования обновлены",
804
+ "Periodic snapshots enabled": "Регулярные снимки (снэпшоты) активированы",
805
+ "Snapshot will be made every hour if there are changes": "Снимки (снэпшоты) будут выполняться каждый час",
806
+ "Manual backup": "Ручное резервное копирование",
807
+ "Automated backup": "Автоматическое резервное копирование",
808
+ "Snapshots": "Снимки (снэпшоты)",
809
+ "Mobile app": "Мобильное приложение",
810
+ "Module store": "Магазин модулей",
811
+ "Upgrade installed modules": "Обновить установленные модули",
812
+ "Add another module": "Добавить модуль",
813
+ "Module": "Модуль",
814
+ "Module installation and control": "Установка и управление модулями",
815
+ "System logging verbosity": "Уровень логирования системы",
816
+ "Source of module for install. Few options:npm - download from npm repository,local - get from local file system,github - download from github,git - get from git": "Источник для установки модуля:npm - загрузка из репозитория npm,local - установка из локальной файловой системы,github - загрузка из github,git - загрузка из git",
817
+ "Version of module, latest is default value": "Версия модуля, значение по-умолчанию latest",
818
+ "For npm - name of npm package, e.g. @saltcorn/html or saltcorn-gantt, check at npmjs.com, for local - absolute path to module folder in file system, e.g. C:\\gitsrc\\any-bootstrap-theme\\, for github - name of github project.": "для npm - имя npm пактеа, например, @saltcorn/html или saltcorn-gantt, см. npmjs.com, для local - абсолютный путь к папке модуля в локальной файловой системе, например, C:\\gitsrc\\any-bootstrap-theme\\, для github - имя проекта github.",
819
+ "Modules up-to-date": "Модули обновлены до актуальной версии",
820
+ "Add module": "Добавить модуль",
821
+ "Module name": "Имя модуля",
822
+ "Build mobile app": "Создать мобильное приложение",
823
+ "Please select at least one platform (android or iOS).": "Пожалуйста выберите как минимум одну платформу (android или iOS).",
824
+ "Please enter a valid server URL.": "Пожалуйста введите корректный URL сервера.",
825
+ "Only the android build supports docker.": "Только сборка для android поддерживает docker.",
826
+ "Entry point": "Точка входа в приложение",
827
+ "Platform": "Платформа",
828
+ "docker": "docker",
829
+ "App file": "Файл приложения",
830
+ "Server URL": "URL сервера",
831
+ "android": "android",
832
+ "iOS": "iOS"
797
833
  }
package/locales/zh.json CHANGED
@@ -179,7 +179,7 @@
179
179
  "Pack %s installed": "已安装包 %s",
180
180
  "Pack %s uninstalled": "包 %s 已卸载",
181
181
  "Uninstall": "卸载",
182
- "Result preview for ": "结果预览", // todo
182
+ "Result preview for ": "结果预览",
183
183
  "Choose views for <a href=\"/search\">search results</a> for each table.<br/>Set to blank to omit table from global search.": "为每个表选择<a href=\"/search\">搜索结果</a>的视图。<br/>为空则可从全局搜索中忽略表。",
184
184
  "These tables lack suitable views: ": "这些表缺少合适的视图:",
185
185
  "Search configuration": "搜索配置",
package/markup/admin.js CHANGED
@@ -345,7 +345,7 @@ const flash_restart = (req) => {
345
345
  * @param {*} opts.formArgs
346
346
  * @returns {Promise<Form>}
347
347
  */
348
- const config_fields_form = async ({ field_names, req, ...formArgs }) => {
348
+ const config_fields_form = async ({ field_names, req, action, ...formArgs }) => {
349
349
  const values = {};
350
350
  const state = getState();
351
351
  const fields = [];
@@ -396,8 +396,9 @@ const config_fields_form = async ({ field_names, req, ...formArgs }) => {
396
396
  const form = new Form({
397
397
  fields,
398
398
  values,
399
- submitButtonClass: "btn-outline-primary",
400
- onChange: "remove_outline(this)",
399
+ action,
400
+ noSubmitButton: true,
401
+ onChange: `saveAndContinue(this)`,
401
402
  ...formArgs,
402
403
  });
403
404
  await form.fill_fkey_options();
@@ -87,7 +87,7 @@ const plugin_functions_info_card = (plugin, req) => ({
87
87
  */
88
88
  const plugin_viewtemplates_info_card = (plugin, req) => ({
89
89
  type: "card",
90
- title: req.__("View templates"),
90
+ title: req.__("View patterns"),
91
91
  contents: withCfg(plugin, "viewtemplates", [])
92
92
  .map(({ name, description }) => div(h4(name), p(description)))
93
93
  .join("<hr>"),
@@ -101,10 +101,10 @@ const showRepository = (repo) =>
101
101
  !repo
102
102
  ? repo
103
103
  : repo.url
104
- ? link(repo.url, repo.url)
105
- : repo.startsWith && repo.startsWith("github:")
106
- ? link(repo.replace("github:", "https://github.com/"), repo)
107
- : repo;
104
+ ? link(repo.url, repo.url)
105
+ : repo.startsWith && repo.startsWith("github:")
106
+ ? link(repo.replace("github:", "https://github.com/"), repo)
107
+ : repo;
108
108
 
109
109
  module.exports = {
110
110
  plugin_types_info_card,
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@saltcorn/server",
3
- "version": "0.7.3-beta.7",
3
+ "version": "0.7.4-beta.1",
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.7.3-beta.7",
10
- "@saltcorn/builder": "0.7.3-beta.7",
11
- "@saltcorn/data": "0.7.3-beta.7",
12
- "@saltcorn/admin-models": "0.7.3-beta.7",
13
- "@saltcorn/markup": "0.7.3-beta.7",
14
- "@saltcorn/sbadmin2": "0.7.3-beta.7",
9
+ "@saltcorn/base-plugin": "0.7.4-beta.1",
10
+ "@saltcorn/builder": "0.7.4-beta.1",
11
+ "@saltcorn/data": "0.7.4-beta.1",
12
+ "@saltcorn/admin-models": "0.7.4-beta.1",
13
+ "@saltcorn/markup": "0.7.4-beta.1",
14
+ "@saltcorn/sbadmin2": "0.7.4-beta.1",
15
15
  "@socket.io/cluster-adapter": "^0.1.0",
16
16
  "@socket.io/sticky": "^1.0.1",
17
17
  "aws-sdk": "^2.1037.0",
@@ -153,7 +153,7 @@ function MenuEditor(e, t) {
153
153
  }
154
154
  });
155
155
  })((n = $(this).closest("li")));
156
- l.onUpdate();
156
+ //l.onUpdate();
157
157
  }),
158
158
  s.on("click", ".btnUp", function (e) {
159
159
  e.preventDefault();
@@ -364,3 +364,78 @@ Copyright (c) 2017 Taha Paksu
364
364
  .dropdown-menu.searchbar-dropdown.show {
365
365
  transform: translate(0px, 40px);
366
366
  }
367
+
368
+ .tippy-box[data-animation="fade"][data-state="hidden"] {
369
+ opacity: 0;
370
+ }
371
+ [data-tippy-root] {
372
+ max-width: calc(100vw - 10px);
373
+ }
374
+ .tippy-box {
375
+ position: relative;
376
+ background-color: #333;
377
+ color: #fff;
378
+ border-radius: 4px;
379
+ font-size: 14px;
380
+ line-height: 1.4;
381
+ white-space: normal;
382
+ outline: 0;
383
+ transition-property: transform, visibility, opacity;
384
+ }
385
+ .tippy-box[data-placement^="top"] > .tippy-arrow {
386
+ bottom: 0;
387
+ }
388
+ .tippy-box[data-placement^="top"] > .tippy-arrow:before {
389
+ bottom: -7px;
390
+ left: 0;
391
+ border-width: 8px 8px 0;
392
+ border-top-color: initial;
393
+ transform-origin: center top;
394
+ }
395
+ .tippy-box[data-placement^="bottom"] > .tippy-arrow {
396
+ top: 0;
397
+ }
398
+ .tippy-box[data-placement^="bottom"] > .tippy-arrow:before {
399
+ top: -7px;
400
+ left: 0;
401
+ border-width: 0 8px 8px;
402
+ border-bottom-color: initial;
403
+ transform-origin: center bottom;
404
+ }
405
+ .tippy-box[data-placement^="left"] > .tippy-arrow {
406
+ right: 0;
407
+ }
408
+ .tippy-box[data-placement^="left"] > .tippy-arrow:before {
409
+ border-width: 8px 0 8px 8px;
410
+ border-left-color: initial;
411
+ right: -7px;
412
+ transform-origin: center left;
413
+ }
414
+ .tippy-box[data-placement^="right"] > .tippy-arrow {
415
+ left: 0;
416
+ }
417
+ .tippy-box[data-placement^="right"] > .tippy-arrow:before {
418
+ left: -7px;
419
+ border-width: 8px 8px 8px 0;
420
+ border-right-color: initial;
421
+ transform-origin: center right;
422
+ }
423
+ .tippy-box[data-inertia][data-state="visible"] {
424
+ transition-timing-function: cubic-bezier(0.54, 1.5, 0.38, 1.11);
425
+ }
426
+ .tippy-arrow {
427
+ width: 16px;
428
+ height: 16px;
429
+ color: #333;
430
+ }
431
+ .tippy-arrow:before {
432
+ content: "";
433
+ position: absolute;
434
+ border-color: transparent;
435
+ border-style: solid;
436
+ }
437
+ .tippy-content {
438
+ position: relative;
439
+ padding: 5px 9px;
440
+ z-index: 1;
441
+ }
@@ -39,16 +39,26 @@ function apply_showif() {
39
39
  $("[data-show-if]").each(function (ix, element) {
40
40
  var e = $(element);
41
41
  try {
42
- var to_show = new Function(
43
- "e",
44
- "return " + decodeURIComponent(e.attr("data-show-if"))
45
- );
42
+ let to_show = e.data("data-show-if-fun");
43
+ if (!to_show) {
44
+ to_show = new Function(
45
+ "e",
46
+ "return " + decodeURIComponent(e.attr("data-show-if"))
47
+ );
48
+ e.data("data-show-if-fun", to_show);
49
+ }
50
+ if (!e.data("data-closest-form-ns"))
51
+ e.data("data-closest-form-ns", e.closest(".form-namespace"));
46
52
  if (to_show(e))
47
53
  e.show()
48
54
  .find("input, textarea, button, select")
49
55
  .prop("disabled", e.attr("data-disabled") || false);
50
56
  else
51
- e.hide().find("input, textarea, button, select").prop("disabled", true);
57
+ e.hide()
58
+ .find(
59
+ "input:enabled, textarea:enabled, button:enabled, select:enabled"
60
+ )
61
+ .prop("disabled", true);
52
62
  } catch (e) {
53
63
  console.error(e);
54
64
  }
@@ -111,7 +121,12 @@ function apply_showif() {
111
121
  `<option ${
112
122
  `${current}` === `${r[dynwhere.refname]}` ? "selected" : ""
113
123
  } value="${r[dynwhere.refname]}">${
114
- r[dynwhere.summary_field]
124
+ dynwhere.label_formula
125
+ ? new Function(
126
+ `{${Object.keys(r).join(",")}}`,
127
+ "return " + dynwhere.label_formula
128
+ )(r)
129
+ : r[dynwhere.summary_field]
115
130
  }</option>`
116
131
  )
117
132
  );
@@ -502,7 +517,7 @@ function common_done(res, isWeb = true) {
502
517
  }
503
518
  }
504
519
 
505
- const repeaterCopyValuesToForm = (form, editor) => {
520
+ const repeaterCopyValuesToForm = (form, editor, noTriggerChange) => {
506
521
  const vs = JSON.parse(editor.getString());
507
522
 
508
523
  const setVal = (k, ix, v) => {
@@ -510,7 +525,7 @@ const repeaterCopyValuesToForm = (form, editor) => {
510
525
  if ($e.length) $e.val(v);
511
526
  else
512
527
  form.append(
513
- `<input type="hidden" name="${k}_${ix}" value="${v}"></input>`
528
+ `<input type="hidden" data-repeater-ix="${ix}" name="${k}_${ix}" value="${v}"></input>`
514
529
  );
515
530
  };
516
531
  vs.forEach((v, ix) => {
@@ -521,8 +536,8 @@ const repeaterCopyValuesToForm = (form, editor) => {
521
536
  });
522
537
  });
523
538
  //delete
524
- //for (let ix = vs.length; ix < vs.length + 20; ix++) {
525
- // $(`input[name="${k}_${ix}"]`).remove();
539
+ //for (let ix = vs.length; ix < vs.length + 5; ix++) {
540
+ // $(`input[data-repeater-ix="${ix}"]`).remove();
526
541
  //}
527
542
  $(`input[type=hidden]`).each(function () {
528
543
  const name = $(this).attr("name");
@@ -533,6 +548,7 @@ const repeaterCopyValuesToForm = (form, editor) => {
533
548
  if (typeof ix !== "number" || isNaN(ix)) return;
534
549
  if (ix >= vs.length) $(this).remove();
535
550
  });
551
+ !noTriggerChange && form.trigger("change");
536
552
  };
537
553
  function align_dropdown(id) {
538
554
  setTimeout(() => {
@@ -319,4 +319,8 @@ table.table-inner-grid, table.table-inner-grid th, table.table-inner-grid td {
319
319
  .editStarRating input:checked + label,
320
320
  .editStarRating input:checked + label ~ label {
321
321
  color: #ffc107;
322
+ }
323
+
324
+ .CodeMirror {
325
+ resize: vertical;
322
326
  }
@@ -213,6 +213,7 @@ function ajax_modal(url, opts = {}) {
213
213
  (opts.onOpen || function () {})(res);
214
214
  $("#scmodal").on("hidden.bs.modal", function (e) {
215
215
  (opts.onClose || function () {})(res);
216
+ $("body").css("overflow", "");
216
217
  });
217
218
  },
218
219
  });
@@ -248,7 +249,7 @@ function saveAndContinue(e, k) {
248
249
  return false;
249
250
  }
250
251
 
251
- function applyViewConfig(e, url) {
252
+ function applyViewConfig(e, url, k) {
252
253
  var form = $(e).closest("form");
253
254
  var form_data = form.serializeArray();
254
255
  const cfg = {};
@@ -264,6 +265,9 @@ function applyViewConfig(e, url) {
264
265
  },
265
266
  data: JSON.stringify(cfg),
266
267
  error: function (request) {},
268
+ success: function (res) {
269
+ k && k(res);
270
+ },
267
271
  });
268
272
 
269
273
  return false;