@saltcorn/server 0.6.4 → 0.7.0-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/auth/admin.js +7 -7
- package/auth/routes.js +3 -3
- package/locales/en.json +2 -2
- package/locales/ru.json +104 -21
- package/markup/admin.js +2 -2
- package/markup/plugin-store.js +14 -14
- package/package.json +7 -7
- package/public/bootstrap-iconpicker.js +554 -0
- package/public/gridedit.js +1 -2
- package/public/jquery-menu-editor.min.js +781 -11
- package/public/saltcorn.css +4 -0
- package/public/saltcorn.js +64 -24
- package/routes/actions.js +4 -6
- package/routes/admin.js +7 -4
- package/routes/eventlog.js +2 -2
- package/routes/homepage.js +13 -13
- package/routes/infoarch.js +1 -1
- package/routes/list.js +15 -8
- package/routes/menu.js +1 -1
- package/routes/pageedit.js +1 -0
- package/routes/plugins.js +10 -12
- package/routes/settings.js +1 -1
- package/routes/tables.js +7 -8
- package/routes/utils.js +10 -6
- package/tests/plugins.test.js +6 -1
package/public/saltcorn.css
CHANGED
package/public/saltcorn.js
CHANGED
|
@@ -30,16 +30,20 @@ function add_repeater(nm) {
|
|
|
30
30
|
function apply_showif() {
|
|
31
31
|
$("[data-show-if]").each(function (ix, element) {
|
|
32
32
|
var e = $(element);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
e
|
|
39
|
-
.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
try {
|
|
34
|
+
var to_show = new Function(
|
|
35
|
+
"e",
|
|
36
|
+
"return " + decodeURIComponent(e.attr("data-show-if"))
|
|
37
|
+
);
|
|
38
|
+
if (to_show(e))
|
|
39
|
+
e.show()
|
|
40
|
+
.find("input, textarea, button, select")
|
|
41
|
+
.prop("disabled", e.attr("data-disabled") || false);
|
|
42
|
+
else
|
|
43
|
+
e.hide().find("input, textarea, button, select").prop("disabled", true);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
console.error(e);
|
|
46
|
+
}
|
|
43
47
|
});
|
|
44
48
|
$("[data-calc-options]").each(function (ix, element) {
|
|
45
49
|
var e = $(element);
|
|
@@ -55,8 +59,19 @@ function apply_showif() {
|
|
|
55
59
|
//console.log(val, options, current,data)
|
|
56
60
|
e.empty();
|
|
57
61
|
(options || []).forEach((o) => {
|
|
58
|
-
if (
|
|
59
|
-
|
|
62
|
+
if (!(o && o.label && o.value)) {
|
|
63
|
+
if (`${current}` === `${o}`)
|
|
64
|
+
e.append($("<option selected>" + o + "</option>"));
|
|
65
|
+
else e.append($("<option>" + o + "</option>"));
|
|
66
|
+
} else {
|
|
67
|
+
e.append(
|
|
68
|
+
$(
|
|
69
|
+
`<option ${
|
|
70
|
+
`${current}` === `${o.value}` ? "selected" : ""
|
|
71
|
+
} value="${o.value}">${o.label}</option>`
|
|
72
|
+
)
|
|
73
|
+
);
|
|
74
|
+
}
|
|
60
75
|
});
|
|
61
76
|
e.change(function (ec) {
|
|
62
77
|
e.attr("data-selected", ec.target.value);
|
|
@@ -76,12 +91,14 @@ function apply_showif() {
|
|
|
76
91
|
});
|
|
77
92
|
});
|
|
78
93
|
}
|
|
79
|
-
function get_form_record(e) {
|
|
94
|
+
function get_form_record(e, select_labels) {
|
|
80
95
|
const rec = {};
|
|
81
96
|
e.closest("form")
|
|
82
97
|
.find("input[name],select[name]")
|
|
83
98
|
.each(function () {
|
|
84
|
-
|
|
99
|
+
if (select_labels && $(this).prop("tagName").toLowerCase() === "select")
|
|
100
|
+
rec[$(this).attr("name")] = $(this).find("option:selected").text();
|
|
101
|
+
else rec[$(this).attr("name")] = $(this).val();
|
|
85
102
|
});
|
|
86
103
|
return rec;
|
|
87
104
|
}
|
|
@@ -193,7 +210,7 @@ function initialize_page() {
|
|
|
193
210
|
if ($(this).find(".editicon").length === 0) {
|
|
194
211
|
var current = $(this).html();
|
|
195
212
|
$(this).html(
|
|
196
|
-
`<span class="current">${current}</span><i class="editicon fas fa-edit
|
|
213
|
+
`<span class="current">${current}</span><i class="editicon fas fa-edit ms-1"></i>`
|
|
197
214
|
);
|
|
198
215
|
}
|
|
199
216
|
});
|
|
@@ -275,7 +292,7 @@ function initialize_page() {
|
|
|
275
292
|
const options = parse(el.attr("locale-date-options"));
|
|
276
293
|
el.text(date.toLocaleDateString(locale, options));
|
|
277
294
|
});
|
|
278
|
-
$('a[data-toggle="tab"]').historyTabs();
|
|
295
|
+
$('a[data-bs-toggle="tab"].deeplink').historyTabs();
|
|
279
296
|
}
|
|
280
297
|
|
|
281
298
|
$(initialize_page);
|
|
@@ -423,8 +440,7 @@ function notifyAlert(note) {
|
|
|
423
440
|
$("#alerts-area")
|
|
424
441
|
.append(`<div class="alert alert-${type} alert-dismissible fade show" role="alert">
|
|
425
442
|
${txt}
|
|
426
|
-
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
427
|
-
<span aria-hidden="true">×</span>
|
|
443
|
+
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
|
428
444
|
</button>
|
|
429
445
|
</div>`);
|
|
430
446
|
}
|
|
@@ -499,8 +515,7 @@ function ajax_modal(url, opts = {}) {
|
|
|
499
515
|
<div class="modal-content">
|
|
500
516
|
<div class="modal-header">
|
|
501
517
|
<h5 class="modal-title">Modal title</h5>
|
|
502
|
-
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
503
|
-
<span aria-hidden="true">×</span>
|
|
518
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
|
504
519
|
</button>
|
|
505
520
|
</div>
|
|
506
521
|
<div class="modal-body">
|
|
@@ -517,7 +532,7 @@ function ajax_modal(url, opts = {}) {
|
|
|
517
532
|
var title = request.getResponseHeader("Page-Title");
|
|
518
533
|
if (title) $("#scmodal .modal-title").html(decodeURIComponent(title));
|
|
519
534
|
$("#scmodal .modal-body").html(res);
|
|
520
|
-
$("#scmodal").
|
|
535
|
+
new bootstrap.Modal($("#scmodal")).show();
|
|
521
536
|
initialize_page();
|
|
522
537
|
(opts.onOpen || function () {})(res);
|
|
523
538
|
$("#scmodal").on("hidden.bs.modal", function (e) {
|
|
@@ -624,11 +639,13 @@ function make_unique_field(
|
|
|
624
639
|
id,
|
|
625
640
|
table_id,
|
|
626
641
|
field_name,
|
|
627
|
-
|
|
642
|
+
elem,
|
|
628
643
|
space,
|
|
629
644
|
start,
|
|
630
|
-
always_append
|
|
645
|
+
always_append,
|
|
646
|
+
char_type
|
|
631
647
|
) {
|
|
648
|
+
const value = $(elem).val();
|
|
632
649
|
if (!value) return;
|
|
633
650
|
$.ajax(
|
|
634
651
|
`/api/${table_id}?approximate=true&${encodeURIComponent(
|
|
@@ -638,12 +655,25 @@ function make_unique_field(
|
|
|
638
655
|
type: "GET",
|
|
639
656
|
success: function (res) {
|
|
640
657
|
if (res.success) {
|
|
658
|
+
const gen_char = (i) => {
|
|
659
|
+
switch (char_type) {
|
|
660
|
+
case "Lowercase Letters":
|
|
661
|
+
return String.fromCharCode("a".charCodeAt(0) + i);
|
|
662
|
+
break;
|
|
663
|
+
case "Uppercase Letters":
|
|
664
|
+
return String.fromCharCode("A".charCodeAt(0) + i);
|
|
665
|
+
break;
|
|
666
|
+
default:
|
|
667
|
+
return i;
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
};
|
|
641
671
|
const vals = res.success
|
|
642
672
|
.map((o) => o[field_name])
|
|
643
673
|
.filter((s) => s.startsWith(value));
|
|
644
674
|
if (vals.includes(value) || always_append) {
|
|
645
675
|
for (let i = start || 0; i < vals.length + (start || 0) + 2; i++) {
|
|
646
|
-
const newname = `${value}${space ? " " : ""}${i}`;
|
|
676
|
+
const newname = `${value}${space ? " " : ""}${gen_char(i)}`;
|
|
647
677
|
if (!vals.includes(newname)) {
|
|
648
678
|
$("#" + id).val(newname);
|
|
649
679
|
return;
|
|
@@ -721,6 +751,16 @@ function room_older(viewname, room_id, btn) {
|
|
|
721
751
|
);
|
|
722
752
|
}
|
|
723
753
|
|
|
754
|
+
function fill_formula_btn_click(btn) {
|
|
755
|
+
const formula = decodeURIComponent($(btn).attr("data-formula"));
|
|
756
|
+
const rec = get_form_record($(btn), true);
|
|
757
|
+
const val = new Function(
|
|
758
|
+
`{${Object.keys(rec).join(",")}}`,
|
|
759
|
+
"return " + formula
|
|
760
|
+
)(rec);
|
|
761
|
+
$(btn).closest(".input-group").find("input").val(val);
|
|
762
|
+
}
|
|
763
|
+
|
|
724
764
|
/*
|
|
725
765
|
https://github.com/jeffdavidgreen/bootstrap-html5-history-tabs/blob/master/bootstrap-history-tabs.js
|
|
726
766
|
Copyright (c) 2015 Jeff Green
|
package/routes/actions.js
CHANGED
|
@@ -144,20 +144,18 @@ router.get(
|
|
|
144
144
|
contents: table(
|
|
145
145
|
tbody(
|
|
146
146
|
tr(
|
|
147
|
-
td({ class: "
|
|
147
|
+
td({ class: "pe-2" }, req.__("Actions available")),
|
|
148
148
|
td(
|
|
149
149
|
actions
|
|
150
|
-
.map((a) =>
|
|
151
|
-
span({ class: "badge badge-primary" }, a.name)
|
|
152
|
-
)
|
|
150
|
+
.map((a) => span({ class: "badge bg-primary" }, a.name))
|
|
153
151
|
.join(" ")
|
|
154
152
|
)
|
|
155
153
|
),
|
|
156
154
|
tr(
|
|
157
|
-
td({ class: "
|
|
155
|
+
td({ class: "pe-2" }, req.__("Event types")),
|
|
158
156
|
td(
|
|
159
157
|
Trigger.when_options
|
|
160
|
-
.map((a) => span({ class: "badge
|
|
158
|
+
.map((a) => span({ class: "badge bg-secondary" }, a))
|
|
161
159
|
.join(" ")
|
|
162
160
|
)
|
|
163
161
|
)
|
package/routes/admin.js
CHANGED
|
@@ -46,7 +46,10 @@ const {
|
|
|
46
46
|
get_process_init_time,
|
|
47
47
|
} = require("@saltcorn/data/db/state");
|
|
48
48
|
const { loadAllPlugins } = require("../load_plugins");
|
|
49
|
-
const {
|
|
49
|
+
const {
|
|
50
|
+
create_backup,
|
|
51
|
+
restore,
|
|
52
|
+
} = require("@saltcorn/admin-models/models/backup");
|
|
50
53
|
const fs = require("fs");
|
|
51
54
|
const load_plugins = require("../load_plugins");
|
|
52
55
|
const {
|
|
@@ -299,7 +302,7 @@ router.get(
|
|
|
299
302
|
post_btn("/admin/backup", req.__("Backup"), req.csrfToken())
|
|
300
303
|
)
|
|
301
304
|
),
|
|
302
|
-
td(p({ class: "
|
|
305
|
+
td(p({ class: "ms-4 pt-2" }, req.__("Download a backup")))
|
|
303
306
|
),
|
|
304
307
|
tr(td(div({ class: "my-4" }))),
|
|
305
308
|
tr(
|
|
@@ -310,7 +313,7 @@ router.get(
|
|
|
310
313
|
req.__("Restore"),
|
|
311
314
|
])
|
|
312
315
|
),
|
|
313
|
-
td(p({ class: "
|
|
316
|
+
td(p({ class: "ms-4" }, req.__("Restore a backup")))
|
|
314
317
|
)
|
|
315
318
|
)
|
|
316
319
|
),
|
|
@@ -393,7 +396,7 @@ router.get(
|
|
|
393
396
|
)
|
|
394
397
|
: isRoot && is_latest
|
|
395
398
|
? span(
|
|
396
|
-
{ class: "badge
|
|
399
|
+
{ class: "badge bg-primary ms-2" },
|
|
397
400
|
req.__("Latest")
|
|
398
401
|
)
|
|
399
402
|
: "")
|
package/routes/eventlog.js
CHANGED
|
@@ -155,9 +155,9 @@ router.get(
|
|
|
155
155
|
a(
|
|
156
156
|
{
|
|
157
157
|
href: "/eventlog/custom/new",
|
|
158
|
-
class: "btn btn-primary mt-1
|
|
158
|
+
class: "btn btn-primary mt-1 me-3",
|
|
159
159
|
},
|
|
160
|
-
i({ class: "fas fa-plus-square
|
|
160
|
+
i({ class: "fas fa-plus-square me-1" }),
|
|
161
161
|
req.__("Create custom event")
|
|
162
162
|
),
|
|
163
163
|
},
|
package/routes/homepage.js
CHANGED
|
@@ -50,17 +50,17 @@ const tableCard = (tables, req) => ({
|
|
|
50
50
|
contents:
|
|
51
51
|
(tables.length <= 1
|
|
52
52
|
? p(
|
|
53
|
-
{ class: "mt-2
|
|
53
|
+
{ class: "mt-2 pe-2" },
|
|
54
54
|
i(req.__("Tables organise data by fields and rows."))
|
|
55
55
|
)
|
|
56
56
|
: "") + tableTable(tables, req),
|
|
57
|
-
bodyClass: "py-0
|
|
57
|
+
bodyClass: "py-0 pe-0",
|
|
58
58
|
footer: div(
|
|
59
59
|
a({ href: `/table/new`, class: "btn btn-primary" }, req.__("Create table")),
|
|
60
60
|
a(
|
|
61
61
|
{
|
|
62
62
|
href: `/table/create-from-csv`,
|
|
63
|
-
class: "btn btn-secondary
|
|
63
|
+
class: "btn btn-secondary ms-2",
|
|
64
64
|
},
|
|
65
65
|
req.__("CSV upload")
|
|
66
66
|
)
|
|
@@ -97,11 +97,11 @@ const viewCard = (views, req) => ({
|
|
|
97
97
|
type: "card",
|
|
98
98
|
title: link("/viewedit", req.__("Views")),
|
|
99
99
|
class: "welcome-page-entity-list",
|
|
100
|
-
bodyClass: "py-0
|
|
100
|
+
bodyClass: "py-0 pe-0",
|
|
101
101
|
contents:
|
|
102
102
|
(views.length <= 1
|
|
103
103
|
? p(
|
|
104
|
-
{ class: "mt-2
|
|
104
|
+
{ class: "mt-2 pe-2" },
|
|
105
105
|
i(
|
|
106
106
|
req.__(
|
|
107
107
|
"Views display data from tables. A view is a view template applied to a table, with configuration."
|
|
@@ -152,7 +152,7 @@ const pageCard = (pages, req) => ({
|
|
|
152
152
|
contents:
|
|
153
153
|
(pages.length <= 1
|
|
154
154
|
? p(
|
|
155
|
-
{ class: "mt-2
|
|
155
|
+
{ class: "mt-2 pe-2" },
|
|
156
156
|
i(
|
|
157
157
|
req.__(
|
|
158
158
|
"Pages are the web pages of your application built with a drag-and-drop builder. They have static content, and by embedding views, dynamic content."
|
|
@@ -162,8 +162,8 @@ const pageCard = (pages, req) => ({
|
|
|
162
162
|
: "") +
|
|
163
163
|
(pages.length > 0
|
|
164
164
|
? pageTable(pages, req)
|
|
165
|
-
: div({ class: "mt-2
|
|
166
|
-
bodyClass: "py-0
|
|
165
|
+
: div({ class: "mt-2 pe-2" }, p(req.__("No pages")))),
|
|
166
|
+
bodyClass: "py-0 pe-0",
|
|
167
167
|
footer: div(
|
|
168
168
|
a(
|
|
169
169
|
{ href: `/pageedit/new`, class: "btn btn-primary" },
|
|
@@ -231,7 +231,7 @@ const actionsTab = async (req, triggers) => {
|
|
|
231
231
|
{ class: "pb-3" },
|
|
232
232
|
triggers.length <= 1 &&
|
|
233
233
|
p(
|
|
234
|
-
{ class: "mt-2
|
|
234
|
+
{ class: "mt-2 pe-2" },
|
|
235
235
|
i(req.__("Triggers run actions in response to events."))
|
|
236
236
|
),
|
|
237
237
|
triggers.length == 0
|
|
@@ -262,7 +262,7 @@ const actionsTab = async (req, triggers) => {
|
|
|
262
262
|
};
|
|
263
263
|
const packTab = (req, packlist) =>
|
|
264
264
|
div(
|
|
265
|
-
{ class: "pb-3 pt-2
|
|
265
|
+
{ class: "pb-3 pt-2 pe-4" },
|
|
266
266
|
p(req.__("Instead of building, get up and running in no time with packs")),
|
|
267
267
|
p(
|
|
268
268
|
{ class: "font-italic" },
|
|
@@ -289,7 +289,7 @@ const packTab = (req, packlist) =>
|
|
|
289
289
|
|
|
290
290
|
const helpCard = (req) =>
|
|
291
291
|
div(
|
|
292
|
-
{ class: "pb-3 pt-2
|
|
292
|
+
{ class: "pb-3 pt-2 pe-4" },
|
|
293
293
|
p(req.__("Confused?")),
|
|
294
294
|
p(
|
|
295
295
|
req.__(
|
|
@@ -354,7 +354,7 @@ const welcome_page = async (req) => {
|
|
|
354
354
|
{
|
|
355
355
|
type: "card",
|
|
356
356
|
//title: req.__("Install pack"),
|
|
357
|
-
bodyClass: "py-0
|
|
357
|
+
bodyClass: "py-0 pe-0",
|
|
358
358
|
class: "welcome-page-entity-list",
|
|
359
359
|
|
|
360
360
|
tabContents:
|
|
@@ -373,7 +373,7 @@ const welcome_page = async (req) => {
|
|
|
373
373
|
{
|
|
374
374
|
type: "card",
|
|
375
375
|
//title: req.__("Learn"),
|
|
376
|
-
bodyClass: "py-0
|
|
376
|
+
bodyClass: "py-0 pe-0",
|
|
377
377
|
class: "welcome-page-entity-list",
|
|
378
378
|
tabContents:
|
|
379
379
|
users.length > 4
|
package/routes/infoarch.js
CHANGED
package/routes/list.js
CHANGED
|
@@ -264,6 +264,7 @@ router.get(
|
|
|
264
264
|
width: 40,
|
|
265
265
|
hozAlign: "center",
|
|
266
266
|
headerSort: false,
|
|
267
|
+
clipboard: false,
|
|
267
268
|
cellClick: "__delete_tabulator_row",
|
|
268
269
|
});
|
|
269
270
|
res.sendWrap(
|
|
@@ -305,24 +306,25 @@ router.get(
|
|
|
305
306
|
{ href: `/table/${table.id || table.name}`, text: table.name },
|
|
306
307
|
{ text: req.__("Data") },
|
|
307
308
|
],
|
|
308
|
-
right:
|
|
309
|
+
right: div(
|
|
310
|
+
{ class: "d-flex" },
|
|
309
311
|
button(
|
|
310
312
|
{
|
|
311
|
-
class: "btn btn-sm btn-primary
|
|
313
|
+
class: "btn btn-sm btn-primary me-2",
|
|
312
314
|
onClick: "add_tabulator_row()",
|
|
313
315
|
},
|
|
314
|
-
i({ class: "fas fa-plus
|
|
316
|
+
i({ class: "fas fa-plus me-1" }),
|
|
315
317
|
"Add row"
|
|
316
|
-
)
|
|
318
|
+
),
|
|
317
319
|
div(
|
|
318
|
-
{ class: "dropdown
|
|
320
|
+
{ class: "dropdown" },
|
|
319
321
|
button(
|
|
320
322
|
{
|
|
321
323
|
class: "btn btn-sm btn-outline-secondary dropdown-toggle",
|
|
322
324
|
"data-boundary": "viewport",
|
|
323
325
|
type: "button",
|
|
324
326
|
id: "btnHideCols",
|
|
325
|
-
"data-toggle": "dropdown",
|
|
327
|
+
"data-bs-toggle": "dropdown",
|
|
326
328
|
"aria-haspopup": "true",
|
|
327
329
|
"aria-expanded": "false",
|
|
328
330
|
},
|
|
@@ -330,7 +332,7 @@ router.get(
|
|
|
330
332
|
),
|
|
331
333
|
div(
|
|
332
334
|
{
|
|
333
|
-
class: "dropdown-menu",
|
|
335
|
+
class: "dropdown-menu dropdown-menu-end",
|
|
334
336
|
"aria-labelledby": "btnHideCols",
|
|
335
337
|
},
|
|
336
338
|
form(
|
|
@@ -349,7 +351,8 @@ router.get(
|
|
|
349
351
|
)
|
|
350
352
|
)
|
|
351
353
|
)
|
|
352
|
-
)
|
|
354
|
+
)
|
|
355
|
+
),
|
|
353
356
|
},
|
|
354
357
|
{
|
|
355
358
|
type: "blank",
|
|
@@ -374,6 +377,10 @@ router.get(
|
|
|
374
377
|
height:"100%",
|
|
375
378
|
pagination:true,
|
|
376
379
|
paginationSize:20,
|
|
380
|
+
clipboard:true,
|
|
381
|
+
persistence:true,
|
|
382
|
+
persistenceID:"table_tab_${table.name}",
|
|
383
|
+
movableColumns: true,
|
|
377
384
|
initialSort:[
|
|
378
385
|
{column:"id", dir:"asc"},
|
|
379
386
|
],
|
package/routes/menu.js
CHANGED
|
@@ -334,7 +334,7 @@ router.get(
|
|
|
334
334
|
script: static_pre + "/iconset-fontawesome5-3-1.min.js",
|
|
335
335
|
},
|
|
336
336
|
{
|
|
337
|
-
script: static_pre + "/bootstrap-iconpicker.
|
|
337
|
+
script: static_pre + "/bootstrap-iconpicker.js",
|
|
338
338
|
},
|
|
339
339
|
{
|
|
340
340
|
css: static_pre + "/bootstrap-iconpicker.min.css",
|
package/routes/pageedit.js
CHANGED
package/routes/plugins.js
CHANGED
|
@@ -209,7 +209,7 @@ const cfg_link = (req, row) => {
|
|
|
209
209
|
if (plugin.configuration_workflow)
|
|
210
210
|
return a(
|
|
211
211
|
{
|
|
212
|
-
class: "btn btn-secondary btn-sm d-inline
|
|
212
|
+
class: "btn btn-secondary btn-sm d-inline me-1",
|
|
213
213
|
role: "button",
|
|
214
214
|
href: `/plugins/configure/${encodeURIComponent(row.name)}`,
|
|
215
215
|
title: req.__("Configure plugin"),
|
|
@@ -240,7 +240,7 @@ const info_link = (req, row) =>
|
|
|
240
240
|
* @returns {span}
|
|
241
241
|
*/
|
|
242
242
|
const badge = (title) =>
|
|
243
|
-
span({ class: "badge
|
|
243
|
+
span({ class: "badge bg-secondary plugin-store" }, title);
|
|
244
244
|
|
|
245
245
|
/**
|
|
246
246
|
*
|
|
@@ -427,7 +427,7 @@ const store_actions_dropdown = (req) =>
|
|
|
427
427
|
class: "btn btn-outline-secondary",
|
|
428
428
|
type: "button",
|
|
429
429
|
id: "dropdownMenuButton",
|
|
430
|
-
"data-toggle": "dropdown",
|
|
430
|
+
"data-bs-toggle": "dropdown",
|
|
431
431
|
"aria-haspopup": "true",
|
|
432
432
|
"aria-expanded": "false",
|
|
433
433
|
},
|
|
@@ -435,7 +435,7 @@ const store_actions_dropdown = (req) =>
|
|
|
435
435
|
),
|
|
436
436
|
div(
|
|
437
437
|
{
|
|
438
|
-
class: "dropdown-menu dropdown-menu-
|
|
438
|
+
class: "dropdown-menu dropdown-menu-end",
|
|
439
439
|
"aria-labelledby": "dropdownMenuButton",
|
|
440
440
|
},
|
|
441
441
|
a(
|
|
@@ -501,13 +501,10 @@ const plugin_store_html = (items, req) => {
|
|
|
501
501
|
{
|
|
502
502
|
type: "card",
|
|
503
503
|
contents: div(
|
|
504
|
-
{ class: "d-flex" },
|
|
504
|
+
{ class: "d-flex justify-content-between" },
|
|
505
505
|
storeNavPills(req),
|
|
506
|
-
div(
|
|
507
|
-
|
|
508
|
-
search_bar("q", req.query.q || "", { stateField: "q" })
|
|
509
|
-
),
|
|
510
|
-
div({ class: "ml-auto" }, store_actions_dropdown(req))
|
|
506
|
+
div(search_bar("q", req.query.q || "", { stateField: "q" })),
|
|
507
|
+
div(store_actions_dropdown(req))
|
|
511
508
|
),
|
|
512
509
|
},
|
|
513
510
|
{
|
|
@@ -602,6 +599,7 @@ router.post(
|
|
|
602
599
|
refresh_plugin_cfg: plugin.name,
|
|
603
600
|
tenant: db.getTenantSchema(),
|
|
604
601
|
});
|
|
602
|
+
await sleep(500); // Allow other workers to reload this plugin
|
|
605
603
|
res.redirect("/plugins");
|
|
606
604
|
}
|
|
607
605
|
})
|
|
@@ -736,7 +734,7 @@ router.get(
|
|
|
736
734
|
? a(
|
|
737
735
|
{
|
|
738
736
|
href: `/plugins/upgrade-plugin/${plugin_db.name}`,
|
|
739
|
-
class: "btn btn-primary btn-sm
|
|
737
|
+
class: "btn btn-primary btn-sm ms-2",
|
|
740
738
|
},
|
|
741
739
|
req.__("Upgrade")
|
|
742
740
|
)
|
|
@@ -748,7 +746,7 @@ router.get(
|
|
|
748
746
|
th(req.__("Plugin dependencies")),
|
|
749
747
|
td(
|
|
750
748
|
mod.plugin_module.dependencies.map((d) =>
|
|
751
|
-
span({ class: "badge
|
|
749
|
+
span({ class: "badge bg-primary me-1" }, d)
|
|
752
750
|
)
|
|
753
751
|
)
|
|
754
752
|
)
|
package/routes/settings.js
CHANGED
package/routes/tables.js
CHANGED
|
@@ -488,8 +488,7 @@ router.get(
|
|
|
488
488
|
* @param {string} lbl
|
|
489
489
|
* @returns {string}
|
|
490
490
|
*/
|
|
491
|
-
const badge = (col, lbl) =>
|
|
492
|
-
`<span class="badge badge-${col}">${lbl}</span> `;
|
|
491
|
+
const badge = (col, lbl) => `<span class="badge bg-${col}">${lbl}</span> `;
|
|
493
492
|
|
|
494
493
|
/**
|
|
495
494
|
* @param {object} f
|
|
@@ -578,7 +577,7 @@ router.get(
|
|
|
578
577
|
: (r.type && r.type.name) ||
|
|
579
578
|
r.type ||
|
|
580
579
|
r.typename +
|
|
581
|
-
span({ class: "badge
|
|
580
|
+
span({ class: "badge bg-danger ms-1" }, "Unknown type"),
|
|
582
581
|
},
|
|
583
582
|
{
|
|
584
583
|
label: "",
|
|
@@ -1035,22 +1034,22 @@ router.get(
|
|
|
1035
1034
|
const createCard = div(
|
|
1036
1035
|
h5(req.__("Create table")),
|
|
1037
1036
|
a(
|
|
1038
|
-
{ href: `/table/new`, class: "btn btn-primary mt-1
|
|
1039
|
-
i({ class: "fas fa-plus-square
|
|
1037
|
+
{ href: `/table/new`, class: "btn btn-primary mt-1 me-3" },
|
|
1038
|
+
i({ class: "fas fa-plus-square me-1" }),
|
|
1040
1039
|
req.__("Create table")
|
|
1041
1040
|
),
|
|
1042
1041
|
a(
|
|
1043
1042
|
{
|
|
1044
1043
|
href: `/table/create-from-csv`,
|
|
1045
|
-
class: "btn btn-secondary
|
|
1044
|
+
class: "btn btn-secondary me-3 mt-1",
|
|
1046
1045
|
},
|
|
1047
|
-
i({ class: "fas fa-upload
|
|
1046
|
+
i({ class: "fas fa-upload me-1" }),
|
|
1048
1047
|
req.__("Create from CSV upload")
|
|
1049
1048
|
),
|
|
1050
1049
|
!db.isSQLite &&
|
|
1051
1050
|
a(
|
|
1052
1051
|
{ href: `/table/discover`, class: "btn btn-secondary mt-1" },
|
|
1053
|
-
i({ class: "fas fa-map-signs
|
|
1052
|
+
i({ class: "fas fa-map-signs me-1" }),
|
|
1054
1053
|
req.__("Discover tables")
|
|
1055
1054
|
)
|
|
1056
1055
|
);
|
package/routes/utils.js
CHANGED
|
@@ -100,7 +100,8 @@ const set_custom_http_headers = (res, state) => {
|
|
|
100
100
|
* @returns {string}
|
|
101
101
|
*/
|
|
102
102
|
const get_tenant_from_req = (req) => {
|
|
103
|
-
if (req.subdomains && req.subdomains.length > 0)
|
|
103
|
+
if (req.subdomains && req.subdomains.length > 0)
|
|
104
|
+
return req.subdomains[req.subdomains.length - 1];
|
|
104
105
|
|
|
105
106
|
if (req.subdomains && req.subdomains.length == 0)
|
|
106
107
|
return db.connectObj.default_schema;
|
|
@@ -121,8 +122,10 @@ const setTenant = (req, res, next) => {
|
|
|
121
122
|
const other_domain = get_other_domain_tenant(req.hostname);
|
|
122
123
|
if (other_domain) {
|
|
123
124
|
const state = getTenant(other_domain);
|
|
124
|
-
if (!state)
|
|
125
|
-
|
|
125
|
+
if (!state) {
|
|
126
|
+
setLanguage(req, res);
|
|
127
|
+
next();
|
|
128
|
+
} else {
|
|
126
129
|
db.runWithTenant(other_domain, () => {
|
|
127
130
|
setLanguage(req, res, state);
|
|
128
131
|
next();
|
|
@@ -130,10 +133,11 @@ const setTenant = (req, res, next) => {
|
|
|
130
133
|
}
|
|
131
134
|
} else {
|
|
132
135
|
const ten = get_tenant_from_req(req);
|
|
133
|
-
//console.log("tenant", ten);
|
|
134
136
|
const state = getTenant(ten);
|
|
135
|
-
if (!state)
|
|
136
|
-
|
|
137
|
+
if (!state) {
|
|
138
|
+
setLanguage(req, res);
|
|
139
|
+
next();
|
|
140
|
+
} else {
|
|
137
141
|
db.runWithTenant(ten, () => {
|
|
138
142
|
setLanguage(req, res, state);
|
|
139
143
|
next();
|
package/tests/plugins.test.js
CHANGED
|
@@ -90,7 +90,7 @@ describe("Plugin Endpoints", () => {
|
|
|
90
90
|
.expect(toInclude("testfilecontents"));
|
|
91
91
|
await request(app)
|
|
92
92
|
.get(
|
|
93
|
-
"/plugins/pubdeps/sbadmin2/startbootstrap-sb-admin-2/4.1.
|
|
93
|
+
"/plugins/pubdeps/sbadmin2/startbootstrap-sb-admin-2-bs5/4.1.5-beta.0/css/sb-admin-2.min.css"
|
|
94
94
|
)
|
|
95
95
|
.expect(toInclude("Start Bootstrap"));
|
|
96
96
|
|
|
@@ -98,6 +98,11 @@ describe("Plugin Endpoints", () => {
|
|
|
98
98
|
.post("/plugins/delete/" + p.name)
|
|
99
99
|
.set("Cookie", loginCookie)
|
|
100
100
|
.expect(toRedirect("/plugins"));
|
|
101
|
+
await request(app)
|
|
102
|
+
.get(
|
|
103
|
+
"/plugins/pubdeps/sbadmin2/startbootstrap-sb-admin-2-bs5/4.1.5-beta.0/css/sb-admin-2.min.css"
|
|
104
|
+
)
|
|
105
|
+
.expect(toInclude("Start Bootstrap"));
|
|
101
106
|
});
|
|
102
107
|
it("should install named without config", async () => {
|
|
103
108
|
const loginCookie = await getAdminLoginCookie();
|