@saltcorn/server 0.8.8-beta.6 → 0.8.9

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/locales/en.json CHANGED
@@ -1248,5 +1248,7 @@
1248
1248
  "include": "include",
1249
1249
  "Auto public login": "Auto public login",
1250
1250
  "New user view": "New user view",
1251
- "A view to show to new users, to finalise registration (if Edit) or as a welcome view": "A view to show to new users, to finalise registration (if Edit) or as a welcome view"
1251
+ "A view to show to new users, to finalise registration (if Edit) or as a welcome view": "A view to show to new users, to finalise registration (if Edit) or as a welcome view",
1252
+ "View decoration": "View decoration",
1253
+ "Title formula": "Title formula"
1252
1254
  }
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@saltcorn/server",
3
- "version": "0.8.8-beta.6",
3
+ "version": "0.8.9",
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.8.8-beta.6",
10
- "@saltcorn/builder": "0.8.8-beta.6",
11
- "@saltcorn/data": "0.8.8-beta.6",
12
- "@saltcorn/admin-models": "0.8.8-beta.6",
13
- "@saltcorn/filemanager": "0.8.8-beta.6",
14
- "@saltcorn/markup": "0.8.8-beta.6",
15
- "@saltcorn/sbadmin2": "0.8.8-beta.6",
9
+ "@saltcorn/base-plugin": "0.8.9",
10
+ "@saltcorn/builder": "0.8.9",
11
+ "@saltcorn/data": "0.8.9",
12
+ "@saltcorn/admin-models": "0.8.9",
13
+ "@saltcorn/filemanager": "0.8.9",
14
+ "@saltcorn/markup": "0.8.9",
15
+ "@saltcorn/sbadmin2": "0.8.9",
16
16
  "@socket.io/cluster-adapter": "^0.2.1",
17
17
  "@socket.io/sticky": "^1.0.1",
18
18
  "adm-zip": "0.5.10",
@@ -702,6 +702,11 @@ function initialize_page() {
702
702
  }
703
703
  }
704
704
  }
705
+ setTimeout(() => {
706
+ $("#toasts-area")
707
+ .find(".show[rendered='server-side'][type='success']")
708
+ .removeClass("show");
709
+ }, 5000);
705
710
  }
706
711
 
707
712
  $(initialize_page);
@@ -852,6 +857,68 @@ function tristateClick(nm) {
852
857
  }
853
858
  }
854
859
 
860
+ function buildToast(txt, type, spin) {
861
+ const realtype = type === "error" ? "danger" : type;
862
+ const icon =
863
+ realtype === "success"
864
+ ? "fa-check-circle"
865
+ : realtype === "danger"
866
+ ? "fa-times-circle"
867
+ : realtype === "warning"
868
+ ? "fa-exclamation-triangle"
869
+ : "";
870
+ const isNode = typeof parent?.saltcorn?.data?.state === "undefined";
871
+ const rndid = `tab${Math.floor(Math.random() * 16777215).toString(16)}`;
872
+ return {
873
+ id: rndid,
874
+ html: `
875
+ <div
876
+ class="toast show"
877
+ id="${rndid}"
878
+ rendered="client-side",
879
+ role="alert"
880
+ aria-live="assertive"
881
+ aria-atomic="true"
882
+ style="min-width: 350px; max-width: 50vw; width: auto; z-index: 999; ${
883
+ !isNode ? "transform: translateX(-50%);" : ""
884
+ }"
885
+ >
886
+ <div class="toast-header bg-${realtype} text-white py-1 ">
887
+ <i class="fas ${icon} me-2"></i>
888
+ <strong class="me-auto" >
889
+ ${type}
890
+ </strong>
891
+ ${
892
+ spin
893
+ ? ""
894
+ : `<button
895
+ type="button"
896
+ class="btn-close btn-close-white"
897
+ data-bs-dismiss="toast"
898
+ aria-label="Close"
899
+ style="font-size: 12px;"
900
+ ></button>`
901
+ }
902
+ </div>
903
+ <div
904
+ class="toast-body py-2 fs-6 fw-bold d-flex align-items-center"
905
+ >
906
+ <strong>${txt}</strong>
907
+ ${
908
+ spin
909
+ ? `<span
910
+ class="spinner-border ms-auto"
911
+ role="status"
912
+ aria-hidden="true"
913
+ style="width: 1.5rem; height: 1.5rem"></span>`
914
+ : ""
915
+ }
916
+ </div>
917
+ </div>
918
+ `,
919
+ };
920
+ }
921
+
855
922
  function notifyAlert(note, spin) {
856
923
  if (Array.isArray(note)) {
857
924
  note.forEach(notifyAlert);
@@ -865,23 +932,17 @@ function notifyAlert(note, spin) {
865
932
  txt = note.text;
866
933
  type = note.type;
867
934
  }
868
-
869
- $("#alerts-area")
870
- .append(`<div class="alert alert-${type} alert-dismissible fade show ${
871
- spin ? "d-flex align-items-center" : ""
872
- }" role="alert">
873
- ${txt}
874
- ${
875
- spin
876
- ? `<div class="spinner-border ms-auto" role="status" aria-hidden="true"></div>`
877
- : `<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
878
- </button>`
935
+ const { id, html } = buildToast(txt, type, spin);
936
+ $("#toasts-area").append(html);
937
+ if (type === "success") {
938
+ setTimeout(() => {
939
+ $(`#${id}`).removeClass("show");
940
+ }, 5000);
879
941
  }
880
- </div>`);
881
942
  }
882
943
 
883
944
  function emptyAlerts() {
884
- $("#alerts-area").html("");
945
+ $("#toasts-area").html("");
885
946
  }
886
947
 
887
948
  function press_store_button(clicked) {
package/routes/admin.js CHANGED
@@ -1464,7 +1464,7 @@ const buildDialogScript = () => {
1464
1464
  }
1465
1465
 
1466
1466
  function handleMessages() {
1467
- notifyAlert("Building the app, please wait.")
1467
+ notifyAlert("Building the app, please wait.", true)
1468
1468
  ${
1469
1469
  getState().getConfig("apple_team_id") &&
1470
1470
  getState().getConfig("apple_team_id") !== "null"
package/routes/menu.js CHANGED
@@ -70,7 +70,7 @@ const menuForm = async (req) => {
70
70
  .map(([k, v]) => k),
71
71
  ];
72
72
  const triggers = Trigger.find({
73
- when_trigger: {or: ["API call", "Never"]},
73
+ when_trigger: { or: ["API call", "Never"] },
74
74
  });
75
75
  triggers.forEach((tr) => {
76
76
  actions.push(tr.name);
@@ -155,6 +155,22 @@ const menuForm = async (req) => {
155
155
  class: "item-menu",
156
156
  required: false,
157
157
  },
158
+ {
159
+ name: "target_blank",
160
+ label: req.__("Open in new tab"),
161
+ type: "Bool",
162
+ required: false,
163
+ class: "item-menu",
164
+ showIf: { type: ["View", "Page", "Link"] },
165
+ },
166
+ {
167
+ name: "in_modal",
168
+ label: req.__("Open in popup modal?"),
169
+ type: "Bool",
170
+ required: false,
171
+ class: "item-menu",
172
+ showIf: { type: ["View", "Page", "Link"] },
173
+ },
158
174
  {
159
175
  name: "url",
160
176
  label: req.__("URL"),
@@ -7,7 +7,7 @@
7
7
 
8
8
  const Router = require("express-promise-router");
9
9
 
10
- const { renderForm, renderBuilder, alert } = require("@saltcorn/markup");
10
+ const { renderForm, renderBuilder, toast } = require("@saltcorn/markup");
11
11
  const tags = require("@saltcorn/markup/tags");
12
12
  const { p, a, div, script, text, domReady, code, pre, tbody, tr, th, td } =
13
13
  tags;
@@ -65,27 +65,7 @@ router.get(
65
65
 
66
66
  const viewMarkup = await viewsList(views, req);
67
67
  const tables = await Table.find();
68
- const viewAccessWarning = (view) => {
69
- const table = tables.find((t) => t.name === view.table);
70
- if (!table) return false;
71
- if (table.name === "users") return false;
72
- if (table.ownership_field_id || table.ownership_formula) return false;
73
68
 
74
- return table.min_role_read < view.min_role;
75
- };
76
- const hasAccessWarning = views.filter(viewAccessWarning);
77
- const accessWarning =
78
- hasAccessWarning.length > 0
79
- ? alert(
80
- "danger",
81
- `<p>${req.__(
82
- `You have views with a role to access lower than the table role to read, with no table ownership. This may cause a denial of access. Users need to have table read access to any data displayed.`
83
- )}</p>
84
- ${req.__("Views potentially affected")}: ${hasAccessWarning
85
- .map((v) => v.name)
86
- .join(", ")}`
87
- )
88
- : "";
89
69
  res.sendWrap(req.__(`Views`), {
90
70
  above: [
91
71
  {
@@ -97,7 +77,6 @@ router.get(
97
77
  class: "mt-0",
98
78
  title: req.__("Your views"),
99
79
  contents: [
100
- accessWarning,
101
80
  viewMarkup,
102
81
  tables.length > 0
103
82
  ? a(
@@ -250,8 +250,11 @@ Gordon Kane, 218`;
250
250
  await request(app)
251
251
  .get("/table/")
252
252
  .set("Cookie", loginCookie)
253
- .expect(toInclude("alert-danger"))
254
- .expect(toInclude("books"));
253
+ .expect(
254
+ toInclude(
255
+ "cannot drop table books because other objects depend on it"
256
+ )
257
+ );
255
258
  });
256
259
  });
257
260
  describe("deletion to table with row ownership", () => {