@hed-hog/core 0.0.296 → 0.0.298

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 (67) hide show
  1. package/dist/auth/auth.controller.d.ts +14 -14
  2. package/dist/auth/auth.service.d.ts +14 -14
  3. package/dist/challenge/challenge.service.d.ts +2 -2
  4. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +15 -1
  5. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
  6. package/dist/dashboard/dashboard-core/dashboard-core.controller.js +9 -0
  7. package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
  8. package/dist/dashboard/dashboard-core/dashboard-core.module.d.ts.map +1 -1
  9. package/dist/dashboard/dashboard-core/dashboard-core.module.js +6 -1
  10. package/dist/dashboard/dashboard-core/dashboard-core.module.js.map +1 -1
  11. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +175 -3
  12. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
  13. package/dist/dashboard/dashboard-core/dashboard-core.service.js +531 -5
  14. package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
  15. package/dist/file/file.controller.d.ts.map +1 -1
  16. package/dist/file/file.controller.js +16 -0
  17. package/dist/file/file.controller.js.map +1 -1
  18. package/dist/file/file.service.d.ts +7 -1
  19. package/dist/file/file.service.d.ts.map +1 -1
  20. package/dist/file/file.service.js +38 -1
  21. package/dist/file/file.service.js.map +1 -1
  22. package/dist/file/provider/s3.provider.d.ts +1 -0
  23. package/dist/file/provider/s3.provider.d.ts.map +1 -1
  24. package/dist/file/provider/s3.provider.js +38 -29
  25. package/dist/file/provider/s3.provider.js.map +1 -1
  26. package/dist/oauth/oauth.service.d.ts.map +1 -1
  27. package/dist/oauth/oauth.service.js +2 -1
  28. package/dist/oauth/oauth.service.js.map +1 -1
  29. package/dist/profile/profile.controller.d.ts +6 -6
  30. package/dist/profile/profile.service.d.ts +6 -6
  31. package/dist/session/session.controller.d.ts +2 -2
  32. package/dist/session/session.service.d.ts +3 -3
  33. package/dist/setting/setting.controller.d.ts +9 -9
  34. package/dist/setting/setting.service.d.ts +10 -10
  35. package/dist/user/constants/user.constants.d.ts +1 -0
  36. package/dist/user/constants/user.constants.d.ts.map +1 -1
  37. package/dist/user/constants/user.constants.js +2 -1
  38. package/dist/user/constants/user.constants.js.map +1 -1
  39. package/dist/user/user.controller.d.ts +15 -15
  40. package/dist/user/user.service.d.ts +39 -39
  41. package/dist/user/user.service.d.ts.map +1 -1
  42. package/dist/user/user.service.js +2 -1
  43. package/dist/user/user.service.js.map +1 -1
  44. package/hedhog/data/dashboard_item.yaml +11 -11
  45. package/hedhog/data/route.yaml +8 -0
  46. package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +76 -15
  47. package/hedhog/frontend/app/dashboard/components/widgets/email-notifications.tsx.ejs +85 -61
  48. package/hedhog/frontend/app/dashboard/components/widgets/locale-config.tsx.ejs +139 -280
  49. package/hedhog/frontend/app/dashboard/components/widgets/mail-config.tsx.ejs +161 -407
  50. package/hedhog/frontend/app/dashboard/components/widgets/oauth-config.tsx.ejs +150 -271
  51. package/hedhog/frontend/app/dashboard/components/widgets/profile-card.tsx.ejs +3 -3
  52. package/hedhog/frontend/app/dashboard/components/widgets/storage-config.tsx.ejs +161 -305
  53. package/hedhog/frontend/app/dashboard/components/widgets/theme-config.tsx.ejs +184 -246
  54. package/hedhog/frontend/app/dashboard/components/widgets/user-roles.tsx.ejs +12 -14
  55. package/hedhog/frontend/messages/en.json +90 -0
  56. package/hedhog/frontend/messages/pt.json +90 -0
  57. package/hedhog/table/mail_sent_user.yaml +75 -0
  58. package/package.json +4 -4
  59. package/src/dashboard/dashboard-core/dashboard-core.controller.ts +5 -0
  60. package/src/dashboard/dashboard-core/dashboard-core.module.ts +6 -1
  61. package/src/dashboard/dashboard-core/dashboard-core.service.ts +766 -3
  62. package/src/file/file.controller.ts +37 -13
  63. package/src/file/file.service.ts +47 -5
  64. package/src/file/provider/s3.provider.ts +39 -29
  65. package/src/oauth/oauth.service.ts +8 -7
  66. package/src/user/constants/user.constants.ts +1 -0
  67. package/src/user/user.service.ts +2 -1
@@ -8,14 +8,427 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
+ var DashboardCoreService_1;
11
12
  Object.defineProperty(exports, "__esModule", { value: true });
12
13
  exports.DashboardCoreService = void 0;
13
14
  const api_locale_1 = require("@hed-hog/api-locale");
14
15
  const api_prisma_1 = require("@hed-hog/api-prisma");
15
16
  const common_1 = require("@nestjs/common");
16
- let DashboardCoreService = class DashboardCoreService {
17
- constructor(prismaService) {
17
+ const setting_service_1 = require("../../setting/setting.service");
18
+ const MAIL_PROVIDER_REQUIREMENTS = {
19
+ SMTP: ['mail-from', 'mail-smtp-host', 'mail-smtp-port', 'mail-client-secret'],
20
+ GMAIL: [
21
+ 'mail-from',
22
+ 'mail-gmail-client-id',
23
+ 'mail-gmail-client-secret',
24
+ 'mail-gmail-refresh-token',
25
+ ],
26
+ SES: [
27
+ 'mail-from',
28
+ 'mail-aws-access-key-id',
29
+ 'mail-aws-secret-access-key',
30
+ 'mail-aws-region',
31
+ ],
32
+ };
33
+ const MAIL_PROVIDER_LABELS = {
34
+ SMTP: 'SMTP',
35
+ GMAIL: 'Gmail',
36
+ SES: 'Amazon SES',
37
+ };
38
+ const OAUTH_PROVIDER_DEFINITIONS = [
39
+ {
40
+ id: 'google',
41
+ label: 'Google',
42
+ requiredKeys: ['google_client_id', 'google_client_secret', 'url'],
43
+ scopeKey: 'google_scopes',
44
+ },
45
+ {
46
+ id: 'facebook',
47
+ label: 'Facebook',
48
+ requiredKeys: ['facebook_client_id', 'facebook_client_secret', 'url'],
49
+ scopeKey: 'facebook_scopes',
50
+ },
51
+ {
52
+ id: 'github',
53
+ label: 'GitHub',
54
+ requiredKeys: ['github_client_id', 'github_client_secret', 'api-url'],
55
+ scopeKey: 'github_scopes',
56
+ },
57
+ {
58
+ id: 'microsoft',
59
+ label: 'Microsoft',
60
+ requiredKeys: ['microsoft_client_id', 'microsoft_client_secret', 'url'],
61
+ scopeKey: 'microsoft_scopes',
62
+ },
63
+ {
64
+ id: 'microsoft_entra_id',
65
+ label: 'Microsoft Entra ID',
66
+ requiredKeys: [
67
+ 'microsoft_entra_id_client_id',
68
+ 'microsoft_entra_id_client_secret',
69
+ 'microsoft_entra_id_tenant_id',
70
+ 'url',
71
+ ],
72
+ scopeKey: 'microsoft_entra_id_scopes',
73
+ },
74
+ ];
75
+ const LOCALE_SETTING_KEYS = ['date-format', 'time-format', 'timezone'];
76
+ const MAIL_SETTING_KEYS = [
77
+ 'mail-provider',
78
+ 'mail-from',
79
+ 'mail-gmail-client-id',
80
+ 'mail-gmail-client-secret',
81
+ 'mail-gmail-refresh-token',
82
+ 'mail-smtp-host',
83
+ 'mail-smtp-port',
84
+ 'mail-smtp-secure',
85
+ 'mail-client-secret',
86
+ 'mail-aws-access-key-id',
87
+ 'mail-aws-secret-access-key',
88
+ 'mail-aws-region',
89
+ ];
90
+ const OAUTH_SETTING_KEYS = [
91
+ 'providers',
92
+ 'url',
93
+ 'api-url',
94
+ 'google_client_id',
95
+ 'google_client_secret',
96
+ 'google_scopes',
97
+ 'facebook_client_id',
98
+ 'facebook_client_secret',
99
+ 'facebook_scopes',
100
+ 'github_client_id',
101
+ 'github_client_secret',
102
+ 'github_scopes',
103
+ 'microsoft_client_id',
104
+ 'microsoft_client_secret',
105
+ 'microsoft_scopes',
106
+ 'microsoft_entra_id_client_id',
107
+ 'microsoft_entra_id_client_secret',
108
+ 'microsoft_entra_id_tenant_id',
109
+ 'microsoft_entra_id_scopes',
110
+ ];
111
+ const THEME_SETTING_KEYS = [
112
+ 'system-name',
113
+ 'system-slogan',
114
+ 'icon-url',
115
+ 'image-url',
116
+ 'theme-mode',
117
+ 'theme-font',
118
+ 'theme-text-size',
119
+ 'theme-radius',
120
+ 'theme-primary-light',
121
+ 'theme-primary-foreground-light',
122
+ 'theme-secondary-light',
123
+ 'theme-secondary-foreground-light',
124
+ 'theme-accent-light',
125
+ 'theme-accent-foreground-light',
126
+ 'theme-muted-light',
127
+ 'theme-muted-foreground-light',
128
+ 'theme-background-light',
129
+ 'theme-background-foreground-light',
130
+ 'theme-card-light',
131
+ 'theme-card-foreground-light',
132
+ 'theme-primary-dark',
133
+ 'theme-primary-foreground-dark',
134
+ 'theme-secondary-dark',
135
+ 'theme-secondary-foreground-dark',
136
+ 'theme-accent-dark',
137
+ 'theme-accent-foreground-dark',
138
+ 'theme-muted-dark',
139
+ 'theme-muted-foreground-dark',
140
+ 'theme-background-dark',
141
+ 'theme-background-foreground-dark',
142
+ 'theme-card-dark',
143
+ 'theme-card-foreground-dark',
144
+ ];
145
+ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
146
+ constructor(prismaService, settingService) {
18
147
  this.prismaService = prismaService;
148
+ this.settingService = settingService;
149
+ this.logger = new common_1.Logger(DashboardCoreService_1.name);
150
+ }
151
+ async getConfigOverview() {
152
+ const [localeConfig, mailConfig, oauthConfig, storageConfig, themeConfig] = await Promise.all([
153
+ this.getLocaleConfigOverview(),
154
+ this.getMailConfigOverview(),
155
+ this.getOAuthConfigOverview(),
156
+ this.getStorageConfigOverview(),
157
+ this.getThemeConfigOverview(),
158
+ ]);
159
+ return {
160
+ localeConfig,
161
+ mailConfig,
162
+ oauthConfig,
163
+ storageConfig,
164
+ themeConfig,
165
+ };
166
+ }
167
+ async getLocaleConfigOverview() {
168
+ const [settings, locales] = await Promise.all([
169
+ this.settingService.getSettingValues([...LOCALE_SETTING_KEYS]),
170
+ this.prismaService.locale.findMany({
171
+ orderBy: [{ enabled: 'desc' }, { code: 'asc' }],
172
+ select: {
173
+ id: true,
174
+ code: true,
175
+ region: true,
176
+ name: true,
177
+ enabled: true,
178
+ },
179
+ }),
180
+ ]);
181
+ const enabledLocaleCount = locales.filter((locale) => locale.enabled).length;
182
+ const disabledLocaleCount = locales.length - enabledLocaleCount;
183
+ return {
184
+ status: {
185
+ isConfigured: enabledLocaleCount > 0 &&
186
+ this.hasConfigValue(settings['date-format']) &&
187
+ this.hasConfigValue(settings['time-format']) &&
188
+ this.hasConfigValue(settings['timezone']),
189
+ enabledLocaleCount,
190
+ disabledLocaleCount,
191
+ },
192
+ settings: {
193
+ dateFormat: this.toNullableString(settings['date-format']),
194
+ timeFormat: this.toNullableString(settings['time-format']),
195
+ timezone: this.toNullableString(settings['timezone']),
196
+ },
197
+ locales,
198
+ };
199
+ }
200
+ async getMailConfigOverview() {
201
+ var _a;
202
+ const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
203
+ const [settings, templateCount, sentCount, sentLast30Days] = await Promise.all([
204
+ this.settingService.getSettingValues([...MAIL_SETTING_KEYS]),
205
+ this.prismaService.mail.count(),
206
+ this.prismaService.mail_sent.count(),
207
+ this.prismaService.mail_sent.count({
208
+ where: {
209
+ created_at: {
210
+ gte: thirtyDaysAgo,
211
+ },
212
+ },
213
+ }),
214
+ ]);
215
+ const selectedProvider = this.toNullableUppercaseString(settings['mail-provider']);
216
+ const providers = Object.entries(MAIL_PROVIDER_REQUIREMENTS).map(([providerId, requiredKeys]) => {
217
+ var _a;
218
+ const missingKeys = this.getMissingSettingKeys(settings, requiredKeys);
219
+ return {
220
+ id: providerId,
221
+ label: (_a = MAIL_PROVIDER_LABELS[providerId]) !== null && _a !== void 0 ? _a : providerId,
222
+ selected: providerId === selectedProvider,
223
+ configured: missingKeys.length === 0,
224
+ missingKeys,
225
+ };
226
+ });
227
+ const configuredProvider = providers.find((provider) => provider.id === selectedProvider && provider.configured);
228
+ return {
229
+ status: {
230
+ isConfigured: configuredProvider !== undefined,
231
+ selectedProvider,
232
+ configuredProvider: (_a = configuredProvider === null || configuredProvider === void 0 ? void 0 : configuredProvider.id) !== null && _a !== void 0 ? _a : null,
233
+ },
234
+ sender: {
235
+ from: this.toNullableString(settings['mail-from']),
236
+ },
237
+ metrics: {
238
+ templateCount,
239
+ sentCount,
240
+ sentLast30Days,
241
+ },
242
+ providers,
243
+ };
244
+ }
245
+ async getOAuthConfigOverview() {
246
+ const [settings, connectedAccounts] = await Promise.all([
247
+ this.settingService.getSettingValues([...OAUTH_SETTING_KEYS]),
248
+ this.prismaService.user_account.groupBy({
249
+ by: ['provider'],
250
+ _count: {
251
+ _all: true,
252
+ },
253
+ }),
254
+ ]);
255
+ const enabledProviders = this.normalizeProviderList(settings['providers']);
256
+ const connectedAccountsByProvider = new Map(connectedAccounts.map((entry) => [String(entry.provider), entry._count._all]));
257
+ const providers = OAUTH_PROVIDER_DEFINITIONS.map((provider) => {
258
+ var _a;
259
+ const missingKeys = this.getMissingSettingKeys(settings, provider.requiredKeys);
260
+ const scopes = Array.isArray(settings[provider.scopeKey])
261
+ ? settings[provider.scopeKey]
262
+ : [];
263
+ return {
264
+ id: provider.id,
265
+ label: provider.label,
266
+ enabled: enabledProviders.includes(provider.id),
267
+ configured: missingKeys.length === 0,
268
+ missingKeys,
269
+ scopesCount: scopes.length,
270
+ connectedUsers: (_a = connectedAccountsByProvider.get(provider.id)) !== null && _a !== void 0 ? _a : 0,
271
+ };
272
+ });
273
+ return {
274
+ status: {
275
+ isConfigured: providers.some((provider) => provider.enabled && provider.configured),
276
+ enabledProviderCount: providers.filter((provider) => provider.enabled).length,
277
+ configuredProviderCount: providers.filter((provider) => provider.configured).length,
278
+ connectedAccountCount: providers.reduce((total, provider) => total + provider.connectedUsers, 0),
279
+ },
280
+ providers,
281
+ };
282
+ }
283
+ async getStorageConfigOverview() {
284
+ var _a, _b;
285
+ const profiles = await this.prismaService.storage_profile.findMany({
286
+ where: {
287
+ deleted_at: null,
288
+ },
289
+ orderBy: [{ is_default: 'desc' }, { is_active: 'desc' }, { name: 'asc' }],
290
+ select: {
291
+ id: true,
292
+ name: true,
293
+ provider_type: true,
294
+ bucket_name: true,
295
+ region: true,
296
+ endpoint_url: true,
297
+ base_path: true,
298
+ path_template: true,
299
+ force_path_style: true,
300
+ is_default: true,
301
+ is_active: true,
302
+ test_status: true,
303
+ last_tested_at: true,
304
+ updated_at: true,
305
+ },
306
+ });
307
+ const providerMap = new Map();
308
+ profiles.forEach((profile) => {
309
+ var _a;
310
+ const providerType = String(profile.provider_type);
311
+ const current = (_a = providerMap.get(providerType)) !== null && _a !== void 0 ? _a : {
312
+ providerType,
313
+ total: 0,
314
+ active: 0,
315
+ defaults: 0,
316
+ };
317
+ current.total += 1;
318
+ current.active += profile.is_active ? 1 : 0;
319
+ current.defaults += profile.is_default ? 1 : 0;
320
+ providerMap.set(providerType, current);
321
+ });
322
+ const activeProfiles = profiles.filter((profile) => profile.is_active).length;
323
+ const defaultProfile = (_a = profiles.find((profile) => profile.is_default)) !== null && _a !== void 0 ? _a : null;
324
+ return {
325
+ status: {
326
+ isConfigured: activeProfiles > 0,
327
+ totalProfiles: profiles.length,
328
+ activeProfiles,
329
+ defaultProfileId: (_b = defaultProfile === null || defaultProfile === void 0 ? void 0 : defaultProfile.id) !== null && _b !== void 0 ? _b : null,
330
+ },
331
+ providers: Array.from(providerMap.values()),
332
+ profiles: profiles.map((profile) => ({
333
+ id: profile.id,
334
+ name: profile.name,
335
+ providerType: String(profile.provider_type),
336
+ bucketName: profile.bucket_name,
337
+ region: profile.region,
338
+ endpointUrl: profile.endpoint_url,
339
+ basePath: profile.base_path,
340
+ pathTemplate: profile.path_template,
341
+ forcePathStyle: profile.force_path_style,
342
+ isDefault: profile.is_default,
343
+ isActive: profile.is_active,
344
+ testStatus: String(profile.test_status),
345
+ lastTestedAt: profile.last_tested_at,
346
+ updatedAt: profile.updated_at,
347
+ })),
348
+ };
349
+ }
350
+ async getThemeConfigOverview() {
351
+ const settings = await this.settingService.getSettingValues([...THEME_SETTING_KEYS]);
352
+ const configuredTokenCount = THEME_SETTING_KEYS.filter((key) => this.hasConfigValue(settings[key])).length;
353
+ return {
354
+ status: {
355
+ isConfigured: this.hasConfigValue(settings['system-name']) ||
356
+ this.hasConfigValue(settings['theme-primary-light']) ||
357
+ this.hasConfigValue(settings['theme-primary-dark']),
358
+ configuredTokenCount,
359
+ },
360
+ branding: {
361
+ systemName: this.toNullableString(settings['system-name']),
362
+ systemSlogan: this.toNullableString(settings['system-slogan']),
363
+ iconUrl: this.toNullableString(settings['icon-url']),
364
+ imageUrl: this.toNullableString(settings['image-url']),
365
+ },
366
+ presentation: {
367
+ mode: this.toNullableString(settings['theme-mode']),
368
+ font: this.toNullableString(settings['theme-font']),
369
+ textSize: this.toNullableString(settings['theme-text-size']),
370
+ radius: this.toNullableString(settings['theme-radius']),
371
+ },
372
+ palette: {
373
+ light: {
374
+ primary: this.toNullableString(settings['theme-primary-light']),
375
+ primaryForeground: this.toNullableString(settings['theme-primary-foreground-light']),
376
+ secondary: this.toNullableString(settings['theme-secondary-light']),
377
+ secondaryForeground: this.toNullableString(settings['theme-secondary-foreground-light']),
378
+ accent: this.toNullableString(settings['theme-accent-light']),
379
+ accentForeground: this.toNullableString(settings['theme-accent-foreground-light']),
380
+ muted: this.toNullableString(settings['theme-muted-light']),
381
+ mutedForeground: this.toNullableString(settings['theme-muted-foreground-light']),
382
+ background: this.toNullableString(settings['theme-background-light']),
383
+ backgroundForeground: this.toNullableString(settings['theme-background-foreground-light']),
384
+ card: this.toNullableString(settings['theme-card-light']),
385
+ cardForeground: this.toNullableString(settings['theme-card-foreground-light']),
386
+ },
387
+ dark: {
388
+ primary: this.toNullableString(settings['theme-primary-dark']),
389
+ primaryForeground: this.toNullableString(settings['theme-primary-foreground-dark']),
390
+ secondary: this.toNullableString(settings['theme-secondary-dark']),
391
+ secondaryForeground: this.toNullableString(settings['theme-secondary-foreground-dark']),
392
+ accent: this.toNullableString(settings['theme-accent-dark']),
393
+ accentForeground: this.toNullableString(settings['theme-accent-foreground-dark']),
394
+ muted: this.toNullableString(settings['theme-muted-dark']),
395
+ mutedForeground: this.toNullableString(settings['theme-muted-foreground-dark']),
396
+ background: this.toNullableString(settings['theme-background-dark']),
397
+ backgroundForeground: this.toNullableString(settings['theme-background-foreground-dark']),
398
+ card: this.toNullableString(settings['theme-card-dark']),
399
+ cardForeground: this.toNullableString(settings['theme-card-foreground-dark']),
400
+ },
401
+ },
402
+ };
403
+ }
404
+ getMissingSettingKeys(settings, requiredKeys) {
405
+ return requiredKeys.filter((key) => !this.hasConfigValue(settings[key]));
406
+ }
407
+ hasConfigValue(value) {
408
+ if (Array.isArray(value)) {
409
+ return value.length > 0;
410
+ }
411
+ if (typeof value === 'string') {
412
+ return value.trim().length > 0;
413
+ }
414
+ return value !== null && value !== undefined;
415
+ }
416
+ toNullableString(value) {
417
+ if (typeof value !== 'string') {
418
+ return value === null || value === undefined ? null : String(value);
419
+ }
420
+ const normalized = value.trim();
421
+ return normalized.length > 0 ? normalized : null;
422
+ }
423
+ toNullableUppercaseString(value) {
424
+ const normalized = this.toNullableString(value);
425
+ return normalized ? normalized.toUpperCase() : null;
426
+ }
427
+ normalizeProviderList(value) {
428
+ if (!Array.isArray(value)) {
429
+ return [];
430
+ }
431
+ return value.map((provider) => String(provider).toLowerCase());
19
432
  }
20
433
  async getHome(userId, locale) {
21
434
  const user = await this.prismaService.user.findUnique({
@@ -739,10 +1152,121 @@ let DashboardCoreService = class DashboardCoreService {
739
1152
  });
740
1153
  });
741
1154
  }
1155
+ async getEmailNotificationStats(userId) {
1156
+ var _a, _b;
1157
+ const now = new Date();
1158
+ const periodStart = new Date(now);
1159
+ periodStart.setHours(0, 0, 0, 0);
1160
+ periodStart.setDate(periodStart.getDate() - 13);
1161
+ const periodEnd = new Date(now);
1162
+ periodEnd.setHours(23, 59, 59, 999);
1163
+ const toDateKey = (date) => {
1164
+ const year = date.getFullYear();
1165
+ const month = String(date.getMonth() + 1).padStart(2, '0');
1166
+ const day = String(date.getDate()).padStart(2, '0');
1167
+ return `${year}-${month}-${day}`;
1168
+ };
1169
+ try {
1170
+ const [cardsRows, chartRows] = await Promise.all([
1171
+ this.prismaService.$queryRaw `
1172
+ SELECT
1173
+ COUNT(*) FILTER (WHERE "status" IN ('received', 'read'))::bigint as received,
1174
+ COUNT(*) FILTER (WHERE "status" = 'read')::bigint as read,
1175
+ COUNT(*) FILTER (WHERE "status" = 'received' AND "read_at" IS NULL)::bigint as unread,
1176
+ COUNT(*) FILTER (WHERE "status" = 'error')::bigint as error
1177
+ FROM "mail_sent_user"
1178
+ WHERE "user_id" = ${userId}
1179
+ AND "created_at" >= ${periodStart}
1180
+ AND "created_at" <= ${periodEnd}
1181
+ `,
1182
+ this.prismaService.$queryRaw `
1183
+ SELECT
1184
+ DATE("created_at") as date,
1185
+ COUNT(*) FILTER (WHERE "status" IN ('received', 'read'))::bigint as received,
1186
+ COUNT(*) FILTER (WHERE "status" = 'read')::bigint as read
1187
+ FROM "mail_sent_user"
1188
+ WHERE "user_id" = ${userId}
1189
+ AND "created_at" >= ${periodStart}
1190
+ AND "created_at" <= ${periodEnd}
1191
+ GROUP BY DATE("created_at")
1192
+ ORDER BY date ASC
1193
+ `,
1194
+ ]);
1195
+ const cards = (_a = cardsRows[0]) !== null && _a !== void 0 ? _a : {
1196
+ received: BigInt(0),
1197
+ read: BigInt(0),
1198
+ unread: BigInt(0),
1199
+ error: BigInt(0),
1200
+ };
1201
+ const chartMap = new Map();
1202
+ for (const row of chartRows) {
1203
+ const rowDate = new Date(row.date);
1204
+ rowDate.setHours(0, 0, 0, 0);
1205
+ const key = toDateKey(rowDate);
1206
+ chartMap.set(key, {
1207
+ received: Number(row.received),
1208
+ read: Number(row.read),
1209
+ });
1210
+ }
1211
+ const dateFormatter = new Intl.DateTimeFormat('pt-BR', {
1212
+ day: '2-digit',
1213
+ month: '2-digit',
1214
+ });
1215
+ const chart = [];
1216
+ for (let i = 13; i >= 0; i--) {
1217
+ const day = new Date(now);
1218
+ day.setDate(day.getDate() - i);
1219
+ day.setHours(0, 0, 0, 0);
1220
+ const key = toDateKey(day);
1221
+ const values = (_b = chartMap.get(key)) !== null && _b !== void 0 ? _b : { received: 0, read: 0 };
1222
+ chart.push({
1223
+ date: dateFormatter.format(day),
1224
+ received: values.received,
1225
+ read: values.read,
1226
+ });
1227
+ }
1228
+ return {
1229
+ cards: {
1230
+ received: Number(cards.received),
1231
+ read: Number(cards.read),
1232
+ unread: Number(cards.unread),
1233
+ error: Number(cards.error),
1234
+ },
1235
+ chart,
1236
+ };
1237
+ }
1238
+ catch (error) {
1239
+ this.logger.error('Error loading email notification stats:', error);
1240
+ const dateFormatter = new Intl.DateTimeFormat('pt-BR', {
1241
+ day: '2-digit',
1242
+ month: '2-digit',
1243
+ });
1244
+ const chart = [];
1245
+ for (let i = 13; i >= 0; i--) {
1246
+ const day = new Date(now);
1247
+ day.setDate(day.getDate() - i);
1248
+ chart.push({
1249
+ date: dateFormatter.format(day),
1250
+ received: 0,
1251
+ read: 0,
1252
+ });
1253
+ }
1254
+ return {
1255
+ cards: {
1256
+ received: 0,
1257
+ read: 0,
1258
+ unread: 0,
1259
+ error: 0,
1260
+ },
1261
+ chart,
1262
+ };
1263
+ }
1264
+ }
742
1265
  async getWidgetsData(userId, locale) {
743
- const [accountSecurity, activityTimeline, loginHistory, profile, quickStats, userRoles, userSessions] = await Promise.all([
1266
+ const [accountSecurity, activityTimeline, emailNotifications, loginHistory, profile, quickStats, userRoles, userSessions] = await Promise.all([
744
1267
  this.getAccountSecurity(userId),
745
1268
  this.getActivityTimeline(userId),
1269
+ this.getEmailNotificationStats(userId),
746
1270
  this.getLoginHistory(userId),
747
1271
  this.getProfile(userId),
748
1272
  this.getQuickStats(userId),
@@ -752,6 +1276,7 @@ let DashboardCoreService = class DashboardCoreService {
752
1276
  return {
753
1277
  accountSecurity,
754
1278
  activityTimeline,
1279
+ emailNotifications,
755
1280
  loginHistory,
756
1281
  profile,
757
1282
  quickStats,
@@ -780,8 +1305,9 @@ let DashboardCoreService = class DashboardCoreService {
780
1305
  }
781
1306
  };
782
1307
  exports.DashboardCoreService = DashboardCoreService;
783
- exports.DashboardCoreService = DashboardCoreService = __decorate([
1308
+ exports.DashboardCoreService = DashboardCoreService = DashboardCoreService_1 = __decorate([
784
1309
  (0, common_1.Injectable)(),
785
- __metadata("design:paramtypes", [api_prisma_1.PrismaService])
1310
+ __metadata("design:paramtypes", [api_prisma_1.PrismaService,
1311
+ setting_service_1.SettingService])
786
1312
  ], DashboardCoreService);
787
1313
  //# sourceMappingURL=dashboard-core.service.js.map