@saltcorn/server 0.7.3 → 0.7.4-beta.2
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 +2 -1
- package/auth/routes.js +80 -92
- package/errors.js +51 -48
- package/locales/en.json +47 -2
- package/locales/it.json +2 -1
- package/locales/ru.json +42 -6
- package/locales/zh.json +1 -1
- package/markup/admin.js +15 -1
- package/markup/plugin-store.js +5 -5
- package/package.json +7 -7
- package/public/jquery-menu-editor.min.js +1 -1
- package/public/saltcorn-builder.css +75 -0
- package/public/saltcorn-common.js +24 -9
- package/public/saltcorn.css +28 -1
- package/public/saltcorn.js +9 -7
- package/routes/actions.js +2 -39
- package/routes/admin.js +375 -90
- package/routes/api.js +9 -1
- package/routes/common_lists.js +419 -0
- package/routes/fields.js +34 -19
- package/routes/homepage.js +60 -60
- package/routes/index.js +4 -0
- package/routes/menu.js +65 -4
- package/routes/packs.js +4 -4
- package/routes/page.js +5 -1
- package/routes/pageedit.js +13 -98
- package/routes/plugins.js +116 -118
- package/routes/settings.js +3 -3
- package/routes/tables.js +158 -193
- package/routes/tag_entries.js +173 -0
- package/routes/tags.js +266 -0
- package/routes/tenant.js +27 -27
- package/routes/utils.js +4 -0
- package/routes/view.js +18 -1
- package/routes/viewedit.js +22 -132
- package/serve.js +54 -38
- package/tests/admin.test.js +1 -1
- package/tests/api.test.js +17 -0
- package/tests/clientjs.test.js +11 -1
- package/tests/plugins.test.js +1 -1
- package/tests/viewedit.test.js +1 -1
- package/wrapper.js +57 -55
package/routes/api.js
CHANGED
|
@@ -112,6 +112,13 @@ function accessAllowed(req, user, trigger) {
|
|
|
112
112
|
return role <= trigger.min_role;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
const getFlashes = (req) =>
|
|
116
|
+
["error", "success", "danger", "warning", "information"]
|
|
117
|
+
.map((type) => {
|
|
118
|
+
return { type, msg: req.flash(type) };
|
|
119
|
+
})
|
|
120
|
+
.filter((a) => a.msg && a.msg.length && a.msg.length > 0);
|
|
121
|
+
|
|
115
122
|
router.post(
|
|
116
123
|
"/viewQuery/:viewName/:queryName",
|
|
117
124
|
error_catcher(async (req, res, next) => {
|
|
@@ -134,7 +141,7 @@ router.post(
|
|
|
134
141
|
if (queries[queryName]) {
|
|
135
142
|
const { args } = req.body;
|
|
136
143
|
const resp = await queries[queryName](...args, true);
|
|
137
|
-
res.json({ success: resp });
|
|
144
|
+
res.json({ success: resp, alerts: getFlashes(req) });
|
|
138
145
|
} else {
|
|
139
146
|
res.status(404).json({ error: req.__("Not found") });
|
|
140
147
|
}
|
|
@@ -235,6 +242,7 @@ router.get(
|
|
|
235
242
|
rows = await table.getJoinedRows(joinOpts);
|
|
236
243
|
} else if (req_query && req_query !== {}) {
|
|
237
244
|
const tbl_fields = await table.getFields();
|
|
245
|
+
readState(req_query, tbl_fields, req);
|
|
238
246
|
const qstate = await stateFieldsToWhere({
|
|
239
247
|
fields: tbl_fields,
|
|
240
248
|
approximate: !!approximate,
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
const User = require("@saltcorn/data/models/user");
|
|
2
|
+
const Table = require("@saltcorn/data/models/table");
|
|
3
|
+
const { editRoleForm } = require("../markup/forms.js");
|
|
4
|
+
const {
|
|
5
|
+
mkTable,
|
|
6
|
+
link,
|
|
7
|
+
post_delete_btn,
|
|
8
|
+
settingsDropdown,
|
|
9
|
+
post_dropdown_item,
|
|
10
|
+
} = require("@saltcorn/markup");
|
|
11
|
+
|
|
12
|
+
const { h4, p, div, a, input, text } = require("@saltcorn/markup/tags");
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} col
|
|
16
|
+
* @param {string} lbl
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
const badge = (col, lbl) => `<span class="badge bg-${col}">${lbl}</span> `;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Table badges to show in System Table list views
|
|
23
|
+
* Currently supports:
|
|
24
|
+
* - Owned - if ownership_field_id? What is it?
|
|
25
|
+
* - History - if table has versioning
|
|
26
|
+
* - External - if this is external table
|
|
27
|
+
* @param {object} t table object
|
|
28
|
+
* @param {object} req http request
|
|
29
|
+
* @returns {string} html string with list of badges
|
|
30
|
+
*/
|
|
31
|
+
const tableBadges = (t, req) => {
|
|
32
|
+
let s = "";
|
|
33
|
+
if (t.ownership_field_id) s += badge("primary", req.__("Owned"));
|
|
34
|
+
if (t.versioned) s += badge("success", req.__("History"));
|
|
35
|
+
if (t.external) s += badge("info", req.__("External"));
|
|
36
|
+
return s;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const valIfSet = (check, value) => (check ? value : "");
|
|
40
|
+
|
|
41
|
+
const listClass = (tagId, showList) =>
|
|
42
|
+
valIfSet(tagId, `collapse ${valIfSet(showList, "show")}`);
|
|
43
|
+
|
|
44
|
+
const tablesList = async (tables, req, { tagId, domId, showList } = {}) => {
|
|
45
|
+
const roles = await User.get_roles();
|
|
46
|
+
const getRole = (rid) => roles.find((r) => r.id === rid).role;
|
|
47
|
+
return tables.length > 0
|
|
48
|
+
? mkTable(
|
|
49
|
+
[
|
|
50
|
+
{
|
|
51
|
+
label: req.__("Name"),
|
|
52
|
+
key: (r) => link(`/table/${r.id || r.name}`, text(r.name)),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: "",
|
|
56
|
+
key: (r) => tableBadges(r, req),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: req.__("Access Read/Write"),
|
|
60
|
+
key: (t) =>
|
|
61
|
+
t.external
|
|
62
|
+
? `${getRole(t.min_role_read)} (read only)`
|
|
63
|
+
: `${getRole(t.min_role_read)}/${getRole(t.min_role_write)}`,
|
|
64
|
+
},
|
|
65
|
+
!tagId
|
|
66
|
+
? {
|
|
67
|
+
label: req.__("Delete"),
|
|
68
|
+
key: (r) =>
|
|
69
|
+
r.name === "users" || r.external
|
|
70
|
+
? ""
|
|
71
|
+
: post_delete_btn(`/table/delete/${r.id}`, req, r.name),
|
|
72
|
+
}
|
|
73
|
+
: {
|
|
74
|
+
label: req.__("Remove From Tag"),
|
|
75
|
+
key: (r) =>
|
|
76
|
+
post_delete_btn(
|
|
77
|
+
`/tag-entries/remove/tables/${r.id}/${tagId}`,
|
|
78
|
+
req,
|
|
79
|
+
`${r.name} from this tag`
|
|
80
|
+
),
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
tables,
|
|
84
|
+
{
|
|
85
|
+
hover: true,
|
|
86
|
+
tableClass: listClass(tagId, showList),
|
|
87
|
+
tableId: domId,
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
: div(
|
|
91
|
+
{ class: listClass(tagId, showList), id: domId },
|
|
92
|
+
h4(req.__("No tables defined")),
|
|
93
|
+
p(req.__("Tables hold collections of similar data"))
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {object} view
|
|
99
|
+
* @param {object[]} roles
|
|
100
|
+
* @param {object} req
|
|
101
|
+
* @returns {Form}
|
|
102
|
+
*/
|
|
103
|
+
const editViewRoleForm = (view, roles, req) =>
|
|
104
|
+
editRoleForm({
|
|
105
|
+
url: `/viewedit/setrole/${view.id}`,
|
|
106
|
+
current_role: view.min_role,
|
|
107
|
+
roles,
|
|
108
|
+
req,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {object} view
|
|
113
|
+
* @param {object} req
|
|
114
|
+
* @returns {div}
|
|
115
|
+
*/
|
|
116
|
+
const view_dropdown = (view, req) =>
|
|
117
|
+
settingsDropdown(`dropdownMenuButton${view.id}`, [
|
|
118
|
+
a(
|
|
119
|
+
{
|
|
120
|
+
class: "dropdown-item",
|
|
121
|
+
href: `/view/${encodeURIComponent(view.name)}`,
|
|
122
|
+
},
|
|
123
|
+
'<i class="fas fa-running"></i> ' + req.__("Run")
|
|
124
|
+
),
|
|
125
|
+
a(
|
|
126
|
+
{
|
|
127
|
+
class: "dropdown-item",
|
|
128
|
+
href: `/viewedit/edit/${encodeURIComponent(view.name)}`,
|
|
129
|
+
},
|
|
130
|
+
'<i class="fas fa-edit"></i> ' + req.__("Edit")
|
|
131
|
+
),
|
|
132
|
+
post_dropdown_item(
|
|
133
|
+
`/viewedit/add-to-menu/${view.id}`,
|
|
134
|
+
'<i class="fas fa-bars"></i> ' + req.__("Add to menu"),
|
|
135
|
+
req
|
|
136
|
+
),
|
|
137
|
+
post_dropdown_item(
|
|
138
|
+
`/viewedit/clone/${view.id}`,
|
|
139
|
+
'<i class="far fa-copy"></i> ' + req.__("Duplicate"),
|
|
140
|
+
req
|
|
141
|
+
),
|
|
142
|
+
a(
|
|
143
|
+
{
|
|
144
|
+
class: "dropdown-item",
|
|
145
|
+
href: `javascript:ajax_modal('/admin/snapshot-restore/view/${view.name}')`,
|
|
146
|
+
},
|
|
147
|
+
'<i class="fas fa-undo-alt"></i> ' + req.__("Restore")
|
|
148
|
+
),
|
|
149
|
+
div({ class: "dropdown-divider" }),
|
|
150
|
+
post_dropdown_item(
|
|
151
|
+
`/viewedit/delete/${view.id}`,
|
|
152
|
+
'<i class="far fa-trash-alt"></i> ' + req.__("Delete"),
|
|
153
|
+
req,
|
|
154
|
+
true,
|
|
155
|
+
view.name
|
|
156
|
+
),
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
const setTableRefs = async (views) => {
|
|
160
|
+
const tables = await Table.find();
|
|
161
|
+
const getTable = (tid) => tables.find((t) => t.id === tid).name;
|
|
162
|
+
|
|
163
|
+
views.forEach((v) => {
|
|
164
|
+
if (v.table_id) v.table = getTable(v.table_id);
|
|
165
|
+
else if (v.exttable_name) v.table = v.exttable_name;
|
|
166
|
+
else v.table = "";
|
|
167
|
+
});
|
|
168
|
+
return views;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const viewsList = async (views, req, { tagId, domId, showList } = {}) => {
|
|
172
|
+
const roles = await User.get_roles();
|
|
173
|
+
|
|
174
|
+
return views.length > 0
|
|
175
|
+
? mkTable(
|
|
176
|
+
[
|
|
177
|
+
{
|
|
178
|
+
label: req.__("Name"),
|
|
179
|
+
key: (r) => link(`/view/${encodeURIComponent(r.name)}`, r.name),
|
|
180
|
+
sortlink: !tagId
|
|
181
|
+
? `javascript:set_state_field('_sortby', 'name')`
|
|
182
|
+
: undefined,
|
|
183
|
+
},
|
|
184
|
+
// description - currently I dont want to show description in view list
|
|
185
|
+
// because description can be long
|
|
186
|
+
/*
|
|
187
|
+
{
|
|
188
|
+
label: req.__("Description"),
|
|
189
|
+
key: "description",
|
|
190
|
+
// this is sorting by column
|
|
191
|
+
sortlink: `javascript:set_state_field('_sortby', 'description')`,
|
|
192
|
+
},
|
|
193
|
+
*/
|
|
194
|
+
// template
|
|
195
|
+
{
|
|
196
|
+
label: req.__("Pattern"),
|
|
197
|
+
key: "viewtemplate",
|
|
198
|
+
sortlink: !tagId
|
|
199
|
+
? `javascript:set_state_field('_sortby', 'viewtemplate')`
|
|
200
|
+
: undefined,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
label: req.__("Table"),
|
|
204
|
+
key: (r) => link(`/table/${r.table}`, r.table),
|
|
205
|
+
sortlink: !tagId
|
|
206
|
+
? `javascript:set_state_field('_sortby', 'table')`
|
|
207
|
+
: undefined,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
label: req.__("Role to access"),
|
|
211
|
+
key: (row) => editViewRoleForm(row, roles, req),
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
label: "",
|
|
215
|
+
key: (r) =>
|
|
216
|
+
link(
|
|
217
|
+
`/viewedit/config/${encodeURIComponent(r.name)}`,
|
|
218
|
+
req.__("Configure")
|
|
219
|
+
),
|
|
220
|
+
},
|
|
221
|
+
!tagId
|
|
222
|
+
? {
|
|
223
|
+
label: "",
|
|
224
|
+
key: (r) => view_dropdown(r, req),
|
|
225
|
+
}
|
|
226
|
+
: {
|
|
227
|
+
label: req.__("Remove From Tag"),
|
|
228
|
+
key: (r) =>
|
|
229
|
+
post_delete_btn(
|
|
230
|
+
`/tag-entries/remove/views/${r.id}/${tagId}`,
|
|
231
|
+
req,
|
|
232
|
+
`${r.name} from this tag`
|
|
233
|
+
),
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
views,
|
|
237
|
+
{
|
|
238
|
+
hover: true,
|
|
239
|
+
tableClass: listClass(tagId, showList),
|
|
240
|
+
tableId: domId,
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
: div(
|
|
244
|
+
{ class: listClass(tagId, showList), id: domId },
|
|
245
|
+
h4(req.__("No views defined")),
|
|
246
|
+
p(req.__("Views define how table rows are displayed to the user"))
|
|
247
|
+
);
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @param {object} page
|
|
252
|
+
* @param {object} req
|
|
253
|
+
* @returns {string}
|
|
254
|
+
*/
|
|
255
|
+
const page_dropdown = (page, req) =>
|
|
256
|
+
settingsDropdown(`dropdownMenuButton${page.id}`, [
|
|
257
|
+
a(
|
|
258
|
+
{
|
|
259
|
+
class: "dropdown-item",
|
|
260
|
+
href: `/page/${encodeURIComponent(page.name)}`,
|
|
261
|
+
},
|
|
262
|
+
'<i class="fas fa-running"></i> ' + req.__("Run")
|
|
263
|
+
),
|
|
264
|
+
a(
|
|
265
|
+
{
|
|
266
|
+
class: "dropdown-item",
|
|
267
|
+
href: `/pageedit/edit-properties/${encodeURIComponent(page.name)}`,
|
|
268
|
+
},
|
|
269
|
+
'<i class="fas fa-edit"></i> ' + req.__("Edit properties")
|
|
270
|
+
),
|
|
271
|
+
post_dropdown_item(
|
|
272
|
+
`/pageedit/add-to-menu/${page.id}`,
|
|
273
|
+
'<i class="fas fa-bars"></i> ' + req.__("Add to menu"),
|
|
274
|
+
req
|
|
275
|
+
),
|
|
276
|
+
post_dropdown_item(
|
|
277
|
+
`/pageedit/clone/${page.id}`,
|
|
278
|
+
'<i class="far fa-copy"></i> ' + req.__("Duplicate"),
|
|
279
|
+
req
|
|
280
|
+
),
|
|
281
|
+
a(
|
|
282
|
+
{
|
|
283
|
+
class: "dropdown-item",
|
|
284
|
+
href: `javascript:ajax_modal('/admin/snapshot-restore/page/${page.name}')`,
|
|
285
|
+
},
|
|
286
|
+
'<i class="fas fa-undo-alt"></i> ' + req.__("Restore")
|
|
287
|
+
),
|
|
288
|
+
div({ class: "dropdown-divider" }),
|
|
289
|
+
post_dropdown_item(
|
|
290
|
+
`/pageedit/delete/${page.id}`,
|
|
291
|
+
'<i class="far fa-trash-alt"></i> ' + req.__("Delete"),
|
|
292
|
+
req,
|
|
293
|
+
true,
|
|
294
|
+
page.name
|
|
295
|
+
),
|
|
296
|
+
]);
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* @param {object} page
|
|
300
|
+
* @param {*} roles
|
|
301
|
+
* @param {object} req
|
|
302
|
+
* @returns {Form}
|
|
303
|
+
*/
|
|
304
|
+
const editPageRoleForm = (page, roles, req) =>
|
|
305
|
+
editRoleForm({
|
|
306
|
+
url: `/pageedit/setrole/${page.id}`,
|
|
307
|
+
current_role: page.min_role,
|
|
308
|
+
roles,
|
|
309
|
+
req,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @param {*} rows
|
|
314
|
+
* @param {*} roles
|
|
315
|
+
* @param {object} req
|
|
316
|
+
* @returns {div}
|
|
317
|
+
*/
|
|
318
|
+
const getPageList = (rows, roles, req, { tagId, domId, showList } = {}) => {
|
|
319
|
+
return mkTable(
|
|
320
|
+
[
|
|
321
|
+
{
|
|
322
|
+
label: req.__("Name"),
|
|
323
|
+
key: (r) => link(`/page/${r.name}`, r.name),
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
label: req.__("Role to access"),
|
|
327
|
+
key: (row) => editPageRoleForm(row, roles, req),
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
label: req.__("Edit"),
|
|
331
|
+
key: (r) => link(`/pageedit/edit/${r.name}`, req.__("Edit")),
|
|
332
|
+
},
|
|
333
|
+
!tagId
|
|
334
|
+
? {
|
|
335
|
+
label: "",
|
|
336
|
+
key: (r) => page_dropdown(r, req),
|
|
337
|
+
}
|
|
338
|
+
: {
|
|
339
|
+
label: req.__("Remove From Tag"),
|
|
340
|
+
key: (r) =>
|
|
341
|
+
post_delete_btn(
|
|
342
|
+
`/tag-entries/remove/pages/${r.id}/${tagId}`,
|
|
343
|
+
req,
|
|
344
|
+
`${r.name} from this tag`
|
|
345
|
+
),
|
|
346
|
+
},
|
|
347
|
+
,
|
|
348
|
+
],
|
|
349
|
+
rows,
|
|
350
|
+
{
|
|
351
|
+
hover: true,
|
|
352
|
+
tableClass: tagId ? `collapse ${showList ? "show" : ""}` : "",
|
|
353
|
+
tableId: domId,
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const getTriggerList = (triggers, req, { tagId, domId, showList } = {}) => {
|
|
359
|
+
return mkTable(
|
|
360
|
+
[
|
|
361
|
+
{ label: req.__("Name"), key: "name" },
|
|
362
|
+
{ label: req.__("Action"), key: "action" },
|
|
363
|
+
{
|
|
364
|
+
label: req.__("Table or Channel"),
|
|
365
|
+
key: (r) => r.table_name || r.channel,
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
label: req.__("When"),
|
|
369
|
+
key: (a) =>
|
|
370
|
+
a.when_trigger === "API call"
|
|
371
|
+
? `API: ${base_url}api/action/${a.name}`
|
|
372
|
+
: a.when_trigger,
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
label: req.__("Test run"),
|
|
376
|
+
key: (r) =>
|
|
377
|
+
r.table_id
|
|
378
|
+
? ""
|
|
379
|
+
: link(`/actions/testrun/${r.id}`, req.__("Test run")),
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
label: req.__("Edit"),
|
|
383
|
+
key: (r) => link(`/actions/edit/${r.id}`, req.__("Edit")),
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
label: req.__("Configure"),
|
|
387
|
+
key: (r) => link(`/actions/configure/${r.id}`, req.__("Configure")),
|
|
388
|
+
},
|
|
389
|
+
!tagId
|
|
390
|
+
? {
|
|
391
|
+
label: req.__("Delete"),
|
|
392
|
+
key: (r) => post_delete_btn(`/actions/delete/${r.id}`, req),
|
|
393
|
+
}
|
|
394
|
+
: {
|
|
395
|
+
label: req.__("Remove From Tag"),
|
|
396
|
+
key: (r) =>
|
|
397
|
+
post_delete_btn(
|
|
398
|
+
`/tag-entries/remove/trigger/${r.id}/${tagId}`,
|
|
399
|
+
req,
|
|
400
|
+
`${r.name} from this tag`
|
|
401
|
+
),
|
|
402
|
+
},
|
|
403
|
+
],
|
|
404
|
+
triggers,
|
|
405
|
+
{
|
|
406
|
+
hover: true,
|
|
407
|
+
tableClass: tagId ? `collapse ${showList ? "show" : ""}` : "",
|
|
408
|
+
tableId: domId,
|
|
409
|
+
}
|
|
410
|
+
);
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
module.exports = {
|
|
414
|
+
tablesList,
|
|
415
|
+
setTableRefs,
|
|
416
|
+
viewsList,
|
|
417
|
+
getPageList,
|
|
418
|
+
getTriggerList,
|
|
419
|
+
};
|
package/routes/fields.js
CHANGED
|
@@ -28,6 +28,7 @@ const { readState } = require("@saltcorn/data/plugin-helper");
|
|
|
28
28
|
const { wizardCardTitle } = require("../markup/forms.js");
|
|
29
29
|
const FieldRepeat = require("@saltcorn/data/models/fieldrepeat");
|
|
30
30
|
const { applyAsync } = require("@saltcorn/data/utils");
|
|
31
|
+
const { text } = require("@saltcorn/markup/tags");
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* @type {object}
|
|
@@ -348,13 +349,12 @@ const fieldFlow = (req) =>
|
|
|
348
349
|
// todo sublabel
|
|
349
350
|
input_type: "custom_html",
|
|
350
351
|
attributes: {
|
|
351
|
-
html: `<button type="button" id="test_formula_btn" onclick="test_formula('${
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
)}</button>
|
|
352
|
+
html: `<button type="button" id="test_formula_btn" onclick="test_formula('${table.name
|
|
353
|
+
}', ${JSON.stringify(
|
|
354
|
+
context.stored
|
|
355
|
+
)})" class="btn btn-outline-secondary">${req.__(
|
|
356
|
+
"Test"
|
|
357
|
+
)}</button>
|
|
358
358
|
<div id="test_formula_output"></div>`,
|
|
359
359
|
},
|
|
360
360
|
}),
|
|
@@ -633,8 +633,7 @@ router.post(
|
|
|
633
633
|
result = f(rows[0]);
|
|
634
634
|
}
|
|
635
635
|
res.send(
|
|
636
|
-
`Result of running on row with id=${
|
|
637
|
-
rows[0].id
|
|
636
|
+
`Result of running on row with id=${rows[0].id
|
|
638
637
|
} is: <pre>${JSON.stringify(result)}</pre>`
|
|
639
638
|
);
|
|
640
639
|
} catch (e) {
|
|
@@ -679,14 +678,30 @@ router.post(
|
|
|
679
678
|
(f) => f.name === kpath[1]
|
|
680
679
|
);
|
|
681
680
|
//console.log({ kpath, fieldview, targetField });
|
|
682
|
-
let fv = targetField.type.fieldviews[fieldview];
|
|
683
|
-
if (!fv) {
|
|
684
|
-
fv =
|
|
685
|
-
targetField.type.fieldviews.show ||
|
|
686
|
-
targetField.type.fieldviews.as_text;
|
|
687
|
-
}
|
|
688
681
|
const q = { [reftable.pk_name]: row[kpath[0]] };
|
|
689
682
|
const refRow = await reftable.getRow(q);
|
|
683
|
+
let fv;
|
|
684
|
+
if (targetField.type === "Key") {
|
|
685
|
+
fv = getState().keyFieldviews[fieldview]
|
|
686
|
+
if (!fv) {
|
|
687
|
+
const reftable2 = Table.findOne({ name: targetField.reftable_name })
|
|
688
|
+
const refRow2 = await reftable2.getRow({ [reftable2.pk_name]: refRow[kpath[1]] })
|
|
689
|
+
if (refRow2) {
|
|
690
|
+
res.send(text(`${refRow2[targetField.attributes.summary_field]}`));
|
|
691
|
+
} else {
|
|
692
|
+
res.send("");
|
|
693
|
+
}
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
} else {
|
|
697
|
+
targetField.type.fieldviews[fieldview];
|
|
698
|
+
if (!fv)
|
|
699
|
+
fv =
|
|
700
|
+
targetField.type.fieldviews.show ||
|
|
701
|
+
targetField.type.fieldviews.as_text;
|
|
702
|
+
|
|
703
|
+
}
|
|
704
|
+
|
|
690
705
|
const configuration = req.query;
|
|
691
706
|
let configFields = [];
|
|
692
707
|
if (fv.configFields)
|
|
@@ -788,22 +803,22 @@ router.post(
|
|
|
788
803
|
field.type === "Key"
|
|
789
804
|
? getState().keyFieldviews
|
|
790
805
|
: field.type === "File"
|
|
791
|
-
|
|
792
|
-
|
|
806
|
+
? getState().fileviews
|
|
807
|
+
: field.type.fieldviews;
|
|
793
808
|
if (!field.type || !fieldviews) {
|
|
794
809
|
res.send("");
|
|
795
810
|
return;
|
|
796
811
|
}
|
|
797
812
|
const fv = fieldviews[fieldview];
|
|
798
813
|
if (!fv && field.type === "Key" && fieldview === "select")
|
|
799
|
-
res.send("
|
|
814
|
+
res.send(`<input readonly class="form-control form-select"></input>`);
|
|
800
815
|
else if (!fv) res.send("");
|
|
801
816
|
else if (fv.isEdit || fv.isFilter)
|
|
802
817
|
res.send(
|
|
803
818
|
fv.run(
|
|
804
819
|
field.name,
|
|
805
820
|
undefined,
|
|
806
|
-
{
|
|
821
|
+
{ readonly: true, ...configuration, ...(field.attributes || {}) },
|
|
807
822
|
"",
|
|
808
823
|
false,
|
|
809
824
|
field
|