@opengis/admin 0.3.21 → 0.3.23
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-DsqxZzEq.js → add-page-2cPkdIAC.js} +29 -26
- package/dist/{admin-interface-C8SGlC1N.js → admin-interface-D9Dx7QqK.js} +234 -232
- package/dist/{admin-view-DtdqTUPa.js → admin-view-C_Ecdip-.js} +29 -29
- package/dist/admin.js +1 -1
- package/dist/admin.umd.cjs +88 -88
- package/dist/{card-view-juhvChuX.js → card-view-MuS2Gqq6.js} +3 -3
- package/dist/{edit-page-DB1hlRzp.js → edit-page-Dr397YuE.js} +33 -31
- package/dist/{import-file-BSdaeh6s.js → import-file-CcRnsq1s.js} +23212 -23090
- package/dist/{profile-page-B-RhB5JP.js → profile-page-BrKTAsqO.js} +2 -2
- package/dist/style.css +1 -1
- package/module/settings/card/admin.roles.table/access.hbs +11 -11
- package/module/settings/card/admin.roles.table/general_info.hbs +9 -9
- package/module/settings/card/admin.roles.table/index.yml +22 -22
- package/module/settings/card/admin.roles.table/users.hbs +12 -12
- package/module/settings/card/admin.routes.table/general_info.hbs +13 -13
- package/module/settings/card/admin.routes.table/index.yml +15 -15
- package/module/settings/card/admin.table_properties.table/custom_columns.hbs +22 -22
- package/module/settings/card/admin.table_properties.table/index.yml +12 -12
- package/module/settings/card/admin.table_properties.table/info.hbs +17 -17
- package/module/settings/card/admin.users.table/general_info.hbs +18 -18
- package/module/settings/card/admin.users.table/index.yml +20 -20
- package/module/settings/card/admin.users.table/last_login.hbs +17 -17
- package/module/settings/card/admin.users.table/logs.hbs +16 -16
- package/module/settings/card/admin.users.table/routes.hbs +13 -13
- package/module/settings/card/admin.users.table/user_roles.hbs +35 -35
- package/module/settings/cls/change_type.json +13 -13
- package/module/settings/cls/core.column_type.json +14 -14
- package/module/settings/form/admin.custom_column.form.json +55 -55
- package/module/settings/form/admin.routes.form.json +25 -25
- package/module/settings/form/admin.rules.form.json +30 -30
- package/module/settings/form/admin.table_properties.form.json +19 -19
- package/module/settings/form/admin.user_roles.form.json +24 -24
- package/module/settings/form/admin.users.form.json +177 -177
- package/module/settings/form/admin.users_edit.form.json +145 -145
- package/module/settings/form/context.account_grants.form.json +24 -24
- package/module/settings/form/context.account_users.form.json +12 -12
- package/module/settings/form/user.user_roles.form.json +13 -13
- package/module/settings/menu.json +72 -72
- package/module/settings/table/admin.accounts.table.json +49 -49
- package/module/settings/table/admin.custom_column.table.json +100 -100
- package/module/settings/table/admin.roles.table.json +77 -77
- package/module/settings/table/admin.routes.table.json +73 -73
- package/module/settings/table/admin.rules.table.json +77 -77
- package/module/settings/table/admin.table_properties.table.json +37 -37
- package/module/settings/table/admin.user_roles.table.json +74 -74
- package/module/settings/table/admin.users.table.json +135 -135
- package/module/settings/table/context.account_grants.table.json +88 -88
- package/module/settings/table/context.account_users.table.json +53 -53
- package/module/settings/table/log.table_changes.table.json +100 -100
- package/package.json +102 -102
- package/plugin.js +30 -30
- package/server/helpers/index.js +40 -40
- package/server/helpers/list/descriptionList.js +45 -45
- package/server/helpers/list/tableList.js +82 -82
- package/server/helpers/list/utils/buttonDel.js +12 -12
- package/server/helpers/list/utils/buttonEdit.js +14 -14
- package/server/helpers/utils/buttonAdd.js +6 -6
- package/server/helpers/utils/buttonDel.js +6 -6
- package/server/helpers/utils/buttonEdit.js +5 -5
- package/server/helpers/utils/paddingNumber.js +3 -3
- package/server/plugins/access/funcs/getAdminAccess.js +12 -12
- package/server/plugins/hook.js +276 -275
- package/server/plugins/vite.js +77 -77
- package/server/routes/access/controllers/access.interface.js +33 -33
- package/server/routes/data/controllers/cardData.js +127 -127
- package/server/routes/data/controllers/tableFilter.js +9 -9
- package/server/routes/data/controllers/tableInfo.js +112 -112
- package/server/routes/dblist/controllers/readItems.js +20 -20
- package/server/routes/dblist/controllers/setItem.js +22 -22
- package/server/routes/dblist/index.mjs +18 -18
- package/server/routes/dblist/utils/formatData.js +7 -7
- package/server/routes/menu/controllers/getMenu.js +77 -77
- package/server/routes/menu/controllers/interfaces.js +20 -20
- package/server/routes/menu/index.mjs +7 -7
- package/server/routes/print/controllers/printTemplate.add.js +37 -37
- package/server/routes/print/controllers/printTemplate.delete.js +29 -29
- package/server/routes/print/controllers/printTemplate.edit.js +42 -42
- package/server/routes/print/controllers/printTemplate.js +67 -67
- package/server/routes/print/controllers/printTemplateList.js +19 -19
- package/server/routes/print/controllers/printTemplatePreview.js +87 -87
- package/server/routes/print/index.mjs +19 -19
- package/server/routes/properties/controllers/admin.properties.get.js +31 -31
- package/server/routes/properties/controllers/table.properties.get.js +120 -120
- package/server/routes/properties/controllers/table.properties.post.js +115 -115
- package/server/routes/properties/controllers/user.properties.get.js +19 -19
- package/server/routes/properties/controllers/user.properties.post.js +10 -10
- package/server/routes/properties/index.mjs +21 -21
- package/server/routes/properties/utils/dataInsert.js +26 -26
- package/server/routes/properties/utils/getColumnMetaData.js +17 -17
- package/server/routes/properties/utils/refreshData.js +128 -128
- package/server/routes/report/utils/getFilterQuery.js +67 -67
- package/server/routes/templates/index.mjs +16 -16
- package/server/routes/user/controllers/user.cls.post.js +54 -54
- package/server/routes/util/index.mjs +5 -5
- package/server/routes/widget/controllers/widget.get.js +125 -125
- package/server/templates/form/admin.profile.form.json +31 -31
- package/server/templates/form/cp_building.form.json +32 -32
- package/server/templates/pt/card-print.pt.hbs +245 -245
- package/utils.js +26 -26
package/server/plugins/hook.js
CHANGED
@@ -1,276 +1,277 @@
|
|
1
|
-
import path from 'node:path';
|
2
|
-
import { createHash } from 'node:crypto';
|
3
|
-
import { readFileSync } from 'node:fs';
|
4
|
-
|
5
|
-
import {
|
6
|
-
getTemplatePath, addHook, getToken, getTemplate, config, pgClients, initPG, getRedis, logger,
|
7
|
-
} from '@opengis/fastify-table/utils.js';
|
8
|
-
|
9
|
-
import getMenu from '../routes/menu/controllers/getMenu.js';
|
10
|
-
import printTemplates from '../routes/print/controllers/printTemplates.js';
|
11
|
-
|
12
|
-
const { client } = pgClients;
|
13
|
-
|
14
|
-
const rclient = getRedis();
|
15
|
-
|
16
|
-
export default async function plugin(fastify) {
|
17
|
-
const user1 = config?.auth?.disable || process.env.NODE_ENV !== 'admin' ? { uid: '1' } : null;
|
18
|
-
await initPG(client);
|
19
|
-
|
20
|
-
addHook('preForm', async ({ form, user }) => {
|
21
|
-
if (!user?.uid) return null;
|
22
|
-
const opt = await getToken({ mode: 'w', token: form, uid: user.uid, json: 1 });
|
23
|
-
return opt;
|
24
|
-
});
|
25
|
-
|
26
|
-
fastify.addHook('onListen', async () => {
|
27
|
-
const json = await getMenu({ user: { uid: 1 } });
|
28
|
-
// insert interface list to db (user access management)
|
29
|
-
if (client?.pk?.['admin.routes'] && json?.menus?.length) {
|
30
|
-
const menuList = json?.menus?.filter?.((el) => (el?.table || el?.component || el?.menu?.length) /*&& el?.ua || el?.en || el?.name*/);
|
31
|
-
|
32
|
-
// skip dupes
|
33
|
-
//admin_route_menu_id_fkey
|
34
|
-
const q = `insert into admin.menu(name, ord) values${menuList.map((el, i) => `('${(el?.ua || el?.en || el?.name).replace(/'/g, "''")}', ${i}) `).join(',')
|
35
|
-
} on conflict (name) do update set ord=excluded.ord, enabled=true returning name, menu_id`;
|
36
|
-
|
37
|
-
const { rows = [] } = menuList?.length ? await client.query(q) : {};
|
38
|
-
const menus = rows.reduce((acc, curr) => Object.assign(acc, { [curr.menu_id]: menuList.find((item) => (item?.ua || item?.en || item?.name) === curr.name) }), {});
|
39
|
-
|
40
|
-
const values = Object.entries(menus).reduce((acc, curr) => {
|
41
|
-
if (curr[1]?.table || curr[1]?.component) { acc.push({ ...curr[1], menuId: curr[0] }); }
|
42
|
-
curr[1]?.menu?.forEach((el) => acc.push({ ...el, menuId: curr[0] }));
|
43
|
-
return acc;
|
44
|
-
}, []);
|
45
|
-
|
46
|
-
await Promise.all(values.filter((el) => el?.table).map(async (el) => {
|
47
|
-
const loadTable = await getTemplate('table', el.table);
|
48
|
-
Object.assign(el, {
|
49
|
-
table1: loadTable?.table || el.table,
|
50
|
-
actions: loadTable?.actions,
|
51
|
-
access: loadTable?.access,
|
52
|
-
});
|
53
|
-
}));
|
54
|
-
// console.log(values)
|
55
|
-
const q1 = `insert into admin.routes(route_id, alias, title, menu_id, table_name, actions, access, query)
|
56
|
-
values ${values.filter((el) => el?.path).map((el) => `('${el.path}', ${el.table ? `'${el.table}'` : null},
|
57
|
-
${(el.title || el.ua) ? `'${(el.title || el.ua).replace(/'/g, "''")}'` : null},
|
58
|
-
${el.menuId ? `'${el.menuId}'` : null}, ${el.table1 ? `'${el.table1}'` : null},
|
59
|
-
${el.actions?.length ? `'{ ${el.actions} }'::text[]` : null}, ${el.access ? `'${el.access}'` : null},
|
60
|
-
${el.query ? `'${el.query.replace(/'/g, "''")}'` : '\'1=1\''})`).join(',')}
|
61
|
-
on conflict (route_id) do update set menu_id=excluded.menu_id, alias=excluded.alias, title=excluded.title, enabled=true, query=excluded.query,
|
62
|
-
table_name=excluded.table_name, actions=excluded.actions, access=excluded.access returning route_id, table_name`;
|
63
|
-
|
64
|
-
try {
|
65
|
-
console.log('admin/hook routes sql start');
|
66
|
-
|
67
|
-
const { rowCount: menuCount } = await client.query(`delete from admin.menu
|
68
|
-
where not array[menu_id] <@ $1::text[] and menu_id not in (select menu_id from admin.routes)`, [rows.map((el) => el.menu_id)]);
|
69
|
-
console.log('delete deprecated menus ok', menuCount);
|
70
|
-
|
71
|
-
const { rowCount: interfaceCount } = await client.query(`delete from admin.routes
|
72
|
-
where not array[route_id] <@ $1::text[] and route_id not in (select route_id from admin.role_access)`, [values.filter((el) => el?.path)]);
|
73
|
-
console.log('delete deprecated interfaces ok', interfaceCount);
|
74
|
-
|
75
|
-
const { rowCount } = values?.length ? await client.query(q1) : {};
|
76
|
-
console.log('insert interfaces ok', rowCount);
|
77
|
-
} catch (err) {
|
78
|
-
console.log('admin/hook routes sql error', values, q1, err);
|
79
|
-
}
|
80
|
-
}
|
81
|
-
});
|
82
|
-
|
83
|
-
fastify.addHook('onListen', async () => {
|
84
|
-
// insert document templates to db (print API)
|
85
|
-
const printTemplateList = getTemplatePath('print');
|
86
|
-
printTemplateList.filter(el => el[2] === 'json').map((el) => {
|
87
|
-
const settings = JSON.parse(readFileSync(el[1]) || '{}');
|
88
|
-
const htmlPath = printTemplateList.find(item => item[0] === el[0] && ['hbs', 'html'].includes(item[2]))?.[1];
|
89
|
-
const html = htmlPath ? readFileSync(htmlPath, 'utf-8') : null;
|
90
|
-
Object.assign(settings, { html });
|
91
|
-
printTemplates[el[0]] = settings;
|
92
|
-
});
|
93
|
-
if (client?.pk?.['admin.templates']) {
|
94
|
-
const arr = Object.keys(printTemplates || {}).map(el => ({ name: el, ...printTemplates?.[el] || {} })).filter(el => el.name && el.route && el.html);
|
95
|
-
|
96
|
-
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)]);
|
97
|
-
console.log('delete deprecated templates', 'ok', rowsCount);
|
98
|
-
const { rowsCount: empty = 0 } = await pgClients.client.query('delete from admin.templates where body is null');
|
99
|
-
console.log('delete empty templates', 'ok', empty);
|
100
|
-
|
101
|
-
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 || el.name).replace(/'/g, "''")}', 'demo', '${(el.html || '').replace(/'/g, "''")}') on conflict(name, type) do update set route_id=excluded.route_id, title=excluded.title`).join(';');
|
102
|
-
const res = await pgClients.client.query(q);
|
103
|
-
console.log('insert print templates', 'ok', (Array.isArray(res) ? res : [res]).length);
|
104
|
-
}
|
105
|
-
});
|
106
|
-
|
107
|
-
fastify.addHook('onListen', async () => {
|
108
|
-
const clsQuery = [];
|
109
|
-
if (!client?.pk?.['admin.cls']) return;
|
110
|
-
|
111
|
-
const selectList = getTemplatePath('select');
|
112
|
-
const clsList = (getTemplatePath('cls'))?.filter((el) => !(selectList?.map((el) => el?.[0]) || []).includes(el[0]));
|
113
|
-
const cls = (selectList || []).concat(clsList || [])
|
114
|
-
?.map((el) => ({ name: el[0], module: path.basename(path.dirname(path.dirname(el[1]))), type: { 'json': 'cls', 'sql': 'select' }[el[2]] }))
|
115
|
-
if (!cls?.length) return;
|
116
|
-
|
117
|
-
const dupes = cls.filter((el, idx, arr) => arr.map((item) => item.name).indexOf(el.name) !== idx);
|
118
|
-
//console.log('cls insert skip dupes', dupes.map((el) => el.name));
|
119
|
-
|
120
|
-
try {
|
121
|
-
const hashes = await rclient.hgetall('cls-insert-hashes').then(obj => Object.keys(obj));
|
122
|
-
const
|
123
|
-
|
124
|
-
const
|
125
|
-
const
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
await
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
const
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
const
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
const
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
const
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
.
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
const
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
.
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
1
|
+
import path from 'node:path';
|
2
|
+
import { createHash } from 'node:crypto';
|
3
|
+
import { readFileSync } from 'node:fs';
|
4
|
+
|
5
|
+
import {
|
6
|
+
getTemplatePath, addHook, getToken, getTemplate, config, pgClients, initPG, getRedis, logger,
|
7
|
+
} from '@opengis/fastify-table/utils.js';
|
8
|
+
|
9
|
+
import getMenu from '../routes/menu/controllers/getMenu.js';
|
10
|
+
import printTemplates from '../routes/print/controllers/printTemplates.js';
|
11
|
+
|
12
|
+
const { client } = pgClients;
|
13
|
+
|
14
|
+
const rclient = getRedis();
|
15
|
+
|
16
|
+
export default async function plugin(fastify) {
|
17
|
+
const user1 = config?.auth?.disable || process.env.NODE_ENV !== 'admin' ? { uid: '1' } : null;
|
18
|
+
await initPG(client);
|
19
|
+
|
20
|
+
addHook('preForm', async ({ form, user }) => {
|
21
|
+
if (!user?.uid) return null;
|
22
|
+
const opt = await getToken({ mode: 'w', token: form, uid: user.uid, json: 1 });
|
23
|
+
return opt;
|
24
|
+
});
|
25
|
+
|
26
|
+
fastify.addHook('onListen', async () => {
|
27
|
+
const json = await getMenu({ user: { uid: 1 } });
|
28
|
+
// insert interface list to db (user access management)
|
29
|
+
if (client?.pk?.['admin.routes'] && json?.menus?.length) {
|
30
|
+
const menuList = json?.menus?.filter?.((el) => (el?.table || el?.component || el?.menu?.length) /*&& el?.ua || el?.en || el?.name*/);
|
31
|
+
|
32
|
+
// skip dupes
|
33
|
+
//admin_route_menu_id_fkey
|
34
|
+
const q = `insert into admin.menu(name, ord) values${menuList.map((el, i) => `('${(el?.ua || el?.en || el?.name).replace(/'/g, "''")}', ${i}) `).join(',')
|
35
|
+
} on conflict (name) do update set ord=excluded.ord, enabled=true returning name, menu_id`;
|
36
|
+
|
37
|
+
const { rows = [] } = menuList?.length ? await client.query(q) : {};
|
38
|
+
const menus = rows.reduce((acc, curr) => Object.assign(acc, { [curr.menu_id]: menuList.find((item) => (item?.ua || item?.en || item?.name) === curr.name) }), {});
|
39
|
+
|
40
|
+
const values = Object.entries(menus).reduce((acc, curr) => {
|
41
|
+
if (curr[1]?.table || curr[1]?.component) { acc.push({ ...curr[1], menuId: curr[0] }); }
|
42
|
+
curr[1]?.menu?.forEach((el) => acc.push({ ...el, menuId: curr[0] }));
|
43
|
+
return acc;
|
44
|
+
}, []);
|
45
|
+
|
46
|
+
await Promise.all(values.filter((el) => el?.table).map(async (el) => {
|
47
|
+
const loadTable = await getTemplate('table', el.table);
|
48
|
+
Object.assign(el, {
|
49
|
+
table1: loadTable?.table || el.table,
|
50
|
+
actions: loadTable?.actions,
|
51
|
+
access: loadTable?.access,
|
52
|
+
});
|
53
|
+
}));
|
54
|
+
// console.log(values)
|
55
|
+
const q1 = `insert into admin.routes(route_id, alias, title, menu_id, table_name, actions, access, query)
|
56
|
+
values ${values.filter((el) => el?.path).map((el) => `('${el.path}', ${el.table ? `'${el.table}'` : null},
|
57
|
+
${(el.title || el.ua) ? `'${(el.title || el.ua).replace(/'/g, "''")}'` : null},
|
58
|
+
${el.menuId ? `'${el.menuId}'` : null}, ${el.table1 ? `'${el.table1}'` : null},
|
59
|
+
${el.actions?.length ? `'{ ${el.actions} }'::text[]` : null}, ${el.access ? `'${el.access}'` : null},
|
60
|
+
${el.query ? `'${el.query.replace(/'/g, "''")}'` : '\'1=1\''})`).join(',')}
|
61
|
+
on conflict (route_id) do update set menu_id=excluded.menu_id, alias=excluded.alias, title=excluded.title, enabled=true, query=excluded.query,
|
62
|
+
table_name=excluded.table_name, actions=excluded.actions, access=excluded.access returning route_id, table_name`;
|
63
|
+
|
64
|
+
try {
|
65
|
+
console.log('admin/hook routes sql start');
|
66
|
+
|
67
|
+
const { rowCount: menuCount } = await client.query(`delete from admin.menu
|
68
|
+
where not array[menu_id] <@ $1::text[] and menu_id not in (select menu_id from admin.routes)`, [rows.map((el) => el.menu_id)]);
|
69
|
+
console.log('delete deprecated menus ok', menuCount);
|
70
|
+
|
71
|
+
const { rowCount: interfaceCount } = await client.query(`delete from admin.routes
|
72
|
+
where not array[route_id] <@ $1::text[] and route_id not in (select route_id from admin.role_access)`, [values.filter((el) => el?.path)]);
|
73
|
+
console.log('delete deprecated interfaces ok', interfaceCount);
|
74
|
+
|
75
|
+
const { rowCount } = values?.length ? await client.query(q1) : {};
|
76
|
+
console.log('insert interfaces ok', rowCount);
|
77
|
+
} catch (err) {
|
78
|
+
console.log('admin/hook routes sql error', values, q1, err);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
});
|
82
|
+
|
83
|
+
fastify.addHook('onListen', async () => {
|
84
|
+
// insert document templates to db (print API)
|
85
|
+
const printTemplateList = getTemplatePath('print');
|
86
|
+
printTemplateList.filter(el => el[2] === 'json').map((el) => {
|
87
|
+
const settings = JSON.parse(readFileSync(el[1]) || '{}');
|
88
|
+
const htmlPath = printTemplateList.find(item => item[0] === el[0] && ['hbs', 'html'].includes(item[2]))?.[1];
|
89
|
+
const html = htmlPath ? readFileSync(htmlPath, 'utf-8') : null;
|
90
|
+
Object.assign(settings, { html });
|
91
|
+
printTemplates[el[0]] = settings;
|
92
|
+
});
|
93
|
+
if (client?.pk?.['admin.templates']) {
|
94
|
+
const arr = Object.keys(printTemplates || {}).map(el => ({ name: el, ...printTemplates?.[el] || {} })).filter(el => el.name && el.route && el.html);
|
95
|
+
|
96
|
+
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)]);
|
97
|
+
console.log('delete deprecated templates', 'ok', rowsCount);
|
98
|
+
const { rowsCount: empty = 0 } = await pgClients.client.query('delete from admin.templates where body is null');
|
99
|
+
console.log('delete empty templates', 'ok', empty);
|
100
|
+
|
101
|
+
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 || el.name).replace(/'/g, "''")}', 'demo', '${(el.html || '').replace(/'/g, "''")}') on conflict(name, type) do update set route_id=excluded.route_id, title=excluded.title`).join(';');
|
102
|
+
const res = await pgClients.client.query(q);
|
103
|
+
console.log('insert print templates', 'ok', (Array.isArray(res) ? res : [res]).length);
|
104
|
+
}
|
105
|
+
});
|
106
|
+
|
107
|
+
fastify.addHook('onListen', async () => {
|
108
|
+
const clsQuery = [];
|
109
|
+
if (!client?.pk?.['admin.cls']) return;
|
110
|
+
|
111
|
+
const selectList = getTemplatePath('select');
|
112
|
+
const clsList = (getTemplatePath('cls'))?.filter((el) => !(selectList?.map((el) => el?.[0]) || []).includes(el[0]));
|
113
|
+
const cls = (selectList || []).concat(clsList || [])
|
114
|
+
?.map((el) => ({ name: el[0], module: path.basename(path.dirname(path.dirname(el[1]))), type: { 'json': 'cls', 'sql': 'select' }[el[2]] }))
|
115
|
+
if (!cls?.length) return;
|
116
|
+
|
117
|
+
const dupes = cls.filter((el, idx, arr) => arr.map((item) => item.name).indexOf(el.name) !== idx);
|
118
|
+
//console.log('cls insert skip dupes', dupes.map((el) => el.name));
|
119
|
+
|
120
|
+
try {
|
121
|
+
const hashes = await rclient.hgetall('cls-insert-hashes').then(obj => Object.keys(obj));
|
122
|
+
const names = await pgClients.client.query(`select array_agg(name) from admin.cls where parent is null`).then(el => el.rows?.[0]?.array_agg || []);
|
123
|
+
const qHashes = await Promise.all(cls.filter((el, idx, arr) => arr.map((item) => item.name).indexOf(el.name) === idx).map(async (el) => {
|
124
|
+
const { name, module, type } = el;
|
125
|
+
const loadTemplate = await getTemplate(type, name);
|
126
|
+
const hash = createHash('md5').update(type === 'cls' ? JSON.stringify(loadTemplate) : (loadTemplate?.sql || loadTemplate)).digest('hex');
|
127
|
+
if (type === 'select' && (!hashes.includes(hash) || !names.includes(name))) {
|
128
|
+
clsQuery.push(`insert into admin.cls(name,type,data,module) values('${name}','sql','${(loadTemplate?.sql || loadTemplate)?.replace(/'/g, "''")}', '${module?.replace(/'/g, "''")}')`);
|
129
|
+
return hash;
|
130
|
+
} else if (type === 'cls' && loadTemplate?.length && (!hashes.includes(hash) || !names.includes(name))) {
|
131
|
+
clsQuery.push(`insert into admin.cls(name,type, module) values('${name}','json', '${module?.replace(/'/g, "''")}');
|
132
|
+
insert into admin.cls(code,name,parent,icon,data)
|
133
|
+
select value->>'id',value->>'text','${name}',value->>'icon',value->>'data'
|
134
|
+
from json_array_elements('${JSON.stringify(loadTemplate).replace(/'/g, "''")}'::json)`);
|
135
|
+
return hash;
|
136
|
+
} else if (hashes.includes(hash)) {
|
137
|
+
console.log(name, type, names.includes(name) ? 'skip equal hash' : 'insert missing cls');
|
138
|
+
} else {
|
139
|
+
console.log(name, type, 'empty');
|
140
|
+
}
|
141
|
+
}));
|
142
|
+
|
143
|
+
const { rowCount = 0 } = await client.query('delete from admin.cls where not name = any($1::text[]) and (case when type = \'json\' then parent = any($1::text[]) else parent is null end)', [cls.map(el => el.name)]);
|
144
|
+
console.log('admin/hook old cls deleted', rowCount);
|
145
|
+
if (clsQuery.filter((el) => el).length) {
|
146
|
+
console.log('admin/hook cls sql start', clsQuery?.length);
|
147
|
+
await client.query(clsQuery.filter((el) => el).join(';'));
|
148
|
+
await Promise.all(qHashes.filter(el => el).map(async (el) => rclient.hset('cls-insert-hashes', el, 1)));
|
149
|
+
logger.file('migration/hash', { list: qHashes.filter(el => el) });
|
150
|
+
console.log('admin/hook cls sql finish', clsQuery?.length);
|
151
|
+
}
|
152
|
+
} catch (err) {
|
153
|
+
console.error('admin/hook cls sql error', err.toString());
|
154
|
+
}
|
155
|
+
});
|
156
|
+
|
157
|
+
addHook('afterTable', async ({ table, res = {}, payload: rows = [], user = {} }) => {
|
158
|
+
const loadTable = await getTemplate('table', table);
|
159
|
+
const { uid } = user1 || user;
|
160
|
+
if (!uid || !table || !client?.pk?.[table] || !rows.length || !loadTable?.table) return;
|
161
|
+
|
162
|
+
// admin.custom_column - user column data
|
163
|
+
const { rows: properties = [] } = await client.query(`select column_id, name, title, format, data from admin.custom_column
|
164
|
+
where _table and entity=$1 and uid=$2`, [table, uid]);
|
165
|
+
const extraColumnList = properties.map((row) => ({ id: row.column_id, name: row.name, title: row.title, format: row.format, data: row.data }));
|
166
|
+
if (!extraColumnList?.length) return;
|
167
|
+
|
168
|
+
if (res?.columns?.length) {
|
169
|
+
extraColumnList.forEach((col) => res.columns.push(col));
|
170
|
+
}
|
171
|
+
|
172
|
+
const { rows: extraData = [] } = await client.query(`select object_id, json_object_agg( property_id, coalesce(value_date::text,value_text) ) as extra from crm.extra_data
|
173
|
+
where property_entity=$1 and property_id=any($2) and object_id=any($3) group by object_id`, [table, extraColumnList?.map((el) => el.id), rows.map((el) => el.id)]);
|
174
|
+
|
175
|
+
if (!extraData?.length) {
|
176
|
+
// Object.assign(rows?.[0] || {}, { ...extraColumnList.reduce((acc, curr) => Object.assign(acc, { [curr.name]: null }), {}) });
|
177
|
+
return;
|
178
|
+
}
|
179
|
+
|
180
|
+
rows.filter((row) => extraData.map((el) => el?.object_id).includes(row.id)).forEach((row) => {
|
181
|
+
const { extra = {} } = extraData.find((el) => el.object_id === row.id);
|
182
|
+
Object.assign(row, { ...Object.fromEntries(Object.entries(extra).map((el) => [extraColumnList.find((col) => col.id === el[0]).name, el[1]])) });
|
183
|
+
});
|
184
|
+
|
185
|
+
// admin.custom_column - metaFormat
|
186
|
+
await Promise.all(extraColumnList.filter((el) => el?.data).map(async (attr) => {
|
187
|
+
const values = [...new Set(rows?.map((el) => el[attr.name]).flat())].filter((el) => el);
|
188
|
+
if (!values.length) return;
|
189
|
+
const cls = await getSelectVal({ name: attr.data, values });
|
190
|
+
if (!cls) return;
|
191
|
+
rows.forEach(el => {
|
192
|
+
const val = el[attr.name]?.map?.(c => cls[c] || c) || cls[el[attr.name]] || el[attr.name];
|
193
|
+
if (!val) return;
|
194
|
+
Object.assign(el, { [val?.color ? `${attr.name}_data` : `${attr.name}_text`]: (val.color ? val : val.text || val) });
|
195
|
+
});
|
196
|
+
}));
|
197
|
+
});
|
198
|
+
|
199
|
+
// extract table from form token for user columns - p.2 - read (refactor to global token)
|
200
|
+
addHook('preTemplate', async ({ name, type, user = {} }) => {
|
201
|
+
if (!name || !type) return;
|
202
|
+
const { uid } = user1 || user;
|
203
|
+
const tokenData = await getToken({
|
204
|
+
uid, token: name, mode: 'w', json: 1,
|
205
|
+
}) // edit?
|
206
|
+
|| await getToken({
|
207
|
+
uid, token: name, mode: 'a', json: 1,
|
208
|
+
}) || {}; // add?
|
209
|
+
return { name: tokenData?.[type] };
|
210
|
+
});
|
211
|
+
|
212
|
+
addHook('afterTemplate', async ({ name, type, payload: data = {}, user = {} }) => {
|
213
|
+
const { uid } = user1 || user;
|
214
|
+
// extract table from form token for user columns - p.1 - assign (refactor to global token)
|
215
|
+
if (!uid || !data || type !== 'form' || !name) return null;
|
216
|
+
|
217
|
+
const { form, id, table } = await getToken({
|
218
|
+
uid, token: name, mode: 'w', json: 1,
|
219
|
+
}) // edit?
|
220
|
+
|| await getToken({
|
221
|
+
uid, token: name, mode: 'a', json: 1,
|
222
|
+
}) || {}; // add?
|
223
|
+
|
224
|
+
const { rows: properties = [] } = await client.query(`select name, title, format, data from admin.custom_column
|
225
|
+
where entity=$1 and uid=$2`, [table || name, uid]);
|
226
|
+
|
227
|
+
await Promise.all(properties.map(async (el) => {
|
228
|
+
const clsData = el.data ? await getTemplate(['cls', 'select'], el.data) : undefined;
|
229
|
+
const type = clsData ? 'Select' : ({ date: 'DatePicker' }[el.format] || 'Text');
|
230
|
+
Object.assign(data?.schema || data || {}, { [el.name]: { type, ua: el.title, data: el.data, options: type === 'Select' && Array.isArray(clsData) && clsData?.length ? clsData : undefined, extra: 1 } });
|
231
|
+
}));
|
232
|
+
});
|
233
|
+
|
234
|
+
addHook('afterUpdate', async ({ table, body = {}, payload: res = {}, user = {} }) => {
|
235
|
+
const { uid } = user1 || user;
|
236
|
+
if (!uid || !table || !Object.keys(body)?.length) return null;
|
237
|
+
|
238
|
+
const loadTable = await getTemplate('table', table);
|
239
|
+
if (!client?.pk?.[loadTable?.table || table]) return null;
|
240
|
+
const pk = client?.pk?.[loadTable?.table || table];
|
241
|
+
const id = res[pk];
|
242
|
+
|
243
|
+
const { rows: properties = [] } = await client.query(`select column_id, name, title, format, data from admin.custom_column
|
244
|
+
where entity=$1 and uid=$2`, [table, uid]);
|
245
|
+
|
246
|
+
if (!id || !properties?.length) return null;
|
247
|
+
|
248
|
+
const q = `delete from crm.extra_data where property_entity='${table}' and object_id='${id}';${properties
|
249
|
+
.filter((el) => Object.keys(body).includes(el.name))
|
250
|
+
.map((el) => `insert into crm.extra_data(property_id,property_key,property_entity,object_id,${el.format?.toLowerCase() === 'date' ? 'value_date' : 'value_text'})
|
251
|
+
select '${el.column_id}', '${el.name}', '${table}', '${id}', ${el.format?.toLowerCase() === 'date' ? `'${body[el.name]}'::timestamp without time zone` : `'${body[el.name]}'::text`}`)
|
252
|
+
.join(';\n') || ''}`;
|
253
|
+
return client.query(q);
|
254
|
+
});
|
255
|
+
|
256
|
+
addHook('afterInsert', async ({ table, body = {}, payload: res = {}, user = {} }) => {
|
257
|
+
const { uid } = user1 || user;
|
258
|
+
if (!uid || !table || !Object.keys(body)?.length) return null;
|
259
|
+
|
260
|
+
const loadTable = await getTemplate('table', table);
|
261
|
+
if (!client?.pk?.[loadTable?.table || table]) return null;
|
262
|
+
const pk = client?.pk?.[loadTable?.table || table];
|
263
|
+
const id = res.rows?.[0]?.[pk];
|
264
|
+
|
265
|
+
const { rows: properties = [] } = await client.query(`select column_id, name, title, format, data from admin.custom_column
|
266
|
+
where entity=$1 and uid=$2`, [table, uid]);
|
267
|
+
|
268
|
+
if (!id || !properties?.length) return null;
|
269
|
+
|
270
|
+
const q = properties
|
271
|
+
.filter((el) => Object.keys(body).includes(el.name))
|
272
|
+
.map((el) => `insert into crm.extra_data(property_id,property_key,property_entity,object_id,${el.format?.toLowerCase() === 'date' ? 'value_date' : 'value_text'})
|
273
|
+
select '${el.column_id}', '${el.name}', '${table}', '${id}', ${el.format?.toLowerCase() === 'date' ? `'${body[el.name]}'::timestamp without time zone` : `'${body[el.name]}'::text`}`)
|
274
|
+
.join(';\n');
|
275
|
+
return client.query(q);
|
276
|
+
});
|
276
277
|
}
|