@saltcorn/server 1.1.0-beta.9 → 1.1.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.
@@ -40,6 +40,19 @@ $(window).resize(() => {
40
40
  setScreenInfoCookie();
41
41
  });
42
42
 
43
+ function get_current_state_url(e) {
44
+ const localizer = e ? $(e).closest("[data-sc-local-state]") : [];
45
+ let $modal = $("#scmodal");
46
+ if (localizer.length) {
47
+ const localState = localizer.attr("data-sc-local-state") || "";
48
+ return localState;
49
+ } else if ($modal.length === 0 || !$modal.hasClass("show"))
50
+ return getIsNode()
51
+ ? window.location.href
52
+ : parent.saltcorn.mobileApp.navigation.currentUrl();
53
+ else return $modal.prop("data-modal-state");
54
+ }
55
+
43
56
  //avoids hiding in overflow:hidden
44
57
  function init_bs5_dropdowns() {
45
58
  $("body").on(
@@ -704,7 +717,7 @@ function doMobileTransforms() {
704
717
  href: [
705
718
  {
706
719
  web: "javascript:history.back()",
707
- mobile: "javascript:parent.goBack()",
720
+ mobile: "javascript:parent.saltcorn.mobileApp.navigation.goBack()",
708
721
  },
709
722
  {
710
723
  web: "javascript:ajax_modal",
@@ -714,7 +727,7 @@ function doMobileTransforms() {
714
727
  onclick: [
715
728
  {
716
729
  web: "history.back()",
717
- mobile: "parent.goBack()",
730
+ mobile: "parent.saltcorn.mobileApp.navigation.goBack()",
718
731
  },
719
732
  {
720
733
  web: "ajax_modal",
@@ -727,6 +740,34 @@ function doMobileTransforms() {
727
740
  ],
728
741
  };
729
742
 
743
+ // change /plugins or plugins to sc_plugins
744
+ // capacitor reserves the plugins prefix for cordova plugins
745
+ const normalisePluginsPrefix = (path) => {
746
+ if (path.startsWith("/plugins/") || path.startsWith("plugins/"))
747
+ return path.replace(/\/?plugins\//, "sc_plugins/");
748
+ return null;
749
+ };
750
+ $("link").each(function () {
751
+ const path = $(this).attr("href");
752
+ if (path) {
753
+ const newPath = normalisePluginsPrefix(path);
754
+ if (newPath) {
755
+ $(this).attr("href", newPath);
756
+ console.log("transformed link", path, newPath);
757
+ }
758
+ }
759
+ });
760
+ $("script").each(function () {
761
+ const path = $(this).attr("src");
762
+ if (path) {
763
+ const newPath = normalisePluginsPrefix(path);
764
+ if (newPath) {
765
+ $(this).attr("src", newPath);
766
+ console.log("transformed script", path, newPath);
767
+ }
768
+ }
769
+ });
770
+
730
771
  $("a").each(function () {
731
772
  let path = $(this).attr("href") || "";
732
773
  if (path.startsWith("http")) {
@@ -807,48 +848,46 @@ function doMobileTransforms() {
807
848
  });
808
849
 
809
850
  $("[mobile-img-path]").each(async function () {
810
- if (parent.loadEncodedFile) {
811
- const fileId = $(this).attr("mobile-img-path");
812
- const base64Encoded = await parent.loadEncodedFile(fileId);
813
- this.src = base64Encoded;
814
- }
851
+ const fileId = $(this).attr("mobile-img-path");
852
+ const base64Encoded =
853
+ await parent.saltcorn.mobileApp.common.loadEncodedFile(fileId);
854
+ this.src = base64Encoded;
815
855
  });
816
856
 
817
857
  $("[mobile-bg-img-path]").each(async function () {
818
- if (parent.loadEncodedFile) {
819
- const fileId = $(this).attr("mobile-bg-img-path");
820
- if (fileId) {
821
- const base64Encoded = await parent.loadEncodedFile(fileId);
822
- this.style.backgroundImage = `url("${base64Encoded}")`;
823
- }
858
+ const fileId = $(this).attr("mobile-bg-img-path");
859
+ if (fileId) {
860
+ const base64Encoded =
861
+ await parent.saltcorn.mobileApp.common.loadEncodedFile(fileId);
862
+ this.style.backgroundImage = `url("${base64Encoded}")`;
824
863
  }
825
864
  });
826
865
 
827
866
  $("img:not([mobile-img-path]):not([mobile-bg-img-path])").each(
828
867
  async function () {
829
- if (parent.loadEncodedFile) {
830
- const jThis = $(this);
831
- const src = jThis.attr("src");
832
- if (src?.includes("/files/serve/")) {
833
- const tokens = src.split("/files/serve/");
834
- if (tokens.length > 1) {
835
- const fileId = tokens[1];
836
- const base64Encoded = await parent.loadEncodedFile(fileId);
837
- this.src = base64Encoded;
838
- }
839
- } else if (src?.includes("/files/resize/")) {
840
- const tokens = src.split("/files/resize/");
841
- if (tokens.length > 1) {
842
- const idAndDims = tokens[1].split("/");
843
- const width = idAndDims[0];
844
- const height = idAndDims.length > 2 ? idAndDims[1] : undefined;
845
- const fileId = idAndDims[idAndDims.length - 1];
846
- const style = { width: `${width || 50}px` };
847
- if (height > 0) style.height = `${height}px`;
848
- const base64Encoded = await parent.loadEncodedFile(fileId);
849
- this.src = base64Encoded;
850
- jThis.css(style);
851
- }
868
+ const jThis = $(this);
869
+ const src = jThis.attr("src");
870
+ if (src?.includes("/files/serve/")) {
871
+ const tokens = src.split("/files/serve/");
872
+ if (tokens.length > 1) {
873
+ const fileId = tokens[1];
874
+ const base64Encoded =
875
+ await parent.saltcorn.mobileApp.common.loadEncodedFile(fileId);
876
+ this.src = base64Encoded;
877
+ }
878
+ } else if (src?.includes("/files/resize/")) {
879
+ const tokens = src.split("/files/resize/");
880
+ if (tokens.length > 1) {
881
+ const idAndDims = tokens[1].split("/");
882
+ const width = idAndDims[0];
883
+ const height = idAndDims.length > 2 ? idAndDims[1] : undefined;
884
+ const fileId = idAndDims[idAndDims.length - 1];
885
+ const style = { width: `${width || 50}px` };
886
+ if (height > 0) style.height = `${height}px`;
887
+ const base64Encoded =
888
+ await parent.saltcorn.mobileApp.common.loadEncodedFile(fileId);
889
+ this.src = base64Encoded;
890
+ jThis.css(style);
852
891
  }
853
892
  }
854
893
  }
@@ -1031,7 +1070,11 @@ function initialize_page() {
1031
1070
  </form>`
1032
1071
  );
1033
1072
  });
1034
- if (!isNode) doMobileTransforms();
1073
+ if (!isNode) {
1074
+ doMobileTransforms();
1075
+ const anchor = parent.saltcorn.mobileApp.navigation.getAnchor();
1076
+ if (anchor) $(`[href="#${anchor}"][data-bs-toggle="tab"]`).tab("show");
1077
+ }
1035
1078
  function setExplainer(that) {
1036
1079
  var id = $(that).attr("id") + "_explainer";
1037
1080
 
@@ -1064,11 +1107,12 @@ function initialize_page() {
1064
1107
  codes.forEach((el) => {
1065
1108
  //console.log($(el).attr("mode"), el);
1066
1109
  if ($(el).hasClass("codemirror-enabled")) return;
1067
-
1068
- const cm = CodeMirror.fromTextArea(el, {
1110
+ const cmOpts = {
1069
1111
  lineNumbers: true,
1070
1112
  mode: $(el).attr("mode"),
1071
- });
1113
+ };
1114
+ if (_sc_lightmode === "dark") cmOpts.theme = "blackboard";
1115
+ const cm = CodeMirror.fromTextArea(el, cmOpts);
1072
1116
  $(el).addClass("codemirror-enabled");
1073
1117
  cm.on(
1074
1118
  "change",
@@ -1139,11 +1183,13 @@ function initialize_page() {
1139
1183
  }
1140
1184
  }
1141
1185
  }
1186
+
1142
1187
  setTimeout(() => {
1143
1188
  $("#toasts-area")
1144
1189
  .find(".show[rendered='server-side'][type='success']")
1145
1190
  .removeClass("show");
1146
1191
  }, 5000);
1192
+
1147
1193
  $(".lazy-accoordion").on("show.bs.collapse", function (e) {
1148
1194
  const $e = $(e.target).find("[data-sc-view-source]");
1149
1195
  if ($.trim($e.html()) == "") {
@@ -1171,7 +1217,6 @@ function initialize_page() {
1171
1217
  $(initialize_page);
1172
1218
 
1173
1219
  function cancel_inline_edit(e, opts1) {
1174
- const isNode = getIsNode();
1175
1220
  var opts = JSON.parse(decodeURIComponent(opts1 || "") || "{}");
1176
1221
  var form = $(e.target).closest("form");
1177
1222
  form.replaceWith(opts.resetHtml);
@@ -1550,14 +1595,15 @@ async function common_done(res, viewnameOrElem, isWeb = true) {
1550
1595
  });
1551
1596
  }
1552
1597
  if (res.eval_js) await handle(res.eval_js, eval_it);
1553
- else if (res.goto) {
1598
+ /// TODO got and resume_workflow - use localStorage
1599
+ if (res.goto) {
1554
1600
  if (!isWeb) {
1555
1601
  const next = new URL(res.goto, "http://localhost");
1556
1602
  const pathname = next.pathname;
1557
1603
  if (pathname.startsWith("/view/") || pathname.startsWith("/page/")) {
1558
1604
  const route = `get${pathname}${next.search ? "?" + next.search : ""}`;
1559
- await parent.handleRoute(route);
1560
- } else parent.cordova.InAppBrowser.open(res.goto, "_system");
1605
+ await parent.saltcorn.mobileApp.navigation.handleRoute(route);
1606
+ } else parent.cordova.InAppBrowser.open(res.goto, "_system"); // TODO
1561
1607
  } else if (res.target === "_blank") window.open(res.goto, "_blank").focus();
1562
1608
  else {
1563
1609
  const prev = new URL(window.location.href);
@@ -1572,6 +1618,9 @@ async function common_done(res, viewnameOrElem, isWeb = true) {
1572
1618
  location.reload();
1573
1619
  }
1574
1620
  }
1621
+ if (res.resume_workflow) {
1622
+ ajax_post_json(`/actions/resume-workflow/${res.resume_workflow}`, {});
1623
+ }
1575
1624
  if (res.reload_page) {
1576
1625
  (isWeb ? location : parent).reload(); //TODO notify to cookie if reload or goto
1577
1626
  }
@@ -85,18 +85,15 @@ div[data-inline-edit-dest-url]:hover .editicon {
85
85
  border-left: none;
86
86
  border-color: #95a5a6;
87
87
  padding-left: 0.3rem;
88
- background-color: #ffffff;
89
88
  }
90
89
 
91
90
  .search-bar input[type="search"] {
92
91
  border-color: #95a5a6;
93
92
  padding-left: 0.3rem;
94
- background-color: #ffffff;
95
93
  }
96
94
 
97
95
  .search-bar button.search-bar {
98
96
  border-color: #95a5a6;
99
- background-color: #ffffff;
100
97
  border-left: 1px solid #95a5a6 !important;
101
98
  border-top: 1px solid #95a5a6 !important;
102
99
  border-bottom: 1px solid #95a5a6 !important;
@@ -358,7 +355,7 @@ table.table-inner-grid td {
358
355
  }
359
356
 
360
357
  .w-unset {
361
- width: unset;
358
+ width: unset !important;
362
359
  }
363
360
 
364
361
  .preview-text {
@@ -610,4 +607,14 @@ button.monospace-copy-btn {
610
607
 
611
608
  i[class^="unicode-"], i[class*=" unicode-"] {
612
609
  font-style: normal;
610
+ }
611
+
612
+ .tabulator.table-dark:not(.thead-light) .tabulator-footer, .tabulator.table-dark:not(.thead-light) .tabulator-footer .tabulator-col {
613
+ background-color: #212529;
614
+ border-color: #32383e;
615
+ color: #fff;
616
+ }
617
+
618
+ .mobile-toast-margin {
619
+ margin-bottom: 1.0rem
613
620
  }
@@ -84,17 +84,6 @@ function removeQueryStringParameter(uri1, key) {
84
84
  return uri + hash;
85
85
  }
86
86
 
87
- function get_current_state_url(e) {
88
- const localizer = e ? $(e).closest("[data-sc-local-state]") : [];
89
- let $modal = $("#scmodal");
90
- if (localizer.length) {
91
- const localState = localizer.attr("data-sc-local-state") || "";
92
- return localState;
93
- } else if ($modal.length === 0 || !$modal.hasClass("show"))
94
- return window.location.href;
95
- else return $modal.prop("data-modal-state");
96
- }
97
-
98
87
  function select_id(id, e) {
99
88
  pjax_to(updateQueryStringParameter(get_current_state_url(e), "id", id), e);
100
89
  }
@@ -423,6 +412,27 @@ function saveAndContinueAsync(e) {
423
412
  });
424
413
  }
425
414
 
415
+ function saveAndContinueIfValid(e, k, event) {
416
+ //wait for applyShowIf
417
+ setTimeout(() => {
418
+ if (
419
+ event &&
420
+ event.target &&
421
+ event.target.classList &&
422
+ event.target.classList.contains("no-form-change")
423
+ )
424
+ return;
425
+ var form = $(e).closest("form");
426
+
427
+ if (form[0].checkValidity?.() === false) {
428
+ form[0].reportValidity();
429
+ return;
430
+ }
431
+
432
+ saveAndContinue(e, k, event);
433
+ });
434
+ }
435
+
426
436
  function saveAndContinue(e, k, event) {
427
437
  if (
428
438
  event &&
@@ -432,6 +442,7 @@ function saveAndContinue(e, k, event) {
432
442
  )
433
443
  return;
434
444
  var form = $(e).closest("form");
445
+
435
446
  let focusedEl = null;
436
447
  if (!event || !event.srcElement) {
437
448
  const el = form.find("select[sc-received-focus]")[0];
@@ -460,6 +471,7 @@ function saveAndContinue(e, k, event) {
460
471
  data: form_data,
461
472
  success: function (res) {
462
473
  ajax_indicator(false);
474
+ form.removeAttr("data-unsaved-changes");
463
475
  form.parent().find(".full-form-error").text("");
464
476
  if (res.id && form.find("input[name=id")) {
465
477
  form.append(
@@ -576,9 +588,10 @@ function updateViewPreview() {
576
588
  }
577
589
  }
578
590
 
579
- function ajaxSubmitForm(e, force_no_reload) {
591
+ function ajaxSubmitForm(e, force_no_reload, event) {
580
592
  var form = $(e).closest("form");
581
593
  var url = form.attr("action");
594
+ if(event) event.preventDefault();
582
595
  $.ajax(url, {
583
596
  type: "POST",
584
597
  headers: {
@@ -890,9 +903,9 @@ function build_mobile_app(button) {
890
903
 
891
904
  if (
892
905
  params.useDocker &&
893
- !window.cordovaBuilderAvailable &&
906
+ !window.capacitorBuilderAvailable &&
894
907
  !confirm(
895
- "Docker is selected but the Cordova builder seems not to be installed. " +
908
+ "Docker is selected but the Capacitor builder seems not to be installed. " +
896
909
  "Do you really want to continue?"
897
910
  )
898
911
  ) {
@@ -935,11 +948,11 @@ function build_mobile_app(button) {
935
948
  });
936
949
  }
937
950
 
938
- function pull_cordova_builder() {
939
- ajax_post("/admin/mobile-app/pull-cordova-builder", {
951
+ function pull_capacitor_builder() {
952
+ ajax_post("/admin/mobile-app/pull-capacitor-builder", {
940
953
  success: () => {
941
954
  notifyAlert(
942
- "Pulling the the cordova-builder. " +
955
+ "Pulling the the capacitor-builder. " +
943
956
  "To see the progress, open the logs viewer with the System logging verbosity set to 'All'."
944
957
  );
945
958
  },
@@ -989,12 +1002,12 @@ function check_xcodebuild() {
989
1002
  });
990
1003
  }
991
1004
 
992
- function check_cordova_builder() {
993
- $.ajax("/admin/mobile-app/check-cordova-builder", {
1005
+ function check_capacitor_builder() {
1006
+ $.ajax("/admin/mobile-app/check-capacitor-builder", {
994
1007
  type: "GET",
995
1008
  success: function (res) {
996
- window.cordovaBuilderAvailable = !!res.installed;
997
- if (window.cordovaBuilderAvailable) {
1009
+ window.capacitorBuilderAvailable = !!res.installed;
1010
+ if (window.capacitorBuilderAvailable) {
998
1011
  $("#dockerBuilderStatusId").html(
999
1012
  `<span>
1000
1013
  installed<i class="ps-2 fas fa-check text-success"></i>
@@ -1088,7 +1101,7 @@ function toggle_tbl_sync() {
1088
1101
  function toggle_android_platform() {
1089
1102
  if ($("#androidCheckboxId")[0].checked === true) {
1090
1103
  $("#dockerCheckboxId").attr("hidden", false);
1091
- $("#dockerCheckboxId").attr("checked", window.cordovaBuilderAvailable);
1104
+ $("#dockerCheckboxId").attr("checked", window.capacitorBuilderAvailable);
1092
1105
  $("#dockerLabelId").removeClass("d-none");
1093
1106
  } else {
1094
1107
  $("#dockerCheckboxId").attr("hidden", true);
@@ -1189,6 +1202,31 @@ function installPWA() {
1189
1202
  }
1190
1203
  }
1191
1204
 
1205
+ function check_unsaved_form(event, script_tag) {
1206
+ const form = $(script_tag).parent().find("form");
1207
+ if (form.attr("data-unsaved-changes")) {
1208
+ event.preventDefault();
1209
+ event.returnValue = true;
1210
+ }
1211
+ }
1212
+ function check_delete_unsaved(tablename, script_tag) {
1213
+ const form = $(script_tag).parent().find("form");
1214
+ if (form.length && !form.attr("data-form-changed")) {
1215
+ //delete row
1216
+ const rec = get_form_record(form);
1217
+ if (navigator.sendBeacon) {
1218
+ navigator.sendBeacon(`/api/${tablename}/delete/${rec.id}`);
1219
+ } else
1220
+ $.ajax({
1221
+ url: `/api/${tablename}/${rec.id}`,
1222
+ type: "DELETE",
1223
+ headers: {
1224
+ "CSRF-Token": _sc_globalCsrf,
1225
+ },
1226
+ });
1227
+ }
1228
+ }
1229
+
1192
1230
  (() => {
1193
1231
  const e = document.querySelector("[data-sidebar-toggler]");
1194
1232
  let closed = localStorage.getItem("sidebarClosed") === "true";