@opengis/admin 0.3.117 → 0.3.119
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/config.js +4 -4
- package/dist/{add-page-D0ed-dNM.js → add-page-fdr6t9-i.js} +1 -1
- package/dist/{admin-interface-C5aCSsqj.js → admin-interface-bYzTXuVs.js} +2 -2
- package/dist/{admin-view-X6ZS7IvV.js → admin-view-3hBO0cXK.js} +1 -1
- package/dist/admin.js +1 -1
- package/dist/admin.umd.cjs +47 -47
- package/dist/assets/logo.svg +41 -41
- package/dist/{card-view-Bs0tW4Ry.js → card-view-Dfgoq-T0.js} +1 -1
- package/dist/{edit-page-BtGxSoh_.js → edit-page-pykfh5fh.js} +1 -1
- package/dist/{import-file-DkbpNIPX.js → import-file-DPcs2POV.js} +4987 -4995
- package/dist/{profile-page-DmxAaYaO.js → profile-page-UeVwkn5K.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 +3 -3
- package/plugin.js +3 -3
- 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/descriptionList.js +1 -1
- 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/access/index.mjs +6 -6
- package/server/plugins/adminHook.js +81 -81
- package/server/plugins/cron.js +10 -10
- package/server/plugins/docs.js +28 -28
- package/server/plugins/hook.js +1 -2
- package/server/routes/access/controllers/access.group.js +29 -29
- package/server/routes/access/controllers/access.group.post.js +54 -54
- package/server/routes/access/index.mjs +11 -11
- package/server/routes/access/schema.mjs +67 -67
- package/server/routes/calendar/controllers/calendar.data.js +125 -125
- package/server/routes/calendar/index.mjs +7 -7
- package/server/routes/calendar/schema.js +21 -21
- package/server/routes/notifications/controllers/readNotifications.js +18 -18
- package/server/routes/notifications/controllers/testEmail.js +35 -35
- package/server/routes/notifications/controllers/userNotifications.js +53 -53
- package/server/routes/notifications/hook/onWidgetSet.js +56 -56
- package/server/routes/notifications/index.mjs +26 -26
- package/server/routes/notifications/schema.js +16 -16
- package/server/routes/properties/schema.js +10 -10
- package/server/routes/report/controllers/list.js +23 -23
- package/server/routes/report/index.mjs +9 -9
- package/server/routes/report/utils/formatValue.js +179 -179
- 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/routes/user/schema.js +14 -14
- package/server/routes/util/controllers/code.generator.js +89 -89
- package/server/routes/widget/controllers/widget.del.js +80 -80
- package/server/routes/widget/controllers/widget.set.js +101 -101
- package/server/routes/widget/hook/onWidgetSet.js +12 -12
- package/server/routes/widget/index.mjs +20 -20
- package/server/routes/widget/schema.js +12 -12
- 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/data/controllers/cardData.js +0 -132
- package/server/routes/data/controllers/cardTabData.js +0 -50
- package/server/routes/data/controllers/funcs/getFilterSQL/index.js +0 -92
- package/server/routes/data/controllers/funcs/getFilterSQL/util/formatValue.js +0 -170
- package/server/routes/data/controllers/funcs/getFilterSQL/util/getCustomQuery.js +0 -13
- package/server/routes/data/controllers/funcs/getFilterSQL/util/getFilterQuery.js +0 -64
- package/server/routes/data/controllers/funcs/getFilterSQL/util/getOptimizedQuery.js +0 -12
- package/server/routes/data/controllers/funcs/getFilterSQL/util/getTableSql.js +0 -34
- package/server/routes/data/controllers/tableData.js +0 -45
- package/server/routes/data/controllers/tableDataId.js +0 -28
- package/server/routes/data/controllers/tableFilter.js +0 -10
- package/server/routes/data/controllers/tableInfo.js +0 -112
- package/server/routes/data/controllers/tokenInfo.js +0 -10
- package/server/routes/data/controllers/utils/assignTokens.js +0 -31
- package/server/routes/data/controllers/utils/conditions.js +0 -21
- package/server/routes/data/controllers/utils/getColumns.js +0 -9
- package/server/routes/data/index.mjs +0 -20
- package/server/routes/data/schema.js +0 -54
- package/server/routes/menu/controllers/getMenu.js +0 -81
- package/server/routes/menu/controllers/interfaces.js +0 -21
- package/server/routes/menu/index.mjs +0 -7
- package/server/routes/menu/schema.js +0 -0
- package/server/routes/templates/controllers/getTemplate.js +0 -45
- package/server/routes/templates/index.mjs +0 -16
- package/server/routes/templates/schema.js +0 -9
@@ -1,126 +1,126 @@
|
|
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 = {}, session = {},
|
7
|
-
}) {
|
8
|
-
const { name } = params;
|
9
|
-
const { granularity = 'month' } = query;
|
10
|
-
const { user = {} } = session.passport || {};
|
11
|
-
|
12
|
-
if (!name) {
|
13
|
-
return { message: 'not enough params: name', status: 400 };
|
14
|
-
}
|
15
|
-
|
16
|
-
if (query.granularity && !['day', 'month', 'week', 'year'].includes(granularity)) {
|
17
|
-
return { message: 'invalid query params: granularity', status: 400 };
|
18
|
-
}
|
19
|
-
|
20
|
-
const body = await getTemplate('calendar', name);
|
21
|
-
|
22
|
-
if (!body) {
|
23
|
-
return { message: `calendar not found: ${name}`, status: 404 };
|
24
|
-
}
|
25
|
-
|
26
|
-
const {
|
27
|
-
title,
|
28
|
-
table,
|
29
|
-
meta = {},
|
30
|
-
} = body || {};
|
31
|
-
|
32
|
-
if (!table) {
|
33
|
-
return { message: 'not enough calendar params: table', status: 404 };
|
34
|
-
}
|
35
|
-
if (!pg.pk?.[table]) {
|
36
|
-
return { message: `table pkey not found: ${table}`, status: 404 };
|
37
|
-
}
|
38
|
-
|
39
|
-
const filterList = (body?.filter || [])
|
40
|
-
.concat(body?.filterInline || [])
|
41
|
-
.concat(body?.filterCustom || [])
|
42
|
-
.concat(body?.filterState || [])
|
43
|
-
.concat(body?.filterList || [])
|
44
|
-
.concat(body?.filters || [])
|
45
|
-
.concat(body?.filter_list || []);
|
46
|
-
|
47
|
-
const { columns = [] } = await getMeta({ pg, table });
|
48
|
-
const columnList = columns?.map((el) => el?.name);
|
49
|
-
|
50
|
-
const dateColumn = columns?.find((el) => el?.name === (meta?.date || meta?.start))?.name
|
51
|
-
|| columns?.find((el) => el?.name === 'cdate')?.name;
|
52
|
-
|
53
|
-
if (query.date && !dateColumn) {
|
54
|
-
return { message: 'invalid template params: date column not found', status: 400 };
|
55
|
-
}
|
56
|
-
|
57
|
-
if (query.date && !isValidDate(query.date)) {
|
58
|
-
return { message: 'Invalid date: out of range or incorrect format', status: 400 };
|
59
|
-
}
|
60
|
-
|
61
|
-
const filterWhere = filterList?.length && query.filter?.length
|
62
|
-
? filterList
|
63
|
-
.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true))
|
64
|
-
.map((el) => {
|
65
|
-
const val = query.filter.split(',').find((e) => e?.split('=')?.shift()?.includes(el.column || el.name))?.split('=')?.pop();
|
66
|
-
if (val) return el.column && val ? `(${[`${el.column}::text='${val.replace(/'/g, "''")}'::text`, el.query].filter((el) => el).join(' and ')})` : el.query;
|
67
|
-
})
|
68
|
-
.filter((el) => el)
|
69
|
-
.join(' and ')
|
70
|
-
: undefined;
|
71
|
-
|
72
|
-
const queryWhere = handlebarsSync.compile(body.query || '1=1')({ user, uid: user?.uid });
|
73
|
-
const filterDate = query.date ? `date_trunc('${granularity}', "${dateColumn}"::date)='${query.date}'::date` : undefined;
|
74
|
-
|
75
|
-
const where = [queryWhere, filterDate, filterWhere].filter((el) => el).join(' and ');
|
76
|
-
|
77
|
-
const filtersByColumn = filterList.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true) && el?.column);
|
78
|
-
|
79
|
-
const filters = [];
|
80
|
-
if (filtersByColumn?.length) {
|
81
|
-
await Promise.all(filtersByColumn.map(async (el) => {
|
82
|
-
const { rows: filterData = [] } = await pg.query(`select ${el.column.replace(/'/g, "''")} as id, count(*) from ${table}
|
83
|
-
where ${el.query || '1=1'} and ${filterWhere || '1=1'} group by ${el.column.replace(/'/g, "''")}`);
|
84
|
-
if (!filterData?.length) return;
|
85
|
-
|
86
|
-
const clsData = await getTemplate(['cls', 'select'], el.cls);
|
87
|
-
|
88
|
-
if (!el.cls || !clsData?.length) {
|
89
|
-
filterData.forEach((item) => filters.push(item));
|
90
|
-
return;
|
91
|
-
}
|
92
|
-
|
93
|
-
filterData.forEach((filter) => {
|
94
|
-
const cls = clsData.find((item) => item.id === filter.id.toString());
|
95
|
-
Object.assign(filter, { title: cls?.text, color: cls?.color });
|
96
|
-
filters.push(filter);
|
97
|
-
});
|
98
|
-
}));
|
99
|
-
}
|
100
|
-
|
101
|
-
const filtersByPreparedQuery = filterList.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true) && !el?.column && el?.query);
|
102
|
-
|
103
|
-
if (filtersByPreparedQuery?.length) {
|
104
|
-
await Promise.all(filtersByPreparedQuery.map(async (el) => {
|
105
|
-
const { rows = [] } = await pg.query(`select ${el.query} as id, count(*) from ${table}
|
106
|
-
where ${filterWhere || '1=1'} group by ${el.query}`);
|
107
|
-
rows.forEach((item) => filters.push(item));
|
108
|
-
}));
|
109
|
-
}
|
110
|
-
|
111
|
-
const metaColumns = Object.keys(meta)
|
112
|
-
.filter((el) => ['date', 'start', 'end', 'title', 'status'].includes(el) && columnList.includes(meta[el]))
|
113
|
-
.map((el) => `"${meta[el]}" as ${el}`);
|
114
|
-
|
115
|
-
if (!metaColumns?.length) {
|
116
|
-
return { message: `calendar param meta is invalid: invalid/empty keys`, status: 404 };
|
117
|
-
}
|
118
|
-
|
119
|
-
const q = `select ${metaColumns.join(',')} from ${table} where ${where}`;
|
120
|
-
if (query?.sql && user?.user_type?.includes('admin')) return q;
|
121
|
-
|
122
|
-
const { rows = [] } = await pg.query(q);
|
123
|
-
|
124
|
-
return { title, filters, granularity, sql: user?.user_type?.includes('admin') ? q : undefined, rows };
|
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 = {}, session = {},
|
7
|
+
}) {
|
8
|
+
const { name } = params;
|
9
|
+
const { granularity = 'month' } = query;
|
10
|
+
const { user = {} } = session.passport || {};
|
11
|
+
|
12
|
+
if (!name) {
|
13
|
+
return { message: 'not enough params: name', status: 400 };
|
14
|
+
}
|
15
|
+
|
16
|
+
if (query.granularity && !['day', 'month', 'week', 'year'].includes(granularity)) {
|
17
|
+
return { message: 'invalid query params: granularity', status: 400 };
|
18
|
+
}
|
19
|
+
|
20
|
+
const body = await getTemplate('calendar', name);
|
21
|
+
|
22
|
+
if (!body) {
|
23
|
+
return { message: `calendar not found: ${name}`, status: 404 };
|
24
|
+
}
|
25
|
+
|
26
|
+
const {
|
27
|
+
title,
|
28
|
+
table,
|
29
|
+
meta = {},
|
30
|
+
} = body || {};
|
31
|
+
|
32
|
+
if (!table) {
|
33
|
+
return { message: 'not enough calendar params: table', status: 404 };
|
34
|
+
}
|
35
|
+
if (!pg.pk?.[table]) {
|
36
|
+
return { message: `table pkey not found: ${table}`, status: 404 };
|
37
|
+
}
|
38
|
+
|
39
|
+
const filterList = (body?.filter || [])
|
40
|
+
.concat(body?.filterInline || [])
|
41
|
+
.concat(body?.filterCustom || [])
|
42
|
+
.concat(body?.filterState || [])
|
43
|
+
.concat(body?.filterList || [])
|
44
|
+
.concat(body?.filters || [])
|
45
|
+
.concat(body?.filter_list || []);
|
46
|
+
|
47
|
+
const { columns = [] } = await getMeta({ pg, table });
|
48
|
+
const columnList = columns?.map((el) => el?.name);
|
49
|
+
|
50
|
+
const dateColumn = columns?.find((el) => el?.name === (meta?.date || meta?.start))?.name
|
51
|
+
|| columns?.find((el) => el?.name === 'cdate')?.name;
|
52
|
+
|
53
|
+
if (query.date && !dateColumn) {
|
54
|
+
return { message: 'invalid template params: date column not found', status: 400 };
|
55
|
+
}
|
56
|
+
|
57
|
+
if (query.date && !isValidDate(query.date)) {
|
58
|
+
return { message: 'Invalid date: out of range or incorrect format', status: 400 };
|
59
|
+
}
|
60
|
+
|
61
|
+
const filterWhere = filterList?.length && query.filter?.length
|
62
|
+
? filterList
|
63
|
+
.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true))
|
64
|
+
.map((el) => {
|
65
|
+
const val = query.filter.split(',').find((e) => e?.split('=')?.shift()?.includes(el.column || el.name))?.split('=')?.pop();
|
66
|
+
if (val) return el.column && val ? `(${[`${el.column}::text='${val.replace(/'/g, "''")}'::text`, el.query].filter((el) => el).join(' and ')})` : el.query;
|
67
|
+
})
|
68
|
+
.filter((el) => el)
|
69
|
+
.join(' and ')
|
70
|
+
: undefined;
|
71
|
+
|
72
|
+
const queryWhere = handlebarsSync.compile(body.query || '1=1')({ user, uid: user?.uid });
|
73
|
+
const filterDate = query.date ? `date_trunc('${granularity}', "${dateColumn}"::date)='${query.date}'::date` : undefined;
|
74
|
+
|
75
|
+
const where = [queryWhere, filterDate, filterWhere].filter((el) => el).join(' and ');
|
76
|
+
|
77
|
+
const filtersByColumn = filterList.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true) && el?.column);
|
78
|
+
|
79
|
+
const filters = [];
|
80
|
+
if (filtersByColumn?.length) {
|
81
|
+
await Promise.all(filtersByColumn.map(async (el) => {
|
82
|
+
const { rows: filterData = [] } = await pg.query(`select ${el.column.replace(/'/g, "''")} as id, count(*) from ${table}
|
83
|
+
where ${el.query || '1=1'} and ${filterWhere || '1=1'} group by ${el.column.replace(/'/g, "''")}`);
|
84
|
+
if (!filterData?.length) return;
|
85
|
+
|
86
|
+
const clsData = await getTemplate(['cls', 'select'], el.cls);
|
87
|
+
|
88
|
+
if (!el.cls || !clsData?.length) {
|
89
|
+
filterData.forEach((item) => filters.push(item));
|
90
|
+
return;
|
91
|
+
}
|
92
|
+
|
93
|
+
filterData.forEach((filter) => {
|
94
|
+
const cls = clsData.find((item) => item.id === filter.id.toString());
|
95
|
+
Object.assign(filter, { title: cls?.text, color: cls?.color });
|
96
|
+
filters.push(filter);
|
97
|
+
});
|
98
|
+
}));
|
99
|
+
}
|
100
|
+
|
101
|
+
const filtersByPreparedQuery = filterList.filter((el) => (Object.hasOwn(el, 'enabled') ? el?.enabled : true) && !el?.column && el?.query);
|
102
|
+
|
103
|
+
if (filtersByPreparedQuery?.length) {
|
104
|
+
await Promise.all(filtersByPreparedQuery.map(async (el) => {
|
105
|
+
const { rows = [] } = await pg.query(`select ${el.query} as id, count(*) from ${table}
|
106
|
+
where ${filterWhere || '1=1'} group by ${el.query}`);
|
107
|
+
rows.forEach((item) => filters.push(item));
|
108
|
+
}));
|
109
|
+
}
|
110
|
+
|
111
|
+
const metaColumns = Object.keys(meta)
|
112
|
+
.filter((el) => ['date', 'start', 'end', 'title', 'status'].includes(el) && columnList.includes(meta[el]))
|
113
|
+
.map((el) => `"${meta[el]}" as ${el}`);
|
114
|
+
|
115
|
+
if (!metaColumns?.length) {
|
116
|
+
return { message: `calendar param meta is invalid: invalid/empty keys`, status: 404 };
|
117
|
+
}
|
118
|
+
|
119
|
+
const q = `select ${metaColumns.join(',')} from ${table} where ${where}`;
|
120
|
+
if (query?.sql && user?.user_type?.includes('admin')) return q;
|
121
|
+
|
122
|
+
const { rows = [] } = await pg.query(q);
|
123
|
+
|
124
|
+
return { title, filters, granularity, sql: user?.user_type?.includes('admin') ? q : undefined, rows };
|
125
|
+
|
126
126
|
}
|
@@ -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,22 +1,22 @@
|
|
1
|
-
const calendarDataSchema = {
|
2
|
-
params: {
|
3
|
-
name: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
4
|
-
},
|
5
|
-
querystring: {
|
6
|
-
date: { type: 'string', pattern: '^\\d{4}-\\d{2}-\\d{2}$' },
|
7
|
-
sql: { type: 'string', pattern: '^(\\d)$' },
|
8
|
-
},
|
9
|
-
|
10
|
-
// query: {
|
11
|
-
// type: 'object',
|
12
|
-
// properties: {
|
13
|
-
// date: {
|
14
|
-
// type: 'string',
|
15
|
-
// format: 'date',
|
16
|
-
// },
|
17
|
-
// },
|
18
|
-
// },
|
19
|
-
};
|
20
|
-
|
21
|
-
export { calendarDataSchema }
|
1
|
+
const calendarDataSchema = {
|
2
|
+
params: {
|
3
|
+
name: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
4
|
+
},
|
5
|
+
querystring: {
|
6
|
+
date: { type: 'string', pattern: '^\\d{4}-\\d{2}-\\d{2}$' },
|
7
|
+
sql: { type: 'string', pattern: '^(\\d)$' },
|
8
|
+
},
|
9
|
+
|
10
|
+
// query: {
|
11
|
+
// type: 'object',
|
12
|
+
// properties: {
|
13
|
+
// date: {
|
14
|
+
// type: 'string',
|
15
|
+
// format: 'date',
|
16
|
+
// },
|
17
|
+
// },
|
18
|
+
// },
|
19
|
+
};
|
20
|
+
|
21
|
+
export { calendarDataSchema }
|
22
22
|
export default null;
|
@@ -1,18 +1,18 @@
|
|
1
|
-
export default async function readNotifications({
|
2
|
-
pg, params = {}, query = {}, user = {},
|
3
|
-
}, reply) {
|
4
|
-
const { uid } = user || {};
|
5
|
-
|
6
|
-
if (!uid) {
|
7
|
-
return reply.status(401).send('access restricted: user ');
|
8
|
-
}
|
9
|
-
|
10
|
-
const q = `update crm.notifications set read=true where read is not true
|
11
|
-
and ${params?.id ? 'notification_id=$2' : '1=1'} and addressee_id=$1`;
|
12
|
-
|
13
|
-
if (query.sql) return q;
|
14
|
-
|
15
|
-
const { rowCount = 0 } = await pg.query(q, [uid, params?.id].filter((el) => el));
|
16
|
-
|
17
|
-
return reply.status(200).send(`${rowCount} unread notifications marked as read`);
|
18
|
-
}
|
1
|
+
export default async function readNotifications({
|
2
|
+
pg, params = {}, query = {}, user = {},
|
3
|
+
}, reply) {
|
4
|
+
const { uid } = user || {};
|
5
|
+
|
6
|
+
if (!uid) {
|
7
|
+
return reply.status(401).send('access restricted: user ');
|
8
|
+
}
|
9
|
+
|
10
|
+
const q = `update crm.notifications set read=true where read is not true
|
11
|
+
and ${params?.id ? 'notification_id=$2' : '1=1'} and addressee_id=$1`;
|
12
|
+
|
13
|
+
if (query.sql) return q;
|
14
|
+
|
15
|
+
const { rowCount = 0 } = await pg.query(q, [uid, params?.id].filter((el) => el));
|
16
|
+
|
17
|
+
return reply.status(200).send(`${rowCount} unread notifications marked as read`);
|
18
|
+
}
|
@@ -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 = {}, session = {},
|
7
|
-
}) {
|
8
|
-
const { local } = config || {};
|
9
|
-
|
10
|
-
if (!session?.passport?.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 = {}, session = {},
|
7
|
+
}) {
|
8
|
+
const { local } = config || {};
|
9
|
+
|
10
|
+
if (!session?.passport?.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,53 +1,53 @@
|
|
1
|
-
// for example only
|
2
|
-
/*
|
3
|
-
const res = await dataInsert({
|
4
|
-
pg,
|
5
|
-
table: 'crm.notifications',
|
6
|
-
data: {
|
7
|
-
subject: 'notif title',
|
8
|
-
body: 'notif body',
|
9
|
-
link: 'http://localhost:3000/api/notification',
|
10
|
-
addressee_id: userId,
|
11
|
-
author_id: userId,
|
12
|
-
},
|
13
|
-
});
|
14
|
-
*/
|
15
|
-
|
16
|
-
import { getSelectVal } from '@opengis/fastify-table/utils.js';
|
17
|
-
|
18
|
-
const maxLimit = 100;
|
19
|
-
|
20
|
-
export default async function userNotifications({
|
21
|
-
pg, query = {}, session = {},
|
22
|
-
}) {
|
23
|
-
const time = Date.now();
|
24
|
-
|
25
|
-
const { uid } = session.passport?.user || {};
|
26
|
-
|
27
|
-
if (!uid) {
|
28
|
-
return { message: 'access restricted', status: 403 };
|
29
|
-
}
|
30
|
-
|
31
|
-
const limit = Math.min(maxLimit, +(query.limit || 5));
|
32
|
-
const offset = query.page && query.page > 0 ? (query.page - 1) * limit : 0;
|
33
|
-
|
34
|
-
const q = `select notification_id as id, subject, body, cdate,
|
35
|
-
author_id, read, link, entity_id, (select avatar from admin.users where uid=a.author_id limit 1) as avatar from crm.notifications a where addressee_id=$1 order by cdate desc limit $2 offset $3`;
|
36
|
-
|
37
|
-
if (query.sql) return q;
|
38
|
-
|
39
|
-
const { rows = [] } = pg.pk?.['crm.notifications'] ? await pg.query(q, [uid, limit, offset]) : {};
|
40
|
-
|
41
|
-
const values = rows.map((el) => el.author_id)
|
42
|
-
?.filter((el, idx, arr) => el && arr.indexOf(el) === idx);
|
43
|
-
|
44
|
-
if (values?.length) {
|
45
|
-
const vals = await getSelectVal({ name: 'core.user_mentioned', values });
|
46
|
-
rows.forEach((row) => {
|
47
|
-
Object.assign(row, { author: vals?.[row.author_id] });
|
48
|
-
});
|
49
|
-
}
|
50
|
-
|
51
|
-
return { time: Date.now() - time, total: rows?.length, rows };
|
52
|
-
|
53
|
-
}
|
1
|
+
// for example only
|
2
|
+
/*
|
3
|
+
const res = await dataInsert({
|
4
|
+
pg,
|
5
|
+
table: 'crm.notifications',
|
6
|
+
data: {
|
7
|
+
subject: 'notif title',
|
8
|
+
body: 'notif body',
|
9
|
+
link: 'http://localhost:3000/api/notification',
|
10
|
+
addressee_id: userId,
|
11
|
+
author_id: userId,
|
12
|
+
},
|
13
|
+
});
|
14
|
+
*/
|
15
|
+
|
16
|
+
import { getSelectVal } from '@opengis/fastify-table/utils.js';
|
17
|
+
|
18
|
+
const maxLimit = 100;
|
19
|
+
|
20
|
+
export default async function userNotifications({
|
21
|
+
pg, query = {}, session = {},
|
22
|
+
}) {
|
23
|
+
const time = Date.now();
|
24
|
+
|
25
|
+
const { uid } = session.passport?.user || {};
|
26
|
+
|
27
|
+
if (!uid) {
|
28
|
+
return { message: 'access restricted', status: 403 };
|
29
|
+
}
|
30
|
+
|
31
|
+
const limit = Math.min(maxLimit, +(query.limit || 5));
|
32
|
+
const offset = query.page && query.page > 0 ? (query.page - 1) * limit : 0;
|
33
|
+
|
34
|
+
const q = `select notification_id as id, subject, body, cdate,
|
35
|
+
author_id, read, link, entity_id, (select avatar from admin.users where uid=a.author_id limit 1) as avatar from crm.notifications a where addressee_id=$1 order by cdate desc limit $2 offset $3`;
|
36
|
+
|
37
|
+
if (query.sql) return q;
|
38
|
+
|
39
|
+
const { rows = [] } = pg.pk?.['crm.notifications'] ? await pg.query(q, [uid, limit, offset]) : {};
|
40
|
+
|
41
|
+
const values = rows.map((el) => el.author_id)
|
42
|
+
?.filter((el, idx, arr) => el && arr.indexOf(el) === idx);
|
43
|
+
|
44
|
+
if (values?.length) {
|
45
|
+
const vals = await getSelectVal({ name: 'core.user_mentioned', values });
|
46
|
+
rows.forEach((row) => {
|
47
|
+
Object.assign(row, { author: vals?.[row.author_id] });
|
48
|
+
});
|
49
|
+
}
|
50
|
+
|
51
|
+
return { time: Date.now() - time, total: rows?.length, rows };
|
52
|
+
|
53
|
+
}
|
@@ -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, session, 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, session, 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, session, 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, session, 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
|
+
}
|