@saltcorn/server 0.7.2-beta.0 → 0.7.2-beta.10

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.
@@ -1,332 +1,14 @@
1
- //https://stackoverflow.com/a/698386
2
- jQuery.fn.swapWith = function (to) {
3
- return this.each(function () {
4
- var copy_to = $(to).clone(true);
5
- var copy_from = $(this).clone(true);
6
- $(to).replaceWith(copy_from);
7
- $(this).replaceWith(copy_to);
8
- });
9
- };
10
-
11
- //avoids hiding in overflow:hidden
12
- function init_bs5_dropdowns() {
13
- $("body").on(
14
- "show.bs.dropdown",
15
- "table [data-bs-toggle=dropdown]",
16
- function () {
17
- let target;
18
- if (!$("#page-inner-content").length) target = $("body");
19
- else target = $("#page-inner-content");
20
- let dropdown = bootstrap.Dropdown.getInstance(this);
21
- $(dropdown._menu).insertAfter(target);
22
- }
23
- );
24
- }
25
1
  function sortby(k, desc) {
26
2
  set_state_fields({ _sortby: k, _sortdesc: desc ? "on" : { unset: true } });
27
3
  }
28
4
  function gopage(n, pagesize, extra = {}) {
29
5
  set_state_fields({ ...extra, _page: n, _pagesize: pagesize });
30
6
  }
31
- function add_repeater(nm) {
32
- var es = $("div.form-repeat.repeat-" + nm);
33
- var e = es.first();
34
- var newix = es.length;
35
- var newe = $(e).clone();
36
- newe.find("[name]").each(function (ix, element) {
37
- var newnm = (element.name || "").replace("_0", "_" + newix);
38
- var newid = (element.id || "").replace("_0", "_" + newix);
39
- $(element).attr("name", newnm).attr("id", newid);
40
- });
41
- newe.appendTo($("div.repeats-" + nm));
42
- }
43
- // "e.closest('.form-namespace').find('.coltype').val()==='Field';"
44
- function apply_showif() {
45
- $("[data-show-if]").each(function (ix, element) {
46
- var e = $(element);
47
- try {
48
- var to_show = new Function(
49
- "e",
50
- "return " + decodeURIComponent(e.attr("data-show-if"))
51
- );
52
- if (to_show(e))
53
- e.show()
54
- .find("input, textarea, button, select")
55
- .prop("disabled", e.attr("data-disabled") || false);
56
- else
57
- e.hide().find("input, textarea, button, select").prop("disabled", true);
58
- } catch (e) {
59
- console.error(e);
60
- }
61
- });
62
- $("[data-calc-options]").each(function (ix, element) {
63
- var e = $(element);
64
- var data = JSON.parse(decodeURIComponent(e.attr("data-calc-options")));
65
-
66
- var val = e
67
- .closest(".form-namespace")
68
- .find(`[data-fieldname=${data[0]}]`)
69
- .val();
70
7
 
71
- var options = data[1][val];
72
- var current = e.attr("data-selected");
73
- //console.log(val, options, current,data)
74
- e.empty();
75
- (options || []).forEach((o) => {
76
- if (!(o && o.label && o.value)) {
77
- if (`${current}` === `${o}`)
78
- e.append($("<option selected>" + o + "</option>"));
79
- else e.append($("<option>" + o + "</option>"));
80
- } else {
81
- e.append(
82
- $(
83
- `<option ${
84
- `${current}` === `${o.value}` ? "selected" : ""
85
- } value="${o.value}">${o.label}</option>`
86
- )
87
- );
88
- }
89
- });
90
- e.change(function (ec) {
91
- e.attr("data-selected", ec.target.value);
92
- });
93
- });
94
- $("[data-source-url]").each(function (ix, element) {
95
- const e = $(element);
96
- const rec = get_form_record(e);
97
- ajax_post_json(e.attr("data-source-url"), rec, {
98
- success: (data) => {
99
- e.html(data);
100
- },
101
- error: (err) => {
102
- console.error(err);
103
- e.html("");
104
- },
105
- });
106
- });
107
- }
108
- function get_form_record(e, select_labels) {
109
- const rec = {};
110
- e.closest("form")
111
- .find("input[name],select[name]")
112
- .each(function () {
113
- if (select_labels && $(this).prop("tagName").toLowerCase() === "select")
114
- rec[$(this).attr("name")] = $(this).find("option:selected").text();
115
- else if ($(this).prop("type") === "checkbox")
116
- rec[$(this).attr("name")] = $(this).prop("checked");
117
- else rec[$(this).attr("name")] = $(this).val();
118
- });
119
- return rec;
120
- }
121
- function showIfFormulaInputs(e, fml) {
122
- const rec = get_form_record(e);
123
- return new Function(`{${Object.keys(rec).join(",")}}`, "return " + fml)(rec);
124
- }
125
-
126
- function rep_del(e) {
127
- var myrep = $(e).closest(".form-repeat");
128
- var ix = myrep.index();
129
- var parent = myrep.parent();
130
- parent.children().each(function (childix, element) {
131
- if (childix > ix) {
132
- reindex(element, childix, childix - 1);
133
- }
134
- });
135
- myrep.remove();
136
- }
137
-
138
- function reindex(element, oldix, newix) {
139
- $(element).html(
140
- $(element)
141
- .html()
142
- .split("_" + oldix)
143
- .join("_" + newix)
144
- );
145
- }
146
-
147
- function get_form_subset_record(e) {
148
- const rec = {};
149
- e.find("input[name],select[name]").each(function () {
150
- rec[$(this).attr("name")] = $(this).val();
151
- });
152
- return rec;
153
- }
154
-
155
- function apply_form_subset_record(e, vals) {
156
- e.find("input[name],select[name]").each(function () {
157
- var name = $(this).attr("name");
158
- if (vals[name]) $(this).val(vals[name]);
159
- });
160
- }
161
-
162
- function reindex_form_record(vals, oldix, newix) {
163
- const rec = {};
164
- Object.keys(vals).forEach((k) => {
165
- const newkey = k.split("_" + oldix).join("_" + newix);
166
- rec[newkey] = vals[k];
167
- });
168
- return rec;
169
- }
170
-
171
- function rep_up(e) {
172
- var myrep = $(e).closest(".form-repeat");
173
- var theform = $(e).closest("form");
174
- var ix = myrep.index();
175
- var parent = myrep.parent();
176
- if (ix > 0) {
177
- var swap_with = parent.children(".form-repeat").eq(ix - 1);
178
- var vals1 = reindex_form_record(get_form_subset_record(myrep), ix, ix - 1);
179
- var vals2 = reindex_form_record(
180
- get_form_subset_record(swap_with),
181
- ix - 1,
182
- ix
183
- );
184
- reindex(myrep, ix, ix - 1);
185
- reindex(swap_with, ix - 1, ix);
186
- $(myrep).swapWith(swap_with);
187
- apply_form_subset_record(theform, vals2);
188
- apply_form_subset_record(theform, vals1);
189
- }
190
- }
191
-
192
- function rep_down(e) {
193
- var myrep = $(e).closest(".form-repeat");
194
- var theform = $(e).closest("form");
195
- var ix = myrep.index();
196
- var parent = myrep.parent();
197
- var nchildren = parent.children(".form-repeat").length;
198
- if (ix < nchildren - 1) {
199
- var swap_with = parent.children(".form-repeat").eq(ix + 1);
200
- var vals1 = reindex_form_record(get_form_subset_record(myrep), ix, ix + 1);
201
- var vals2 = reindex_form_record(
202
- get_form_subset_record(swap_with),
203
- ix + 1,
204
- ix
205
- );
206
- reindex(myrep, ix, ix + 1);
207
- reindex(swap_with, ix + 1, ix);
208
- $(myrep).swapWith(swap_with);
209
- apply_form_subset_record(theform, vals2);
210
- apply_form_subset_record(theform, vals1);
211
- }
212
- }
213
-
214
- function reload_on_init() {
215
- localStorage.setItem("reload_on_init", true);
216
- }
217
8
  if (localStorage.getItem("reload_on_init")) {
218
9
  localStorage.removeItem("reload_on_init");
219
10
  location.reload();
220
11
  }
221
- function initialize_page() {
222
- $("form").change(apply_showif);
223
- apply_showif();
224
- apply_showif();
225
- $("[data-inline-edit-dest-url]").each(function () {
226
- if ($(this).find(".editicon").length === 0) {
227
- var current = $(this).html();
228
- $(this).html(
229
- `<span class="current">${current}</span><i class="editicon fas fa-edit ms-1"></i>`
230
- );
231
- }
232
- });
233
- $("[data-inline-edit-dest-url]").click(function () {
234
- var url = $(this).attr("data-inline-edit-dest-url");
235
- var current = $(this).children("span.current").html();
236
- $(this).replaceWith(
237
- `<form method="post" action="${url}" >
238
- <input type="hidden" name="_csrf" value="${_sc_globalCsrf}">
239
- <input type="text" name="value" value="${current}">
240
- <button type="submit" class="btn btn-sm btn-primary">OK</button>
241
- </form>`
242
- );
243
- });
244
- function setExplainer(that) {
245
- var id = $(that).attr("id") + "_explainer";
246
-
247
- var explainers = JSON.parse(
248
- decodeURIComponent($(that).attr("data-explainers"))
249
- );
250
- var currentVal = explainers[$(that).val()];
251
- $("#" + id).html(`<strong>${$(that).val()}</strong>: ${currentVal}`);
252
- if (currentVal) $("#" + id).show();
253
- else $("#" + id).hide();
254
- }
255
- $("[data-explainers]").each(function () {
256
- var id = $(this).attr("id") + "_explainer";
257
- if ($("#" + id).length === 0) {
258
- $(this).after(`<div class="alert alert-info my-2" id="${id}"></div>`);
259
- setExplainer(this);
260
- }
261
- });
262
- $("[data-explainers]").change(function () {
263
- setExplainer(this);
264
- });
265
-
266
- const codes = [];
267
- $("textarea.to-code").each(function () {
268
- codes.push(this);
269
- });
270
- if (codes.length > 0)
271
- enable_codemirror(() => {
272
- setTimeout(() => {
273
- codes.forEach((el) => {
274
- //console.log($(el).attr("mode"), el);
275
- CodeMirror.fromTextArea(el, {
276
- lineNumbers: true,
277
- mode: $(el).attr("mode"),
278
- });
279
- });
280
- }, 100);
281
- });
282
- const locale =
283
- navigator.userLanguage ||
284
- (navigator.languages &&
285
- navigator.languages.length &&
286
- navigator.languages[0]) ||
287
- navigator.language ||
288
- navigator.browserLanguage ||
289
- navigator.systemLanguage ||
290
- "en";
291
- window.detected_locale = locale;
292
- const parse = (s) => JSON.parse(decodeURIComponent(s));
293
- $("time[locale-time-options]").each(function () {
294
- var el = $(this);
295
- var date = new Date(el.attr("datetime"));
296
- const options = parse(el.attr("locale-time-options"));
297
- el.text(date.toLocaleTimeString(locale, options));
298
- });
299
- $("time[locale-options]").each(function () {
300
- var el = $(this);
301
- var date = new Date(el.attr("datetime"));
302
- const options = parse(el.attr("locale-options"));
303
- el.text(date.toLocaleString(locale, options));
304
- });
305
- $("time[locale-date-options]").each(function () {
306
- var el = $(this);
307
- var date = new Date(el.attr("datetime"));
308
- const options = parse(el.attr("locale-date-options"));
309
- el.text(date.toLocaleDateString(locale, options));
310
- });
311
- $('a[data-bs-toggle="tab"].deeplink').historyTabs();
312
- init_bs5_dropdowns();
313
- }
314
-
315
- $(initialize_page);
316
-
317
- function enable_codemirror(f) {
318
- $("<link/>", {
319
- rel: "stylesheet",
320
- type: "text/css",
321
- href: `/static_assets/${_sc_version_tag}/codemirror.css`,
322
- }).appendTo("head");
323
- $.ajax({
324
- url: `/static_assets/${_sc_version_tag}/codemirror.min.js`,
325
- dataType: "script",
326
- cache: true,
327
- success: f,
328
- });
329
- }
330
12
 
331
13
  //https://stackoverflow.com/a/6021027
332
14
  function updateQueryStringParameter(uri1, key, value) {
@@ -441,75 +123,9 @@ function href_to(href) {
441
123
  function clear_state() {
442
124
  pjax_to(window.location.href.split("?")[0]);
443
125
  }
444
- function tristateClick(nm) {
445
- var current = $(`button#trib${nm}`).html();
446
- switch (current) {
447
- case "?":
448
- $(`button#trib${nm}`).html("T");
449
- $(`input#input${nm}`).val("on");
450
- break;
451
- case "T":
452
- $(`button#trib${nm}`).html("F");
453
- $(`input#input${nm}`).val("off");
454
- break;
455
- default:
456
- $(`button#trib${nm}`).html("?");
457
- $(`input#input${nm}`).val("?");
458
- break;
459
- }
460
- }
461
-
462
- function notifyAlert(note, spin) {
463
- if (Array.isArray(note)) {
464
- note.forEach(notifyAlert);
465
- return;
466
- }
467
- var txt, type;
468
- if (typeof note == "string") {
469
- txt = note;
470
- type = "info";
471
- } else {
472
- txt = note.text;
473
- type = note.type;
474
- }
475
-
476
- $("#alerts-area")
477
- .append(`<div class="alert alert-${type} alert-dismissible fade show ${
478
- spin ? "d-flex align-items-center" : ""
479
- }" role="alert">
480
- ${txt}
481
- ${
482
- spin
483
- ? `<div class="spinner-border ms-auto" role="status" aria-hidden="true"></div>`
484
- : `<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
485
- </button>`
486
- }
487
- </div>`);
488
- }
489
126
 
490
127
  function ajax_done(res) {
491
- if (res.notify) notifyAlert(res.notify);
492
- if (res.error) notifyAlert({ type: "danger", text: res.error });
493
- if (res.eval_js) eval(res.eval_js);
494
- if (res.reload_page) location.reload(); //TODO notify to cookie if reload or goto
495
- if (res.download) {
496
- const dataurl = `data:${
497
- res.download.mimetype || "application/octet-stream"
498
- };base64,${res.download.blob}`;
499
- fetch(dataurl)
500
- .then((res) => res.blob())
501
- .then((blob) => {
502
- const link = document.createElement("a");
503
- link.href = window.URL.createObjectURL(blob);
504
- if (res.download.filename) link.download = res.download.filename;
505
- else link.target = "_blank";
506
- link.click();
507
- });
508
- }
509
- if (res.goto) {
510
- if (res.target === "_blank") window.open(res.goto, "_blank").focus();
511
- else window.location.href = res.goto;
512
- }
128
+ common_done(res);
513
129
  }
514
130
 
515
131
  function view_post(viewname, route, data, onDone) {
@@ -546,11 +162,6 @@ function globalErrorCatcher(message, source, lineno, colno, error) {
546
162
  });
547
163
  }
548
164
 
549
- function press_store_button(clicked) {
550
- const width = $(clicked).width();
551
- $(clicked).html('<i class="fas fa-spinner fa-spin"></i>').width(width);
552
- }
553
-
554
165
  function ajax_modal(url, opts = {}) {
555
166
  if ($("#scmodal").length === 0) {
556
167
  $("body").append(`<div id="scmodal", class="modal">
@@ -591,6 +202,7 @@ function ajax_modal(url, opts = {}) {
591
202
 
592
203
  function saveAndContinue(e, k) {
593
204
  var form = $(e).closest("form");
205
+ submitWithEmptyAction(form[0]);
594
206
  var url = form.attr("action");
595
207
  var form_data = form.serialize();
596
208
  $.ajax(url, {
@@ -639,36 +251,17 @@ function applyViewConfig(e, url) {
639
251
  return false;
640
252
  }
641
253
 
642
- const repeaterCopyValuesToForm = (form, editor) => {
643
- const vs = JSON.parse(editor.getString());
644
- //console.log(vs)
645
- const setVal = (k, ix, v) => {
646
- const $e = form.find(`input[name="${k}_${ix}"]`);
647
- if ($e.length) $e.val(v);
648
- else
649
- form.append(
650
- `<input type="hidden" name="${k}_${ix}" value="${v}"></input>`
651
- );
652
- };
653
- vs.forEach((v, ix) => {
654
- Object.entries(v).forEach(([k, v]) => {
655
- //console.log(ix, k, typeof v, v)
656
- if (typeof v === "boolean") setVal(k, ix, v ? "on" : "");
657
- else setVal(k, ix, v);
658
- });
659
- });
660
- };
661
-
662
254
  function ajaxSubmitForm(e) {
663
255
  var form = $(e).closest("form");
664
256
  var url = form.attr("action");
665
- var form_data = form.serialize();
666
257
  $.ajax(url, {
667
258
  type: "POST",
668
259
  headers: {
669
260
  "CSRF-Token": _sc_globalCsrf,
670
261
  },
671
- data: form_data,
262
+ data: new FormData(form[0]),
263
+ processData: false,
264
+ contentType: false,
672
265
  success: function () {
673
266
  var no_reload = $("#scmodal").hasClass("no-submit-reload");
674
267
  $("#scmodal").modal("hide");
@@ -743,31 +336,16 @@ function make_unique_field(
743
336
  type: "GET",
744
337
  success: function (res) {
745
338
  if (res.success) {
746
- const gen_char = (i) => {
747
- switch (char_type) {
748
- case "Lowercase Letters":
749
- return String.fromCharCode("a".charCodeAt(0) + i);
750
- break;
751
- case "Uppercase Letters":
752
- return String.fromCharCode("A".charCodeAt(0) + i);
753
- break;
754
- default:
755
- return i;
756
- break;
757
- }
758
- };
759
- const vals = res.success
760
- .map((o) => o[field_name])
761
- .filter((s) => s.startsWith(value));
762
- if (vals.includes(value) || always_append) {
763
- for (let i = start || 0; i < vals.length + (start || 0) + 2; i++) {
764
- const newname = `${value}${space ? " " : ""}${gen_char(i)}`;
765
- if (!vals.includes(newname)) {
766
- $("#" + id).val(newname);
767
- return;
768
- }
769
- }
770
- }
339
+ unique_field_from_rows(
340
+ res.success,
341
+ id,
342
+ field_name,
343
+ space,
344
+ start,
345
+ always_append,
346
+ char_type,
347
+ value
348
+ );
771
349
  }
772
350
  },
773
351
  }
@@ -782,26 +360,6 @@ function test_formula(tablename, stored) {
782
360
  },
783
361
  });
784
362
  }
785
- function align_dropdown(id) {
786
- setTimeout(() => {
787
- if ($("#dm" + id).hasClass("show")) {
788
- var inputWidth = $("#search-input-group-" + id).outerWidth();
789
- $("#dm" + id).css("width", inputWidth);
790
- var d0pos = $("#search-input-group-" + id).offset();
791
- $("#dm" + id).offset({ left: d0pos.left });
792
- $(document).on("click", "#dm" + id, function (e) {
793
- e.stopPropagation();
794
- });
795
- }
796
- }, 0);
797
- }
798
-
799
- function remove_outline(form) {
800
- $(form)
801
- .find("button[type=submit]")
802
- .removeClass("btn-outline-primary")
803
- .addClass("btn-primary");
804
- }
805
363
 
806
364
  function init_room(viewname, room_id) {
807
365
  const socket = io({ transports: ["websocket"] });
@@ -871,25 +429,6 @@ async function fill_formula_btn_click(btn, k) {
871
429
  if (k) k();
872
430
  }
873
431
 
874
- const columnSummary = (col) => {
875
- if (!col) return "Unknown";
876
- switch (col.type) {
877
- case "Field":
878
- return `Field ${col.field_name} ${col.fieldview || ""}`;
879
- case "Link":
880
- return `Link ${col.link_text}`;
881
- case "JoinField":
882
- return `Join ${col.join_field}`;
883
- case "ViewLink":
884
- return `View link ${col.view_label || col.view.split(":")[1] || ""}`;
885
- case "Action":
886
- return `Action ${col.action_label || col.action_name}`;
887
- case "Aggregation":
888
- return `${col.stat} ${col.agg_field} ${col.agg_relation}`;
889
- default:
890
- return "Unknown";
891
- }
892
- };
893
432
 
894
433
  /*
895
434
  https://github.com/jeffdavidgreen/bootstrap-html5-history-tabs/blob/master/bootstrap-history-tabs.js
@@ -17,6 +17,7 @@ const relevantPackages = [
17
17
  "db-common",
18
18
  "postgres",
19
19
  "saltcorn-data",
20
+ "saltcorn-admin-models",
20
21
  "saltcorn-markup",
21
22
  "saltcorn-sbadmin2",
22
23
  "server",
@@ -28,7 +29,6 @@ const relevantPackages = [
28
29
  */
29
30
  const excludePatterns = [
30
31
  /\/node_modules/,
31
- /\/public/,
32
32
  /\.git/,
33
33
  /\.docs/,
34
34
  /\.docs/,