@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/routes/tables.js CHANGED
@@ -83,38 +83,38 @@ const tableForm = async (table, req) => {
83
83
  .map((f) => ({ value: f.id, label: f.name }));
84
84
  const form = new Form({
85
85
  action: "/table",
86
- submitButtonClass: "btn-outline-primary",
87
- onChange: "remove_outline(this)",
86
+ noSubmitButton: true,
87
+ onChange: "saveAndContinue(this)",
88
88
  fields: [
89
89
  ...(!table.external
90
90
  ? [
91
- {
92
- label: req.__("Ownership field"),
93
- name: "ownership_field_id",
94
- sublabel: req.__(
95
- "The user referred to in this field will be the owner of the row"
96
- ),
97
- input_type: "select",
98
- options: [
99
- { value: "", label: req.__("None") },
100
- ...userFields,
101
- { value: "_formula", label: req.__("Formula") },
102
- ],
103
- },
104
- {
105
- name: "ownership_formula",
106
- label: req.__("Ownership formula"),
107
- validator: expressionValidator,
108
- type: "String",
109
- class: "validate-expression",
110
- sublabel:
111
- req.__("User is treated as owner if true. In scope: ") +
112
- ["user", ...fields.map((f) => f.name)]
113
- .map((fn) => code(fn))
114
- .join(", "),
115
- showIf: { ownership_field_id: "_formula" },
116
- },
117
- ]
91
+ {
92
+ label: req.__("Ownership field"),
93
+ name: "ownership_field_id",
94
+ sublabel: req.__(
95
+ "The user referred to in this field will be the owner of the row"
96
+ ),
97
+ input_type: "select",
98
+ options: [
99
+ { value: "", label: req.__("None") },
100
+ ...userFields,
101
+ { value: "_formula", label: req.__("Formula") },
102
+ ],
103
+ },
104
+ {
105
+ name: "ownership_formula",
106
+ label: req.__("Ownership formula"),
107
+ validator: expressionValidator,
108
+ type: "String",
109
+ class: "validate-expression",
110
+ sublabel:
111
+ req.__("User is treated as owner if true. In scope: ") +
112
+ ["user", ...fields.map((f) => f.name)]
113
+ .map((fn) => code(fn))
114
+ .join(", "),
115
+ showIf: { ownership_field_id: "_formula" },
116
+ },
117
+ ]
118
118
  : []),
119
119
  // description of table
120
120
  {
@@ -138,24 +138,24 @@ const tableForm = async (table, req) => {
138
138
  ...(table.external
139
139
  ? []
140
140
  : [
141
- {
142
- label: req.__("Minimum role to write"),
143
- name: "min_role_write",
144
- input_type: "select",
145
- sublabel: req.__(
146
- "User must have this role or higher to edit or create new rows in the table"
147
- ),
148
- options: roleOptions,
149
- },
150
- {
151
- label: req.__("Version history"),
152
- sublabel: req.__(
153
- "Version history allows to track table data changes"
154
- ),
155
- name: "versioned",
156
- type: "Bool",
157
- },
158
- ]),
141
+ {
142
+ label: req.__("Minimum role to write"),
143
+ name: "min_role_write",
144
+ input_type: "select",
145
+ sublabel: req.__(
146
+ "User must have this role or higher to edit or create new rows in the table"
147
+ ),
148
+ options: roleOptions,
149
+ },
150
+ {
151
+ label: req.__("Version history"),
152
+ sublabel: req.__(
153
+ "Version history allows to track table data changes"
154
+ ),
155
+ name: "versioned",
156
+ type: "Bool",
157
+ },
158
+ ]),
159
159
  ],
160
160
  });
161
161
  if (table) {
@@ -222,11 +222,11 @@ const discoverForm = (tables, req) => {
222
222
  blurb:
223
223
  tables.length > 0
224
224
  ? req.__(
225
- "The following tables in your database can be imported into Saltcorn:"
226
- )
225
+ "The following tables in your database can be imported into Saltcorn:"
226
+ )
227
227
  : req.__(
228
- "There are no tables in the database that can be imported into Saltcorn."
229
- ),
228
+ "There are no tables in the database that can be imported into Saltcorn."
229
+ ),
230
230
  submitLabel: req.__("Import"),
231
231
  fields: tables.map((t) => ({
232
232
  name: t.table_name,
@@ -579,11 +579,11 @@ router.get(
579
579
  key: (r) =>
580
580
  r.type === "Key"
581
581
  ? `Key to ` +
582
- a({ href: `/table/${r.reftable_name}` }, r.reftable_name)
582
+ a({ href: `/table/${r.reftable_name}` }, r.reftable_name)
583
583
  : (r.type && r.type.name) ||
584
- r.type ||
585
- r.typename +
586
- span({ class: "badge bg-danger ms-1" }, "Unknown type"),
584
+ r.type ||
585
+ r.typename +
586
+ span({ class: "badge bg-danger ms-1" }, "Unknown type"),
587
587
  },
588
588
  {
589
589
  label: "",
@@ -597,23 +597,23 @@ router.get(
597
597
  ...(table.external
598
598
  ? []
599
599
  : [
600
- {
601
- label: req.__("Edit"),
602
- key: (r) => link(`/field/${r.id}`, req.__("Edit")),
603
- },
604
- ]),
600
+ {
601
+ label: req.__("Edit"),
602
+ key: (r) => link(`/field/${r.id}`, req.__("Edit")),
603
+ },
604
+ ]),
605
605
  ...(table.external || db.isSQLite
606
606
  ? []
607
607
  : [
608
- {
609
- label: req.__("Delete"),
610
- key: (r) =>
611
- (table.name === "users" && r.name === "email") ||
608
+ {
609
+ label: req.__("Delete"),
610
+ key: (r) =>
611
+ (table.name === "users" && r.name === "email") ||
612
612
  r.primary_key
613
- ? ""
614
- : post_delete_btn(`/field/delete/${r.id}`, req, r.name),
615
- },
616
- ]),
613
+ ? ""
614
+ : post_delete_btn(`/field/delete/${r.id}`, req, r.name),
615
+ },
616
+ ]),
617
617
  ],
618
618
  fields,
619
619
  { hover: true }
@@ -622,17 +622,17 @@ router.get(
622
622
  tableHtml,
623
623
  inbound_refs.length > 0
624
624
  ? req.__("Inbound keys: ") +
625
- inbound_refs.map((tnm) => link(`/table/${tnm}`, tnm)).join(", ") +
626
- "<br>"
625
+ inbound_refs.map((tnm) => link(`/table/${tnm}`, tnm)).join(", ") +
626
+ "<br>"
627
627
  : "",
628
628
  !table.external &&
629
- a(
630
- {
631
- href: `/field/new/${table.id}`,
632
- class: "btn btn-primary add-field mt-2",
633
- },
634
- req.__("Add field")
635
- ),
629
+ a(
630
+ {
631
+ href: `/field/new/${table.id}`,
632
+ class: "btn btn-primary add-field mt-2",
633
+ },
634
+ req.__("Add field")
635
+ ),
636
636
  ];
637
637
  }
638
638
  var viewCard;
@@ -645,7 +645,7 @@ router.get(
645
645
  viewCardContents = mkTable(
646
646
  [
647
647
  { label: req.__("Name"), key: "name" },
648
- { label: req.__("Template"), key: "viewtemplate" },
648
+ { label: req.__("Pattern"), key: "viewtemplate" },
649
649
  {
650
650
  label: req.__("Run"),
651
651
  key: (r) =>
@@ -704,8 +704,8 @@ router.get(
704
704
  table.name === "users"
705
705
  ? `/useradmin/`
706
706
  : fields.length === 1
707
- ? `javascript:;` // Fix problem with edition of table with only one column ID / Primary Key
708
- : `/list/${table.name}`,
707
+ ? `javascript:;` // Fix problem with edition of table with only one column ID / Primary Key
708
+ : `/list/${table.name}`,
709
709
  },
710
710
  i({ class: "fas fa-2x fa-edit" }),
711
711
  "<br/>",
@@ -725,74 +725,74 @@ router.get(
725
725
  )
726
726
  ),
727
727
  !table.external &&
728
- div(
729
- { class: "mx-auto" },
730
- form(
731
- {
732
- method: "post",
733
- action: `/table/upload_to_table/${table.name}`,
734
- encType: "multipart/form-data",
735
- },
736
- input({ type: "hidden", name: "_csrf", value: req.csrfToken() }),
737
- label(
738
- { class: "btn-link", for: "upload_to_table" },
739
- i({ class: "fas fa-2x fa-upload" }),
740
- "<br/>",
741
- req.__("Upload CSV")
742
- ),
743
- input({
744
- id: "upload_to_table",
745
- name: "file",
746
- type: "file",
747
- accept: "text/csv,.csv",
748
- onchange: "this.form.submit();",
749
- })
750
- )
751
- ),
728
+ div(
729
+ { class: "mx-auto" },
730
+ form(
731
+ {
732
+ method: "post",
733
+ action: `/table/upload_to_table/${table.name}`,
734
+ encType: "multipart/form-data",
735
+ },
736
+ input({ type: "hidden", name: "_csrf", value: req.csrfToken() }),
737
+ label(
738
+ { class: "btn-link", for: "upload_to_table" },
739
+ i({ class: "fas fa-2x fa-upload" }),
740
+ "<br/>",
741
+ req.__("Upload CSV")
742
+ ),
743
+ input({
744
+ id: "upload_to_table",
745
+ name: "file",
746
+ type: "file",
747
+ accept: "text/csv,.csv",
748
+ onchange: "this.form.submit();",
749
+ })
750
+ )
751
+ ),
752
752
  // only if table is not external
753
753
  !table.external &&
754
- div(
755
- { class: "mx-auto" },
756
- settingsDropdown(`dataMenuButton`, [
757
- a(
758
- {
759
- class: "dropdown-item",
760
- href: `/table/constraints/${table.id}`,
761
- },
762
- '<i class="fas fa-ban"></i>&nbsp;' + req.__("Constraints")
763
- ),
764
- // rename table doesnt supported for sqlite
765
- !db.isSQLite &&
766
- table.name !== "users" &&
767
- a(
768
- {
769
- class: "dropdown-item",
770
- href: `/table/rename/${table.id}`,
771
- },
772
- '<i class="fas fa-edit"></i>&nbsp;' + req.__("Rename table")
773
- ),
774
- post_dropdown_item(
775
- `/table/recalc-stored/${table.name}`,
776
- '<i class="fas fa-sync"></i>&nbsp;' +
777
- req.__("Recalculate stored fields"),
778
- req
779
- ),
780
- post_dropdown_item(
781
- `/table/delete-all-rows/${table.name}`,
782
- '<i class="far fa-trash-alt"></i>&nbsp;' +
783
- req.__("Delete all rows"),
784
- req,
785
- true
786
- ),
787
- table.name !== "users" &&
788
- post_dropdown_item(
789
- `/table/forget-table/${table.id}`,
790
- '<i class="fas fa-recycle"></i>&nbsp;' + req.__("Forget table"),
791
- req,
792
- true
793
- ),
794
- ])
795
- )
754
+ div(
755
+ { class: "mx-auto" },
756
+ settingsDropdown(`dataMenuButton`, [
757
+ a(
758
+ {
759
+ class: "dropdown-item",
760
+ href: `/table/constraints/${table.id}`,
761
+ },
762
+ '<i class="fas fa-ban"></i>&nbsp;' + req.__("Constraints")
763
+ ),
764
+ // rename table doesnt supported for sqlite
765
+ !db.isSQLite &&
766
+ table.name !== "users" &&
767
+ a(
768
+ {
769
+ class: "dropdown-item",
770
+ href: `/table/rename/${table.id}`,
771
+ },
772
+ '<i class="fas fa-edit"></i>&nbsp;' + req.__("Rename table")
773
+ ),
774
+ post_dropdown_item(
775
+ `/table/recalc-stored/${table.name}`,
776
+ '<i class="fas fa-sync"></i>&nbsp;' +
777
+ req.__("Recalculate stored fields"),
778
+ req
779
+ ),
780
+ post_dropdown_item(
781
+ `/table/delete-all-rows/${table.name}`,
782
+ '<i class="far fa-trash-alt"></i>&nbsp;' +
783
+ req.__("Delete all rows"),
784
+ req,
785
+ true
786
+ ),
787
+ table.name !== "users" &&
788
+ post_dropdown_item(
789
+ `/table/forget-table/${table.id}`,
790
+ '<i class="fas fa-recycle"></i>&nbsp;' + req.__("Forget table"),
791
+ req,
792
+ true
793
+ ),
794
+ ])
795
+ )
796
796
  );
797
797
  // add table form
798
798
  if (table.ownership_formula && !table.ownership_field_id)
@@ -815,12 +815,12 @@ router.get(
815
815
  },
816
816
  ...(fields.length > 0
817
817
  ? [
818
- {
819
- type: "card",
820
- title: req.__("Table data"),
821
- contents: dataCard,
822
- },
823
- ]
818
+ {
819
+ type: "card",
820
+ title: req.__("Table data"),
821
+ contents: dataCard,
822
+ },
823
+ ]
824
824
  : []),
825
825
  ...(viewCard ? [viewCard] : []),
826
826
  {
@@ -910,7 +910,8 @@ router.post(
910
910
  );
911
911
  else if (!hasError) req.flash("success", req.__("Table saved"));
912
912
 
913
- res.redirect(`/table/${id}`);
913
+ if (!req.xhr) res.redirect(`/table/${id}`);
914
+ else res.json({ success: "ok" });
914
915
  }
915
916
  })
916
917
  );
@@ -1013,39 +1014,39 @@ router.get(
1013
1014
  const mainCard =
1014
1015
  rows.length > 0
1015
1016
  ? mkTable(
1016
- [
1017
- {
1018
- label: req.__("Name"),
1019
- key: (r) => link(`/table/${r.id || r.name}`, text(r.name)),
1020
- },
1021
- {
1022
- label: "",
1023
- key: (r) => tableBadges(r, req),
1024
- },
1025
- {
1026
- label: req.__("Access Read/Write"),
1027
- key: (t) =>
1028
- t.external
1029
- ? `${getRole(t.min_role_read)} (read only)`
1030
- : `${getRole(t.min_role_read)}/${getRole(
1031
- t.min_role_write
1032
- )}`,
1033
- },
1034
- {
1035
- label: req.__("Delete"),
1036
- key: (r) =>
1037
- r.name === "users" || r.external
1038
- ? ""
1039
- : post_delete_btn(`/table/delete/${r.id}`, req, r.name),
1040
- },
1041
- ],
1042
- rows,
1043
- { hover: true }
1044
- )
1017
+ [
1018
+ {
1019
+ label: req.__("Name"),
1020
+ key: (r) => link(`/table/${r.id || r.name}`, text(r.name)),
1021
+ },
1022
+ {
1023
+ label: "",
1024
+ key: (r) => tableBadges(r, req),
1025
+ },
1026
+ {
1027
+ label: req.__("Access Read/Write"),
1028
+ key: (t) =>
1029
+ t.external
1030
+ ? `${getRole(t.min_role_read)} (read only)`
1031
+ : `${getRole(t.min_role_read)}/${getRole(
1032
+ t.min_role_write
1033
+ )}`,
1034
+ },
1035
+ {
1036
+ label: req.__("Delete"),
1037
+ key: (r) =>
1038
+ r.name === "users" || r.external
1039
+ ? ""
1040
+ : post_delete_btn(`/table/delete/${r.id}`, req, r.name),
1041
+ },
1042
+ ],
1043
+ rows,
1044
+ { hover: true }
1045
+ )
1045
1046
  : div(
1046
- h4(req.__("No tables defined")),
1047
- p(req.__("Tables hold collections of similar data"))
1048
- );
1047
+ h4(req.__("No tables defined")),
1048
+ p(req.__("Tables hold collections of similar data"))
1049
+ );
1049
1050
  const createCard = div(
1050
1051
  h5(req.__("Create table")),
1051
1052
  a(
@@ -1062,11 +1063,11 @@ router.get(
1062
1063
  req.__("Create from CSV upload")
1063
1064
  ),
1064
1065
  !db.isSQLite &&
1065
- a(
1066
- { href: `/table/discover`, class: "btn btn-secondary mt-1" },
1067
- i({ class: "fas fa-map-signs me-1" }),
1068
- req.__("Discover tables")
1069
- )
1066
+ a(
1067
+ { href: `/table/discover`, class: "btn btn-secondary mt-1" },
1068
+ i({ class: "fas fa-map-signs me-1" }),
1069
+ req.__("Discover tables")
1070
+ )
1070
1071
  );
1071
1072
  res.sendWrap(req.__("Tables"), {
1072
1073
  above: [
package/routes/tenant.js CHANGED
@@ -161,32 +161,32 @@ router.get(
161
161
  req.__(
162
162
  "Hosting on this site is provided for free and with no guarantee of availability or security of your application. "
163
163
  ) +
164
- " " +
165
- req.__(
166
- "This facility is intended solely for you to evaluate the suitability of Saltcorn. "
167
- ) +
168
- " " +
169
- req.__(
170
- "If you would like to store private information that needs to be secure, please use self-hosted Saltcorn. "
171
- ) +
172
- " " +
173
- req.__(
174
- 'See <a href="https://github.com/saltcorn/saltcorn">GitHub repository</a> for instructions<p>'
175
- )
164
+ " " +
165
+ req.__(
166
+ "This facility is intended solely for you to evaluate the suitability of Saltcorn. "
167
+ ) +
168
+ " " +
169
+ req.__(
170
+ "If you would like to store private information that needs to be secure, please use self-hosted Saltcorn. "
171
+ ) +
172
+ " " +
173
+ req.__(
174
+ 'See <a href="https://github.com/saltcorn/saltcorn">GitHub repository</a> for instructions<p>'
175
+ )
176
176
  )
177
177
  );
178
178
 
179
179
  res.sendWrap(
180
180
  req.__("Create application"),
181
181
  create_tenant_warning +
182
- renderForm(tenant_form(req), req.csrfToken()) +
183
- p(
184
- { class: "mt-2" },
185
- req.__("To login to a previously created application, go to: "),
186
- code(`${req.protocol}://`) +
187
- i(req.__("Application name")) +
188
- code("." + req.hostname)
189
- )
182
+ renderForm(tenant_form(req), req.csrfToken()) +
183
+ p(
184
+ { class: "mt-2" },
185
+ req.__("To login to a previously created application, go to: "),
186
+ code(`${req.protocol}://`) +
187
+ i(req.__("Application name")) +
188
+ code("." + req.hostname)
189
+ )
190
190
  );
191
191
  })
192
192
  );
@@ -294,13 +294,13 @@ router.post(
294
294
  " " +
295
295
  hasTemplate
296
296
  ? req.__(
297
- 'Use this link: <a href="%s">%s</a> to revisit your application at any time.',
298
- newurl,
299
- newurl
300
- )
297
+ 'Use this link: <a href="%s">%s</a> to revisit your application at any time.',
298
+ newurl,
299
+ newurl
300
+ )
301
301
  : req.__(
302
- "Use this link to revisit your application at any time."
303
- )
302
+ "Use this link to revisit your application at any time."
303
+ )
304
304
  )
305
305
  )
306
306
  );
@@ -452,8 +452,10 @@ router.post(
452
452
  } else {
453
453
  await save_config_from_form(form);
454
454
 
455
- req.flash("success", req.__("Tenant settings updated"));
456
- res.redirect("/tenant/settings");
455
+ if (!req.xhr) {
456
+ req.flash("success", req.__("Tenant settings updated"));
457
+ res.redirect("/tenant/settings");
458
+ } else res.json({ success: "ok" });
457
459
  }
458
460
  })
459
461
  );
@@ -584,7 +586,7 @@ router.get(
584
586
  td(a({ href: info.base_url + "actions" }, info.nactions))
585
587
  ),
586
588
  tr(
587
- th(req.__("Plugins")),
589
+ th(req.__("Modules")),
588
590
  td(a({ href: info.base_url + "plugins" }, info.nplugins))
589
591
  ),
590
592
  tr(
package/routes/utils.js CHANGED
@@ -128,6 +128,7 @@ const setTenant = (req, res, next) => {
128
128
  } else {
129
129
  db.runWithTenant(other_domain, () => {
130
130
  setLanguage(req, res, state);
131
+ state.log(5, `${req.method} ${req.originalUrl}`);
131
132
  next();
132
133
  });
133
134
  }
@@ -140,12 +141,14 @@ const setTenant = (req, res, next) => {
140
141
  } else {
141
142
  db.runWithTenant(ten, () => {
142
143
  setLanguage(req, res, state);
144
+ state.log(5, `${req.method} ${req.originalUrl}`);
143
145
  next();
144
146
  });
145
147
  }
146
148
  }
147
149
  } else {
148
150
  setLanguage(req, res);
151
+ getState().log(5, `${req.method} ${req.originalUrl}`);
149
152
  next();
150
153
  }
151
154
  };
@@ -240,4 +243,5 @@ module.exports = {
240
243
  getGitRevision,
241
244
  getSessionStore,
242
245
  setTenant,
246
+ get_tenant_from_req
243
247
  };