@inspirer-dev/crm-dashboard 1.0.89 → 1.0.91

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.
@@ -17,6 +17,70 @@ const controller = ({ strapi }: { strapi: Core.Strapi }) => ({
17
17
  async getAntiSpamLogs(ctx: any) {
18
18
  ctx.body = await strapi.plugin('crm-dashboard').service('service').getAntiSpamLogs(ctx.query);
19
19
  },
20
+
21
+ async listManualPushTemplates(ctx: any) {
22
+ ctx.body = await strapi.plugin('crm-dashboard').service('service').listManualPushTemplates();
23
+ },
24
+
25
+ async dispatchManualPush(ctx: any) {
26
+ try {
27
+ ctx.body = await strapi
28
+ .plugin('crm-dashboard')
29
+ .service('service')
30
+ .dispatchManualPush(ctx.request.body);
31
+ } catch (err: any) {
32
+ const status = err?.response?.status || 500;
33
+ ctx.status = status;
34
+ ctx.body = {
35
+ error: 'Dispatch failed',
36
+ status,
37
+ backend: err?.response?.data ?? err?.message ?? null,
38
+ };
39
+ }
40
+ },
41
+
42
+ async dispatchTestManualPush(ctx: any) {
43
+ try {
44
+ ctx.body = await strapi
45
+ .plugin('crm-dashboard')
46
+ .service('service')
47
+ .dispatchTestManualPush(ctx.request.body);
48
+ } catch (err: any) {
49
+ const status = err?.response?.status || 500;
50
+ ctx.status = status;
51
+ ctx.body = {
52
+ error: 'Dispatch test failed',
53
+ status,
54
+ backend: err?.response?.data ?? err?.message ?? null,
55
+ };
56
+ }
57
+ },
58
+
59
+ async getManualPushHistory(ctx: any) {
60
+ try {
61
+ ctx.body = await strapi
62
+ .plugin('crm-dashboard')
63
+ .service('service')
64
+ .getManualPushHistory(ctx.query);
65
+ } catch (err: any) {
66
+ const status = err?.response?.status || 500;
67
+ ctx.status = status;
68
+ ctx.body = { error: 'Failed to load history', status };
69
+ }
70
+ },
71
+
72
+ async getManualPushStats(ctx: any) {
73
+ try {
74
+ ctx.body = await strapi
75
+ .plugin('crm-dashboard')
76
+ .service('service')
77
+ .getManualPushStats(ctx.params.manualPushId);
78
+ } catch (err: any) {
79
+ const status = err?.response?.status || 500;
80
+ ctx.status = status;
81
+ ctx.body = { error: 'Failed to load stats', status };
82
+ }
83
+ },
20
84
  });
21
85
 
22
86
  export default controller;
@@ -41,6 +41,61 @@ const adminRoutes = [
41
41
  },
42
42
  },
43
43
  },
44
+ {
45
+ method: 'GET',
46
+ path: '/manual-pushes/templates',
47
+ handler: 'controller.listManualPushTemplates',
48
+ config: {
49
+ policies: [],
50
+ auth: {
51
+ scope: ['plugin::crm-dashboard.access'],
52
+ },
53
+ },
54
+ },
55
+ {
56
+ method: 'POST',
57
+ path: '/manual-pushes/dispatch',
58
+ handler: 'controller.dispatchManualPush',
59
+ config: {
60
+ policies: [],
61
+ auth: {
62
+ scope: ['plugin::crm-dashboard.access'],
63
+ },
64
+ },
65
+ },
66
+ {
67
+ method: 'POST',
68
+ path: '/manual-pushes/dispatch-test',
69
+ handler: 'controller.dispatchTestManualPush',
70
+ config: {
71
+ policies: [],
72
+ auth: {
73
+ scope: ['plugin::crm-dashboard.access'],
74
+ },
75
+ },
76
+ },
77
+ {
78
+ method: 'GET',
79
+ path: '/manual-pushes/history',
80
+ handler: 'controller.getManualPushHistory',
81
+ config: {
82
+ policies: [],
83
+ auth: {
84
+ scope: ['plugin::crm-dashboard.access'],
85
+ },
86
+ },
87
+ },
88
+ {
89
+ method: 'GET',
90
+ path: '/manual-pushes/:manualPushId/stats',
91
+ handler: 'controller.getManualPushStats',
92
+ config: {
93
+ policies: [],
94
+ auth: {
95
+ scope: ['plugin::crm-dashboard.access'],
96
+ },
97
+ },
98
+ },
44
99
  ];
45
100
 
46
101
  export default {
@@ -2,6 +2,24 @@ import type { Core } from '@strapi/strapi';
2
2
  import axios from 'axios';
3
3
 
4
4
  const API_URL = process.env.API_URL || 'http://localhost:3100';
5
+ const STATISTICS_SECRET_KEY = process.env.STATISTICS_SECRET_KEY || '';
6
+
7
+ const authHeaders = () =>
8
+ STATISTICS_SECRET_KEY ? { Authorization: `Bearer ${STATISTICS_SECRET_KEY}` } : {};
9
+
10
+ const formatAxiosError = (err: unknown): string => {
11
+ const e = err as { response?: { status?: number; data?: unknown }; message?: string };
12
+ const status = e?.response?.status;
13
+ const data = e?.response?.data;
14
+ const text = data && typeof data === 'object' ? JSON.stringify(data) : String(data ?? '');
15
+ return [
16
+ status ? `status=${status}` : '',
17
+ text ? `body=${text}` : '',
18
+ e?.message ? `msg=${e.message}` : '',
19
+ ]
20
+ .filter(Boolean)
21
+ .join(' | ');
22
+ };
5
23
 
6
24
  export default ({ strapi }: { strapi: Core.Strapi }) => ({
7
25
  async getLogs(query: Record<string, unknown>) {
@@ -10,7 +28,10 @@ export default ({ strapi }: { strapi: Core.Strapi }) => ({
10
28
  return data;
11
29
  } catch (err) {
12
30
  strapi.log.error('Failed to fetch CRM logs from backend', err);
13
- return { error: 'Failed to fetch logs', details: err instanceof Error ? err.message : String(err) };
31
+ return {
32
+ error: 'Failed to fetch logs',
33
+ details: err instanceof Error ? err.message : String(err),
34
+ };
14
35
  }
15
36
  },
16
37
 
@@ -20,7 +41,118 @@ export default ({ strapi }: { strapi: Core.Strapi }) => ({
20
41
  return data;
21
42
  } catch (err) {
22
43
  strapi.log.error('Failed to fetch Anti-spam logs from backend', err);
23
- return { error: 'Failed to fetch logs', details: err instanceof Error ? err.message : String(err) };
44
+ return {
45
+ error: 'Failed to fetch logs',
46
+ details: err instanceof Error ? err.message : String(err),
47
+ };
48
+ }
49
+ },
50
+
51
+ async listManualPushTemplates() {
52
+ try {
53
+ const entries = await strapi.documents('api::manual-push.manual-push').findMany({
54
+ status: 'published',
55
+ locale: 'ru',
56
+ populate: { image: { fields: ['url', 'alternativeText', 'width', 'height'] } },
57
+ sort: { updatedAt: 'desc' },
58
+ pagination: { pageSize: 200 },
59
+ } as any);
60
+
61
+ const enriched = await Promise.all(
62
+ (entries ?? []).map(async (e: any) => {
63
+ let enEntry: any = null;
64
+ try {
65
+ enEntry = await strapi.documents('api::manual-push.manual-push').findOne({
66
+ documentId: e.documentId,
67
+ status: 'published',
68
+ locale: 'en',
69
+ } as any);
70
+ } catch {
71
+ enEntry = null;
72
+ }
73
+ const locales: string[] = ['ru'];
74
+ if (enEntry) locales.push('en');
75
+ return {
76
+ documentId: e.documentId,
77
+ name: e.name,
78
+ body: e.body,
79
+ bodyEn: enEntry?.body ?? null,
80
+ image: e.image
81
+ ? {
82
+ url: e.image.url,
83
+ alternativeText: e.image.alternativeText,
84
+ width: e.image.width,
85
+ height: e.image.height,
86
+ }
87
+ : null,
88
+ buttonLabel: e.buttonLabel ?? null,
89
+ buttonUrl: e.buttonUrl ?? null,
90
+ buttonLabelEn: enEntry?.buttonLabel ?? null,
91
+ buttonUrlEn: enEntry?.buttonUrl ?? null,
92
+ testUserIds: Array.isArray(e.testUserIds) ? e.testUserIds : [],
93
+ locales,
94
+ updatedAt: e.updatedAt,
95
+ createdAt: e.createdAt,
96
+ };
97
+ })
98
+ );
99
+
100
+ return { data: enriched };
101
+ } catch (err) {
102
+ strapi.log.error('Failed to list manual-push templates', err);
103
+ return {
104
+ error: 'Failed to list templates',
105
+ details: err instanceof Error ? err.message : String(err),
106
+ };
107
+ }
108
+ },
109
+
110
+ async dispatchManualPush(body: Record<string, unknown>) {
111
+ try {
112
+ const { data } = await axios.post(`${API_URL}/crm/admin/manual-pushes/dispatch`, body, {
113
+ headers: authHeaders(),
114
+ });
115
+ return data;
116
+ } catch (err) {
117
+ strapi.log.error(`Failed to dispatch manual push: ${formatAxiosError(err)}`);
118
+ throw err;
119
+ }
120
+ },
121
+
122
+ async dispatchTestManualPush(body: Record<string, unknown>) {
123
+ try {
124
+ const { data } = await axios.post(`${API_URL}/crm/admin/manual-pushes/dispatch-test`, body, {
125
+ headers: authHeaders(),
126
+ });
127
+ return data;
128
+ } catch (err) {
129
+ strapi.log.error(`Failed to dispatch test manual push: ${formatAxiosError(err)}`);
130
+ throw err;
131
+ }
132
+ },
133
+
134
+ async getManualPushHistory(query: Record<string, unknown>) {
135
+ try {
136
+ const { data } = await axios.get(`${API_URL}/crm/admin/manual-pushes`, {
137
+ params: query,
138
+ headers: authHeaders(),
139
+ });
140
+ return data;
141
+ } catch (err) {
142
+ strapi.log.error(`Failed to fetch manual push history: ${formatAxiosError(err)}`);
143
+ throw err;
144
+ }
145
+ },
146
+
147
+ async getManualPushStats(manualPushId: string) {
148
+ try {
149
+ const { data } = await axios.get(`${API_URL}/crm/admin/manual-pushes/${manualPushId}/stats`, {
150
+ headers: authHeaders(),
151
+ });
152
+ return data;
153
+ } catch (err) {
154
+ strapi.log.error(`Failed to fetch manual push stats: ${formatAxiosError(err)}`);
155
+ throw err;
24
156
  }
25
157
  },
26
158
  });