@opengis/admin 0.2.121 → 0.2.123

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. package/dist/{add-page-D9BweG1f.js → add-page-CNaov3n_.js} +1 -1
  2. package/dist/{admin-interface-Bq8kf59d.js → admin-interface-Bfl5z6ck.js} +582 -732
  3. package/dist/{admin-view-pmWjnncn.js → admin-view-DYePX_Un.js} +1 -1
  4. package/dist/admin.js +2 -2
  5. package/dist/admin.umd.cjs +50 -50
  6. package/dist/{card-view-DNKItKZ_.js → card-view-OkM8SWMi.js} +1 -1
  7. package/dist/{edit-page-DmanLFQC.js → edit-page-BXf-hnHj.js} +1 -1
  8. package/dist/{import-file-B3hz_TTe.js → import-file-Cds3w-U5.js} +15024 -14822
  9. package/dist/{profile-page-CnXrMOV_.js → profile-page-B7ofAYKr.js} +1 -1
  10. package/dist/style.css +1 -1
  11. package/module/settings/card/admin.roles.table/index.yml +3 -0
  12. package/module/settings/card/admin.routes.table/index.yml +15 -11
  13. package/module/settings/card/admin.users.table/index.yml +3 -0
  14. package/module/settings/menu.json +21 -13
  15. package/{server/templates → module/settings}/setting/test.json +5 -5
  16. package/package.json +4 -4
  17. package/server/plugins/hook.js +13 -1
  18. package/server/routes/data/controllers/tableFilter.js +8 -1
  19. package/server/routes/menu/controllers/getMenu.js +9 -3
  20. package/server/routes/print/controllers/printTemplate.add.js +37 -0
  21. package/server/routes/print/controllers/printTemplate.delete.js +29 -0
  22. package/server/routes/print/controllers/printTemplate.edit.js +42 -0
  23. package/server/routes/print/controllers/printTemplate.js +24 -79
  24. package/server/routes/print/controllers/printTemplateList.js +20 -0
  25. package/server/routes/print/controllers/printTemplatePreview.js +81 -0
  26. package/server/routes/print/index.mjs +14 -2
  27. package/server/routes/properties/controllers/admin.properties.get.js +4 -3
  28. package/server/routes/properties/controllers/admin.properties.post.js +2 -2
  29. package/server/routes/properties/index.mjs +1 -1
  30. package/server/routes/report/controllers/data.js +76 -0
  31. package/server/routes/report/controllers/list.js +18 -0
  32. package/server/routes/report/index.mjs +7 -0
  33. package/server/routes/report/utils/formatValue.js +179 -0
  34. package/server/routes/report/utils/getFilterQuery.js +67 -0
@@ -1,5 +1,8 @@
1
1
  component: default
2
2
  isHeaderEditButton: false
3
+ meta: {
4
+ title: full_name
5
+ }
3
6
 
4
7
  panels:
5
8
  - type: vertical-tabs # tabs
@@ -39,26 +39,34 @@
39
39
  "icon": "IconSettingsCog",
40
40
  "menu": [
41
41
  {
42
- "path": "admin.user-cls",
43
- "ua": "Довідники ",
44
- "component": "user-cls-page"
45
- },
46
- {
47
- "path": "admin.properties",
48
- "table": "admin.properties.table",
42
+ "path": "admin.settings",
43
+ "component": "admin-properties-page" ,
49
44
  "ua": "Налаштування",
50
45
  "en": "Settings"
51
46
  },
52
47
  {
53
- "path": "admin.table_settings",
54
- "ua": "Налаштування таблиць",
48
+ "path": "admin.templates",
49
+ "ua": "Друк ",
50
+ "component": "template-print-page"
51
+ },
52
+ {
53
+ "path": "admin.interfaces",
54
+ "ua": "Таблиці",
55
55
  "component": "table-settings-page"
56
56
  },
57
57
  {
58
- "path": "admin.admin_properties",
59
- "ua": "Налаштування адміна",
60
- "component": "admin-properties-page"
61
- }
58
+ "path": "admin.user-cls",
59
+ "ua": "Довідники ",
60
+ "component": "user-cls-page"
61
+ },
62
+ {
63
+ "path": "admin.reports",
64
+ "ua": "Звіти  ",
65
+ "component": "reports-page"
66
+ },
67
+ { "path": "admin.admin_properties",
68
+ "ua": "Налаштування адміна",
69
+ "table": "admin.properties.table"}
62
70
  ]
63
71
  }
64
72
  ]
@@ -1,6 +1,6 @@
1
- {
2
- "admin.title": {
3
- "type": "Text",
4
- "ua": "Назва"
5
- }
1
+ {
2
+ "admin.title": {
3
+ "type": "Text",
4
+ "ua": "Назва"
5
+ }
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/admin",
3
- "version": "0.2.121",
3
+ "version": "0.2.123",
4
4
  "description": "This project Softpro Admin",
5
5
  "main": "dist/admin.js",
6
6
  "type": "module",
@@ -48,9 +48,9 @@
48
48
  "@fullcalendar/vue3": "^6.1.15",
49
49
  "@opengis/fastify-auth": "^1.0.70",
50
50
  "@opengis/fastify-file": "^1.0.42",
51
- "@opengis/fastify-table": "^1.2.8",
51
+ "@opengis/fastify-table": "^1.2.11",
52
52
  "@opengis/v3-core": "^0.3.45",
53
- "@opengis/v3-filter": "^0.0.68",
53
+ "@opengis/v3-filter": "^0.0.71",
54
54
  "@tabler/icons-vue": "^3.28.1",
55
55
  "@tiptap/core": "^2.8.0",
56
56
  "@tiptap/extension-color": "^2.8.0",
@@ -94,6 +94,6 @@
94
94
  "vitepress": "^1.1.3",
95
95
  "vitepress-plugin-mermaid": "^2.0.16",
96
96
  "vitepress-plugin-tabs": "^0.5.0",
97
- "vitepress-sidebar": "^1.22.0"
97
+ "vitepress-sidebar": "1.30.2"
98
98
  }
99
99
  }
@@ -83,10 +83,22 @@ export default async function plugin(fastify) {
83
83
  const printTemplateList = getTemplatePath('print');
84
84
  printTemplateList.filter(el => el[2] === 'json').map((el) => {
85
85
  const settings = JSON.parse(readFileSync(el[1]) || '{}');
86
+ const htmlPath = printTemplateList.find(item => item[0] === el[0] && ['hbs', 'html'].includes(item[2]))?.[1];
87
+ const html = htmlPath ? readFileSync(htmlPath, 'utf-8') : null;
88
+ Object.assign(settings, { html });
86
89
  printTemplates[el[0]] = settings;
87
90
  });
88
91
  if (client?.pk?.['admin.templates']) {
89
- console.log('insert into admin.templates', printTemplateList); // test!
92
+ const arr = Object.keys(printTemplates || {}).map(el => ({ name: el, ...printTemplates?.[el] || {} }));
93
+
94
+ const { rowsCount = 0 } = await pgClients.client.query(`delete from admin.templates where not (name=any($1::text[])) and type = 'demo'`, [arr.map(el => el.name)]);
95
+ console.log('delete deprecated templates', 'ok', rowsCount);
96
+ const { rowsCount: empty = 0 } = await pgClients.client.query('delete from admin.templates where body is null');
97
+ console.log('delete empty templates', 'ok', empty);
98
+
99
+ const q = arr.map(el => `insert into admin.templates(name, route_id, title, type, body) values ('${el.name.replace(/'/g, "''")}', '${el.route.replace(/'/g, "''")}', '${el.title.replace(/'/g, "''")}', 'demo', '${(el.html || '').replace(/'/g, "''")}') on conflict(name, type) do update set route_id=excluded.route_id, title=excluded.title`).join(';');
100
+ const res = await pgClients.client.query(q);
101
+ console.log('insert print templates', 'ok', (Array.isArray(res) ? res : [res]).length);
90
102
  }
91
103
  });
92
104
 
@@ -1,4 +1,4 @@
1
- import { getTemplate, getMeta, handlebarsSync } from "@opengis/fastify-table/utils.js";
1
+ import { getTemplate, getMeta, handlebarsSync, autoIndex, logger } from "@opengis/fastify-table/utils.js";
2
2
 
3
3
  export default async function tableFilter(req) {
4
4
  const time = Date.now();
@@ -31,6 +31,13 @@ export default async function tableFilter(req) {
31
31
  const { rows: properties = [] } = await pg.query(`select column_id, name, title, format, data from admin.custom_column where entity=$1 and uid=$2 and filter`, [params.name, uid]);
32
32
  properties.forEach((row) => filters.push({ id: row.name, name: row.name, ua: row.title, type: row.format, data: row.data }));
33
33
 
34
+
35
+ autoIndex({ table: loadTable.table, columns: filters.filter((el) => columns?.find?.((item) => item?.name === el.name)) })
36
+ .catch(err => {
37
+ logger.file('autoindex/error', { name: params?.name, error: err.toString(), stack: err.stack });
38
+ });
39
+
40
+
34
41
  await Promise.all(filters.filter((el) => el.data).map(async (el) => {
35
42
 
36
43
  const cls = await getTemplate(['cls', 'select'], el.data);
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { join } from 'path';
3
- import { userTemplateDir, config, getAccess, pgClients } from '@opengis/fastify-table/utils.js';
3
+ import { userTemplateDir, config, pgClients } from '@opengis/fastify-table/utils.js';
4
4
 
5
5
  import { existsSync, readdirSync, readFileSync } from 'fs';
6
6
  const menuCache = [];
@@ -38,8 +38,14 @@ export default async function adminMenu({ user = {}, session, pg = pgClients.cli
38
38
 
39
39
  if (session && user?.uid && !config.local && !config.admin && !user.user_type?.includes?.('admin') && !user.type?.includes?.('admin') && pg.pk['admin.role_access']) {
40
40
  const { type, gl = [], routes = [] } = await pg.query(`select user_type as type, b.gl,routes from admin.users a
41
- left join lateral ( select array_agg(role_id) as gl from admin.user_roles where user_uid=a.uid)b on 1=1
42
- left join lateral ( select array_agg(route_id) as routes from admin.role_access where role_id=any(b.gl))r on 1=1
41
+ left join lateral (
42
+ select array_agg(role_id) as gl from admin.user_roles
43
+ where user_uid=a.uid
44
+ and role_id in ( select role_id from admin.roles where enabled)
45
+ )b on 1=1
46
+ left join lateral (
47
+ select array_agg(route_id) as routes from admin.role_access where role_id=any(b.gl)
48
+ )r on 1=1
43
49
  where uid=$1`, [user.uid]).then(el => el.rows[0] || {});
44
50
  /* const { interfaces = [] } = await pg.query(`select array_agg(route_id) as interfaces from admin.role_access
45
51
  where user_uid=$1 or role_id=any($2::text[])`, [user.uid, gl]).then((res) => res.rows?.[0] || {}); */
@@ -0,0 +1,37 @@
1
+ import { pgClients, dataInsert } from '@opengis/fastify-table/utils.js';
2
+
3
+ export default async function printTemplateAdd({
4
+ pg = pgClients.client, body = {}, user = {},
5
+ }) {
6
+ if (!user?.uid) {
7
+ return { message: 'access restricted', status: 403 };
8
+ }
9
+
10
+ const { name, title, route, html } = body;
11
+
12
+ if (!name) {
13
+ return { message: 'not enough body params: name', status: 400 };
14
+ }
15
+
16
+ if (!html) {
17
+ return { message: 'not enough body params: html', status: 400 };
18
+ }
19
+
20
+ const id = await pg.query(`select template_id as id from admin.templates where $1 in (template_id, name)`, [name])
21
+ .then(el => el.rows?.[0]?.id);
22
+
23
+ if (id) {
24
+ return { message: 'access restricted: template exists', status: 403 };
25
+ }
26
+
27
+ const res = await dataInsert({
28
+ pg,
29
+ table: 'admin.templates',
30
+ data: { name, title, route_id: route, body: html, type: 'user' },
31
+ uid: user?.uid,
32
+ })
33
+
34
+ const data = res.rows?.[0];
35
+
36
+ return { id: data?.template_id, data };
37
+ }
@@ -0,0 +1,29 @@
1
+ import { pgClients, dataDelete } from '@opengis/fastify-table/utils.js';
2
+
3
+ export default async function printTemplateDelete({
4
+ pg = pgClients.client, params = {}, user = {},
5
+ }) {
6
+ if (!user?.uid) {
7
+ return { message: 'access restricted', status: 403 };
8
+ }
9
+
10
+ const { id, type } = await pg.query(`select template_id as id, type from admin.templates where enabled and $1 in (template_id, name)`, [params.id])
11
+ .then(el => el.rows?.[0] || {});
12
+
13
+ if (!id) {
14
+ return { message: 'template not found', status: 404 };
15
+ }
16
+
17
+ if (type === 'demo') {
18
+ return { message: 'access restricted: demo', status: 403 };
19
+ }
20
+
21
+ const res = await dataDelete({
22
+ pg,
23
+ table: 'admin.templates',
24
+ id,
25
+ uid: user?.uid,
26
+ });
27
+
28
+ return { id: res?.template_id, data: res };
29
+ }
@@ -0,0 +1,42 @@
1
+ import { pgClients, dataInsert } from '@opengis/fastify-table/utils.js';
2
+
3
+ export default async function printTemplateEdit({
4
+ pg = pgClients.client, params = {}, body = {}, user = {},
5
+ }) {
6
+ if (!user?.uid) {
7
+ return { message: 'access restricted', status: 403 };
8
+ }
9
+
10
+ if (!params?.id) {
11
+ return { message: 'not enough params: id', status: 400 };
12
+ }
13
+
14
+ const { html, route, title } = body;
15
+
16
+ if (!html) {
17
+ return { message: 'not enough body params: html', status: 400 };
18
+ }
19
+
20
+ const { id, name } = await pg.query(`select template_id as id, name from admin.templates where $1 in (template_id, name)`, [params.id])
21
+ .then(el => el.rows?.[0] || {});
22
+
23
+ if (!id) {
24
+ return { message: 'template not found', status: 404 };
25
+ }
26
+
27
+ await pg.query(`delete from admin.templates where $1 in (template_id, name)`, [id]);
28
+
29
+ const data = { name, body: html, type: 'user' };
30
+ if (title) Object.assign(data, { title });
31
+ if (route) Object.assign(data, { route_id: route });
32
+
33
+ const res = await dataInsert({
34
+ pg,
35
+ table: 'admin.templates',
36
+ id,
37
+ data,
38
+ uid: user?.uid,
39
+ });
40
+
41
+ return { id: res.rows?.[0]?.template_id, data: res.rows?.[0] };
42
+ }
@@ -3,8 +3,6 @@ import { createHash } from 'node:crypto';
3
3
  import { config, getFilterSQL, getTemplate, handlebars, pgClients } from '@opengis/fastify-table/utils.js';
4
4
  import { grpc } from '@opengis/fastify-file/utils.js';
5
5
 
6
- import printTemplates from './printTemplates.js';
7
-
8
6
  const { htmlToPdf } = grpc();
9
7
 
10
8
  export default async function printTemplate(req, reply) {
@@ -12,110 +10,57 @@ export default async function printTemplate(req, reply) {
12
10
  pg = pgClients.client,
13
11
  params = {},
14
12
  query = {},
15
- user = {},
16
13
  } = req;
17
14
 
18
15
  if (!params?.name) {
19
16
  return { message: 'not enough params: name', status: 400 };
20
17
  }
21
18
 
22
- const printBody = await getTemplate('print', params.name);
23
-
24
- /* -- params.name === interface -- */
25
- if (!printBody?.route) {
26
- const where = user?.user_type?.includes('admin')
27
- ? '1=1'
28
- : `coalesce(b.user_uid, d.user_uid)='${user?.uid?.replace(/'/g, "''")}'::text`;
29
-
30
- const { route_id: routeId, alias } = await pg.query(`select a.route_id, alias
31
- from admin.routes a
32
- left join admin.role_access b on
33
- a.route_id=b.route_id
34
- left join admin.roles c on
35
- b.role_id=c.role_id
36
- and c.enabled
37
- left join admin.user_roles d on
38
- c.role_id=d.role_id
39
- and ( case when
40
- d.expiration is not null
41
- then d.expiration > CURRENT_DATE
42
- else 1=1
43
- end )
44
- where $1 in (a.route_id, a.alias, a.table_name) and ${where}`, [params.name])
45
- .then(el => el.rows?.[0] || {});
46
-
47
- if (!routeId || !alias) {
48
- return { message: `access restricted: route (${params.name}/${routeId})`, status: 403 };
49
- }
50
-
51
- const rows = Object.keys(printTemplates)
52
- .filter(key => printTemplates[key]?.route === routeId)
53
- .map(key => ({ key, title: printTemplates[key]?.title }));
54
-
55
- return { rows };
19
+ if (!params?.id) {
20
+ return { message: 'not enough params: id', status: 400 };
56
21
  }
57
22
 
58
- if (!query.preview && !query?.demo && !params?.id) {
59
- return { message: 'not enough params: id', status: 400 };
23
+ const { id, route, body = '' } = await pg.query(`select template_id as id, body, route_id as route from admin.templates where $1 in (template_id,name)`, [params.name])
24
+ .then(el => el.rows?.[0] || {});
25
+
26
+ if (!id) {
27
+ return reply.status(404).send('template not found');
60
28
  }
61
29
 
62
30
  /* -- params.name === document template -- */
63
31
  const format = query.format || (config.debug ? 'html' : 'pdf');
64
32
 
65
33
  const hash = createHash('md5')
66
- .update([query?.preview, query?.demo, params?.name, params?.id].join())
34
+ .update([params?.name, params?.id].join())
67
35
  .digest('hex');
68
36
 
69
37
  const headers = format === 'pdf'
70
38
  ? { 'Content-Disposition': `inline; filename=${hash}.pdf`, 'Content-Type': 'application/pdf' }
71
39
  : { 'Content-Type': 'text/html; charset=utf-8' };
72
40
 
73
- const pt = printBody?.hbs || printBody?.html;
74
-
75
- if (query?.preview) {
76
- const matches = pt.match(/{{(?!\!)([^}]*)}}/g);
77
- const preview = `<style> #toggle { background: yellow; } </style>`
78
- + matches.reduce((acc, curr) => acc.replace(curr, curr.replace(/{{(?!\!)([^}]*)}}/g, `<div id="toggle">${curr.replace(/{/g, '%7B').replace(/}/g, '%7D')}</div>`)), pt);
79
-
80
- const html = await handlebars.compile(preview)({});
41
+ const table = await pg.query(`select alias from admin.routes where route_id=$1`, [route])
42
+ .then(el => el.rows?.[0]?.alias);
81
43
 
82
- if (format == 'html') {
83
- return reply.headers(headers).send(html.replace(/%7B/g, '{').replace(/%7D/g, '}'));
84
- }
85
-
86
- const result = await htmlToPdf({ html: html.replace(/%7B/g, '{').replace(/%7D/g, '}') });
87
- const buffer = Buffer.from(result.result, 'base64');
88
- return reply.headers(headers).send(buffer);
44
+ if (!table) {
45
+ return { message: 'route table not found', status: 404 };
89
46
  }
90
47
 
91
- if (query?.demo || params?.id) {
92
- const table = await pg.query(`select alias from admin.routes where route_id=$1`, [printBody.route])
93
- .then(el => el.rows?.[0]?.alias);
94
-
95
- if (!table) {
96
- return { message: 'route table not found', status: 404 };
97
- }
98
-
99
- const loadTable = await getTemplate('table', table);
100
- const { optimizedSQL } = await getFilterSQL({ table, pg });
48
+ const loadTable = await getTemplate('table', table);
49
+ const { optimizedSQL } = await getFilterSQL({ table, pg });
101
50
 
102
- const where = query.demo
103
- ? ' 1=1 limit 1'
104
- : `${loadTable?.key || pg.pk?.[loadTable?.table || table]}=$1`;
51
+ const where = `${loadTable?.key || pg.pk?.[loadTable?.table || table]}=$1`;
105
52
 
106
- const q = `select * from (${optimizedSQL})q where ${loadTable?.query || '1=1'} and ${where}`;
53
+ const q = `select * from (${optimizedSQL})q where ${loadTable?.query || '1=1'} and ${where}`;
107
54
 
108
- const obj = await pg.query(q, [params.id].filter(el => el && !query.demo))
109
- .then(el => el.rows?.[0] || {});
55
+ const obj = await pg.query(q, [params.id]).then(el => el.rows?.[0] || {});
110
56
 
111
- const html = await handlebars.compile(pt)(obj);
57
+ const html = await handlebars.compile(body)(obj);
112
58
 
113
- if (format == 'html') {
114
- return reply.headers(headers).send(html);
115
- }
116
-
117
- const result = await htmlToPdf({ html });
118
- const buffer = Buffer.from(result.result, 'base64');
119
- return reply.headers(headers).send(buffer);
59
+ if (format == 'html') {
60
+ return reply.headers(headers).send(html);
120
61
  }
62
+
63
+ const result = await htmlToPdf({ html });
64
+ const buffer = Buffer.from(result.result, 'base64');
65
+ return reply.headers(headers).send(buffer);
121
66
  }
@@ -0,0 +1,20 @@
1
+ import { pgClients } from "@opengis/fastify-table/utils.js";
2
+
3
+ const maxLimit = 100;
4
+
5
+ export default async function printTemplateList({
6
+ pg = pgClients.client, query = {},
7
+ }) {
8
+ const { page = 1 } = query;
9
+
10
+ const limit = Math.min(maxLimit, +(query.limit || 20));
11
+
12
+ const offset = page && page > 0 ? (page - 1) * limit : '0';
13
+
14
+ const q = `select template_id as id, name, title, route_id as route, type from admin.templates
15
+ where enabled limit ${limit} offset ${offset}`;
16
+
17
+ const { rows = [] } = pg.pk?.['admin.templates'] ? await pg.query(q) : {};
18
+
19
+ return { page, limit, rows };
20
+ }
@@ -0,0 +1,81 @@
1
+ import { createHash } from 'node:crypto';
2
+
3
+ import { config, getFilterSQL, getTemplate, handlebars, pgClients } from '@opengis/fastify-table/utils.js';
4
+ import { grpc } from '@opengis/fastify-file/utils.js';
5
+
6
+ const { htmlToPdf } = grpc();
7
+
8
+ export default async function printTemplate(req, reply) {
9
+ const {
10
+ pg = pgClients.client,
11
+ params = {},
12
+ query = {},
13
+ } = req;
14
+
15
+ if (!params?.name) {
16
+ return reply.status(404).send('not enough params: name');
17
+ }
18
+
19
+ const { id, name, title, body = '', route } = await pg.query(`select template_id as id, name, title, body, route_id as route from admin.templates where $1 in (template_id,name)`, [params.name])
20
+ .then(el => el.rows?.[0] || {});
21
+
22
+ if (!id) {
23
+ return reply.status(404).send('template not found');
24
+ }
25
+
26
+ /* -- params.name === document template -- */
27
+ const format = query.format || (config.debug ? 'html' : 'pdf');
28
+
29
+ const hash = createHash('md5')
30
+ .update([query?.preview, query?.demo, params?.name].join())
31
+ .digest('hex');
32
+
33
+ const headers = format === 'pdf'
34
+ ? { 'Content-Disposition': `inline; filename=${hash}.pdf`, 'Content-Type': 'application/pdf' }
35
+ : { 'Content-Type': 'text/html; charset=utf-8' };
36
+
37
+ if (query?.preview) {
38
+ const matches = body?.match?.(/{{(?!\!)([^}]*)}}/g) || [];
39
+ const preview = `<style> #toggle { background: yellow; } </style>`
40
+ + matches.reduce((acc, curr) => acc.replace(curr, curr.replace(/{{(?!\!)([^}]*)}}/g, `<div id="toggle">${curr.replace(/{/g, '%7B').replace(/}/g, '%7D')}</div>`)), body);
41
+
42
+ const html = await handlebars.compile(preview)({});
43
+
44
+ if (format == 'html') {
45
+ return reply.headers(headers).send(html.replace(/%7B/g, '{').replace(/%7D/g, '}'));
46
+ }
47
+
48
+ const result = await htmlToPdf({ html: html.replace(/%7B/g, '{').replace(/%7D/g, '}') });
49
+ const buffer = Buffer.from(result.result, 'base64');
50
+ return reply.headers(headers).send(buffer);
51
+ }
52
+
53
+ if (query?.demo) {
54
+ const table = await pg.query(`select alias from admin.routes where route_id=$1`, [route])
55
+ .then(el => el.rows?.[0]?.alias);
56
+
57
+ if (!table) {
58
+ return reply.status(404).send('route table not found');
59
+ }
60
+
61
+ const loadTable = await getTemplate('table', table);
62
+ const { optimizedSQL } = await getFilterSQL({ table, pg });
63
+
64
+ const q = `select * from (${optimizedSQL})q where ${loadTable?.query || '1=1'} limit 1`;
65
+
66
+ const obj = await pg.query(q).then(el => el.rows?.[0] || {});
67
+
68
+ const html = await handlebars.compile(body)(obj);
69
+
70
+ if (format == 'html') {
71
+ return reply.headers(headers).send(html);
72
+ }
73
+
74
+ const result = await htmlToPdf({ html });
75
+ const buffer = Buffer.from(result.result, 'base64');
76
+ return reply.headers(headers).send(buffer);
77
+ }
78
+
79
+ // for body edit
80
+ return { name, title, html: body, route };
81
+ }
@@ -1,7 +1,19 @@
1
1
  import cardPrint from './controllers/cardPrint.js';
2
+ import printTemplateAdd from './controllers/printTemplate.add.js';
3
+ import printTemplateEdit from './controllers/printTemplate.edit.js';
4
+ import printTemplateDelete from './controllers/printTemplate.delete.js';
2
5
  import printTemplate from './controllers/printTemplate.js';
6
+ import printTemplatePreview from './controllers/printTemplatePreview.js';
7
+ import printTemplateList from './controllers/printTemplateList.js';
8
+
9
+ const policy = ['user'];
3
10
 
4
11
  export default async function route(app) {
5
- app.get(`/card-print/:table/:id`, cardPrint);
6
- app.get('/print-template/:name/:id?', printTemplate);
12
+ app.get(`/card-print/:table/:id`, { config: { policy } }, cardPrint);
13
+ app.get('/print-template/:name/:id', { config: { policy } }, printTemplate);
14
+ app.get('/print-template/:name', { config: { policy } }, printTemplatePreview);
15
+ app.get('/print-template', { config: { policy } }, printTemplateList);
16
+ app.post('/print-template', { config: { policy } }, printTemplateAdd);
17
+ app.put('/print-template/:id', { config: { policy } }, printTemplateEdit);
18
+ app.delete('/print-template/:id', { config: { policy } }, printTemplateDelete);
7
19
  }
@@ -9,16 +9,17 @@ const redis = getRedis();
9
9
  export default async function getSettingsApp({
10
10
  pg = pgClients.client, params = {}, query = {},
11
11
  }) {
12
+ const time = Date.now();
12
13
  if (!pg.pk?.[table]) {
13
14
  return { message: 'table not found', status: 404 };
14
15
  }
15
16
 
16
- const keyCache = `${pg.options?.database}:settings:${params?.key || 'all'}:${query?.json ? 'json' : 'plain'}:${table}`;
17
+ /*const keyCache = `${pg.options?.database}:settings:${params?.key || 'all'}:${query?.json ? 'json' : 'plain'}:${table}`;
17
18
  const cache = await redis.get(keyCache);
18
19
 
19
20
  if (cache && !config?.local) {
20
21
  return JSON.parse(cache);
21
- }
22
+ }*/
22
23
 
23
24
  const settings = await getSettings({
24
25
  pg, key: params.key, json: query.json, redis, table,
@@ -28,5 +29,5 @@ export default async function getSettingsApp({
28
29
  .map(async (el) => ({ name: el[0], body: await getTemplate('setting', el[0]) }))
29
30
  );
30
31
 
31
- return { message: { forms, settings }, status: 200 };
32
+ return { message: { time: Date.now() - time, forms, settings }, status: 200 };
32
33
  }
@@ -3,9 +3,9 @@ const table = 'admin.properties';
3
3
  import { setSettings } from '../../../../utils.js';
4
4
 
5
5
  export default async function postSettingsApp({
6
- pg, session = {}, body = {},
6
+ pg, user = {}, body = {},
7
7
  }) {
8
- if (session.passport?.user?.user_type !== 'superadmin') {
8
+ if (!user?.user_type?.includes?.('admin')) {
9
9
  return { message: 'access restricted', status: 403 };
10
10
  }
11
11
  const { key, val } = body;
@@ -11,7 +11,7 @@ import { propertiesSchema } from './schema.js';
11
11
 
12
12
  export default async function route(fastify) {
13
13
  fastify.get('/settings-app/:key?', { scheme: propertiesSchema }, getSettingsApp);
14
- fastify.post('/settings-app', { config: { policy: ['superadmin'] } }, postSettingsApp);
14
+ fastify.post('/settings-app', { config: { policy: ['admin'] } }, postSettingsApp);
15
15
 
16
16
  fastify.get('/settings-user/:key?', { scheme: propertiesSchema }, getSettingsUser);
17
17
  fastify.post('/settings-user', {}, postSettingsUser);