@opengis/admin 0.2.61 → 0.2.63
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/dist/{add-page-7lwkpclk.js → add-page-B-HdoM-b.js} +1 -1
- package/dist/{admin-interface-CI6dXY6S.js → admin-interface-CB_IDKZ4.js} +354 -350
- package/dist/admin-view-Dho_oQDM.js +650 -0
- package/dist/admin.js +2 -2
- package/dist/admin.umd.cjs +113 -29268
- package/dist/{card-view-Dpi1KUgZ.js → card-view-nRpGn7Eh.js} +1 -1
- package/dist/{edit-page-3A9esUlY.js → edit-page-CL1s0lQK.js} +1 -1
- package/dist/{import-file-BNV8_q-Q.js → import-file-D3jqKElS.js} +3754 -3698
- package/dist/style.css +1 -1
- package/package.json +3 -2
- package/plugin.js +2 -2
- package/server/routes/menu/controllers/getMenu.js +2 -1
- package/server/routes/print/controllers/cardPrint.js +108 -0
- package/server/routes/print/index.mjs +5 -0
- package/server/routes/widget/controllers/widget.del.js +12 -6
- package/server/routes/widget/controllers/widget.get.js +32 -30
- package/server/templates/pt/card-print.pt.hbs +15 -0
- package/dist/admin-view-DLchstfQ.js +0 -58998
@@ -0,0 +1,108 @@
|
|
1
|
+
import path from 'path';
|
2
|
+
import qr from 'qrcode';
|
3
|
+
import { createHash } from 'crypto';
|
4
|
+
|
5
|
+
import {
|
6
|
+
config, getTemplate, pgClients, handlebars, getFolder, getFilterSQL, logger,
|
7
|
+
metaFormat,
|
8
|
+
} from '@opengis/fastify-table/utils.js';
|
9
|
+
import { grpc } from '@opengis/fastify-file/utils.js';
|
10
|
+
|
11
|
+
const { htmlToPdf } = grpc();
|
12
|
+
|
13
|
+
export default async function cardPrint(req, reply) {
|
14
|
+
const { pg = pgClients.client, params = {}, query = {}, user = {} } = req;
|
15
|
+
const { table, id } = params;
|
16
|
+
|
17
|
+
const { template = 'card-print.pt', tab } = query;
|
18
|
+
const format = query.format || (config.debug ? 'html' : 'pdf');
|
19
|
+
|
20
|
+
const hash = createHash('md5').update([table, id, template, tab].join()).digest('hex');
|
21
|
+
|
22
|
+
// const rootDir = getFolder(req, 'local');
|
23
|
+
// const filepath = path.join(rootDir, '/files/tmp/print/', `${hash}.pdf`);
|
24
|
+
|
25
|
+
const headers = {
|
26
|
+
'Content-Disposition': `inline; filename=${hash}.pdf`,
|
27
|
+
'Content-Type': 'application/pdf',
|
28
|
+
};
|
29
|
+
|
30
|
+
if (!user?.uid) {
|
31
|
+
return { message: 'access restricted', status: 401 };
|
32
|
+
}
|
33
|
+
|
34
|
+
if (!table || !id) {
|
35
|
+
return { message: 'not enougn params: table, id', status: 400 };
|
36
|
+
}
|
37
|
+
|
38
|
+
const body = await getTemplate('table', table);
|
39
|
+
|
40
|
+
if (!body?.table) {
|
41
|
+
return { message: 'table nof found', status: 404 };
|
42
|
+
}
|
43
|
+
|
44
|
+
if (!body.key && !pg.pk?.[body.table]) {
|
45
|
+
return { message: 'pkey not found', status: 404 };
|
46
|
+
}
|
47
|
+
|
48
|
+
const where = `${body.query || '1=1'} and ${body.key || pg.pk?.[body.table]}=$1`;
|
49
|
+
|
50
|
+
const { optimizedSQL = `select * from ${body.table} where ${body.query || '1=1'} and ` } = await getFilterSQL({
|
51
|
+
pg,
|
52
|
+
table,
|
53
|
+
query: where,
|
54
|
+
})
|
55
|
+
const { rows = [] } = await pg.query(`select * from (${optimizedSQL})q where ${where}`, [id]);
|
56
|
+
|
57
|
+
const cls = body?.columns?.filter(el => el.data)?.reduce((acc, curr) => Object.assign(acc, { [curr.name]: curr.data }), {});
|
58
|
+
await metaFormat({ rows, cls, sufix: false });
|
59
|
+
|
60
|
+
const data = rows?.[0];
|
61
|
+
if (!data) {
|
62
|
+
return { message: 'data not found', status: 404 };
|
63
|
+
}
|
64
|
+
|
65
|
+
const pt = await getTemplate('pt', template);
|
66
|
+
|
67
|
+
const url = (req.protocol || 'https') + '://' + req.hostname + req.url;
|
68
|
+
const qrCode = `<img src="${await qr.toDataURL(url, { type: 'png', ec_level: 'M', size: 5, margin: 4 })}" alt="qrcode">`;
|
69
|
+
|
70
|
+
const cardTemplates = await getTemplate('card', table);
|
71
|
+
const titles = (cardTemplates?.find(el => el[0] === 'index.yml')?.[1] || {})?.panels
|
72
|
+
?.reduce((acc, curr) => curr.items?.reduce?.((acc1, curr1) => Object.assign(acc, { [curr1.name]: curr1.title })), {});
|
73
|
+
const cardHbsTabs = cardTemplates.filter(el => el[0].endsWith('hbs'));
|
74
|
+
|
75
|
+
const tabs = tab ? cardHbsTabs.filter(el => [tab, `${tab}.hbs`].includes(el[0])) : cardHbsTabs;
|
76
|
+
const tabData = await Promise.all(tabs.map(async (el) => {
|
77
|
+
const html = await handlebars.compile(el[1].replace(/\{\{\{button[^\}]*\}\}\}/g, ''))(data);
|
78
|
+
return { name: el[0], title: titles[el[0].slice(0, el[0].length - 4)], html };
|
79
|
+
}));
|
80
|
+
|
81
|
+
const title = data?.[body.meta.title || ''];
|
82
|
+
|
83
|
+
const columnTitles = body?.columns?.reduce((acc, curr) => Object.assign(acc, { [curr.name]: curr.title || curr.ua }), {});
|
84
|
+
const obj = {
|
85
|
+
title,
|
86
|
+
table_title: body.ua || body.title,
|
87
|
+
rows: tabData,
|
88
|
+
data: Object.keys(data).filter(el => columnTitles[el]).reduce((acc, curr) => Object.assign(acc, { [columnTitles[curr] || curr]: data[curr] }), {}),
|
89
|
+
rawData: data,
|
90
|
+
url,
|
91
|
+
qr: qrCode,
|
92
|
+
};
|
93
|
+
|
94
|
+
const html = await handlebars.compile(pt || 'template not found')(obj);
|
95
|
+
|
96
|
+
if (format == 'html') {
|
97
|
+
return reply.headers({ 'Content-Type': 'text/html; charset=utf-8' }).send(html);
|
98
|
+
}
|
99
|
+
|
100
|
+
const result = await htmlToPdf({ html });
|
101
|
+
const buffer = Buffer.from(result.result, 'base64');
|
102
|
+
|
103
|
+
// await mkdir(path.dirname(filepath), { recursive: true });
|
104
|
+
// await writeFile(filepath, buffer);
|
105
|
+
|
106
|
+
logger.file('printPdf', { table, id, format, uid: user?.uid });
|
107
|
+
return reply.headers(headers).send(buffer);
|
108
|
+
}
|
@@ -17,8 +17,10 @@
|
|
17
17
|
* @returns {String|Object} message Повідомлення про успішне виконання або об'єкт з параметрами
|
18
18
|
*/
|
19
19
|
|
20
|
+
import { pgClients, logChanges } from "@opengis/fastify-table/utils.js";
|
21
|
+
|
20
22
|
export default async function widgetDel({
|
21
|
-
pg, params = {}, session = {},
|
23
|
+
pg = pgClients.client, params = {}, session = {},
|
22
24
|
}) {
|
23
25
|
const { user = {} } = session.passport || {};
|
24
26
|
if (!user.uid) return { error: 'access restricted', status: 403 };
|
@@ -29,13 +31,17 @@ export default async function widgetDel({
|
|
29
31
|
const sqls = {
|
30
32
|
comment: 'delete from crm.communications where entity_id=$1 and uid=$2 and communication_id=$3',
|
31
33
|
checklist: 'delete from crm.checklists where entity_id=$1 and uid=$2 and checklist_id=$3',
|
32
|
-
file: 'update crm.files set file_status=3 where entity_id=$1 and uid=$2 and file_id=$3',
|
33
|
-
gallery: 'update crm.files set file_status=3 where entity_id=$1 and uid=$2 and file_id=$3',
|
34
|
+
file: 'update crm.files set file_status=3 where entity_id=$1 and uid=$2 and file_id=$3 returning uploaded_name',
|
35
|
+
gallery: 'update crm.files set file_status=3 where entity_id=$1 and uid=$2 and file_id=$3 returning uploaded_name',
|
34
36
|
};
|
35
37
|
const sql = sqls[type];
|
36
38
|
if (!sql) return { error: 'type not valid', status: 401 };
|
37
|
-
|
38
|
-
await pg.query(sql, [objectid, user.uid, id]);
|
39
|
+
|
40
|
+
const { rows = [] } = await pg.query(sql, [objectid, user.uid, id]);
|
41
|
+
const table = { comment: 'crm.communications', checklist: 'crm.checklists', file: 'crm.files', gallery: 'crm.files' }[type];
|
42
|
+
await logChanges({
|
43
|
+
pg, table, id, data: rows[0], uid: user?.uid, type: 'DELETE',
|
44
|
+
});
|
39
45
|
return { data: { id }, user: { uid: user.uid, name: user.user_name } };
|
40
|
-
|
46
|
+
|
41
47
|
}
|
@@ -1,6 +1,4 @@
|
|
1
|
-
import { getMeta, getToken } from '@opengis/fastify-table/utils.js';
|
2
|
-
|
3
|
-
import historyFormat from './utils/historyFormat.js';
|
1
|
+
import { getMeta, getToken, pgClients } from '@opengis/fastify-table/utils.js';
|
4
2
|
|
5
3
|
const galleryExtList = ['png', 'svg', 'jpg', 'jpeg', 'gif', 'mp4', 'mov', 'avi'];
|
6
4
|
|
@@ -10,10 +8,8 @@ const galleryExtList = ['png', 'svg', 'jpg', 'jpeg', 'gif', 'mp4', 'mov', 'avi']
|
|
10
8
|
*/
|
11
9
|
|
12
10
|
export default async function widgetGet({
|
13
|
-
pg,
|
11
|
+
pg = pgClients.client, user = {}, params = {}, query = {},
|
14
12
|
}) {
|
15
|
-
const { user = {} } = session.passport || {};
|
16
|
-
|
17
13
|
const param = user?.uid ? await getToken({
|
18
14
|
token: params.objectid, mode: 'w', uid: user.uid,
|
19
15
|
}) : null;
|
@@ -29,15 +25,22 @@ export default async function widgetGet({
|
|
29
25
|
from crm.communications c left join admin.users u on u.uid=c.uid where entity_id=$1 order by cdate desc`
|
30
26
|
: 'select communication_id, entity_id, body, subject, cdate, uid from crm.communications where entity_id=$1 order by cdate desc',
|
31
27
|
|
32
|
-
history: `SELECT
|
28
|
+
history: `SELECT change_id, entity_id, entity_type, change_type, change_date, a.change_user_id, a.uid, a.cdate, b.json_agg as changes,
|
29
|
+
(coalesce(coalesce(u.sur_name,'')||coalesce(' '||u.user_name,'') ||coalesce(' '||u.father_name,''),u.login)) as username
|
30
|
+
FROM log.table_changes a
|
31
|
+
left join admin.users u on a.change_user_id = u.uid
|
33
32
|
left join lateral(
|
34
|
-
select
|
33
|
+
select json_agg(row_to_json(q)) from (
|
34
|
+
select change_data_id, entity_key, value_new, value_old from log.table_changes_data
|
35
|
+
where change_id=a.change_id
|
36
|
+
)q
|
35
37
|
)b on 1=1
|
36
38
|
where (entity_id=$1 or entity_id in (
|
37
39
|
select communication_id as comments from crm.communications where entity_id=$1
|
38
40
|
union all select file_id from crm.files where entity_id=$1
|
39
41
|
union all select checklist_id from crm.checklists where entity_id=$1)
|
40
|
-
)
|
42
|
+
) order by cdate desc
|
43
|
+
limit 100`,
|
41
44
|
|
42
45
|
checklist: pg.pk['admin.users']
|
43
46
|
? `SELECT checklist_id, entity_id, subject, is_done, done_date, c.uid, c.cdate, coalesce(user_name,' ')||' '||coalesce(sur_name,'') as username,
|
@@ -66,31 +69,30 @@ export default async function widgetGet({
|
|
66
69
|
}
|
67
70
|
|
68
71
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
72
|
+
/* data */
|
73
|
+
const time = [Date.now()];
|
74
|
+
const { rows } = await pg.query(sql, [objectid, params.type === 'gallery' ? galleryExtList : null].filter((el) => el));
|
75
|
+
time.push(Date.now());
|
73
76
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
+
/* Object info */
|
78
|
+
const { tableName } = pg.pk['log.table_changes'] ? await pg.one('select entity_type as "tableName" from log.table_changes where entity_id=$1 limit 1', [objectid]) : {};
|
79
|
+
const { pk } = await getMeta({ table: tableName });
|
77
80
|
|
78
|
-
|
81
|
+
const q = tableName && pg.pk['admin.users'] ? `select coalesce(b.user_name,'')||coalesce(' '||b.sur_name,'') as author, a.cdate, a.editor_date from ${tableName} a
|
79
82
|
left join admin.users b on a.uid=b.uid where a.${pk}=$1 limit 1` : undefined;
|
80
|
-
|
81
|
-
|
82
|
-
if (query.debug && user?.user_type === 'admin') {
|
83
|
-
return {
|
84
|
-
sql, type: params.type, q, id: objectid, data,
|
85
|
-
};
|
86
|
-
}
|
83
|
+
const data = pk && q ? await pg.one(q, [objectid]) : {};
|
87
84
|
|
88
|
-
|
85
|
+
if (query.debug && user?.user_type === 'admin') {
|
89
86
|
return {
|
90
|
-
|
91
|
-
rows: params.type === 'history' ? await historyFormat(rows, tableName, pg) : rows,
|
92
|
-
user: { uid: user?.uid, name: user?.user_name },
|
93
|
-
data: { author: data?.author, cdate: data?.cdate, edate: data?.editor_date },
|
94
|
-
objectid: params.objectid,
|
87
|
+
sql, type: params.type, q, id: objectid, data,
|
95
88
|
};
|
89
|
+
}
|
90
|
+
|
91
|
+
return {
|
92
|
+
time: { data: time[1] - time[0] },
|
93
|
+
rows,
|
94
|
+
user: { uid: user?.uid, name: user?.user_name },
|
95
|
+
data: { author: data?.author, cdate: data?.cdate, edate: data?.editor_date },
|
96
|
+
objectid: params.objectid,
|
97
|
+
};
|
96
98
|
}
|