ngx-dsxlibrary 1.0.61 → 1.0.63

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.
@@ -20,7 +20,6 @@ import { JwtHelperService } from '@auth0/angular-jwt';
20
20
  import { CookieService } from 'ngx-cookie-service';
21
21
  import { CommonModule } from '@angular/common';
22
22
  import { AccordionModule } from 'primeng/accordion';
23
- import { MessageService } from 'primeng/api';
24
23
  import { AutoCompleteModule } from 'primeng/autocomplete';
25
24
  import { AutoFocusModule } from 'primeng/autofocus';
26
25
  import { AvatarModule } from 'primeng/avatar';
@@ -220,6 +219,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
220
219
 
221
220
  class AlertaService {
222
221
  toastrService = inject(ToastrService);
222
+ //private primeMessageService = inject(MessageService);
223
223
  /**
224
224
  * @param {number} toastrType - 1. Success 2. Info 3. Warning 4. Error
225
225
  * @param {string} toastrTitle - Titulo de la alerta
@@ -369,22 +369,27 @@ class AlertaService {
369
369
  }
370
370
  return Swal.fire(alertConfig);
371
371
  }
372
- configureTimer(config, showConfirmButton, timer) {
373
- if (!showConfirmButton && timer > 0) {
374
- config.timer = timer;
375
- config.timerProgressBar = true;
376
- }
377
- }
378
- //notifyAlertSuccess(message: string) {
379
- // this._notyf.success({
380
- // message: message,
381
- // duration: 1500,
382
- // position: {
383
- // x: 'center',
384
- // y: 'top'
385
- // }
386
- // });
387
- //}
372
+ // private configureTimer(
373
+ // config: SweetAlertOptions,
374
+ // showConfirmButton: boolean,
375
+ // timer: number
376
+ // ) {
377
+ // if (!showConfirmButton && timer > 0) {
378
+ // config.timer = timer;
379
+ // config.timerProgressBar = true;
380
+ // }
381
+ // }
382
+ // No se puede utilizar por conflicto con primeng
383
+ // notyfAlert(message: string) {
384
+ // this.notyf.success({
385
+ // message: message,
386
+ // duration: 1500,
387
+ // position: {
388
+ // x: 'center',
389
+ // y: 'top',
390
+ // },
391
+ // });
392
+ // }
388
393
  toastrHttpResponse(response) {
389
394
  const time = 3000;
390
395
  const align = 'toast-top-center';
@@ -465,19 +470,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
465
470
 
466
471
  /**
467
472
  * Servicio para gestionar los parámetros de seguridad de la aplicación.
468
- * Permite cargar los parámetros desde la API, mantenerlos en memoria, y acceder
469
- * a sus valores de forma segura evitando `undefined` en los componentes.
473
+ * Permite cargar los parámetros desde la API, mantenerlos en memoria, acceder y comparar valores de forma segura.
474
+ * Utiliza tipado genérico para los nombres de parámetros y cache interno para optimizar consultas repetidas.
475
+ *
476
+ * @template T Tipo de los nombres de parámetros permitidos (usualmente un union type de string)
470
477
  */
471
478
  class ParameterValuesService {
472
- /** Parámetros iniciales inyectados mediante INITIAL_PARAMETERS */
479
+ /**
480
+ * Parámetros iniciales inyectados mediante INITIAL_PARAMETERS.
481
+ * Se usan para validar y mapear los parámetros recibidos de la API.
482
+ */
473
483
  initialParameters = inject(INITIAL_PARAMETERS);
474
- /** Servicio que contiene el método getParameterSecurity() */
484
+ /**
485
+ * Cache interno para optimizar la comparación de valores de parámetros.
486
+ * La clave es una combinación de nombre e índice, el valor es el resultado de la consulta.
487
+ */
488
+ parameterCache = new Map();
489
+ alertedParams = new Set();
490
+ /**
491
+ * Servicio que contiene el método getParameterSecurity() para obtener los parámetros desde la API.
492
+ */
475
493
  apiService = inject(SecurityService);
476
- /** Señal que contiene los parámetros cargados */
477
- _dataParameter = signal(this.initialParameters, ...(ngDevMode ? [{ debugName: "_dataParameter" }] : []));
478
- /** Flag que indica si ya se cargaron los parámetros desde la API */
494
+ /**
495
+ * Señal reactiva que contiene los parámetros cargados y permite actualizaciones automáticas.
496
+ */
497
+ _dataParameter = signal(this.initializeData(), ...(ngDevMode ? [{ debugName: "_dataParameter" }] : []));
498
+ /**
499
+ * Flag que indica si ya se cargaron los parámetros desde la API.
500
+ */
479
501
  _loaded = false;
480
- /** ===================== GETTERS/SETTERS ===================== */
502
+ /**
503
+ * Inicializa los datos de parámetros usando los valores inyectados.
504
+ * @returns Array de parámetros iniciales tipados
505
+ */
506
+ initializeData() {
507
+ return this.initialParameters.map((param) => this.createMyParameterValue(param.parameterName, param.values));
508
+ }
509
+ /**
510
+ * Crea una instancia de MyParameterValues tipada y segura.
511
+ * @param parameterName Nombre del parámetro
512
+ * @param values Valores asociados al parámetro
513
+ * @returns Objeto MyParameterValues
514
+ */
515
+ createMyParameterValue(parameterName, values) {
516
+ return {
517
+ parameterName,
518
+ values: [...values],
519
+ };
520
+ }
481
521
  /**
482
522
  * Devuelve los parámetros actuales como un array de solo lectura.
483
523
  */
@@ -496,7 +536,6 @@ class ParameterValuesService {
496
536
  }
497
537
  this._dataParameter.set(values);
498
538
  }
499
- /** ===================== MÉTODOS PRINCIPALES ===================== */
500
539
  /**
501
540
  * Carga los parámetros desde la API.
502
541
  * Si ya se cargaron y force=false, devuelve la copia en memoria.
@@ -530,7 +569,53 @@ class ParameterValuesService {
530
569
  refreshParameters() {
531
570
  return this.loadParameters(true);
532
571
  }
533
- /** ===================== MÉTODOS PRIVADOS ===================== */
572
+ /**
573
+ * Crea una copia segura y mutable de los parámetros actuales.
574
+ * @returns Array de parámetros
575
+ */
576
+ createSafeCopy() {
577
+ return this.dataParameter.map((item) => this.createMyParameterValue(item.parameterName, [...item.values]));
578
+ }
579
+ /**
580
+ * Mapea los parámetros recibidos de la API a objetos tipados y seguros.
581
+ * @param apiParameters Parámetros recibidos desde la API
582
+ * @returns Array de MyParameterValues
583
+ */
584
+ mapToMyParameterValues(apiParameters) {
585
+ const initialNames = this.initialParameters.map((p) => p.parameterName);
586
+ return apiParameters
587
+ .filter((param) => initialNames.includes(param.parameterName))
588
+ .map((param) => {
589
+ // Función de conversión type-safe
590
+ return this.convertToTypedParameter(param);
591
+ })
592
+ .filter((param) => param !== null);
593
+ }
594
+ /**
595
+ * Convierte un parámetro de la API a un objeto tipado, validando el nombre.
596
+ * @param param Parámetro recibido de la API
597
+ * @returns Objeto MyParameterValues o null si no es válido
598
+ */
599
+ convertToTypedParameter(param) {
600
+ const initialParam = this.initialParameters.find((p) => p.parameterName === param.parameterName);
601
+ if (!initialParam) {
602
+ return null;
603
+ }
604
+ // Conversión segura con verificación
605
+ if (this.isValidParameterName(param.parameterName)) {
606
+ return this.createMyParameterValue(param.parameterName, param.parameterValues?.map((v) => v.value) ?? []);
607
+ }
608
+ return null;
609
+ }
610
+ /**
611
+ * Verifica si un nombre de parámetro es válido según los parámetros iniciales.
612
+ * @param name Nombre a validar
613
+ * @returns true si es válido
614
+ */
615
+ isValidParameterName(name) {
616
+ // Verifica que el nombre esté en los parámetros iniciales
617
+ return this.initialParameters.some((param) => param.parameterName === name);
618
+ }
534
619
  /**
535
620
  * Valida que los parámetros devueltos por la API coincidan con los iniciales.
536
621
  * Muestra errores o advertencias en consola si existen diferencias.
@@ -549,21 +634,6 @@ class ParameterValuesService {
549
634
  console.warn(`Cantidad distinta: iniciales=${initialNames.length}, api=${apiNames.length}`);
550
635
  }
551
636
  }
552
- /**
553
- * Transforma un array de ParameterSecurity en MyParameterValues
554
- * @param apiParameters Parámetros recibidos desde la API
555
- * @returns Array de MyParameterValues
556
- */
557
- mapToMyParameterValues(apiParameters) {
558
- const initialNames = this.initialParameters.map((p) => p.parameterName);
559
- return apiParameters
560
- .filter((param) => initialNames.includes(param.parameterName))
561
- .map((param) => ({
562
- parameterName: param.parameterName,
563
- values: param.parameterValues?.map((v) => v.value) ?? [],
564
- }));
565
- }
566
- /** ===================== HELPERS SEGUROS ===================== */
567
637
  /**
568
638
  * Obtiene un valor específico de un parámetro.
569
639
  * Devuelve `defaultValue` si no existe o el índice es inválido.
@@ -580,14 +650,35 @@ class ParameterValuesService {
580
650
  return param.values[index];
581
651
  }
582
652
  /**
583
- * Compara un valor específico con un valor esperado.
653
+ * Compara un valor específico con un valor esperado, usando cache para optimizar llamadas repetidas.
584
654
  * @param parameterName Nombre del parámetro
585
655
  * @param expectedValue Valor esperado
586
656
  * @param index Índice del valor dentro del array (default: 0)
587
657
  * @returns true si coincide, false en caso contrario
588
658
  */
589
659
  isParameterValue(parameterName, expectedValue, index = 0) {
590
- return this.getValue(parameterName, index) === expectedValue;
660
+ const cacheKey = `${String(parameterName)}_${index}`;
661
+ // Validación: si el parámetro no existe, muestra mensaje solo una vez y corta el flujo
662
+ const paramExists = this.dataParameter.some((p) => p.parameterName === parameterName);
663
+ if (!paramExists) {
664
+ if (!this.alertedParams.has(parameterName)) {
665
+ window.alert(`Error: El parámetro '${parameterName}' no existe.`);
666
+ this.alertedParams.add(parameterName);
667
+ }
668
+ return false;
669
+ }
670
+ if (!this.parameterCache.has(cacheKey)) {
671
+ //console.log('Parametro: ' + parameterName);
672
+ const value = this.getValue(parameterName, index);
673
+ this.parameterCache.set(cacheKey, value);
674
+ }
675
+ return this.parameterCache.get(cacheKey) === expectedValue;
676
+ }
677
+ /**
678
+ * Limpia el cache interno de comparaciones de parámetros.
679
+ */
680
+ clearParameterCache() {
681
+ this.parameterCache.clear();
591
682
  }
592
683
  /**
593
684
  * Verifica si un parámetro tiene al menos un valor.
@@ -617,7 +708,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
617
708
  }] });
618
709
 
619
710
  class NavbarDsxComponent {
620
- _securityService = inject(SecurityService);
711
+ //private _securityService = inject(SecurityService);
621
712
  _parameterSecurityService = inject(ParameterValuesService);
622
713
  _alertaService = inject(AlertaService);
623
714
  logoWidth = input('300', ...(ngDevMode ? [{ debugName: "logoWidth" }] : []));
@@ -662,7 +753,7 @@ class NavbarDsxComponent {
662
753
  console.error('Error al actualizar parámetros de SeguridadIT', err);
663
754
  this._alertaService.toastrAlerts(3, 'SeguridadIT', 'Error al actualizar parámetros!', 2);
664
755
  },
665
- complete: () => '',
756
+ complete: () => this._parameterSecurityService.clearParameterCache(),
666
757
  });
667
758
  }
668
759
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: NavbarDsxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -1043,13 +1134,6 @@ function createInitialCache(cacheKeys) {
1043
1134
  return Object.fromEntries(Object.values(cacheKeys).map((key) => [key, false]));
1044
1135
  }
1045
1136
 
1046
- const INITIAL_PARAMETERS_FOR_TYPE = [
1047
- 'pCreate',
1048
- 'pRead',
1049
- 'pUpdate',
1050
- 'pDelete',
1051
- ];
1052
-
1053
1137
  class DsxAddToolsModule {
1054
1138
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DsxAddToolsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1055
1139
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.6", ngImport: i0, type: DsxAddToolsModule, imports: [JsonValuesDebujComponent], exports: [CommonModule,
@@ -1071,6 +1155,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
1071
1155
  JsonValuesDebujComponent,
1072
1156
  ReactiveFormsModule,
1073
1157
  ],
1158
+ providers: [],
1074
1159
  }]
1075
1160
  }] });
1076
1161
 
@@ -1140,7 +1225,7 @@ class PrimeNgModule {
1140
1225
  ToastModule,
1141
1226
  ToggleButtonModule,
1142
1227
  TooltipModule] });
1143
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: PrimeNgModule, providers: [MessageService], imports: [AccordionModule,
1228
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: PrimeNgModule, imports: [AccordionModule,
1144
1229
  AutoCompleteModule,
1145
1230
  AutoFocusModule,
1146
1231
  AvatarGroupModule,
@@ -1178,7 +1263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
1178
1263
  declarations: [],
1179
1264
  imports: [],
1180
1265
  exports: [...PRIME_NG_MODULES],
1181
- providers: [MessageService],
1266
+ providers: [],
1182
1267
  }]
1183
1268
  }] });
1184
1269
 
@@ -1459,39 +1544,38 @@ class UtilityAddService {
1459
1544
  *
1460
1545
  * @template T - El tipo genérico del modelo a procesar.
1461
1546
  * @param form - El formulario reactivo de Angular del que se obtendrán los valores.
1462
- * @param campos - Un array de objetos que especifican los campos de fecha y el tipo de conversión a aplicar. Cada objeto debe contener:
1547
+ * @param campos - Uno o más objetos que especifican los campos de fecha y el tipo de conversión a aplicar. Cada objeto debe contener:
1463
1548
  * - `nombre`: El nombre del campo de fecha en el modelo.
1464
1549
  * - `tipo`: El tipo de conversión que se debe aplicar (por ejemplo, `'short'` o `'zh'`).
1465
- * @param fieldName - (Opcional) El nombre de un campo específico en el formulario que contiene los datos. Si no se proporciona, se obtendrán todos los valores del formulario.
1466
- * @returns Un objeto del tipo `typeModel<T>` que contiene un array `values` con los datos procesados y las conversiones de fecha aplicadas.
1467
- * @throws Error - Si el campo especificado no existe en el formulario, o si un campo de fecha especificado no existe en los datos.
1550
+ * @returns Un objeto del tipo `typeModel<T>` con los datos procesados y las conversiones de fecha aplicadas.
1551
+ * @throws Error - Si el campo de fecha especificado no existe en los datos del formulario.
1552
+ *
1553
+ * @example
1554
+ * // Procesar varios campos de fecha
1555
+ * const precioValues = service.sanitizarModelo<ItemPrecioModel>(
1556
+ * form,
1557
+ * { nombre: 'fechaInicio', tipo: 'short' },
1558
+ * { nombre: 'fechaFin', tipo: 'zh' }
1559
+ * );
1468
1560
  */
1469
- sanitizarModelo(form, campos, fieldName) {
1470
- // Obtén los valores del formulario: un campo específico o todos los valores
1471
- const rawData = fieldName
1472
- ? form.get(fieldName)?.getRawValue()
1473
- : form.getRawValue();
1561
+ sanitizarModelo(form, ...campos) {
1562
+ // Obtén todos los valores del formulario
1563
+ const rawData = form.getRawValue();
1474
1564
  if (!rawData) {
1475
- const errorMessage = fieldName
1476
- ? `El campo "${fieldName}" no existe en el formulario.`
1477
- : `El formulario no tiene valores.`;
1478
- throw new Error(errorMessage);
1565
+ throw new Error('El formulario no tiene valores.');
1479
1566
  }
1480
1567
  // Procesa los valores sin envolver en un arreglo
1481
- const updatedValue = { ...rawData }; // Esto es un objeto, no un array
1568
+ const updatedValue = { ...rawData };
1482
1569
  // Itera sobre los campos de fecha especificados para realizar las conversiones
1483
1570
  campos.forEach(({ nombre, tipo }) => {
1484
- // Verifica si el campo de fecha existe en el valor
1485
1571
  if (!(nombre in updatedValue)) {
1486
1572
  throw new Error(`El campo "${nombre}" no existe en el valor.`);
1487
1573
  }
1488
- // Realiza la conversión de la fecha si tiene un valor
1489
1574
  updatedValue[nombre] = updatedValue[nombre]
1490
- ? this.convertirFecha(updatedValue[nombre], tipo) // Llama a la función genérica de conversión
1575
+ ? this.convertirFecha(updatedValue[nombre], tipo)
1491
1576
  : null;
1492
1577
  });
1493
- // Retorna el objeto con los valores procesados, no un arreglo
1494
- return updatedValue; // Devuelves un objeto con los valores, no un array
1578
+ return updatedValue;
1495
1579
  }
1496
1580
  /**
1497
1581
  * Convierte una fecha al formato especificado.
@@ -1504,6 +1588,26 @@ class UtilityAddService {
1504
1588
  * @returns La fecha convertida como string según el tipo especificado.
1505
1589
  * @throws Error - Si el tipo de conversión no es válido o soportado.
1506
1590
  */
1591
+ /**
1592
+ * Convierte una fecha al formato especificado.
1593
+ *
1594
+ * @param fecha - La fecha en formato string que se desea convertir.
1595
+ * Debe estar en un formato reconocible por `Date` o en ISO 8601.
1596
+ * @param tipo - El tipo de conversión a realizar. Actualmente soporta:
1597
+ * - `'short'`: Convierte la fecha a un formato corto (YYYY-MM-DD).
1598
+ * - `'zh'`: Convierte la fecha considerando la zona horaria configurada.
1599
+ * - `'iso'`: Convierte la fecha a formato ISO 8601 (string).
1600
+ * @returns La fecha convertida como string según el tipo especificado.
1601
+ * @throws Error - Si el tipo de conversión no es válido o soportado.
1602
+ *
1603
+ * @example
1604
+ * // Formato corto
1605
+ * service.convertirFecha('2025-08-21', 'short'); // '2025-08-21'
1606
+ * // Zona horaria
1607
+ * service.convertirFecha('2025-08-21', 'zh'); // '2025-08-21T00:00:00-06:00' (ejemplo)
1608
+ * // Formato ISO
1609
+ * service.convertirFecha('2025-08-21', 'iso'); // '2025-08-21T00:00:00.000Z'
1610
+ */
1507
1611
  convertirFecha(fecha, tipo) {
1508
1612
  switch (tipo) {
1509
1613
  case 'short':
@@ -1512,6 +1616,11 @@ class UtilityAddService {
1512
1616
  case 'zh':
1513
1617
  // Implementación para zonas horarias
1514
1618
  return this.convertirFechaSegunZonaHoraria(fecha);
1619
+ case 'iso': {
1620
+ // Convertir a Date y luego a string ISO
1621
+ const date = this.convertirFechaISOString(fecha);
1622
+ return date ? date.toISOString() : null;
1623
+ }
1515
1624
  default:
1516
1625
  throw new Error(`Tipo de conversión desconocido: ${tipo}`);
1517
1626
  }