@jvsoft/utils 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/ng-package.json +7 -0
  3. package/package.json +10 -24
  4. package/src/classes/data-model.ts +150 -0
  5. package/src/functions/base64.ts +8 -0
  6. package/src/functions/browser.ts +20 -0
  7. package/src/functions/crypto-js.ts +29 -0
  8. package/src/functions/date.ts +23 -0
  9. package/src/functions/email.ts +17 -0
  10. package/src/functions/file.ts +138 -0
  11. package/src/functions/forms.ts +145 -0
  12. package/src/functions/http-client.ts +110 -0
  13. package/src/functions/index.ts +1 -0
  14. package/src/functions/local-storage.ts +102 -0
  15. package/src/functions/mat-form-controls/autocomplete.ts +275 -0
  16. package/src/functions/mat-form-controls/index.ts +6 -0
  17. package/src/functions/ng-package.json +5 -0
  18. package/src/functions/number.ts +3 -0
  19. package/src/functions/object-transformation.ts +37 -0
  20. package/src/functions/objects-arrays.ts +243 -0
  21. package/src/functions/public-api.ts +19 -0
  22. package/src/functions/string.ts +9 -0
  23. package/src/functions/sweetalert.ts +95 -0
  24. package/src/functions/utiles.ts +20 -0
  25. package/{interfaces/datos.d.ts → src/interfaces/datos.ts} +2 -1
  26. package/src/interfaces/index.ts +1 -0
  27. package/src/interfaces/ng-package.json +5 -0
  28. package/src/interfaces/otros.ts +0 -0
  29. package/src/interfaces/public-api.ts +3 -0
  30. package/src/interfaces/routes.ts +42 -0
  31. package/src/pipes/data-en-lista.pipe.ts +40 -0
  32. package/src/pipes/date-diff-string.pipe.ts +117 -0
  33. package/src/pipes/filtro.pipe.ts +64 -0
  34. package/src/pipes/form-control-is-required.pipe.ts +17 -0
  35. package/src/pipes/index.ts +1 -0
  36. package/src/pipes/json-parse.pipe.ts +18 -0
  37. package/src/pipes/ng-package.json +5 -0
  38. package/src/pipes/no-sanitize.pipe.ts +12 -0
  39. package/src/pipes/public-api.ts +10 -0
  40. package/src/pipes/tipo-valor-funcion.pipe.ts +23 -0
  41. package/src/pipes/zero-fill.pipe.ts +19 -0
  42. package/src/public-api.ts +12 -0
  43. package/tsconfig.lib.json +17 -0
  44. package/tsconfig.lib.prod.json +11 -0
  45. package/tsconfig.spec.json +15 -0
  46. package/classes/data-model.d.ts +0 -25
  47. package/fesm2022/jvsoft-utils-src-functions.mjs +0 -1109
  48. package/fesm2022/jvsoft-utils-src-functions.mjs.map +0 -1
  49. package/fesm2022/jvsoft-utils-src-interfaces.mjs +0 -6
  50. package/fesm2022/jvsoft-utils-src-interfaces.mjs.map +0 -1
  51. package/fesm2022/jvsoft-utils-src-pipes.mjs +0 -290
  52. package/fesm2022/jvsoft-utils-src-pipes.mjs.map +0 -1
  53. package/fesm2022/jvsoft-utils.mjs +0 -1526
  54. package/fesm2022/jvsoft-utils.mjs.map +0 -1
  55. package/functions/base64.d.ts +0 -2
  56. package/functions/browser.d.ts +0 -1
  57. package/functions/crypto-js.d.ts +0 -2
  58. package/functions/date.d.ts +0 -3
  59. package/functions/email.d.ts +0 -2
  60. package/functions/file.d.ts +0 -10
  61. package/functions/forms.d.ts +0 -10
  62. package/functions/http-client.d.ts +0 -2
  63. package/functions/index.d.ts +0 -1
  64. package/functions/local-storage.d.ts +0 -29
  65. package/functions/mat-form-controls/autocomplete.d.ts +0 -21
  66. package/functions/mat-form-controls/index.d.ts +0 -2
  67. package/functions/number.d.ts +0 -1
  68. package/functions/object-transformation.d.ts +0 -2
  69. package/functions/objects-arrays.d.ts +0 -37
  70. package/functions/public-api.d.ts +0 -16
  71. package/functions/string.d.ts +0 -1
  72. package/functions/sweetalert.d.ts +0 -5
  73. package/functions/utiles.d.ts +0 -1
  74. package/index.d.ts +0 -5
  75. package/interfaces/index.d.ts +0 -1
  76. package/interfaces/public-api.d.ts +0 -1
  77. package/pipes/data-en-lista.pipe.d.ts +0 -8
  78. package/pipes/date-diff-string.pipe.d.ts +0 -17
  79. package/pipes/filtro.pipe.d.ts +0 -18
  80. package/pipes/form-control-is-required.pipe.d.ts +0 -9
  81. package/pipes/index.d.ts +0 -1
  82. package/pipes/json-parse.pipe.d.ts +0 -7
  83. package/pipes/no-sanitize.pipe.d.ts +0 -10
  84. package/pipes/public-api.d.ts +0 -8
  85. package/pipes/tipo-valor-funcion.pipe.d.ts +0 -9
  86. package/pipes/zero-fill.pipe.d.ts +0 -8
  87. package/public-api.d.ts +0 -4
  88. package/src/functions/base64.d.ts +0 -2
  89. package/src/functions/browser.d.ts +0 -1
  90. package/src/functions/crypto-js.d.ts +0 -2
  91. package/src/functions/date.d.ts +0 -3
  92. package/src/functions/email.d.ts +0 -2
  93. package/src/functions/file.d.ts +0 -10
  94. package/src/functions/forms.d.ts +0 -10
  95. package/src/functions/http-client.d.ts +0 -2
  96. package/src/functions/index.d.ts +0 -5
  97. package/src/functions/local-storage.d.ts +0 -29
  98. package/src/functions/mat-form-controls/autocomplete.d.ts +0 -21
  99. package/src/functions/mat-form-controls/index.d.ts +0 -2
  100. package/src/functions/number.d.ts +0 -1
  101. package/src/functions/object-transformation.d.ts +0 -2
  102. package/src/functions/objects-arrays.d.ts +0 -37
  103. package/src/functions/public-api.d.ts +0 -16
  104. package/src/functions/string.d.ts +0 -1
  105. package/src/functions/sweetalert.d.ts +0 -5
  106. package/src/functions/utiles.d.ts +0 -1
  107. package/src/interfaces/datos.d.ts +0 -4
  108. package/src/interfaces/index.d.ts +0 -5
  109. package/src/interfaces/public-api.d.ts +0 -1
  110. package/src/pipes/data-en-lista.pipe.d.ts +0 -8
  111. package/src/pipes/date-diff-string.pipe.d.ts +0 -17
  112. package/src/pipes/filtro.pipe.d.ts +0 -18
  113. package/src/pipes/form-control-is-required.pipe.d.ts +0 -9
  114. package/src/pipes/index.d.ts +0 -5
  115. package/src/pipes/json-parse.pipe.d.ts +0 -7
  116. package/src/pipes/no-sanitize.pipe.d.ts +0 -10
  117. package/src/pipes/public-api.d.ts +0 -8
  118. package/src/pipes/tipo-valor-funcion.pipe.d.ts +0 -9
  119. package/src/pipes/zero-fill.pipe.d.ts +0 -8
@@ -0,0 +1,243 @@
1
+ export function deepMerge(source: any, target: any): any {
2
+ // Crea un clon profundo sin usar JSON.parse(JSON.stringify)
3
+ let cloneSource = deepClone(source);
4
+
5
+ if (typeof target !== 'object' || target === null) {
6
+ return target;
7
+ }
8
+
9
+ if (typeof cloneSource !== 'object' || cloneSource === null) {
10
+ cloneSource = Array.isArray(target) ? [] : {};
11
+ }
12
+
13
+ for (const key of Object.keys(target)) {
14
+ const targetValue = target[key];
15
+ const sourceValue = cloneSource[key];
16
+
17
+ if (typeof targetValue === 'object' && targetValue !== null && !Array.isArray(targetValue)) {
18
+ cloneSource[key] = deepMerge(sourceValue, targetValue);
19
+ } else {
20
+ cloneSource[key] = targetValue;
21
+ }
22
+ }
23
+ return cloneSource; // Retorna el clon y no modifica el original
24
+ }
25
+
26
+ // Función de clonación profunda que maneja funciones, fechas y otros tipos especiales
27
+ export function deepClone(obj: any): any {
28
+ if (obj === null || typeof obj !== 'object') {
29
+ return obj; // Devuelve el valor si no es un objeto
30
+ }
31
+
32
+ // Manejar instancias de Date
33
+ if (obj instanceof Date) {
34
+ return new Date(obj.getTime());
35
+ }
36
+
37
+ // Manejar funciones devolviendo una copia directa
38
+ if (typeof obj === 'function') {
39
+ return obj.bind({}); // Devuelve una copia de la función enlazada a un contexto vacío
40
+ }
41
+
42
+ // Crear un nuevo objeto o array
43
+ const clonedObj: Record<string, any> = Array.isArray(obj) ? [] : {};
44
+
45
+ // Clonar recursivamente las propiedades del objeto
46
+ for (const key in obj) {
47
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
48
+ clonedObj[key] = deepClone(obj[key]);
49
+ }
50
+ }
51
+
52
+ return clonedObj;
53
+ }
54
+
55
+ /**
56
+ * Busca un elemento en un array o jerarquía de objetos según un campo y valor especificado.
57
+ *
58
+ * @returns El elemento encontrado o undefined si no existe.
59
+ */
60
+ export function buscarPorCampo<T>(datosFn: {
61
+ items: T[];
62
+ campo: keyof T;
63
+ valor: any;
64
+ campoHijo?: string; // Campo opcional para búsqueda recursiva
65
+ }): T | undefined {
66
+ for (const item of datosFn.items) {
67
+ // Verifica si el campo coincide con el valor
68
+ if (item[datosFn.campo] === datosFn.valor) {
69
+ return item;
70
+ }
71
+
72
+ // Verifica si hay un campo hijo y si es un array
73
+ if (datosFn.campoHijo && item[datosFn.campoHijo as keyof T] && Array.isArray(item[datosFn.campoHijo as keyof T])) {
74
+ // Realiza la búsqueda recursiva en el campo hijo
75
+ const encontrado = buscarPorCampo({
76
+ items: item[datosFn.campoHijo as keyof T] as T[], // Asegura el tipo correcto
77
+ campo: datosFn.campo,
78
+ valor: datosFn.valor,
79
+ campoHijo: datosFn.campoHijo,
80
+ });
81
+
82
+ // Si se encuentra el valor en el campo hijo, retorna el resultado
83
+ if (encontrado) {
84
+ return encontrado;
85
+ }
86
+ }
87
+ }
88
+
89
+ // Si no se encuentra nada, retorna undefined
90
+ return undefined;
91
+ }
92
+
93
+ export function sumarPropiedades(item: Record<string, any>, campos: string[]) {
94
+ const datosSumar = campos.map(campo => (item[campo] * 1));
95
+ return datosSumar.reduce((a, b) => a + b, 0);
96
+ }
97
+
98
+ export function esNumero(value: any): boolean {
99
+ return !isNaN(Number(value));
100
+ }
101
+
102
+ export function sumarObjetos(arrayObjetos: any[], campos: string[]): Record<string, number> {
103
+ return arrayObjetos.reduce((accumulator: Record<string, number>, item: any) => {
104
+ campos.forEach(campo => {
105
+ const valor = Number(item[campo]);
106
+ if (!isNaN(valor)) {
107
+ accumulator[campo] = (accumulator[campo] ?? 0) + valor;
108
+ }
109
+ });
110
+ return accumulator;
111
+ }, {});
112
+ }
113
+
114
+ export function getUniqueValues(array: any[]) {
115
+ return array.filter((currentValue, index, arr) => (
116
+ arr.indexOf(currentValue) === index
117
+ ));
118
+ }
119
+
120
+ export function getUniqueValuesByProperty<T>(objetos: T[], campo: string): T[] {
121
+ const objetosUnicos: {[key: string]: T} = {};
122
+
123
+ objetos.forEach(objeto => {
124
+ // Verificar si el objeto tiene el campo especificado
125
+ // @ts-ignore
126
+ if (objeto.hasOwnProperty(campo)) {
127
+ // @ts-ignore
128
+ const valorCampo = objeto[campo];
129
+
130
+ // Utilizar el valor del campo como clave en un objeto para asegurar que no haya duplicados
131
+ objetosUnicos[valorCampo] = objeto;
132
+ }
133
+ });
134
+
135
+ // Convertir el objeto de claves únicas de vuelta a una lista de objetos
136
+ return Object.values(objetosUnicos);
137
+ }
138
+
139
+
140
+ export function ordenarArray(array: any[], numeros = false, sentido: 'ASC' | 'DESC' = 'ASC'): any[] {
141
+ if (numeros) {
142
+ if (sentido != 'ASC') {
143
+ return array.sort((a: any, b: any) => b - a);
144
+ }
145
+ return array.sort((a: any, b: any) => a - b);
146
+ }
147
+ return array.sort((a, b) => (a > b) ? 1:((b > a) ? -1:0));
148
+
149
+ }
150
+
151
+ export function ordenarPorPropiedad(objData: any, propiedad: string, /**@deprecated*/ numeros = false) {
152
+ return ordenarPorPropiedades(objData, {propiedades: [propiedad], direcciones:['asc']});
153
+ }
154
+
155
+ export function ordenarPorPropiedades<T>(arr: T[], options: {
156
+ propiedades: (keyof T)[],
157
+ direcciones?: ('asc' | 'desc' | '')[],
158
+ }): T[] {
159
+ const {propiedades, direcciones = []} = options;
160
+ const orden = direcciones.map(d => d === 'desc' ? -1:1);
161
+
162
+ return [...arr].sort((a, b) => {
163
+ return propiedades.reduce((acc, propiedad, index) => {
164
+ if (acc !== 0) return acc; // Si ya hay diferencia, no seguir comparando
165
+
166
+ const aValue = a[propiedad];
167
+ const bValue = b[propiedad];
168
+
169
+ if (typeof aValue === 'string' && typeof bValue === 'string') {
170
+ return aValue.localeCompare(bValue) * orden[index]; // 🔹 Comparación alfabética
171
+ }
172
+ if (typeof aValue === 'number' && typeof bValue === 'number') {
173
+ return (aValue - bValue) * orden[index]; // 🔹 Comparación numérica
174
+ }
175
+
176
+ return 0; // En caso de valores no comparables
177
+ }, 0);
178
+ });
179
+ }
180
+
181
+ export function groupBy<T extends Record<string, any>, K extends keyof T>(
182
+ array: T[],
183
+ key: K | ((obj: T) => string)
184
+ ): Record<string, T[]> {
185
+ const keyFn = key instanceof Function ? key:(obj: T) => obj[key];
186
+ return array.reduce((objectsByKeyValue, obj) => {
187
+ const value = keyFn(obj);
188
+ objectsByKeyValue[value] = (objectsByKeyValue[value] || []).concat(obj);
189
+ return objectsByKeyValue;
190
+ }, {} as Record<string, T[]>);
191
+ }
192
+
193
+ export function nestGroupsBy(arr: any, properties: any) {
194
+ const fnGroupBy = (conversions: any, property2: any) => {
195
+ return conversions.reduce((acc: any, obj: any) => {
196
+ const key = obj[property2];
197
+ if (!acc[key]) {
198
+ acc[key] = [];
199
+ }
200
+ acc[key].push(obj);
201
+ return acc;
202
+ }, {});
203
+ };
204
+ properties = Array.from(properties);
205
+ if (properties.length === 1) {
206
+ return fnGroupBy(arr, properties[0]);
207
+ }
208
+ const property = properties.shift();
209
+ const grouped = fnGroupBy(arr, property);
210
+ Object.keys(grouped).forEach(key => {
211
+ grouped[key] = nestGroupsBy(grouped[key], Array.from(properties));
212
+ });
213
+ return grouped;
214
+ }
215
+
216
+
217
+ /**
218
+ * Obtiene un valor de un objeto usando una ruta de propiedad anidada.
219
+ *
220
+ * @param obj - Objeto de entrada.
221
+ * @param path - Ruta en formato punto (ej: "cliente.orden").
222
+ * @returns El valor encontrado o undefined si no existe.
223
+ */
224
+ function getValueByPath(obj: any, path: string): any {
225
+ return path.split('.').reduce((acc, key) => acc?.[key], obj);
226
+ }
227
+
228
+ /**
229
+ * Retorna el valor máximo del campo especificado (incluso anidado) en un arreglo de objetos.
230
+ *
231
+ * @param data - Lista de objetos a procesar.
232
+ * @param campo - Nombre del campo a evaluar, puede ser anidado (ej. "campo.orden").
233
+ * @param incrementar - Si es true, retorna el valor máximo + 1. Por defecto es true.
234
+ * @returns El valor máximo encontrado, posiblemente incrementado.
235
+ */
236
+ export function obtenerUltimoOrden(data: any[], campo: string, incrementar: boolean = true): number {
237
+ const max = data.reduce((mayor, item) => {
238
+ const valor = Number(getValueByPath(item, campo)) || 0;
239
+ return valor > mayor ? valor:mayor;
240
+ }, 0);
241
+
242
+ return incrementar ? max + 1:max;
243
+ }
@@ -0,0 +1,19 @@
1
+ export * from './mat-form-controls';
2
+
3
+ export * from './base64'
4
+ export * from './browser'
5
+ export * from './crypto-js';
6
+ export * from './date';
7
+ export * from './email';
8
+ export * from './file'
9
+ export * from './forms'
10
+ export * from './http-client'
11
+ export * from './local-storage';
12
+ export * from './number';
13
+ export * from './object-transformation'
14
+ export * from './objects-arrays'
15
+ export * from './string'
16
+ export * from './sweetalert'
17
+ export * from './utiles'
18
+
19
+
@@ -0,0 +1,9 @@
1
+ export function generateRandomString(length: number) {
2
+ let result = '';
3
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
4
+ const charactersLength = characters.length;
5
+ for (let i = 0; i < length; i++) {
6
+ result += characters.charAt(Math.floor(Math.random() * charactersLength));
7
+ }
8
+ return result;
9
+ }
@@ -0,0 +1,95 @@
1
+ import swal, {SweetAlertOptions, SweetAlertResult} from 'sweetalert2';
2
+
3
+ export function mensajeAlerta(tipo: 'success' | 'error' | 'info' | 'warning' | 'question', titulo: string, mensaje: string, opciones?: SweetAlertOptions) {
4
+ opciones = {
5
+ ...{
6
+ heightAuto: false,
7
+ title: titulo,
8
+ html: mensaje,
9
+ icon: tipo,
10
+ confirmButtonText: 'Aceptar',
11
+ // customClass: {
12
+ // confirmButton: 'btn btn-lg btn-outline-success mx-2',
13
+ // cancelButton: 'btn btn-lg btn-outline-dark mx-2'
14
+ // },
15
+ // buttonsStyling: false
16
+ },
17
+ ...opciones
18
+ };
19
+ return swal.fire(opciones);
20
+ }
21
+
22
+ export function mensajeTimer(tipo: 'success' | 'error' | 'info' | 'warning' | 'question', titulo: string, mensaje: string, milisegundos = 3000, showLoading = true, opciones?: SweetAlertOptions) {
23
+ let timerInterval: any;
24
+ opciones = {
25
+ ...{
26
+ heightAuto: false,
27
+ title: titulo,
28
+ html: mensaje + '<br> Se cerrará en <strong> X </strong> segundos.',
29
+ icon: tipo,
30
+ timer: milisegundos,
31
+ showCancelButton: false,
32
+ showConfirmButton: false,
33
+ willOpen: () => {
34
+ if (showLoading) {
35
+ swal.showLoading();
36
+ }
37
+ timerInterval = setInterval(() => {
38
+ const impr = Math.ceil(((swal.getTimerLeft() ?? 1)/ 1000));
39
+ if (swal.getHtmlContainer()) {
40
+ // @ts-ignore
41
+ swal.getHtmlContainer().querySelector('strong').textContent = String(impr);
42
+ }
43
+ }, 100);
44
+ },
45
+ willClose: () => {
46
+ clearInterval(timerInterval);
47
+ }
48
+ },
49
+ ...opciones
50
+ };
51
+ return swal.fire(opciones);
52
+ }
53
+
54
+ // @ts-ignore
55
+ export function mensajeConfirmacion(tipo: 'success' | 'error' | 'info' | 'warning' | 'question', titulo, mensaje, opciones?: SweetAlertOptions): Promise<SweetAlertResult<Awaited<any>>> {
56
+ opciones = {
57
+ ...{
58
+ heightAuto: false,
59
+ title: titulo,
60
+ html: mensaje,
61
+ icon: tipo,
62
+ showCancelButton: true,
63
+ // confirmButtonColor: '#3f51b5',
64
+ // cancelButtonColor: '#ffffff',
65
+ confirmButtonText: 'Confirmar',
66
+ cancelButtonText: 'Cancelar',
67
+ reverseButtons: true,
68
+ // customClass: {
69
+ // confirmButton: 'btn btn-lg btn-outline-success mx-2',
70
+ // cancelButton: 'btn btn-lg btn-outline-dark mx-2'
71
+ // },
72
+ // buttonsStyling: false
73
+ },
74
+ ...opciones
75
+ };
76
+ return swal.fire(opciones);
77
+ }
78
+ export function mensajeToast(tipo: 'success' | 'error' | 'info' | 'warning' | 'question', titulo: string, mensaje: string, opciones?: SweetAlertOptions) {
79
+ opciones = {
80
+ ...{
81
+ heightAuto: false,
82
+ title: titulo,
83
+ html: mensaje,
84
+ icon: tipo,
85
+ confirmButtonText: 'Aceptar',
86
+ toast: true,
87
+ position: 'top-end',
88
+ showConfirmButton: false,
89
+ timer: 3000,
90
+ timerProgressBar: true,
91
+ },
92
+ ...opciones
93
+ };
94
+ return swal.fire(opciones);
95
+ }
@@ -0,0 +1,20 @@
1
+ import {mensajeAlerta} from './sweetalert';
2
+
3
+ export function verificarRUC(ruc: string) {
4
+ const f = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
5
+ const rucArray = ruc.split('');
6
+ const nArray = f.map((item, idx) => {
7
+ return item * parseFloat(rucArray[idx]);
8
+ });
9
+ const suma = nArray.reduce((a, b) => a + b, 0);
10
+ const residuo = suma % 11;
11
+ const residuo2 = 11 - residuo;
12
+ // @residuo=CONVERT(Integer,Right(CONVERT(VarChar,@residuo),1))
13
+ const residuo3 = residuo2.toString().charAt(residuo2.toString().length - 1);
14
+ const ultimoCaracter = ruc.toString().charAt(ruc.toString().length - 1);
15
+ if (residuo3 == ultimoCaracter) {
16
+ return true;
17
+ }
18
+ mensajeAlerta('error', 'Datos No válidos', ' El número de RUC no es válido');
19
+ return false;
20
+ }
@@ -1,4 +1,5 @@
1
- import { BehaviorSubject } from 'rxjs';
1
+ import {BehaviorSubject} from 'rxjs';
2
+
2
3
  export interface DataServidor {
3
4
  [key: string]: BehaviorSubject<any>;
4
5
  }
@@ -0,0 +1 @@
1
+ export * from './public-api'
@@ -0,0 +1,5 @@
1
+ {
2
+ "lib": {
3
+ "entryFile": "public-api.ts"
4
+ }
5
+ }
File without changes
@@ -0,0 +1,3 @@
1
+ export * from './datos';
2
+ // export * from './otros';
3
+
@@ -0,0 +1,42 @@
1
+ import {Route} from '@angular/router';
2
+ import {Type} from '@angular/core';
3
+
4
+ export interface JVSoftRouteData {
5
+ scrollDisabled?: boolean;
6
+ toolbarShadowEnabled?: boolean;
7
+ containerEnabled?: boolean;
8
+
9
+ iMenuId?: number;
10
+ sinReloj?: boolean;
11
+ titulo?: string;
12
+ ignorarDerechos?: boolean,
13
+ derechos?: any;
14
+
15
+ [key: string]: any;
16
+
17
+ // camposFiltro?: CampoFiltro[];
18
+ // parametrosFiltro?: ControlParams[];
19
+ // parametrosFiltro$?: Observable<ControlParams[]>;
20
+ /** Usar junto al guard CanActivate 'activarCondicionDespachoGuard' **/
21
+ activarCondicionDespachoGuardParams?: {
22
+ condicion?(despacho: any): boolean,
23
+ error?: {
24
+ rutaRedireccion?: string,
25
+ mensaje?: string,
26
+ }
27
+ },
28
+
29
+ headerTemplates?: {
30
+ bajo?: Type<any>;
31
+ medio?: Type<any>;
32
+ botonesCentro: any[];
33
+ }
34
+ }
35
+
36
+
37
+ export interface JVSoftRoute extends Route {
38
+ data?: JVSoftRouteData;
39
+ children?: JVSoftRoute[];
40
+ }
41
+
42
+ export type JVSoftRoutes = JVSoftRoute[];
@@ -0,0 +1,40 @@
1
+ import {Pipe, PipeTransform} from '@angular/core';
2
+
3
+ @Pipe({
4
+ name: 'dataEnLista',
5
+ })
6
+ export class DataEnListaPipe implements PipeTransform {
7
+
8
+ transform(coleccion: object[], idBuscar: string | string[], dato: any): any {
9
+ if (coleccion) {
10
+ if (Array.isArray(idBuscar)) {
11
+ return coleccion.find(item => {
12
+ const arrCoincide: any[] = [];
13
+ idBuscar.forEach((campo: string, idx) => {
14
+ // @ts-ignore
15
+ arrCoincide.push((item[campo] == dato[idx]));
16
+ });
17
+ return arrCoincide.every(e => e === true);
18
+ });
19
+ }
20
+ // @ts-ignore
21
+ return coleccion.find(item => item[idBuscar] == dato);
22
+ }
23
+ return null;
24
+ }
25
+
26
+ // opcSelec(coleccion, idBuscar, formControl) {
27
+ // if (coleccion) {
28
+ // if (formControl.value == '') {
29
+ // return {cModuloNombre: '', cModuloPadreNombre: 'Todos', iModuloId: ''};
30
+ // }
31
+ // return coleccion.find(item => item[idBuscar] == formControl.value);
32
+ // }
33
+ // return null;
34
+ // }
35
+
36
+ }
37
+
38
+ export function dataEnLista(coleccion: object[], idBuscar: string | string[], dato: any): any {
39
+ return new DataEnListaPipe().transform(coleccion, idBuscar, dato);
40
+ }
@@ -0,0 +1,117 @@
1
+ import {Pipe, PipeTransform} from '@angular/core';
2
+
3
+ @Pipe({
4
+ name: 'dateDiffString',
5
+ pure: true
6
+ })
7
+ export class DateDiffStringPipe implements PipeTransform {
8
+ transform(startingDate: Date, endingDate: Date): any {
9
+ let startDate = new Date(startingDate);
10
+ // user not pass endingDate then set current date as end date.
11
+ if (!endingDate) {
12
+ endingDate = new Date();
13
+ }
14
+ let endDate = new Date(endingDate);
15
+ // chack start date and end date and base on condication alter date.
16
+ if (startDate > endDate) {
17
+ const swap = startDate;
18
+ startDate = endDate;
19
+ endDate = swap;
20
+ }
21
+
22
+ const disgregado = this.separarMilisegundos(endDate.getTime() - startDate.getTime());
23
+ // console.log(disgregado);
24
+ const formatearATexto = (arrayToFill: string[], campo: any, texto: any, textoPlural = 's') => {
25
+ if (campo > 0) {
26
+ arrayToFill.push( campo + ' ' + texto + (campo > 1 ? textoPlural : '') );
27
+ }
28
+ return arrayToFill;
29
+ };
30
+
31
+ let arrDFinal: any[] = [];
32
+ arrDFinal = formatearATexto(arrDFinal, disgregado.years, 'año');
33
+ arrDFinal = formatearATexto(arrDFinal, disgregado.months, 'mes', 'es');
34
+ arrDFinal = formatearATexto(arrDFinal, disgregado.weeks, 'semana');
35
+ arrDFinal = formatearATexto(arrDFinal, disgregado.days, 'día');
36
+ arrDFinal = formatearATexto(arrDFinal, disgregado.hours, 'hora');
37
+ arrDFinal = formatearATexto(arrDFinal, disgregado.minutes, 'minuto');
38
+ arrDFinal = formatearATexto(arrDFinal, disgregado.seconds, 'segundo');
39
+ if (arrDFinal.length > 3) {
40
+ arrDFinal.splice(3);
41
+ arrDFinal.splice(-1, 0, 'y');
42
+ } else {
43
+ if (arrDFinal.length > 1) {
44
+ arrDFinal.splice(-1, 0, 'y');
45
+ }
46
+ }
47
+ return arrDFinal.join(' ');
48
+ }
49
+
50
+ separarMilisegundos(milisegundos: any): {
51
+ years: number,
52
+ months: number,
53
+ weeks: number,
54
+ days: number,
55
+ hours: number,
56
+ minutes: number,
57
+ seconds: number,
58
+ } {
59
+ const todoEnSegundos = milisegundos / 1000;
60
+ let secsUsed = 0;
61
+ const years = Math.floor(todoEnSegundos / 31536000);
62
+ if (years > 0) {
63
+ secsUsed += (years * 31536000);
64
+ }
65
+ const months = Math.floor((todoEnSegundos - secsUsed) / 2628288);
66
+ if (months > 0) {
67
+ secsUsed += (months * 2628288);
68
+ }
69
+ const weeks = Math.floor((todoEnSegundos - secsUsed) / 604800);
70
+ if (weeks > 0) {
71
+ secsUsed += (weeks * 604800);
72
+ }
73
+ const days = Math.floor((todoEnSegundos - secsUsed) / 86400);
74
+ if (days > 0) {
75
+ secsUsed += (days * 86400);
76
+ }
77
+ const hours = Math.floor((todoEnSegundos - secsUsed) / 3600);
78
+ if (hours > 0) {
79
+ secsUsed += (hours * 3600);
80
+ }
81
+ const minutes = Math.floor((todoEnSegundos - secsUsed) / 60);
82
+ if (minutes > 0) {
83
+ secsUsed += (minutes * 60);
84
+ }
85
+ const seconds = Math.round(todoEnSegundos - secsUsed);
86
+
87
+ return {
88
+ years,
89
+ months,
90
+ weeks,
91
+ days,
92
+ hours,
93
+ minutes,
94
+ seconds,
95
+ };
96
+ }
97
+
98
+ /*
99
+ transform(to: Date, from: Date, seconds = true, strict = false): string {
100
+ if (typeof to == 'string') {
101
+ to = new Date(to);
102
+ }
103
+ if (typeof from == 'string') {
104
+ from = new Date(from);
105
+ }
106
+ console.log(typeof to, typeof from);
107
+ console.log(to);
108
+ console.log(from);
109
+
110
+ return strict ? formatDistanceStrict(from, to, {unit: 'minute', locale: es}) : formatDistance(from, to, {includeSeconds: seconds, locale: es});
111
+ }
112
+ */
113
+ }
114
+
115
+ export function dateDiffString(startingDate: Date, endingDate: Date){
116
+ return new DateDiffStringPipe().transform(startingDate, endingDate);
117
+ }
@@ -0,0 +1,64 @@
1
+ import {Pipe, PipeTransform} from '@angular/core';
2
+
3
+ interface OpcionesBusqueda {
4
+ texto: string;
5
+ longitudMinima?: number;
6
+ campo?: string | string[];
7
+ mostrarObligado?: MostrarObligado;
8
+ }
9
+
10
+ interface MostrarObligado {
11
+ campo: string;
12
+ items: any[];
13
+ }
14
+
15
+ @Pipe({
16
+ name: 'filtro'
17
+ })
18
+ export class FiltroPipe implements PipeTransform {
19
+
20
+ transform(items: any[], opcionesBusqueda: OpcionesBusqueda): any[] {
21
+ if (!items || !Array.isArray(items)) return [];
22
+ if (!opcionesBusqueda.texto || opcionesBusqueda.texto.length < (opcionesBusqueda.longitudMinima ?? 1)) return items;
23
+
24
+ const normalize = (() => {
25
+ const from = 'ÃÀÁÄÂÈÉËÊÌÍÏÎÒÓÖÔÙÚÜÛãàáäâèéëêìíïîòóöôùúüûÑñÇç';
26
+ const to = 'AAAAAEEEEIIIIOOOOUUUUaaaaaeeeeiiiioooouuuunncc';
27
+ const mapping: Record<string, string> = {};
28
+
29
+ for (let i = 0; i < from.length; i++) {
30
+ mapping[from[i]] = to[i];
31
+ }
32
+
33
+ return (str: string): string => {
34
+ return str.split('').map(c => mapping[c] || c).join('');
35
+ };
36
+ })();
37
+
38
+ const textoNormalizado = normalize(opcionesBusqueda.texto.toLowerCase());
39
+
40
+ return items.filter(item => {
41
+ // 🔹 Manejo de `mostrarObligado`
42
+ if (opcionesBusqueda.mostrarObligado) {
43
+ const {campo, items: obligados} = opcionesBusqueda.mostrarObligado;
44
+ if (obligados.includes(item[campo])) return true;
45
+ }
46
+
47
+ // 🔹 Manejo de `campo`
48
+ if (opcionesBusqueda.campo) {
49
+ if (Array.isArray(opcionesBusqueda.campo)) {
50
+ return opcionesBusqueda.campo.some(campo => {
51
+ const valor = item[campo] as string | undefined;
52
+ return valor ? normalize(valor.toLowerCase()).includes(textoNormalizado):false;
53
+ });
54
+ }
55
+ else {
56
+ const valor = item[opcionesBusqueda.campo] as string | undefined;
57
+ return valor ? normalize(valor.toLowerCase()).includes(textoNormalizado):false;
58
+ }
59
+ }
60
+
61
+ return false;
62
+ });
63
+ }
64
+ }