aril 1.2.36 → 1.2.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/boot/config/api/src/api.service.d.ts +2 -1
- package/esm2022/boot/config/api/src/api.service.mjs +24 -7
- package/esm2022/boot/host/src/bootstrap.mjs +13 -4
- package/esm2022/permission/aril-permission.mjs +5 -0
- package/esm2022/permission/index.mjs +4 -0
- package/esm2022/permission/src/constants.mjs +4 -0
- package/esm2022/permission/src/has-permission.directive.mjs +49 -0
- package/esm2022/permission/src/permission.service.mjs +57 -0
- package/esm2022/provider/src/index.mjs +2 -1
- package/esm2022/provider/src/prodiveHost.mjs +3 -2
- package/esm2022/provider/src/provideHostPermissions.mjs +43 -0
- package/esm2022/theme/layout/app/notifications/notifications-sidebar.component.mjs +146 -49
- package/esm2022/theme/layout/service/interfaces/interfaces.mjs +1 -1
- package/esm2022/theme/layout/service/notifications.service.mjs +8 -2
- package/fesm2022/{aril-app.component-W3wwVSp1.mjs → aril-app.component-BUjucZ0J.mjs} +2 -1
- package/fesm2022/{aril-app.component-W3wwVSp1.mjs.map → aril-app.component-BUjucZ0J.mjs.map} +1 -1
- package/fesm2022/aril-boot-config-api.mjs +23 -6
- package/fesm2022/aril-boot-config-api.mjs.map +1 -1
- package/fesm2022/aril-boot-host.mjs +12 -3
- package/fesm2022/aril-boot-host.mjs.map +1 -1
- package/fesm2022/aril-permission.mjs +114 -0
- package/fesm2022/aril-permission.mjs.map +1 -0
- package/fesm2022/aril-provider.mjs +44 -2
- package/fesm2022/aril-provider.mjs.map +1 -1
- package/fesm2022/aril-theme-layout.mjs +145 -39
- package/fesm2022/aril-theme-layout.mjs.map +1 -1
- package/fesm2022/aril.mjs +13 -4
- package/fesm2022/aril.mjs.map +1 -1
- package/package.json +87 -81
- package/permission/index.d.ts +3 -0
- package/permission/src/constants.d.ts +1 -0
- package/permission/src/has-permission.directive.d.ts +16 -0
- package/permission/src/permission.service.d.ts +15 -0
- package/provider/src/index.d.ts +1 -0
- package/provider/src/provideHostPermissions.d.ts +6 -0
- package/theme/layout/app/notifications/notifications-sidebar.component.d.ts +2288 -2267
- package/theme/layout/app/notifications/notifications-sidebar.component.html +66 -68
- package/theme/layout/app/notifications/notifications-sidebar.component.scss +234 -120
- package/theme/layout/app/notifications/notifications-sidebar.component.ts +182 -56
- package/theme/layout/service/interfaces/interfaces.d.ts +5 -1
- package/theme/layout/service/interfaces/interfaces.ts +6 -1
- package/theme/layout/service/notifications.service.d.ts +1 -0
- package/theme/layout/service/notifications.service.ts +5 -0
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { CommonModule } from '@angular/common';
|
|
2
|
-
import { Component, OnInit, effect, signal } from '@angular/core';
|
|
2
|
+
import { Component, OnInit, computed, effect, signal, untracked } from '@angular/core';
|
|
3
3
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { FormsModule } from '@angular/forms';
|
|
4
5
|
import { Router } from '@angular/router';
|
|
5
6
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { PaginatorModule } from 'primeng/paginator';
|
|
9
|
-
import { ScrollPanelModule } from 'primeng/scrollpanel';
|
|
7
|
+
import { MenuItem } from 'primeng/api';
|
|
8
|
+
import { Menu, MenuModule } from 'primeng/menu';
|
|
10
9
|
import { SidebarModule } from 'primeng/sidebar';
|
|
11
10
|
import { TooltipModule } from 'primeng/tooltip';
|
|
12
11
|
|
|
12
|
+
import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
|
13
13
|
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
|
14
14
|
import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
|
|
15
15
|
import { KeycloakService } from 'keycloak-angular';
|
|
16
|
-
import { Subject, switchMap } from 'rxjs';
|
|
16
|
+
import { map, mergeMap, Subject, switchMap } from 'rxjs';
|
|
17
17
|
|
|
18
18
|
import { ButtonComponent } from 'aril/ui/button';
|
|
19
|
+
import { SwitchComponent } from 'aril/ui/switch';
|
|
19
20
|
import { regularIcons, solidIcons } from 'aril/util/lib';
|
|
20
21
|
import { SafePipe } from 'aril/util/pipes';
|
|
21
22
|
|
|
@@ -29,14 +30,13 @@ import { NotificationsService } from '../../service/notifications.service';
|
|
|
29
30
|
selector: 'app-notifications-sidebar',
|
|
30
31
|
imports: [
|
|
31
32
|
CommonModule,
|
|
33
|
+
FormsModule,
|
|
32
34
|
SidebarModule,
|
|
33
|
-
|
|
34
|
-
ConfirmDialogModule,
|
|
35
|
-
PaginatorModule,
|
|
35
|
+
MenuModule,
|
|
36
36
|
ButtonComponent,
|
|
37
|
+
SwitchComponent,
|
|
37
38
|
TranslocoModule,
|
|
38
39
|
TooltipModule,
|
|
39
|
-
BadgeModule,
|
|
40
40
|
FontAwesomeModule,
|
|
41
41
|
SafePipe
|
|
42
42
|
],
|
|
@@ -44,8 +44,16 @@ import { NotificationsService } from '../../service/notifications.service';
|
|
|
44
44
|
styleUrls: ['./notifications-sidebar.component.scss']
|
|
45
45
|
})
|
|
46
46
|
export class NotificationsSidebarComponent implements OnInit {
|
|
47
|
+
private readonly pageSize = 10;
|
|
48
|
+
|
|
47
49
|
notifications = signal<SmsEmailAuditResponseDTO[]>([]);
|
|
48
|
-
|
|
50
|
+
totalRecords = signal(0);
|
|
51
|
+
onlyUnread = signal(true);
|
|
52
|
+
pageNumber = signal(1);
|
|
53
|
+
|
|
54
|
+
remainingCount = computed(() => Math.max(this.totalRecords() - this.notifications().length, 0));
|
|
55
|
+
|
|
56
|
+
menuItems: MenuItem[] = [];
|
|
49
57
|
|
|
50
58
|
ActivityTypesEnum = ActivityTypesEnum;
|
|
51
59
|
DetailNotificationTypeEnum = DetailNotificationTypeEnum;
|
|
@@ -57,11 +65,42 @@ export class NotificationsSidebarComponent implements OnInit {
|
|
|
57
65
|
|
|
58
66
|
private subjects = {
|
|
59
67
|
markAsRead: new Subject<string>(),
|
|
68
|
+
markAllAsRead: new Subject<void>(),
|
|
60
69
|
loadNotifications: new Subject<void>()
|
|
61
70
|
};
|
|
62
71
|
|
|
63
72
|
markAsReadService = toSignal(
|
|
64
|
-
this.subjects.markAsRead.pipe(
|
|
73
|
+
this.subjects.markAsRead.pipe(
|
|
74
|
+
mergeMap((id) => this.notificationsService.markAsReadNotification(id).pipe(map((result) => ({ result, id }))))
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
markAllAsReadService = toSignal(
|
|
79
|
+
this.subjects.markAllAsRead.pipe(
|
|
80
|
+
switchMap(() =>
|
|
81
|
+
this.notificationsService.markAllAsReadNotification({
|
|
82
|
+
toList: [this.getUserMail, ...this.getUserPhones],
|
|
83
|
+
endDate: new Date().dateToLong('time') || 0
|
|
84
|
+
})
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
loadNotificationsService = toSignal(
|
|
90
|
+
this.subjects.loadNotifications.pipe(
|
|
91
|
+
switchMap(() =>
|
|
92
|
+
this.notificationsService.getNotifications({
|
|
93
|
+
pager: {
|
|
94
|
+
pageSize: this.pageSize,
|
|
95
|
+
pageNumber: this.pageNumber()
|
|
96
|
+
},
|
|
97
|
+
startDate: this.oneMonthAgo.dateToLong('time') || 0,
|
|
98
|
+
endDate: new Date().dateToLong('time') || 0,
|
|
99
|
+
...(this.onlyUnread() ? { read: false } : {}),
|
|
100
|
+
toList: [this.getUserMail, ...this.getUserPhones]
|
|
101
|
+
})
|
|
102
|
+
)
|
|
103
|
+
)
|
|
65
104
|
);
|
|
66
105
|
|
|
67
106
|
get getUserPhones(): string[] {
|
|
@@ -78,22 +117,13 @@ export class NotificationsSidebarComponent implements OnInit {
|
|
|
78
117
|
return this.keycloak.getKeycloakInstance().profile?.email as string;
|
|
79
118
|
}
|
|
80
119
|
|
|
81
|
-
|
|
82
|
-
this.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
},
|
|
89
|
-
startDate: this.oneMonthAgo.dateToLong('time') || 0,
|
|
90
|
-
endDate: new Date().dateToLong('time') || 0,
|
|
91
|
-
read: false,
|
|
92
|
-
toList: [this.getUserMail, ...this.getUserPhones],
|
|
93
|
-
})
|
|
94
|
-
)
|
|
95
|
-
)
|
|
96
|
-
);
|
|
120
|
+
get unreadCount(): number {
|
|
121
|
+
return this.layoutService.getUnreadNotificationCount();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
get loading(): boolean {
|
|
125
|
+
return !!this.notificationsService.states.getNotifications?.waitingForResponse;
|
|
126
|
+
}
|
|
97
127
|
|
|
98
128
|
constructor(
|
|
99
129
|
public layoutService: LayoutService,
|
|
@@ -106,10 +136,6 @@ export class NotificationsSidebarComponent implements OnInit {
|
|
|
106
136
|
}
|
|
107
137
|
|
|
108
138
|
ngOnInit(): void {
|
|
109
|
-
this.loadNotifications();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private loadNotifications(): void {
|
|
113
139
|
this.subjects.loadNotifications.next();
|
|
114
140
|
}
|
|
115
141
|
|
|
@@ -118,23 +144,57 @@ export class NotificationsSidebarComponent implements OnInit {
|
|
|
118
144
|
() => {
|
|
119
145
|
const service = this.loadNotificationsService();
|
|
120
146
|
if (service?.response) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.
|
|
147
|
+
const result = service.response.result || [];
|
|
148
|
+
const isFirstPage = untracked(this.pageNumber) === 1;
|
|
149
|
+
this.notifications.update((current) =>
|
|
150
|
+
isFirstPage ? result : [...current, ...result.filter((item) => !current.some((existing) => existing.id === item.id))]
|
|
151
|
+
);
|
|
152
|
+
this.totalRecords.set(service.response.resultInfo.totalItem || 0);
|
|
153
|
+
if (untracked(this.onlyUnread)) {
|
|
154
|
+
this.layoutService.setUnreadNotificationCount(service.response.resultInfo.totalItem || 0);
|
|
155
|
+
}
|
|
124
156
|
}
|
|
125
157
|
},
|
|
126
158
|
{ allowSignalWrites: true }
|
|
127
159
|
);
|
|
128
|
-
effect(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (this.selectedNotification?.detailNotificationType === DetailNotificationTypeEnum.TODO_ITEM) {
|
|
134
|
-
this.router.navigate([`mng/todo-tasks/detail/${this.selectedNotification?.referenceId}`]);
|
|
160
|
+
effect(
|
|
161
|
+
() => {
|
|
162
|
+
const marked = this.markAsReadService();
|
|
163
|
+
if (marked?.result?.response) {
|
|
164
|
+
this.applyMarkedAsRead(marked.id);
|
|
135
165
|
}
|
|
136
|
-
}
|
|
137
|
-
|
|
166
|
+
},
|
|
167
|
+
{ allowSignalWrites: true }
|
|
168
|
+
);
|
|
169
|
+
effect(
|
|
170
|
+
() => {
|
|
171
|
+
const service = this.markAllAsReadService();
|
|
172
|
+
if (service?.response) {
|
|
173
|
+
this.applyAllMarkedAsRead();
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{ allowSignalWrites: true }
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private applyMarkedAsRead(id: string): void {
|
|
181
|
+
if (untracked(this.onlyUnread)) {
|
|
182
|
+
this.notifications.update((items) => items.filter((item) => item.id !== id));
|
|
183
|
+
this.totalRecords.update((total) => Math.max(total - 1, 0));
|
|
184
|
+
} else {
|
|
185
|
+
this.notifications.update((items) => items.map((item) => (item.id === id ? { ...item, read: true } : item)));
|
|
186
|
+
}
|
|
187
|
+
this.layoutService.setUnreadNotificationCount(Math.max(this.layoutService.getUnreadNotificationCount() - 1, 0));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private applyAllMarkedAsRead(): void {
|
|
191
|
+
if (untracked(this.onlyUnread)) {
|
|
192
|
+
this.notifications.set([]);
|
|
193
|
+
this.totalRecords.set(0);
|
|
194
|
+
} else {
|
|
195
|
+
this.notifications.update((items) => items.map((item) => (item.read ? item : { ...item, read: true })));
|
|
196
|
+
}
|
|
197
|
+
this.layoutService.setUnreadNotificationCount(0);
|
|
138
198
|
}
|
|
139
199
|
|
|
140
200
|
get visible(): boolean {
|
|
@@ -145,26 +205,92 @@ export class NotificationsSidebarComponent implements OnInit {
|
|
|
145
205
|
this.layoutService.state.notificationsSidebarVisible = value;
|
|
146
206
|
}
|
|
147
207
|
|
|
148
|
-
|
|
149
|
-
this.
|
|
150
|
-
this.
|
|
151
|
-
this.
|
|
208
|
+
onOnlyUnreadChange(value: boolean): void {
|
|
209
|
+
this.onlyUnread.set(value);
|
|
210
|
+
this.pageNumber.set(1);
|
|
211
|
+
this.notifications.set([]);
|
|
212
|
+
this.subjects.loadNotifications.next();
|
|
213
|
+
}
|
|
152
214
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
215
|
+
onSidebarShow(): void {
|
|
216
|
+
this.pageNumber.set(1);
|
|
217
|
+
this.subjects.loadNotifications.next();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
showMore(): void {
|
|
221
|
+
this.pageNumber.set(Math.floor(this.notifications().length / this.pageSize) + 1);
|
|
222
|
+
this.subjects.loadNotifications.next();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
toggleMenu(event: Event, menu: Menu): void {
|
|
226
|
+
this.menuItems = [
|
|
227
|
+
...(this.unreadCount > 0 ?
|
|
228
|
+
[
|
|
229
|
+
{
|
|
230
|
+
label: this.translocoService.translate('notifications.markAllAsRead'),
|
|
231
|
+
icon: 'pi pi-check-circle',
|
|
232
|
+
command: () => this.subjects.markAllAsRead.next()
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
: []),
|
|
236
|
+
{
|
|
237
|
+
label: this.translocoService.translate('notifications.allNotificationsPage'),
|
|
238
|
+
icon: 'pi pi-external-link',
|
|
239
|
+
command: () => this.navigateToAllNotifications()
|
|
240
|
+
}
|
|
241
|
+
];
|
|
242
|
+
menu.toggle(event);
|
|
158
243
|
}
|
|
159
244
|
|
|
160
|
-
|
|
245
|
+
markNotificationAsRead(notification: SmsEmailAuditResponseDTO): void {
|
|
161
246
|
if (!notification.read) {
|
|
162
247
|
this.subjects.markAsRead.next(notification.id);
|
|
163
248
|
}
|
|
164
249
|
}
|
|
165
250
|
|
|
166
|
-
|
|
167
|
-
|
|
251
|
+
openNotification(notification: SmsEmailAuditResponseDTO): void {
|
|
252
|
+
const isTodo = notification.detailNotificationType === DetailNotificationTypeEnum.TODO_ITEM;
|
|
253
|
+
const isBatch = notification.detailNotificationType === DetailNotificationTypeEnum.BATCH_JOB;
|
|
254
|
+
if (!isTodo && !isBatch) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
this.markNotificationAsRead(notification);
|
|
258
|
+
this.visible = false;
|
|
259
|
+
const route = isTodo ? `mng/todo-tasks/detail/${notification.referenceId}` : `mng/bulk-operations/${notification.referenceId}`;
|
|
260
|
+
this.router.navigate([route]);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
isNavigable(notification: SmsEmailAuditResponseDTO): boolean {
|
|
264
|
+
return (
|
|
265
|
+
notification.detailNotificationType === DetailNotificationTypeEnum.TODO_ITEM ||
|
|
266
|
+
notification.detailNotificationType === DetailNotificationTypeEnum.BATCH_JOB
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
getNotificationIcon(notification: SmsEmailAuditResponseDTO): IconProp {
|
|
271
|
+
if (notification.detailNotificationType === DetailNotificationTypeEnum.TODO_ITEM) {
|
|
272
|
+
return solidIcons.faListCheck;
|
|
273
|
+
}
|
|
274
|
+
if (notification.detailNotificationType === DetailNotificationTypeEnum.BATCH_JOB) {
|
|
275
|
+
return solidIcons.faGear;
|
|
276
|
+
}
|
|
277
|
+
if (notification.type === ActivityTypesEnum.SMS) {
|
|
278
|
+
return regularIcons.faMessage;
|
|
279
|
+
}
|
|
280
|
+
return notification.read ? regularIcons.faEnvelopeOpen : regularIcons.faEnvelope;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
getNotificationIconClass(notification: SmsEmailAuditResponseDTO): string {
|
|
284
|
+
if (notification.detailNotificationType === DetailNotificationTypeEnum.TODO_ITEM) {
|
|
285
|
+
return 'todo';
|
|
286
|
+
}
|
|
287
|
+
if (notification.detailNotificationType === DetailNotificationTypeEnum.BATCH_JOB) {
|
|
288
|
+
return 'batch';
|
|
289
|
+
}
|
|
290
|
+
if (notification.type === ActivityTypesEnum.SMS) {
|
|
291
|
+
return 'sms';
|
|
292
|
+
}
|
|
293
|
+
return notification.read ? 'email-read' : 'email-unread';
|
|
168
294
|
}
|
|
169
295
|
|
|
170
296
|
getNotificationTitle(notification: SmsEmailAuditResponseDTO): string {
|
|
@@ -88,7 +88,7 @@ export interface SmsEmailAuditRequestDto {
|
|
|
88
88
|
refMdId?: number;
|
|
89
89
|
referenceId?: string;
|
|
90
90
|
traceId?: string;
|
|
91
|
-
read
|
|
91
|
+
read?: boolean;
|
|
92
92
|
pager?: Pager;
|
|
93
93
|
username?: string;
|
|
94
94
|
startReadTime?: number;
|
|
@@ -116,6 +116,10 @@ export interface SmsEmailAuditResponseDTO {
|
|
|
116
116
|
traceId: string;
|
|
117
117
|
detailNotificationType: string;
|
|
118
118
|
}
|
|
119
|
+
export interface MarkAllReadNotificationRequestDTO {
|
|
120
|
+
toList: string[];
|
|
121
|
+
endDate: number;
|
|
122
|
+
}
|
|
119
123
|
export interface Pager {
|
|
120
124
|
pageSize: number;
|
|
121
125
|
pageNumber: number;
|
|
@@ -105,7 +105,7 @@ export interface SmsEmailAuditRequestDto {
|
|
|
105
105
|
refMdId?: number;
|
|
106
106
|
referenceId?: string;
|
|
107
107
|
traceId?: string;
|
|
108
|
-
read
|
|
108
|
+
read?: boolean;
|
|
109
109
|
pager?: Pager;
|
|
110
110
|
username?: string;
|
|
111
111
|
startReadTime?: number;
|
|
@@ -135,6 +135,11 @@ export interface SmsEmailAuditResponseDTO {
|
|
|
135
135
|
detailNotificationType: string;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
export interface MarkAllReadNotificationRequestDTO {
|
|
139
|
+
toList: string[];
|
|
140
|
+
endDate: number;
|
|
141
|
+
}
|
|
142
|
+
|
|
138
143
|
export interface Pager {
|
|
139
144
|
pageSize: number;
|
|
140
145
|
pageNumber: number;
|
|
@@ -7,6 +7,7 @@ export declare class NotificationsService extends RestClient {
|
|
|
7
7
|
constructor();
|
|
8
8
|
getNotifications(post: Interfaces.SmsEmailAuditRequestDto): Observable<ServiceResponse<Interfaces.Response<Interfaces.SmsEmailAuditResponseDTO>>>;
|
|
9
9
|
markAsReadNotification(pluginId: string): Observable<ServiceResponse<boolean>>;
|
|
10
|
+
markAllAsReadNotification(post: Interfaces.MarkAllReadNotificationRequestDTO): Observable<ServiceResponse<boolean>>;
|
|
10
11
|
static ɵfac: i0.ɵɵFactoryDeclaration<NotificationsService, never>;
|
|
11
12
|
static ɵprov: i0.ɵɵInjectableDeclaration<NotificationsService>;
|
|
12
13
|
}
|
|
@@ -23,4 +23,9 @@ export class NotificationsService extends RestClient {
|
|
|
23
23
|
markAsReadNotification(pluginId: string) {
|
|
24
24
|
return new Observable<ServiceResponse<boolean>>();
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
@ServiceCall(HTTPMethods.PUTBYPARAMS, ProxyTypes.ClientSide, 'audits/read-all', { success: 'notifications.markedAllAsRead' })
|
|
28
|
+
markAllAsReadNotification(post: Interfaces.MarkAllReadNotificationRequestDTO) {
|
|
29
|
+
return new Observable<ServiceResponse<boolean>>();
|
|
30
|
+
}
|
|
26
31
|
}
|