@jvsoft/utils 0.0.13-alpha.5 → 1.0.0-alpha.10
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/README.md +5 -0
- package/directives/auto-select-first.directive.d.ts +13 -0
- package/directives/autocomplete-match-validator.directive.d.ts +10 -0
- package/directives/autocomplete.directive.d.ts +23 -0
- package/{src/functions → directives}/index.d.ts +1 -1
- package/directives/popover/popover-listener.directive.d.ts +12 -0
- package/directives/popover/popover-panel.component.d.ts +13 -0
- package/directives/popover/popover.directive.d.ts +23 -0
- package/directives/popover/popover.interface.d.ts +8 -0
- package/directives/popover/popover.service.d.ts +17 -0
- package/directives/public-api.d.ts +8 -0
- package/fesm2022/jvsoft-utils-directives.mjs +459 -0
- package/fesm2022/jvsoft-utils-directives.mjs.map +1 -0
- package/fesm2022/{jvsoft-utils-src-functions.mjs → jvsoft-utils-functions.mjs} +543 -190
- package/fesm2022/jvsoft-utils-functions.mjs.map +1 -0
- package/fesm2022/{jvsoft-utils-src-interfaces.mjs → jvsoft-utils-interfaces.mjs} +1 -1
- package/fesm2022/jvsoft-utils-interfaces.mjs.map +1 -0
- package/fesm2022/{jvsoft-utils-src-pipes.mjs → jvsoft-utils-pipes.mjs} +57 -2
- package/fesm2022/jvsoft-utils-pipes.mjs.map +1 -0
- package/fesm2022/jvsoft-utils-services.mjs +105 -0
- package/fesm2022/jvsoft-utils-services.mjs.map +1 -0
- package/fesm2022/jvsoft-utils.mjs +1142 -196
- package/fesm2022/jvsoft-utils.mjs.map +1 -1
- package/functions/base64.d.ts +87 -0
- package/functions/dev-log.d.ts +97 -0
- package/functions/index.d.ts +4 -0
- package/functions/mat-form-controls/autocomplete.d.ts +43 -27
- package/functions/objects-arrays.d.ts +13 -97
- package/functions/public-api.d.ts +1 -0
- package/interfaces/index.d.ts +4 -0
- package/package.json +27 -17
- package/pipes/display-with.pipe.d.ts +14 -0
- package/pipes/index.d.ts +4 -0
- package/pipes/public-api.d.ts +1 -0
- package/public-api.d.ts +6 -4
- package/{src/pipes → services}/index.d.ts +1 -1
- package/services/public-api.d.ts +1 -0
- package/services/reloj.service.d.ts +31 -0
- package/fesm2022/jvsoft-utils-src-functions.mjs.map +0 -1
- package/fesm2022/jvsoft-utils-src-interfaces.mjs.map +0 -1
- package/fesm2022/jvsoft-utils-src-pipes.mjs.map +0 -1
- package/src/functions/base64.d.ts +0 -2
- package/src/functions/browser.d.ts +0 -1
- package/src/functions/crypto-js.d.ts +0 -2
- package/src/functions/date.d.ts +0 -3
- package/src/functions/email.d.ts +0 -2
- package/src/functions/file.d.ts +0 -10
- package/src/functions/forms.d.ts +0 -23
- package/src/functions/http-client.d.ts +0 -2
- package/src/functions/local-storage.d.ts +0 -29
- package/src/functions/mat-form-controls/autocomplete.d.ts +0 -51
- package/src/functions/mat-form-controls/index.d.ts +0 -2
- package/src/functions/number.d.ts +0 -2
- package/src/functions/object-transformation.d.ts +0 -2
- package/src/functions/objects-arrays.d.ts +0 -147
- package/src/functions/public-api.d.ts +0 -16
- package/src/functions/string.d.ts +0 -23
- package/src/functions/sweetalert.d.ts +0 -5
- package/src/functions/utiles.d.ts +0 -1
- package/src/interfaces/datos.d.ts +0 -4
- package/src/interfaces/index.d.ts +0 -5
- package/src/interfaces/public-api.d.ts +0 -1
- package/src/pipes/data-en-lista.pipe.d.ts +0 -8
- package/src/pipes/date-diff-string.pipe.d.ts +0 -17
- package/src/pipes/filtro.pipe.d.ts +0 -18
- package/src/pipes/form-control-is-required.pipe.d.ts +0 -9
- package/src/pipes/json-parse.pipe.d.ts +0 -7
- package/src/pipes/no-sanitize.pipe.d.ts +0 -10
- package/src/pipes/public-api.d.ts +0 -8
- package/src/pipes/tipo-valor-funcion.pipe.d.ts +0 -9
- package/src/pipes/zero-fill.pipe.d.ts +0 -8
- /package/{classes → src/classes}/data-model.d.ts +0 -0
|
@@ -1,27 +1,24 @@
|
|
|
1
|
-
import { Validators, FormGroup, FormControl, FormArray } from '@angular/forms';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
1
|
+
import { Validators, FormGroup, FormControl, FormArray, NG_VALIDATORS, NgControl, FormControlName } from '@angular/forms';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { inject, DestroyRef, Pipe, input, forwardRef, Directive, computed, Component, TemplateRef, Injectable, ElementRef, ViewContainerRef, HostListener, output, effect, untracked, signal } from '@angular/core';
|
|
4
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
|
+
import { tap, startWith, debounceTime, isObservable, switchMap, of, finalize, Subject, merge, distinctUntilChanged, map as map$1 } from 'rxjs';
|
|
4
6
|
import { map } from 'rxjs/operators';
|
|
5
7
|
import { Buffer } from 'buffer';
|
|
6
8
|
import CryptoJS from 'crypto-js';
|
|
7
|
-
import
|
|
9
|
+
import * as i1$1 from '@angular/common';
|
|
10
|
+
import { formatDate, CommonModule } from '@angular/common';
|
|
8
11
|
import { saveAs } from 'file-saver';
|
|
9
12
|
import { ReactiveFormConfig } from '@rxweb/reactive-form-validators';
|
|
10
13
|
import moment from 'moment';
|
|
11
14
|
import swal from 'sweetalert2';
|
|
12
15
|
import { jwtDecode } from 'jwt-decode';
|
|
13
|
-
import * as i0 from '@angular/core';
|
|
14
|
-
import { Pipe } from '@angular/core';
|
|
15
16
|
import * as i1 from '@angular/platform-browser';
|
|
17
|
+
import { Overlay, OverlayPositionBuilder } from '@angular/cdk/overlay';
|
|
18
|
+
import { ComponentPortal } from '@angular/cdk/portal';
|
|
19
|
+
import { ToastrService } from 'ngx-toastr';
|
|
20
|
+
import { format } from 'date-fns';
|
|
16
21
|
|
|
17
|
-
/**
|
|
18
|
-
* Realiza una fusión profunda entre dos objetos, sin modificar el original.
|
|
19
|
-
* Si el valor en target no es un objeto, lo reemplaza directamente.
|
|
20
|
-
*
|
|
21
|
-
* @param source - Objeto fuente que se clonará y fusionará.
|
|
22
|
-
* @param target - Objeto destino cuyos valores se fusionarán.
|
|
23
|
-
* @returns Un nuevo objeto con la fusión profunda.
|
|
24
|
-
*/
|
|
25
22
|
function deepMerge(source, target) {
|
|
26
23
|
// Crea un clon profundo sin usar JSON.parse(JSON.stringify)
|
|
27
24
|
let cloneSource = deepClone(source);
|
|
@@ -43,12 +40,7 @@ function deepMerge(source, target) {
|
|
|
43
40
|
}
|
|
44
41
|
return cloneSource; // Retorna el clon y no modifica el original
|
|
45
42
|
}
|
|
46
|
-
|
|
47
|
-
* Realiza una clonación profunda de un objeto, manejando funciones, fechas y arrays.
|
|
48
|
-
*
|
|
49
|
-
* @param obj - Objeto a clonar.
|
|
50
|
-
* @returns Una copia profunda del objeto.
|
|
51
|
-
*/
|
|
43
|
+
// Función de clonación profunda que maneja funciones, fechas y otros tipos especiales
|
|
52
44
|
function deepClone(obj) {
|
|
53
45
|
if (obj === null || typeof obj !== 'object') {
|
|
54
46
|
return obj; // Devuelve el valor si no es un objeto
|
|
@@ -74,7 +66,6 @@ function deepClone(obj) {
|
|
|
74
66
|
/**
|
|
75
67
|
* Busca un elemento en un array o jerarquía de objetos según un campo y valor especificado.
|
|
76
68
|
*
|
|
77
|
-
* @param datosFn - Objeto con los parámetros de búsqueda: items, campo, valor y opcionalmente campoHijo.
|
|
78
69
|
* @returns El elemento encontrado o undefined si no existe.
|
|
79
70
|
*/
|
|
80
71
|
function buscarPorCampo(datosFn) {
|
|
@@ -101,33 +92,13 @@ function buscarPorCampo(datosFn) {
|
|
|
101
92
|
// Si no se encuentra nada, retorna undefined
|
|
102
93
|
return undefined;
|
|
103
94
|
}
|
|
104
|
-
/**
|
|
105
|
-
* Suma los valores de las propiedades especificadas de un objeto.
|
|
106
|
-
*
|
|
107
|
-
* @param item - Objeto con las propiedades a sumar.
|
|
108
|
-
* @param campos - Array de nombres de las propiedades a sumar.
|
|
109
|
-
* @returns La suma de los valores de las propiedades.
|
|
110
|
-
*/
|
|
111
95
|
function sumarPropiedades(item, campos) {
|
|
112
96
|
const datosSumar = campos.map(campo => (item[campo] * 1));
|
|
113
97
|
return datosSumar.reduce((a, b) => a + b, 0);
|
|
114
98
|
}
|
|
115
|
-
/**
|
|
116
|
-
* Verifica si el valor proporcionado es un número válido.
|
|
117
|
-
*
|
|
118
|
-
* @param value - Valor a verificar.
|
|
119
|
-
* @returns true si es un número, false en caso contrario.
|
|
120
|
-
*/
|
|
121
99
|
function esNumero(value) {
|
|
122
100
|
return !isNaN(Number(value));
|
|
123
101
|
}
|
|
124
|
-
/**
|
|
125
|
-
* Suma los valores de las propiedades especificadas en un array de objetos.
|
|
126
|
-
*
|
|
127
|
-
* @param arrayObjetos - Array de objetos a procesar.
|
|
128
|
-
* @param campos - Array de nombres de las propiedades a sumar.
|
|
129
|
-
* @returns Objeto con la suma de cada propiedad.
|
|
130
|
-
*/
|
|
131
102
|
function sumarObjetos(arrayObjetos, campos) {
|
|
132
103
|
return arrayObjetos.reduce((accumulator, item) => {
|
|
133
104
|
campos.forEach(campo => {
|
|
@@ -139,22 +110,9 @@ function sumarObjetos(arrayObjetos, campos) {
|
|
|
139
110
|
return accumulator;
|
|
140
111
|
}, {});
|
|
141
112
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Obtiene los valores únicos de un array.
|
|
144
|
-
*
|
|
145
|
-
* @param array - Array de valores.
|
|
146
|
-
* @returns Array con los valores únicos.
|
|
147
|
-
*/
|
|
148
113
|
function getUniqueValues(array) {
|
|
149
114
|
return array.filter((currentValue, index, arr) => (arr.indexOf(currentValue) === index));
|
|
150
115
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Obtiene los objetos únicos de un array según una propiedad específica.
|
|
153
|
-
*
|
|
154
|
-
* @param objetos - Array de objetos.
|
|
155
|
-
* @param campo - Nombre de la propiedad para determinar unicidad.
|
|
156
|
-
* @returns Array de objetos únicos por la propiedad.
|
|
157
|
-
*/
|
|
158
116
|
function getUniqueValuesByProperty(objetos, campo) {
|
|
159
117
|
const objetosUnicos = {};
|
|
160
118
|
objetos.forEach(objeto => {
|
|
@@ -170,14 +128,6 @@ function getUniqueValuesByProperty(objetos, campo) {
|
|
|
170
128
|
// Convertir el objeto de claves únicas de vuelta a una lista de objetos
|
|
171
129
|
return Object.values(objetosUnicos);
|
|
172
130
|
}
|
|
173
|
-
/**
|
|
174
|
-
* Ordena un array de valores numéricos o alfabéticos.
|
|
175
|
-
*
|
|
176
|
-
* @param array - Array a ordenar.
|
|
177
|
-
* @param numeros - Si es true, ordena como números.
|
|
178
|
-
* @param sentido - 'ASC' para ascendente, 'DESC' para descendente.
|
|
179
|
-
* @returns Array ordenado.
|
|
180
|
-
*/
|
|
181
131
|
function ordenarArray(array, numeros = false, sentido = 'ASC') {
|
|
182
132
|
if (numeros) {
|
|
183
133
|
if (sentido != 'ASC') {
|
|
@@ -187,24 +137,9 @@ function ordenarArray(array, numeros = false, sentido = 'ASC') {
|
|
|
187
137
|
}
|
|
188
138
|
return array.sort((a, b) => (a > b) ? 1 : ((b > a) ? -1 : 0));
|
|
189
139
|
}
|
|
190
|
-
/**
|
|
191
|
-
* Ordena un array de objetos por una propiedad específica.
|
|
192
|
-
*
|
|
193
|
-
* @param objData - Array de objetos a ordenar.
|
|
194
|
-
* @param propiedad - Propiedad por la que se ordena.
|
|
195
|
-
* @param numeros - (Obsoleto) Si es true, ordena como números.
|
|
196
|
-
* @returns Array ordenado.
|
|
197
|
-
*/
|
|
198
140
|
function ordenarPorPropiedad(objData, propiedad, /**@deprecated*/ numeros = false) {
|
|
199
141
|
return ordenarPorPropiedades(objData, { propiedades: [propiedad], direcciones: ['asc'] });
|
|
200
142
|
}
|
|
201
|
-
/**
|
|
202
|
-
* Ordena un array de objetos por varias propiedades y direcciones.
|
|
203
|
-
*
|
|
204
|
-
* @param arr - Array de objetos a ordenar.
|
|
205
|
-
* @param options - Opciones con propiedades y direcciones de orden.
|
|
206
|
-
* @returns Array ordenado.
|
|
207
|
-
*/
|
|
208
143
|
function ordenarPorPropiedades(arr, options) {
|
|
209
144
|
const { propiedades, direcciones = [] } = options;
|
|
210
145
|
const orden = direcciones.map(d => d === 'desc' ? -1 : 1);
|
|
@@ -224,13 +159,6 @@ function ordenarPorPropiedades(arr, options) {
|
|
|
224
159
|
}, 0);
|
|
225
160
|
});
|
|
226
161
|
}
|
|
227
|
-
/**
|
|
228
|
-
* Agrupa los elementos de un array según una clave o función de clave.
|
|
229
|
-
*
|
|
230
|
-
* @param array - Array de objetos a agrupar.
|
|
231
|
-
* @param key - Propiedad o función para agrupar.
|
|
232
|
-
* @returns Objeto con los grupos por clave.
|
|
233
|
-
*/
|
|
234
162
|
function groupBy(array, key) {
|
|
235
163
|
const keyFn = key instanceof Function ? key : (obj) => obj[key];
|
|
236
164
|
return array.reduce((objectsByKeyValue, obj) => {
|
|
@@ -239,13 +167,6 @@ function groupBy(array, key) {
|
|
|
239
167
|
return objectsByKeyValue;
|
|
240
168
|
}, {});
|
|
241
169
|
}
|
|
242
|
-
/**
|
|
243
|
-
* Agrupa y anida los elementos de un array según una lista de propiedades.
|
|
244
|
-
*
|
|
245
|
-
* @param arr - Array de objetos a agrupar.
|
|
246
|
-
* @param properties - Propiedades para agrupar de forma anidada.
|
|
247
|
-
* @returns Objeto anidado por los grupos de propiedades.
|
|
248
|
-
*/
|
|
249
170
|
function nestGroupsBy(arr, properties) {
|
|
250
171
|
const fnGroupBy = (conversions, property2) => {
|
|
251
172
|
return conversions.reduce((acc, obj) => {
|
|
@@ -319,13 +240,6 @@ function eliminarColumnaPorIndex(data, columnIndex) {
|
|
|
319
240
|
return newRow;
|
|
320
241
|
});
|
|
321
242
|
}
|
|
322
|
-
/**
|
|
323
|
-
* Elimina elementos duplicados de un array de objetos según claves específicas.
|
|
324
|
-
*
|
|
325
|
-
* @param array - Array de objetos.
|
|
326
|
-
* @param claves - Claves para determinar unicidad. Si no se especifica, compara todo el objeto.
|
|
327
|
-
* @returns Array sin duplicados.
|
|
328
|
-
*/
|
|
329
243
|
function eliminarDuplicados(array, claves) {
|
|
330
244
|
const unicos = new Map();
|
|
331
245
|
for (const item of array) {
|
|
@@ -338,14 +252,6 @@ function eliminarDuplicados(array, claves) {
|
|
|
338
252
|
}
|
|
339
253
|
return Array.from(unicos.values());
|
|
340
254
|
}
|
|
341
|
-
/**
|
|
342
|
-
* Elimina elementos de un array origen que estén presentes en otro array, según claves específicas.
|
|
343
|
-
*
|
|
344
|
-
* @param origen - Array original.
|
|
345
|
-
* @param elementosAEliminar - Elementos a eliminar del array origen.
|
|
346
|
-
* @param claves - Claves para comparar los objetos. Si no se especifica, compara todo el objeto.
|
|
347
|
-
* @returns Array filtrado sin los elementos eliminados.
|
|
348
|
-
*/
|
|
349
255
|
function eliminarElementos(origen, elementosAEliminar, claves) {
|
|
350
256
|
const clavesSet = new Set();
|
|
351
257
|
for (const item of elementosAEliminar) {
|
|
@@ -361,41 +267,12 @@ function eliminarElementos(origen, elementosAEliminar, claves) {
|
|
|
361
267
|
return !clavesSet.has(key);
|
|
362
268
|
});
|
|
363
269
|
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Devuelve un valor de visualización para un elemento buscado.
|
|
367
|
-
* Compatible con listas simples, objetos y campos múltiples.
|
|
368
|
-
*/
|
|
369
|
-
function mostrarValorEnBusqueda(campos, idxSel) {
|
|
370
|
-
const buscarEnLista = (lista) => {
|
|
371
|
-
if (!lista)
|
|
372
|
-
return null;
|
|
373
|
-
if (campos.campoId === '*object*' || campos.campoId === '*objeto*') {
|
|
374
|
-
return lista.find((x) => JSON.stringify(x).trim() === JSON.stringify(idxSel).trim());
|
|
375
|
-
}
|
|
376
|
-
return lista.find((x) => x[campos.campoId] === idxSel);
|
|
377
|
-
};
|
|
378
|
-
const impDataMostrar = () => {
|
|
379
|
-
let vD = buscarEnLista(campos.lista) || (campos.opcExtra && buscarEnLista(campos.opcExtra));
|
|
380
|
-
if (!vD)
|
|
381
|
-
return '';
|
|
382
|
-
if (Array.isArray(campos.campoValue)) {
|
|
383
|
-
return campos.campoValue.map((vCampo) => vD[vCampo] ?? '').join(' - ').trim();
|
|
384
|
-
}
|
|
385
|
-
return (vD[campos.campoValue] ?? '').trim();
|
|
386
|
-
};
|
|
387
|
-
if (esNumero(idxSel)) {
|
|
388
|
-
if ((idxSel > 0 && campos.lista?.length) || (idxSel && typeof idxSel === 'object')) {
|
|
389
|
-
return impDataMostrar();
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
else if (campos.lista?.length) {
|
|
393
|
-
return impDataMostrar();
|
|
394
|
-
}
|
|
395
|
-
return '';
|
|
396
|
-
}
|
|
397
270
|
/**
|
|
398
|
-
* Filtra datos
|
|
271
|
+
* Filtra datos localmente según un valor de búsqueda
|
|
272
|
+
* @param data - Array de datos a filtrar
|
|
273
|
+
* @param value - Valor de búsqueda
|
|
274
|
+
* @param campoBuscar - Campo(s) por el cual buscar
|
|
275
|
+
* @returns Array filtrado
|
|
399
276
|
*/
|
|
400
277
|
function filtrarDatosLocal(data, value, campoBuscar) {
|
|
401
278
|
if (!value)
|
|
@@ -414,32 +291,286 @@ function filtrarDatosLocal(data, value, campoBuscar) {
|
|
|
414
291
|
});
|
|
415
292
|
});
|
|
416
293
|
}
|
|
294
|
+
|
|
417
295
|
/**
|
|
418
|
-
*
|
|
296
|
+
* Intenta obtener el DestroyRef desde el llamador (objThis/control)
|
|
297
|
+
* o inyectándolo si estamos en un contexto de inyección.
|
|
419
298
|
*/
|
|
420
|
-
function
|
|
421
|
-
|
|
299
|
+
function obtenerDestroyRef(caller, manualDRef, fnName = 'N/A') {
|
|
300
|
+
let dRef = manualDRef || caller?.['destroyRef'] || caller?.['_destroyRef'];
|
|
301
|
+
if (!dRef) {
|
|
302
|
+
try {
|
|
303
|
+
dRef = inject(DestroyRef, { optional: true });
|
|
304
|
+
}
|
|
305
|
+
catch (e) {
|
|
306
|
+
console.warn(`${fnName}: Falló inject(DestroyRef) (fuera del contexto de inyección). Pasa el destroyRef explícitamente o decláralo en el componente para habilitar la limpieza.`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return dRef ?? undefined;
|
|
310
|
+
}
|
|
311
|
+
function mostrarValorEnBusqueda(campos, idxSel) {
|
|
312
|
+
const impDataMostrar = () => {
|
|
313
|
+
let vD;
|
|
314
|
+
if (campos.campoId == '*object*' || campos.campoId == '*objeto*') {
|
|
315
|
+
console.log(campos);
|
|
316
|
+
vD = campos.lista.find((x) => JSON.stringify(x).trim() == JSON.stringify(idxSel).trim());
|
|
317
|
+
console.log(vD);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
vD = campos.lista.find((x) => x[campos.campoId] == idxSel);
|
|
321
|
+
}
|
|
322
|
+
if (!vD && campos.opcExtra) {
|
|
323
|
+
console.log('eval ', campos.opcExtra);
|
|
324
|
+
if (campos.campoId == '*object*' || campos.campoId == '*objeto*') {
|
|
325
|
+
console.log(campos);
|
|
326
|
+
vD = campos.opcExtra.find((x) => JSON.stringify(x).trim() == JSON.stringify(idxSel).trim());
|
|
327
|
+
console.log(vD);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
vD = campos.opcExtra.find((x) => x[campos.campoId] == idxSel);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (vD) {
|
|
334
|
+
let txtFinal = '';
|
|
335
|
+
if (Array.isArray(campos.campoValue)) {
|
|
336
|
+
campos.campoValue.forEach((vCampo, idx) => {
|
|
337
|
+
txtFinal += (vD[vCampo] ?? '');
|
|
338
|
+
if (idx < campos.campoValue.length - 1) {
|
|
339
|
+
txtFinal += ' - ';
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
txtFinal = vD[campos.campoValue] ?? '';
|
|
345
|
+
}
|
|
346
|
+
return txtFinal.trim();
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
console.log('ASSSSS ----- SSSS ');
|
|
350
|
+
}
|
|
351
|
+
return '';
|
|
352
|
+
};
|
|
353
|
+
if (esNumero(idxSel)) {
|
|
354
|
+
if (idxSel > 0 && campos.lista?.length > 0) {
|
|
355
|
+
return impDataMostrar();
|
|
356
|
+
}
|
|
357
|
+
else if (idxSel && typeof idxSel == 'object') {
|
|
358
|
+
return impDataMostrar();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
if (campos.lista?.length > 0) {
|
|
363
|
+
return impDataMostrar();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return '';
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* @deprecated Use JvsAutocompleteDirective en su lugar para un enfoque más declarativo y robusto.
|
|
370
|
+
*/
|
|
371
|
+
function changeSelectData(objThis, dataFiltro) {
|
|
372
|
+
const dRef = obtenerDestroyRef(objThis, dataFiltro.destroyRef, 'changeSelectData');
|
|
373
|
+
objThis['filtrados'][dataFiltro.variableResultado] = dataFiltro.formControl.valueChanges.pipe(dRef ? takeUntilDestroyed(dRef) : tap(() => { })).pipe(startWith(''), map(value => {
|
|
374
|
+
const varN = dataFiltro.data;
|
|
375
|
+
if (varN) {
|
|
376
|
+
if (value) {
|
|
377
|
+
return varN.map(x => x).filter(dat => {
|
|
378
|
+
if (Array.isArray(dataFiltro.campoBuscar)) {
|
|
379
|
+
let encontrado = false;
|
|
380
|
+
for (const vCampo of dataFiltro.campoBuscar) {
|
|
381
|
+
// console.log(vCampo, value, dat[vCampo]);
|
|
382
|
+
if (isNaN(Number(value))) {
|
|
383
|
+
// NO ES NUMERO
|
|
384
|
+
if (value && dat[vCampo] && dat[vCampo].toLowerCase().includes(value?.toString().toLowerCase())) {
|
|
385
|
+
encontrado = true;
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
if (value && dat[vCampo] && dat[vCampo].toString().includes(value?.toString())) {
|
|
391
|
+
encontrado = true;
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return encontrado;
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
if (isNaN(Number(value))) {
|
|
400
|
+
return dat[dataFiltro.campoBuscar].toLowerCase().includes(value?.toString().toLowerCase());
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
return dat[dataFiltro.campoBuscar].toString().includes(value?.toString());
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
return varN;
|
|
409
|
+
}
|
|
410
|
+
return false;
|
|
411
|
+
}));
|
|
422
412
|
}
|
|
423
413
|
/**
|
|
424
|
-
*
|
|
414
|
+
* @deprecated Use JvsAutocompleteDirective en su lugar para un enfoque más declarativo y robusto.
|
|
425
415
|
*/
|
|
426
|
-
function changeSelect(control, formControl, tipo, campoBuscar, campoFiltro = null) {
|
|
427
|
-
|
|
428
|
-
|
|
416
|
+
function changeSelect(control, formControl, tipo, campoBuscar, campoFiltro = null, destroyRef) {
|
|
417
|
+
// console.log(formControl);
|
|
418
|
+
// const formGroup = formControl.parent.controls;
|
|
419
|
+
// console.warn( Object.keys(formGroup).find(name => formControl === formGroup[name]) || null );
|
|
420
|
+
if (!campoFiltro) {
|
|
421
|
+
campoFiltro = tipo;
|
|
422
|
+
}
|
|
423
|
+
const dRef = obtenerDestroyRef(control, destroyRef, 'changeSelect');
|
|
424
|
+
control['filtrados'][campoFiltro ?? '__'] = formControl.valueChanges.pipe(dRef ? takeUntilDestroyed(dRef) : tap(() => { })).pipe(startWith(''), map(value => {
|
|
425
|
+
// console.warn(value);
|
|
429
426
|
const partes = tipo.split('.');
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
control
|
|
433
|
-
|
|
427
|
+
let varN;
|
|
428
|
+
if (control['dataServidor']) {
|
|
429
|
+
varN = (partes.length > 1) ? control['dataServidor'][partes[0]][partes[1]] : control['dataServidor'][tipo];
|
|
430
|
+
}
|
|
431
|
+
else if (control['dataServidorSuscripcion']) {
|
|
432
|
+
varN = control['dataServidorSuscripcion'][tipo].getValue();
|
|
433
|
+
}
|
|
434
|
+
if (varN) {
|
|
435
|
+
if (value) {
|
|
436
|
+
return varN.map((x) => x).filter((dat) => {
|
|
437
|
+
if (Array.isArray(campoBuscar)) {
|
|
438
|
+
let encontrado = false;
|
|
439
|
+
for (const vCampo of campoBuscar) {
|
|
440
|
+
// console.log(vCampo, value, dat[vCampo]);
|
|
441
|
+
if (isNaN(Number(value))) {
|
|
442
|
+
// NO ES NUMERO
|
|
443
|
+
if (value && dat[vCampo] && dat[vCampo].toLowerCase().includes(value?.toString().toLowerCase())) {
|
|
444
|
+
encontrado = true;
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
if (value && dat[vCampo] && dat[vCampo].toString().includes(value?.toString())) {
|
|
450
|
+
encontrado = true;
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return encontrado;
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
if (isNaN(Number(value))) {
|
|
459
|
+
return dat[campoBuscar].toLowerCase().includes(value?.toString().toLowerCase());
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
return dat[campoBuscar].toString().includes(value?.toString());
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
return varN;
|
|
468
|
+
}
|
|
469
|
+
return false;
|
|
434
470
|
}));
|
|
435
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* @deprecated Use JvsAutocompleteDirective en su lugar para un enfoque más declarativo y robusto.
|
|
474
|
+
*/
|
|
475
|
+
function changeSelectDataApi(objThis, dataFiltro) {
|
|
476
|
+
if (!dataFiltro.variableResultado) {
|
|
477
|
+
dataFiltro.variableResultado = dataFiltro.tipoReq;
|
|
478
|
+
}
|
|
479
|
+
const idFiltrado = dataFiltro.variableResultado;
|
|
480
|
+
const dRef = obtenerDestroyRef(objThis, dataFiltro.destroyRef, 'changeSelectDataApi');
|
|
481
|
+
dataFiltro.formControl.valueChanges.pipe(dRef ? takeUntilDestroyed(dRef) : tap(() => { }), debounceTime(500), tap(() => {
|
|
482
|
+
objThis.filtrados[dataFiltro.variableResultado + 'tmp'] = isObservable(objThis.filtrados[idFiltrado]) ? [] : objThis.filtrados[idFiltrado] || [];
|
|
483
|
+
if (objThis.filtrados[idFiltrado] !== objThis.filtrados[idFiltrado + 'tmp']) {
|
|
484
|
+
objThis.filtrados[idFiltrado] = [];
|
|
485
|
+
}
|
|
486
|
+
objThis.isLoading = true;
|
|
487
|
+
}), switchMap(value => {
|
|
488
|
+
if (dataFiltro.campoId) {
|
|
489
|
+
const busquedaActual2 = objThis.filtrados[idFiltrado + 'tmp'].findIndex((item) => item[dataFiltro.campoId ?? '--'] === value);
|
|
490
|
+
if (busquedaActual2 >= 0) {
|
|
491
|
+
return of({ [dataFiltro.tipoReq]: objThis.filtrados[idFiltrado + 'tmp'] });
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return !value || value.length < (dataFiltro.minLength ?? 3) ? [] : (dataFiltro.queryService.getDataMethod('GET', dataFiltro.tipoReq, {
|
|
495
|
+
...(dataFiltro.dataExtra ?? {}),
|
|
496
|
+
...(dataFiltro.dataExtraVariable ? Object.fromEntries(dataFiltro.dataExtraVariable.map((objData) => [objData.campo, objData.ctrlValue.value])) : {}),
|
|
497
|
+
txtBuscar: value,
|
|
498
|
+
}, dataFiltro.anonimo).pipe(finalize(() => objThis.isLoading = false)));
|
|
499
|
+
})).subscribe((data) => {
|
|
500
|
+
objThis.filtrados[idFiltrado] = data[dataFiltro.tipoReq] ?? [];
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* @deprecated Use JvsAutocompleteDirective en su lugar para un enfoque más declarativo y robusto.
|
|
505
|
+
*/
|
|
506
|
+
function changeSelectApi(control, queryService, formControl, tipo, dataExtra = {}, dataExtraVariable = null, minLength = 1, anonimo = false, destroyRef) {
|
|
507
|
+
const dRef = obtenerDestroyRef(control, destroyRef, 'changeSelectApi');
|
|
508
|
+
formControl.valueChanges.pipe(dRef ? takeUntilDestroyed(dRef) : tap(() => { }), debounceTime(500), tap((value) => {
|
|
509
|
+
control['filtrados'][tipo + 'tmp'] = isObservable(control['filtrados'][tipo]) ? [] : control['filtrados'][tipo];
|
|
510
|
+
if (control['filtrados'][tipo] != control['filtrados'][tipo + 'tmp']) {
|
|
511
|
+
control['filtrados'][tipo] = [];
|
|
512
|
+
}
|
|
513
|
+
control['isLoading'] = true;
|
|
514
|
+
}), switchMap(value => {
|
|
515
|
+
const formGroup = formControl.parent?.controls;
|
|
516
|
+
const nombreControl = Object.keys(formGroup).find(name => formControl === formGroup[name]) || null;
|
|
517
|
+
if (nombreControl && control['filtrados'][tipo + 'tmp'] && control['filtrados'][tipo + 'tmp'].length > 0) {
|
|
518
|
+
const busquedaActual = control['filtrados'][tipo + 'tmp'].findIndex((item) => item[nombreControl] == value);
|
|
519
|
+
if (busquedaActual >= 0) {
|
|
520
|
+
const vRet = {};
|
|
521
|
+
vRet[tipo] = control['filtrados'][tipo + 'tmp'];
|
|
522
|
+
control['isLoading'] = false;
|
|
523
|
+
return of(vRet);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
if (!value || value.length < minLength) {
|
|
527
|
+
return [];
|
|
528
|
+
}
|
|
529
|
+
const dataExtraVariableData = {};
|
|
530
|
+
if (dataExtraVariable) {
|
|
531
|
+
// @ts-ignore
|
|
532
|
+
for (const objData of dataExtraVariable) {
|
|
533
|
+
dataExtraVariableData[objData.campo] = objData.ctrlValue.value;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return queryService.getDataMethod('GET', tipo, { ...dataExtra, ...dataExtraVariableData, ...{ txtBuscar: value } }, anonimo).pipe(finalize(() => {
|
|
537
|
+
control['isLoading'] = false;
|
|
538
|
+
}));
|
|
539
|
+
})).subscribe((data) => {
|
|
540
|
+
if (data[tipo] == undefined) {
|
|
541
|
+
control['filtrados'][tipo] = [];
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
control['filtrados'][tipo] = data[tipo];
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Comprueba si un valor es una Promesa
|
|
550
|
+
* @param valor - Valor a verificar
|
|
551
|
+
* @returns true si es una Promise
|
|
552
|
+
*/
|
|
553
|
+
function esPromise(valor) {
|
|
554
|
+
return !!valor && typeof valor.then === 'function';
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Selecciona todo el texto de un input
|
|
558
|
+
* @param event - Evento del input
|
|
559
|
+
*/
|
|
560
|
+
function seleccionarTextoInput$1(event) {
|
|
561
|
+
event.target.select();
|
|
562
|
+
}
|
|
436
563
|
/**
|
|
437
564
|
* Función genérica para vincular un FormControl con datos desde API o Promise.
|
|
438
565
|
* Preparada para migrar a signals en el futuro.
|
|
439
566
|
*/
|
|
567
|
+
/**
|
|
568
|
+
* @deprecated Use JvsAutocompleteDirective en su lugar para un enfoque más declarativo y robusto.
|
|
569
|
+
*/
|
|
440
570
|
function changeSelectReformateado(config) {
|
|
441
|
-
const { objThis, tipoReq, formControl, queryService, campoId, minLength = 3, dataExtra = {}, dataExtraVariable = [], anonimo = false, variableResultado = tipoReq, } = config;
|
|
442
|
-
|
|
571
|
+
const { objThis, tipoReq, formControl, queryService, campoId, minLength = 3, dataExtra = {}, dataExtraVariable = [], anonimo = false, variableResultado = tipoReq, destroyRef } = config;
|
|
572
|
+
const dRef = obtenerDestroyRef(objThis, destroyRef, 'changeSelectReformateado');
|
|
573
|
+
formControl.valueChanges.pipe(dRef ? takeUntilDestroyed(dRef) : tap(() => { }), debounceTime(500), tap(() => {
|
|
443
574
|
objThis.filtrados[variableResultado + 'tmp'] = isObservable(objThis.filtrados[variableResultado])
|
|
444
575
|
? []
|
|
445
576
|
: objThis.filtrados[variableResultado] || [];
|
|
@@ -459,10 +590,11 @@ function changeSelectReformateado(config) {
|
|
|
459
590
|
objThis.isLoading = false;
|
|
460
591
|
return of({ [tipoReq]: [] });
|
|
461
592
|
}
|
|
462
|
-
const extraVars = Object.fromEntries(dataExtraVariable.map(v => [v.campo, v.ctrlValue.value]));
|
|
593
|
+
const extraVars = Object.fromEntries(dataExtraVariable.map((v) => [v.campo, v.ctrlValue.value]));
|
|
463
594
|
const query = queryService.getDataMethod('GET', tipoReq, { ...dataExtra, ...extraVars, txtBuscar: value }, anonimo);
|
|
464
595
|
if (esPromise(query)) {
|
|
465
|
-
return query
|
|
596
|
+
return query
|
|
597
|
+
.then((data) => ({ [tipoReq]: data[tipoReq] ?? [] }))
|
|
466
598
|
.finally(() => { objThis.isLoading = false; });
|
|
467
599
|
}
|
|
468
600
|
return query.pipe(finalize(() => { objThis.isLoading = false; }));
|
|
@@ -470,54 +602,138 @@ function changeSelectReformateado(config) {
|
|
|
470
602
|
objThis.filtrados[variableResultado] = data[tipoReq] ?? [];
|
|
471
603
|
});
|
|
472
604
|
}
|
|
605
|
+
|
|
606
|
+
function seleccionarTextoInput(event) {
|
|
607
|
+
event.target.select();
|
|
608
|
+
}
|
|
609
|
+
|
|
473
610
|
/**
|
|
474
|
-
*
|
|
611
|
+
* Codifica un string a base64 (método legacy)
|
|
612
|
+
* @param val - String a codificar
|
|
613
|
+
* @returns String codificado en base64
|
|
614
|
+
* @deprecated Use encodeBase64String() en su lugar
|
|
475
615
|
*/
|
|
476
|
-
function
|
|
477
|
-
return
|
|
478
|
-
objThis,
|
|
479
|
-
tipoReq: dataFiltro.tipoReq,
|
|
480
|
-
formControl: dataFiltro.formControl,
|
|
481
|
-
queryService: dataFiltro.queryService,
|
|
482
|
-
campoId: dataFiltro.campoId,
|
|
483
|
-
minLength: dataFiltro.minLength,
|
|
484
|
-
dataExtra: dataFiltro.dataExtra,
|
|
485
|
-
dataExtraVariable: dataFiltro.dataExtraVariable,
|
|
486
|
-
anonimo: dataFiltro.anonimo,
|
|
487
|
-
variableResultado: dataFiltro.variableResultado,
|
|
488
|
-
});
|
|
616
|
+
function b64Encode(val) {
|
|
617
|
+
return Buffer.from(val, 'binary').toString('base64');
|
|
489
618
|
}
|
|
490
619
|
/**
|
|
491
|
-
*
|
|
620
|
+
* Decodifica un string desde base64 (método legacy)
|
|
621
|
+
* @param val - String en base64 a decodificar
|
|
622
|
+
* @returns String decodificado
|
|
623
|
+
* @deprecated Use decodeBase64String() en su lugar
|
|
492
624
|
*/
|
|
493
|
-
function
|
|
494
|
-
return
|
|
495
|
-
objThis: control,
|
|
496
|
-
tipoReq: tipo,
|
|
497
|
-
formControl,
|
|
498
|
-
queryService,
|
|
499
|
-
minLength,
|
|
500
|
-
dataExtra,
|
|
501
|
-
dataExtraVariable: dataExtraVariable ?? [],
|
|
502
|
-
anonimo,
|
|
503
|
-
});
|
|
625
|
+
function b64Decode(val) {
|
|
626
|
+
return Buffer.from(val, 'base64').toString('binary');
|
|
504
627
|
}
|
|
505
628
|
/**
|
|
506
|
-
*
|
|
629
|
+
* Codificar string a Base64 (UTF-8 seguro)
|
|
630
|
+
* @param str - String a codificar
|
|
631
|
+
* @returns String codificado en base64
|
|
632
|
+
*
|
|
633
|
+
* @example
|
|
634
|
+
* ```typescript
|
|
635
|
+
* const encoded = encodeBase64String('Hola Mundo ñ');
|
|
636
|
+
* // encoded: "SG9sYSBNdW5kbyDDsQ=="
|
|
637
|
+
* ```
|
|
507
638
|
*/
|
|
508
|
-
function
|
|
509
|
-
|
|
639
|
+
function encodeBase64String(str) {
|
|
640
|
+
const encoder = new TextEncoder();
|
|
641
|
+
const bytes = encoder.encode(str);
|
|
642
|
+
let binary = '';
|
|
643
|
+
bytes.forEach(b => binary += String.fromCharCode(b));
|
|
644
|
+
return btoa(binary);
|
|
510
645
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
646
|
+
/**
|
|
647
|
+
* Decodificar Base64 a string (UTF-8 seguro)
|
|
648
|
+
* @param b64 - String en base64 a decodificar
|
|
649
|
+
* @returns String decodificado
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* ```typescript
|
|
653
|
+
* const decoded = decodeBase64String('SG9sYSBNdW5kbyDDsQ==');
|
|
654
|
+
* // decoded: "Hola Mundo ñ"
|
|
655
|
+
* ```
|
|
656
|
+
*/
|
|
657
|
+
function decodeBase64String(b64) {
|
|
658
|
+
const binary = atob(b64);
|
|
659
|
+
const bytes = new Uint8Array(binary.length);
|
|
660
|
+
for (let i = 0; i < binary.length; i++) {
|
|
661
|
+
bytes[i] = binary.charCodeAt(i);
|
|
662
|
+
}
|
|
663
|
+
const decoder = new TextDecoder();
|
|
664
|
+
return decoder.decode(bytes);
|
|
514
665
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
666
|
+
/**
|
|
667
|
+
* Codificar un objeto a base64 (UTF-8 seguro)
|
|
668
|
+
* @param obj - Objeto a codificar
|
|
669
|
+
* @returns String codificado en base64
|
|
670
|
+
*
|
|
671
|
+
* @example
|
|
672
|
+
* ```typescript
|
|
673
|
+
* const obj = { nombre: 'Juan', edad: 25 };
|
|
674
|
+
* const encoded = encodeBase64Object(obj);
|
|
675
|
+
* ```
|
|
676
|
+
*/
|
|
677
|
+
function encodeBase64Object(obj) {
|
|
678
|
+
return encodeBase64String(JSON.stringify(obj));
|
|
518
679
|
}
|
|
519
|
-
|
|
520
|
-
|
|
680
|
+
/**
|
|
681
|
+
* Decodificar un base64 y obtener el objeto original
|
|
682
|
+
* @param b64 - String en base64 a decodificar
|
|
683
|
+
* @returns Objeto decodificado
|
|
684
|
+
*
|
|
685
|
+
* @example
|
|
686
|
+
* ```typescript
|
|
687
|
+
* const obj = decodeBase64Object<{ nombre: string, edad: number }>(encoded);
|
|
688
|
+
* // obj: { nombre: 'Juan', edad: 25 }
|
|
689
|
+
* ```
|
|
690
|
+
*/
|
|
691
|
+
function decodeBase64Object(b64) {
|
|
692
|
+
return JSON.parse(decodeBase64String(b64));
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Codificar archivo a Base64 (retorna solo el contenido, sin "data:...")
|
|
696
|
+
* @param file - Archivo o Blob a codificar
|
|
697
|
+
* @returns Promise con el string en base64
|
|
698
|
+
*
|
|
699
|
+
* @example
|
|
700
|
+
* ```typescript
|
|
701
|
+
* const file = event.target.files[0];
|
|
702
|
+
* const base64 = await encodeBase64File(file);
|
|
703
|
+
* // base64: "iVBORw0KGgoAAAANSUhEUgAA..."
|
|
704
|
+
* ```
|
|
705
|
+
*/
|
|
706
|
+
function encodeBase64File(file) {
|
|
707
|
+
return new Promise((resolve, reject) => {
|
|
708
|
+
const reader = new FileReader();
|
|
709
|
+
reader.onload = () => {
|
|
710
|
+
const result = reader.result;
|
|
711
|
+
resolve(result.split(',')[1]); // quita el prefijo "data:...;base64,"
|
|
712
|
+
};
|
|
713
|
+
reader.onerror = reject;
|
|
714
|
+
reader.readAsDataURL(file);
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Decodificar Base64 a Blob (para reconstruir archivos en Angular)
|
|
719
|
+
* @param b64 - String en base64
|
|
720
|
+
* @param mimeType - Tipo MIME del archivo (opcional)
|
|
721
|
+
* @returns Blob con el contenido decodificado
|
|
722
|
+
*
|
|
723
|
+
* @example
|
|
724
|
+
* ```typescript
|
|
725
|
+
* const blob = decodeBase64ToBlob(base64String, 'image/png');
|
|
726
|
+
* const url = URL.createObjectURL(blob);
|
|
727
|
+
* // Usar url para mostrar imagen o descargar
|
|
728
|
+
* ```
|
|
729
|
+
*/
|
|
730
|
+
function decodeBase64ToBlob(b64, mimeType = 'application/octet-stream') {
|
|
731
|
+
const byteChars = atob(b64);
|
|
732
|
+
const byteNumbers = new Array(byteChars.length);
|
|
733
|
+
for (let i = 0; i < byteChars.length; i++) {
|
|
734
|
+
byteNumbers[i] = byteChars.charCodeAt(i);
|
|
735
|
+
}
|
|
736
|
+
return new Blob([new Uint8Array(byteNumbers)], { type: mimeType });
|
|
521
737
|
}
|
|
522
738
|
|
|
523
739
|
function getBrowserName() {
|
|
@@ -583,6 +799,147 @@ function formatearFechaCadena(fecha) {
|
|
|
583
799
|
return new Date(year, month, day);
|
|
584
800
|
}
|
|
585
801
|
|
|
802
|
+
/**
|
|
803
|
+
* Configuración global para las utilidades de logging
|
|
804
|
+
*/
|
|
805
|
+
let isProductionMode = false;
|
|
806
|
+
/**
|
|
807
|
+
* Configura el modo de producción para las utilidades de logging
|
|
808
|
+
* @param production - true si está en modo producción, false para desarrollo
|
|
809
|
+
*
|
|
810
|
+
* @example
|
|
811
|
+
* ```typescript
|
|
812
|
+
* import { setProductionMode } from '@jvsoft/utils';
|
|
813
|
+
* import { environment } from './environments/environment';
|
|
814
|
+
*
|
|
815
|
+
* setProductionMode(environment.production);
|
|
816
|
+
* ```
|
|
817
|
+
*/
|
|
818
|
+
function setProductionMode(production) {
|
|
819
|
+
isProductionMode = production;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Obtiene el estado actual del modo de producción
|
|
823
|
+
* @returns true si está en modo producción, false en desarrollo
|
|
824
|
+
*/
|
|
825
|
+
function isProduction() {
|
|
826
|
+
return isProductionMode;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Muestra mensajes de log solo en modo desarrollo
|
|
830
|
+
* @param args - Argumentos a mostrar en consola
|
|
831
|
+
*
|
|
832
|
+
* @example
|
|
833
|
+
* ```typescript
|
|
834
|
+
* devLog('Usuario cargado:', usuario);
|
|
835
|
+
* devLog('Estado:', { activo: true, rol: 'admin' });
|
|
836
|
+
* ```
|
|
837
|
+
*/
|
|
838
|
+
function devLog(...args) {
|
|
839
|
+
if (!isProductionMode) {
|
|
840
|
+
console.log(...args);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Muestra advertencias solo en modo desarrollo
|
|
845
|
+
* @param args - Argumentos a mostrar como advertencia
|
|
846
|
+
*
|
|
847
|
+
* @example
|
|
848
|
+
* ```typescript
|
|
849
|
+
* devWarn('Función deprecada, usar nuevaFuncion() en su lugar');
|
|
850
|
+
* ```
|
|
851
|
+
*/
|
|
852
|
+
function devWarn(...args) {
|
|
853
|
+
if (!isProductionMode) {
|
|
854
|
+
console.warn(...args);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Muestra errores en consola (siempre, incluso en producción)
|
|
859
|
+
* @param args - Argumentos a mostrar como error
|
|
860
|
+
*
|
|
861
|
+
* @example
|
|
862
|
+
* ```typescript
|
|
863
|
+
* devError('Error al cargar datos:', error);
|
|
864
|
+
* ```
|
|
865
|
+
*/
|
|
866
|
+
function devError(...args) {
|
|
867
|
+
console.error(...args);
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Crea un grupo de logs solo en modo desarrollo
|
|
871
|
+
* @param label - Etiqueta del grupo
|
|
872
|
+
* @param collapsed - Si el grupo debe estar colapsado por defecto
|
|
873
|
+
*
|
|
874
|
+
* @example
|
|
875
|
+
* ```typescript
|
|
876
|
+
* devGroup('Datos del usuario');
|
|
877
|
+
* devLog('Nombre:', usuario.nombre);
|
|
878
|
+
* devLog('Email:', usuario.email);
|
|
879
|
+
* devGroupEnd();
|
|
880
|
+
* ```
|
|
881
|
+
*/
|
|
882
|
+
function devGroup(label, collapsed = false) {
|
|
883
|
+
if (!isProductionMode) {
|
|
884
|
+
if (collapsed) {
|
|
885
|
+
console.groupCollapsed(label);
|
|
886
|
+
}
|
|
887
|
+
else {
|
|
888
|
+
console.group(label);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Cierra el grupo de logs actual
|
|
894
|
+
*/
|
|
895
|
+
function devGroupEnd() {
|
|
896
|
+
if (!isProductionMode) {
|
|
897
|
+
console.groupEnd();
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Muestra una tabla en consola solo en modo desarrollo
|
|
902
|
+
* @param data - Datos a mostrar en formato tabla
|
|
903
|
+
*
|
|
904
|
+
* @example
|
|
905
|
+
* ```typescript
|
|
906
|
+
* devTable([
|
|
907
|
+
* { nombre: 'Juan', edad: 25 },
|
|
908
|
+
* { nombre: 'María', edad: 30 }
|
|
909
|
+
* ]);
|
|
910
|
+
* ```
|
|
911
|
+
*/
|
|
912
|
+
function devTable(data) {
|
|
913
|
+
if (!isProductionMode) {
|
|
914
|
+
console.table(data);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Inicia un temporizador solo en modo desarrollo
|
|
919
|
+
* @param label - Etiqueta del temporizador
|
|
920
|
+
*
|
|
921
|
+
* @example
|
|
922
|
+
* ```typescript
|
|
923
|
+
* devTime('carga-datos');
|
|
924
|
+
* // ... código a medir
|
|
925
|
+
* devTimeEnd('carga-datos'); // Muestra: carga-datos: 123.45ms
|
|
926
|
+
* ```
|
|
927
|
+
*/
|
|
928
|
+
function devTime(label) {
|
|
929
|
+
if (!isProductionMode) {
|
|
930
|
+
console.time(label);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Finaliza un temporizador y muestra el tiempo transcurrido
|
|
935
|
+
* @param label - Etiqueta del temporizador
|
|
936
|
+
*/
|
|
937
|
+
function devTimeEnd(label) {
|
|
938
|
+
if (!isProductionMode) {
|
|
939
|
+
console.timeEnd(label);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
586
943
|
function maskEmail(email) {
|
|
587
944
|
const [user, domain] = email.split("@");
|
|
588
945
|
if (user.length <= 2) {
|
|
@@ -1791,18 +2148,607 @@ function zeroFill(value, digitos, ...args) {
|
|
|
1791
2148
|
return new ZeroFillPipe().transform(value, digitos, args);
|
|
1792
2149
|
}
|
|
1793
2150
|
|
|
2151
|
+
class JvsDisplayWithPipe {
|
|
2152
|
+
/**
|
|
2153
|
+
* Retorna una función compatible con [displayWith] de MatAutocomplete.
|
|
2154
|
+
* @param lista La lista de objetos donde buscar.
|
|
2155
|
+
* @param campoId El nombre del campo que coincide con el valor del control (ej: 'iCarreraId').
|
|
2156
|
+
* @param campoValue El nombre del campo (o campos) a mostrar (ej: 'cCarreraNombre' o ['cCodigo', 'cNombre']).
|
|
2157
|
+
* @param opcExtra Lista opcional de objetos extra donde buscar si no se encuentra en la lista principal.
|
|
2158
|
+
*/
|
|
2159
|
+
transform(lista, campoId, campoValue, opcExtra) {
|
|
2160
|
+
return (idxSel) => {
|
|
2161
|
+
if (idxSel === null || idxSel === undefined || !lista) {
|
|
2162
|
+
return '';
|
|
2163
|
+
}
|
|
2164
|
+
const impDataMostrar = (vD) => {
|
|
2165
|
+
if (!vD)
|
|
2166
|
+
return '';
|
|
2167
|
+
if (Array.isArray(campoValue)) {
|
|
2168
|
+
return campoValue
|
|
2169
|
+
.map(field => vD[field] ?? '')
|
|
2170
|
+
.filter(val => !!val)
|
|
2171
|
+
.join(' - ');
|
|
2172
|
+
}
|
|
2173
|
+
return vD[campoValue]?.toString() || '';
|
|
2174
|
+
};
|
|
2175
|
+
// Buscar en la lista principal
|
|
2176
|
+
let item;
|
|
2177
|
+
if (campoId === '*object*' || campoId === '*objeto*') {
|
|
2178
|
+
item = lista.find(x => JSON.stringify(x).trim() === JSON.stringify(idxSel).trim());
|
|
2179
|
+
}
|
|
2180
|
+
else {
|
|
2181
|
+
item = lista.find(x => x[campoId] == idxSel);
|
|
2182
|
+
}
|
|
2183
|
+
// Si no se encuentra, buscar en opcExtra
|
|
2184
|
+
if (!item && opcExtra) {
|
|
2185
|
+
if (campoId === '*object*' || campoId === '*objeto*') {
|
|
2186
|
+
item = opcExtra.find(x => JSON.stringify(x).trim() === JSON.stringify(idxSel).trim());
|
|
2187
|
+
}
|
|
2188
|
+
else {
|
|
2189
|
+
item = opcExtra.find(x => x[campoId] == idxSel);
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
return item ? impDataMostrar(item).trim() : '';
|
|
2193
|
+
};
|
|
2194
|
+
}
|
|
2195
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsDisplayWithPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
2196
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: JvsDisplayWithPipe, isStandalone: true, name: "jvsDisplayWith" });
|
|
2197
|
+
}
|
|
2198
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsDisplayWithPipe, decorators: [{
|
|
2199
|
+
type: Pipe,
|
|
2200
|
+
args: [{
|
|
2201
|
+
name: 'jvsDisplayWith',
|
|
2202
|
+
standalone: true
|
|
2203
|
+
}]
|
|
2204
|
+
}] });
|
|
2205
|
+
|
|
1794
2206
|
// export * from './otros';
|
|
1795
2207
|
|
|
2208
|
+
class AutocompleteMatchValidatorDirective {
|
|
2209
|
+
opciones = input([], { alias: 'jvsAutocompleteMatch' });
|
|
2210
|
+
formControlName = input();
|
|
2211
|
+
idLista = input();
|
|
2212
|
+
validate(control) {
|
|
2213
|
+
const idLista = this.idLista() ?? this.formControlName();
|
|
2214
|
+
const value = control.value;
|
|
2215
|
+
const opciones = this.opciones();
|
|
2216
|
+
if (!value)
|
|
2217
|
+
return null;
|
|
2218
|
+
if (!opciones) {
|
|
2219
|
+
console.error('Debe definir opciones para el validador jvsAutocompleteMatch');
|
|
2220
|
+
return { itemSelected: true };
|
|
2221
|
+
}
|
|
2222
|
+
const encontrado = opciones.some(item => typeof value === 'object'
|
|
2223
|
+
? item[idLista] === value[idLista]
|
|
2224
|
+
: item[idLista] === value);
|
|
2225
|
+
return encontrado ? null : { itemSelected: true };
|
|
2226
|
+
}
|
|
2227
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AutocompleteMatchValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2228
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: AutocompleteMatchValidatorDirective, isStandalone: true, selector: "[jvsAutocompleteMatch]", inputs: { opciones: { classPropertyName: "opciones", publicName: "jvsAutocompleteMatch", isSignal: true, isRequired: false, transformFunction: null }, formControlName: { classPropertyName: "formControlName", publicName: "formControlName", isSignal: true, isRequired: false, transformFunction: null }, idLista: { classPropertyName: "idLista", publicName: "idLista", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
2229
|
+
{
|
|
2230
|
+
provide: NG_VALIDATORS,
|
|
2231
|
+
useExisting: forwardRef(() => AutocompleteMatchValidatorDirective),
|
|
2232
|
+
multi: true,
|
|
2233
|
+
},
|
|
2234
|
+
], ngImport: i0 });
|
|
2235
|
+
}
|
|
2236
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AutocompleteMatchValidatorDirective, decorators: [{
|
|
2237
|
+
type: Directive,
|
|
2238
|
+
args: [{
|
|
2239
|
+
selector: '[jvsAutocompleteMatch]',
|
|
2240
|
+
providers: [
|
|
2241
|
+
{
|
|
2242
|
+
provide: NG_VALIDATORS,
|
|
2243
|
+
useExisting: forwardRef(() => AutocompleteMatchValidatorDirective),
|
|
2244
|
+
multi: true,
|
|
2245
|
+
},
|
|
2246
|
+
],
|
|
2247
|
+
standalone: true
|
|
2248
|
+
}]
|
|
2249
|
+
}] });
|
|
2250
|
+
|
|
2251
|
+
class JvsPopoverPanelComponent {
|
|
2252
|
+
content = input(null);
|
|
2253
|
+
templateContent = input(null);
|
|
2254
|
+
context = input(null);
|
|
2255
|
+
customClass = input('');
|
|
2256
|
+
baseClasses = 'bg-white shadow-md rounded border-sm border-gray-700 p-1 mat-elevation-z4';
|
|
2257
|
+
combinedClasses = computed(() => {
|
|
2258
|
+
return `${this.baseClasses} ${this.customClass()}`.trim();
|
|
2259
|
+
});
|
|
2260
|
+
isTemplate() {
|
|
2261
|
+
return !!this.templateContent();
|
|
2262
|
+
}
|
|
2263
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2264
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.14", type: JvsPopoverPanelComponent, isStandalone: true, selector: "jvs-popover-panel", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, templateContent: { classPropertyName: "templateContent", publicName: "templateContent", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, customClass: { classPropertyName: "customClass", publicName: "customClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
2265
|
+
<div [class]="combinedClasses()">
|
|
2266
|
+
<ng-container *ngIf="isTemplate(); else htmlContent">
|
|
2267
|
+
<ng-container *ngTemplateOutlet="templateContent(); context: context()"></ng-container>
|
|
2268
|
+
</ng-container>
|
|
2269
|
+
<ng-template #htmlContent>
|
|
2270
|
+
<div [innerHTML]="content()"></div>
|
|
2271
|
+
</ng-template>
|
|
2272
|
+
</div>
|
|
2273
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
2274
|
+
}
|
|
2275
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverPanelComponent, decorators: [{
|
|
2276
|
+
type: Component,
|
|
2277
|
+
args: [{ selector: 'jvs-popover-panel', standalone: true, imports: [CommonModule], template: `
|
|
2278
|
+
<div [class]="combinedClasses()">
|
|
2279
|
+
<ng-container *ngIf="isTemplate(); else htmlContent">
|
|
2280
|
+
<ng-container *ngTemplateOutlet="templateContent(); context: context()"></ng-container>
|
|
2281
|
+
</ng-container>
|
|
2282
|
+
<ng-template #htmlContent>
|
|
2283
|
+
<div [innerHTML]="content()"></div>
|
|
2284
|
+
</ng-template>
|
|
2285
|
+
</div>
|
|
2286
|
+
`, styles: [":host{display:block}\n"] }]
|
|
2287
|
+
}] });
|
|
2288
|
+
|
|
2289
|
+
class JvsPopoverService {
|
|
2290
|
+
overlay = inject(Overlay);
|
|
2291
|
+
overlayPositionBuilder = inject(OverlayPositionBuilder);
|
|
2292
|
+
overlayRef = null;
|
|
2293
|
+
open(element, content, options = {}) {
|
|
2294
|
+
this.close();
|
|
2295
|
+
const positionStrategy = this.overlayPositionBuilder
|
|
2296
|
+
.flexibleConnectedTo(element)
|
|
2297
|
+
.withPositions([
|
|
2298
|
+
{
|
|
2299
|
+
originX: 'center',
|
|
2300
|
+
originY: options.position === 'top' ? 'top' : 'bottom',
|
|
2301
|
+
overlayX: 'center',
|
|
2302
|
+
overlayY: options.position === 'top' ? 'bottom' : 'top',
|
|
2303
|
+
offsetY: options.position === 'top' ? -8 : 8
|
|
2304
|
+
}
|
|
2305
|
+
]);
|
|
2306
|
+
this.overlayRef = this.overlay.create({
|
|
2307
|
+
positionStrategy,
|
|
2308
|
+
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
2309
|
+
hasBackdrop: false
|
|
2310
|
+
});
|
|
2311
|
+
const portal = new ComponentPortal(JvsPopoverPanelComponent, options.viewContainerRef);
|
|
2312
|
+
const containerRef = this.overlayRef.attach(portal);
|
|
2313
|
+
if (content instanceof TemplateRef) {
|
|
2314
|
+
containerRef.setInput('templateContent', content);
|
|
2315
|
+
}
|
|
2316
|
+
else {
|
|
2317
|
+
containerRef.setInput('content', content);
|
|
2318
|
+
}
|
|
2319
|
+
if (options.customClass) {
|
|
2320
|
+
containerRef.setInput('customClass', options.customClass);
|
|
2321
|
+
}
|
|
2322
|
+
if (options.context) {
|
|
2323
|
+
containerRef.setInput('context', options.context);
|
|
2324
|
+
}
|
|
2325
|
+
return this.overlayRef;
|
|
2326
|
+
}
|
|
2327
|
+
close() {
|
|
2328
|
+
if (this.overlayRef) {
|
|
2329
|
+
this.overlayRef.detach();
|
|
2330
|
+
this.overlayRef.dispose();
|
|
2331
|
+
this.overlayRef = null;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2335
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverService, providedIn: 'root' });
|
|
2336
|
+
}
|
|
2337
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverService, decorators: [{
|
|
2338
|
+
type: Injectable,
|
|
2339
|
+
args: [{
|
|
2340
|
+
providedIn: 'root'
|
|
2341
|
+
}]
|
|
2342
|
+
}] });
|
|
2343
|
+
|
|
2344
|
+
class JvsPopoverDirective {
|
|
2345
|
+
popoverService = inject(JvsPopoverService);
|
|
2346
|
+
elementRef = inject(ElementRef);
|
|
2347
|
+
viewContainerRef = inject(ViewContainerRef);
|
|
2348
|
+
content = input(null, { alias: 'jvsPopover' });
|
|
2349
|
+
context = input(null);
|
|
2350
|
+
trigger = input('hover');
|
|
2351
|
+
position = input('bottom');
|
|
2352
|
+
customClass = input('');
|
|
2353
|
+
onMouseEnter() {
|
|
2354
|
+
if (this.trigger() === 'hover') {
|
|
2355
|
+
this.show();
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
onMouseLeave() {
|
|
2359
|
+
if (this.trigger() === 'hover') {
|
|
2360
|
+
this.hide();
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
onClick() {
|
|
2364
|
+
if (this.trigger() === 'click') {
|
|
2365
|
+
this.show();
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
onFocus() {
|
|
2369
|
+
if (this.trigger() === 'focus') {
|
|
2370
|
+
this.show();
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
onBlur() {
|
|
2374
|
+
if (this.trigger() === 'focus') {
|
|
2375
|
+
this.hide();
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
ngOnDestroy() {
|
|
2379
|
+
this.hide();
|
|
2380
|
+
}
|
|
2381
|
+
show() {
|
|
2382
|
+
const content = this.content();
|
|
2383
|
+
if (!content)
|
|
2384
|
+
return;
|
|
2385
|
+
this.popoverService.open(this.elementRef.nativeElement, content, {
|
|
2386
|
+
position: this.position(),
|
|
2387
|
+
customClass: this.customClass(),
|
|
2388
|
+
viewContainerRef: this.viewContainerRef,
|
|
2389
|
+
context: this.context()
|
|
2390
|
+
});
|
|
2391
|
+
}
|
|
2392
|
+
hide() {
|
|
2393
|
+
this.popoverService.close();
|
|
2394
|
+
}
|
|
2395
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2396
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: JvsPopoverDirective, isStandalone: true, selector: "[jvsPopover]", inputs: { content: { classPropertyName: "content", publicName: "jvsPopover", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, customClass: { classPropertyName: "customClass", publicName: "customClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "click": "onClick()", "focusin": "onFocus()", "focusout": "onBlur()" } }, ngImport: i0 });
|
|
2397
|
+
}
|
|
2398
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverDirective, decorators: [{
|
|
2399
|
+
type: Directive,
|
|
2400
|
+
args: [{
|
|
2401
|
+
selector: '[jvsPopover]',
|
|
2402
|
+
standalone: true
|
|
2403
|
+
}]
|
|
2404
|
+
}], propDecorators: { onMouseEnter: [{
|
|
2405
|
+
type: HostListener,
|
|
2406
|
+
args: ['mouseenter']
|
|
2407
|
+
}], onMouseLeave: [{
|
|
2408
|
+
type: HostListener,
|
|
2409
|
+
args: ['mouseleave']
|
|
2410
|
+
}], onClick: [{
|
|
2411
|
+
type: HostListener,
|
|
2412
|
+
args: ['click']
|
|
2413
|
+
}], onFocus: [{
|
|
2414
|
+
type: HostListener,
|
|
2415
|
+
args: ['focusin']
|
|
2416
|
+
}], onBlur: [{
|
|
2417
|
+
type: HostListener,
|
|
2418
|
+
args: ['focusout']
|
|
2419
|
+
}] } });
|
|
2420
|
+
|
|
2421
|
+
class JvsPopoverListenerDirective {
|
|
2422
|
+
popoverService = inject(JvsPopoverService);
|
|
2423
|
+
elementRef = inject(ElementRef);
|
|
2424
|
+
trigger = input('hover');
|
|
2425
|
+
onMouseOver(event) {
|
|
2426
|
+
if (this.trigger() !== 'hover')
|
|
2427
|
+
return;
|
|
2428
|
+
const target = this.findPopoverTarget(event.target);
|
|
2429
|
+
if (target) {
|
|
2430
|
+
const content = target.getAttribute('data-jvs-popover');
|
|
2431
|
+
if (content) {
|
|
2432
|
+
this.popoverService.open(target, content, {
|
|
2433
|
+
position: target.getAttribute('data-jvs-position') || 'bottom',
|
|
2434
|
+
customClass: target.getAttribute('data-jvs-class') || ''
|
|
2435
|
+
});
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
onMouseOut(event) {
|
|
2440
|
+
if (this.trigger() !== 'hover')
|
|
2441
|
+
return;
|
|
2442
|
+
this.popoverService.close();
|
|
2443
|
+
}
|
|
2444
|
+
onClick(event) {
|
|
2445
|
+
if (this.trigger() !== 'click')
|
|
2446
|
+
return;
|
|
2447
|
+
const target = this.findPopoverTarget(event.target);
|
|
2448
|
+
if (target) {
|
|
2449
|
+
const content = target.getAttribute('data-jvs-popover');
|
|
2450
|
+
if (content) {
|
|
2451
|
+
this.popoverService.open(target, content, {
|
|
2452
|
+
position: target.getAttribute('data-jvs-position') || 'bottom',
|
|
2453
|
+
customClass: target.getAttribute('data-jvs-class') || ''
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
findPopoverTarget(el) {
|
|
2459
|
+
while (el && el !== this.elementRef.nativeElement) {
|
|
2460
|
+
if (el.hasAttribute('data-jvs-popover')) {
|
|
2461
|
+
return el;
|
|
2462
|
+
}
|
|
2463
|
+
el = el.parentElement;
|
|
2464
|
+
}
|
|
2465
|
+
return null;
|
|
2466
|
+
}
|
|
2467
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverListenerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2468
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: JvsPopoverListenerDirective, isStandalone: true, selector: "[jvsPopoverListener]", inputs: { trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseover": "onMouseOver($event)", "mouseout": "onMouseOut($event)", "click": "onClick($event)" } }, ngImport: i0 });
|
|
2469
|
+
}
|
|
2470
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverListenerDirective, decorators: [{
|
|
2471
|
+
type: Directive,
|
|
2472
|
+
args: [{
|
|
2473
|
+
selector: '[jvsPopoverListener]',
|
|
2474
|
+
standalone: true
|
|
2475
|
+
}]
|
|
2476
|
+
}], propDecorators: { onMouseOver: [{
|
|
2477
|
+
type: HostListener,
|
|
2478
|
+
args: ['mouseover', ['$event']]
|
|
2479
|
+
}], onMouseOut: [{
|
|
2480
|
+
type: HostListener,
|
|
2481
|
+
args: ['mouseout', ['$event']]
|
|
2482
|
+
}], onClick: [{
|
|
2483
|
+
type: HostListener,
|
|
2484
|
+
args: ['click', ['$event']]
|
|
2485
|
+
}] } });
|
|
2486
|
+
|
|
2487
|
+
class JvsAutocompleteDirective {
|
|
2488
|
+
destroyRef = inject(DestroyRef);
|
|
2489
|
+
ngControl = inject(NgControl, { optional: true });
|
|
2490
|
+
focus$ = new Subject();
|
|
2491
|
+
// Signal-based Inputs
|
|
2492
|
+
data = input(null);
|
|
2493
|
+
fields = input('');
|
|
2494
|
+
typeReq = input('');
|
|
2495
|
+
queryService = input(null);
|
|
2496
|
+
minLength = input(3);
|
|
2497
|
+
dataExtra = input({});
|
|
2498
|
+
anonimo = input(false);
|
|
2499
|
+
debounce = input(300);
|
|
2500
|
+
// Modern Outputs
|
|
2501
|
+
filtered = output();
|
|
2502
|
+
loading = output();
|
|
2503
|
+
onFocus() {
|
|
2504
|
+
this.focus$.next();
|
|
2505
|
+
}
|
|
2506
|
+
ngOnInit() {
|
|
2507
|
+
const control = this.ngControl;
|
|
2508
|
+
if (!control || !control.valueChanges) {
|
|
2509
|
+
console.warn('JvsAutocompleteDirective: No se encontró ngControl o valueChanges. Asegúrate de que el input tenga un formControl o formControlName.');
|
|
2510
|
+
return;
|
|
2511
|
+
}
|
|
2512
|
+
// Si es data local, bajamos el debounce por defecto a 0 si no se ha especificado
|
|
2513
|
+
const isLocal = this.data() && !this.typeReq();
|
|
2514
|
+
const actualDebounce = (isLocal && this.debounce() === 300) ? 0 : this.debounce();
|
|
2515
|
+
merge(control.valueChanges.pipe(debounceTime(actualDebounce)), this.focus$).pipe(takeUntilDestroyed(this.destroyRef), startWith(control.value), distinctUntilChanged(), tap(() => {
|
|
2516
|
+
if (this.typeReq())
|
|
2517
|
+
this.loading.emit(true);
|
|
2518
|
+
}), switchMap(() => {
|
|
2519
|
+
const value = control.value;
|
|
2520
|
+
// Si el valor es un objeto (proviene de seleccionar una opción), no volvemos a filtrar
|
|
2521
|
+
if (typeof value === 'object' && value !== null) {
|
|
2522
|
+
if (this.typeReq())
|
|
2523
|
+
this.loading.emit(false);
|
|
2524
|
+
return of(null);
|
|
2525
|
+
}
|
|
2526
|
+
if (this.typeReq() && this.queryService()) {
|
|
2527
|
+
return this.fetchApi(value?.toString() || '');
|
|
2528
|
+
}
|
|
2529
|
+
else if (this.data()) {
|
|
2530
|
+
const res = this.filterLocal(value?.toString() || '');
|
|
2531
|
+
return of(res);
|
|
2532
|
+
}
|
|
2533
|
+
if (this.typeReq())
|
|
2534
|
+
this.loading.emit(false);
|
|
2535
|
+
return of([]);
|
|
2536
|
+
})).subscribe((result) => {
|
|
2537
|
+
if (result !== null) {
|
|
2538
|
+
this.filtered.emit(result);
|
|
2539
|
+
}
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
filterLocal(value) {
|
|
2543
|
+
const data = this.data();
|
|
2544
|
+
if (!value)
|
|
2545
|
+
return data || [];
|
|
2546
|
+
const search = value.toLowerCase();
|
|
2547
|
+
const rawFields = this.fields();
|
|
2548
|
+
const fields = Array.isArray(rawFields) ? rawFields : [rawFields];
|
|
2549
|
+
return (data || []).filter(item => {
|
|
2550
|
+
return fields.some(field => {
|
|
2551
|
+
const val = item[field];
|
|
2552
|
+
return val && val.toString().toLowerCase().includes(search);
|
|
2553
|
+
});
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
fetchApi(value) {
|
|
2557
|
+
const typeReq = this.typeReq();
|
|
2558
|
+
const queryService = this.queryService();
|
|
2559
|
+
if (!value || value.length < this.minLength()) {
|
|
2560
|
+
this.loading.emit(false);
|
|
2561
|
+
return of([]);
|
|
2562
|
+
}
|
|
2563
|
+
return queryService.getDataMethod('GET', typeReq, {
|
|
2564
|
+
...this.dataExtra(),
|
|
2565
|
+
txtBuscar: value
|
|
2566
|
+
}, this.anonimo()).pipe(map$1((res) => res[typeReq] ?? []), finalize(() => this.loading.emit(false)));
|
|
2567
|
+
}
|
|
2568
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsAutocompleteDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2569
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: JvsAutocompleteDirective, isStandalone: true, selector: "[jvsAutocomplete]", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null }, typeReq: { classPropertyName: "typeReq", publicName: "typeReq", isSignal: true, isRequired: false, transformFunction: null }, queryService: { classPropertyName: "queryService", publicName: "queryService", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, dataExtra: { classPropertyName: "dataExtra", publicName: "dataExtra", isSignal: true, isRequired: false, transformFunction: null }, anonimo: { classPropertyName: "anonimo", publicName: "anonimo", isSignal: true, isRequired: false, transformFunction: null }, debounce: { classPropertyName: "debounce", publicName: "debounce", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filtered: "filtered", loading: "loading" }, host: { listeners: { "focus": "onFocus()" } }, ngImport: i0 });
|
|
2570
|
+
}
|
|
2571
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsAutocompleteDirective, decorators: [{
|
|
2572
|
+
type: Directive,
|
|
2573
|
+
args: [{
|
|
2574
|
+
selector: '[jvsAutocomplete]',
|
|
2575
|
+
standalone: true
|
|
2576
|
+
}]
|
|
2577
|
+
}], propDecorators: { onFocus: [{
|
|
2578
|
+
type: HostListener,
|
|
2579
|
+
args: ['focus']
|
|
2580
|
+
}] } });
|
|
2581
|
+
|
|
2582
|
+
class AutoSelectFirstDirective {
|
|
2583
|
+
ngControl = inject(NgControl, { optional: true });
|
|
2584
|
+
fcName = inject(FormControlName, { optional: true });
|
|
2585
|
+
toastr = inject(ToastrService, { optional: true });
|
|
2586
|
+
// Inputs using Signals
|
|
2587
|
+
options = input(null, { alias: 'jvsAutoSelectFirst' });
|
|
2588
|
+
jvsIdKey = input(null);
|
|
2589
|
+
jvsEmptyMsg = input('Lista sin elementos');
|
|
2590
|
+
onAutoSelect = output();
|
|
2591
|
+
constructor() {
|
|
2592
|
+
effect(() => {
|
|
2593
|
+
const currentOptions = this.options();
|
|
2594
|
+
const idKey = this.jvsIdKey();
|
|
2595
|
+
const emptyMsg = this.jvsEmptyMsg();
|
|
2596
|
+
if (currentOptions === null)
|
|
2597
|
+
return;
|
|
2598
|
+
const optionsArray = Array.isArray(currentOptions) ? currentOptions : [];
|
|
2599
|
+
if (optionsArray.length > 0) {
|
|
2600
|
+
untracked(() => {
|
|
2601
|
+
const control = this.ngControl?.control;
|
|
2602
|
+
const currentValue = control?.value;
|
|
2603
|
+
// Only autoselect if empty
|
|
2604
|
+
if (control && (currentValue === null || currentValue === undefined || currentValue === '')) {
|
|
2605
|
+
const firstItem = optionsArray[0];
|
|
2606
|
+
let valueToSet;
|
|
2607
|
+
// Resolve key
|
|
2608
|
+
let effectiveKey = idKey;
|
|
2609
|
+
// Default to formControlName if not provided
|
|
2610
|
+
if (!effectiveKey && this.fcName) {
|
|
2611
|
+
effectiveKey = this.fcName.name;
|
|
2612
|
+
}
|
|
2613
|
+
if (effectiveKey) {
|
|
2614
|
+
if (Array.isArray(effectiveKey)) {
|
|
2615
|
+
// Composite key: build an object with the specified keys
|
|
2616
|
+
valueToSet = {};
|
|
2617
|
+
effectiveKey.forEach(key => {
|
|
2618
|
+
valueToSet[key] = firstItem[key];
|
|
2619
|
+
});
|
|
2620
|
+
}
|
|
2621
|
+
else {
|
|
2622
|
+
valueToSet = firstItem[effectiveKey];
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
else {
|
|
2626
|
+
// Use whole item if no key resolution possible
|
|
2627
|
+
valueToSet = firstItem;
|
|
2628
|
+
}
|
|
2629
|
+
control.setValue(valueToSet);
|
|
2630
|
+
this.onAutoSelect.emit(firstItem);
|
|
2631
|
+
}
|
|
2632
|
+
});
|
|
2633
|
+
}
|
|
2634
|
+
else if (emptyMsg && this.toastr) {
|
|
2635
|
+
this.toastr.warning(emptyMsg, 'Filtrado');
|
|
2636
|
+
}
|
|
2637
|
+
});
|
|
2638
|
+
}
|
|
2639
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AutoSelectFirstDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2640
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: AutoSelectFirstDirective, isStandalone: true, selector: "[jvsAutoSelectFirst]", inputs: { options: { classPropertyName: "options", publicName: "jvsAutoSelectFirst", isSignal: true, isRequired: false, transformFunction: null }, jvsIdKey: { classPropertyName: "jvsIdKey", publicName: "jvsIdKey", isSignal: true, isRequired: false, transformFunction: null }, jvsEmptyMsg: { classPropertyName: "jvsEmptyMsg", publicName: "jvsEmptyMsg", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAutoSelect: "onAutoSelect" }, ngImport: i0 });
|
|
2641
|
+
}
|
|
2642
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AutoSelectFirstDirective, decorators: [{
|
|
2643
|
+
type: Directive,
|
|
2644
|
+
args: [{
|
|
2645
|
+
selector: '[jvsAutoSelectFirst]',
|
|
2646
|
+
standalone: true
|
|
2647
|
+
}]
|
|
2648
|
+
}], ctorParameters: () => [] });
|
|
2649
|
+
|
|
2650
|
+
class RelojService {
|
|
2651
|
+
// El offset es la diferencia: ServerTime - LocalTime (performance.now())
|
|
2652
|
+
offset = signal(0);
|
|
2653
|
+
STORAGE_KEY = 'srv_clock_offset';
|
|
2654
|
+
// Signal que cambia cada segundo para forzar la reactividad del reloj
|
|
2655
|
+
ticker = signal(0);
|
|
2656
|
+
// Hora actual calculada basándose en performance.now() para evitar drift y suspensión
|
|
2657
|
+
timestamp = computed(() => {
|
|
2658
|
+
this.ticker(); // Dependencia reactiva para que el computed se ejecute cada segundo
|
|
2659
|
+
// performance.now() es monotónico, Date.now() es manipulable por el usuario
|
|
2660
|
+
// Usamos Date.now() inicialmente pero ajustado por el offset calculado
|
|
2661
|
+
return Date.now() + this.offset();
|
|
2662
|
+
});
|
|
2663
|
+
date = computed(() => new Date(this.timestamp()));
|
|
2664
|
+
dateTime = computed(() => {
|
|
2665
|
+
return format(this.date(), "yyyy-MM-dd'T'HH:mm");
|
|
2666
|
+
});
|
|
2667
|
+
constructor() {
|
|
2668
|
+
this.cargarOffsetInicial();
|
|
2669
|
+
this.escucharCambiosOtrasPestanas();
|
|
2670
|
+
this.iniciarVigilanteWarp();
|
|
2671
|
+
// Iniciar el ticker que mantiene el reloj vivo
|
|
2672
|
+
setInterval(() => {
|
|
2673
|
+
this.ticker.update(n => n + 1);
|
|
2674
|
+
}, 1000);
|
|
2675
|
+
}
|
|
2676
|
+
/**
|
|
2677
|
+
* Sincroniza el reloj interno con una hora oficial del servidor.
|
|
2678
|
+
* Calculamos el offset respecto al tiempo local actual.
|
|
2679
|
+
*/
|
|
2680
|
+
sincronizar(serverTime) {
|
|
2681
|
+
const srvTime = new Date(serverTime).getTime();
|
|
2682
|
+
const lclTime = Date.now();
|
|
2683
|
+
const nuevoOffset = srvTime - lclTime;
|
|
2684
|
+
this.offset.set(nuevoOffset);
|
|
2685
|
+
localStorage.setItem(this.STORAGE_KEY, nuevoOffset.toString());
|
|
2686
|
+
this.estaSincronizado.set(true);
|
|
2687
|
+
}
|
|
2688
|
+
/**
|
|
2689
|
+
* Fuerza que la próxima petición HTTP pida la hora al servidor.
|
|
2690
|
+
* Útil tras reconexiones de socket o detecciones de warp.
|
|
2691
|
+
*/
|
|
2692
|
+
forzarSincronizacion() {
|
|
2693
|
+
this.estaSincronizado.set(false);
|
|
2694
|
+
}
|
|
2695
|
+
estaSincronizado = signal(false);
|
|
2696
|
+
get sincronizado() { return this.estaSincronizado(); }
|
|
2697
|
+
cargarOffsetInicial() {
|
|
2698
|
+
const guardado = localStorage.getItem(this.STORAGE_KEY);
|
|
2699
|
+
if (guardado) {
|
|
2700
|
+
this.offset.set(parseInt(guardado, 10));
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
escucharCambiosOtrasPestanas() {
|
|
2704
|
+
window.addEventListener('storage', (event) => {
|
|
2705
|
+
if (event.key === this.STORAGE_KEY && event.newValue) {
|
|
2706
|
+
this.offset.set(parseInt(event.newValue, 10));
|
|
2707
|
+
}
|
|
2708
|
+
});
|
|
2709
|
+
}
|
|
2710
|
+
/**
|
|
2711
|
+
* Monitoriza saltos bruscos en el tiempo (suspensión o cambio manual de hora).
|
|
2712
|
+
* Si detectamos un "warp", podríamos pedir una sincronización forzada.
|
|
2713
|
+
*/
|
|
2714
|
+
iniciarVigilanteWarp() {
|
|
2715
|
+
let lastPerformance = performance.now();
|
|
2716
|
+
let lastDate = Date.now();
|
|
2717
|
+
setInterval(() => {
|
|
2718
|
+
const currentPerformance = performance.now();
|
|
2719
|
+
const currentDate = Date.now();
|
|
2720
|
+
const perfDelta = currentPerformance - lastPerformance;
|
|
2721
|
+
const dateDelta = currentDate - lastDate;
|
|
2722
|
+
// Si la diferencia entre deltas es mayor a 2s (ajustable), hubo un warp
|
|
2723
|
+
if (Math.abs(perfDelta - dateDelta) > 2000) {
|
|
2724
|
+
console.warn('[RelojService] Salto temporal detectado (Warp). Se recomienda sincronizar.');
|
|
2725
|
+
this.forzarSincronizacion();
|
|
2726
|
+
}
|
|
2727
|
+
lastPerformance = currentPerformance;
|
|
2728
|
+
lastDate = currentDate;
|
|
2729
|
+
}, 5000);
|
|
2730
|
+
}
|
|
2731
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: RelojService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2732
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: RelojService, providedIn: 'root' });
|
|
2733
|
+
}
|
|
2734
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: RelojService, decorators: [{
|
|
2735
|
+
type: Injectable,
|
|
2736
|
+
args: [{
|
|
2737
|
+
providedIn: 'root'
|
|
2738
|
+
}]
|
|
2739
|
+
}], ctorParameters: () => [] });
|
|
2740
|
+
|
|
2741
|
+
/*
|
|
2742
|
+
* Public API Surface of utils services
|
|
2743
|
+
*/
|
|
2744
|
+
|
|
1796
2745
|
/*
|
|
1797
2746
|
* Public API Surface of utils
|
|
1798
2747
|
*/
|
|
1799
|
-
// export * from './functions/common.function';
|
|
1800
|
-
// export * from './lib/utils.component';
|
|
1801
|
-
// export * from './lib/utils.service';
|
|
1802
2748
|
|
|
1803
2749
|
/**
|
|
1804
2750
|
* Generated bundle index. Do not edit.
|
|
1805
2751
|
*/
|
|
1806
2752
|
|
|
1807
|
-
export { DataEnListaPipe, DataModel, DateDiffStringPipe, FiltroPipe, FormControlIsRequiredPipe, JsonParsePipe, NoSanitizePipe, TipoValorFuncionPipe, ZeroFillPipe, b64Decode, b64Encode, buscarPorCampo, changeSelect, changeSelectApi, changeSelectData, changeSelectDataApi, changeSelectReformateado, convertirBytes, dataEnLista, dateDiffString, deepClone, deepMerge, delLocalStorage, desencriptar, downLoadFileStream, eliminarColumnaPorIndex, eliminarDuplicados, eliminarElementos, encriptar, esNumero, establecerQuitarRequired, extraerDominio, formControlIsRequired, formatearFecha, formatearFechaCadena, formatearFechaFormato, generateRandomString, getBrowserName, getCambiarPwd, getDataArchivoFromPath, getFormValidationErrors, getLocalStorage, getUniqueValues, getUniqueValuesByProperty, groupBy, inicializarVariablesSessionStorage, isEmail, jwtToken, jwtTokenData, jwtTokenExpiracion, jwtTokenExpiracionFaltante, localStorageKeys, markAsTouchedWithoutEmitEvent, maskEmail, mensajeAlerta, mensajeConfirmacion, mensajeTimer, mensajeToast, mensajesDeError, mensajesErrorFormControl, mostrarValorEnBusqueda, nestGroupsBy, numberToWords, objectPropertiesBoolean, objectPropertiesToType, obtenerHostDesdeUrl, obtenerMimeType, obtenerUltimoOrden, ordenarArray, ordenarPorPropiedad, ordenarPorPropiedades, roundToDecimal, sanitizarNombreArchivo, seleccionarTextoInput, setCambiarPwd, setControlDesdeLista, setJwtTokenData, setLocalStorage, sumarObjetos, sumarPropiedades, tipoValorFuncion, toFormData, transformarFechasPorNombreDeCampo, verificarRUC, zeroFill };
|
|
2753
|
+
export { AutoSelectFirstDirective, AutocompleteMatchValidatorDirective, DataEnListaPipe, DataModel, DateDiffStringPipe, FiltroPipe, FormControlIsRequiredPipe, JsonParsePipe, JvsAutocompleteDirective, JvsDisplayWithPipe, JvsPopoverDirective, JvsPopoverListenerDirective, JvsPopoverPanelComponent, JvsPopoverService, NoSanitizePipe, RelojService, TipoValorFuncionPipe, ZeroFillPipe, b64Decode, b64Encode, buscarPorCampo, changeSelect, changeSelectApi, changeSelectData, changeSelectDataApi, changeSelectReformateado, convertirBytes, dataEnLista, dateDiffString, decodeBase64Object, decodeBase64String, decodeBase64ToBlob, deepClone, deepMerge, delLocalStorage, desencriptar, devError, devGroup, devGroupEnd, devLog, devTable, devTime, devTimeEnd, devWarn, downLoadFileStream, eliminarColumnaPorIndex, eliminarDuplicados, eliminarElementos, encodeBase64File, encodeBase64Object, encodeBase64String, encriptar, esNumero, esPromise, establecerQuitarRequired, extraerDominio, filtrarDatosLocal, formControlIsRequired, formatearFecha, formatearFechaCadena, formatearFechaFormato, generateRandomString, getBrowserName, getCambiarPwd, getDataArchivoFromPath, getFormValidationErrors, getLocalStorage, getUniqueValues, getUniqueValuesByProperty, getValueByPath, groupBy, inicializarVariablesSessionStorage, isEmail, isProduction, jwtToken, jwtTokenData, jwtTokenExpiracion, jwtTokenExpiracionFaltante, localStorageKeys, markAsTouchedWithoutEmitEvent, maskEmail, mensajeAlerta, mensajeConfirmacion, mensajeTimer, mensajeToast, mensajesDeError, mensajesErrorFormControl, mostrarValorEnBusqueda, nestGroupsBy, numberToWords, objectPropertiesBoolean, objectPropertiesToType, obtenerHostDesdeUrl, obtenerMimeType, obtenerUltimoOrden, ordenarArray, ordenarPorPropiedad, ordenarPorPropiedades, roundToDecimal, sanitizarNombreArchivo, seleccionarTextoInput, setCambiarPwd, setControlDesdeLista, setJwtTokenData, setLocalStorage, setProductionMode, sumarObjetos, sumarPropiedades, tipoValorFuncion, toFormData, transformarFechasPorNombreDeCampo, verificarRUC, zeroFill };
|
|
1808
2754
|
//# sourceMappingURL=jvsoft-utils.mjs.map
|