@opengis/admin 0.1.58 → 0.1.60

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.
Files changed (117) hide show
  1. package/README.md +29 -29
  2. package/config.js +4 -4
  3. package/dist/{add-page-d6TCPawD.js → add-page-C3Wh2-Ml.js} +13 -11
  4. package/dist/admin-interface-C4m7uvG2.js +896 -0
  5. package/dist/admin-view-YtM2-LrW.js +225 -0
  6. package/dist/admin.js +1 -1
  7. package/dist/admin.umd.cjs +95 -207
  8. package/dist/card-page-WrYs8chM.js +133 -0
  9. package/dist/{card-view-UYkkl_Pu.js → card-view-BwtqUSFP.js} +1 -1
  10. package/dist/{edit-page-CtKHElG1.js → edit-page-CMTqsvJf.js} +34 -33
  11. package/dist/import-file-bdYAo8iW.js +29759 -0
  12. package/dist/style.css +1 -1
  13. package/dist/userMenu-CT1xO2Pt.js +5 -0
  14. package/module/settings/card/admin.roles.table/access.hbs +27 -27
  15. package/module/settings/card/admin.roles.table/general_info.hbs +16 -16
  16. package/module/settings/card/admin.roles.table/index.yml +14 -14
  17. package/module/settings/card/admin.roles.table/users.hbs +27 -27
  18. package/module/settings/card/admin.routes.table/general_info.hbs +40 -40
  19. package/module/settings/card/admin.routes.table/index.yml +8 -8
  20. package/module/settings/card/admin.routes.table/users.hbs +33 -33
  21. package/module/settings/card/admin.users.table/general_info.hbs +25 -25
  22. package/module/settings/card/admin.users.table/index.yml +12 -12
  23. package/module/settings/card/admin.users.table/logs.hbs +30 -30
  24. package/module/settings/card/admin.users.table/user_roles.hbs +24 -24
  25. package/module/settings/cls/core.actions.json +13 -13
  26. package/module/settings/cls/core.scope.json +13 -13
  27. package/module/settings/cls/properties.site_status.json +13 -13
  28. package/module/settings/cls/properties.widget_status.json +13 -13
  29. package/module/settings/cls/users.user_type.json +13 -13
  30. package/module/settings/form/admin.access.form.json +36 -36
  31. package/module/settings/form/admin.custom_column.form.json +71 -71
  32. package/module/settings/form/admin.properties.form.json +15 -15
  33. package/module/settings/form/admin.roles.form.json +19 -19
  34. package/module/settings/form/admin.routes.form.json +25 -25
  35. package/module/settings/form/admin.user_properties.form.json +15 -15
  36. package/module/settings/form/admin.user_roles.form.json +21 -21
  37. package/module/settings/form/admin.users.form.json +150 -150
  38. package/module/settings/form/user.user_roles.form.json +13 -13
  39. package/module/settings/interface/admin.properties.json +4 -4
  40. package/module/settings/interface/admin.roles.json +4 -4
  41. package/module/settings/interface/admin.routes.json +4 -4
  42. package/module/settings/interface/admin.users.json +4 -4
  43. package/module/settings/menu.json +50 -50
  44. package/module/settings/select/core.routes.sql +1 -1
  45. package/module/settings/select/core.user_uid.sql +1 -1
  46. package/module/settings/table/admin.access.table.json +77 -77
  47. package/module/settings/table/admin.custom_column.table.json +94 -94
  48. package/module/settings/table/admin.properties.table.json +33 -33
  49. package/module/settings/table/admin.roles.table.json +58 -58
  50. package/module/settings/table/admin.routes.table.json +67 -67
  51. package/module/settings/table/admin.user_properties.table.json +28 -28
  52. package/module/settings/table/admin.user_roles.table.json +66 -66
  53. package/module/settings/table/admin.users.table.json +119 -119
  54. package/package.json +79 -81
  55. package/plugin.js +100 -162
  56. package/server/helpers/controllers/badge.js +11 -11
  57. package/server/helpers/controllers/hb.js +2 -2
  58. package/server/helpers/controllers/map.js +2 -2
  59. package/server/helpers/controllers/mls.js +2 -2
  60. package/server/helpers/controllers/vue.js +2 -2
  61. package/server/helpers/index.mjs +13 -13
  62. package/server/plugins/adminHook.js +165 -0
  63. package/server/plugins/cron.js +11 -0
  64. package/server/plugins/docs.js +28 -28
  65. package/server/plugins/hook.js +152 -228
  66. package/server/plugins/vite.js +69 -69
  67. package/server/routes/calendar/controllers/calendar.data.js +88 -88
  68. package/server/routes/calendar/index.mjs +17 -17
  69. package/server/routes/data/controllers/cardData.js +57 -56
  70. package/server/routes/data/controllers/cardTabData.js +49 -49
  71. package/server/routes/data/controllers/funcs/getFilterSQL/index.js +92 -92
  72. package/server/routes/data/controllers/funcs/getFilterSQL/util/formatValue.js +170 -170
  73. package/server/routes/data/controllers/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
  74. package/server/routes/data/controllers/funcs/getFilterSQL/util/getFilterQuery.js +64 -64
  75. package/server/routes/data/controllers/funcs/getFilterSQL/util/getOptimizedQuery.js +12 -12
  76. package/server/routes/data/controllers/funcs/getFilterSQL/util/getTableSql.js +34 -34
  77. package/server/routes/data/controllers/tableData.js +112 -145
  78. package/server/routes/data/controllers/tableDataId.js +27 -27
  79. package/server/routes/data/controllers/tableFilter.js +63 -63
  80. package/server/routes/data/controllers/utils/assignTokens.js +30 -30
  81. package/server/routes/data/controllers/utils/getColumns.js +8 -21
  82. package/server/routes/data/index.mjs +15 -15
  83. package/server/routes/data/schema.js +7 -7
  84. package/server/routes/menu/controllers/getMenu.js +34 -34
  85. package/server/routes/menu/index.mjs +5 -5
  86. package/server/routes/notifications/controllers/readNotifications.js +30 -30
  87. package/server/routes/notifications/controllers/userNotifications.js +64 -64
  88. package/server/routes/notifications/hook/onWidgetSet.js +63 -63
  89. package/server/routes/notifications/index.mjs +40 -40
  90. package/server/routes/properties/controllers/admin.properties.get.js +29 -29
  91. package/server/routes/properties/controllers/user.properties.get.js +34 -34
  92. package/server/routes/properties/controllers/user.properties.post.js +30 -30
  93. package/server/routes/properties/funcs/getSettings.js +56 -56
  94. package/server/routes/properties/funcs/setSettings.js +44 -44
  95. package/server/routes/properties/funcs/utils/dataInsert.js +26 -26
  96. package/server/routes/properties/index.mjs +26 -26
  97. package/server/routes/root.mjs +3 -3
  98. package/server/routes/templates/controllers/getTemplate.js +20 -16
  99. package/server/routes/templates/index.mjs +14 -14
  100. package/server/templates/cls/itree.recrzone_category.json +73 -73
  101. package/server/templates/cls/test.json +9 -9
  102. package/server/templates/form/admin.user_cls.data.form.json +49 -49
  103. package/server/templates/form/admin.user_group_rel.form.json +21 -21
  104. package/server/templates/form/cp_building.form.json +32 -32
  105. package/server/templates/form/form-user-pass.json +10 -10
  106. package/server/templates/form/form-user_group.json +39 -39
  107. package/server/templates/form/form-users.json +156 -156
  108. package/server/templates/form/user_group_access.form.json +22 -22
  109. package/server/templates/select/account_id.json +2 -2
  110. package/server/templates/table/gis.dataset.table.json +43 -43
  111. package/server/templates/table/management.user_group.table.json +112 -112
  112. package/server/templates/table/management.users.table.json +126 -126
  113. package/utils.js +21 -21
  114. package/dist/admin-interface-w6YuIWM3.js +0 -1343
  115. package/dist/admin-view-3Sz3UF_y.js +0 -461
  116. package/dist/card-page-BsQts5XS.js +0 -230
  117. package/dist/import-file-CsCQ5xvs.js +0 -47264
@@ -1,228 +1,152 @@
1
- import fp from 'fastify-plugin';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
-
5
- import { addHook, getTemplatePath, getTemplate, pgClients } from '@opengis/fastify-table/utils.js';
6
-
7
- import getMenu from '../routes/menu/controllers/getMenu.js';
8
-
9
- import config from '../../config.js';
10
-
11
- // to export the decorators to the outer scope
12
-
13
- async function plugin(fastify) {
14
- fastify.decorate('config', config);
15
-
16
- addHook('afterTemplate', async ({ req, data = {} }) => {
17
- const { uid } = req.session.passport?.user || {};
18
- if (!uid || !data || req.params?.type !== 'form' || !req.params?.name) return null;
19
- const { pg, params = {} } = req;
20
- const { rows: properties = [] } = await pg.query(`select name, title, format, data from admin.custom_column
21
- where entity=$1 and uid=$2`, [params.name?.replace('.form', '.table'), uid]);
22
- await Promise.all(properties.map(async (el) => {
23
- const clsData = el.data ? await getTemplate(['cls', 'select'], el.data) : undefined;
24
- const type = clsData ? 'Select' : ({ date: 'DatePicker' }[el.format] || 'Text');
25
- 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 } });
26
- }));
27
- });
28
-
29
- addHook('afterUpdate', async ({ req, res = {} }) => {
30
- const {
31
- pg, session = {}, params = {}, body = {},
32
- } = req;
33
- const { uid } = session.passport?.user || {};
34
- if (!uid) return null;
35
-
36
- const loadTable = await getTemplate('table', params.table);
37
- if (!pg.pk[loadTable?.table || params.table]) return null;
38
- const pk = pg.pk[loadTable?.table || params.table];
39
- const id = res[pk];
40
-
41
- const { rows: properties = [] } = await pg.query(`select column_id, name, title, format, data from admin.custom_column
42
- where entity=$1 and uid=$2`, [params.table, uid]);
43
-
44
- if (!id || !properties?.length) return null;
45
-
46
- const q = `delete from crm.extra_data where property_entity='${params.table}' and object_id='${id}';${properties
47
- .filter((el) => Object.keys(body).includes(el.name))
48
- .map((el) => `insert into crm.extra_data(property_id,property_key,property_entity,object_id,${el.format?.toLowerCase() === 'date' ? 'value_date' : 'value_text'})
49
- select '${el.column_id}', '${el.name}', '${params.table}', '${id}', ${el.format?.toLowerCase() === 'date' ? `'${body[el.name]}'::timestamp without time zone` : `'${body[el.name]}'::text`}`)
50
- .join(';\n') || ''}`;
51
- return pg.query(q);
52
- });
53
-
54
- addHook('afterInsert', async ({ req, res = {} }) => {
55
- const {
56
- pg, session = {}, params = {}, body = {},
57
- } = req;
58
- const { uid } = session.passport?.user || {};
59
- if (!uid) return null;
60
-
61
- const loadTable = await getTemplate('table', params.table);
62
- if (!pg.pk[loadTable?.table || params.table]) return null;
63
- const pk = pg.pk[loadTable?.table || params.table];
64
- const id = res.rows?.[0]?.[pk];
65
-
66
- const { rows: properties = [] } = await pg.query(`select column_id, name, title, format, data from admin.custom_column
67
- where entity=$1 and uid=$2`, [params.table, uid]);
68
-
69
- if (!id || !properties?.length) return null;
70
-
71
- const q = properties
72
- .filter((el) => Object.keys(body).includes(el.name))
73
- .map((el) => `insert into crm.extra_data(property_id,property_key,property_entity,object_id,${el.format?.toLowerCase() === 'date' ? 'value_date' : 'value_text'})
74
- select '${el.column_id}', '${el.name}', '${params.table}', '${id}', ${el.format?.toLowerCase() === 'date' ? `'${body[el.name]}'::timestamp without time zone` : `'${body[el.name]}'::text`}`)
75
- .join(';\n');
76
- return pg.query(q);
77
- });
78
-
79
- fastify.addHook('onListen', async () => {
80
- const { client } = pgClients;
81
- const json = await getMenu();
82
- // insert interface list to db (user access management)
83
- if (client?.pk?.['admin.routes'] && json?.length) {
84
- const menuList = json.filter((el) => el?.menu?.length && el?.ua || el?.en || el?.name);
85
- const interfaces = menuList.reduce((acc, curr) => { curr.menu.forEach((el) => acc.push(el.path)); return acc; }, []);
86
- await client.query('update admin.routes set enabled=false where not array[route_id] <@ $1::text[]', [interfaces]);
87
-
88
- const q = `insert into admin.menu(name, ord) values${menuList.map((el, i) => `('${(el?.ua || el?.en || el?.name).replace(/'/g, '’')}', ${i}) `).join(',')
89
- } on conflict (name) do update set ord=excluded.ord, enabled=true returning name, menu_id`;
90
- const { rows = [] } = await client.query(q);
91
- await client.query('update admin.menu set enabled=false where not array[menu_id] <@ $1::text[]', [rows.map((el) => el.menu_id)]);
92
-
93
- const menus = rows.reduce((acc, curr) => Object.assign(acc, { [curr.menu_id]: menuList.find((item) => (item?.ua || item?.en || item?.name) === curr.name) }), {});
94
- const values = Object.entries(menus).reduce((acc, curr) => { curr[1]?.menu?.forEach((el) => acc.push({ ...el, menuId: curr[0] })); return acc; }, []);
95
-
96
- await Promise.all(values.filter((el) => el?.table).map(async (el) => Object.assign(el, { table: (await getTemplate('table', el.table))?.table || el.table })));
97
-
98
- const q1 = `insert into admin.routes(route_id, alias, title, menu_id, table_name) values ${values.map((el) => `('${el.path}', '${el.path}', '${el.title}', '${el.menuId}', '${el.table}')`).join(',')}
99
- on conflict (route_id) do update set menu_id=excluded.menu_id, title=excluded.title, enabled=true,
100
- table_name=excluded.table_name returning route_id, table_name`;
101
- try {
102
- const { rowCount } = await client.query(q1);
103
- // console.log('interface insert ok', values, rowCount);
104
- } catch (err) {
105
- console.log('interface insert error', values, q1, err);
106
- }
107
- }
108
- });
109
-
110
- fastify.addHook('onListen', async () => {
111
- const { client: pg } = pgClients;
112
- const clsQuery = [];
113
- if (!pg.pk?.['admin.cls']) return;
114
-
115
- const selectList = await getTemplatePath('select');
116
- const clsList = (await getTemplatePath('cls'))?.filter((el) => !(selectList?.map((el) => el?.[0]) || []).includes(el[0]));
117
- const cls = (selectList || []).concat(clsList || [])
118
- ?.map((el) => ({ name: el[0], module: path.basename(path.dirname(path.dirname(el[1]))), type: { 'json': 'cls', 'sql': 'select' }[el[2]] }))
119
- if (!cls?.length) return;
120
-
121
- const dupes = cls.filter((el, idx, arr) => arr.map((item) => item.name).indexOf(el.name) !== idx);
122
- // console.log('cls insert skip dupes', dupes.map((el) => el.name));
123
-
124
- try {
125
- await Promise.all(cls.filter((el, idx, arr) => arr.map((item) => item.name).indexOf(el.name) === idx).map(async (el) => {
126
- const { name, module, type } = el;
127
- const loadTemplate = await getTemplate(type, name);
128
- //console.log(name, type);
129
- if (type === 'select') {
130
- clsQuery.push(`insert into admin.cls(name,type,data,module) values('${name}','sql','${(loadTemplate?.sql || loadTemplate)?.replace(/'/g, "''")}', '${module?.replace(/'/g, "''")}')`);
131
- } else if (type === 'cls' && loadTemplate?.length) {
132
- clsQuery.push(`insert into admin.cls(name,type, module) values('${name}','json', '${module?.replace(/'/g, "''")}');
133
- insert into admin.cls(code,name,parent,icon)
134
- select value->>'id',value->>'text','${name}',value->>'icon'
135
- from json_array_elements('${JSON.stringify(loadTemplate).replace(/'/g, "''")}'::json)`);
136
- } else {
137
- console.log(name, type, 'empty');
138
- }
139
- }));
140
-
141
- await pg.query('truncate admin.cls');
142
- if (clsQuery.filter((el) => el).length) {
143
- await pg.query(clsQuery.filter((el) => el).join(';'));
144
- console.log('cls insert ok', clsQuery?.length);
145
- }
146
- } catch (err) {
147
- console.error('cls insert error', err.toString());
148
- }
149
- });
150
-
151
- // pre Request
152
- fastify.addHook('onRequest', async (req) => {
153
- req.funcs = fastify;
154
- const { user } = req.session?.passport || {};
155
- req.user = user;
156
- });
157
-
158
- // preSerialization
159
- fastify.addHook('preSerialization', async (req, reply, payload) => {
160
- if (req.url.includes('/suggest/') && !req.query.json) {
161
- return payload?.data;
162
- }
163
- if (payload?.redirect) {
164
- return reply.redirect(payload.redirect);
165
- }
166
- if (reply.sent) {
167
- return null;
168
- }
169
-
170
- if (['200', '400', '500', '403', '404'].includes(payload?.status)) {
171
- reply.status(payload.status);
172
- }
173
- /* if (payload.headers) {
174
- reply.headers(payload.headers);
175
- } */
176
- if (payload?.buffer) {
177
- return payload.buffer;
178
- }
179
- if (payload?.file) {
180
- // const buffer = await readFile(payload.file);
181
- // return reply.send(buffer);
182
- const stream = fs.createReadStream(payload.file);
183
- return stream;
184
- // return reply.send(stream);
185
- }
186
-
187
- if (payload?.message) {
188
- return payload.message;
189
- }
190
- return payload;
191
- });
192
-
193
- // preValidation
194
- fastify.addHook('preValidation', async (req) => {
195
- const parseRawBody = ['POST', 'PUT'].includes(req.method) && req.body && typeof req.body === 'string'
196
- && req.body.trim(/\r\n/g).startsWith('{')
197
- && req.body.trim(/\r\n/g).endsWith('}');
198
- if (parseRawBody) {
199
- try {
200
- req.body = JSON.parse(req.body || '{}');
201
- }
202
- catch (err) {
203
- // throw new Error('invalid body');
204
- // return { error: 'invalid body', status: 400 };
205
- }
206
- }
207
- });
208
-
209
- // allow upload file
210
- const kIsMultipart = Symbol.for('[FastifyMultipart.isMultipart]');
211
- fastify.addContentTypeParser('multipart', (request, _, done) => {
212
- request[kIsMultipart] = true;
213
- done(null);
214
- });
215
-
216
- // parse Body
217
- function contentParser(req, body, done) {
218
- const parseBody = decodeURIComponent(body.toString()).split('&').reduce((acc, el) => {
219
- const [key, val] = el.split('=');
220
- return { ...acc, [key]: val };
221
- }, {});
222
- done(null, parseBody);
223
- }
224
-
225
- fastify.addContentTypeParser('application/x-www-form-urlencoded', { parseAs: 'buffer' }, contentParser);
226
- }
227
-
228
- export default fp(plugin);
1
+ import { addHook, getToken, setToken, getTemplate } from '@opengis/fastify-table/utils.js';
2
+
3
+ export default async function plugin(fastify) {
4
+
5
+ addHook('preTable', async ({ req }) => {
6
+ if (!req?.routeOptions?.method) return;
7
+ const mode = { POST: 'a', DELETE: 'w', PUT: 'w', GET: 'w' }[req.routeOptions.method] || 'w';
8
+ const { funcs, params = {}, session = {} } = req;
9
+ const { uid } = funcs?.config?.auth?.disable ? { uid: '1' } : (session?.passport?.user || {});
10
+ const opt = await getToken({
11
+ uid, token: params.id || params.form || params.table, mode, json: 1,
12
+ });
13
+ if (opt) Object.assign(req, { opt });
14
+ if (!opt && !funcs?.config?.local) {
15
+ return { message: 'access restricted: edit', status: 403 };
16
+ }
17
+ return null;
18
+ });
19
+
20
+ addHook('afterTable', async ({ req = {}, res = {}, rows = [], table }) => {
21
+ const { pg, funcs, params = {}, session = {} } = req;
22
+ const { uid } = funcs?.config?.auth?.disable ? { uid: '1' } : (session?.passport?.user || {});
23
+ if (!uid || !table || !pg?.pk?.[table] || !rows.length || !params.table) return;
24
+
25
+ // admin.custom_column - user column data
26
+ const { rows: properties = [] } = await pg.query(`select column_id, name, title, format, data from admin.custom_column
27
+ where _table and entity=$1 and uid=$2`, [params.table, uid]);
28
+ const extraColumnList = properties.map((row) => ({ id: row.column_id, name: row.name, title: row.title, format: row.format, data: row.data }));
29
+ if (!extraColumnList?.length) return;
30
+
31
+ if (res?.columns?.length) {
32
+ extraColumnList.forEach((col) => res.columns.push(col));
33
+ }
34
+
35
+ const { rows: extraData = [] } = await pg.query(`select object_id, json_object_agg( property_id, coalesce(value_date::text,value_text) ) as extra from crm.extra_data
36
+ where property_entity=$1 and property_id=any($2) and object_id=any($3) group by object_id`, [params.table, extraColumnList?.map((el) => el.id), rows.map((el) => el.id)]);
37
+
38
+ if (!extraData?.length) {
39
+ // Object.assign(rows?.[0] || {}, { ...extraColumnList.reduce((acc, curr) => Object.assign(acc, { [curr.name]: null }), {}) });
40
+ return;
41
+ }
42
+
43
+ rows.filter((row) => extraData.map((el) => el?.object_id).includes(row.id)).forEach((row) => {
44
+ const { extra = {} } = extraData.find((el) => el.object_id === row.id);
45
+ Object.assign(row, { ...Object.fromEntries(Object.entries(extra).map((el) => [extraColumnList.find((col) => col.id === el[0]).name, el[1]])) });
46
+ });
47
+
48
+ // admin.custom_column - metaFormat
49
+ await Promise.all(extraColumnList.filter((el) => el?.data).map(async (attr) => {
50
+ const values = [...new Set(rows?.map((el) => el[attr.name]).flat())].filter((el) => el);
51
+ if (!values.length) return;
52
+ const cls = await getSelectVal({ name: attr.data, values });
53
+ if (!cls) return;
54
+ rows.forEach(el => {
55
+ const val = el[attr.name]?.map?.(c => cls[c] || c) || cls[el[attr.name]] || el[attr.name];
56
+ if (!val) return;
57
+ Object.assign(el, { [val?.color ? `${attr.name}_data` : `${attr.name}_text`]: (val.color ? val : val.text || val) });
58
+ });
59
+ }));
60
+ });
61
+
62
+ // extract table from form token for user columns - p.2 - read (refactor to global token)
63
+ /* addHook('preTemplate', async ({ req = {} }) => {
64
+ const { funcs, params = {}, session = {} } = req;
65
+ const { uid } = funcs?.config?.auth?.disable ? { uid: '1' } : (session?.passport?.user || {});
66
+ if (!uid || params?.type !== 'form' || !params?.name) return null;
67
+
68
+ const { table, form } = await getToken({
69
+ uid, token: params.name, mode: 'w', json: 1,
70
+ }) || {};
71
+ if (form) {
72
+ Object.assign(req.params || {}, { name: form, table });
73
+ }
74
+ }); */
75
+
76
+ addHook('afterTemplate', async ({ req = {}, data = {} }) => {
77
+ const { funcs, session = {} } = req;
78
+ const { uid } = funcs?.config?.auth?.disable ? { uid: '1' } : (session?.passport?.user || {});
79
+ const { pg, params = {} } = req;
80
+ // extract table from form token for user columns - p.1 - assign (refactor to global token)
81
+ /* if (params?.type === 'table') {
82
+ const { form } = await getTemplate('table', params.name) || {};
83
+ if (!form) return;
84
+ const editTokens = setToken({
85
+ ids: [{ table: params.name, form }],
86
+ mode: 'w',
87
+ uid,
88
+ array: 1,
89
+ });
90
+ Object.assign(data, { token: editTokens[0] });
91
+ } */
92
+ if (!uid || !data || params?.type !== 'form' || !params?.name) return null;
93
+
94
+ const { rows: properties = [] } = await pg.query(`select name, title, format, data from admin.custom_column
95
+ where entity=$1 and uid=$2`, [params.table || params.name, uid]);
96
+ await Promise.all(properties.map(async (el) => {
97
+ const clsData = el.data ? await getTemplate(['cls', 'select'], el.data) : undefined;
98
+ const type = clsData ? 'Select' : ({ date: 'DatePicker' }[el.format] || 'Text');
99
+ 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 } });
100
+ }));
101
+ });
102
+
103
+ addHook('afterUpdate', async ({ req, res = {} }) => {
104
+ const {
105
+ pg, funcs, session = {}, params = {}, body = {},
106
+ } = req;
107
+ const { uid } = funcs?.config?.auth?.disable ? { uid: '1' } : (session?.passport?.user || {});
108
+ if (!uid) return null;
109
+
110
+ const loadTable = await getTemplate('table', params.table);
111
+ if (!pg.pk[loadTable?.table || params.table]) return null;
112
+ const pk = pg.pk[loadTable?.table || params.table];
113
+ const id = res[pk];
114
+
115
+ const { rows: properties = [] } = await pg.query(`select column_id, name, title, format, data from admin.custom_column
116
+ where entity=$1 and uid=$2`, [params.table, uid]);
117
+
118
+ if (!id || !properties?.length) return null;
119
+
120
+ const q = `delete from crm.extra_data where property_entity='${params.table}' and object_id='${id}';${properties
121
+ .filter((el) => Object.keys(body).includes(el.name))
122
+ .map((el) => `insert into crm.extra_data(property_id,property_key,property_entity,object_id,${el.format?.toLowerCase() === 'date' ? 'value_date' : 'value_text'})
123
+ select '${el.column_id}', '${el.name}', '${params.table}', '${id}', ${el.format?.toLowerCase() === 'date' ? `'${body[el.name]}'::timestamp without time zone` : `'${body[el.name]}'::text`}`)
124
+ .join(';\n') || ''}`;
125
+ return pg.query(q);
126
+ });
127
+
128
+ addHook('afterInsert', async ({ req, res = {} }) => {
129
+ const {
130
+ pg, funcs, session = {}, params = {}, body = {},
131
+ } = req;
132
+ const { uid } = funcs?.config?.auth?.disable ? { uid: '1' } : (session?.passport?.user || {});
133
+ if (!uid) return null;
134
+
135
+ const loadTable = await getTemplate('table', params.table);
136
+ if (!pg.pk[loadTable?.table || params.table]) return null;
137
+ const pk = pg.pk[loadTable?.table || params.table];
138
+ const id = res.rows?.[0]?.[pk];
139
+
140
+ const { rows: properties = [] } = await pg.query(`select column_id, name, title, format, data from admin.custom_column
141
+ where entity=$1 and uid=$2`, [params.table, uid]);
142
+
143
+ if (!id || !properties?.length) return null;
144
+
145
+ const q = properties
146
+ .filter((el) => Object.keys(body).includes(el.name))
147
+ .map((el) => `insert into crm.extra_data(property_id,property_key,property_entity,object_id,${el.format?.toLowerCase() === 'date' ? 'value_date' : 'value_text'})
148
+ select '${el.column_id}', '${el.name}', '${params.table}', '${id}', ${el.format?.toLowerCase() === 'date' ? `'${body[el.name]}'::timestamp without time zone` : `'${body[el.name]}'::text`}`)
149
+ .join(';\n');
150
+ return pg.query(q);
151
+ });
152
+ }
@@ -1,69 +1,69 @@
1
- import fs from 'fs';
2
- import path, { dirname } from 'path';
3
- import { fileURLToPath } from 'url';
4
-
5
- const dir = dirname(fileURLToPath(import.meta.url));
6
- const root = `${dir}/../..`;
7
-
8
- const isProduction = process.env.NODE_ENV === 'production';
9
-
10
- async function plugin(fastify) {
11
- // vite server
12
- if (!isProduction) {
13
- const vite = await import('vite');
14
-
15
- const viteServer = await vite.createServer({
16
- server: {
17
- middlewareMode: true,
18
- },
19
- });
20
- // hot reload
21
- viteServer.watcher.on('all', function (d, t) {
22
- if (!t.includes('module')) return;
23
- console.log(d, t);
24
- viteServer.ws.send({ type: 'full-reload' });
25
- });
26
-
27
- // this is middleware for vite's dev servert
28
- fastify.addHook('onRequest', async (req, reply) => {
29
- const { user } = req.session?.passport || {};
30
- const { disableAuth } = req.funcs?.config || {};
31
- if (!user && !disableAuth) {
32
- // return reply.send('access restricted');
33
- }
34
-
35
- const next = () => new Promise((resolve) => {
36
- viteServer.middlewares(req.raw, reply.raw, () => resolve());
37
- });
38
- await next();
39
- });
40
- fastify.get('*', async () => { });
41
- return;
42
- }
43
-
44
- // From Build
45
- fastify.get('*', async (req, reply) => {
46
- const { user } = req.session?.passport || {};
47
-
48
- // if (!user) return reply.redirect('/login');
49
- const stream = fs.createReadStream('dist/index.html');
50
- return reply.type('text/html').send(stream);
51
- });
52
-
53
- async function staticFile(req, reply) {
54
- const assetsDir = 'dist';
55
- const filePath = path.join(root, assetsDir, req.url);
56
- const ext = path.extname(filePath);
57
- const mime = {
58
- '.js': 'text/javascript', '.css': 'text/css', '.woff2': 'application/font-woff', '.png': 'image/png', '.svg': 'image/svg+xml', '.jpg': 'image/jpg',
59
- }[ext];
60
- reply.headers({ 'Cache-control': 'max-age=3600, public' });
61
- const stream = fs.createReadStream(filePath);
62
- return mime ? reply.type(mime).send(stream) : stream;
63
- }
64
-
65
- fastify.get('/assets/*', staticFile);
66
- fastify.get('/public/*', staticFile);
67
- }
68
-
69
- export default plugin;
1
+ import fs from 'fs';
2
+ import path, { dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const dir = dirname(fileURLToPath(import.meta.url));
6
+ const root = `${dir}/../..`;
7
+
8
+ const isProduction = process.env.NODE_ENV === 'production';
9
+
10
+ async function plugin(fastify) {
11
+ // vite server
12
+ if (!isProduction) {
13
+ const vite = await import('vite');
14
+
15
+ const viteServer = await vite.createServer({
16
+ server: {
17
+ middlewareMode: true,
18
+ },
19
+ });
20
+ // hot reload
21
+ viteServer.watcher.on('all', function (d, t) {
22
+ if (!t.includes('module')) return;
23
+ console.log(d, t);
24
+ viteServer.ws.send({ type: 'full-reload' });
25
+ });
26
+
27
+ // this is middleware for vite's dev servert
28
+ fastify.addHook('onRequest', async (req, reply) => {
29
+ const { user } = req.session?.passport || {};
30
+ const { disableAuth } = req.funcs?.config || {};
31
+ if (!user && !disableAuth) {
32
+ // return reply.send('access restricted');
33
+ }
34
+
35
+ const next = () => new Promise((resolve) => {
36
+ viteServer.middlewares(req.raw, reply.raw, () => resolve());
37
+ });
38
+ await next();
39
+ });
40
+ fastify.get('*', async () => { });
41
+ return;
42
+ }
43
+
44
+ // From Build
45
+ fastify.get('*', async (req, reply) => {
46
+ const { user } = req.session?.passport || {};
47
+
48
+ if (!user) return reply.redirect('/login');
49
+ const stream = fs.createReadStream('dist/index.html');
50
+ return reply.type('text/html').send(stream);
51
+ });
52
+
53
+ async function staticFile(req, reply) {
54
+ const assetsDir = 'dist';
55
+ const filePath = path.join(root, assetsDir, req.url);
56
+ const ext = path.extname(filePath);
57
+ const mime = {
58
+ '.js': 'text/javascript', '.css': 'text/css', '.woff2': 'application/font-woff', '.png': 'image/png', '.svg': 'image/svg+xml', '.jpg': 'image/jpg',
59
+ }[ext];
60
+ reply.headers({ 'Cache-control': 'max-age=3600, public' });
61
+ const stream = fs.createReadStream(filePath);
62
+ return mime ? reply.type(mime).send(stream) : stream;
63
+ }
64
+
65
+ fastify.get('/assets/*', staticFile);
66
+ fastify.get('/public/*', staticFile);
67
+ }
68
+
69
+ export default plugin;