@opengis/admin 0.4.36 → 0.4.37
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/README.md +97 -97
- package/dist/{add-page-BbGCyn0k.js → add-page-GMWte58m.js} +1 -1
- package/dist/{admin-interface-BbtDg4Fy.js → admin-interface-TLM61JNF.js} +2 -2
- package/dist/{admin-view-BT95LpxW.js → admin-view-BKD-rKqQ.js} +1 -1
- package/dist/admin.js +1 -1
- package/dist/admin.umd.cjs +57 -57
- package/dist/assets/logo.svg +41 -41
- package/dist/{card-view-Cwu20O9Z.js → card-view-CwkJ9Qg2.js} +1 -1
- package/dist/{edit-page-D1ZN9oak.js → edit-page-C_igWB2a.js} +1 -1
- package/dist/{import-file-CGrExq_X.js → import-file-2iB1izw1.js} +11497 -11244
- package/dist/{profile-page-Quk3Xc6g.js → profile-page-Cuy6hkl8.js} +1 -1
- package/dist/style.css +1 -1
- package/module/settings/card/admin.accounts.table/index.yml +7 -7
- package/module/settings/card/admin.accounts.table/rules.hbs +18 -18
- package/module/settings/card/admin.accounts.table/users.hbs +13 -13
- package/module/settings/card/admin.routes.table/groups.hbs +11 -11
- package/module/settings/card/admin.routes.table/users.hbs +16 -16
- package/module/settings/cls/core.actions.json +17 -17
- package/module/settings/cls/core.scope.json +13 -13
- package/module/settings/cls/properties.site_status.json +13 -13
- package/module/settings/cls/properties.widget_status.json +13 -13
- package/module/settings/cls/yes_no.json +11 -11
- package/module/settings/form/admin.accounts.form.json +13 -13
- package/module/settings/form/admin.properties.form.json +15 -15
- package/module/settings/form/admin.roles.form.json +21 -21
- package/module/settings/form/admin.user_properties.form.json +15 -15
- package/module/settings/form/admin.user_roles_card.form.json +13 -13
- package/module/settings/interface/admin.properties.json +4 -4
- package/module/settings/interface/admin.roles.json +4 -4
- package/module/settings/interface/admin.routes.json +4 -4
- package/module/settings/interface/admin.users.json +4 -4
- package/module/settings/select/core.routes.sql +1 -1
- package/module/settings/select/core.user_mentioned.sql +1 -1
- package/module/settings/select/core.user_uid.sql +1 -1
- package/module/settings/table/admin.properties.table.json +39 -39
- package/module/settings/table/admin.user_properties.table.json +34 -34
- package/package.json +1 -1
- package/server/helpers/core/coalesce.js +7 -7
- package/server/helpers/core/select.js +48 -48
- package/server/helpers/core/token.js +18 -18
- package/server/helpers/list/buttonHelper.js +21 -21
- package/server/helpers/list/utils/button.js +5 -5
- package/server/helpers/temp/contentList.js +58 -58
- package/server/helpers/temp/ifCond.js +101 -101
- package/server/helpers/utils/button.js +5 -5
- package/server/helpers/utils/mdToHTML.js +17 -17
- package/server/plugins/cron.js +10 -10
- package/server/plugins/docs.js +28 -28
- package/server/routes/calendar/controllers/calendar.data.js +124 -124
- package/server/routes/calendar/index.mjs +7 -7
- package/server/routes/notifications/controllers/testEmail.js +35 -35
- package/server/routes/notifications/hook/onWidgetSet.js +56 -56
- package/server/routes/notifications/index.mjs +33 -26
- package/server/routes/root.mjs +3 -3
- package/server/routes/user/controllers/user.cls.id.js +14 -14
- package/server/routes/user/controllers/user.cls.js +72 -72
- package/server/routes/user/controllers/user.info.js +17 -17
- package/server/templates/cls/itree.recrzone_category.json +73 -73
- package/server/templates/cls/test.json +9 -9
- package/server/templates/form/admin.user_cls.data.form.json +49 -49
- package/server/templates/form/admin.user_group_rel.form.json +21 -21
- package/server/templates/form/form-user-pass.json +10 -10
- package/server/templates/form/form-user_group.json +39 -39
- package/server/templates/form/form-users.json +156 -156
- package/server/templates/form/user_group_access.form.json +22 -22
- package/server/templates/select/account_id.json +2 -2
- package/server/templates/table/gis.dataset.table.json +43 -43
- package/server/templates/table/management.user_group.table.json +112 -112
- package/server/templates/table/management.users.table.json +126 -126
- package/server/utils/addNotification.js +21 -21
- package/server/utils/sendNotification.js +89 -89
- package/server/routes/notifications/controllers/readNotifications.js +0 -18
- package/server/routes/notifications/controllers/userNotifications.js +0 -53
- package/server/routes/notifications/schema.js +0 -23
|
@@ -1,125 +1,125 @@
|
|
|
1
|
-
import { getMeta, getTemplate, pgClients, handlebarsSync } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
const isValidDate = (dateStr) => (new Date(dateStr)).toString() !== 'Invalid Date';
|
|
4
|
-
|
|
5
|
-
export default async function calendarData({
|
|
6
|
-
pg = pgClients.client, params = {}, query = {}, user = {},
|
|
7
|
-
}) {
|
|
8
|
-
const { name } = params;
|
|
9
|
-
const { granularity = 'month' } = query;
|
|
10
|
-
|
|
11
|
-
if (!name) {
|
|
12
|
-
return { message: 'not enough params: name', status: 400 };
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (query.granularity && !['day', 'month', 'week', 'year'].includes(granularity)) {
|
|
16
|
-
return { message: 'invalid query params: granularity', status: 400 };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const body = await getTemplate('calendar', name);
|
|
20
|
-
|
|
21
|
-
if (!body) {
|
|
22
|
-
return { message: `calendar not found: ${name}`, status: 404 };
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const {
|
|
26
|
-
title,
|
|
27
|
-
table,
|
|
28
|
-
meta = {},
|
|
29
|
-
} = body || {};
|
|
30
|
-
|
|
31
|
-
if (!table) {
|
|
32
|
-
return { message: 'not enough calendar params: table', status: 404 };
|
|
33
|
-
}
|
|
34
|
-
if (!pg.pk?.[table]) {
|
|
35
|
-
return { message: `table pkey not found: ${table}`, status: 404 };
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const filterList = (body?.filter || [])
|
|
39
|
-
.concat(body?.filterInline || [])
|
|
40
|
-
.concat(body?.filterCustom || [])
|
|
41
|
-
.concat(body?.filterState || [])
|
|
42
|
-
.concat(body?.filterList || [])
|
|
43
|
-
.concat(body?.filters || [])
|
|
44
|
-
.concat(body?.filter_list || []);
|
|
45
|
-
|
|
46
|
-
const { columns = [] } = await getMeta({ pg, table });
|
|
47
|
-
const columnList = columns?.map((el) => el?.name);
|
|
48
|
-
|
|
49
|
-
const dateColumn = columns?.find((el) => el?.name === (meta?.date || meta?.start))?.name
|
|
50
|
-
|| columns?.find((el) => el?.name === 'cdate')?.name;
|
|
51
|
-
|
|
52
|
-
if (query.date && !dateColumn) {
|
|
53
|
-
return { message: 'invalid template params: date column not found', status: 400 };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (query.date && !isValidDate(query.date)) {
|
|
57
|
-
return { message: 'Invalid date: out of range or incorrect format', status: 400 };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const filterWhere = filterList?.length && query.filter?.length
|
|
61
|
-
? filterList
|
|
62
|
-
.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true))
|
|
63
|
-
.map((el) => {
|
|
64
|
-
const val = query.filter.split(',').find((e) => e?.split('=')?.shift()?.includes(el.column || el.name))?.split('=')?.pop();
|
|
65
|
-
if (val) return el.column && val ? `(${[`${el.column}::text='${val.replace(/'/g, "''")}'::text`, el.query].filter((el) => el).join(' and ')})` : el.query;
|
|
66
|
-
})
|
|
67
|
-
.filter((el) => el)
|
|
68
|
-
.join(' and ')
|
|
69
|
-
: undefined;
|
|
70
|
-
|
|
71
|
-
const queryWhere = handlebarsSync.compile(body.query || '1=1')({ user, uid: user?.uid });
|
|
72
|
-
const filterDate = query.date ? `date_trunc('${granularity}', "${dateColumn}"::date)='${query.date}'::date` : undefined;
|
|
73
|
-
|
|
74
|
-
const where = [queryWhere, filterDate, filterWhere].filter((el) => el).join(' and ');
|
|
75
|
-
|
|
76
|
-
const filtersByColumn = filterList.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true) && el?.column);
|
|
77
|
-
|
|
78
|
-
const filters = [];
|
|
79
|
-
if (filtersByColumn?.length) {
|
|
80
|
-
await Promise.all(filtersByColumn.map(async (el) => {
|
|
81
|
-
const { rows: filterData = [] } = await pg.query(`select ${el.column.replace(/'/g, "''")} as id, count(*) from ${table}
|
|
82
|
-
where ${el.query || '1=1'} and ${filterWhere || '1=1'} group by ${el.column.replace(/'/g, "''")}`);
|
|
83
|
-
if (!filterData?.length) return;
|
|
84
|
-
|
|
85
|
-
const clsData = await getTemplate(['cls', 'select'], el.cls);
|
|
86
|
-
|
|
87
|
-
if (!el.cls || !clsData?.length) {
|
|
88
|
-
filterData.forEach((item) => filters.push(item));
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
filterData.forEach((filter) => {
|
|
93
|
-
const cls = clsData.find((item) => item.id === filter.id.toString());
|
|
94
|
-
Object.assign(filter, { title: cls?.text, color: cls?.color });
|
|
95
|
-
filters.push(filter);
|
|
96
|
-
});
|
|
97
|
-
}));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const filtersByPreparedQuery = filterList.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true) && !el?.column && el?.query);
|
|
101
|
-
|
|
102
|
-
if (filtersByPreparedQuery?.length) {
|
|
103
|
-
await Promise.all(filtersByPreparedQuery.map(async (el) => {
|
|
104
|
-
const { rows = [] } = await pg.query(`select ${el.query} as id, count(*) from ${table}
|
|
105
|
-
where ${filterWhere || '1=1'} group by ${el.query}`);
|
|
106
|
-
rows.forEach((item) => filters.push(item));
|
|
107
|
-
}));
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const metaColumns = Object.keys(meta)
|
|
111
|
-
.filter((el) => ['date', 'start', 'end', 'title', 'status'].includes(el) && columnList.includes(meta[el]))
|
|
112
|
-
.map((el) => `"${meta[el]}" as ${el}`);
|
|
113
|
-
|
|
114
|
-
if (!metaColumns?.length) {
|
|
115
|
-
return { message: `calendar param meta is invalid: invalid/empty keys`, status: 404 };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const q = `select ${metaColumns.join(',')} from ${table} where ${where}`;
|
|
119
|
-
if (query?.sql && user?.user_type?.includes('admin')) return q;
|
|
120
|
-
|
|
121
|
-
const { rows = [] } = await pg.query(q);
|
|
122
|
-
|
|
123
|
-
return { title, filters, granularity, sql: user?.user_type?.includes('admin') ? q : undefined, rows };
|
|
124
|
-
|
|
1
|
+
import { getMeta, getTemplate, pgClients, handlebarsSync } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
const isValidDate = (dateStr) => (new Date(dateStr)).toString() !== 'Invalid Date';
|
|
4
|
+
|
|
5
|
+
export default async function calendarData({
|
|
6
|
+
pg = pgClients.client, params = {}, query = {}, user = {},
|
|
7
|
+
}) {
|
|
8
|
+
const { name } = params;
|
|
9
|
+
const { granularity = 'month' } = query;
|
|
10
|
+
|
|
11
|
+
if (!name) {
|
|
12
|
+
return { message: 'not enough params: name', status: 400 };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (query.granularity && !['day', 'month', 'week', 'year'].includes(granularity)) {
|
|
16
|
+
return { message: 'invalid query params: granularity', status: 400 };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const body = await getTemplate('calendar', name);
|
|
20
|
+
|
|
21
|
+
if (!body) {
|
|
22
|
+
return { message: `calendar not found: ${name}`, status: 404 };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
title,
|
|
27
|
+
table,
|
|
28
|
+
meta = {},
|
|
29
|
+
} = body || {};
|
|
30
|
+
|
|
31
|
+
if (!table) {
|
|
32
|
+
return { message: 'not enough calendar params: table', status: 404 };
|
|
33
|
+
}
|
|
34
|
+
if (!pg.pk?.[table]) {
|
|
35
|
+
return { message: `table pkey not found: ${table}`, status: 404 };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const filterList = (body?.filter || [])
|
|
39
|
+
.concat(body?.filterInline || [])
|
|
40
|
+
.concat(body?.filterCustom || [])
|
|
41
|
+
.concat(body?.filterState || [])
|
|
42
|
+
.concat(body?.filterList || [])
|
|
43
|
+
.concat(body?.filters || [])
|
|
44
|
+
.concat(body?.filter_list || []);
|
|
45
|
+
|
|
46
|
+
const { columns = [] } = await getMeta({ pg, table });
|
|
47
|
+
const columnList = columns?.map((el) => el?.name);
|
|
48
|
+
|
|
49
|
+
const dateColumn = columns?.find((el) => el?.name === (meta?.date || meta?.start))?.name
|
|
50
|
+
|| columns?.find((el) => el?.name === 'cdate')?.name;
|
|
51
|
+
|
|
52
|
+
if (query.date && !dateColumn) {
|
|
53
|
+
return { message: 'invalid template params: date column not found', status: 400 };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (query.date && !isValidDate(query.date)) {
|
|
57
|
+
return { message: 'Invalid date: out of range or incorrect format', status: 400 };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const filterWhere = filterList?.length && query.filter?.length
|
|
61
|
+
? filterList
|
|
62
|
+
.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true))
|
|
63
|
+
.map((el) => {
|
|
64
|
+
const val = query.filter.split(',').find((e) => e?.split('=')?.shift()?.includes(el.column || el.name))?.split('=')?.pop();
|
|
65
|
+
if (val) return el.column && val ? `(${[`${el.column}::text='${val.replace(/'/g, "''")}'::text`, el.query].filter((el) => el).join(' and ')})` : el.query;
|
|
66
|
+
})
|
|
67
|
+
.filter((el) => el)
|
|
68
|
+
.join(' and ')
|
|
69
|
+
: undefined;
|
|
70
|
+
|
|
71
|
+
const queryWhere = handlebarsSync.compile(body.query || '1=1')({ user, uid: user?.uid });
|
|
72
|
+
const filterDate = query.date ? `date_trunc('${granularity}', "${dateColumn}"::date)='${query.date}'::date` : undefined;
|
|
73
|
+
|
|
74
|
+
const where = [queryWhere, filterDate, filterWhere].filter((el) => el).join(' and ');
|
|
75
|
+
|
|
76
|
+
const filtersByColumn = filterList.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true) && el?.column);
|
|
77
|
+
|
|
78
|
+
const filters = [];
|
|
79
|
+
if (filtersByColumn?.length) {
|
|
80
|
+
await Promise.all(filtersByColumn.map(async (el) => {
|
|
81
|
+
const { rows: filterData = [] } = await pg.query(`select ${el.column.replace(/'/g, "''")} as id, count(*) from ${table}
|
|
82
|
+
where ${el.query || '1=1'} and ${filterWhere || '1=1'} group by ${el.column.replace(/'/g, "''")}`);
|
|
83
|
+
if (!filterData?.length) return;
|
|
84
|
+
|
|
85
|
+
const clsData = await getTemplate(['cls', 'select'], el.cls);
|
|
86
|
+
|
|
87
|
+
if (!el.cls || !clsData?.length) {
|
|
88
|
+
filterData.forEach((item) => filters.push(item));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
filterData.forEach((filter) => {
|
|
93
|
+
const cls = clsData.find((item) => item.id === filter.id.toString());
|
|
94
|
+
Object.assign(filter, { title: cls?.text, color: cls?.color });
|
|
95
|
+
filters.push(filter);
|
|
96
|
+
});
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const filtersByPreparedQuery = filterList.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true) && !el?.column && el?.query);
|
|
101
|
+
|
|
102
|
+
if (filtersByPreparedQuery?.length) {
|
|
103
|
+
await Promise.all(filtersByPreparedQuery.map(async (el) => {
|
|
104
|
+
const { rows = [] } = await pg.query(`select ${el.query} as id, count(*) from ${table}
|
|
105
|
+
where ${filterWhere || '1=1'} group by ${el.query}`);
|
|
106
|
+
rows.forEach((item) => filters.push(item));
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const metaColumns = Object.keys(meta)
|
|
111
|
+
.filter((el) => ['date', 'start', 'end', 'title', 'status'].includes(el) && columnList.includes(meta[el]))
|
|
112
|
+
.map((el) => `"${meta[el]}" as ${el}`);
|
|
113
|
+
|
|
114
|
+
if (!metaColumns?.length) {
|
|
115
|
+
return { message: `calendar param meta is invalid: invalid/empty keys`, status: 404 };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const q = `select ${metaColumns.join(',')} from ${table} where ${where}`;
|
|
119
|
+
if (query?.sql && user?.user_type?.includes('admin')) return q;
|
|
120
|
+
|
|
121
|
+
const { rows = [] } = await pg.query(q);
|
|
122
|
+
|
|
123
|
+
return { title, filters, granularity, sql: user?.user_type?.includes('admin') ? q : undefined, rows };
|
|
124
|
+
|
|
125
125
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import calendarData from "./controllers/calendar.data.js";
|
|
2
|
-
|
|
3
|
-
import { calendarDataSchema } from './schema.js';
|
|
4
|
-
|
|
5
|
-
export default async function route(fastify) {
|
|
6
|
-
fastify.get('/calendar/:name', { schema: calendarDataSchema }, calendarData);
|
|
7
|
-
}
|
|
1
|
+
import calendarData from "./controllers/calendar.data.js";
|
|
2
|
+
|
|
3
|
+
import { calendarDataSchema } from './schema.js';
|
|
4
|
+
|
|
5
|
+
export default async function route(fastify) {
|
|
6
|
+
fastify.get('/calendar/:name', { schema: calendarDataSchema }, calendarData);
|
|
7
|
+
}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import { config } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
import { sendNotification } from '../../../../utils.js';
|
|
4
|
-
|
|
5
|
-
export default async function testNotification({
|
|
6
|
-
pg, query = {}, user = {},
|
|
7
|
-
}) {
|
|
8
|
-
const { local } = config || {};
|
|
9
|
-
|
|
10
|
-
if (!user?.user_type?.includes('admin') && !local) {
|
|
11
|
-
return { message: 'Forbidden', status: 403 };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const date = new Date().toISOString().split('T')[0];
|
|
15
|
-
if (!query.to) {
|
|
16
|
-
return { message: 'param to is required', status: 400 };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const {
|
|
20
|
-
to, template, table, id, nocache,
|
|
21
|
-
} = query;
|
|
22
|
-
|
|
23
|
-
const data = await sendNotification({
|
|
24
|
-
pg,
|
|
25
|
-
to,
|
|
26
|
-
template,
|
|
27
|
-
title: `Test Softpro ${date}`,
|
|
28
|
-
table,
|
|
29
|
-
nocache,
|
|
30
|
-
id,
|
|
31
|
-
message: `Test mail Softpro ${date} Lorem Ipsum Lorem Ipsum`,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
return { message: data || 'ok' };
|
|
35
|
-
}
|
|
1
|
+
import { config } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
import { sendNotification } from '../../../../utils.js';
|
|
4
|
+
|
|
5
|
+
export default async function testNotification({
|
|
6
|
+
pg, query = {}, user = {},
|
|
7
|
+
}) {
|
|
8
|
+
const { local } = config || {};
|
|
9
|
+
|
|
10
|
+
if (!user?.user_type?.includes('admin') && !local) {
|
|
11
|
+
return { message: 'Forbidden', status: 403 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const date = new Date().toISOString().split('T')[0];
|
|
15
|
+
if (!query.to) {
|
|
16
|
+
return { message: 'param to is required', status: 400 };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
to, template, table, id, nocache,
|
|
21
|
+
} = query;
|
|
22
|
+
|
|
23
|
+
const data = await sendNotification({
|
|
24
|
+
pg,
|
|
25
|
+
to,
|
|
26
|
+
template,
|
|
27
|
+
title: `Test Softpro ${date}`,
|
|
28
|
+
table,
|
|
29
|
+
nocache,
|
|
30
|
+
id,
|
|
31
|
+
message: `Test mail Softpro ${date} Lorem Ipsum Lorem Ipsum`,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return { message: data || 'ok' };
|
|
35
|
+
}
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
/* eslint-disable camelcase */
|
|
2
|
-
import { config, pgClients, getSelect } from '@opengis/fastify-table/utils.js';
|
|
3
|
-
|
|
4
|
-
import { addNotification, sendNotification } from '../../../../utils.js';
|
|
5
|
-
|
|
6
|
-
function sequence(arr, data, fn) {
|
|
7
|
-
return arr.reduce((promise, row) => promise.then(() => fn({
|
|
8
|
-
...data, ...row,
|
|
9
|
-
})), Promise.resolve());
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default async function onWidgetSet({ pg = pgClients?.client, link, user, type, payload: data = {} }) {
|
|
13
|
-
const values = data.body?.match(/\B@[a-zA-z0-9а-яА-яіїІЇєЄ]+ [a-zA-z0-9а-яА-яіїІЇєЄ]+/g)
|
|
14
|
-
?.filter((el, idx, arr) => el?.replace && arr.indexOf(el) === idx)
|
|
15
|
-
?.map((el) => el.replace(/@/g, ''));
|
|
16
|
-
|
|
17
|
-
if (type !== 'comment' || !values?.length) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const { sql } = await getSelect('core.user_mentioned');
|
|
22
|
-
|
|
23
|
-
const { rows = [] } = await pg.query(`with data (id,name,email) as (${sql})
|
|
24
|
-
select id, name, email from data where name = any($1)`, [values]);
|
|
25
|
-
|
|
26
|
-
if (!rows?.length) {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const message = `${data.body?.substring(0, 50)}...`;
|
|
31
|
-
const subject = 'You were mentioned';
|
|
32
|
-
|
|
33
|
-
await sequence(rows, {}, async ({ id, name, email }) => {
|
|
34
|
-
const res = await addNotification({
|
|
35
|
-
pg, user, subject, entity: data.entity_id, body: message, link, uid: id,
|
|
36
|
-
});
|
|
37
|
-
try {
|
|
38
|
-
const res1 = await sendNotification({
|
|
39
|
-
pg,
|
|
40
|
-
to: email,
|
|
41
|
-
// template,
|
|
42
|
-
message,
|
|
43
|
-
title: subject,
|
|
44
|
-
data,
|
|
45
|
-
nocache: 1,
|
|
46
|
-
});
|
|
47
|
-
if (config.local) console.info('comment notification', name, id, email, res1);
|
|
48
|
-
await pg.query('update crm.notifications set sent=true where notification_id=$1', [res?.notification_id]);
|
|
49
|
-
}
|
|
50
|
-
catch (err) {
|
|
51
|
-
console.error('comment notification send error', err.toString());
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
console.log('comment notification add', rows);
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
import { config, pgClients, getSelect } from '@opengis/fastify-table/utils.js';
|
|
3
|
+
|
|
4
|
+
import { addNotification, sendNotification } from '../../../../utils.js';
|
|
5
|
+
|
|
6
|
+
function sequence(arr, data, fn) {
|
|
7
|
+
return arr.reduce((promise, row) => promise.then(() => fn({
|
|
8
|
+
...data, ...row,
|
|
9
|
+
})), Promise.resolve());
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default async function onWidgetSet({ pg = pgClients?.client, link, user, type, payload: data = {} }) {
|
|
13
|
+
const values = data.body?.match(/\B@[a-zA-z0-9а-яА-яіїІЇєЄ]+ [a-zA-z0-9а-яА-яіїІЇєЄ]+/g)
|
|
14
|
+
?.filter((el, idx, arr) => el?.replace && arr.indexOf(el) === idx)
|
|
15
|
+
?.map((el) => el.replace(/@/g, ''));
|
|
16
|
+
|
|
17
|
+
if (type !== 'comment' || !values?.length) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { sql } = await getSelect('core.user_mentioned');
|
|
22
|
+
|
|
23
|
+
const { rows = [] } = await pg.query(`with data (id,name,email) as (${sql})
|
|
24
|
+
select id, name, email from data where name = any($1)`, [values]);
|
|
25
|
+
|
|
26
|
+
if (!rows?.length) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const message = `${data.body?.substring(0, 50)}...`;
|
|
31
|
+
const subject = 'You were mentioned';
|
|
32
|
+
|
|
33
|
+
await sequence(rows, {}, async ({ id, name, email }) => {
|
|
34
|
+
const res = await addNotification({
|
|
35
|
+
pg, user, subject, entity: data.entity_id, body: message, link, uid: id,
|
|
36
|
+
});
|
|
37
|
+
try {
|
|
38
|
+
const res1 = await sendNotification({
|
|
39
|
+
pg,
|
|
40
|
+
to: email,
|
|
41
|
+
// template,
|
|
42
|
+
message,
|
|
43
|
+
title: subject,
|
|
44
|
+
data,
|
|
45
|
+
nocache: 1,
|
|
46
|
+
});
|
|
47
|
+
if (config.local) console.info('comment notification', name, id, email, res1);
|
|
48
|
+
await pg.query('update crm.notifications set sent=true where notification_id=$1', [res?.notification_id]);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
console.error('comment notification send error', err.toString());
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
console.log('comment notification add', rows);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
@@ -1,26 +1,33 @@
|
|
|
1
|
-
import { addHook } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
// api
|
|
4
|
-
import testEmail from './controllers/testEmail.js';
|
|
5
|
-
import readNotifications from './controllers/readNotifications.js'; // mark as read
|
|
6
|
-
import userNotifications from './controllers/userNotifications.js'; // check all, backend pagination
|
|
7
|
-
|
|
8
|
-
// hook
|
|
9
|
-
import onWidgetSet from './hook/onWidgetSet.js'; // send notification on comment
|
|
10
|
-
|
|
11
|
-
// funcs
|
|
12
|
-
// import addNotification from '../notifications/funcs/addNotification.js'; // add to db
|
|
13
|
-
// import notification from '../notifications/funcs/sendNotification.js'; // send notification
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
import { addHook } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
// api
|
|
4
|
+
import testEmail from './controllers/testEmail.js';
|
|
5
|
+
// import readNotifications from './controllers/readNotifications.js'; // mark as read
|
|
6
|
+
// import userNotifications from './controllers/userNotifications.js'; // check all, backend pagination
|
|
7
|
+
|
|
8
|
+
// hook
|
|
9
|
+
import onWidgetSet from './hook/onWidgetSet.js'; // send notification on comment
|
|
10
|
+
|
|
11
|
+
// funcs
|
|
12
|
+
// import addNotification from '../notifications/funcs/addNotification.js'; // add to db
|
|
13
|
+
// import notification from '../notifications/funcs/sendNotification.js'; // send notification
|
|
14
|
+
|
|
15
|
+
const emailSchema = {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
quertstring: {
|
|
19
|
+
to: { type: 'string', pattern: '^((?!\\.)[\\w\\-_.]*[^.])(@\\w+)(\\.\\w+(\\.\\w+)?[^.\\W])$' },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default async function route(fastify) {
|
|
25
|
+
|
|
26
|
+
// fastify.decorate('addNotification', addNotification);
|
|
27
|
+
// fastify.decorate('notification', notification);
|
|
28
|
+
|
|
29
|
+
fastify.get('/test-email', { config: { policy: ['user'] }, schema: emailSchema }, testEmail);
|
|
30
|
+
// fastify.get('/notification', { config: { policy: ['user'] }, schema: notificationSchema }, userNotifications); // moved to fastify-table
|
|
31
|
+
// fastify.get('/notification-read/:id?', { config: { policy: ['user'] }, schema: notificationSchema }, readNotifications); // moved to fastify-table
|
|
32
|
+
addHook('onWidgetSet', onWidgetSet);
|
|
33
|
+
}
|
package/server/routes/root.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export default async function (fastify, opts) {
|
|
2
|
-
fastify.get(`/test`, () => { return { test: true } });
|
|
3
|
-
}
|
|
1
|
+
export default async function (fastify, opts) {
|
|
2
|
+
fastify.get(`/test`, () => { return { test: true } });
|
|
3
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import userCls from './user.cls.js';
|
|
2
|
-
|
|
3
|
-
export default async function userClsId(req) {
|
|
4
|
-
const { id } = req.params || {};
|
|
5
|
-
const res = await userCls(req);
|
|
6
|
-
if (req.query?.sql || res?.error) {
|
|
7
|
-
return res;
|
|
8
|
-
}
|
|
9
|
-
const { rows = [] } = res?.message || {};
|
|
10
|
-
if (!rows?.length) {
|
|
11
|
-
return { message: `cls not found: ${id}`, status: 404 };
|
|
12
|
-
}
|
|
13
|
-
return { message: rows?.[0], status: 200 };
|
|
14
|
-
}
|
|
1
|
+
import userCls from './user.cls.js';
|
|
2
|
+
|
|
3
|
+
export default async function userClsId(req) {
|
|
4
|
+
const { id } = req.params || {};
|
|
5
|
+
const res = await userCls(req);
|
|
6
|
+
if (req.query?.sql || res?.error) {
|
|
7
|
+
return res;
|
|
8
|
+
}
|
|
9
|
+
const { rows = [] } = res?.message || {};
|
|
10
|
+
if (!rows?.length) {
|
|
11
|
+
return { message: `cls not found: ${id}`, status: 404 };
|
|
12
|
+
}
|
|
13
|
+
return { message: rows?.[0], status: 200 };
|
|
14
|
+
}
|