@opengis/fastify-table 1.4.65 → 1.4.67
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/package.json +61 -61
- package/server/helpers/core/token.js +18 -18
- package/server/plugins/cron/funcs/addCron.js +52 -52
- package/server/plugins/crud/funcs/getOpt.js +14 -14
- package/server/plugins/crud/funcs/setToken.js +1 -1
- package/server/plugins/crud/funcs/utils/getFolder.js +11 -11
- package/server/plugins/logger/errorStatus.js +19 -19
- package/server/plugins/redis/client.js +8 -8
- package/server/plugins/redis/funcs/redisClients.js +3 -3
- package/server/plugins/table/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
- package/server/plugins/table/funcs/getFilterSQL/util/getTableSql.js +34 -34
- package/server/plugins/table/funcs/getTemplates.js +19 -19
- package/server/plugins/table/funcs/gisIRColumn.js +82 -82
- package/server/plugins/table/funcs/loadTemplate.js +1 -1
- package/server/plugins/table/funcs/loadTemplatePath.js +1 -1
- package/server/plugins/table/funcs/userTemplateDir.js +1 -1
- package/server/routes/crud/controllers/table.js +7 -6
- package/server/routes/table/controllers/form.js +3 -3
- package/server/routes/table/controllers/getFormByTable.js +110 -0
- package/server/routes/table/controllers/search.js +74 -74
- package/server/routes/table/functions/getData.js +5 -3
- package/server/routes/table/index.js +3 -2
- package/server/routes/table/schema.js +1 -1
- package/server/routes/widget/controllers/widget.del.js +89 -89
- package/server/routes/widget/hook/onWidgetSet.js +13 -13
- package/server/routes/widget/index.mjs +38 -38
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import getSelect from './getSelect.js';
|
|
2
|
-
|
|
3
|
-
import getFilterSQL from './getFilterSQL/index.js';
|
|
4
|
-
import getTemplate from './getTemplate.js';
|
|
5
|
-
import pgClients from '../../pg/pgClients.js';
|
|
6
|
-
import config from '../../../../config.js';
|
|
7
|
-
import getSelectVal from './metaFormat/getSelectVal.js';
|
|
8
|
-
|
|
9
|
-
export default async function gisIRColumn({
|
|
10
|
-
pg = pgClients.client, layer, column, sql, query = '1=1', filter, state, search, custom,
|
|
11
|
-
}) {
|
|
12
|
-
const time = Date.now();
|
|
13
|
-
|
|
14
|
-
const sel = await getSelect(query.cls || column, pg);
|
|
15
|
-
|
|
16
|
-
const body = await getTemplate('table', layer);
|
|
17
|
-
const fData = await getFilterSQL({
|
|
18
|
-
table: layer,
|
|
19
|
-
filter,
|
|
20
|
-
state,
|
|
21
|
-
search,
|
|
22
|
-
custom,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const { tlist } = await pg.one(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist from pg_class
|
|
26
|
-
where relkind in ('r','v','m')`);
|
|
27
|
-
|
|
28
|
-
const tableName = body?.table || layer;
|
|
29
|
-
if (!tlist.includes(tableName)) return { error: `table not found: ${tableName}`, status: 400 };
|
|
30
|
-
|
|
31
|
-
// eslint-disable-next-line max-len
|
|
32
|
-
const { fields } = await pg.query(`select * from (${fData?.optimizedSQL || `select * from ${tableName}`})q limit 0`);
|
|
33
|
-
|
|
34
|
-
const col = fields.find((el) => el.name === column);
|
|
35
|
-
|
|
36
|
-
if (!col) return { status: 404, message: 'not found' };
|
|
37
|
-
const colField = pg.pgType[col.dataTypeID]?.includes('[]') ? `unnest(${column})` : column;
|
|
38
|
-
|
|
39
|
-
const q = `select ${colField} as id, count(*)::int from (
|
|
40
|
-
${fData?.optimizedSQL || `select * from ${tableName} where ${body?.query || 'true'}`}
|
|
41
|
-
)t group by ${colField} order by count desc limit 15`;
|
|
42
|
-
|
|
43
|
-
if (sql) return q;
|
|
44
|
-
|
|
45
|
-
if (!body?.columns?.length) {
|
|
46
|
-
const { rows } = await pg.query(q);
|
|
47
|
-
if (sel?.arr?.length) {
|
|
48
|
-
rows.forEach((el) => {
|
|
49
|
-
const data = sel?.find((item) => item.id?.toString() === el.id?.toString());
|
|
50
|
-
Object.assign(el, data || {});
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
count: rows?.reduce((acc, el) => acc + el.count, 0),
|
|
55
|
-
sql: config.local ? q : undefined,
|
|
56
|
-
rows,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const { rows } = await pg.query(q);
|
|
61
|
-
const cls = query.cls || body?.columns?.find((el) => el.name === column)?.data || col.data || col.option;
|
|
62
|
-
const select = await getSelectVal({
|
|
63
|
-
pg, name: cls, values: rows.map((el) => el.id), ar: 1,
|
|
64
|
-
});
|
|
65
|
-
rows.forEach((el) => {
|
|
66
|
-
if (Array.isArray(select)) {
|
|
67
|
-
Object.assign(el, select.find((item) => item.id?.toString() === el.id?.toString()) || {});
|
|
68
|
-
}
|
|
69
|
-
else if (typeof select?.[el.id] === 'string') {
|
|
70
|
-
Object.assign(el, { text: select?.[el.id] });
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
Object.assign(el, select?.[el.id] || {});
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
return {
|
|
77
|
-
time: Date.now() - time,
|
|
78
|
-
count: rows.reduce((acc, el) => acc + el.count, 0),
|
|
79
|
-
sql: config.local ? q : undefined,
|
|
80
|
-
rows,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
1
|
+
import getSelect from './getSelect.js';
|
|
2
|
+
|
|
3
|
+
import getFilterSQL from './getFilterSQL/index.js';
|
|
4
|
+
import getTemplate from './getTemplate.js';
|
|
5
|
+
import pgClients from '../../pg/pgClients.js';
|
|
6
|
+
import config from '../../../../config.js';
|
|
7
|
+
import getSelectVal from './metaFormat/getSelectVal.js';
|
|
8
|
+
|
|
9
|
+
export default async function gisIRColumn({
|
|
10
|
+
pg = pgClients.client, layer, column, sql, query = '1=1', filter, state, search, custom,
|
|
11
|
+
}) {
|
|
12
|
+
const time = Date.now();
|
|
13
|
+
|
|
14
|
+
const sel = await getSelect(query.cls || column, pg);
|
|
15
|
+
|
|
16
|
+
const body = await getTemplate('table', layer);
|
|
17
|
+
const fData = await getFilterSQL({
|
|
18
|
+
table: layer,
|
|
19
|
+
filter,
|
|
20
|
+
state,
|
|
21
|
+
search,
|
|
22
|
+
custom,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const { tlist } = await pg.one(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist from pg_class
|
|
26
|
+
where relkind in ('r','v','m')`);
|
|
27
|
+
|
|
28
|
+
const tableName = body?.table || layer;
|
|
29
|
+
if (!tlist.includes(tableName)) return { error: `table not found: ${tableName}`, status: 400 };
|
|
30
|
+
|
|
31
|
+
// eslint-disable-next-line max-len
|
|
32
|
+
const { fields } = await pg.query(`select * from (${fData?.optimizedSQL || `select * from ${tableName}`})q limit 0`);
|
|
33
|
+
|
|
34
|
+
const col = fields.find((el) => el.name === column);
|
|
35
|
+
|
|
36
|
+
if (!col) return { status: 404, message: 'not found' };
|
|
37
|
+
const colField = pg.pgType[col.dataTypeID]?.includes('[]') ? `unnest(${column})` : column;
|
|
38
|
+
|
|
39
|
+
const q = `select ${colField} as id, count(*)::int from (
|
|
40
|
+
${fData?.optimizedSQL || `select * from ${tableName} where ${body?.query || 'true'}`}
|
|
41
|
+
)t group by ${colField} order by count desc limit 15`;
|
|
42
|
+
|
|
43
|
+
if (sql) return q;
|
|
44
|
+
|
|
45
|
+
if (!body?.columns?.length) {
|
|
46
|
+
const { rows } = await pg.query(q);
|
|
47
|
+
if (sel?.arr?.length) {
|
|
48
|
+
rows.forEach((el) => {
|
|
49
|
+
const data = sel?.find((item) => item.id?.toString() === el.id?.toString());
|
|
50
|
+
Object.assign(el, data || {});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
count: rows?.reduce((acc, el) => acc + el.count, 0),
|
|
55
|
+
sql: config.local ? q : undefined,
|
|
56
|
+
rows,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const { rows } = await pg.query(q);
|
|
61
|
+
const cls = query.cls || body?.columns?.find((el) => el.name === column)?.data || col.data || col.option;
|
|
62
|
+
const select = await getSelectVal({
|
|
63
|
+
pg, name: cls, values: rows.map((el) => el.id), ar: 1,
|
|
64
|
+
});
|
|
65
|
+
rows.forEach((el) => {
|
|
66
|
+
if (Array.isArray(select)) {
|
|
67
|
+
Object.assign(el, select.find((item) => item.id?.toString() === el.id?.toString()) || {});
|
|
68
|
+
}
|
|
69
|
+
else if (typeof select?.[el.id] === 'string') {
|
|
70
|
+
Object.assign(el, { text: select?.[el.id] });
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
Object.assign(el, select?.[el.id] || {});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
time: Date.now() - time,
|
|
78
|
+
count: rows.reduce((acc, el) => acc + el.count, 0),
|
|
79
|
+
sql: config.local ? q : undefined,
|
|
80
|
+
rows,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default {};
|
|
1
|
+
export default {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default {};
|
|
1
|
+
export default {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default [];
|
|
1
|
+
export default [];
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
|
|
5
5
|
import extraDataGet from '../../../plugins/extra/extraDataGet.js';
|
|
6
6
|
|
|
7
|
-
export default async function tableAPI(req, reply) {
|
|
7
|
+
export default async function tableAPI(req, reply, called) {
|
|
8
8
|
const {
|
|
9
9
|
pg = pgClients.client, params, user = {}, query = {},
|
|
10
10
|
} = req;
|
|
@@ -15,14 +15,14 @@ export default async function tableAPI(req, reply) {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
if (hookData?.message && hookData?.status) {
|
|
18
|
-
return
|
|
18
|
+
return reply.status(hookData?.status).send(hookData?.message);
|
|
19
19
|
}
|
|
20
20
|
const templateName = hookData?.table || tokenData.table || params.table;
|
|
21
21
|
|
|
22
22
|
const loadTable = await getTemplate('table', templateName);
|
|
23
23
|
|
|
24
24
|
if (!loadTable && !pg.pk?.[tokenData.table]) {
|
|
25
|
-
return
|
|
25
|
+
return reply.status(404).send('not found');
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const { table = params.table, /* columns, */ form } = hookData || loadTable || tokenData;
|
|
@@ -30,6 +30,7 @@ export default async function tableAPI(req, reply) {
|
|
|
30
30
|
const id = hookData?.id || tokenData.id || params.id;
|
|
31
31
|
|
|
32
32
|
if (tokenData && !id) return { message: {} };
|
|
33
|
+
|
|
33
34
|
if (!table && !id) {
|
|
34
35
|
return reply.status(400).send('not enough params');
|
|
35
36
|
}
|
|
@@ -38,11 +39,11 @@ export default async function tableAPI(req, reply) {
|
|
|
38
39
|
table, form, id, user,
|
|
39
40
|
}, pg) || {};
|
|
40
41
|
|
|
41
|
-
if (!tokenData && !config?.local && !config.security?.disableToken) {
|
|
42
|
+
if (!tokenData && !config?.local && !config.security?.disableToken && !called) {
|
|
42
43
|
return reply.status(400).send('invalid token');
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
if (!actions.includes('edit') && !config?.local && !tokenData) {
|
|
46
|
+
if (!actions.includes('edit') && !config?.local && !tokenData && !called) {
|
|
46
47
|
return reply.status(403).send('access restricted: actions');
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -97,7 +98,7 @@ export default async function tableAPI(req, reply) {
|
|
|
97
98
|
Object.assign(data, { [key]: extraRows });
|
|
98
99
|
}));
|
|
99
100
|
}
|
|
100
|
-
if (user?.uid && !config.security?.disableToken && actions.includes('edit')) {
|
|
101
|
+
if (user?.uid && !config.security?.disableToken && actions.includes('edit') && !called) {
|
|
101
102
|
data.token = tokenData?.table ? params.table : setToken({
|
|
102
103
|
ids: [JSON.stringify({ id, table, form })],
|
|
103
104
|
uid: user.uid,
|
|
@@ -13,13 +13,13 @@ export default async function formFunction(req) {
|
|
|
13
13
|
const time = Date.now();
|
|
14
14
|
|
|
15
15
|
const { pg, params, user } = req;
|
|
16
|
-
const hookData = await applyHook('preForm', { form: params?.
|
|
16
|
+
const hookData = await applyHook('preForm', { form: params?.name, user });
|
|
17
17
|
|
|
18
18
|
if (hookData?.message && hookData?.status) {
|
|
19
19
|
return { message: hookData?.message, status: hookData?.status };
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const form = await getTemplate('form', hookData?.form || params?.
|
|
22
|
+
const form = await getTemplate('form', hookData?.form || params?.name);
|
|
23
23
|
if (!form) { return { status: 404, message: 'not found' }; }
|
|
24
24
|
|
|
25
25
|
// replace settings
|
|
@@ -34,7 +34,7 @@ export default async function formFunction(req) {
|
|
|
34
34
|
|
|
35
35
|
const res = { time: Date.now() - time, form };
|
|
36
36
|
const res1 = await applyHook('afterForm', {
|
|
37
|
-
form: hookData?.form || params?.
|
|
37
|
+
form: hookData?.form || params?.name,
|
|
38
38
|
payload: res,
|
|
39
39
|
user,
|
|
40
40
|
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {
|
|
2
|
+
config, applyHook, getTemplate, pgClients, getAccess, setToken, getSelectMeta,
|
|
3
|
+
} from '../../../../utils.js';
|
|
4
|
+
|
|
5
|
+
import getEditData from '../../crud/controllers/table.js';
|
|
6
|
+
|
|
7
|
+
const q = `select
|
|
8
|
+
property_key as key,
|
|
9
|
+
property_json as json,
|
|
10
|
+
property_int as int,
|
|
11
|
+
property_text as text
|
|
12
|
+
from admin.properties
|
|
13
|
+
where 1=1`;
|
|
14
|
+
|
|
15
|
+
export default async function getForm({
|
|
16
|
+
pg = pgClients.client, params = {}, user = {}, query = {},
|
|
17
|
+
}, reply) {
|
|
18
|
+
const time = Date.now();
|
|
19
|
+
const { add, edit } = query;
|
|
20
|
+
|
|
21
|
+
if (!user?.uid) {
|
|
22
|
+
return reply.status(401).send('unauthorized');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const hookData = await applyHook('preForm', { table: params.name, user });
|
|
26
|
+
|
|
27
|
+
if (hookData?.message && hookData?.status) {
|
|
28
|
+
return reply.status(hookData?.status).send(hookData?.message);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { form } = await getTemplate('table', hookData?.table || params.name) || {};
|
|
32
|
+
|
|
33
|
+
if (!form) {
|
|
34
|
+
return reply.status(404).send('form not found');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const { actions = [] } = await getAccess({ table: hookData?.table || params.name, form, user }, pg) || {};
|
|
38
|
+
|
|
39
|
+
const loadTemplate = form ? await getTemplate('form', form) : null;
|
|
40
|
+
|
|
41
|
+
if (!loadTemplate) {
|
|
42
|
+
return reply.status(404).send('form template not found');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const { schema = loadTemplate } = loadTemplate;
|
|
46
|
+
|
|
47
|
+
await Promise.all(Object.keys(schema || {}).filter(key => schema[key]?.data).map(async key => {
|
|
48
|
+
const { arr } = await getSelectMeta({ name: schema[key].data, pg }) || {};
|
|
49
|
+
if (arr) {
|
|
50
|
+
schema[key].data = undefined;
|
|
51
|
+
schema[key].options = arr;
|
|
52
|
+
}
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
const res = { schema };
|
|
56
|
+
|
|
57
|
+
if (add && user.uid) {
|
|
58
|
+
if (!actions.includes('add') && !config.local) {
|
|
59
|
+
return reply.status(403).send('access restricted: actions');
|
|
60
|
+
}
|
|
61
|
+
const addTokens = setToken({
|
|
62
|
+
ids: [
|
|
63
|
+
JSON.stringify({
|
|
64
|
+
table: hookData?.table || params.name,
|
|
65
|
+
form,
|
|
66
|
+
})],
|
|
67
|
+
uid: user.uid,
|
|
68
|
+
array: 1,
|
|
69
|
+
});
|
|
70
|
+
Object.assign(res, { token: addTokens[0] });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (edit && user.uid) {
|
|
74
|
+
if (!actions.includes('edit') && !config.local) {
|
|
75
|
+
return reply.status(403).send('access restricted: actions');
|
|
76
|
+
}
|
|
77
|
+
const editTokens = setToken({
|
|
78
|
+
ids: [JSON.stringify({ id: edit, table: hookData?.table || params.name, form })],
|
|
79
|
+
uid: user.uid,
|
|
80
|
+
array: 1,
|
|
81
|
+
});
|
|
82
|
+
const data = await getEditData({
|
|
83
|
+
pg, params: { table: hookData?.table || params.name, id: edit }, user,
|
|
84
|
+
}, reply, true);
|
|
85
|
+
Object.assign(res, { token: editTokens[0], data });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// replace settings
|
|
89
|
+
const arr = JSON.stringify(loadTemplate).match(/{{settings.([^}]*)}}/g);
|
|
90
|
+
|
|
91
|
+
if (arr?.length) {
|
|
92
|
+
const string = JSON.stringify(loadTemplate);
|
|
93
|
+
const { rows = [] } = await pg.query(q);
|
|
94
|
+
const settings = rows.reduce((acc, curr) => Object.assign(acc, { [curr.key]: curr.json || curr.int || curr.text }), {});
|
|
95
|
+
const match = arr.reduce((acc, curr) => Object.assign(acc, { [curr]: settings[curr.replace(/^{{settings./g, '').replace(/}}$/, '')] }), {});
|
|
96
|
+
const result = Object.keys(match).reduce((s, m) => s.replace(m, match[m]), string);
|
|
97
|
+
Object.assign(res, { time: Date.now() - time, schema: JSON.parse(result) });
|
|
98
|
+
return res;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
Object.assign(res, { time: Date.now() - time });
|
|
102
|
+
|
|
103
|
+
const res1 = await applyHook('afterForm', {
|
|
104
|
+
table: hookData?.table || params.name,
|
|
105
|
+
payload: res,
|
|
106
|
+
user,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
return reply.status(200).send(res1 || res);
|
|
110
|
+
}
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getMeta, metaFormat, getTemplates, getTemplate, handlebars,
|
|
3
|
-
} from '../../../../utils.js';
|
|
4
|
-
|
|
5
|
-
function sequence(tables, data, fn) {
|
|
6
|
-
return tables.reduce((promise, table) => promise.then(() => fn({
|
|
7
|
-
...data, tableName: table.replace('.json', ''),
|
|
8
|
-
})), Promise.resolve());
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async function getData({
|
|
12
|
-
pg, tableName, query = {}, maxLimit, res,
|
|
13
|
-
}) {
|
|
14
|
-
const loadTable = await getTemplate('table', tableName);
|
|
15
|
-
|
|
16
|
-
if (!loadTable) { return { message: 'not found', status: 404 }; }
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
table, columns, meta,
|
|
20
|
-
} = loadTable;
|
|
21
|
-
|
|
22
|
-
const { pk } = await getMeta(table);
|
|
23
|
-
|
|
24
|
-
const cols = columns.map((el) => el.name || el).join(',');
|
|
25
|
-
const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
|
|
26
|
-
const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
|
|
27
|
-
|
|
28
|
-
const limit = Math.max(maxLimit - res.rows.length, 0);
|
|
29
|
-
// Math.max(query.offset - res.rows.length,0)
|
|
30
|
-
const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
|
|
31
|
-
|
|
32
|
-
const search1 = meta?.search && query.key ? `(${meta?.search.concat(meta?.title ? `,${meta?.title}` : '').split(',').map(el => `${el} ilike '%${query.key}%'`).join(' or ')})` : 'false';
|
|
33
|
-
|
|
34
|
-
const where = [!pk ? 'false' : 'true', loadTable.query, search1].filter((el) => el);
|
|
35
|
-
const q = `select ${[`"${pk}" as id`, meta?.title ? `${meta.title} as title` : ''].filter((el) => el).join(',')} from ${table} t where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
|
|
36
|
-
if (query.sql) {
|
|
37
|
-
res.sql.push(q);
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const { rows } = await pg.query(q);
|
|
42
|
-
|
|
43
|
-
const total = await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count) || 0;
|
|
44
|
-
|
|
45
|
-
await metaFormat({ rows, table: tableName });
|
|
46
|
-
res.total += +total;
|
|
47
|
-
rows.forEach((row) => {
|
|
48
|
-
const href = meta?.href ? handlebars.compile(meta.href)({ ...row, [pk]: row.id }) : undefined;
|
|
49
|
-
res.rows.push({
|
|
50
|
-
...row, register: tableName, register_title: loadTable.ua, href,
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export default async function search({
|
|
57
|
-
pg, funcs, query = {},
|
|
58
|
-
}) {
|
|
59
|
-
const time = Date.now();
|
|
60
|
-
|
|
61
|
-
const tables = query.table ? [query.table] : await getTemplates('table');
|
|
62
|
-
const res = { rows: [], sql: [], total: 0 };
|
|
63
|
-
|
|
64
|
-
const maxLimit = Math.min(100, query.limit || '16');
|
|
65
|
-
await sequence(tables, {
|
|
66
|
-
pg, funcs, query, maxLimit, res,
|
|
67
|
-
}, getData);
|
|
68
|
-
|
|
69
|
-
if (query.sql) return res.sql.join(';\n');
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
time: Date.now() - time, total: res.total, count: res.rows.length, rows: res.rows,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
getMeta, metaFormat, getTemplates, getTemplate, handlebars,
|
|
3
|
+
} from '../../../../utils.js';
|
|
4
|
+
|
|
5
|
+
function sequence(tables, data, fn) {
|
|
6
|
+
return tables.reduce((promise, table) => promise.then(() => fn({
|
|
7
|
+
...data, tableName: table.replace('.json', ''),
|
|
8
|
+
})), Promise.resolve());
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async function getData({
|
|
12
|
+
pg, tableName, query = {}, maxLimit, res,
|
|
13
|
+
}) {
|
|
14
|
+
const loadTable = await getTemplate('table', tableName);
|
|
15
|
+
|
|
16
|
+
if (!loadTable) { return { message: 'not found', status: 404 }; }
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
table, columns, meta,
|
|
20
|
+
} = loadTable;
|
|
21
|
+
|
|
22
|
+
const { pk } = await getMeta(table);
|
|
23
|
+
|
|
24
|
+
const cols = columns.map((el) => el.name || el).join(',');
|
|
25
|
+
const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
|
|
26
|
+
const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
|
|
27
|
+
|
|
28
|
+
const limit = Math.max(maxLimit - res.rows.length, 0);
|
|
29
|
+
// Math.max(query.offset - res.rows.length,0)
|
|
30
|
+
const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
|
|
31
|
+
|
|
32
|
+
const search1 = meta?.search && query.key ? `(${meta?.search.concat(meta?.title ? `,${meta?.title}` : '').split(',').map(el => `${el} ilike '%${query.key}%'`).join(' or ')})` : 'false';
|
|
33
|
+
|
|
34
|
+
const where = [!pk ? 'false' : 'true', loadTable.query, search1].filter((el) => el);
|
|
35
|
+
const q = `select ${[`"${pk}" as id`, meta?.title ? `${meta.title} as title` : ''].filter((el) => el).join(',')} from ${table} t where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
|
|
36
|
+
if (query.sql) {
|
|
37
|
+
res.sql.push(q);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const { rows } = await pg.query(q);
|
|
42
|
+
|
|
43
|
+
const total = await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count) || 0;
|
|
44
|
+
|
|
45
|
+
await metaFormat({ rows, table: tableName });
|
|
46
|
+
res.total += +total;
|
|
47
|
+
rows.forEach((row) => {
|
|
48
|
+
const href = meta?.href ? handlebars.compile(meta.href)({ ...row, [pk]: row.id }) : undefined;
|
|
49
|
+
res.rows.push({
|
|
50
|
+
...row, register: tableName, register_title: loadTable.ua, href,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default async function search({
|
|
57
|
+
pg, funcs, query = {},
|
|
58
|
+
}) {
|
|
59
|
+
const time = Date.now();
|
|
60
|
+
|
|
61
|
+
const tables = query.table ? [query.table] : await getTemplates('table');
|
|
62
|
+
const res = { rows: [], sql: [], total: 0 };
|
|
63
|
+
|
|
64
|
+
const maxLimit = Math.min(100, query.limit || '16');
|
|
65
|
+
await sequence(tables, {
|
|
66
|
+
pg, funcs, query, maxLimit, res,
|
|
67
|
+
}, getData);
|
|
68
|
+
|
|
69
|
+
if (query.sql) return res.sql.join(';\n');
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
time: Date.now() - time, total: res.total, count: res.rows.length, rows: res.rows,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -108,7 +108,9 @@ export default async function dataAPI(req, reply, called) {
|
|
|
108
108
|
logger.file('crud/warning', { msg: 'invalid filters', template: tokenData?.table || hookData?.table || params.table });
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
const
|
|
111
|
+
const objectId = tokenData?.id || hookData?.id || params.id;
|
|
112
|
+
|
|
113
|
+
const { list: filters = [] } = objectId ? {} : await getFilter({
|
|
112
114
|
pg, table: tokenData?.table || hookData?.table || params.table, user,
|
|
113
115
|
}) || {};
|
|
114
116
|
|
|
@@ -156,7 +158,6 @@ export default async function dataAPI(req, reply, called) {
|
|
|
156
158
|
});
|
|
157
159
|
}
|
|
158
160
|
|
|
159
|
-
const objectId = tokenData?.id || hookData?.id || params.id;
|
|
160
161
|
const isdefault = !objectId ? filters.find(el => el.default) : null;
|
|
161
162
|
|
|
162
163
|
const checkFilter = [query.filter, query.search, query.state, query.custom, isdefault].filter((el) => el).length;
|
|
@@ -353,6 +354,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
353
354
|
});
|
|
354
355
|
const name = el[0].substring(0, el[0].lastIndexOf('.'));
|
|
355
356
|
html[name] = htmlContent;
|
|
357
|
+
panels?.forEach?.(panel => panel?.items?.filter?.(item => item.name === name)?.forEach?.(el1 => Object.assign(el1, { html: htmlContent })));
|
|
356
358
|
}
|
|
357
359
|
catch (err) {
|
|
358
360
|
const name = el[0].substring(0, el[0].lastIndexOf('.'));
|
|
@@ -398,7 +400,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
398
400
|
}
|
|
399
401
|
|
|
400
402
|
// console.log({ add: loadTable.table, form: loadTable.form });
|
|
401
|
-
if (uid && !config.security?.disableToken && actions.includes('add')) {
|
|
403
|
+
if (uid && !config.security?.disableToken && actions.includes('add') && !objectId) {
|
|
402
404
|
const addTokens = setToken({
|
|
403
405
|
ids: [
|
|
404
406
|
JSON.stringify({
|
|
@@ -9,7 +9,8 @@ import tokenInfo from './controllers/tokenInfo.js';
|
|
|
9
9
|
import card from './controllers/card.js';
|
|
10
10
|
import search from './controllers/search.js';
|
|
11
11
|
import filter from './controllers/filter.js';
|
|
12
|
-
import form from './controllers/form.js';
|
|
12
|
+
// import form from './controllers/form.js';
|
|
13
|
+
import form from './controllers/getFormByTable.js';
|
|
13
14
|
|
|
14
15
|
import loadTemplatePath from '../../plugins/table/funcs/loadTemplatePath.js';
|
|
15
16
|
|
|
@@ -48,7 +49,7 @@ async function plugin(app, config = {}) {
|
|
|
48
49
|
|
|
49
50
|
app.get(`${prefix}/templates`, () => loadTemplatePath);
|
|
50
51
|
app.get(`${prefix}/filter/:table`, { config: { policy }, schema: filterSchema }, filter);
|
|
51
|
-
app.get(`${prefix}/form/:
|
|
52
|
+
app.get(`${prefix}/form/:name`, { config: { policy: ['user', 'site'] }, schema: formSchema }, form);
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export default plugin;
|