@jvsoft/utils 0.0.10 → 0.0.11
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/CHANGELOG.md +7 -0
- package/ng-package.json +7 -0
- package/package.json +9 -24
- package/src/classes/data-model.ts +150 -0
- package/src/functions/base64.ts +8 -0
- package/src/functions/browser.ts +20 -0
- package/src/functions/crypto-js.ts +29 -0
- package/src/functions/date.ts +23 -0
- package/src/functions/email.ts +17 -0
- package/src/functions/file.ts +138 -0
- package/src/functions/forms.ts +145 -0
- package/src/functions/http-client.ts +110 -0
- package/src/functions/index.ts +1 -0
- package/src/functions/local-storage.ts +102 -0
- package/src/functions/mat-form-controls/autocomplete.ts +275 -0
- package/src/functions/mat-form-controls/index.ts +6 -0
- package/src/functions/ng-package.json +5 -0
- package/src/functions/number.ts +3 -0
- package/src/functions/object-transformation.ts +37 -0
- package/src/functions/objects-arrays.ts +243 -0
- package/src/functions/public-api.ts +19 -0
- package/src/functions/string.ts +9 -0
- package/src/functions/sweetalert.ts +95 -0
- package/src/functions/utiles.ts +20 -0
- package/{interfaces/datos.d.ts → src/interfaces/datos.ts} +2 -1
- package/src/interfaces/index.ts +1 -0
- package/src/interfaces/ng-package.json +5 -0
- package/src/interfaces/otros.ts +0 -0
- package/src/interfaces/public-api.ts +3 -0
- package/src/interfaces/routes.ts +42 -0
- package/src/pipes/data-en-lista.pipe.ts +40 -0
- package/src/pipes/date-diff-string.pipe.ts +117 -0
- package/src/pipes/filtro.pipe.ts +64 -0
- package/src/pipes/form-control-is-required.pipe.ts +17 -0
- package/src/pipes/index.ts +1 -0
- package/src/pipes/json-parse.pipe.ts +18 -0
- package/src/pipes/ng-package.json +5 -0
- package/src/pipes/no-sanitize.pipe.ts +12 -0
- package/src/pipes/public-api.ts +10 -0
- package/src/pipes/tipo-valor-funcion.pipe.ts +23 -0
- package/src/pipes/zero-fill.pipe.ts +19 -0
- package/src/public-api.ts +12 -0
- package/tsconfig.lib.json +17 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +15 -0
- package/classes/data-model.d.ts +0 -25
- package/fesm2022/jvsoft-utils-src-functions.mjs +0 -1109
- package/fesm2022/jvsoft-utils-src-functions.mjs.map +0 -1
- package/fesm2022/jvsoft-utils-src-interfaces.mjs +0 -6
- package/fesm2022/jvsoft-utils-src-interfaces.mjs.map +0 -1
- package/fesm2022/jvsoft-utils-src-pipes.mjs +0 -290
- package/fesm2022/jvsoft-utils-src-pipes.mjs.map +0 -1
- package/fesm2022/jvsoft-utils.mjs +0 -1526
- package/fesm2022/jvsoft-utils.mjs.map +0 -1
- package/functions/base64.d.ts +0 -2
- package/functions/browser.d.ts +0 -1
- package/functions/crypto-js.d.ts +0 -2
- package/functions/date.d.ts +0 -3
- package/functions/email.d.ts +0 -2
- package/functions/file.d.ts +0 -10
- package/functions/forms.d.ts +0 -10
- package/functions/http-client.d.ts +0 -2
- package/functions/index.d.ts +0 -1
- package/functions/local-storage.d.ts +0 -29
- package/functions/mat-form-controls/autocomplete.d.ts +0 -21
- package/functions/mat-form-controls/index.d.ts +0 -2
- package/functions/number.d.ts +0 -1
- package/functions/object-transformation.d.ts +0 -2
- package/functions/objects-arrays.d.ts +0 -37
- package/functions/public-api.d.ts +0 -16
- package/functions/string.d.ts +0 -1
- package/functions/sweetalert.d.ts +0 -5
- package/functions/utiles.d.ts +0 -1
- package/index.d.ts +0 -5
- package/interfaces/index.d.ts +0 -1
- package/interfaces/public-api.d.ts +0 -1
- package/pipes/data-en-lista.pipe.d.ts +0 -8
- package/pipes/date-diff-string.pipe.d.ts +0 -17
- package/pipes/filtro.pipe.d.ts +0 -18
- package/pipes/form-control-is-required.pipe.d.ts +0 -9
- package/pipes/index.d.ts +0 -1
- package/pipes/json-parse.pipe.d.ts +0 -7
- package/pipes/no-sanitize.pipe.d.ts +0 -10
- package/pipes/public-api.d.ts +0 -8
- package/pipes/tipo-valor-funcion.pipe.d.ts +0 -9
- package/pipes/zero-fill.pipe.d.ts +0 -8
- package/public-api.d.ts +0 -4
- 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 -10
- package/src/functions/http-client.d.ts +0 -2
- package/src/functions/index.d.ts +0 -5
- package/src/functions/local-storage.d.ts +0 -29
- package/src/functions/mat-form-controls/autocomplete.d.ts +0 -21
- package/src/functions/mat-form-controls/index.d.ts +0 -2
- package/src/functions/number.d.ts +0 -1
- package/src/functions/object-transformation.d.ts +0 -2
- package/src/functions/objects-arrays.d.ts +0 -37
- package/src/functions/public-api.d.ts +0 -16
- package/src/functions/string.d.ts +0 -1
- 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/index.d.ts +0 -5
- 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/CHANGELOG.md
ADDED
package/ng-package.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jvsoft/utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
4
7
|
"peerDependencies": {
|
|
5
8
|
"@angular/common": ">=16.0.0",
|
|
6
9
|
"@angular/core": ">=16.0.0",
|
|
@@ -19,27 +22,9 @@
|
|
|
19
22
|
"tslib": "^2.3.0"
|
|
20
23
|
},
|
|
21
24
|
"sideEffects": false,
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"default": "./package.json"
|
|
27
|
-
},
|
|
28
|
-
".": {
|
|
29
|
-
"types": "./index.d.ts",
|
|
30
|
-
"default": "./fesm2022/jvsoft-utils.mjs"
|
|
31
|
-
},
|
|
32
|
-
"./src/interfaces": {
|
|
33
|
-
"types": "./src/interfaces/index.d.ts",
|
|
34
|
-
"default": "./fesm2022/jvsoft-utils-src-interfaces.mjs"
|
|
35
|
-
},
|
|
36
|
-
"./src/functions": {
|
|
37
|
-
"types": "./src/functions/index.d.ts",
|
|
38
|
-
"default": "./fesm2022/jvsoft-utils-src-functions.mjs"
|
|
39
|
-
},
|
|
40
|
-
"./src/pipes": {
|
|
41
|
-
"types": "./src/pipes/index.d.ts",
|
|
42
|
-
"default": "./fesm2022/jvsoft-utils-src-pipes.mjs"
|
|
43
|
-
}
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "ng build utils --configuration production",
|
|
27
|
+
"watch": "ng build utils --watch --configuration development",
|
|
28
|
+
"test": "ng test utils"
|
|
44
29
|
}
|
|
45
|
-
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {AbstractControl, FormControl, FormControlOptions, FormGroup, ValidationErrors, ValidatorFn, Validators} from '@angular/forms';
|
|
2
|
+
import {esNumero} from '../functions';
|
|
3
|
+
|
|
4
|
+
export class DataModel {
|
|
5
|
+
public modelosChk: { [key: string]: boolean | any } = {}; // Usar any para valores dinámicos
|
|
6
|
+
|
|
7
|
+
public checkbox: ForCheckboxModel;
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
this.checkbox = new ForCheckboxModel(this);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
generarId(row: any, campoValor: string[] | string, separador = '') {
|
|
14
|
+
if (typeof campoValor == 'string') {
|
|
15
|
+
campoValor = [campoValor];
|
|
16
|
+
}
|
|
17
|
+
return campoValor.map(data => row[data]).join(separador);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Agrega controles al objeto modelosChk
|
|
21
|
+
agregarControles(lista: any[], idLista: string, limpiar = true, campoValor: string[] | string | null = null, campoValorSeparador = '') {
|
|
22
|
+
|
|
23
|
+
if (limpiar) {
|
|
24
|
+
this.modelosChk = {};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const asignarValor = (dat: any, idLista: string, campoValor: string, key?: string) => {
|
|
28
|
+
if (!key) {
|
|
29
|
+
key = dat[idLista] + (campoValor.includes('.') ? '':`.${campoValor}`);
|
|
30
|
+
}
|
|
31
|
+
const mat = campoValor.match(/^([in])[A-Z][a-zA-Z]+/);
|
|
32
|
+
if (mat) {
|
|
33
|
+
this.modelosChk[key] = dat[campoValor] * 1;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.modelosChk[key] = dat[campoValor];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
lista.forEach(dat => {
|
|
42
|
+
if (campoValor === null) {
|
|
43
|
+
// Caso 1: Sin campoValor, se asigna false
|
|
44
|
+
this.modelosChk[dat[idLista]] = false;
|
|
45
|
+
}
|
|
46
|
+
else if (typeof campoValor === 'string') {
|
|
47
|
+
// Caso 2: campoValor es un string
|
|
48
|
+
asignarValor(dat, idLista, campoValor, dat[idLista]);
|
|
49
|
+
}
|
|
50
|
+
else if (campoValorSeparador) {
|
|
51
|
+
const idStr = this.generarId(dat, campoValor, campoValorSeparador);
|
|
52
|
+
// Caso 2: campoValor es un string
|
|
53
|
+
asignarValor(dat, idLista, '.', idStr);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Caso 3: campoValor es un array de strings
|
|
57
|
+
campoValor.forEach(data => asignarValor(dat, idLista, data));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Establece el estado de un índice
|
|
63
|
+
setState(idx: string, state: boolean) {
|
|
64
|
+
this.modelosChk[idx] = state;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Obtiene el estado de un índice
|
|
68
|
+
getState(idx: string): boolean | any {
|
|
69
|
+
return this.modelosChk[idx];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getDataMultiple(idx: string) {
|
|
73
|
+
const camposMod = Object.keys(this.modelosChk).filter(key => key.split('.')[0] == idx);
|
|
74
|
+
const vRet: any = {};
|
|
75
|
+
camposMod.forEach(key => {
|
|
76
|
+
vRet[key.split('.')[1]] = this.modelosChk[key];
|
|
77
|
+
});
|
|
78
|
+
return vRet;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Genera una lista basada en el estado de los índices
|
|
82
|
+
generarLista(tipoRetorno: 'array' | 'object' | null = null, esCampoNumerico = false): string | object | any[] {
|
|
83
|
+
const strLista: string[] = [];
|
|
84
|
+
const objLista: { [key: string]: boolean | any } = {};
|
|
85
|
+
Object.keys(this.modelosChk).forEach(key => {
|
|
86
|
+
if ((esCampoNumerico && esNumero(this.modelosChk[key])) ||
|
|
87
|
+
(this.modelosChk[key])
|
|
88
|
+
) {
|
|
89
|
+
strLista.push(key);
|
|
90
|
+
objLista[key] = this.modelosChk[key];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
if (tipoRetorno === 'array') {
|
|
94
|
+
return strLista;
|
|
95
|
+
}
|
|
96
|
+
if (tipoRetorno === 'object') {
|
|
97
|
+
return objLista;
|
|
98
|
+
}
|
|
99
|
+
return strLista.join(',');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
generarFormGroupFromModelosChk(tipo?: string): FormGroup {
|
|
103
|
+
const formGroupObj: { [key: string]: FormControl } = {};
|
|
104
|
+
let validadores: ValidatorFn | ((control: AbstractControl) => ValidationErrors | null)[] | FormControlOptions | null | undefined = []
|
|
105
|
+
if (tipo == 'number') {
|
|
106
|
+
validadores = [
|
|
107
|
+
Validators.required,
|
|
108
|
+
Validators.min(1)
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
Object.keys(this.modelosChk).forEach(key => {
|
|
112
|
+
formGroupObj[key] = new FormControl(this.modelosChk[key], validadores);
|
|
113
|
+
});
|
|
114
|
+
return new FormGroup(formGroupObj);
|
|
115
|
+
|
|
116
|
+
// return this.formBuilder.group(formGroupObj);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
class ForCheckboxModel {
|
|
121
|
+
private modeloCheck: DataModel;
|
|
122
|
+
|
|
123
|
+
constructor(modeloCheck: DataModel) {
|
|
124
|
+
this.modeloCheck = modeloCheck;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
get cantidadActivos() {
|
|
128
|
+
return Object.values(this.modeloCheck.modelosChk).filter(Boolean).length;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
get existenActivados() {
|
|
132
|
+
return this.cantidadActivos > 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get todosActivos() {
|
|
136
|
+
const total = Object.keys(this.modeloCheck.modelosChk).length;
|
|
137
|
+
const activos = this.cantidadActivos;
|
|
138
|
+
return activos > 0 && total === activos;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
get algunosActivos() {
|
|
142
|
+
const total = Object.keys(this.modeloCheck.modelosChk).length;
|
|
143
|
+
const activos = this.cantidadActivos;
|
|
144
|
+
return activos > 0 && total !== activos;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
establecerTodos(activo: boolean) {
|
|
148
|
+
Object.keys(this.modeloCheck.modelosChk).forEach(idx => this.modeloCheck.modelosChk[idx] = activo);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
export function getBrowserName() {
|
|
3
|
+
const agent = window.navigator.userAgent.toLowerCase();
|
|
4
|
+
switch (true) {
|
|
5
|
+
case agent.indexOf('edge') > -1:
|
|
6
|
+
return 'edge';
|
|
7
|
+
case agent.indexOf('opr') > -1 && !!(<any>window).opr:
|
|
8
|
+
return 'opera';
|
|
9
|
+
case agent.indexOf('chrome') > -1 && !!(<any>window).chrome:
|
|
10
|
+
return 'chrome';
|
|
11
|
+
case agent.indexOf('trident') > -1:
|
|
12
|
+
return 'ie';
|
|
13
|
+
case agent.indexOf('firefox') > -1:
|
|
14
|
+
return 'firefox';
|
|
15
|
+
case agent.indexOf('safari') > -1:
|
|
16
|
+
return 'safari';
|
|
17
|
+
default:
|
|
18
|
+
return 'other';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// import * as CryptoJS from 'crypto-js';
|
|
2
|
+
import CryptoJS from 'crypto-js';
|
|
3
|
+
// var CryptoJS = require("crypto-js");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// Clave secreta (debe ser de 16, 24 o 32 caracteres)
|
|
7
|
+
|
|
8
|
+
const secretKey = CryptoJS.enc.Utf8.parse('JVSoftSecret@20615178350');
|
|
9
|
+
const iv = CryptoJS.enc.Utf8.parse('AnSalHuaJVSoft07'); // Debe ser de 16 bytes
|
|
10
|
+
|
|
11
|
+
// Función para encriptar texto
|
|
12
|
+
export function encriptar(text: string): string {
|
|
13
|
+
const encrypted = CryptoJS.AES.encrypt(text, secretKey, {
|
|
14
|
+
iv: iv,
|
|
15
|
+
mode: CryptoJS.mode.CBC,
|
|
16
|
+
padding: CryptoJS.pad.Pkcs7,
|
|
17
|
+
});
|
|
18
|
+
return encrypted.toString(); // Texto cifrado en Base64
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Función para desencriptar texto
|
|
22
|
+
export function desencriptar(ciphertext: string): string {
|
|
23
|
+
const decrypted = CryptoJS.AES.decrypt(ciphertext, secretKey, {
|
|
24
|
+
iv: iv,
|
|
25
|
+
mode: CryptoJS.mode.CBC,
|
|
26
|
+
padding: CryptoJS.pad.Pkcs7,
|
|
27
|
+
});
|
|
28
|
+
return decrypted.toString(CryptoJS.enc.Utf8);
|
|
29
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {formatDate} from '@angular/common';
|
|
2
|
+
|
|
3
|
+
export function formatearFechaFormato(val: string, format: string = 'dd/MM/yyyy') {
|
|
4
|
+
return val ? formatDate(val, format, 'es-PE'):'';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function formatearFecha(val: string, hora = '00:00:00') {
|
|
8
|
+
if (val) {
|
|
9
|
+
if (val.length <= 10) {
|
|
10
|
+
val = val + ' ' + hora;
|
|
11
|
+
}
|
|
12
|
+
return new Date(val);
|
|
13
|
+
}
|
|
14
|
+
return val;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function formatearFechaCadena(fecha: string): Date {
|
|
18
|
+
const year = parseInt(fecha.substring(0, 4), 10);
|
|
19
|
+
const month = parseInt(fecha.substring(4, 6), 10) - 1;
|
|
20
|
+
const day = parseInt(fecha.substring(6, 8), 10);
|
|
21
|
+
|
|
22
|
+
return new Date(year, month, day);
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function maskEmail(email: string): string {
|
|
2
|
+
const [user, domain] = email.split("@");
|
|
3
|
+
|
|
4
|
+
if (user.length <= 2) {
|
|
5
|
+
return `${user[0]}***@${domain}`; // 🔹 Si el usuario es muy corto, no se oculta nada
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (user.length <= 4) {
|
|
9
|
+
return `${user[0]}***${user.slice(-1)}@${domain}`; // 🔹 Muestra 1 al inicio y 1 al final
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return `${user.slice(0, 2)}***${user.slice(-2)}@${domain}`; // 🔹 Muestra 2 al inicio y 2 al final
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isEmail(email: string): boolean {
|
|
16
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
17
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import {saveAs} from 'file-saver';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const mimeTypes: { [key: string]: string } = {
|
|
5
|
+
// Imágenes
|
|
6
|
+
'jpg': 'image/jpeg',
|
|
7
|
+
'jpeg': 'image/jpeg',
|
|
8
|
+
'png': 'image/png',
|
|
9
|
+
'gif': 'image/gif',
|
|
10
|
+
'webp': 'image/webp',
|
|
11
|
+
'svg': 'image/svg+xml',
|
|
12
|
+
'ico': 'image/x-icon',
|
|
13
|
+
'bmp': 'image/bmp',
|
|
14
|
+
|
|
15
|
+
// Documentos
|
|
16
|
+
'pdf': 'application/pdf',
|
|
17
|
+
'doc': 'application/msword',
|
|
18
|
+
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
19
|
+
'xls': 'application/vnd.ms-excel',
|
|
20
|
+
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
21
|
+
'ppt': 'application/vnd.ms-powerpoint',
|
|
22
|
+
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
23
|
+
'txt': 'text/plain',
|
|
24
|
+
'csv': 'text/csv',
|
|
25
|
+
'json': 'application/json',
|
|
26
|
+
'xml': 'application/xml',
|
|
27
|
+
'html': 'text/html',
|
|
28
|
+
|
|
29
|
+
// Audio
|
|
30
|
+
'mp3': 'audio/mpeg',
|
|
31
|
+
'wav': 'audio/wav',
|
|
32
|
+
'ogg': 'audio/ogg',
|
|
33
|
+
'm4a': 'audio/mp4',
|
|
34
|
+
|
|
35
|
+
// Video
|
|
36
|
+
'mp4': 'video/mp4',
|
|
37
|
+
'avi': 'video/x-msvideo',
|
|
38
|
+
'mov': 'video/quicktime',
|
|
39
|
+
'wmv': 'video/x-ms-wmv',
|
|
40
|
+
'flv': 'video/x-flv',
|
|
41
|
+
'webm': 'video/webm',
|
|
42
|
+
'mkv': 'video/x-matroska',
|
|
43
|
+
|
|
44
|
+
// Archivos comprimidos
|
|
45
|
+
'zip': 'application/zip',
|
|
46
|
+
'rar': 'application/vnd.rar',
|
|
47
|
+
'7z': 'application/x-7z-compressed',
|
|
48
|
+
'tar': 'application/x-tar',
|
|
49
|
+
'gz': 'application/gzip',
|
|
50
|
+
'bz2': 'application/x-bzip2',
|
|
51
|
+
|
|
52
|
+
// Otros formatos
|
|
53
|
+
'js': 'application/javascript',
|
|
54
|
+
'css': 'text/css',
|
|
55
|
+
'ts': 'application/typescript',
|
|
56
|
+
'md': 'text/markdown',
|
|
57
|
+
'exe': 'application/octet-stream',
|
|
58
|
+
'eot': 'application/vnd.ms-fontobject',
|
|
59
|
+
'woff': 'font/woff',
|
|
60
|
+
'woff2': 'font/woff2',
|
|
61
|
+
'ttf': 'font/ttf',
|
|
62
|
+
'otf': 'font/otf',
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export function obtenerMimeType(nombreArchivo: string): string | null {
|
|
66
|
+
const extension = nombreArchivo.split('.').pop()?.toLowerCase();
|
|
67
|
+
return extension ? mimeTypes[extension] || 'application/octet-stream' : null;
|
|
68
|
+
}
|
|
69
|
+
export function sanitizarNombreArchivo(nombre: string, reemplazo: string = '_'): string {
|
|
70
|
+
// 1. Quitar caracteres no válidos para nombres de archivo
|
|
71
|
+
const nombreSanitizado = nombre.replace(/[\/\\:*?"<>|]/g, reemplazo);
|
|
72
|
+
|
|
73
|
+
// 2. Reemplazar espacios múltiples o al inicio/final
|
|
74
|
+
const nombreLimpio = nombreSanitizado.trim().replace(/\s+/g, reemplazo);
|
|
75
|
+
|
|
76
|
+
// 3. Asegurar longitud máxima (opcional, aquí 255 caracteres)
|
|
77
|
+
return nombreLimpio.substring(0, 255);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function getDataArchivoFromPath(value: string, conTimeStamp = false): {
|
|
81
|
+
nombre: string, extension?: string, d?: any, fechaSubida: any
|
|
82
|
+
} {
|
|
83
|
+
const partesPath = value.split('/');
|
|
84
|
+
const nombreCompleto = partesPath[partesPath.length - 1];
|
|
85
|
+
let timeStamp = 1;
|
|
86
|
+
let nombreSinTimeStamp = nombreCompleto;
|
|
87
|
+
const partesNombre: any [] = nombreCompleto.split('-');
|
|
88
|
+
if (partesNombre.length > 1) {
|
|
89
|
+
timeStamp = partesNombre[0] * 1;
|
|
90
|
+
partesNombre.shift();
|
|
91
|
+
nombreSinTimeStamp = partesNombre.join('-');
|
|
92
|
+
}
|
|
93
|
+
if (conTimeStamp) {
|
|
94
|
+
return {
|
|
95
|
+
nombre: nombreCompleto,
|
|
96
|
+
extension: nombreCompleto.split('.').pop(),
|
|
97
|
+
d: timeStamp,
|
|
98
|
+
fechaSubida: timeStamp ? new Date(timeStamp * 1000):'',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
nombre: nombreSinTimeStamp,
|
|
103
|
+
extension: nombreSinTimeStamp.split('.').pop(),
|
|
104
|
+
d: timeStamp,
|
|
105
|
+
fechaSubida: timeStamp ? new Date(timeStamp * 1000):'',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function convertirBytes(valor: number, unidadSalida: string | null = null, incluirUnidad: boolean = true): string | number | null {
|
|
110
|
+
const unidades: string[] = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
111
|
+
const indiceEntrada: number = unidadSalida ? unidades.indexOf(unidadSalida):0;
|
|
112
|
+
|
|
113
|
+
if (indiceEntrada === -1) {
|
|
114
|
+
// Unidad de entrada no válida
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let indiceActual: number = indiceEntrada;
|
|
119
|
+
let resultado: number = valor;
|
|
120
|
+
|
|
121
|
+
let cont = 0;
|
|
122
|
+
|
|
123
|
+
while (cont < 6 && (indiceActual < unidades.length - 1) && (resultado >= 1024)) {
|
|
124
|
+
resultado /= 1024;
|
|
125
|
+
indiceActual++;
|
|
126
|
+
}
|
|
127
|
+
if (incluirUnidad) {
|
|
128
|
+
return `${resultado.toFixed(2)} ${unidades[indiceActual]}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return resultado;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
export function downLoadFileStream(data: any, type: string, nombreArchivo?: string) {
|
|
136
|
+
const blob = new Blob([data], {type});
|
|
137
|
+
saveAs(blob, nombreArchivo);
|
|
138
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {AbstractControl, FormArray, FormControl, FormGroup, ValidationErrors, Validators} from '@angular/forms';
|
|
2
|
+
import {ReactiveFormConfig} from '@rxweb/reactive-form-validators';
|
|
3
|
+
|
|
4
|
+
export function establecerQuitarRequired(formulario: FormGroup, establecer: any[] = [], quitar: any[] = [], camposDisabled: string[] | 'todos' = []) {
|
|
5
|
+
establecer.forEach((control: string) => {
|
|
6
|
+
if (!formulario.get(control)?.hasValidator(Validators.required)) {
|
|
7
|
+
formulario.get(control)?.addValidators([Validators.required]);
|
|
8
|
+
formulario.get(control)?.enable();
|
|
9
|
+
formulario.get(control)?.updateValueAndValidity();
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const deshabilitar = (strControl: string) => {
|
|
13
|
+
if (camposDisabled == 'todos') {
|
|
14
|
+
formulario.get(strControl)?.disable();
|
|
15
|
+
console.log(strControl);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
if (camposDisabled.includes(strControl)) {
|
|
19
|
+
formulario.get(strControl)?.disable();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
quitar.forEach(control => {
|
|
24
|
+
if (formulario.get(control)?.hasValidator(Validators.required)) {
|
|
25
|
+
formulario.get(control)?.removeValidators([Validators.required]);
|
|
26
|
+
formulario.get(control)?.updateValueAndValidity();
|
|
27
|
+
}
|
|
28
|
+
deshabilitar(control);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getFormValidationErrors(form: FormGroup) {
|
|
33
|
+
const result: { control: string; error: string; value: any; }[] = [];
|
|
34
|
+
Object.keys(form.controls).forEach(key => {
|
|
35
|
+
const formProperty = form.get(key);
|
|
36
|
+
if (formProperty instanceof FormGroup) {
|
|
37
|
+
result.push(...getFormValidationErrors(formProperty));
|
|
38
|
+
}
|
|
39
|
+
const controlErrors: ValidationErrors | null | undefined = formProperty?.errors;
|
|
40
|
+
if (controlErrors) {
|
|
41
|
+
Object.keys(controlErrors).forEach(keyError => {
|
|
42
|
+
result.push({
|
|
43
|
+
control: key,
|
|
44
|
+
error: keyError,
|
|
45
|
+
value: controlErrors[keyError]
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function mensajesErrorFormControl(control: AbstractControl | null): string {
|
|
55
|
+
if (!control || !control.errors || !control.touched) return '';
|
|
56
|
+
|
|
57
|
+
ReactiveFormConfig.set({
|
|
58
|
+
// RxwebValidators
|
|
59
|
+
validationMessage: {
|
|
60
|
+
required: 'Es requerido',
|
|
61
|
+
numeric: 'Debe ser numérico valido',
|
|
62
|
+
// minLength: 'minimum length is {{1}}',
|
|
63
|
+
// maxLength: 'allowed max length is {{1}}',
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const errorMessages: Record<string, string> = {
|
|
68
|
+
required: 'Es requerido',
|
|
69
|
+
numeric: 'Debe ser numérico válido',
|
|
70
|
+
min: `Valor mínimo permitido: ${control.errors['min']?.min}`,
|
|
71
|
+
minValue: 'Debe ser positivo',
|
|
72
|
+
minlength: `Mínimo ${control.errors['minlength']?.requiredLength} caracteres.`,
|
|
73
|
+
maxlength: `Caracteres ${control.errors['maxlength']?.actualLength}/${control.errors['maxlength']?.requiredLength}`,
|
|
74
|
+
email: 'No se cumple con el formato de Correo Electrónico',
|
|
75
|
+
isNumeric: 'Debe seleccionar una opción',
|
|
76
|
+
hasNumber: 'Se requiere al menos un número',
|
|
77
|
+
hasCapitalCase: 'Se requiere al menos una mayúscula',
|
|
78
|
+
hasSmallCase: 'Se requiere al menos una minúscula',
|
|
79
|
+
hasSpecialCharacters: 'Se requiere al menos un carácter especial',
|
|
80
|
+
NoPassswordMatch: 'La contraseña no coincide',
|
|
81
|
+
itemSelected: 'Debe seleccionar una opción de la lista',
|
|
82
|
+
inputMask: 'El formato ingresado no es válido',
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Devuelve el primer mensaje de error encontrado
|
|
86
|
+
for (const errorKey of Object.keys(control.errors)) {
|
|
87
|
+
if (errorMessages[errorKey]) {
|
|
88
|
+
return errorMessages[errorKey];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Si el error tiene un mensaje personalizado, usarlo
|
|
93
|
+
return control.errors[Object.keys(control.errors)[0]]?.message || '';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function toFormData<T extends Record<string, any>>(formValue: T): FormData {
|
|
97
|
+
const formData = new FormData();
|
|
98
|
+
|
|
99
|
+
Object.keys(formValue).forEach((key) => {
|
|
100
|
+
const value = formValue[key];
|
|
101
|
+
|
|
102
|
+
if (value === null || value === undefined) {
|
|
103
|
+
return; // Ignorar valores nulos o indefinidos
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
value.forEach((item, index) => {
|
|
108
|
+
if (typeof item === 'object' && item !== null) {
|
|
109
|
+
if ('file' in item) {
|
|
110
|
+
formData.append(`${key}[${index}]`, item.file);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
formData.append(`${key}[${index}]`, JSON.stringify(item));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
formData.append(`${key}[${index}]`, item.toString());
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
else if (typeof value === 'object') {
|
|
122
|
+
// Si es un objeto (pero no un array), convertirlo a JSON
|
|
123
|
+
formData.append(key, JSON.stringify(value));
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Para valores primitivos (string, number, boolean)
|
|
127
|
+
formData.append(key, value.toString());
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return formData;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function markAsTouchedWithoutEmitEvent(control: AbstractControl): void {
|
|
135
|
+
if (control instanceof FormControl) {
|
|
136
|
+
control.markAsTouched({onlySelf: true});
|
|
137
|
+
control.updateValueAndValidity({emitEvent: false});
|
|
138
|
+
}
|
|
139
|
+
else if (control instanceof FormGroup || control instanceof FormArray) {
|
|
140
|
+
Object.values(control.controls).forEach(childControl => {
|
|
141
|
+
markAsTouchedWithoutEmitEvent(childControl);
|
|
142
|
+
});
|
|
143
|
+
control.updateValueAndValidity({emitEvent: false});
|
|
144
|
+
}
|
|
145
|
+
}
|