@saltcorn/server 1.1.0-beta.13 → 1.1.0-beta.15

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.
@@ -81,6 +81,31 @@ const logSettingsForm = async (req) => {
81
81
  input_type: "date",
82
82
  attributes: { minDate: new Date(), maxDate: hoursFuture(24 * 7 * 2) },
83
83
  },
84
+ {
85
+ input_type: "section_header",
86
+ label: req.__("Delete old workflow runs with status after days"),
87
+ },
88
+ {
89
+ name: "delete_finished_workflows_days",
90
+ label: req.__("Finished"),
91
+ type: "Integer",
92
+ },
93
+ {
94
+ name: "delete_error_workflows_days",
95
+ label: req.__("Error"),
96
+ type: "Integer",
97
+ },
98
+ {
99
+ name: "delete_waiting_workflows_days",
100
+ label: req.__("Waiting"),
101
+ type: "Integer",
102
+ },
103
+
104
+ {
105
+ name: "delete_running_workflows_days",
106
+ label: req.__("Running"),
107
+ type: "Integer",
108
+ },
84
109
  {
85
110
  input_type: "section_header",
86
111
  label: req.__("Which events should be logged?"),
@@ -143,6 +168,10 @@ router.get(
143
168
  "next_weekly_event",
144
169
  {}
145
170
  );
171
+ ["error", "finished", "running", "waiting"].forEach((k) => {
172
+ let cfgk = `delete_${k}_workflows_days`;
173
+ form.values[cfgk] = getState().getConfig(cfgk);
174
+ });
146
175
 
147
176
  send_events_page({
148
177
  res,
@@ -348,6 +377,13 @@ router.post(
348
377
  delete form.values[k];
349
378
  }
350
379
  }
380
+ for (const status of ["error", "finished", "running", "waiting"]) {
381
+ let k = `delete_${status}_workflows_days`;
382
+ if (form.values[k]) {
383
+ await getState().setConfig(k, form.values[k]);
384
+ delete form.values[k];
385
+ }
386
+ }
351
387
 
352
388
  await getState().setConfig("event_log_settings", form.values);
353
389
 
package/routes/fields.js CHANGED
@@ -301,6 +301,10 @@ const fieldFlow = (req) =>
301
301
  if (context.id) {
302
302
  const field = await Field.findOne({ id: context.id });
303
303
  try {
304
+ if (fldRow.label && field.label != fldRow.label) {
305
+ fldRow.name = Field.labelToName(fldRow.label);
306
+ }
307
+
304
308
  await field.update(fldRow);
305
309
  } catch (e) {
306
310
  return {
package/routes/tables.js CHANGED
@@ -56,7 +56,7 @@ const {
56
56
  } = require("@saltcorn/data/models/discovery");
57
57
  const { getState } = require("@saltcorn/data/db/state");
58
58
  const { cardHeaderTabs } = require("@saltcorn/markup/layout_utils");
59
- const { tablesList, viewsList } = require("./common_lists");
59
+ const { tablesList, viewsList, getTriggerList } = require("./common_lists");
60
60
  const {
61
61
  InvalidConfiguration,
62
62
  removeAllWhiteSpace,
@@ -757,6 +757,8 @@ router.get(
757
757
  const triggers = table.id ? Trigger.find({ table_id: table.id }) : [];
758
758
  triggers.sort(comparingCaseInsensitive("name"));
759
759
  let fieldCard;
760
+ const nPrimaryKeys = fields.filter((f) => f.primary_key).length;
761
+
760
762
  if (fields.length === 0) {
761
763
  fieldCard = [
762
764
  h4(req.__(`No fields defined in %s table`, table.name)),
@@ -818,28 +820,25 @@ router.get(
818
820
  { hover: true }
819
821
  );
820
822
  fieldCard = [
823
+ nPrimaryKeys > 1 &&
824
+ div(
825
+ { class: "alert alert-danger", role: "alert" },
826
+ i({ class: "fas fa-exclamation-triangle" }),
827
+ "This table has composite primary keys which is not supported in Saltcorn. A procedure to introduce a single autoincrementing primary key is available.",
828
+ post_btn(
829
+ `/table/repair-composite-primary/${table.id}`,
830
+ "Add autoincrementing primary key",
831
+ req.csrfToken(),
832
+ { btnClass: "btn-danger" }
833
+ )
834
+ ),
835
+
821
836
  tableHtml,
822
837
  inbound_refs.length > 0
823
838
  ? req.__("Inbound keys: ") +
824
839
  inbound_refs.map((tnm) => link(`/table/${tnm}`, tnm)).join(", ") +
825
840
  "<br>"
826
841
  : "",
827
- triggers.length
828
- ? req.__("Table triggers: ") +
829
- triggers
830
- .map((t) =>
831
- link(
832
- `/actions/configure/${
833
- t.id
834
- }?on_done_redirect=${encodeURIComponent(
835
- `table/${table.name}`
836
- )}`,
837
- t.name
838
- )
839
- )
840
- .join(", ") +
841
- "<br>"
842
- : "",
843
842
  !table.external &&
844
843
  !table.provider_name &&
845
844
  a(
@@ -851,7 +850,8 @@ router.get(
851
850
  ),
852
851
  ];
853
852
  }
854
- var viewCard;
853
+ let viewCard;
854
+ let triggerCard = "";
855
855
  if (fields.length > 0) {
856
856
  const views = await View.find(
857
857
  table.id ? { table_id: table.id } : { exttable_name: table.name }
@@ -884,6 +884,25 @@ router.get(
884
884
  req.__("Create view")
885
885
  ),
886
886
  };
887
+
888
+ triggerCard = {
889
+ type: "card",
890
+ id: "table-triggers",
891
+ title: req.__("Triggers on table"),
892
+ contents:
893
+ (triggers.length
894
+ ? await getTriggerList(triggers, req)
895
+ : p("Triggers run actions in response to events on this table")) +
896
+ a(
897
+ {
898
+ href: `/actions/new?table=${encodeURIComponent(
899
+ table.name
900
+ )}&on_done_redirect=${encodeURIComponent(`table/${table.name}`)}`,
901
+ class: "btn btn-primary",
902
+ },
903
+ req.__("Create trigger")
904
+ ),
905
+ };
887
906
  }
888
907
  const models = await Model.find({ table_id: table.id });
889
908
  const modelCard = div(
@@ -1078,6 +1097,7 @@ router.get(
1078
1097
  ]
1079
1098
  : []),
1080
1099
  ...(viewCard ? [viewCard] : []),
1100
+ ...(triggerCard ? [triggerCard] : []),
1081
1101
  {
1082
1102
  type: "card",
1083
1103
  title: req.__("Edit table properties"),
@@ -1111,7 +1131,7 @@ router.post(
1111
1131
  const v = req.body;
1112
1132
  if (typeof v.id === "undefined" && typeof v.external === "undefined") {
1113
1133
  // insert
1114
- v.name = v.name.trim()
1134
+ v.name = v.name.trim();
1115
1135
  const { name, ...rest } = v;
1116
1136
  const alltables = await Table.find({});
1117
1137
  const existing_tables = [
@@ -1162,6 +1182,7 @@ router.post(
1162
1182
  let notify = "";
1163
1183
  if (!rest.versioned) rest.versioned = false;
1164
1184
  if (!rest.has_sync_info) rest.has_sync_info = false;
1185
+ rest.is_user_group = !!rest.is_user_group;
1165
1186
  if (rest.ownership_field_id === "_formula") {
1166
1187
  rest.ownership_field_id = null;
1167
1188
  const fmlValidRes = expressionValidator(rest.ownership_formula);
@@ -1922,7 +1943,7 @@ router.post(
1922
1943
  const table = Table.findOne({ name });
1923
1944
 
1924
1945
  try {
1925
- await table.deleteRows({}, req.user);
1946
+ await table.deleteRows({}, req.user, true);
1926
1947
  req.flash("success", req.__("Deleted all rows"));
1927
1948
  } catch (e) {
1928
1949
  req.flash("error", e.message);
@@ -2074,3 +2095,20 @@ router.post(
2074
2095
  respondWorkflow(table, workflow, wfres, req, res);
2075
2096
  })
2076
2097
  );
2098
+
2099
+ router.post(
2100
+ "/repair-composite-primary/:id",
2101
+ isAdmin,
2102
+ error_catcher(async (req, res) => {
2103
+ const { id } = req.params;
2104
+
2105
+ const table = Table.findOne({ id });
2106
+ if (!table) {
2107
+ req.flash("error", `Table not found`);
2108
+ res.redirect(`/table`);
2109
+ return;
2110
+ }
2111
+ await table.repairCompositePrimary();
2112
+ res.redirect(`/table/${table.id}`);
2113
+ })
2114
+ );