@saltcorn/server 0.7.4-beta.0 → 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/locales/en.json +19 -1
- package/locales/it.json +2 -1
- package/locales/ru.json +42 -6
- package/markup/plugin-store.js +5 -5
- package/package.json +7 -7
- package/public/saltcorn-builder.css +75 -0
- package/public/saltcorn.css +4 -0
- package/routes/admin.js +131 -108
- package/routes/fields.js +11 -13
- package/routes/homepage.js +60 -60
- package/routes/menu.js +65 -4
- package/routes/packs.js +4 -4
- package/routes/plugins.js +116 -118
- package/routes/settings.js +3 -3
- package/routes/tables.js +187 -187
- package/routes/tenant.js +27 -27
- package/routes/viewedit.js +68 -68
- package/tests/admin.test.js +1 -1
- package/tests/plugins.test.js +1 -1
- package/tests/viewedit.test.js +1 -1
- package/wrapper.js +57 -55
package/routes/menu.js
CHANGED
|
@@ -22,6 +22,9 @@ const { renderForm } = require("@saltcorn/markup");
|
|
|
22
22
|
const { script, domReady, div, ul } = require("@saltcorn/markup/tags");
|
|
23
23
|
const { send_infoarch_page } = require("../markup/admin.js");
|
|
24
24
|
const Table = require("@saltcorn/data/models/table");
|
|
25
|
+
const Trigger = require("@saltcorn/data/models/trigger");
|
|
26
|
+
const { run_action_column } = require("@saltcorn/data/plugin-helper");
|
|
27
|
+
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* @type {object}
|
|
@@ -61,6 +64,18 @@ const menuForm = async (req) => {
|
|
|
61
64
|
dynSectionFieldOptions[table.name].push(field.name);
|
|
62
65
|
}
|
|
63
66
|
}
|
|
67
|
+
const stateActions = getState().actions;
|
|
68
|
+
const actions = [
|
|
69
|
+
...Object.entries(stateActions)
|
|
70
|
+
.filter(([k, v]) => !v.requireRow && !v.disableInBuilder)
|
|
71
|
+
.map(([k, v]) => k),
|
|
72
|
+
];
|
|
73
|
+
const triggers = await Trigger.find({
|
|
74
|
+
when_trigger: { or: ["API call", "Never"] },
|
|
75
|
+
});
|
|
76
|
+
triggers.forEach((tr) => {
|
|
77
|
+
actions.push(tr.name);
|
|
78
|
+
});
|
|
64
79
|
|
|
65
80
|
return new Form({
|
|
66
81
|
action: "/menu/",
|
|
@@ -92,6 +107,7 @@ const menuForm = async (req) => {
|
|
|
92
107
|
"Dynamic",
|
|
93
108
|
"Search",
|
|
94
109
|
"Separator",
|
|
110
|
+
"Action"
|
|
95
111
|
],
|
|
96
112
|
},
|
|
97
113
|
{
|
|
@@ -101,7 +117,7 @@ const menuForm = async (req) => {
|
|
|
101
117
|
input_type: "text",
|
|
102
118
|
required: true,
|
|
103
119
|
showIf: {
|
|
104
|
-
type: ["View", "Page", "Link", "Header", "Dynamic", "Search"],
|
|
120
|
+
type: ["View", "Page", "Link", "Header", "Dynamic", "Search", "Action"],
|
|
105
121
|
},
|
|
106
122
|
},
|
|
107
123
|
{
|
|
@@ -111,7 +127,7 @@ const menuForm = async (req) => {
|
|
|
111
127
|
attributes: {
|
|
112
128
|
html: `<button type="button" id="myEditor_icon" class="btn btn-outline-secondary"></button>`,
|
|
113
129
|
},
|
|
114
|
-
showIf: { type: ["View", "Page", "Link", "Header"] },
|
|
130
|
+
showIf: { type: ["View", "Page", "Link", "Header", "Action"] },
|
|
115
131
|
},
|
|
116
132
|
{
|
|
117
133
|
name: "icon",
|
|
@@ -149,6 +165,17 @@ const menuForm = async (req) => {
|
|
|
149
165
|
attributes: { options: views.map((r) => r.select_option) },
|
|
150
166
|
showIf: { type: "View" },
|
|
151
167
|
},
|
|
168
|
+
{
|
|
169
|
+
name: "action_name",
|
|
170
|
+
label: req.__("Action"),
|
|
171
|
+
type: "String",
|
|
172
|
+
class: "item-menu",
|
|
173
|
+
required: true,
|
|
174
|
+
attributes: {
|
|
175
|
+
options: actions,
|
|
176
|
+
},
|
|
177
|
+
showIf: { type: "Action" },
|
|
178
|
+
},
|
|
152
179
|
{
|
|
153
180
|
name: "dyn_table",
|
|
154
181
|
label: req.__("Table"),
|
|
@@ -217,7 +244,7 @@ const menuForm = async (req) => {
|
|
|
217
244
|
class: "item-menu",
|
|
218
245
|
type: "String",
|
|
219
246
|
required: true,
|
|
220
|
-
showIf: { type: ["View", "Page", "Link", "Header", "Dynamic"] },
|
|
247
|
+
showIf: { type: ["View", "Page", "Link", "Header", "Dynamic", "Action"] },
|
|
221
248
|
attributes: {
|
|
222
249
|
options: [
|
|
223
250
|
{ name: "", label: "Link" },
|
|
@@ -239,7 +266,7 @@ const menuForm = async (req) => {
|
|
|
239
266
|
{
|
|
240
267
|
name: "location",
|
|
241
268
|
label: req.__("Location"),
|
|
242
|
-
showIf: { type: ["View", "Page", "Link", "Header", "Dynamic"] },
|
|
269
|
+
showIf: { type: ["View", "Page", "Link", "Header", "Dynamic", "Action"] },
|
|
243
270
|
sublabel: req.__("Not all themes support all locations"),
|
|
244
271
|
class: "item-menu",
|
|
245
272
|
type: "String",
|
|
@@ -404,3 +431,37 @@ router.post(
|
|
|
404
431
|
res.json({ success: true });
|
|
405
432
|
})
|
|
406
433
|
);
|
|
434
|
+
|
|
435
|
+
router.post(
|
|
436
|
+
"/runaction/:name",
|
|
437
|
+
error_catcher(async (req, res) => {
|
|
438
|
+
const { name } = req.params;
|
|
439
|
+
const role = (req.user || {}).role_id || 10;
|
|
440
|
+
const state = getState();
|
|
441
|
+
const menu_items = state.getConfig("menu_items");
|
|
442
|
+
let menu_item;
|
|
443
|
+
const search = items =>
|
|
444
|
+
items
|
|
445
|
+
.filter((item) => role <= +item.min_role)
|
|
446
|
+
.forEach(item => {
|
|
447
|
+
if (item.type === "Action" && item.action_name === name)
|
|
448
|
+
menu_item = item;
|
|
449
|
+
else if (item.subitems)
|
|
450
|
+
search(item.subitems);
|
|
451
|
+
})
|
|
452
|
+
search(menu_items);
|
|
453
|
+
if (menu_item)
|
|
454
|
+
try {
|
|
455
|
+
const result = await run_action_column({
|
|
456
|
+
col: menu_item,
|
|
457
|
+
referrer: req.get("Referrer"),
|
|
458
|
+
req,
|
|
459
|
+
});
|
|
460
|
+
res.json({ success: "ok", ...(result || {}) });
|
|
461
|
+
} catch (e) {
|
|
462
|
+
res.status(400).json({ error: e.message || e });
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
else res.status(404).json({ error: "Action not found" });
|
|
466
|
+
})
|
|
467
|
+
);
|
package/routes/packs.js
CHANGED
|
@@ -116,7 +116,7 @@ router.get(
|
|
|
116
116
|
type: "breadcrumbs",
|
|
117
117
|
crumbs: [
|
|
118
118
|
{ text: req.__("Settings") },
|
|
119
|
-
{ text: req.__("
|
|
119
|
+
{ text: req.__("Modules"), href: "/plugins" },
|
|
120
120
|
{ text: req.__("Create pack") },
|
|
121
121
|
],
|
|
122
122
|
},
|
|
@@ -184,7 +184,7 @@ router.post(
|
|
|
184
184
|
type: "breadcrumbs",
|
|
185
185
|
crumbs: [
|
|
186
186
|
{ text: req.__("Settings") },
|
|
187
|
-
{ text: req.__("
|
|
187
|
+
{ text: req.__("Modules"), href: "/plugins" },
|
|
188
188
|
{ text: req.__("Create pack") },
|
|
189
189
|
],
|
|
190
190
|
},
|
|
@@ -242,7 +242,7 @@ router.get(
|
|
|
242
242
|
type: "breadcrumbs",
|
|
243
243
|
crumbs: [
|
|
244
244
|
{ text: req.__("Settings") },
|
|
245
|
-
{ text: req.__("
|
|
245
|
+
{ text: req.__("Modules"), href: "/plugins" },
|
|
246
246
|
{ text: req.__("Install pack") },
|
|
247
247
|
],
|
|
248
248
|
},
|
|
@@ -293,7 +293,7 @@ router.post(
|
|
|
293
293
|
type: "breadcrumbs",
|
|
294
294
|
crumbs: [
|
|
295
295
|
{ text: req.__("Settings") },
|
|
296
|
-
{ text: req.__("
|
|
296
|
+
{ text: req.__("Modules"), href: "/plugins" },
|
|
297
297
|
{ text: req.__("Install pack") },
|
|
298
298
|
],
|
|
299
299
|
},
|
package/routes/plugins.js
CHANGED
|
@@ -79,7 +79,7 @@ const pluginForm = (req, plugin) => {
|
|
|
79
79
|
label: req.__("Name"),
|
|
80
80
|
name: "name",
|
|
81
81
|
input_type: "text",
|
|
82
|
-
sublabel: req.__("
|
|
82
|
+
sublabel: req.__("Module name"),
|
|
83
83
|
}),
|
|
84
84
|
new Field({
|
|
85
85
|
label: req.__("Source"),
|
|
@@ -88,11 +88,11 @@ const pluginForm = (req, plugin) => {
|
|
|
88
88
|
required: true,
|
|
89
89
|
attributes: { options: "npm,local,github,git" },
|
|
90
90
|
sublabel: req.__(
|
|
91
|
-
"Source of
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
"Source of module for install. Few options:" +
|
|
92
|
+
"npm - download from npm repository," +
|
|
93
|
+
"local - get from local file system," +
|
|
94
|
+
"github - download from github," +
|
|
95
|
+
"git - get from git"
|
|
96
96
|
),
|
|
97
97
|
}),
|
|
98
98
|
new Field({
|
|
@@ -101,19 +101,19 @@ const pluginForm = (req, plugin) => {
|
|
|
101
101
|
input_type: "text",
|
|
102
102
|
sublabel: req.__(
|
|
103
103
|
"For npm - name of npm package, e.g. @saltcorn/html or saltcorn-gantt, check at npmjs.com, " +
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
"for local - absolute path to module folder in file system, e.g. C:\\gitsrc\\any-bootstrap-theme\\, " +
|
|
105
|
+
"for github - name of github project."
|
|
106
106
|
),
|
|
107
107
|
}),
|
|
108
108
|
...(schema === db.connectObj.default_schema
|
|
109
109
|
? [
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
new Field({
|
|
111
|
+
label: req.__("Version"),
|
|
112
|
+
name: "version",
|
|
113
|
+
input_type: "text",
|
|
114
|
+
sublabel: req.__("Version of module, latest is default value"),
|
|
115
|
+
}),
|
|
116
|
+
]
|
|
117
117
|
: []),
|
|
118
118
|
new Field({
|
|
119
119
|
label: req.__("Private SSH key"),
|
|
@@ -257,7 +257,7 @@ const store_item_html = (req) => (item) => ({
|
|
|
257
257
|
title: item.name,
|
|
258
258
|
contents: div(
|
|
259
259
|
div(
|
|
260
|
-
item.plugin && badge(req.__("
|
|
260
|
+
item.plugin && badge(req.__("Module")),
|
|
261
261
|
item.pack && badge(req.__("Pack")),
|
|
262
262
|
item.has_theme && badge(req.__("Theme")),
|
|
263
263
|
item.has_auth && badge(req.__("Authentication")),
|
|
@@ -269,72 +269,72 @@ const store_item_html = (req) => (item) => ({
|
|
|
269
269
|
div(item.description || ""),
|
|
270
270
|
item.documentation_link
|
|
271
271
|
? div(
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
)
|
|
272
|
+
a(
|
|
273
|
+
{ href: item.documentation_link, target: "_blank" },
|
|
274
|
+
req.__("Documentation")
|
|
276
275
|
)
|
|
276
|
+
)
|
|
277
277
|
: ""
|
|
278
278
|
),
|
|
279
279
|
footer: div(
|
|
280
280
|
div(
|
|
281
281
|
!item.installed &&
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
282
|
+
item.plugin &&
|
|
283
|
+
post_btn(
|
|
284
|
+
`/plugins/install/${encodeURIComponent(item.name)}`,
|
|
285
|
+
req.__("Install"),
|
|
286
|
+
req.csrfToken(),
|
|
287
|
+
{
|
|
288
|
+
klass: "store-install",
|
|
289
|
+
small: true,
|
|
290
|
+
onClick: "press_store_button(this)",
|
|
291
|
+
}
|
|
292
|
+
),
|
|
293
293
|
!item.installed &&
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
294
|
+
item.pack &&
|
|
295
|
+
post_btn(
|
|
296
|
+
`/packs/install-named/${encodeURIComponent(item.name)}`,
|
|
297
|
+
req.__("Install"),
|
|
298
|
+
req.csrfToken(),
|
|
299
|
+
{
|
|
300
|
+
klass: "store-install",
|
|
301
|
+
small: true,
|
|
302
|
+
onClick: "press_store_button(this)",
|
|
303
|
+
}
|
|
304
|
+
),
|
|
305
305
|
|
|
306
306
|
item.installed && item.plugin && cfg_link(req, item),
|
|
307
307
|
item.installed && item.plugin && info_link(req, item),
|
|
308
308
|
|
|
309
309
|
item.installed &&
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
310
|
+
item.pack &&
|
|
311
|
+
post_btn(
|
|
312
|
+
`/packs/uninstall/${encodeURIComponent(item.name)}`,
|
|
313
|
+
req.__("Uninstall"),
|
|
314
|
+
req.csrfToken(),
|
|
315
|
+
{
|
|
316
|
+
klass: "store-install",
|
|
317
|
+
small: true,
|
|
318
|
+
btnClass: "btn-danger",
|
|
319
|
+
formClass: "d-inline",
|
|
320
|
+
onClick: "press_store_button(this)",
|
|
321
|
+
}
|
|
322
|
+
),
|
|
323
323
|
item.installed &&
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
324
|
+
item.plugin &&
|
|
325
|
+
item.name !== "base" &&
|
|
326
|
+
post_btn(
|
|
327
|
+
`/plugins/delete/${encodeURIComponent(item.name)}`,
|
|
328
|
+
req.__("Remove"),
|
|
329
|
+
req.csrfToken(),
|
|
330
|
+
{
|
|
331
|
+
klass: "store-install",
|
|
332
|
+
small: true,
|
|
333
|
+
btnClass: "btn-danger",
|
|
334
|
+
formClass: "d-inline",
|
|
335
|
+
onClick: "press_store_button(this)",
|
|
336
|
+
}
|
|
337
|
+
)
|
|
338
338
|
)
|
|
339
339
|
),
|
|
340
340
|
});
|
|
@@ -354,7 +354,7 @@ const storeNavPills = (req) => {
|
|
|
354
354
|
"nav-link",
|
|
355
355
|
(req.query.set === txt.toLowerCase() ||
|
|
356
356
|
(txt === "All" && !req.query.set)) &&
|
|
357
|
-
|
|
357
|
+
"active",
|
|
358
358
|
],
|
|
359
359
|
},
|
|
360
360
|
req.__(txt)
|
|
@@ -363,7 +363,7 @@ const storeNavPills = (req) => {
|
|
|
363
363
|
return ul(
|
|
364
364
|
{ class: "nav nav-pills plugin-section" },
|
|
365
365
|
link("All"),
|
|
366
|
-
link("
|
|
366
|
+
link("Modules"),
|
|
367
367
|
link("Packs"),
|
|
368
368
|
link("Themes"),
|
|
369
369
|
link("Installed")
|
|
@@ -407,7 +407,7 @@ const satisfy_q = (p, q) => {
|
|
|
407
407
|
*/
|
|
408
408
|
const filter_items_set = (items, query) => {
|
|
409
409
|
switch (query.set) {
|
|
410
|
-
case "
|
|
410
|
+
case "modules":
|
|
411
411
|
return items.filter((item) => item.plugin && !item.has_theme);
|
|
412
412
|
case "packs":
|
|
413
413
|
return items.filter((item) => item.pack);
|
|
@@ -451,23 +451,23 @@ const store_actions_dropdown = (req) =>
|
|
|
451
451
|
'<i class="fas fa-sync"></i> ' + req.__("Refresh")
|
|
452
452
|
),
|
|
453
453
|
db.getTenantSchema() === db.connectObj.default_schema &&
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
454
|
+
a(
|
|
455
|
+
{
|
|
456
|
+
class: "dropdown-item",
|
|
457
|
+
href: `/plugins/upgrade`,
|
|
458
|
+
onClick: `notifyAlert('Upgrading modules...', true)`,
|
|
459
|
+
},
|
|
460
|
+
'<i class="far fa-arrow-alt-circle-up"></i> ' +
|
|
461
|
+
req.__("Upgrade installed modules")
|
|
462
|
+
),
|
|
463
463
|
db.getTenantSchema() === db.connectObj.default_schema &&
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
464
|
+
a(
|
|
465
|
+
{
|
|
466
|
+
class: "dropdown-item",
|
|
467
|
+
href: `/plugins/new`,
|
|
468
|
+
},
|
|
469
|
+
'<i class="fas fa-plus"></i> ' + req.__("Add another module")
|
|
470
|
+
),
|
|
471
471
|
|
|
472
472
|
a(
|
|
473
473
|
{
|
|
@@ -501,7 +501,7 @@ const plugin_store_html = (items, req) => {
|
|
|
501
501
|
type: "breadcrumbs",
|
|
502
502
|
crumbs: [
|
|
503
503
|
{ text: req.__("Settings"), href: "/settings" },
|
|
504
|
-
{ text: req.__("
|
|
504
|
+
{ text: req.__("Module store") },
|
|
505
505
|
],
|
|
506
506
|
},
|
|
507
507
|
{
|
|
@@ -534,7 +534,7 @@ router.get(
|
|
|
534
534
|
error_catcher(async (req, res) => {
|
|
535
535
|
const items = await get_store_items();
|
|
536
536
|
const relevant_items = filter_items(items, req.query);
|
|
537
|
-
res.sendWrap(req.__("
|
|
537
|
+
res.sendWrap(req.__("Module store"), plugin_store_html(relevant_items, req));
|
|
538
538
|
})
|
|
539
539
|
);
|
|
540
540
|
|
|
@@ -574,9 +574,8 @@ router.get(
|
|
|
574
574
|
onclick: "location.reload()",
|
|
575
575
|
},
|
|
576
576
|
];
|
|
577
|
-
wfres.renderForm.onChange = `${
|
|
578
|
-
|
|
579
|
-
};$('#btnReloadNow').removeClass('btn-outline-secondary').addClass('btn-secondary')`;
|
|
577
|
+
wfres.renderForm.onChange = `${wfres.renderForm.onChange || ""
|
|
578
|
+
};$('#btnReloadNow').removeClass('btn-outline-secondary').addClass('btn-secondary')`;
|
|
580
579
|
}
|
|
581
580
|
|
|
582
581
|
res.sendWrap(req.__(`Configure %s Plugin`, plugin.name), {
|
|
@@ -620,9 +619,8 @@ router.post(
|
|
|
620
619
|
onclick: "location.reload()",
|
|
621
620
|
},
|
|
622
621
|
];
|
|
623
|
-
wfres.renderForm.onChange = `${
|
|
624
|
-
|
|
625
|
-
};$('#btnReloadNow').removeClass('btn-outline-secondary').addClass('btn-secondary')`;
|
|
622
|
+
wfres.renderForm.onChange = `${wfres.renderForm.onChange || ""
|
|
623
|
+
};$('#btnReloadNow').removeClass('btn-outline-secondary').addClass('btn-secondary')`;
|
|
626
624
|
}
|
|
627
625
|
res.sendWrap(req.__(`Configure %s Plugin`, plugin.name), {
|
|
628
626
|
type: "card",
|
|
@@ -694,13 +692,13 @@ router.get(
|
|
|
694
692
|
type: "breadcrumbs",
|
|
695
693
|
crumbs: [
|
|
696
694
|
{ text: req.__("Settings"), href: "/settings" },
|
|
697
|
-
{ text: req.__("
|
|
695
|
+
{ text: req.__("Module store"), href: "/plugins" },
|
|
698
696
|
{ text: req.__("New") },
|
|
699
697
|
],
|
|
700
698
|
},
|
|
701
699
|
{
|
|
702
700
|
type: "card",
|
|
703
|
-
title: req.__(`Add
|
|
701
|
+
title: req.__(`Add module`),
|
|
704
702
|
contents: renderForm(pluginForm(req), req.csrfToken()),
|
|
705
703
|
},
|
|
706
704
|
],
|
|
@@ -808,35 +806,35 @@ router.get(
|
|
|
808
806
|
latest || "",
|
|
809
807
|
can_update
|
|
810
808
|
? a(
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
809
|
+
{
|
|
810
|
+
href: `/plugins/upgrade-plugin/${plugin_db.name}`,
|
|
811
|
+
class: "btn btn-primary btn-sm ms-2",
|
|
812
|
+
},
|
|
813
|
+
req.__("Upgrade")
|
|
814
|
+
)
|
|
817
815
|
: ""
|
|
818
816
|
)
|
|
819
817
|
),
|
|
820
818
|
mod.plugin_module.dependencies
|
|
821
819
|
? tr(
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
)
|
|
820
|
+
th(req.__("Plugin dependencies")),
|
|
821
|
+
td(
|
|
822
|
+
mod.plugin_module.dependencies.map((d) =>
|
|
823
|
+
span({ class: "badge bg-primary me-1" }, d)
|
|
827
824
|
)
|
|
828
825
|
)
|
|
826
|
+
)
|
|
829
827
|
: null,
|
|
830
828
|
store_item && store_item.documentation_link
|
|
831
829
|
? tr(
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
)
|
|
830
|
+
th(req.__("Documentation")),
|
|
831
|
+
td(
|
|
832
|
+
link(
|
|
833
|
+
store_item.documentation_link,
|
|
834
|
+
store_item.documentation_link
|
|
838
835
|
)
|
|
839
836
|
)
|
|
837
|
+
)
|
|
840
838
|
: null,
|
|
841
839
|
pkgjson && pkgjson.repository
|
|
842
840
|
? tr(th(req.__("Repository")), td(showRepository(pkgjson.repository)))
|
|
@@ -861,13 +859,13 @@ router.get(
|
|
|
861
859
|
type: "breadcrumbs",
|
|
862
860
|
crumbs: [
|
|
863
861
|
{ text: req.__("Settings"), href: "/settings" },
|
|
864
|
-
{ text: req.__("
|
|
862
|
+
{ text: req.__("Module store"), href: "/plugins" },
|
|
865
863
|
{ text: plugin_db.name },
|
|
866
864
|
],
|
|
867
865
|
},
|
|
868
866
|
{
|
|
869
867
|
type: "card",
|
|
870
|
-
title: req.__(`%s
|
|
868
|
+
title: req.__(`%s module information`, plugin_db.name),
|
|
871
869
|
contents: p(store_item.description) + infoTable,
|
|
872
870
|
},
|
|
873
871
|
...cards,
|
|
@@ -913,7 +911,7 @@ router.get(
|
|
|
913
911
|
for (const plugin of installed_plugins) {
|
|
914
912
|
await plugin.upgrade_version((p, f) => load_plugins.loadPlugin(p, f));
|
|
915
913
|
}
|
|
916
|
-
req.flash("success", req.__(`
|
|
914
|
+
req.flash("success", req.__(`Modules up-to-date`));
|
|
917
915
|
await restart_tenant(loadAllPlugins);
|
|
918
916
|
process.send &&
|
|
919
917
|
process.send({ restart_tenant: true, tenant: db.getTenantSchema() });
|
package/routes/settings.js
CHANGED
|
@@ -63,9 +63,9 @@ router.get(
|
|
|
63
63
|
href: "/admin",
|
|
64
64
|
}),
|
|
65
65
|
settingsCard({
|
|
66
|
-
title: req.__("
|
|
67
|
-
icon: "fas fa-
|
|
68
|
-
blurb: req.__("
|
|
66
|
+
title: req.__("Modules"),
|
|
67
|
+
icon: "fas fa-cubes",
|
|
68
|
+
blurb: req.__("Module installation and control"),
|
|
69
69
|
href: "/plugins",
|
|
70
70
|
}),
|
|
71
71
|
settingsCard({
|