intelica-library-components 1.1.18 → 1.1.22
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.
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, Injectable, signal, Pipe, Component, TemplateRef, ContentChild, Input, Directive, EventEmitter, ContentChildren, Output, HostListener, forwardRef, ViewChild, PLATFORM_ID, Inject, output, Optional, Host } from '@angular/core';
|
|
3
3
|
import { getCookie, Cookies, setCookie } from 'typescript-cookie';
|
|
4
|
+
import * as i1$4 from '@angular/common/http';
|
|
4
5
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
5
|
-
import { BehaviorSubject, catchError, throwError, from, switchMap, Subject, Subscription, of, delay, tap, map } from 'rxjs';
|
|
6
|
+
import { BehaviorSubject, catchError, throwError, from, switchMap, Subject, Subscription, of, delay, tap, map, firstValueFrom } from 'rxjs';
|
|
6
7
|
import Swal from 'sweetalert2';
|
|
7
8
|
import * as i1 from '@angular/common';
|
|
8
9
|
import { DatePipe, CommonModule, NgIf, isPlatformBrowser, NgClass } from '@angular/common';
|
|
@@ -56,6 +57,7 @@ import JSEncrypt from 'jsencrypt';
|
|
|
56
57
|
import { Guid } from 'guid-typescript';
|
|
57
58
|
import Aura from '@primeng/themes/aura';
|
|
58
59
|
import { definePreset } from '@primeng/themes';
|
|
60
|
+
import * as signalR from '@microsoft/signalr';
|
|
59
61
|
|
|
60
62
|
class ConfigService {
|
|
61
63
|
Http = inject(HttpClient);
|
|
@@ -10386,11 +10388,569 @@ const IntelicaTheme = definePreset(Aura, {
|
|
|
10386
10388
|
},
|
|
10387
10389
|
});
|
|
10388
10390
|
|
|
10391
|
+
// notification/dto/recipient-dispatch-error.dto.ts
|
|
10392
|
+
|
|
10393
|
+
class NotificationService {
|
|
10394
|
+
http;
|
|
10395
|
+
configService = inject(ConfigService);
|
|
10396
|
+
path = `${this.configService.environment?.notificationsPath}/Notifications`;
|
|
10397
|
+
defaultHeaders = new HttpHeaders({
|
|
10398
|
+
refreshtoken: "f06c110a-ea4e-44a9-896f-210f3b387e57",
|
|
10399
|
+
languagecode: "EN",
|
|
10400
|
+
pageRoot: "",
|
|
10401
|
+
authorization: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcmVmZXJyZWRfdXNlcm5hbWUiOiJBbGV4YW5kZXIiLCJmdWxsTmFtZSI6IkFsZXhhbmRlciBUb3JyZSIsInN1YiI6Ijg3ZTQxYzZlLWNmN2EtNDk4MC05YTQ1LThjZjllNWMwOGMzZCIsImVtYWlsIjoiam9oYW4uY2FyYm9uZWxAaW50ZWxpY2EuY29tIiwiYnVzaW5lc3NVc2VyQ2xpZW50R3JvdXBJRCI6ImNlMjE5NDAyLWQyMDAtNGU1Yy1iNzE0LWJkNDJiMjZhNzNkNSIsImJhbmtzSUQiOiJnUlZPUEt6V3BNbHQ2NFE3OWdDcUxlQ1pFeWp2RjVFQVo0TmNMVTQvZlhJMVlvbERPeEFOV0NWTUpFYkJYRDJQUHkvUi8xdDVQVHBFZ08vcFFPcnMwVnNNeWRONkVocEY5MzRCRDJFRXhlelVyakZWWVduWitrcCtObGRLOU56VWg4VjZaRjBVTzEyN0JIaG12aGhUNzZMRm51Zm9nSndUTHVuOW5qMFpEaSsxV3MxTHkzZytzWkNYSVdTelR3QjBEc1g5Y2tXSTJrWmFHeWhHVlFhTlliT3hGYzU5UU9xV0pxQUJqdmVBdFNEaGNQdFZta3RIOXFaaEJ5Tkphdkh5R1pkWWJScXovcUZPOW1HUC92NjVScFZ5djNwejhCZUtvMVlJVW5vSUFqSU9udzRTMEkzcmxaSTNrTExBRFFOdnhBSk81NjgvZTVvdWlVZFd3SDlJd2c9PSIsImlzSW50ZWxpY2EiOiIxIiwiY2xpZW50R3JvdXBJRCI6ImU5ZDc1ODY3LTZkMDQtNGNiMC1iZjMxLTE5MmI5Y2VjMzVkYSIsImNsaWVudElEIjoiMDYzMGU0MDEtMzk1Ny00OTU5LTljYTUtYjM1MGVkNmU5Yjk2IiwiYm5rR3JvdXBJRCI6IjAiLCJpbXJwUHJvamVjdElEIjoiMTAwNjMyIiwiZXhwIjoxNzY4ODU3MTUwLCJpc3MiOiJpbnRlbGljYS5jb20iLCJhdWQiOiJpbnRlbGljYS5jb20ifQ.n0BGAUHrp6BiA_XpgTw6WdresOk_C3aaON7V7AcF5uo",
|
|
10402
|
+
});
|
|
10403
|
+
constructor(http) {
|
|
10404
|
+
this.http = http;
|
|
10405
|
+
}
|
|
10406
|
+
getNotificacionsByUser(userId) {
|
|
10407
|
+
return this.http.get(`${this.path}/users/${encodeURIComponent(userId)}`, { headers: this.defaultHeaders });
|
|
10408
|
+
}
|
|
10409
|
+
markAsRead(recipientId) {
|
|
10410
|
+
return this.http.post(`${this.path}/users/recipients/${recipientId}/read`, {}, { headers: this.defaultHeaders });
|
|
10411
|
+
}
|
|
10412
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationService, deps: [{ token: i1$4.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
10413
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationService, providedIn: "root" });
|
|
10414
|
+
}
|
|
10415
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationService, decorators: [{
|
|
10416
|
+
type: Injectable,
|
|
10417
|
+
args: [{ providedIn: "root" }]
|
|
10418
|
+
}], ctorParameters: () => [{ type: i1$4.HttpClient }] });
|
|
10419
|
+
|
|
10420
|
+
class NotificationJobService {
|
|
10421
|
+
http;
|
|
10422
|
+
configService = inject(ConfigService);
|
|
10423
|
+
path = `${this.configService.environment?.notificationsPath}/NotificationJobs`;
|
|
10424
|
+
defaultHeaders = new HttpHeaders({
|
|
10425
|
+
refreshtoken: "f06c110a-ea4e-44a9-896f-210f3b387e57",
|
|
10426
|
+
languagecode: "EN",
|
|
10427
|
+
pageRoot: "",
|
|
10428
|
+
authorization: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcmVmZXJyZWRfdXNlcm5hbWUiOiJBbGV4YW5kZXIiLCJmdWxsTmFtZSI6IkFsZXhhbmRlciBUb3JyZSIsInN1YiI6Ijg3ZTQxYzZlLWNmN2EtNDk4MC05YTQ1LThjZjllNWMwOGMzZCIsImVtYWlsIjoiam9oYW4uY2FyYm9uZWxAaW50ZWxpY2EuY29tIiwiYnVzaW5lc3NVc2VyQ2xpZW50R3JvdXBJRCI6ImNlMjE5NDAyLWQyMDAtNGU1Yy1iNzE0LWJkNDJiMjZhNzNkNSIsImJhbmtzSUQiOiJnUlZPUEt6V3BNbHQ2NFE3OWdDcUxlQ1pFeWp2RjVFQVo0TmNMVTQvZlhJMVlvbERPeEFOV0NWTUpFYkJYRDJQUHkvUi8xdDVQVHBFZ08vcFFPcnMwVnNNeWRONkVocEY5MzRCRDJFRXhlelVyakZWWVduWitrcCtObGRLOU56VWg4VjZaRjBVTzEyN0JIaG12aGhUNzZMRm51Zm9nSndUTHVuOW5qMFpEaSsxV3MxTHkzZytzWkNYSVdTelR3QjBEc1g5Y2tXSTJrWmFHeWhHVlFhTlliT3hGYzU5UU9xV0pxQUJqdmVBdFNEaGNQdFZta3RIOXFaaEJ5Tkphdkh5R1pkWWJScXovcUZPOW1HUC92NjVScFZ5djNwejhCZUtvMVlJVW5vSUFqSU9udzRTMEkzcmxaSTNrTExBRFFOdnhBSk81NjgvZTVvdWlVZFd3SDlJd2c9PSIsImlzSW50ZWxpY2EiOiIxIiwiY2xpZW50R3JvdXBJRCI6ImU5ZDc1ODY3LTZkMDQtNGNiMC1iZjMxLTE5MmI5Y2VjMzVkYSIsImNsaWVudElEIjoiMDYzMGU0MDEtMzk1Ny00OTU5LTljYTUtYjM1MGVkNmU5Yjk2IiwiYm5rR3JvdXBJRCI6IjAiLCJpbXJwUHJvamVjdElEIjoiMTAwNjMyIiwiZXhwIjoxNzY4ODU3MTUwLCJpc3MiOiJpbnRlbGljYS5jb20iLCJhdWQiOiJpbnRlbGljYS5jb20ifQ.n0BGAUHrp6BiA_XpgTw6WdresOk_C3aaON7V7AcF5uo",
|
|
10429
|
+
});
|
|
10430
|
+
constructor(http) {
|
|
10431
|
+
this.http = http;
|
|
10432
|
+
}
|
|
10433
|
+
createJobNotifications(payload) {
|
|
10434
|
+
return this.http.post(`${this.path}/notifications`, payload, {
|
|
10435
|
+
headers: this.defaultHeaders,
|
|
10436
|
+
});
|
|
10437
|
+
}
|
|
10438
|
+
createJob(payload) {
|
|
10439
|
+
return this.http.post(`${this.path}`, payload, {
|
|
10440
|
+
headers: this.defaultHeaders,
|
|
10441
|
+
});
|
|
10442
|
+
}
|
|
10443
|
+
getJob(jobId) {
|
|
10444
|
+
return this.http.get(`${this.path}/${jobId}`);
|
|
10445
|
+
}
|
|
10446
|
+
createNotifications(jobId, payload) {
|
|
10447
|
+
return this.http.post(`${this.path}/${jobId}/notifications`, payload, { headers: this.defaultHeaders });
|
|
10448
|
+
}
|
|
10449
|
+
getActiveJob(featureCode, origin) {
|
|
10450
|
+
let url = `${this.path}/active?featureCode=${encodeURIComponent(featureCode)}`;
|
|
10451
|
+
if (origin) {
|
|
10452
|
+
url += `&origin=${encodeURIComponent(origin)}`;
|
|
10453
|
+
}
|
|
10454
|
+
return this.http.get(url, { headers: this.defaultHeaders }).pipe(map(list => (Array.isArray(list) && list.length > 0 ? list[0] : null)), catchError(err => {
|
|
10455
|
+
console.error("Error obteniendo active jobs", err);
|
|
10456
|
+
return of(null);
|
|
10457
|
+
}));
|
|
10458
|
+
}
|
|
10459
|
+
getRecipients(jobId) {
|
|
10460
|
+
return this.http.get(`${this.path}/${jobId}/recipients`, { headers: this.defaultHeaders });
|
|
10461
|
+
}
|
|
10462
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationJobService, deps: [{ token: i1$4.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
10463
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationJobService, providedIn: "root" });
|
|
10464
|
+
}
|
|
10465
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationJobService, decorators: [{
|
|
10466
|
+
type: Injectable,
|
|
10467
|
+
args: [{ providedIn: "root" }]
|
|
10468
|
+
}], ctorParameters: () => [{ type: i1$4.HttpClient }] });
|
|
10469
|
+
|
|
10470
|
+
class NotificationSignalRService {
|
|
10471
|
+
zone;
|
|
10472
|
+
configService = inject(ConfigService);
|
|
10473
|
+
path = `${this.configService.environment?.signalPath}/websocket`;
|
|
10474
|
+
hubConnection;
|
|
10475
|
+
startPromise;
|
|
10476
|
+
// Mantiene los grupos a los que ya nos unimos (idempotencia + rejoin tras reconexión)
|
|
10477
|
+
joinedGroups = new Set();
|
|
10478
|
+
notificationSendSubject = new Subject();
|
|
10479
|
+
notificationSend$ = this.notificationSendSubject.asObservable();
|
|
10480
|
+
jobProgressSubject = new Subject();
|
|
10481
|
+
jobProgress$ = this.jobProgressSubject.asObservable();
|
|
10482
|
+
callbackResultSubject = new Subject();
|
|
10483
|
+
callbackResult$ = this.callbackResultSubject.asObservable();
|
|
10484
|
+
constructor(zone) {
|
|
10485
|
+
this.zone = zone;
|
|
10486
|
+
}
|
|
10487
|
+
/**
|
|
10488
|
+
* Inicia la conexión una sola vez. Reutiliza la promesa para evitar carreras.
|
|
10489
|
+
*/
|
|
10490
|
+
startConnection() {
|
|
10491
|
+
if (this.startPromise)
|
|
10492
|
+
return this.startPromise;
|
|
10493
|
+
this.hubConnection = new signalR.HubConnectionBuilder().withUrl(this.path).withAutomaticReconnect().build();
|
|
10494
|
+
this.registerListeners();
|
|
10495
|
+
this.registerReconnectHandlers();
|
|
10496
|
+
this.startPromise = this.hubConnection.start().catch(err => {
|
|
10497
|
+
console.error("Error starting SignalR connection", err);
|
|
10498
|
+
this.startPromise = undefined; // permitir reintentar
|
|
10499
|
+
throw err;
|
|
10500
|
+
});
|
|
10501
|
+
return this.startPromise;
|
|
10502
|
+
}
|
|
10503
|
+
/**
|
|
10504
|
+
* Se une a un grupo de forma idempotente.
|
|
10505
|
+
* Importante: esta función garantiza que la conexión esté iniciada.
|
|
10506
|
+
*/
|
|
10507
|
+
async joinScope(scopeType, scopeId) {
|
|
10508
|
+
await this.startConnection();
|
|
10509
|
+
if (!this.hubConnection)
|
|
10510
|
+
return;
|
|
10511
|
+
const groupName = `${scopeType}-${scopeId}`;
|
|
10512
|
+
if (this.joinedGroups.has(groupName))
|
|
10513
|
+
return;
|
|
10514
|
+
await this.hubConnection.invoke("Connect", groupName);
|
|
10515
|
+
this.joinedGroups.add(groupName);
|
|
10516
|
+
}
|
|
10517
|
+
/**
|
|
10518
|
+
* Sale de un grupo y actualiza el estado local.
|
|
10519
|
+
* Requiere que el Hub implemente el método Disconnect(groupName).
|
|
10520
|
+
*/
|
|
10521
|
+
async leaveScope(scopeType, scopeId) {
|
|
10522
|
+
if (!this.hubConnection)
|
|
10523
|
+
return;
|
|
10524
|
+
const groupName = `${scopeType}-${scopeId}`;
|
|
10525
|
+
if (!this.joinedGroups.has(groupName))
|
|
10526
|
+
return;
|
|
10527
|
+
await this.hubConnection.invoke("Disconnect", groupName);
|
|
10528
|
+
this.joinedGroups.delete(groupName);
|
|
10529
|
+
}
|
|
10530
|
+
/**
|
|
10531
|
+
* Detiene la conexión y limpia estado local.
|
|
10532
|
+
* Útil si quieres liberar recursos al cerrar sesión.
|
|
10533
|
+
*/
|
|
10534
|
+
async stopConnection() {
|
|
10535
|
+
if (!this.hubConnection)
|
|
10536
|
+
return;
|
|
10537
|
+
try {
|
|
10538
|
+
await this.hubConnection.stop();
|
|
10539
|
+
}
|
|
10540
|
+
finally {
|
|
10541
|
+
this.joinedGroups.clear();
|
|
10542
|
+
this.hubConnection = undefined;
|
|
10543
|
+
this.startPromise = undefined;
|
|
10544
|
+
}
|
|
10545
|
+
}
|
|
10546
|
+
registerListeners() {
|
|
10547
|
+
if (!this.hubConnection)
|
|
10548
|
+
return;
|
|
10549
|
+
this.hubConnection.on("NotificationSend", (raw) => {
|
|
10550
|
+
this.zone.run(() => {
|
|
10551
|
+
const data = JSON.parse(raw);
|
|
10552
|
+
this.notificationSendSubject.next(data);
|
|
10553
|
+
});
|
|
10554
|
+
});
|
|
10555
|
+
this.hubConnection.on("JobProgress", (raw) => {
|
|
10556
|
+
this.zone.run(() => {
|
|
10557
|
+
const data = JSON.parse(raw);
|
|
10558
|
+
this.jobProgressSubject.next(data);
|
|
10559
|
+
});
|
|
10560
|
+
});
|
|
10561
|
+
this.hubConnection.on("CallbackResult", (raw) => {
|
|
10562
|
+
this.zone.run(() => {
|
|
10563
|
+
const data = JSON.parse(raw);
|
|
10564
|
+
this.callbackResultSubject.next(data);
|
|
10565
|
+
});
|
|
10566
|
+
});
|
|
10567
|
+
// Opcional (tu hub lo emite): útil para debugging
|
|
10568
|
+
this.hubConnection.on("Connect", (_msg) => { });
|
|
10569
|
+
}
|
|
10570
|
+
/**
|
|
10571
|
+
* SignalR pierde pertenencia a grupos tras reconexión: re-join automático.
|
|
10572
|
+
*/
|
|
10573
|
+
registerReconnectHandlers() {
|
|
10574
|
+
if (!this.hubConnection)
|
|
10575
|
+
return;
|
|
10576
|
+
this.hubConnection.onreconnected(async () => {
|
|
10577
|
+
try {
|
|
10578
|
+
for (const groupName of this.joinedGroups) {
|
|
10579
|
+
await this.hubConnection.invoke("Connect", groupName);
|
|
10580
|
+
}
|
|
10581
|
+
}
|
|
10582
|
+
catch (e) {
|
|
10583
|
+
console.error("Error rejoining groups after reconnection", e);
|
|
10584
|
+
}
|
|
10585
|
+
});
|
|
10586
|
+
this.hubConnection.onclose(() => {
|
|
10587
|
+
// Mantén joinedGroups para poder rejoin si el usuario vuelve a startConnection()
|
|
10588
|
+
this.startPromise = undefined;
|
|
10589
|
+
});
|
|
10590
|
+
}
|
|
10591
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationSignalRService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
10592
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationSignalRService, providedIn: "root" });
|
|
10593
|
+
}
|
|
10594
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationSignalRService, decorators: [{
|
|
10595
|
+
type: Injectable,
|
|
10596
|
+
args: [{ providedIn: "root" }]
|
|
10597
|
+
}], ctorParameters: () => [{ type: i0.NgZone }] });
|
|
10598
|
+
|
|
10599
|
+
class NotificationOrchestratorService {
|
|
10600
|
+
jobService;
|
|
10601
|
+
notificationService;
|
|
10602
|
+
signalR;
|
|
10603
|
+
// Config actual (feature/origin) del “scope”
|
|
10604
|
+
featureCode;
|
|
10605
|
+
origin;
|
|
10606
|
+
currentJobId;
|
|
10607
|
+
subscribedJobId;
|
|
10608
|
+
// --- streams públicos (feature/origin job state)
|
|
10609
|
+
jobStateSubject = new BehaviorSubject({
|
|
10610
|
+
status: "idle",
|
|
10611
|
+
processedCount: 0,
|
|
10612
|
+
totalCount: 0,
|
|
10613
|
+
processedNotificationsCount: 0,
|
|
10614
|
+
totalNotificationsCount: 0,
|
|
10615
|
+
});
|
|
10616
|
+
jobState$ = this.jobStateSubject.asObservable();
|
|
10617
|
+
dispatchErrorsMapSubject = new BehaviorSubject(new Map());
|
|
10618
|
+
dispatchErrors$ = this.dispatchErrorsMapSubject.asObservable();
|
|
10619
|
+
callbackRawSubject = new Subject();
|
|
10620
|
+
callbackRaw$ = this.callbackRawSubject.asObservable();
|
|
10621
|
+
/**
|
|
10622
|
+
* Router de progreso por jobId (para UIs multi-job).
|
|
10623
|
+
*/
|
|
10624
|
+
jobProgressSubjects = new Map();
|
|
10625
|
+
jobWatchRefCount = new Map();
|
|
10626
|
+
/**
|
|
10627
|
+
* Router de NotificationSend por userId (campana/inbox).
|
|
10628
|
+
*/
|
|
10629
|
+
userInboxSubjects = new Map();
|
|
10630
|
+
userWatchRefCount = new Map();
|
|
10631
|
+
// Guard anti-carreras para rehidratación
|
|
10632
|
+
initInFlight;
|
|
10633
|
+
constructor(jobService, notificationService, signalR) {
|
|
10634
|
+
this.jobService = jobService;
|
|
10635
|
+
this.notificationService = notificationService;
|
|
10636
|
+
this.signalR = signalR;
|
|
10637
|
+
// stream global SignalR => orquestador enruta
|
|
10638
|
+
this.signalR.jobProgress$.subscribe(update => this.onJobProgress(update));
|
|
10639
|
+
this.signalR.callbackResult$.subscribe(update => this.onCallbackResult(update));
|
|
10640
|
+
this.signalR.notificationSend$.subscribe(update => this.onNotificationSend(update));
|
|
10641
|
+
}
|
|
10642
|
+
// ---------------------------------------------------------------------
|
|
10643
|
+
// API pública para UI: Inbox user-scoped (NotificationSend)
|
|
10644
|
+
// ---------------------------------------------------------------------
|
|
10645
|
+
async watchUserInbox(userId) {
|
|
10646
|
+
if (!userId)
|
|
10647
|
+
throw new Error("userId is required");
|
|
10648
|
+
const current = this.userWatchRefCount.get(userId) ?? 0;
|
|
10649
|
+
this.userWatchRefCount.set(userId, current + 1);
|
|
10650
|
+
await this.signalR.joinScope("user", userId);
|
|
10651
|
+
return this.userInbox$(userId);
|
|
10652
|
+
}
|
|
10653
|
+
async unwatchUserInbox(userId) {
|
|
10654
|
+
if (!userId)
|
|
10655
|
+
return;
|
|
10656
|
+
const current = this.userWatchRefCount.get(userId) ?? 0;
|
|
10657
|
+
if (current <= 1) {
|
|
10658
|
+
this.userWatchRefCount.delete(userId);
|
|
10659
|
+
await this.signalR.leaveScope("user", userId);
|
|
10660
|
+
const subj = this.userInboxSubjects.get(userId);
|
|
10661
|
+
if (subj) {
|
|
10662
|
+
subj.complete();
|
|
10663
|
+
this.userInboxSubjects.delete(userId);
|
|
10664
|
+
}
|
|
10665
|
+
return;
|
|
10666
|
+
}
|
|
10667
|
+
this.userWatchRefCount.set(userId, current - 1);
|
|
10668
|
+
}
|
|
10669
|
+
userInbox$(userId) {
|
|
10670
|
+
let subj = this.userInboxSubjects.get(userId);
|
|
10671
|
+
if (!subj) {
|
|
10672
|
+
subj = new Subject();
|
|
10673
|
+
this.userInboxSubjects.set(userId, subj);
|
|
10674
|
+
}
|
|
10675
|
+
return subj.asObservable();
|
|
10676
|
+
}
|
|
10677
|
+
// ---------------------------------------------------------------------
|
|
10678
|
+
// API pública para UI: Job progress por jobId (PRG)
|
|
10679
|
+
// ---------------------------------------------------------------------
|
|
10680
|
+
async watchJobProgress(jobId) {
|
|
10681
|
+
if (!jobId)
|
|
10682
|
+
throw new Error("jobId is required");
|
|
10683
|
+
const current = this.jobWatchRefCount.get(jobId) ?? 0;
|
|
10684
|
+
this.jobWatchRefCount.set(jobId, current + 1);
|
|
10685
|
+
await this.signalR.joinScope("job", jobId);
|
|
10686
|
+
return this.jobProgress$(jobId);
|
|
10687
|
+
}
|
|
10688
|
+
async unwatchJobProgress(jobId) {
|
|
10689
|
+
if (!jobId)
|
|
10690
|
+
return;
|
|
10691
|
+
const current = this.jobWatchRefCount.get(jobId) ?? 0;
|
|
10692
|
+
if (current <= 1) {
|
|
10693
|
+
this.jobWatchRefCount.delete(jobId);
|
|
10694
|
+
await this.signalR.leaveScope("job", jobId);
|
|
10695
|
+
const subj = this.jobProgressSubjects.get(jobId);
|
|
10696
|
+
if (subj) {
|
|
10697
|
+
subj.complete();
|
|
10698
|
+
this.jobProgressSubjects.delete(jobId);
|
|
10699
|
+
}
|
|
10700
|
+
return;
|
|
10701
|
+
}
|
|
10702
|
+
this.jobWatchRefCount.set(jobId, current - 1);
|
|
10703
|
+
}
|
|
10704
|
+
jobProgress$(jobId) {
|
|
10705
|
+
let subj = this.jobProgressSubjects.get(jobId);
|
|
10706
|
+
if (!subj) {
|
|
10707
|
+
subj = new Subject();
|
|
10708
|
+
this.jobProgressSubjects.set(jobId, subj);
|
|
10709
|
+
}
|
|
10710
|
+
return subj.asObservable();
|
|
10711
|
+
}
|
|
10712
|
+
// ---------------------------------------------------------------------
|
|
10713
|
+
// Scope feature/origin (tu lógica existente)
|
|
10714
|
+
// ---------------------------------------------------------------------
|
|
10715
|
+
rehydrateScope(featureCode, origin) {
|
|
10716
|
+
this.featureCode = featureCode;
|
|
10717
|
+
this.origin = origin;
|
|
10718
|
+
if (this.initInFlight)
|
|
10719
|
+
return this.initInFlight;
|
|
10720
|
+
this.initInFlight = (async () => {
|
|
10721
|
+
try {
|
|
10722
|
+
await this.rehydrateActiveJobInternal();
|
|
10723
|
+
}
|
|
10724
|
+
finally {
|
|
10725
|
+
this.initInFlight = undefined;
|
|
10726
|
+
}
|
|
10727
|
+
})();
|
|
10728
|
+
return this.initInFlight;
|
|
10729
|
+
}
|
|
10730
|
+
getCurrentJobId() {
|
|
10731
|
+
return this.currentJobId;
|
|
10732
|
+
}
|
|
10733
|
+
getJobStateSnapshot() {
|
|
10734
|
+
return this.jobStateSubject.value;
|
|
10735
|
+
}
|
|
10736
|
+
async ensureActiveOrCreateJobNotifications(totalCount, totalNotificationsCount, notificationDraft) {
|
|
10737
|
+
if (!this.featureCode || !this.origin)
|
|
10738
|
+
throw new Error("Scope not initialized. Call rehydrateScope(featureCode, origin) first.");
|
|
10739
|
+
if (this.currentJobId) {
|
|
10740
|
+
return { jobId: this.currentJobId, mode: "active" };
|
|
10741
|
+
}
|
|
10742
|
+
const jobPayload = {
|
|
10743
|
+
featureCode: this.featureCode,
|
|
10744
|
+
origin: this.origin,
|
|
10745
|
+
totalCount,
|
|
10746
|
+
totalNotificationsCount,
|
|
10747
|
+
};
|
|
10748
|
+
const job = await firstValueFrom(this.jobService.createJob(jobPayload));
|
|
10749
|
+
this.currentJobId = job.jobId;
|
|
10750
|
+
this.setJobState({
|
|
10751
|
+
jobId: this.currentJobId,
|
|
10752
|
+
status: "pending",
|
|
10753
|
+
processedCount: 0,
|
|
10754
|
+
totalCount,
|
|
10755
|
+
processedNotificationsCount: 0,
|
|
10756
|
+
totalNotificationsCount,
|
|
10757
|
+
});
|
|
10758
|
+
await this.subscribeToJob(this.currentJobId);
|
|
10759
|
+
const notifications = notificationDraft.map(draft => ({
|
|
10760
|
+
originReference: `${draft.originReference}-${job.jobId}`,
|
|
10761
|
+
notificationTypeCode: draft.notificationTypeCode,
|
|
10762
|
+
destination: draft.destination,
|
|
10763
|
+
destinationLabel: draft.destinationLabel,
|
|
10764
|
+
bucketName: draft.bucketName,
|
|
10765
|
+
templateName: draft.templateName,
|
|
10766
|
+
templateData: draft.templateData,
|
|
10767
|
+
priorityCode: draft.priorityCode,
|
|
10768
|
+
title: draft.title,
|
|
10769
|
+
body: draft.body,
|
|
10770
|
+
metaData: draft.metaData,
|
|
10771
|
+
recipients: draft.recipients,
|
|
10772
|
+
actions: draft.actions,
|
|
10773
|
+
callbacks: draft.callbacks,
|
|
10774
|
+
}));
|
|
10775
|
+
await firstValueFrom(this.jobService.createNotifications(job.jobId, notifications));
|
|
10776
|
+
return { jobId: this.currentJobId, mode: "created" };
|
|
10777
|
+
}
|
|
10778
|
+
async ensureCreateJobNotifications(featureCode, origin, totalCount, totalNotificationsCount, notificationDraft) {
|
|
10779
|
+
if (!featureCode || !origin)
|
|
10780
|
+
throw new Error("Scope not initialized.");
|
|
10781
|
+
const jobPayload = {
|
|
10782
|
+
featureCode: featureCode,
|
|
10783
|
+
origin: origin,
|
|
10784
|
+
totalCount,
|
|
10785
|
+
totalNotificationsCount,
|
|
10786
|
+
notifications: notificationDraft.map(draft => ({
|
|
10787
|
+
originReference: draft.originReference,
|
|
10788
|
+
notificationTypeCode: draft.notificationTypeCode,
|
|
10789
|
+
destination: draft.destination,
|
|
10790
|
+
destinationLabel: draft.destinationLabel,
|
|
10791
|
+
bucketName: draft.bucketName,
|
|
10792
|
+
templateName: draft.templateName,
|
|
10793
|
+
templateData: draft.templateData,
|
|
10794
|
+
priorityCode: draft.priorityCode,
|
|
10795
|
+
title: draft.title,
|
|
10796
|
+
body: draft.body,
|
|
10797
|
+
metaData: draft.metaData,
|
|
10798
|
+
recipients: draft.recipients,
|
|
10799
|
+
actions: draft.actions,
|
|
10800
|
+
})),
|
|
10801
|
+
};
|
|
10802
|
+
await firstValueFrom(this.jobService.createJobNotifications(jobPayload));
|
|
10803
|
+
}
|
|
10804
|
+
async markAsRead(recipientId) {
|
|
10805
|
+
const result = await firstValueFrom(this.notificationService.markAsRead(recipientId));
|
|
10806
|
+
return result;
|
|
10807
|
+
}
|
|
10808
|
+
async getNotificacionsByUser(userId) {
|
|
10809
|
+
const items = await firstValueFrom(this.notificationService.getNotificacionsByUser(userId));
|
|
10810
|
+
return items;
|
|
10811
|
+
}
|
|
10812
|
+
resetLocal() {
|
|
10813
|
+
this.currentJobId = undefined;
|
|
10814
|
+
this.setJobState({ status: "idle", processedCount: 0, totalCount: 0, processedNotificationsCount: 0, totalNotificationsCount: 0 });
|
|
10815
|
+
this.dispatchErrorsMapSubject.next(new Map());
|
|
10816
|
+
}
|
|
10817
|
+
async rehydrateActiveJobInternal() {
|
|
10818
|
+
if (!this.featureCode || !this.origin)
|
|
10819
|
+
return;
|
|
10820
|
+
const active = await firstValueFrom(this.jobService.getActiveJob(this.featureCode, this.origin));
|
|
10821
|
+
if (!active) {
|
|
10822
|
+
this.currentJobId = undefined;
|
|
10823
|
+
this.setJobState({ status: "idle", processedCount: 0, totalCount: 0, processedNotificationsCount: 0, totalNotificationsCount: 0 });
|
|
10824
|
+
this.dispatchErrorsMapSubject.next(new Map());
|
|
10825
|
+
return;
|
|
10826
|
+
}
|
|
10827
|
+
this.currentJobId = active.jobId;
|
|
10828
|
+
this.setJobState({
|
|
10829
|
+
jobId: active.jobId,
|
|
10830
|
+
status: active.statusCode?.toLowerCase() || "running",
|
|
10831
|
+
processedCount: active.processedCount ?? 0,
|
|
10832
|
+
totalCount: active.totalCount ?? 0,
|
|
10833
|
+
processedNotificationsCount: active.processedNotificationsCount ?? 0,
|
|
10834
|
+
totalNotificationsCount: active.totalNotificationsCount ?? 0,
|
|
10835
|
+
});
|
|
10836
|
+
const recipients = await firstValueFrom(this.jobService.getRecipients(active.jobId));
|
|
10837
|
+
const map = new Map();
|
|
10838
|
+
for (const r of recipients) {
|
|
10839
|
+
if (r.recipientId && r.statusCode === "failed") {
|
|
10840
|
+
map.set(r.recipientId, {
|
|
10841
|
+
recipientId: r.recipientId,
|
|
10842
|
+
lastErrorMessage: r.lastErrorMessage ?? null,
|
|
10843
|
+
channelCode: r.channelCode || undefined,
|
|
10844
|
+
statusCode: r.statusCode,
|
|
10845
|
+
attempts: r.attempts,
|
|
10846
|
+
lastAttemptAt: r.lastAttemptAt ?? null,
|
|
10847
|
+
userId: r.userId ?? null,
|
|
10848
|
+
clientId: r.clientId ?? null,
|
|
10849
|
+
groupId: r.groupId ?? null,
|
|
10850
|
+
});
|
|
10851
|
+
}
|
|
10852
|
+
}
|
|
10853
|
+
this.dispatchErrorsMapSubject.next(map);
|
|
10854
|
+
await this.subscribeToJob(active.jobId);
|
|
10855
|
+
}
|
|
10856
|
+
async subscribeToJob(jobId) {
|
|
10857
|
+
if (this.subscribedJobId && this.subscribedJobId !== jobId) {
|
|
10858
|
+
await this.signalR.leaveScope("job", this.subscribedJobId);
|
|
10859
|
+
await this.signalR.leaveScope("callBack", this.subscribedJobId);
|
|
10860
|
+
}
|
|
10861
|
+
this.subscribedJobId = jobId;
|
|
10862
|
+
await this.signalR.joinScope("job", jobId);
|
|
10863
|
+
await this.signalR.joinScope("callBack", jobId);
|
|
10864
|
+
}
|
|
10865
|
+
onNotificationSend(update) {
|
|
10866
|
+
// Enrutado por userId para campana/inbox
|
|
10867
|
+
if (update.userId) {
|
|
10868
|
+
this.userInboxSubjects.get(update.userId)?.next(update);
|
|
10869
|
+
}
|
|
10870
|
+
}
|
|
10871
|
+
onJobProgress(update) {
|
|
10872
|
+
// Enrutado por jobId para UIs multi-job
|
|
10873
|
+
if (update.jobId) {
|
|
10874
|
+
this.jobProgressSubjects.get(update.jobId)?.next(update);
|
|
10875
|
+
}
|
|
10876
|
+
// Lógica existente: solo aplica al job "actual" (feature/origin)
|
|
10877
|
+
if (!this.currentJobId || update.jobId !== this.currentJobId)
|
|
10878
|
+
return;
|
|
10879
|
+
if (update.recipientId) {
|
|
10880
|
+
const current = this.dispatchErrorsMapSubject.value;
|
|
10881
|
+
const next = new Map(current);
|
|
10882
|
+
if ((update.statusCode ?? "").toLowerCase() === "failed") {
|
|
10883
|
+
next.set(update.recipientId, {
|
|
10884
|
+
recipientId: update.recipientId,
|
|
10885
|
+
lastErrorMessage: update.lastErrorMessage ?? null,
|
|
10886
|
+
notificationId: update.notificationId,
|
|
10887
|
+
jobId: update.jobId ?? null,
|
|
10888
|
+
channelCode: update.channelCode,
|
|
10889
|
+
statusCode: update.statusCode,
|
|
10890
|
+
attempts: update.attempts,
|
|
10891
|
+
lastAttemptAt: update.lastAttemptAt ?? null,
|
|
10892
|
+
userId: update.userId ?? null,
|
|
10893
|
+
clientId: update.clientId ?? null,
|
|
10894
|
+
groupId: update.groupId ?? null,
|
|
10895
|
+
});
|
|
10896
|
+
}
|
|
10897
|
+
else {
|
|
10898
|
+
next.delete(update.recipientId);
|
|
10899
|
+
}
|
|
10900
|
+
this.dispatchErrorsMapSubject.next(next);
|
|
10901
|
+
}
|
|
10902
|
+
if (typeof update.jobProcessedCount === "number" && typeof update.jobTotalCount === "number") {
|
|
10903
|
+
this.setJobState({
|
|
10904
|
+
jobId: this.currentJobId,
|
|
10905
|
+
status: this.jobStateSubject.value.status,
|
|
10906
|
+
processedCount: update.jobProcessedCount,
|
|
10907
|
+
totalCount: update.jobTotalCount,
|
|
10908
|
+
processedNotificationsCount: update.jobProcessedNotificationsCount,
|
|
10909
|
+
totalNotificationsCount: update.jobTotalNotificationsCount,
|
|
10910
|
+
});
|
|
10911
|
+
}
|
|
10912
|
+
if (update.jobStatusCode?.toLowerCase() === "completed") {
|
|
10913
|
+
this.setJobState({
|
|
10914
|
+
jobId: this.currentJobId,
|
|
10915
|
+
status: "completed",
|
|
10916
|
+
processedCount: this.jobStateSubject.value.processedCount,
|
|
10917
|
+
totalCount: this.jobStateSubject.value.totalCount,
|
|
10918
|
+
processedNotificationsCount: this.jobStateSubject.value.processedNotificationsCount,
|
|
10919
|
+
totalNotificationsCount: this.jobStateSubject.value.totalNotificationsCount,
|
|
10920
|
+
});
|
|
10921
|
+
}
|
|
10922
|
+
else if (this.jobStateSubject.value.status === "pending") {
|
|
10923
|
+
this.setJobState({ ...this.jobStateSubject.value, status: "running" });
|
|
10924
|
+
}
|
|
10925
|
+
}
|
|
10926
|
+
onCallbackResult(update) {
|
|
10927
|
+
update.payload = update.payload ? JSON.parse(update.payload) : null;
|
|
10928
|
+
update.responseBody = update.responseBody ? JSON.parse(update.responseBody) : null;
|
|
10929
|
+
this.callbackRawSubject.next(update);
|
|
10930
|
+
}
|
|
10931
|
+
setJobState(state) {
|
|
10932
|
+
this.jobStateSubject.next({
|
|
10933
|
+
jobId: state.jobId,
|
|
10934
|
+
status: state.status,
|
|
10935
|
+
processedCount: state.processedCount,
|
|
10936
|
+
totalCount: state.totalCount,
|
|
10937
|
+
processedNotificationsCount: state.processedNotificationsCount,
|
|
10938
|
+
totalNotificationsCount: state.totalNotificationsCount,
|
|
10939
|
+
});
|
|
10940
|
+
}
|
|
10941
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationOrchestratorService, deps: [{ token: NotificationJobService }, { token: NotificationService }, { token: NotificationSignalRService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
10942
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationOrchestratorService, providedIn: "root" });
|
|
10943
|
+
}
|
|
10944
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: NotificationOrchestratorService, decorators: [{
|
|
10945
|
+
type: Injectable,
|
|
10946
|
+
args: [{ providedIn: "root" }]
|
|
10947
|
+
}], ctorParameters: () => [{ type: NotificationJobService }, { type: NotificationService }, { type: NotificationSignalRService }] });
|
|
10948
|
+
|
|
10389
10949
|
//Pipes
|
|
10390
10950
|
|
|
10391
10951
|
/**
|
|
10392
10952
|
* Generated bundle index. Do not edit.
|
|
10393
10953
|
*/
|
|
10394
10954
|
|
|
10395
|
-
export { ALERT_DEFAULTS, ALERT_ICON_PATHS, ALERT_TYPE_CONFIG, ActionDirective, ActionsMenuComponent, AddFavoritesComponent, AlertButtonMode, AlertService, AlertType, ButtonSplitComponent, CheckboxFilterDirective, Color, ColumnComponent, ColumnGroupComponent, CompareByField, ConfigService, CookieAttributesGeneral, DATEPICKER_BUTTON_TYPES, DataDirective, DateFilterDirective, DateModeOptions, DatepickerComponent, DynamicInputValidation, EchartComponent, EchartService, ElementService, EmailInputValidation, ErrorInterceptor, FeatureFlagService, FilterChipsComponent, FiltersComponent, FormatAmountPipe, GetCookieAttributes, GlobalFeatureFlagService, GlobalTermService, HtmlToExcelService, InitializeConfigService, InputValidation, IntelicaAlertComponent, IntelicaCellCheckboxDirective, IntelicaSessionService, IntelicaTheme, ItemSplitDirective, LanguageService, MatrixColumnComponent, MatrixColumnGroupComponent, MatrixTableComponent, ModalDialogComponent, MultiSelectComponent, OrderConstants, PageRootChildGuard, PaginatorComponent, Patterns, PopoverComponent, ProfileService, RecordPerPageComponent, RefreshTokenInterceptor, RouteGuard, RowResumenComponent, RowResumenTreeComponent, SearchComponent, SelectDetailFilterDirective, SelectFilterDirective, SharedService, SkeletonChartComponent, SkeletonComponent, SkeletonService, SkeletonTableComponent, SortingComponent, SpinnerComponent, SpinnerService, SweetAlertService, TableComponent, TableFetchComponent, TableSortOrder, TemplateDirective, TemplateMenuComponent, TermGuard, TermPipe, TermService, TextAreaFilterDirective, TextFilterDirective, TextRangeFilterDirective, TreeColumnComponent, TreeColumnGroupComponent, TreeTableComponent, TruncatePipe, decryptData, encryptData, getColor };
|
|
10955
|
+
export { ALERT_DEFAULTS, ALERT_ICON_PATHS, ALERT_TYPE_CONFIG, ActionDirective, ActionsMenuComponent, AddFavoritesComponent, AlertButtonMode, AlertService, AlertType, ButtonSplitComponent, CheckboxFilterDirective, Color, ColumnComponent, ColumnGroupComponent, CompareByField, ConfigService, CookieAttributesGeneral, DATEPICKER_BUTTON_TYPES, DataDirective, DateFilterDirective, DateModeOptions, DatepickerComponent, DynamicInputValidation, EchartComponent, EchartService, ElementService, EmailInputValidation, ErrorInterceptor, FeatureFlagService, FilterChipsComponent, FiltersComponent, FormatAmountPipe, GetCookieAttributes, GlobalFeatureFlagService, GlobalTermService, HtmlToExcelService, InitializeConfigService, InputValidation, IntelicaAlertComponent, IntelicaCellCheckboxDirective, IntelicaSessionService, IntelicaTheme, ItemSplitDirective, LanguageService, MatrixColumnComponent, MatrixColumnGroupComponent, MatrixTableComponent, ModalDialogComponent, MultiSelectComponent, NotificationJobService, NotificationOrchestratorService, NotificationService, NotificationSignalRService, OrderConstants, PageRootChildGuard, PaginatorComponent, Patterns, PopoverComponent, ProfileService, RecordPerPageComponent, RefreshTokenInterceptor, RouteGuard, RowResumenComponent, RowResumenTreeComponent, SearchComponent, SelectDetailFilterDirective, SelectFilterDirective, SharedService, SkeletonChartComponent, SkeletonComponent, SkeletonService, SkeletonTableComponent, SortingComponent, SpinnerComponent, SpinnerService, SweetAlertService, TableComponent, TableFetchComponent, TableSortOrder, TemplateDirective, TemplateMenuComponent, TermGuard, TermPipe, TermService, TextAreaFilterDirective, TextFilterDirective, TextRangeFilterDirective, TreeColumnComponent, TreeColumnGroupComponent, TreeTableComponent, TruncatePipe, decryptData, encryptData, getColor };
|
|
10396
10956
|
//# sourceMappingURL=intelica-library-components.mjs.map
|