@acorex/modules 19.3.1 → 19.3.2

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 (159) hide show
  1. package/common/lib/common.module.d.ts +2 -1
  2. package/dashboard-management/lib/entities/dashboard/dashboard.types.d.ts +2 -2
  3. package/dashboard-management/lib/features/home-dashboard/dashboard-home/home-dashboard.d.ts +7 -7
  4. package/dashboard-management/lib/features/home-dashboard/dashboard-home/home-dashboard.store.d.ts +6 -6
  5. package/dashboard-management/lib/features/home-dashboard/dashboard-home/home-dashboard.type.d.ts +3 -3
  6. package/dashboard-management/lib/features/home-dashboard/dashboard-popups/add-dashboard-popup.d.ts +3 -3
  7. package/dashboard-management/lib/features/home-dashboard/dashboard-popups/configuration-popup.d.ts +3 -3
  8. package/dashboard-management/lib/features/home-dashboard/dashboard-popups/dashboard-popup.service.d.ts +5 -5
  9. package/dashboard-management/lib/features/home-dashboard/widget-wrapper/dashboard-widget-wrapper.d.ts +4 -3
  10. package/dashboard-management/lib/features/shared/widgets/bar-chart/bar-chart-widget.component.d.ts +9 -64
  11. package/dashboard-management/lib/features/shared/widgets/clock-calendar/clock-calendar-widget.component.d.ts +0 -1
  12. package/dashboard-management/lib/features/shared/widgets/donut-chart/donut-chart-widget.component.d.ts +9 -50
  13. package/dashboard-management/lib/features/shared/widgets/gauge-chart/gauge-chart-widget.component.d.ts +8 -67
  14. package/dashboard-management/lib/features/shared/widgets/gauge-chart/index.d.ts +0 -1
  15. package/dashboard-management/lib/features/shared/widgets/index.d.ts +0 -2
  16. package/dashboard-management/lib/features/shared/widgets/line-chart/index.d.ts +0 -1
  17. package/dashboard-management/lib/features/shared/widgets/line-chart/line-chart-widget.component.d.ts +9 -68
  18. package/fesm2022/{acorex-modules-auth-acorex-modules-auth-B1HTJdsE.mjs → acorex-modules-auth-acorex-modules-auth-DJZcD1j3.mjs} +23 -83
  19. package/fesm2022/acorex-modules-auth-acorex-modules-auth-DJZcD1j3.mjs.map +1 -0
  20. package/fesm2022/acorex-modules-auth-app-chooser.component-DlYxDGQr.mjs +65 -0
  21. package/fesm2022/acorex-modules-auth-app-chooser.component-DlYxDGQr.mjs.map +1 -0
  22. package/fesm2022/{acorex-modules-auth-login.module-TtdNj0aL.mjs → acorex-modules-auth-login.module-D-XgzifC.mjs} +4 -4
  23. package/fesm2022/{acorex-modules-auth-login.module-TtdNj0aL.mjs.map → acorex-modules-auth-login.module-D-XgzifC.mjs.map} +1 -1
  24. package/fesm2022/{acorex-modules-auth-master.layout-CtVrY1hn.mjs → acorex-modules-auth-master.layout-ZaCb3CED.mjs} +2 -2
  25. package/fesm2022/{acorex-modules-auth-master.layout-CtVrY1hn.mjs.map → acorex-modules-auth-master.layout-ZaCb3CED.mjs.map} +1 -1
  26. package/fesm2022/{acorex-modules-auth-password.component-Dmj9zZSI.mjs → acorex-modules-auth-password.component-C-xRIhrM.mjs} +2 -2
  27. package/fesm2022/{acorex-modules-auth-password.component-Dmj9zZSI.mjs.map → acorex-modules-auth-password.component-C-xRIhrM.mjs.map} +1 -1
  28. package/fesm2022/{acorex-modules-auth-password.component-BXm2NAaN.mjs → acorex-modules-auth-password.component-CLTZoufP.mjs} +2 -2
  29. package/fesm2022/{acorex-modules-auth-password.component-BXm2NAaN.mjs.map → acorex-modules-auth-password.component-CLTZoufP.mjs.map} +1 -1
  30. package/fesm2022/{acorex-modules-auth-routes-DkgsKi3a.mjs → acorex-modules-auth-routes-4T5jq7su.mjs} +2 -2
  31. package/fesm2022/{acorex-modules-auth-routes-DkgsKi3a.mjs.map → acorex-modules-auth-routes-4T5jq7su.mjs.map} +1 -1
  32. package/fesm2022/acorex-modules-auth-tenant-chooser.component-Ow7QtAWc.mjs +98 -0
  33. package/fesm2022/acorex-modules-auth-tenant-chooser.component-Ow7QtAWc.mjs.map +1 -0
  34. package/fesm2022/{acorex-modules-auth-two-factor.module-DDOSqjYs.mjs → acorex-modules-auth-two-factor.module-D72KIpvA.mjs} +2 -2
  35. package/fesm2022/{acorex-modules-auth-two-factor.module-DDOSqjYs.mjs.map → acorex-modules-auth-two-factor.module-D72KIpvA.mjs.map} +1 -1
  36. package/fesm2022/{acorex-modules-auth-user-sessions.component-B3i44VC5.mjs → acorex-modules-auth-user-sessions.component-Btnu_Oeq.mjs} +2 -2
  37. package/fesm2022/{acorex-modules-auth-user-sessions.component-B3i44VC5.mjs.map → acorex-modules-auth-user-sessions.component-Btnu_Oeq.mjs.map} +1 -1
  38. package/fesm2022/acorex-modules-auth.mjs +1 -1
  39. package/fesm2022/acorex-modules-common.mjs +3 -5
  40. package/fesm2022/acorex-modules-common.mjs.map +1 -1
  41. package/fesm2022/{acorex-modules-dashboard-management-acorex-modules-dashboard-management-CReOsVhq.mjs → acorex-modules-dashboard-management-acorex-modules-dashboard-management-VORBD1g-.mjs} +846 -2174
  42. package/fesm2022/acorex-modules-dashboard-management-acorex-modules-dashboard-management-VORBD1g-.mjs.map +1 -0
  43. package/fesm2022/{acorex-modules-dashboard-management-home-dashboard-CHXDeuSF.mjs → acorex-modules-dashboard-management-home-dashboard-DiPn_RhH.mjs} +49 -48
  44. package/fesm2022/acorex-modules-dashboard-management-home-dashboard-DiPn_RhH.mjs.map +1 -0
  45. package/fesm2022/acorex-modules-dashboard-management.mjs +1 -1
  46. package/fesm2022/{acorex-modules-issue-management-acorex-modules-issue-management-Q47ZZSSE.mjs → acorex-modules-issue-management-acorex-modules-issue-management-U5EJyG5e.mjs} +42 -42
  47. package/fesm2022/{acorex-modules-issue-management-acorex-modules-issue-management-Q47ZZSSE.mjs.map → acorex-modules-issue-management-acorex-modules-issue-management-U5EJyG5e.mjs.map} +1 -1
  48. package/fesm2022/{acorex-modules-issue-management-capture-screen.component-Dns1Wrkd.mjs → acorex-modules-issue-management-capture-screen.component-3ZAOJBfn.mjs} +2 -2
  49. package/fesm2022/{acorex-modules-issue-management-capture-screen.component-Dns1Wrkd.mjs.map → acorex-modules-issue-management-capture-screen.component-3ZAOJBfn.mjs.map} +1 -1
  50. package/fesm2022/acorex-modules-issue-management.mjs +1 -1
  51. package/fesm2022/acorex-modules-notification-management.mjs +621 -52
  52. package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
  53. package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-DIsYLKbA.mjs → acorex-modules-platform-management-acorex-modules-platform-management-5lToZD6T.mjs} +6 -6
  54. package/fesm2022/acorex-modules-platform-management-acorex-modules-platform-management-5lToZD6T.mjs.map +1 -0
  55. package/fesm2022/{acorex-modules-platform-management-list-version.component-D83yTFAm.mjs → acorex-modules-platform-management-list-version.component-BElZjmXr.mjs} +2 -2
  56. package/fesm2022/{acorex-modules-platform-management-list-version.component-D83yTFAm.mjs.map → acorex-modules-platform-management-list-version.component-BElZjmXr.mjs.map} +1 -1
  57. package/fesm2022/{acorex-modules-platform-management-settings.provider-DKkXCwrd.mjs → acorex-modules-platform-management-settings.provider-CemrvnbH.mjs} +2 -2
  58. package/fesm2022/{acorex-modules-platform-management-settings.provider-DKkXCwrd.mjs.map → acorex-modules-platform-management-settings.provider-CemrvnbH.mjs.map} +1 -1
  59. package/fesm2022/acorex-modules-platform-management.mjs +1 -1
  60. package/fesm2022/acorex-modules-project-management.mjs +218 -155
  61. package/fesm2022/acorex-modules-project-management.mjs.map +1 -1
  62. package/fesm2022/acorex-modules-security-management.mjs +472 -787
  63. package/fesm2022/acorex-modules-security-management.mjs.map +1 -1
  64. package/fesm2022/acorex-modules-training-management.mjs +5574 -0
  65. package/fesm2022/acorex-modules-training-management.mjs.map +1 -0
  66. package/notification-management/index.d.ts +1 -0
  67. package/notification-management/lib/entities/notification/notification.service.d.ts +6 -6
  68. package/notification-management/lib/features/components/admin-notification-panel/admin-notification-panel.component.d.ts +13 -7
  69. package/{dashboard-management/lib/features/shared/widgets/notification → notification-management/lib/features/dashboard/widgets/my-notification}/index.d.ts +0 -1
  70. package/{dashboard-management/lib/features/shared/widgets/notification → notification-management/lib/features/dashboard/widgets/my-notification}/notification-widget.component.d.ts +37 -9
  71. package/notification-management/lib/features/dashboard/widgets/my-notification/notification-widget.config.d.ts +5 -0
  72. package/notification-management/lib/features/shared/notification-connector.service.d.ts +57 -0
  73. package/notification-management/lib/notification-management.module.d.ts +2 -1
  74. package/notification-management/lib/notification-management.type.d.ts +3 -0
  75. package/package.json +5 -1
  76. package/security-management/lib/entities/index.d.ts +1 -2
  77. package/security-management/lib/entities/profile/index.d.ts +0 -1
  78. package/security-management/lib/entities/users/users.service.d.ts +2 -2
  79. package/security-management/lib/entities/users/users.types.d.ts +2 -2
  80. package/security-management/lib/user-avatar.provider.d.ts +5 -0
  81. package/training-management/README.md +3 -0
  82. package/training-management/index.d.ts +7 -0
  83. package/training-management/lib/const.d.ts +85 -0
  84. package/training-management/lib/entities/certificate/certificate.entity.d.ts +3 -0
  85. package/training-management/lib/entities/certificate/certificate.service.d.ts +10 -0
  86. package/training-management/lib/entities/certificate/certificate.types.d.ts +12 -0
  87. package/training-management/lib/entities/certificate/index.d.ts +3 -0
  88. package/training-management/lib/entities/course/course.entity.d.ts +3 -0
  89. package/training-management/lib/entities/course/course.service.d.ts +10 -0
  90. package/training-management/lib/entities/course/course.types.d.ts +8 -0
  91. package/training-management/lib/entities/course/index.d.ts +3 -0
  92. package/training-management/lib/entities/course-location/course-location.entity.d.ts +3 -0
  93. package/training-management/lib/entities/course-location/course-location.service.d.ts +10 -0
  94. package/training-management/lib/entities/course-location/course-location.types.d.ts +6 -0
  95. package/training-management/lib/entities/course-location/index.d.ts +3 -0
  96. package/training-management/lib/entities/course-period/course-period.entity.d.ts +3 -0
  97. package/training-management/lib/entities/course-period/course-period.service.d.ts +10 -0
  98. package/training-management/lib/entities/course-period/course-period.types.d.ts +6 -0
  99. package/training-management/lib/entities/course-period/index.d.ts +3 -0
  100. package/training-management/lib/entities/course-type/course-type.entity.d.ts +3 -0
  101. package/training-management/lib/entities/course-type/course-type.service.d.ts +10 -0
  102. package/training-management/lib/entities/course-type/course-type.types.d.ts +5 -0
  103. package/training-management/lib/entities/course-type/index.d.ts +3 -0
  104. package/training-management/lib/entities/facilitator-type/facilitator-type.entity.d.ts +3 -0
  105. package/training-management/lib/entities/facilitator-type/facilitator-type.service.d.ts +10 -0
  106. package/training-management/lib/entities/facilitator-type/facilitator-type.types.d.ts +6 -0
  107. package/training-management/lib/entities/facilitator-type/index.d.ts +3 -0
  108. package/training-management/lib/entities/index.d.ts +12 -0
  109. package/training-management/lib/entities/location/index.d.ts +3 -0
  110. package/training-management/lib/entities/location/location.entity.d.ts +3 -0
  111. package/training-management/lib/entities/location/location.service.d.ts +10 -0
  112. package/training-management/lib/entities/location/location.types.d.ts +7 -0
  113. package/training-management/lib/entities/period/index.d.ts +3 -0
  114. package/training-management/lib/entities/period/period.entity.d.ts +3 -0
  115. package/training-management/lib/entities/period/period.service.d.ts +10 -0
  116. package/training-management/lib/entities/period/period.types.d.ts +6 -0
  117. package/training-management/lib/entities/training/index.d.ts +3 -0
  118. package/training-management/lib/entities/training/training.entity.d.ts +3 -0
  119. package/training-management/lib/entities/training/training.service.d.ts +10 -0
  120. package/training-management/lib/entities/training/training.types.d.ts +13 -0
  121. package/training-management/lib/entities/training-facilitator/index.d.ts +3 -0
  122. package/training-management/lib/entities/training-facilitator/training-facilitator.entity.d.ts +3 -0
  123. package/training-management/lib/entities/training-facilitator/training-facilitator.service.d.ts +10 -0
  124. package/training-management/lib/entities/training-facilitator/training-facilitator.types.d.ts +7 -0
  125. package/training-management/lib/entities/training-participant/index.d.ts +3 -0
  126. package/training-management/lib/entities/training-participant/training-participant.entity.d.ts +3 -0
  127. package/training-management/lib/entities/training-participant/training-participant.service.d.ts +10 -0
  128. package/training-management/lib/entities/training-participant/training-participant.types.d.ts +7 -0
  129. package/training-management/lib/entities/training-type/index.d.ts +3 -0
  130. package/training-management/lib/entities/training-type/training-type.entity.d.ts +3 -0
  131. package/training-management/lib/entities/training-type/training-type.service.d.ts +10 -0
  132. package/training-management/lib/entities/training-type/training-type.types.d.ts +7 -0
  133. package/training-management/lib/entity.provider.d.ts +10 -0
  134. package/training-management/lib/menu.provider.d.ts +5 -0
  135. package/training-management/lib/permission-definition.provider.d.ts +4 -0
  136. package/training-management/lib/search-command.provider.d.ts +4 -0
  137. package/training-management/lib/setting.provider.d.ts +4 -0
  138. package/training-management/lib/training-management.module.d.ts +6 -0
  139. package/auth/lib/pages/account/avatar/avatar.component.d.ts +0 -20
  140. package/dashboard-management/lib/features/shared/widgets/bar-chart/bar-chart.type.d.ts +0 -34
  141. package/dashboard-management/lib/features/shared/widgets/donut-chart/donut-chart.type.d.ts +0 -67
  142. package/dashboard-management/lib/features/shared/widgets/gauge-chart/gauge-chart.type.d.ts +0 -29
  143. package/dashboard-management/lib/features/shared/widgets/line-chart/line-chart.type.d.ts +0 -41
  144. package/dashboard-management/lib/features/shared/widgets/notification/notification-widget.config.d.ts +0 -10
  145. package/dashboard-management/lib/features/shared/widgets/notification/notification.type.d.ts +0 -47
  146. package/dashboard-management/lib/features/shared/widgets/shared/chart-base.component.d.ts +0 -44
  147. package/dashboard-management/lib/features/shared/widgets/shared/chart-base.type.d.ts +0 -37
  148. package/dashboard-management/lib/features/shared/widgets/shared/components/chart-tooltip/chart-tooltip.component.d.ts +0 -28
  149. package/dashboard-management/lib/features/shared/widgets/shared/components/chart-tooltip/index.d.ts +0 -1
  150. package/dashboard-management/lib/features/shared/widgets/shared/index.d.ts +0 -3
  151. package/fesm2022/acorex-modules-auth-acorex-modules-auth-B1HTJdsE.mjs.map +0 -1
  152. package/fesm2022/acorex-modules-auth-app-chooser.component-Ct-vco0y.mjs +0 -64
  153. package/fesm2022/acorex-modules-auth-app-chooser.component-Ct-vco0y.mjs.map +0 -1
  154. package/fesm2022/acorex-modules-auth-tenant-chooser.component-D9C6LCjn.mjs +0 -97
  155. package/fesm2022/acorex-modules-auth-tenant-chooser.component-D9C6LCjn.mjs.map +0 -1
  156. package/fesm2022/acorex-modules-dashboard-management-acorex-modules-dashboard-management-CReOsVhq.mjs.map +0 -1
  157. package/fesm2022/acorex-modules-dashboard-management-home-dashboard-CHXDeuSF.mjs.map +0 -1
  158. package/fesm2022/acorex-modules-platform-management-acorex-modules-platform-management-DIsYLKbA.mjs.map +0 -1
  159. package/security-management/lib/entities/profile/profile.service.d.ts +0 -13
@@ -1,34 +1,37 @@
1
1
  import { RootConfig as RootConfig$1 } from '@acorex/modules/text-template-management';
2
2
  import * as i1$2 from '@acorex/platform/common';
3
3
  import { AXPEntityCommandScope, AXPEntityQueryType, AXPComponentSlotModule, AXP_MENU_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER } from '@acorex/platform/common';
4
- import { AXPWidgetsCatalog } from '@acorex/platform/layout/builder';
4
+ import * as i2$1 from '@acorex/platform/layout/builder';
5
+ import { AXPWidgetsCatalog, AXPValueWidgetComponent, cloneProperty, AXPWidgetGroupEnum, AXPLayoutBuilderModule } from '@acorex/platform/layout/builder';
5
6
  import { AXMEntityCrudServiceImpl, AXPEntityService, AXP_ENTITY_DEFINITION_LOADER, AXPEntityStorageService, AXPEntityDataProviderImpl } from '@acorex/platform/layout/entity';
6
7
  import * as i0 from '@angular/core';
7
- import { Injectable, NgModule, inject, input, output, computed, ChangeDetectionStrategy, Component, signal, effect, Injector } from '@angular/core';
8
+ import { Injectable, NgModule, inject, signal, computed, effect, input, output, ChangeDetectionStrategy, Component, Injector, ChangeDetectorRef } from '@angular/core';
8
9
  import { AXPSessionService } from '@acorex/platform/auth';
9
10
  import { firstValueFrom } from 'rxjs';
10
- import * as i4$1 from '@acorex/components/badge';
11
+ import * as i4 from '@acorex/components/badge';
11
12
  import { AXBadgeModule } from '@acorex/components/badge';
12
13
  import * as i1$1 from '@acorex/components/button';
13
14
  import { AXButtonModule } from '@acorex/components/button';
14
- import * as i2 from '@acorex/components/decorators';
15
+ import * as i3 from '@acorex/components/decorators';
15
16
  import { AXDecoratorModule } from '@acorex/components/decorators';
16
- import * as i4$2 from '@acorex/components/popover';
17
+ import * as i4$1 from '@acorex/components/popover';
17
18
  import { AXPopoverModule } from '@acorex/components/popover';
18
19
  import * as i1 from '@angular/common';
19
- import { CommonModule } from '@angular/common';
20
- import * as i2$1 from '@acorex/components/tabs';
20
+ import { CommonModule, DatePipe } from '@angular/common';
21
+ import * as i2 from '@acorex/components/tabs';
21
22
  import { AXTabsModule } from '@acorex/components/tabs';
22
23
  import { AXToastService } from '@acorex/components/toast';
23
- import * as i5 from '@acorex/core/format';
24
+ import * as i3$1 from '@acorex/core/format';
24
25
  import { AXFormatModule } from '@acorex/core/format';
25
26
  import { Router } from '@angular/router';
26
- import * as i3 from '@acorex/components/avatar';
27
- import { AXAvatarModule } from '@acorex/components/avatar';
28
- import * as i4 from '@acorex/components/image';
29
27
  import { AXImageModule } from '@acorex/components/image';
28
+ import { AXPUserAvatarComponent } from '@acorex/platform/layout/components';
29
+ import { AXAvatarModule } from '@acorex/components/avatar';
30
+ import * as i5 from '@acorex/core/translation';
31
+ import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
32
+ import { AXP_WIDGETS_UTILITY_CATEGORY } from '@acorex/modules/dashboard-management';
33
+ import { AXP_APPEARANCE_PROPERTY_GROUP, AXP_STYLING_PROPERTY_GROUP, AXP_DATA_PATH_PROPERTY } from '@acorex/platform/widgets';
30
34
  import { RootConfig as RootConfig$2 } from '@acorex/modules/form-template-management';
31
- import { AXTranslationService } from '@acorex/core/translation';
32
35
  import { AXPWidgetsList } from '@acorex/modules/common';
33
36
  import { AXPDataGenerator } from '@acorex/platform/core';
34
37
 
@@ -1442,6 +1445,215 @@ class AXMNotificationManagmentModuleMenuProvider {
1442
1445
  }
1443
1446
  }
1444
1447
 
1448
+ /**
1449
+ * Signal store that provides a reactive interface for notification-related operations
1450
+ * Acts as a layer between notification components and the entity service
1451
+ */
1452
+ class AXMNotificationConnectorService {
1453
+ // Effects
1454
+ constructor() {
1455
+ this.notificationService = inject(AXMNotificationEntityService);
1456
+ // State signals
1457
+ this.isLoading = signal(false);
1458
+ this.error = signal(null);
1459
+ this.notifications = signal([]);
1460
+ this.totalCount = signal(0);
1461
+ // Public computed signals
1462
+ this.loading = computed(() => this.isLoading());
1463
+ this.errorMessage = computed(() => this.error());
1464
+ this.notificationList = computed(() => this.notifications());
1465
+ this.total = computed(() => this.totalCount());
1466
+ this.unreadCount = computed(() => this.notifications().filter((notification) => notification.readAt === null).length);
1467
+ // Auto-fetch notifications when service is initialized
1468
+ effect(() => {
1469
+ this.getList();
1470
+ });
1471
+ }
1472
+ // Methods from entity service with additional state management
1473
+ /**
1474
+ * Get list of notifications
1475
+ */
1476
+ async getList() {
1477
+ try {
1478
+ this.isLoading.set(true);
1479
+ this.error.set(null);
1480
+ const response = await this.notificationService.getList();
1481
+ this.notifications.set(response.items);
1482
+ this.totalCount.set(response.total);
1483
+ return response;
1484
+ }
1485
+ catch (err) {
1486
+ this.error.set(err instanceof Error ? err.message : 'Failed to fetch notifications');
1487
+ return { total: 0, items: [] };
1488
+ }
1489
+ finally {
1490
+ this.isLoading.set(false);
1491
+ }
1492
+ }
1493
+ /**
1494
+ * Mark notifications as read or toggle read status
1495
+ * If no specific IDs are provided, mark all as read
1496
+ * If specific IDs are provided, toggle their read status (mark as read if unread, mark as unread if read)
1497
+ */
1498
+ async markAsRead(payload = { id: [] }) {
1499
+ try {
1500
+ this.isLoading.set(true);
1501
+ this.error.set(null);
1502
+ await this.notificationService.markAsRead(payload);
1503
+ // Update local state to reflect toggled read status
1504
+ if (payload?.id?.length) {
1505
+ // Toggle read status for specific notifications
1506
+ this.notifications.update((notifications) => notifications.map((notification) => {
1507
+ if (payload.id.includes(notification.id)) {
1508
+ // Toggle read status
1509
+ return {
1510
+ ...notification,
1511
+ readAt: notification.readAt ? null : new Date(),
1512
+ };
1513
+ }
1514
+ return notification;
1515
+ }));
1516
+ }
1517
+ else {
1518
+ // If no specific IDs are provided, mark all unread notifications as read
1519
+ this.notifications.update((notifications) => notifications.map((notification) => notification.readAt ? notification : { ...notification, readAt: new Date() }));
1520
+ }
1521
+ }
1522
+ catch (err) {
1523
+ this.error.set(err instanceof Error ? err.message : 'Failed to mark notifications as read');
1524
+ }
1525
+ finally {
1526
+ this.isLoading.set(false);
1527
+ }
1528
+ }
1529
+ /**
1530
+ * Create a new notification
1531
+ */
1532
+ async create(payload) {
1533
+ try {
1534
+ this.isLoading.set(true);
1535
+ this.error.set(null);
1536
+ await this.notificationService.create(payload);
1537
+ // Refresh list after creating a notification
1538
+ await this.getList();
1539
+ }
1540
+ catch (err) {
1541
+ this.error.set(err instanceof Error ? err.message : 'Failed to create notification');
1542
+ }
1543
+ finally {
1544
+ this.isLoading.set(false);
1545
+ }
1546
+ }
1547
+ // Methods from AXMEntityCrudServiceImpl
1548
+ /**
1549
+ * Insert one notification
1550
+ */
1551
+ async insertOne(request) {
1552
+ try {
1553
+ this.isLoading.set(true);
1554
+ this.error.set(null);
1555
+ const id = await this.notificationService.insertOne(request);
1556
+ // Refresh list after inserting
1557
+ await this.getList();
1558
+ return id;
1559
+ }
1560
+ catch (err) {
1561
+ this.error.set(err instanceof Error ? err.message : 'Failed to insert notification');
1562
+ throw err;
1563
+ }
1564
+ finally {
1565
+ this.isLoading.set(false);
1566
+ }
1567
+ }
1568
+ /**
1569
+ * Get one notification by id
1570
+ */
1571
+ async getOne(id) {
1572
+ try {
1573
+ this.isLoading.set(true);
1574
+ this.error.set(null);
1575
+ return await this.notificationService.getOne(id);
1576
+ }
1577
+ catch (err) {
1578
+ this.error.set(err instanceof Error ? err.message : `Failed to get notification with id ${id}`);
1579
+ throw err;
1580
+ }
1581
+ finally {
1582
+ this.isLoading.set(false);
1583
+ }
1584
+ }
1585
+ /**
1586
+ * Delete one notification
1587
+ */
1588
+ async deleteOne(id) {
1589
+ try {
1590
+ this.isLoading.set(true);
1591
+ this.error.set(null);
1592
+ await this.notificationService.deleteOne(id);
1593
+ // Update local state to remove deleted notification
1594
+ this.notifications.update((notifications) => notifications.filter((notification) => notification.id !== id));
1595
+ // Update total count
1596
+ this.totalCount.update((count) => count - 1);
1597
+ }
1598
+ catch (err) {
1599
+ this.error.set(err instanceof Error ? err.message : `Failed to delete notification with id ${id}`);
1600
+ throw err;
1601
+ }
1602
+ finally {
1603
+ this.isLoading.set(false);
1604
+ }
1605
+ }
1606
+ /**
1607
+ * Update one notification
1608
+ */
1609
+ async updateOne(id, values) {
1610
+ try {
1611
+ this.isLoading.set(true);
1612
+ this.error.set(null);
1613
+ const updated = await this.notificationService.updateOne(id, values);
1614
+ // Update local state to reflect changes
1615
+ this.notifications.update((notifications) => notifications.map((notification) => notification.id === id ? { ...notification, ...values } : notification));
1616
+ return updated;
1617
+ }
1618
+ catch (err) {
1619
+ this.error.set(err instanceof Error ? err.message : `Failed to update notification with id ${id}`);
1620
+ throw err;
1621
+ }
1622
+ finally {
1623
+ this.isLoading.set(false);
1624
+ }
1625
+ }
1626
+ /**
1627
+ * Query notifications
1628
+ */
1629
+ async query(request = { skip: 0, take: 100 }) {
1630
+ try {
1631
+ this.isLoading.set(true);
1632
+ this.error.set(null);
1633
+ const result = await this.notificationService.query(request);
1634
+ // Update local state with query results
1635
+ this.notifications.set(result.items);
1636
+ this.totalCount.set(result.total);
1637
+ return result;
1638
+ }
1639
+ catch (err) {
1640
+ this.error.set(err instanceof Error ? err.message : 'Failed to query notifications');
1641
+ throw err;
1642
+ }
1643
+ finally {
1644
+ this.isLoading.set(false);
1645
+ }
1646
+ }
1647
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMNotificationConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1648
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMNotificationConnectorService, providedIn: 'root' }); }
1649
+ }
1650
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMNotificationConnectorService, decorators: [{
1651
+ type: Injectable,
1652
+ args: [{
1653
+ providedIn: 'root',
1654
+ }]
1655
+ }], ctorParameters: () => [] });
1656
+
1445
1657
  class AXMAdminNotificationItemComponent {
1446
1658
  constructor() {
1447
1659
  this.data = input.required();
@@ -1452,7 +1664,7 @@ class AXMAdminNotificationItemComponent {
1452
1664
  this.onPressNotificationItem.emit(id);
1453
1665
  }
1454
1666
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMAdminNotificationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1455
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXMAdminNotificationItemComponent, isStandalone: true, selector: "axp-master-notification-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onPressNotificationItem: "onPressNotificationItem" }, ngImport: i0, template: "<div\n class=\"notification-item\"\n [id]=\"data().id\"\n (click)=\"pressNotificationItem(data().id)\"\n [class]=\"[data().template.prority, data().readAt ? 'read' : 'unread']\"\n>\n <ax-avatar shape=\"rounded\" color=\"primary\">\n @if(data().user.image){\n <ax-image src=\"https://i.pravatar.cc/300\"></ax-image>\n }@else {\n <ax-icon>\n <i class=\"fa-solid fa-lock\"></i>\n </ax-icon>\n }\n </ax-avatar>\n <div>\n <div class=\"notification-item-title\">{{ data().title }}</div>\n <div class=\"notification-item-body\">{{ data().body }}</div>\n <!-- @if(false){\n <div>\n <div class=\"notification-file\">\n <ax-avatar color=\"primary\">\n <ax-icon>\n <i class=\"fa-solid fa-file-word ax-text-2xl\"></i>\n </ax-icon>\n </ax-avatar>\n <div>\n <div class=\"notification-file-name\">New project details.docx</div>\n <div class=\"notification-file-size\">250 KB</div>\n </div>\n <ax-button look=\"blank\">\n <ax-icon>\n <i class=\"fa-solid fa-download\"></i>\n </ax-icon>\n </ax-button>\n </div>\n </div>\n } -->\n <div class=\"notification-item-time\">{{ differentTime() | format : 'timeleft' | async }}</div>\n </div>\n @if(!data().template.isPinned){\n <div class=\"pin-notification ltr:ax-rotate-45 rtl:ax-left-0 rtl:-ax-rotate-45 ltr:ax-right-0\">\n <ax-icon>\n <i class=\"fa-solid fa-thumbtack\"></i>\n </ax-icon>\n </div>\n }\n</div>\n", styles: [".notification-item{position:relative;display:flex;cursor:pointer;align-items:center;gap:.75rem;overflow-x:hidden;padding:1rem}.notification-item.read{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.notification-item.unread{background:rgb(var(--ax-color-on-surface))}.notification-item.Notice:before,.notification-item.Danger:before,.notification-item.Warning:before{content:\"\";position:absolute;height:95%;width:.2rem;inset-inline-start:0;top:50%;transform:translateY(-50%)}.notification-item.Notice:before{background:rgb(var(--ax-color-success-500))}.notification-item.Danger:before{background:rgb(var(--ax-color-danger-500))}.notification-item.Warning:before{background:rgb(var(--ax-color-warning-500))}.notification-item ax-avatar ax-badge{position:absolute;bottom:0;inset-inline-end:.25rem;top:auto;border-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1))}.notification-item>div{display:flex;flex:1 1 0%;flex-direction:column}.notification-item>div .notification-item-title,.notification-item>div .notification-file-name{max-width:20rem;font-size:1rem;font-weight:600;line-height:1.5rem}.notification-item>div .notification-item-time,.notification-item>div .notification-file-size{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.notification-item>div .notification-item-body{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;max-width:20rem;font-size:.875rem;font-weight:400;line-height:1.5rem}.notification-item>ax-badge{position:absolute;top:1rem;inset-inline-end:1rem}.notification-item .notification-file{margin-top:.5rem;margin-bottom:.5rem;display:flex;gap:.5rem;border-radius:.5rem;border-width:1px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-surface),var(--tw-bg-opacity, 1));padding:.5rem}.notification-item .notification-file>div{flex:1 1 0%}.notification-item .pin-notification{position:absolute;top:0;padding:1rem;--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "component", type: i3.AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXImageModule }, { kind: "component", type: i4.AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "pipe", type: i5.AXFormatPipe, name: "format" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1667
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXMAdminNotificationItemComponent, isStandalone: true, selector: "axp-master-notification-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onPressNotificationItem: "onPressNotificationItem" }, ngImport: i0, template: "<div\n class=\"notification-item\"\n [id]=\"data().id\"\n (click)=\"pressNotificationItem(data().id)\"\n [class]=\"[data().template.prority, data().readAt ? 'read' : 'unread']\"\n>\n <axp-user-avatar [size]=\"40\" [userId]=\"data().user.id!\"></axp-user-avatar>\n <div>\n <div class=\"notification-item-title\">{{ data().user.name || data().title }}</div>\n <div class=\"notification-item-body\">{{ data().body }}</div>\n <!-- @if(false){\n <div>\n <div class=\"notification-file\">\n <ax-avatar color=\"primary\">\n <ax-icon>\n <i class=\"fa-solid fa-file-word ax-text-2xl\"></i>\n </ax-icon>\n </ax-avatar>\n <div>\n <div class=\"notification-file-name\">New project details.docx</div>\n <div class=\"notification-file-size\">250 KB</div>\n </div>\n <ax-button look=\"blank\">\n <ax-icon>\n <i class=\"fa-solid fa-download\"></i>\n </ax-icon>\n </ax-button>\n </div>\n </div>\n } -->\n <div class=\"notification-item-time\">{{ differentTime() | format : 'timeleft' | async }}</div>\n </div>\n @if(!data().template.isPinned){\n <div class=\"pin-notification ltr:ax-rotate-45 rtl:ax-left-0 rtl:-ax-rotate-45 ltr:ax-right-0\">\n <ax-icon>\n <i class=\"fa-solid fa-thumbtack\"></i>\n </ax-icon>\n </div>\n }\n</div>\n", styles: [".notification-item{position:relative;display:flex;cursor:pointer;align-items:center;gap:.75rem;overflow-x:hidden;padding:1rem}.notification-item.read{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.notification-item.unread{background:rgb(var(--ax-color-on-surface))}.notification-item.Notice:before,.notification-item.Danger:before,.notification-item.Warning:before{content:\"\";position:absolute;height:95%;width:.2rem;inset-inline-start:0;top:50%;transform:translateY(-50%)}.notification-item.Notice:before{background:rgb(var(--ax-color-success-500))}.notification-item.Danger:before{background:rgb(var(--ax-color-danger-500))}.notification-item.Warning:before{background:rgb(var(--ax-color-warning-500))}.notification-item ax-avatar ax-badge{position:absolute;bottom:0;inset-inline-end:.25rem;top:auto;border-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1))}.notification-item>div{display:flex;flex:1 1 0%;flex-direction:column}.notification-item>div .notification-item-title,.notification-item>div .notification-file-name{max-width:20rem;font-size:1rem;font-weight:600;line-height:1.5rem}.notification-item>div .notification-item-time,.notification-item>div .notification-file-size{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.notification-item>div .notification-item-body{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;max-width:20rem;font-size:.875rem;font-weight:400;line-height:1.5rem}.notification-item>ax-badge{position:absolute;top:1rem;inset-inline-end:1rem}.notification-item .notification-file{margin-top:.5rem;margin-bottom:.5rem;display:flex;gap:.5rem;border-radius:.5rem;border-width:1px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-surface),var(--tw-bg-opacity, 1));padding:.5rem}.notification-item .notification-file>div{flex:1 1 0%}.notification-item .pin-notification{position:absolute;top:0;padding:1rem;--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId"] }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "pipe", type: i3$1.AXFormatPipe, name: "format" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1456
1668
  }
1457
1669
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMAdminNotificationItemComponent, decorators: [{
1458
1670
  type: Component,
@@ -1460,26 +1672,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
1460
1672
  CommonModule,
1461
1673
  AXButtonModule,
1462
1674
  AXDecoratorModule,
1463
- AXAvatarModule,
1675
+ AXPUserAvatarComponent,
1464
1676
  AXImageModule,
1465
1677
  AXBadgeModule,
1466
1678
  AXFormatModule,
1467
- ], template: "<div\n class=\"notification-item\"\n [id]=\"data().id\"\n (click)=\"pressNotificationItem(data().id)\"\n [class]=\"[data().template.prority, data().readAt ? 'read' : 'unread']\"\n>\n <ax-avatar shape=\"rounded\" color=\"primary\">\n @if(data().user.image){\n <ax-image src=\"https://i.pravatar.cc/300\"></ax-image>\n }@else {\n <ax-icon>\n <i class=\"fa-solid fa-lock\"></i>\n </ax-icon>\n }\n </ax-avatar>\n <div>\n <div class=\"notification-item-title\">{{ data().title }}</div>\n <div class=\"notification-item-body\">{{ data().body }}</div>\n <!-- @if(false){\n <div>\n <div class=\"notification-file\">\n <ax-avatar color=\"primary\">\n <ax-icon>\n <i class=\"fa-solid fa-file-word ax-text-2xl\"></i>\n </ax-icon>\n </ax-avatar>\n <div>\n <div class=\"notification-file-name\">New project details.docx</div>\n <div class=\"notification-file-size\">250 KB</div>\n </div>\n <ax-button look=\"blank\">\n <ax-icon>\n <i class=\"fa-solid fa-download\"></i>\n </ax-icon>\n </ax-button>\n </div>\n </div>\n } -->\n <div class=\"notification-item-time\">{{ differentTime() | format : 'timeleft' | async }}</div>\n </div>\n @if(!data().template.isPinned){\n <div class=\"pin-notification ltr:ax-rotate-45 rtl:ax-left-0 rtl:-ax-rotate-45 ltr:ax-right-0\">\n <ax-icon>\n <i class=\"fa-solid fa-thumbtack\"></i>\n </ax-icon>\n </div>\n }\n</div>\n", styles: [".notification-item{position:relative;display:flex;cursor:pointer;align-items:center;gap:.75rem;overflow-x:hidden;padding:1rem}.notification-item.read{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.notification-item.unread{background:rgb(var(--ax-color-on-surface))}.notification-item.Notice:before,.notification-item.Danger:before,.notification-item.Warning:before{content:\"\";position:absolute;height:95%;width:.2rem;inset-inline-start:0;top:50%;transform:translateY(-50%)}.notification-item.Notice:before{background:rgb(var(--ax-color-success-500))}.notification-item.Danger:before{background:rgb(var(--ax-color-danger-500))}.notification-item.Warning:before{background:rgb(var(--ax-color-warning-500))}.notification-item ax-avatar ax-badge{position:absolute;bottom:0;inset-inline-end:.25rem;top:auto;border-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1))}.notification-item>div{display:flex;flex:1 1 0%;flex-direction:column}.notification-item>div .notification-item-title,.notification-item>div .notification-file-name{max-width:20rem;font-size:1rem;font-weight:600;line-height:1.5rem}.notification-item>div .notification-item-time,.notification-item>div .notification-file-size{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.notification-item>div .notification-item-body{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;max-width:20rem;font-size:.875rem;font-weight:400;line-height:1.5rem}.notification-item>ax-badge{position:absolute;top:1rem;inset-inline-end:1rem}.notification-item .notification-file{margin-top:.5rem;margin-bottom:.5rem;display:flex;gap:.5rem;border-radius:.5rem;border-width:1px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-surface),var(--tw-bg-opacity, 1));padding:.5rem}.notification-item .notification-file>div{flex:1 1 0%}.notification-item .pin-notification{position:absolute;top:0;padding:1rem;--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}\n"] }]
1679
+ ], template: "<div\n class=\"notification-item\"\n [id]=\"data().id\"\n (click)=\"pressNotificationItem(data().id)\"\n [class]=\"[data().template.prority, data().readAt ? 'read' : 'unread']\"\n>\n <axp-user-avatar [size]=\"40\" [userId]=\"data().user.id!\"></axp-user-avatar>\n <div>\n <div class=\"notification-item-title\">{{ data().user.name || data().title }}</div>\n <div class=\"notification-item-body\">{{ data().body }}</div>\n <!-- @if(false){\n <div>\n <div class=\"notification-file\">\n <ax-avatar color=\"primary\">\n <ax-icon>\n <i class=\"fa-solid fa-file-word ax-text-2xl\"></i>\n </ax-icon>\n </ax-avatar>\n <div>\n <div class=\"notification-file-name\">New project details.docx</div>\n <div class=\"notification-file-size\">250 KB</div>\n </div>\n <ax-button look=\"blank\">\n <ax-icon>\n <i class=\"fa-solid fa-download\"></i>\n </ax-icon>\n </ax-button>\n </div>\n </div>\n } -->\n <div class=\"notification-item-time\">{{ differentTime() | format : 'timeleft' | async }}</div>\n </div>\n @if(!data().template.isPinned){\n <div class=\"pin-notification ltr:ax-rotate-45 rtl:ax-left-0 rtl:-ax-rotate-45 ltr:ax-right-0\">\n <ax-icon>\n <i class=\"fa-solid fa-thumbtack\"></i>\n </ax-icon>\n </div>\n }\n</div>\n", styles: [".notification-item{position:relative;display:flex;cursor:pointer;align-items:center;gap:.75rem;overflow-x:hidden;padding:1rem}.notification-item.read{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.notification-item.unread{background:rgb(var(--ax-color-on-surface))}.notification-item.Notice:before,.notification-item.Danger:before,.notification-item.Warning:before{content:\"\";position:absolute;height:95%;width:.2rem;inset-inline-start:0;top:50%;transform:translateY(-50%)}.notification-item.Notice:before{background:rgb(var(--ax-color-success-500))}.notification-item.Danger:before{background:rgb(var(--ax-color-danger-500))}.notification-item.Warning:before{background:rgb(var(--ax-color-warning-500))}.notification-item ax-avatar ax-badge{position:absolute;bottom:0;inset-inline-end:.25rem;top:auto;border-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-surface),var(--tw-border-opacity, 1))}.notification-item>div{display:flex;flex:1 1 0%;flex-direction:column}.notification-item>div .notification-item-title,.notification-item>div .notification-file-name{max-width:20rem;font-size:1rem;font-weight:600;line-height:1.5rem}.notification-item>div .notification-item-time,.notification-item>div .notification-file-size{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.notification-item>div .notification-item-body{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;max-width:20rem;font-size:.875rem;font-weight:400;line-height:1.5rem}.notification-item>ax-badge{position:absolute;top:1rem;inset-inline-end:1rem}.notification-item .notification-file{margin-top:.5rem;margin-bottom:.5rem;display:flex;gap:.5rem;border-radius:.5rem;border-width:1px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-surface),var(--tw-bg-opacity, 1));padding:.5rem}.notification-item .notification-file>div{flex:1 1 0%}.notification-item .pin-notification{position:absolute;top:0;padding:1rem;--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}\n"] }]
1468
1680
  }] });
1469
1681
 
1470
1682
  class AXMAdminNotificationPanelComponent {
1471
1683
  constructor() {
1472
1684
  this.onNewNotfication = output();
1473
- this.notificationService = inject(AXMNotificationEntityService);
1685
+ this.notificationConnector = inject(AXMNotificationConnectorService);
1474
1686
  this.toastService = inject(AXToastService);
1475
1687
  this.router = inject(Router);
1476
1688
  this.sessionService = inject(AXPSessionService);
1477
- this.notifications = signal(undefined);
1478
- this.totalNotifications = signal(undefined);
1689
+ // Use store's signals directly
1690
+ this.notifications = this.notificationConnector.notificationList;
1691
+ this.totalNotifications = this.notificationConnector.total;
1692
+ this.isLoading = this.notificationConnector.loading;
1693
+ this.errorMessage = this.notificationConnector.errorMessage;
1694
+ this.activeTab = signal('All');
1479
1695
  this.tabItems = computed(() => this.getTabItems(this.notifications()), {
1480
1696
  equal: (a, b) => JSON.stringify(a) === JSON.stringify(b),
1481
1697
  });
1482
- this.activeTab = signal('All');
1483
1698
  this.NewNotification = computed(() => this.getNewNotification(this.tabItems()));
1484
1699
  this.NewNotificationEffect = effect(() => this.onNewNotfication.emit(this.NewNotification()));
1485
1700
  }
@@ -1491,15 +1706,7 @@ class AXMAdminNotificationPanelComponent {
1491
1706
  }
1492
1707
  async loadNotification() {
1493
1708
  try {
1494
- const response = await this.notificationService.getList();
1495
- this.totalNotifications.set(response.total);
1496
- const orderedResponse = response.items.sort((a, b) => {
1497
- if (a.template.isPinned === b.template.isPinned) {
1498
- return new Date(a.createAt).getTime() - new Date(b.createAt).getTime();
1499
- }
1500
- return a.template.isPinned ? 1 : -1;
1501
- });
1502
- this.notifications.set(orderedResponse);
1709
+ await this.notificationConnector.getList();
1503
1710
  }
1504
1711
  catch (error) {
1505
1712
  this.toastService.show({
@@ -1517,7 +1724,6 @@ class AXMAdminNotificationPanelComponent {
1517
1724
  return [
1518
1725
  {
1519
1726
  text: 'All',
1520
- //active: true,
1521
1727
  count: 0,
1522
1728
  },
1523
1729
  ];
@@ -1555,40 +1761,33 @@ class AXMAdminNotificationPanelComponent {
1555
1761
  return this.notifications()?.filter((item) => item.template.category === category);
1556
1762
  }
1557
1763
  }
1558
- //
1764
+ /**
1765
+ * Mark a notification as read or unread (toggle read status)
1766
+ */
1559
1767
  async markAsRead(id) {
1560
1768
  try {
1561
- const payload = { id: [id] };
1562
- await this.notificationService.markAsRead(payload);
1563
- this.toggleRead(id);
1769
+ await this.notificationConnector.markAsRead({ id: [id] });
1770
+ }
1771
+ catch (error) {
1772
+ console.error('Failed to toggle notification read status:', error);
1564
1773
  }
1565
- catch (error) { }
1566
- }
1567
- toggleRead(id) {
1568
- this.notifications.update((old) => old?.map((item) => (item.id === id ? { ...item, readAt: item.readAt ? null : new Date() } : item)));
1569
1774
  }
1775
+ /**
1776
+ * Mark all unread notifications as read
1777
+ */
1570
1778
  async markAllAsRead() {
1571
1779
  try {
1572
- await this.notificationService.markAsRead();
1573
- this.toggleMarkAllAsRead();
1780
+ await this.notificationConnector.markAsRead({ id: [] });
1574
1781
  }
1575
1782
  catch (error) {
1576
- console.error(error);
1783
+ console.error('Failed to mark all notifications as read:', error);
1577
1784
  }
1578
1785
  }
1579
- toggleMarkAllAsRead() {
1580
- this.notifications.update((notification) => notification?.map((item) => {
1581
- if (!item.readAt) {
1582
- return { ...item, readAt: new Date() };
1583
- }
1584
- return item;
1585
- }));
1586
- }
1587
1786
  viewAllNotifications() {
1588
1787
  this.router.navigate([`${this.sessionService.application?.name}/m/notification-management/e/my-notification/list`]);
1589
1788
  }
1590
1789
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMAdminNotificationPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1591
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXMAdminNotificationPanelComponent, isStandalone: true, selector: "axm-admin-notification-panel", outputs: { onNewNotfication: "onNewNotfication" }, ngImport: i0, template: "<div class=\"ax-p-4 ax-flex ax-justify-between ax-items-center\">\n <span class=\"ax-text-xl\">Notifications</span>\n <ax-button color=\"default\" look=\"blank\">\n <ax-icon>\n <i class=\"fa-regular fa-gear fa-lg\"></i>\n </ax-icon>\n </ax-button>\n</div>\n<ax-tabs [content]=\"cons\" look=\"with-line\" location=\"bottom\">\n @for(tab of tabItems(); track tab.text){\n <ax-tab-item [text]=\"tab.text\" [active]=\"activeTab() === tab.text\" (activeChange)=\"changeActiveTab(tab.text)\">\n <ax-suffix>\n @if(tab.count){\n <ax-badge [color]=\"activeTab() === tab.text ? 'primary' : 'ghost'\" [text]=\"tab.count.toString()\"></ax-badge>\n }\n </ax-suffix>\n <ax-content>\n <div class=\"ax-max-h-[50vh] ax-overflow-y-auto\">\n @for(notif of getNotificationItems(tab.text); track notif.id){\n <axp-master-notification-item\n [data]=\"notif\"\n (onPressNotificationItem)=\"markAsRead($event)\"\n ></axp-master-notification-item>\n }\n </div>\n <div class=\"ax-flex ax-gap-4 ax-justify-between ax-p-4 ax-border-t ax-border-default\">\n <ax-button\n [disabled]=\"NewNotification() === 0\"\n [color]=\"'default'\"\n text=\"Mark all as read\"\n (onClick)=\"markAllAsRead()\"\n ></ax-button>\n <ax-button color=\"primary\" text=\"View all notifications\" (onClick)=\"viewAllNotifications()\"></ax-button>\n </div>\n </ax-content>\n </ax-tab-item>\n }\n</ax-tabs>\n\n<ng-template [axTabContent] #cons=\"axTabContent\"></ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i2$1.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i2$1.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "directive", type: i2$1.AXTabContentDirective, selector: "[axTabContent]", inputs: ["axTabContent"], exportAs: ["axTabContent"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: AXMAdminNotificationItemComponent, selector: "axp-master-notification-item", inputs: ["data"], outputs: ["onPressNotificationItem"] }, { kind: "ngmodule", type: AXFormatModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1790
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXMAdminNotificationPanelComponent, isStandalone: true, selector: "axm-admin-notification-panel", outputs: { onNewNotfication: "onNewNotfication" }, ngImport: i0, template: "<div class=\"ax-p-4 ax-flex ax-justify-between ax-items-center\">\n <span class=\"ax-text-xl\">Notifications</span>\n <ax-button color=\"default\" look=\"blank\">\n <ax-icon>\n <i class=\"fa-regular fa-gear fa-lg\"></i>\n </ax-icon>\n </ax-button>\n</div>\n<ax-tabs [content]=\"cons\" look=\"with-line\" location=\"bottom\">\n @for(tab of tabItems(); track tab.text){\n <ax-tab-item [text]=\"tab.text\" [active]=\"activeTab() === tab.text\" (activeChange)=\"changeActiveTab(tab.text)\">\n <ax-suffix>\n @if(tab.count){\n <ax-badge [color]=\"activeTab() === tab.text ? 'primary' : 'ghost'\" [text]=\"tab.count.toString()\"></ax-badge>\n }\n </ax-suffix>\n <ax-content>\n <div class=\"ax-max-h-[50vh] ax-overflow-y-auto\">\n @for(notif of getNotificationItems(tab.text); track notif.id){\n <axp-master-notification-item\n [data]=\"notif\"\n (onPressNotificationItem)=\"markAsRead($event)\"\n ></axp-master-notification-item>\n }\n </div>\n <div class=\"ax-flex ax-gap-4 ax-justify-between ax-p-4 ax-border-t ax-border-default\">\n <ax-button\n [disabled]=\"NewNotification() === 0\"\n [color]=\"'default'\"\n text=\"Mark all as read\"\n (onClick)=\"markAllAsRead()\"\n ></ax-button>\n <ax-button color=\"primary\" text=\"View all notifications\" (onClick)=\"viewAllNotifications()\"></ax-button>\n </div>\n </ax-content>\n </ax-tab-item>\n }\n</ax-tabs>\n\n<ng-template [axTabContent] #cons=\"axTabContent\"></ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i2.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i2.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "directive", type: i2.AXTabContentDirective, selector: "[axTabContent]", inputs: ["axTabContent"], exportAs: ["axTabContent"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: AXMAdminNotificationItemComponent, selector: "axp-master-notification-item", inputs: ["data"], outputs: ["onPressNotificationItem"] }, { kind: "ngmodule", type: AXFormatModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1592
1791
  }
1593
1792
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMAdminNotificationPanelComponent, decorators: [{
1594
1793
  type: Component,
@@ -1612,7 +1811,7 @@ class AXMAdminNotificationSlotComponent {
1612
1811
  this.totalNewNotification.set(value);
1613
1812
  }
1614
1813
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMAdminNotificationSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1615
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXMAdminNotificationSlotComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<ax-button class=\"ax-relative\" color=\"primary\" #notification>\n <ax-icon>\n <i class=\"fa-regular fa-bell\"></i>\n </ax-icon>\n <ax-suffix class=\"ax-absolute ax-top-0 ax-left-1/2\">\n @if(totalNewNotification()){\n <ax-badge color=\"success\" [text]=\"totalNewNotification().toString()\"></ax-badge>\n }\n </ax-suffix>\n</ax-button>\n<ax-popover [target]=\"notification\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"ax-bg-lightest ax-border ax-border-default ax-rounded-md ax-shadow-md ax-w-full\">\n <axm-admin-notification-panel (onNewNotfication)=\"setTotalNewNotification($event)\"> </axm-admin-notification-panel>\n </div>\n</ax-popover>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i4$2.AXPopoverComponent, selector: "ax-popover", inputs: ["offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXMAdminNotificationPanelComponent, selector: "axm-admin-notification-panel", outputs: ["onNewNotfication"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1814
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXMAdminNotificationSlotComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<ax-button class=\"ax-relative\" color=\"primary\" #notification>\n <ax-icon>\n <i class=\"fa-regular fa-bell\"></i>\n </ax-icon>\n <ax-suffix class=\"ax-absolute ax-top-0 ax-left-1/2\">\n @if(totalNewNotification()){\n <ax-badge color=\"success\" [text]=\"totalNewNotification().toString()\"></ax-badge>\n }\n </ax-suffix>\n</ax-button>\n<ax-popover [target]=\"notification\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"ax-bg-lightest ax-border ax-border-default ax-rounded-md ax-shadow-md ax-w-full\">\n <axm-admin-notification-panel (onNewNotfication)=\"setTotalNewNotification($event)\"> </axm-admin-notification-panel>\n </div>\n</ax-popover>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i4$1.AXPopoverComponent, selector: "ax-popover", inputs: ["offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXMAdminNotificationPanelComponent, selector: "axm-admin-notification-panel", outputs: ["onNewNotfication"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1616
1815
  }
1617
1816
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMAdminNotificationSlotComponent, decorators: [{
1618
1817
  type: Component,
@@ -1676,9 +1875,369 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
1676
1875
  type: Injectable
1677
1876
  }] });
1678
1877
 
1878
+ /**
1879
+ * Notification Widget Component
1880
+ * Displays notifications in a card with tabs
1881
+ */
1882
+ class AXPNotificationWidgetViewComponent extends AXPValueWidgetComponent {
1883
+ constructor() {
1884
+ super();
1885
+ // Outputs
1886
+ this.notificationClick = output();
1887
+ this.markAsRead = output();
1888
+ // Dependencies
1889
+ this.cdr = inject(ChangeDetectorRef);
1890
+ this.datePipe = inject(DatePipe);
1891
+ this.notificationConnector = inject(AXMNotificationConnectorService);
1892
+ this.toastService = inject(AXToastService);
1893
+ // State
1894
+ this.activeTab = signal('new');
1895
+ this.refreshTimerId = null;
1896
+ // Configuration
1897
+ this.maxItems = computed(() => this.options()?.maxItems ?? 10);
1898
+ this.showAvatar = computed(() => this.options()?.showAvatar ?? true);
1899
+ this.showDate = computed(() => this.options()?.showDate ?? true);
1900
+ this.autoRefresh = computed(() => this.options()?.autoRefresh ?? true);
1901
+ this.refreshInterval = computed(() => (this.options()?.refreshInterval ?? 60) * 1000); // Convert to milliseconds
1902
+ // Use store's signals directly
1903
+ this.notifications = this.notificationConnector.notificationList;
1904
+ this.totalNotifications = this.notificationConnector.total;
1905
+ this.isLoading = this.notificationConnector.loading;
1906
+ // Computed data
1907
+ this.notificationItems = computed(() => {
1908
+ const items = this.notifications();
1909
+ if (!items?.length)
1910
+ return [];
1911
+ // Sort by pinned status and date
1912
+ const sortedItems = [...items].sort((a, b) => {
1913
+ if (a.template.isPinned === b.template.isPinned) {
1914
+ return new Date(b.createAt).getTime() - new Date(a.createAt).getTime();
1915
+ }
1916
+ return a.template.isPinned ? -1 : 1;
1917
+ });
1918
+ // Filter by active tab
1919
+ const filtered = this.activeTab() === 'new' ? sortedItems.filter((n) => !n.readAt) : sortedItems;
1920
+ return filtered.slice(0, this.maxItems());
1921
+ });
1922
+ // Watch for changes to auto-refresh settings
1923
+ effect(() => {
1924
+ this.setupAutoRefresh();
1925
+ });
1926
+ }
1927
+ ngOnInit() {
1928
+ this.loadNotifications();
1929
+ }
1930
+ ngOnDestroy() {
1931
+ this.clearRefreshTimer();
1932
+ }
1933
+ /**
1934
+ * Set up auto-refresh timer based on configuration
1935
+ */
1936
+ setupAutoRefresh() {
1937
+ this.clearRefreshTimer();
1938
+ if (this.autoRefresh()) {
1939
+ const interval = this.refreshInterval();
1940
+ this.refreshTimerId = setInterval(() => {
1941
+ this.loadNotifications();
1942
+ }, interval);
1943
+ }
1944
+ }
1945
+ /**
1946
+ * Clear the refresh timer if it exists
1947
+ */
1948
+ clearRefreshTimer() {
1949
+ if (this.refreshTimerId !== null) {
1950
+ clearInterval(this.refreshTimerId);
1951
+ this.refreshTimerId = null;
1952
+ }
1953
+ }
1954
+ /**
1955
+ * Load notifications data from service
1956
+ */
1957
+ async loadNotifications() {
1958
+ try {
1959
+ await this.notificationConnector.getList();
1960
+ this.cdr.detectChanges();
1961
+ }
1962
+ catch (error) {
1963
+ this.toastService.show({
1964
+ content: typeof error === 'string' ? error : 'Failed to load notifications!',
1965
+ color: 'danger',
1966
+ location: 'bottom-center',
1967
+ closeButton: true,
1968
+ timeOut: 3000,
1969
+ timeOutProgress: true,
1970
+ });
1971
+ }
1972
+ }
1973
+ /**
1974
+ * Manually refresh notifications
1975
+ */
1976
+ refreshNotifications() {
1977
+ this.loadNotifications();
1978
+ }
1979
+ /**
1980
+ * Get the count of new messages for the badge
1981
+ */
1982
+ getNewMessageCount() {
1983
+ const items = this.notifications();
1984
+ if (!items?.length)
1985
+ return 0;
1986
+ return items.filter((n) => !n.readAt).length;
1987
+ }
1988
+ /**
1989
+ * Handle tab change event from ax-tabs component
1990
+ * @param data The tab change event data
1991
+ */
1992
+ handleTabChange(data) {
1993
+ const index = data.index;
1994
+ // Map index to tab name: 0 = 'new', 1 = 'all'
1995
+ const tabName = index === 0 ? 'new' : 'all';
1996
+ this.onTabChange(tabName);
1997
+ }
1998
+ /**
1999
+ * Mark all notifications as read
2000
+ */
2001
+ async markAllAsRead() {
2002
+ try {
2003
+ await this.notificationConnector.markAsRead({ id: [] });
2004
+ this.cdr.detectChanges();
2005
+ }
2006
+ catch (error) {
2007
+ this.toastService.show({
2008
+ content: 'Failed to mark notifications as read',
2009
+ color: 'danger',
2010
+ location: 'bottom-center',
2011
+ closeButton: true,
2012
+ timeOut: 3000,
2013
+ });
2014
+ }
2015
+ }
2016
+ /**
2017
+ * Change the active tab
2018
+ */
2019
+ onTabChange(tabName) {
2020
+ this.activeTab.set(tabName);
2021
+ this.cdr.detectChanges();
2022
+ }
2023
+ /**
2024
+ * Handle notification click event
2025
+ */
2026
+ onNotificationClick(notification) {
2027
+ this.markAsReadIfNeeded(notification);
2028
+ this.notificationClick.emit(notification);
2029
+ }
2030
+ /**
2031
+ * Format the timestamp in a user-friendly way
2032
+ */
2033
+ formatTime(date) {
2034
+ if (!date)
2035
+ return '';
2036
+ const dateObj = typeof date === 'string' ? new Date(date) : date;
2037
+ const diffDays = this.getDaysDifference(dateObj);
2038
+ // Format based on how recent the date is
2039
+ if (diffDays === 0)
2040
+ return this.datePipe.transform(dateObj, 'h:mm a') || ''; // Today
2041
+ if (diffDays === 1)
2042
+ return 'Yesterday';
2043
+ if (diffDays < 7)
2044
+ return this.datePipe.transform(dateObj, 'EEE') || ''; // Day of week
2045
+ return this.datePipe.transform(dateObj, 'MM/dd/yyyy') || ''; // Older date
2046
+ }
2047
+ /**
2048
+ * Mark notification as read if needed
2049
+ */
2050
+ async markAsReadIfNeeded(notification) {
2051
+ try {
2052
+ // Always mark as read on click if unread, but don't toggle back to unread
2053
+ if (notification.readAt)
2054
+ return;
2055
+ await this.notificationConnector.markAsRead({ id: [notification.id] });
2056
+ // Emit the updated notification with readAt set
2057
+ // It will be read now because we only call this for unread notifications
2058
+ const updatedNotification = {
2059
+ ...notification,
2060
+ readAt: new Date(),
2061
+ };
2062
+ this.markAsRead.emit(updatedNotification);
2063
+ this.cdr.detectChanges();
2064
+ }
2065
+ catch (error) {
2066
+ console.error('Failed to mark notification as read:', error);
2067
+ }
2068
+ }
2069
+ /**
2070
+ * Calculate days difference from now
2071
+ */
2072
+ getDaysDifference(date) {
2073
+ const now = new Date();
2074
+ const diffMs = now.getTime() - date.getTime();
2075
+ return Math.floor(diffMs / (1000 * 60 * 60 * 24));
2076
+ }
2077
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPNotificationWidgetViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2078
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXPNotificationWidgetViewComponent, isStandalone: true, selector: "ng-component", outputs: { notificationClick: "notificationClick", markAsRead: "markAsRead" }, providers: [DatePipe], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-p-4 ax-size-full\">\n <ax-tabs\n class=\"ax-bg-light-start ax-border-b ax-border-default\"\n [fitParent]=\"true\"\n location=\"bottom\"\n (onActiveTabChanged)=\"handleTabChange($event)\"\n >\n <ax-tab-item [text]=\"('widget.notification.new' | translate | async) ?? 'New'\" class=\"ax-font-medium\">\n <ax-suffix>\n @if (getNewMessageCount() > 0) {\n <ax-badge color=\"primary\" [text]=\"getNewMessageCount().toString()\" size=\"sm\" class=\"ax-ml-1\"></ax-badge>\n }\n </ax-suffix>\n </ax-tab-item>\n <ax-tab-item [text]=\"('widget.notification.all' | translate | async) ?? 'All'\" class=\"ax-font-medium\"></ax-tab-item>\n </ax-tabs>\n <div class=\"ax-space-y-4 ax-mt-4 ax-px-2\">\n @for (item of notificationItems(); track item.id) {\n <ng-container [ngTemplateOutlet]=\"chatItemTemplateRef\" [ngTemplateOutletContext]=\"{ $implicit: item }\">\n </ng-container>\n } @empty {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-py-12 ax-px-4 ax-text-gray-400\">\n <ax-icon class=\"ax-text-4xl ax-mb-3 ax-text-gray-300\">\n <i class=\"fa-light fa-bell-slash\"></i>\n </ax-icon>\n <p class=\"ax-text-center\">{{ 'widget.notification.noNotifications' | translate | async }}</p>\n </div>\n }\n </div>\n</div>\n\n<ng-template #chatItemTemplateRef let-data>\n <div class=\"ax-flex ax-gap-3\">\n @if(showAvatar()){\n <axp-user-avatar [size]=\"40\" [userId]=\"data.user?.id\"></axp-user-avatar>\n }\n <div class=\"ax-overflow-hidden ax-grow ax-text-start\">\n <h6 class=\"ax-pb-2 ax-font-semibold ax-truncate\">{{ data.user?.name || data.title }}</h6>\n <p class=\"ax-text-xs ax-truncate\">{{ data.body }}</p>\n </div>\n @if(showDate()){\n <div class=\"ax-text-xs ax-shrink-0\">\n <span>\n {{ formatTime(data.createdAt) }}\n </span>\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i2.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i2.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2079
+ }
2080
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPNotificationWidgetViewComponent, decorators: [{
2081
+ type: Component,
2082
+ args: [{ standalone: true, imports: [
2083
+ CommonModule,
2084
+ AXTabsModule,
2085
+ AXDecoratorModule,
2086
+ AXButtonModule,
2087
+ AXBadgeModule,
2088
+ AXAvatarModule,
2089
+ AXImageModule,
2090
+ AXTranslationModule,
2091
+ AXPUserAvatarComponent,
2092
+ ], providers: [DatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-p-4 ax-size-full\">\n <ax-tabs\n class=\"ax-bg-light-start ax-border-b ax-border-default\"\n [fitParent]=\"true\"\n location=\"bottom\"\n (onActiveTabChanged)=\"handleTabChange($event)\"\n >\n <ax-tab-item [text]=\"('widget.notification.new' | translate | async) ?? 'New'\" class=\"ax-font-medium\">\n <ax-suffix>\n @if (getNewMessageCount() > 0) {\n <ax-badge color=\"primary\" [text]=\"getNewMessageCount().toString()\" size=\"sm\" class=\"ax-ml-1\"></ax-badge>\n }\n </ax-suffix>\n </ax-tab-item>\n <ax-tab-item [text]=\"('widget.notification.all' | translate | async) ?? 'All'\" class=\"ax-font-medium\"></ax-tab-item>\n </ax-tabs>\n <div class=\"ax-space-y-4 ax-mt-4 ax-px-2\">\n @for (item of notificationItems(); track item.id) {\n <ng-container [ngTemplateOutlet]=\"chatItemTemplateRef\" [ngTemplateOutletContext]=\"{ $implicit: item }\">\n </ng-container>\n } @empty {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-py-12 ax-px-4 ax-text-gray-400\">\n <ax-icon class=\"ax-text-4xl ax-mb-3 ax-text-gray-300\">\n <i class=\"fa-light fa-bell-slash\"></i>\n </ax-icon>\n <p class=\"ax-text-center\">{{ 'widget.notification.noNotifications' | translate | async }}</p>\n </div>\n }\n </div>\n</div>\n\n<ng-template #chatItemTemplateRef let-data>\n <div class=\"ax-flex ax-gap-3\">\n @if(showAvatar()){\n <axp-user-avatar [size]=\"40\" [userId]=\"data.user?.id\"></axp-user-avatar>\n }\n <div class=\"ax-overflow-hidden ax-grow ax-text-start\">\n <h6 class=\"ax-pb-2 ax-font-semibold ax-truncate\">{{ data.user?.name || data.title }}</h6>\n <p class=\"ax-text-xs ax-truncate\">{{ data.body }}</p>\n </div>\n @if(showDate()){\n <div class=\"ax-text-xs ax-shrink-0\">\n <span>\n {{ formatTime(data.createdAt) }}\n </span>\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
2093
+ }], ctorParameters: () => [] });
2094
+
2095
+ var notificationWidget_component = /*#__PURE__*/Object.freeze({
2096
+ __proto__: null,
2097
+ AXPNotificationWidgetViewComponent: AXPNotificationWidgetViewComponent
2098
+ });
2099
+
2100
+ /**
2101
+ * Configuration for the Notification Widget
2102
+ */
2103
+ const AXPMyNotificationDashboardWidget = {
2104
+ name: 'my-notification-dashboard',
2105
+ title: 'My Notification Widget',
2106
+ categories: [AXP_WIDGETS_UTILITY_CATEGORY],
2107
+ groups: [AXPWidgetGroupEnum.DashboardWidget],
2108
+ type: 'dashboard',
2109
+ description: 'Displays notifications in a widget format',
2110
+ icon: 'fa-regular fa-bell',
2111
+ properties: [
2112
+ cloneProperty(AXP_DATA_PATH_PROPERTY, { visible: false }),
2113
+ // ====== Title ======
2114
+ {
2115
+ name: 'title',
2116
+ title: 'Chart Title',
2117
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2118
+ schema: {
2119
+ defaultValue: '',
2120
+ dataType: 'string',
2121
+ interface: {
2122
+ name: 'title',
2123
+ path: 'options.title',
2124
+ type: AXPWidgetsCatalog.text,
2125
+ options: {
2126
+ placeholder: 'Enter chart title',
2127
+ },
2128
+ },
2129
+ },
2130
+ visible: true,
2131
+ },
2132
+ {
2133
+ name: 'maxItems',
2134
+ title: 'Max Items',
2135
+ description: 'Maximum number of notification items to display',
2136
+ group: AXP_STYLING_PROPERTY_GROUP,
2137
+ schema: {
2138
+ defaultValue: 10,
2139
+ dataType: 'number',
2140
+ interface: {
2141
+ name: 'maxItems',
2142
+ path: 'options.maxItems',
2143
+ type: AXPWidgetsCatalog.number,
2144
+ options: {
2145
+ minValue: 1,
2146
+ maxValue: 100,
2147
+ },
2148
+ },
2149
+ },
2150
+ visible: true,
2151
+ },
2152
+ {
2153
+ name: 'showAvatar',
2154
+ title: 'Show Avatar',
2155
+ description: 'Whether to show avatars in notifications',
2156
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2157
+ schema: {
2158
+ defaultValue: true,
2159
+ dataType: 'boolean',
2160
+ interface: {
2161
+ name: 'showAvatar',
2162
+ path: 'options.showAvatar',
2163
+ type: AXPWidgetsCatalog.toggle,
2164
+ },
2165
+ },
2166
+ visible: true,
2167
+ },
2168
+ {
2169
+ name: 'showDate',
2170
+ title: 'Show Date',
2171
+ description: 'Whether to show date in notifications',
2172
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2173
+ schema: {
2174
+ defaultValue: true,
2175
+ dataType: 'boolean',
2176
+ interface: {
2177
+ name: 'showDate',
2178
+ path: 'options.showDate',
2179
+ type: AXPWidgetsCatalog.toggle,
2180
+ },
2181
+ },
2182
+ visible: true,
2183
+ },
2184
+ {
2185
+ name: 'autoRefresh',
2186
+ title: 'Auto Refresh',
2187
+ description: 'Automatically refresh notifications at regular intervals',
2188
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2189
+ schema: {
2190
+ defaultValue: true,
2191
+ dataType: 'boolean',
2192
+ interface: {
2193
+ name: 'autoRefresh',
2194
+ path: 'options.autoRefresh',
2195
+ type: AXPWidgetsCatalog.toggle,
2196
+ },
2197
+ },
2198
+ visible: true,
2199
+ },
2200
+ {
2201
+ name: 'refreshInterval',
2202
+ title: 'Refresh Interval (seconds)',
2203
+ description: 'Interval in seconds between automatic refreshes',
2204
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2205
+ schema: {
2206
+ defaultValue: 60,
2207
+ dataType: 'number',
2208
+ interface: {
2209
+ name: 'refreshInterval',
2210
+ path: 'options.refreshInterval',
2211
+ type: AXPWidgetsCatalog.number,
2212
+ options: {
2213
+ minValue: 10,
2214
+ maxValue: 3600,
2215
+ },
2216
+ },
2217
+ },
2218
+ visible: true,
2219
+ },
2220
+ ],
2221
+ components: {
2222
+ view: {
2223
+ component: () => Promise.resolve().then(function () { return notificationWidget_component; }).then((c) => c.AXPNotificationWidgetViewComponent),
2224
+ },
2225
+ },
2226
+ meta: {
2227
+ dimensions: {
2228
+ width: 3,
2229
+ height: 5,
2230
+ minWidth: 2,
2231
+ minHeight: 4,
2232
+ maxWidth: 4,
2233
+ maxHeight: 7,
2234
+ },
2235
+ },
2236
+ };
2237
+
1679
2238
  class AXMNotificationManagementModule {
1680
2239
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMNotificationManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1681
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: AXMNotificationManagementModule, imports: [i1$2.AXPComponentSlotModule] }); }
2240
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: AXMNotificationManagementModule, imports: [i1$2.AXPComponentSlotModule, i2$1.AXPLayoutBuilderModule] }); }
1682
2241
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMNotificationManagementModule, providers: [
1683
2242
  {
1684
2243
  provide: AXMNotificationManagementTemplateEntityService,
@@ -1718,6 +2277,11 @@ class AXMNotificationManagementModule {
1718
2277
  component: AXMAdminNotificationSlotComponent,
1719
2278
  },
1720
2279
  ],
2280
+ }),
2281
+ AXPLayoutBuilderModule.forChild({
2282
+ widgets: [
2283
+ AXPMyNotificationDashboardWidget,
2284
+ ],
1721
2285
  })] }); }
1722
2286
  }
1723
2287
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMNotificationManagementModule, decorators: [{
@@ -1732,6 +2296,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
1732
2296
  },
1733
2297
  ],
1734
2298
  }),
2299
+ AXPLayoutBuilderModule.forChild({
2300
+ widgets: [
2301
+ AXPMyNotificationDashboardWidget,
2302
+ ],
2303
+ }),
1735
2304
  ],
1736
2305
  exports: [],
1737
2306
  declarations: [],
@@ -2398,5 +2967,5 @@ async function notificationLogEntityFactory(injector) {
2398
2967
  * Generated bundle index. Do not edit.
2399
2968
  */
2400
2969
 
2401
- export { AXMNotificationEntityService, AXMNotificationEntityServiceImpl, AXMNotificationManagementChannelEntityService, AXMNotificationManagementChannelEntityServiceImpl, AXMNotificationManagementModule, AXMNotificationManagementTemplateEntityModule, AXMNotificationManagementTemplateEntityService, AXMNotificationManagementTemplateEntityServiceImpl, AXMNotificationManagmentModuleMenuProvider, AXMSettingProvider, RootConfig, myNotificationEntityFactory, notificationChannelEntityFactory, notificationEntityFactory, notificationLogEntityFactory, notificationTemplateEntityFactory };
2970
+ export { AXMNotificationEntityService, AXMNotificationEntityServiceImpl, AXMNotificationManagementChannelEntityService, AXMNotificationManagementChannelEntityServiceImpl, AXMNotificationManagementModule, AXMNotificationManagementTemplateEntityModule, AXMNotificationManagementTemplateEntityService, AXMNotificationManagementTemplateEntityServiceImpl, AXMNotificationManagmentModuleMenuProvider, AXMSettingProvider, AXPMyNotificationDashboardWidget, AXPNotificationWidgetViewComponent, RootConfig, myNotificationEntityFactory, notificationChannelEntityFactory, notificationEntityFactory, notificationLogEntityFactory, notificationTemplateEntityFactory };
2402
2971
  //# sourceMappingURL=acorex-modules-notification-management.mjs.map