@saltcorn/server 1.1.1-beta.1 → 1.1.1-beta.3

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/CHANGELOG.md CHANGED
@@ -1,8 +1,86 @@
1
- # Change Log
1
+ # Notable changes
2
2
 
3
- All notable changes to this project will be documented in this file.
4
- See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
3
+ ## 1.1.1 - In beta
5
4
 
6
- ## [0.4.5](https://github.com/saltcorn/saltcorn/compare/v0.4.5-beta.1...v0.4.5) (2021-05-07)
5
+ * Stored calculated fields that contain joinfields in the expression are now automatically
6
+ updated when the values they reference are changed, i.e. changes occur in the tables they
7
+ reference. This is limited to single (expression contains x.y) and double joinfields
8
+ (expression contains x.y.z). In most cases, you can now remove all recalculate_stored_fields
9
+ actions.
7
10
 
8
- **Note:** Version bump only for package @saltcorn/server
11
+ * Builder:
12
+ - Add ability to set custom `id` on containers. This is useful for scroll targets
13
+ - Add animations tab to containers. All animations are activated on scroll
14
+ - Tabs and multi-step actions implement a new interface that lets you move, delete and
15
+ add steps/tabs.
16
+
17
+ * Workflows:
18
+ - APIResponse step type. Provide the API response
19
+ - Stop step type. Stop workflow immediately
20
+ - EditViewForm step type: run a form from an Edit view, add respnse to context
21
+ - Call other workflows in a workflow step. Control subcontext for called workflow
22
+ - Error handling. SetErrorHandler step type, which set the step invoked on errors
23
+ - ForLoop step type for loops over arrays.
24
+ - Varius UX improvements for editing workflows
25
+ - Integrate copilot, if installed, in workflow editing
26
+
27
+ * sbadmin2 theme - Color update: dark side bar, darker primary blue
28
+
29
+ * AppChange event, runs every time a view, table, trigger, page or configuration value
30
+ is changed.
31
+
32
+ * Mobile builder:
33
+ - PJAX view loading.
34
+
35
+ ### Fixes
36
+
37
+ * fix query string build on check_state_field (#2948). Author: St0rml
38
+
39
+ ### Translations
40
+
41
+ * Update Polish translation. Author: skaskiewicz
42
+
43
+ ## 1.1.0 - Released 19 December 2024
44
+
45
+ * Workflows: a new type of trigger composed of steps, with durable execution and
46
+ a context for sharing information between steps. Workflows can include user interaction
47
+ including asking for user input in specified form fields.
48
+
49
+ * Workflow rooms: a new view for chatbot-style interactions with workflows
50
+
51
+ * HTTPS proxy: set an HTTPS proxy with the HTTPS_PROXY environment variable.
52
+
53
+ * Edit view: option to allocate new table row when running with a specified row. This is
54
+ useful when the Edit row includes embedded views based on relations. The allocated row can be
55
+ deleted if there are no changes.
56
+
57
+ * Acquire Let's Encrypt certificates for tenants. If Let's Encrypt is enabled in the root tenant,
58
+ newly created tenants will acquire a certificate. Certificate for existing tenants can be acquired
59
+ in that the settings for that tenant in the root tenant's list of tenants.
60
+
61
+ * Icon plugins. Plugins can now supply additional icons which can be chosen in the builder and
62
+ menu editor
63
+
64
+ * Registry editor: Edit configuration values
65
+
66
+ * Webhook action has more options: method, set reponse value, headers.
67
+
68
+ ### Security
69
+
70
+ - SameSite cookie settings
71
+ - Options to enable Content Security Policy and CORS
72
+ - Warn when loading embedded with without role. Strict enforcement in 1.1.2.
73
+ - Check table permissions when filling select dropdown options
74
+
75
+ ### Fixes
76
+
77
+ * Edit destination formulae are evaluated against the whole row, not only saved form fields
78
+ * Set user groups when admin becomes user
79
+
80
+ ### Translations
81
+
82
+ * Update Polish translation. Author: skaskiewicz
83
+
84
+ ## 1.0.0 - Released 15 November 2024
85
+
86
+ Change tracking from this point.
package/auth/testhelp.js CHANGED
@@ -383,7 +383,13 @@ const load_url_dom = async (url) => {
383
383
  .join("\n");
384
384
  }
385
385
  }
386
+ class FakeIntersectionObserver {
387
+ constructor() {}
388
+ observe() {}
389
+ }
390
+
386
391
  dom.window.XMLHttpRequest = FakeXHR;
392
+ dom.window.IntersectionObserver = FakeIntersectionObserver;
387
393
  await new Promise(function (resolve, reject) {
388
394
  dom.window.addEventListener("DOMContentLoaded", (event) => {
389
395
  resolve();
@@ -55,6 +55,8 @@ user verification is enabled.
55
55
 
56
56
  **Startup**: run this whenever this saltcorn process initializes. 
57
57
 
58
+ **AppChange**: the application build (views, pages, triggers etc.) changed
59
+
58
60
  ## Other events
59
61
 
60
62
  **Never**: this trigger is never run on its own. However triggers that are marked as never
package/locales/en.json CHANGED
@@ -1520,7 +1520,13 @@
1520
1520
  "OK": "OK",
1521
1521
  "Step settings": "Step settings",
1522
1522
  "Action settings": "Action settings",
1523
+ "Keystore file is not applied for debug builds.": "Keystore file is not applied for debug builds.",
1523
1524
  "Workflow": "Workflow",
1524
1525
  "Previous runs": "Previous runs",
1525
- "The workflow the user will be interacting with.": "The workflow the user will be interacting with."
1526
+ "The workflow the user will be interacting with.": "The workflow the user will be interacting with.",
1527
+ "Delete old workflow runs with status after days": "Delete old workflow runs with status after days",
1528
+ "Finished": "Finished",
1529
+ "Error": "Error",
1530
+ "Waiting": "Waiting",
1531
+ "Running": "Running"
1526
1532
  }
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@saltcorn/server",
3
- "version": "1.1.1-beta.1",
3
+ "version": "1.1.1-beta.3",
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": "1.1.1-beta.1",
11
- "@saltcorn/builder": "1.1.1-beta.1",
12
- "@saltcorn/data": "1.1.1-beta.1",
13
- "@saltcorn/admin-models": "1.1.1-beta.1",
14
- "@saltcorn/filemanager": "1.1.1-beta.1",
15
- "@saltcorn/markup": "1.1.1-beta.1",
16
- "@saltcorn/plugins-loader": "1.1.1-beta.1",
17
- "@saltcorn/sbadmin2": "1.1.1-beta.1",
10
+ "@saltcorn/base-plugin": "1.1.1-beta.3",
11
+ "@saltcorn/builder": "1.1.1-beta.3",
12
+ "@saltcorn/data": "1.1.1-beta.3",
13
+ "@saltcorn/admin-models": "1.1.1-beta.3",
14
+ "@saltcorn/filemanager": "1.1.1-beta.3",
15
+ "@saltcorn/markup": "1.1.1-beta.3",
16
+ "@saltcorn/plugins-loader": "1.1.1-beta.3",
17
+ "@saltcorn/sbadmin2": "1.1.1-beta.3",
18
18
  "@socket.io/cluster-adapter": "^0.2.1",
19
19
  "@socket.io/sticky": "^1.0.1",
20
20
  "adm-zip": "0.5.10",
@@ -2024,3 +2024,33 @@ function update_time_of_week(nm) {
2024
2024
  $(`#inputh${nm}`).val(s).trigger("change");
2025
2025
  };
2026
2026
  }
2027
+
2028
+ const observer = new IntersectionObserver(
2029
+ (entries, observer) => {
2030
+ entries.forEach((entry) => {
2031
+ if (entry.isIntersecting) {
2032
+ const delay = entry.target.getAttribute("data-animate-delay"); // delay is optional
2033
+ const duration = entry.target.getAttribute("data-animate-duration"); // delay is optional
2034
+ const animationClass = entry.target.getAttribute("data-animate");
2035
+ if (animationClass) {
2036
+ if (delay) entry.target.style.animationDelay = delay + "s";
2037
+ if (duration) entry.target.style.animationDuration = duration + "s";
2038
+ entry.target.style.animationName = animationClass;
2039
+ entry.target.style.animationFillMode = "both";
2040
+ }
2041
+
2042
+ if (entry.target.getAttribute("data-animate-initial-hide") === "")
2043
+ entry.target.removeAttribute("data-animate-initial-hide");
2044
+
2045
+ observer.unobserve(entry.target);
2046
+ }
2047
+ });
2048
+ },
2049
+ {
2050
+ threshold: 0.2,
2051
+ }
2052
+ );
2053
+
2054
+ document.querySelectorAll("[data-animate]").forEach((element) => {
2055
+ observer.observe(element);
2056
+ });
@@ -632,3 +632,144 @@ i[class*=" unicode-"] {
632
632
  .mobile-toast-margin {
633
633
  margin-bottom: 1rem;
634
634
  }
635
+
636
+ @keyframes fadeIn {
637
+ from {
638
+ opacity: 0;
639
+ }
640
+ to {
641
+ opacity: 1;
642
+ }
643
+ }
644
+
645
+ @keyframes fadeInLeft {
646
+ from {
647
+ opacity: 0;
648
+ transform: translate3d(-100%, 0, 0);
649
+ }
650
+ to {
651
+ opacity: 1;
652
+ transform: translate3d(0, 0, 0);
653
+ }
654
+ }
655
+
656
+ @keyframes fadeInDown {
657
+ from {
658
+ opacity: 0;
659
+ transform: translate3d(0, -100%, 0);
660
+ }
661
+ to {
662
+ opacity: 1;
663
+ transform: translate3d(0, 0, 0);
664
+ }
665
+ }
666
+
667
+ @keyframes fadeInRight {
668
+ from {
669
+ opacity: 0;
670
+ transform: translate3d(100%, 0, 0);
671
+ }
672
+ to {
673
+ opacity: 1;
674
+ transform: translate3d(0, 0, 0);
675
+ }
676
+ }
677
+
678
+ @keyframes fadeInUp {
679
+ from {
680
+ opacity: 0;
681
+ transform: translate3d(0, 100%, 0);
682
+ }
683
+ to {
684
+ opacity: 1;
685
+ transform: translate3d(0, 0, 0);
686
+ }
687
+ }
688
+
689
+ @keyframes rollIn {
690
+ from {
691
+ opacity: 0;
692
+ transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
693
+ }
694
+ to {
695
+ opacity: 1;
696
+ transform: translate3d(0, 0, 0);
697
+ }
698
+ }
699
+
700
+ @keyframes zoomIn {
701
+ from {
702
+ opacity: 0;
703
+ transform: scale3d(0.3, 0.3, 0.3);
704
+ }
705
+ 50% {
706
+ opacity: 1;
707
+ }
708
+ }
709
+
710
+ @keyframes zoomInUp {
711
+ from {
712
+ opacity: 0;
713
+ transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
714
+ animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
715
+ }
716
+ 60% {
717
+ opacity: 1;
718
+ transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
719
+ animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
720
+ }
721
+ }
722
+
723
+ @keyframes bounce {
724
+ from,
725
+ 20%,
726
+ 53%,
727
+ to {
728
+ animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
729
+ transform: translate3d(0, 0, 0);
730
+ }
731
+ 40%,
732
+ 43% {
733
+ animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
734
+ transform: translate3d(0, -30px, 0) scaleY(1.1);
735
+ }
736
+ 70% {
737
+ animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
738
+ transform: translate3d(0, -15px, 0) scaleY(1.05);
739
+ }
740
+ 80% {
741
+ transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
742
+ transform: translate3d(0, 0, 0) scaleY(0.95);
743
+ }
744
+ 90% {
745
+ transform: translate3d(0, -4px, 0) scaleY(1.02);
746
+ }
747
+ }
748
+
749
+ @keyframes tada {
750
+ from {
751
+ transform: scale3d(1, 1, 1);
752
+ }
753
+ 10%,
754
+ 20% {
755
+ transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
756
+ }
757
+ 30%,
758
+ 50%,
759
+ 70%,
760
+ 90% {
761
+ transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
762
+ }
763
+ 40%,
764
+ 60%,
765
+ 80% {
766
+ transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
767
+ }
768
+ to {
769
+ transform: scale3d(1, 1, 1);
770
+ }
771
+ }
772
+
773
+ [data-animate-initial-hide] {
774
+ opacity: 0;
775
+ }
@@ -65,7 +65,7 @@ function updateQueryStringParameters(uri1, kvs) {
65
65
  return uri;
66
66
  }
67
67
 
68
- function removeQueryStringParameter(uri1, key) {
68
+ function removeQueryStringParameter(uri1, key, value) {
69
69
  let hash = "";
70
70
  let uri = uri1;
71
71
  if (uri && uri.includes("#")) {
@@ -73,8 +73,12 @@ function removeQueryStringParameter(uri1, key) {
73
73
  hash = "#" + uris[1];
74
74
  uri = uris[0];
75
75
  }
76
-
77
- var re = new RegExp("([?&])" + key + "=.*?(&|$)", "gi");
76
+ let re;
77
+ if (value) {
78
+ re = new RegExp("([?&])" + key + "=" + value + "?(&|$)", "gi");
79
+ } else {
80
+ re = new RegExp("([?&])" + key + "=.*?(&|$)", "gi");
81
+ }
78
82
  if (uri.match(re)) {
79
83
  uri = uri.replace(re, "$1" + "$2");
80
84
  }
@@ -84,6 +88,28 @@ function removeQueryStringParameter(uri1, key) {
84
88
  return uri + hash;
85
89
  }
86
90
 
91
+ function addQueryStringParameter(uri1, key, value) {
92
+ let hash = "";
93
+ let uri = uri1;
94
+ if (uri && uri.includes("#")) {
95
+ let uris = uri1.split("#");
96
+ hash = "#" + uris[1];
97
+ uri = uris[0];
98
+ }
99
+ var re = new RegExp("([?&])" + key + "=" + value + "?(&|$)", "gi");
100
+ if (uri.match(re)) return uri1;
101
+
102
+ var separator = uri.indexOf("?") !== -1 ? "&" : "?";
103
+ if (Array.isArray(value))
104
+ return (
105
+ uri +
106
+ separator +
107
+ value.map((val) => key + "=" + encodeURIComponent(val)).join("&") +
108
+ hash
109
+ );
110
+ else return uri + separator + key + "=" + encodeURIComponent(value) + hash;
111
+ }
112
+
87
113
  function select_id(id, e) {
88
114
  pjax_to(updateQueryStringParameter(get_current_state_url(e), "id", id), e);
89
115
  }
@@ -96,10 +122,10 @@ function check_state_field(that, e) {
96
122
  const checked = that.checked;
97
123
  const name = that.name;
98
124
  const value = encodeURIComponent(that.value);
99
- var separator = get_current_state_url(e).indexOf("?") !== -1 ? "&" : "?";
100
125
  let dest;
101
- if (checked) dest = get_current_state_url(e) + `${separator}${name}=${value}`;
102
- else dest = get_current_state_url(e).replace(`${name}=${value}`, "");
126
+ if (checked)
127
+ dest = addQueryStringParameter(get_current_state_url(e), name, value);
128
+ else dest = removeQueryStringParameter(get_current_state_url(e), name, value);
103
129
  pjax_to(dest.replace("&&", "&").replace("?&", "?"), e);
104
130
  }
105
131
 
@@ -591,7 +617,7 @@ function updateViewPreview() {
591
617
  function ajaxSubmitForm(e, force_no_reload, event) {
592
618
  var form = $(e).closest("form");
593
619
  var url = form.attr("action");
594
- if(event) event.preventDefault();
620
+ if (event) event.preventDefault();
595
621
  $.ajax(url, {
596
622
  type: "POST",
597
623
  headers: {
@@ -606,10 +632,10 @@ function ajaxSubmitForm(e, force_no_reload, event) {
606
632
  "data-on-close-reload-view"
607
633
  );
608
634
  $("#scmodal").modal("hide");
609
- if (!force_no_reload && on_close_reload_view) {
635
+ if (on_close_reload_view) {
610
636
  const viewE = $(`[data-sc-embed-viewname="${on_close_reload_view}"]`);
611
637
  if (viewE.length) reload_embedded_view(on_close_reload_view);
612
- else location.reload();
638
+ else if (!force_no_reload) location.reload();
613
639
  } else if (!force_no_reload && !no_reload) location.reload();
614
640
  else common_done(res, form.attr("data-viewname"));
615
641
  },
@@ -859,10 +885,16 @@ function builderMenuChanged(e) {
859
885
  });
860
886
  }
861
887
 
862
- function poll_mobile_build_finished(outDirName, pollCount, orginalBtnHtml) {
888
+ function poll_mobile_build_finished(
889
+ outDirName,
890
+ buildDir,
891
+ mode,
892
+ pollCount,
893
+ orginalBtnHtml
894
+ ) {
863
895
  $.ajax("/admin/build-mobile-app/finished", {
864
896
  type: "GET",
865
- data: { build_dir: outDirName },
897
+ data: { out_dir_name: outDirName, mode: mode },
866
898
  success: function (res) {
867
899
  if (!res.finished) {
868
900
  if (pollCount >= 100) {
@@ -873,14 +905,45 @@ function poll_mobile_build_finished(outDirName, pollCount, orginalBtnHtml) {
873
905
  });
874
906
  } else {
875
907
  setTimeout(() => {
876
- poll_mobile_build_finished(outDirName, ++pollCount, orginalBtnHtml);
908
+ poll_mobile_build_finished(
909
+ outDirName,
910
+ buildDir,
911
+ mode,
912
+ ++pollCount,
913
+ orginalBtnHtml
914
+ );
877
915
  }, 5000);
878
916
  }
879
917
  } else {
880
918
  href_to(
881
- `build-mobile-app/result?build_dir_name=${encodeURIComponent(
919
+ `/admin/build-mobile-app/result?out_dir_name=${encodeURIComponent(
882
920
  outDirName
883
- )}`
921
+ )}&build_dir=${encodeURIComponent(buildDir)}&mode=${mode}`
922
+ );
923
+ }
924
+ },
925
+ });
926
+ }
927
+
928
+ function finish_mobile_app(button, outDirName, buildDir) {
929
+ $.ajax("/admin/build-mobile-app/finish", {
930
+ type: "POST",
931
+ headers: {
932
+ "CSRF-Token": _sc_globalCsrf,
933
+ },
934
+ data: { out_dir_name: outDirName, build_dir: buildDir },
935
+ success: function (data) {
936
+ if (data.success) {
937
+ notifyAlert("Finishing the app, please wait.", true);
938
+ for (const msg of data.msgs || []) notifyAlert(msg);
939
+ const orginalBtnHtml = $("#finishMobileAppBtnId").html();
940
+ press_store_button(button);
941
+ poll_mobile_build_finished(
942
+ outDirName,
943
+ buildDir,
944
+ "finish",
945
+ 0,
946
+ orginalBtnHtml
884
947
  );
885
948
  }
886
949
  },
@@ -938,11 +1001,18 @@ function build_mobile_app(button) {
938
1001
  ajax_post("/admin/build-mobile-app", {
939
1002
  data: params,
940
1003
  success: (data) => {
941
- if (data.build_dir_name) {
942
- handleMessages();
1004
+ if (data.out_dir_name && data.build_dir) {
1005
+ notifyAlert("Building the app, please wait.", true);
1006
+ for (const msg of data.msgs || []) notifyAlert(msg);
943
1007
  const orginalBtnHtml = $("#buildMobileAppBtnId").html();
944
1008
  press_store_button(button);
945
- poll_mobile_build_finished(data.build_dir_name, 0, orginalBtnHtml);
1009
+ poll_mobile_build_finished(
1010
+ data.out_dir_name,
1011
+ data.build_dir,
1012
+ data.mode,
1013
+ 0,
1014
+ orginalBtnHtml
1015
+ );
946
1016
  }
947
1017
  },
948
1018
  });