@saltcorn/server 0.8.3 → 0.8.5-beta.0
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 +2 -1
- package/package.json +8 -8
- package/public/saltcorn-common.js +105 -9
- package/routes/admin.js +0 -1
- package/routes/api.js +11 -2
package/locales/en.json
CHANGED
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5-beta.0",
|
|
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.
|
|
10
|
-
"@saltcorn/builder": "0.8.
|
|
11
|
-
"@saltcorn/data": "0.8.
|
|
12
|
-
"@saltcorn/admin-models": "0.8.
|
|
13
|
-
"@saltcorn/filemanager": "0.8.
|
|
14
|
-
"@saltcorn/markup": "0.8.
|
|
15
|
-
"@saltcorn/sbadmin2": "0.8.
|
|
9
|
+
"@saltcorn/base-plugin": "0.8.5-beta.0",
|
|
10
|
+
"@saltcorn/builder": "0.8.5-beta.0",
|
|
11
|
+
"@saltcorn/data": "0.8.5-beta.0",
|
|
12
|
+
"@saltcorn/admin-models": "0.8.5-beta.0",
|
|
13
|
+
"@saltcorn/filemanager": "0.8.5-beta.0",
|
|
14
|
+
"@saltcorn/markup": "0.8.5-beta.0",
|
|
15
|
+
"@saltcorn/sbadmin2": "0.8.5-beta.0",
|
|
16
16
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
17
17
|
"@socket.io/sticky": "^1.0.1",
|
|
18
18
|
"adm-zip": "0.5.10",
|
|
@@ -352,6 +352,20 @@ function rep_down(e) {
|
|
|
352
352
|
apply_form_subset_record(theform, vals1);
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
|
+
//https://stackoverflow.com/a/4835406
|
|
356
|
+
function escapeHtml(text) {
|
|
357
|
+
var map = {
|
|
358
|
+
"&": "&",
|
|
359
|
+
"<": "<",
|
|
360
|
+
">": ">",
|
|
361
|
+
'"': """,
|
|
362
|
+
"'": "'",
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
return text.replace(/[&<>"']/g, function (m) {
|
|
366
|
+
return map[m];
|
|
367
|
+
});
|
|
368
|
+
}
|
|
355
369
|
|
|
356
370
|
function reload_on_init() {
|
|
357
371
|
localStorage.setItem("reload_on_init", true);
|
|
@@ -408,18 +422,60 @@ function initialize_page() {
|
|
|
408
422
|
});
|
|
409
423
|
$("[data-inline-edit-dest-url]").click(function () {
|
|
410
424
|
var url = $(this).attr("data-inline-edit-dest-url");
|
|
411
|
-
var current =
|
|
425
|
+
var current =
|
|
426
|
+
$(this).attr("data-inline-edit-current") ||
|
|
427
|
+
$(this).children("span.current").html();
|
|
412
428
|
var key = $(this).attr("data-inline-edit-field") || "value";
|
|
413
429
|
var ajax = !!$(this).attr("data-inline-edit-ajax");
|
|
414
|
-
$(this).
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
430
|
+
var type = $(this).attr("data-inline-edit-type");
|
|
431
|
+
var is_key = type?.startsWith("Key:");
|
|
432
|
+
const opts = encodeURIComponent(
|
|
433
|
+
JSON.stringify({
|
|
434
|
+
url,
|
|
435
|
+
key,
|
|
436
|
+
ajax,
|
|
437
|
+
current,
|
|
438
|
+
current_label: $(this).attr("data-inline-edit-current-label"),
|
|
439
|
+
type,
|
|
440
|
+
is_key,
|
|
441
|
+
})
|
|
442
|
+
);
|
|
443
|
+
if (is_key) {
|
|
444
|
+
const [tblName, target] = type.replace("Key:", "").split(".");
|
|
445
|
+
$.ajax(`/api/${tblName}`).then((resp) => {
|
|
446
|
+
if (resp.success) {
|
|
447
|
+
const selopts = resp.success.map(
|
|
448
|
+
(r) =>
|
|
449
|
+
`<option ${current == r.id ? `selected ` : ``}value="${
|
|
450
|
+
r.id
|
|
451
|
+
}">${escapeHtml(r[target])}</option>`
|
|
452
|
+
);
|
|
453
|
+
$(this).replaceWith(
|
|
454
|
+
`<form method="post" action="${url}" ${
|
|
455
|
+
ajax ? `onsubmit="inline_ajax_submit(event, '${opts}')"` : ""
|
|
456
|
+
}>
|
|
457
|
+
<input type="hidden" name="_csrf" value="${_sc_globalCsrf}">
|
|
458
|
+
<select name="${key}" value="${current}">${selopts}
|
|
459
|
+
</select>
|
|
460
|
+
<button type="submit" class="btn btn-sm btn-primary">OK</button>
|
|
461
|
+
<button onclick="cancel_inline_edit(event, '${opts}')" type="button" class="btn btn-sm btn-danger"><i class="fas fa-times"></i></button>
|
|
462
|
+
</form>`
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
} else
|
|
467
|
+
$(this).replaceWith(
|
|
468
|
+
`<form method="post" action="${url}" ${
|
|
469
|
+
ajax ? `onsubmit="inline_ajax_submit(event, '${opts}')"` : ""
|
|
470
|
+
}>
|
|
418
471
|
<input type="hidden" name="_csrf" value="${_sc_globalCsrf}">
|
|
419
|
-
<input type="
|
|
472
|
+
<input type="${
|
|
473
|
+
type === "Integer" || type === "Float" ? "number" : "text"
|
|
474
|
+
}" name="${key}" value="${escapeHtml(current)}">
|
|
420
475
|
<button type="submit" class="btn btn-sm btn-primary">OK</button>
|
|
476
|
+
<button onclick="cancel_inline_edit(event, '${opts}')" type="button" class="btn btn-sm btn-danger"><i class="fas fa-times"></i></button>
|
|
421
477
|
</form>`
|
|
422
|
-
|
|
478
|
+
);
|
|
423
479
|
});
|
|
424
480
|
function setExplainer(that) {
|
|
425
481
|
var id = $(that).attr("id") + "_explainer";
|
|
@@ -531,10 +587,33 @@ function initialize_page() {
|
|
|
531
587
|
|
|
532
588
|
$(initialize_page);
|
|
533
589
|
|
|
534
|
-
function
|
|
590
|
+
function cancel_inline_edit(e, opts1) {
|
|
591
|
+
var opts = JSON.parse(decodeURIComponent(opts1 || "") || "{}");
|
|
592
|
+
var form = $(e.target).closest("form");
|
|
593
|
+
|
|
594
|
+
form.replaceWith(`<div
|
|
595
|
+
data-inline-edit-field="${opts.key}"
|
|
596
|
+
${opts.ajax ? `data-inline-edit-ajax="true"` : ""}
|
|
597
|
+
${opts.type ? `data-inline-edit-type="${opts.type}"` : ""}
|
|
598
|
+
${opts.current ? `data-inline-edit-current="${opts.current}"` : ""}
|
|
599
|
+
${
|
|
600
|
+
opts.current_label
|
|
601
|
+
? `data-inline-edit-current-label="${opts.current_label}"`
|
|
602
|
+
: ""
|
|
603
|
+
}
|
|
604
|
+
data-inline-edit-dest-url="${opts.url}">
|
|
605
|
+
<span class="current">${opts.current_label || opts.current}</span>
|
|
606
|
+
<i class="editicon fas fa-edit ms-1"></i>
|
|
607
|
+
</div>`);
|
|
608
|
+
initialize_page();
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function inline_ajax_submit(e, opts1) {
|
|
612
|
+
var opts = JSON.parse(decodeURIComponent(opts1 || "") || "{}");
|
|
535
613
|
e.preventDefault();
|
|
536
614
|
var form = $(e.target).closest("form");
|
|
537
615
|
var form_data = form.serialize();
|
|
616
|
+
var formDataArray = form.serializeArray();
|
|
538
617
|
var url = form.attr("action");
|
|
539
618
|
$.ajax(url, {
|
|
540
619
|
type: "POST",
|
|
@@ -543,7 +622,24 @@ function inline_ajax_submit(e) {
|
|
|
543
622
|
},
|
|
544
623
|
data: form_data,
|
|
545
624
|
success: function (res) {
|
|
546
|
-
|
|
625
|
+
if (opts) {
|
|
626
|
+
let rawVal = formDataArray.find((f) => f.name == opts.key).value;
|
|
627
|
+
let val = opts.is_key
|
|
628
|
+
? form.find("select").find("option:selected").text()
|
|
629
|
+
: rawVal;
|
|
630
|
+
|
|
631
|
+
$(e.target).replaceWith(`<div
|
|
632
|
+
data-inline-edit-field="${opts.key}"
|
|
633
|
+
${opts.ajax ? `data-inline-edit-ajax="true"` : ""}
|
|
634
|
+
${opts.type ? `data-inline-edit-type="${opts.type}"` : ""}
|
|
635
|
+
${opts.current ? `data-inline-edit-current="${rawVal}"` : ""}
|
|
636
|
+
${opts.current_label ? `data-inline-edit-current-label="${val}"` : ""}
|
|
637
|
+
data-inline-edit-dest-url="${opts.url}">
|
|
638
|
+
<span class="current">${val}</span>
|
|
639
|
+
<i class="editicon fas fa-edit ms-1"></i>
|
|
640
|
+
</div>`);
|
|
641
|
+
initialize_page();
|
|
642
|
+
} else location.reload();
|
|
547
643
|
},
|
|
548
644
|
error: function (e) {
|
|
549
645
|
ajax_done(
|
package/routes/admin.js
CHANGED
package/routes/api.js
CHANGED
|
@@ -423,11 +423,20 @@ router.post(
|
|
|
423
423
|
let hasErrors = false;
|
|
424
424
|
Object.keys(row).forEach((k) => {
|
|
425
425
|
const field = fields.find((f) => f.name === k);
|
|
426
|
-
if (!field
|
|
426
|
+
if (!field && k.includes(".")) {
|
|
427
|
+
const [fnm, jkey] = k.split(".");
|
|
428
|
+
const jfield = fields.find((f) => f.name === fnm);
|
|
429
|
+
if (jfield?.type?.name === "JSON") {
|
|
430
|
+
if (!row[fnm]) row[fnm] = { [jkey]: row[k] };
|
|
431
|
+
else row[fnm][jkey] = row[k];
|
|
432
|
+
delete row[k];
|
|
433
|
+
}
|
|
434
|
+
} else if (!field || field.calculated) {
|
|
427
435
|
delete row[k];
|
|
428
436
|
return;
|
|
429
437
|
}
|
|
430
|
-
|
|
438
|
+
|
|
439
|
+
if (field?.type && field.type.validate) {
|
|
431
440
|
const vres = field.type.validate(field.attributes || {})(row[k]);
|
|
432
441
|
if (vres.error) {
|
|
433
442
|
hasErrors = true;
|