utn-cli 2.0.41 → 2.0.43
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/commands/backend.js +7 -7
- package/package.json +1 -1
- package/templates/backend/InformacionDelModulo.json +1 -1
- package/templates/backend/rutas/Servicio1.js +18 -1
- package/templates/backend/servicios/InformacionDelModulo.js +2 -2
- package/templates/backend/servicios/Nucleo/Miscelaneas.js +27 -6
- package/templates/backend/servicios/Servicio1.js +29 -0
- package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.css +11 -0
- package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.html +11 -7
- package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts +91 -12
package/commands/backend.js
CHANGED
|
@@ -40,7 +40,7 @@ async function inicializarProyectoBackend() {
|
|
|
40
40
|
|
|
41
41
|
const NOMBRE_DEL_PROYECTO = await askAndReplace('NOMBRE_DEL_PROYECTO', '¿Cuál es el nombre del proyecto?: ', rutaDeInformacionDelModulo, 'NOMBRE_DEL_PROYECTO');
|
|
42
42
|
await askAndReplace('DESCRIPCION_DEL_PROYECTO', '¿Cuál es la descripción del proyecto?: ', rutaDeInformacionDelModulo, 'DESCRIPCION_DEL_PROYECTO');
|
|
43
|
-
await askAndReplace('DETALLE_DEL_PROYECTO', '¿Cuál es detalle del proyecto?: ', rutaDeInformacionDelModulo, 'DETALLE_DEL_PROYECTO');
|
|
43
|
+
await askAndReplace('DETALLE_DEL_PROYECTO', '¿Cuál es el detalle del proyecto?: ', rutaDeInformacionDelModulo, 'DETALLE_DEL_PROYECTO');
|
|
44
44
|
|
|
45
45
|
const NOMBRE_DEL_CANONICO_DEL_PROYECTO = await askAndReplace('NOMBRE_DEL_CANONICO_DEL_PROYECTO', '¿Cuál es el nombre canónico del proyecto?: ', rutaDeInformacionDelModulo, 'NOMBRE_DEL_CANONICO_DEL_PROYECTO', (val) => {
|
|
46
46
|
const oldFileName = path.join(process.cwd(), 'NOMBRE_DEL_CANONICO_DEL_PROYECTO.rest');
|
|
@@ -58,7 +58,7 @@ async function inicializarProyectoBackend() {
|
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
await askAndReplace('TIPO_DE_TARJETA', '¿Cuál es tipo de tarjeta? Posibles valores: Área, Proceso, Servicio: ', rutaDeInformacionDelModulo, 'TIPO_DE_TARJETA');
|
|
61
|
+
await askAndReplace('TIPO_DE_TARJETA', '¿Cuál es el tipo de tarjeta? Posibles valores: Área, Proceso, Servicio: ', rutaDeInformacionDelModulo, 'TIPO_DE_TARJETA');
|
|
62
62
|
await askAndReplace('NOMBRE_DEL_ROL', '¿Cuál es el nombre del rol?: ', rutaDeInformacionDelModulo, 'NOMBRE_DEL_ROL');
|
|
63
63
|
|
|
64
64
|
const NOMBRE_DEL_REPOSITORIO_DE_BASE_DE_DATOS = await askAndReplace('NOMBRE_DEL_REPOSITORIO_DE_BASE_DE_DATOS', '¿Cuál es el nombre del repositorio de base de datos?: ', rutaDeInformacionDelModulo, 'NOMBRE_DEL_REPOSITORIO_DE_BASE_DE_DATOS', (val) => {
|
|
@@ -82,17 +82,17 @@ async function inicializarProyectoBackend() {
|
|
|
82
82
|
await askAndReplace('NOMBRE_DEL_REPOSITORIO_DE_FRONTEND', '¿Cuál es el nombre del repositorio de frontend?: ', rutaDeInformacionDelModulo, 'NOMBRE_DEL_REPOSITORIO_DE_FRONTEND');
|
|
83
83
|
await askAndReplace('NOMBRE_DEL_PERMISO', '¿Cuál es el nombre del permiso?: ', rutaDeInformacionDelModulo, 'NOMBRE_DEL_PERMISO');
|
|
84
84
|
await askAndReplace('DESCRIPCION_DEL_PERMISO', '¿Cuál es la descripción del permiso?: ', rutaDeInformacionDelModulo, 'DESCRIPCION_DEL_PERMISO');
|
|
85
|
-
await askAndReplace('MENU_PADRE', '¿Cuál es nombre canónico del menú padre?: ', rutaDeInformacionDelModulo, 'MENU_PADRE');
|
|
85
|
+
await askAndReplace('MENU_PADRE', '¿Cuál es el nombre canónico del menú padre?: ', rutaDeInformacionDelModulo, 'MENU_PADRE');
|
|
86
86
|
await askAndReplace('COLOR_DEL_MODULO', '¿Cuál es el color del módulo?: ', rutaDeInformacionDelModulo, 'COLOR_DEL_MODULO');
|
|
87
|
-
await askAndReplace('
|
|
87
|
+
await askAndReplace('CORREO_PARA_REPORTES', '¿Cuál es el correo para reportes?: ', rutaDeInformacionDelModulo, 'CORREO_PARA_REPORTES');
|
|
88
88
|
|
|
89
|
-
const nombre_de_desarrollador = await askAndReplace('nombre_de_desarrollador', '¿Cuál es el nombre
|
|
89
|
+
const nombre_de_desarrollador = await askAndReplace('nombre_de_desarrollador', '¿Cuál es el nombre del desarrollador?: ', path.join(process.cwd(), 'package.json'), 'nombre_de_desarrollador', (val) => {
|
|
90
90
|
reemplazarContenidoEnArchivo(path.join(process.cwd(), 'package.json'), 'nombre_de_desarrollador', `Para la Universidad Técnica Nacional por: ${val}`);
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
await askAndReplace('CEDULA_DEL_DESARROLLADOR', '¿Cuál es el número de cédula del desarrollador?: ', rutaDeInformacionDelModulo, 'CEDULA_DEL_DESARROLLADOR');
|
|
94
94
|
|
|
95
|
-
const url_del_grupo = await askAndReplace('url_del_grupo', '¿Cuál es
|
|
95
|
+
const url_del_grupo = await askAndReplace('url_del_grupo', '¿Cuál es la URL del grupo en el Git?: ', path.join(process.cwd(), 'package.json'), 'url_del_grupo', (val) => {
|
|
96
96
|
reemplazarContenidoEnArchivo(path.join(process.cwd(), 'package.json'), 'url_del_grupo', val);
|
|
97
97
|
});
|
|
98
98
|
|
|
@@ -117,7 +117,7 @@ async function inicializarProyectoBackend() {
|
|
|
117
117
|
reemplazarContenidoEnArchivo(rutaDeInformacionDelModulo, 'BACKENDS_QUE_CONSUME_ESTE_MODULO', '');
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
await askAndReplace('VERSION', '¿Cuál es versión del módulo?: ', rutaDeInformacionDelModulo, 'VERSION');
|
|
120
|
+
await askAndReplace('VERSION', '¿Cuál es la versión del módulo?: ', rutaDeInformacionDelModulo, 'VERSION');
|
|
121
121
|
|
|
122
122
|
fs.writeFileSync(rutaDeInformacionDelModuloJson, JSON.stringify(informacionDelModuloJson, null, 2));
|
|
123
123
|
}
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"DESCRIPCION_DEL_PERMISO": "DESCRIPCION_DEL_PERMISO",
|
|
13
13
|
"MENU_PADRE": "MENU_PADRE",
|
|
14
14
|
"COLOR_DEL_MODULO": "COLOR_DEL_MODULO",
|
|
15
|
-
"
|
|
15
|
+
"CORREO_PARA_REPORTES": "CORREO_PARA_REPORTES",
|
|
16
16
|
"nombre_de_desarrollador": "nombre_de_desarrollador",
|
|
17
17
|
"CEDULA_DEL_DESARROLLADOR": "CEDULA_DEL_DESARROLLADOR",
|
|
18
18
|
"url_del_grupo": "url_del_grupo",
|
|
@@ -23,13 +23,30 @@ Router.get('/funcionDeEjemplo', async (solicitud, respuesta, next) => {
|
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
// Router.post('/cargarArchivo/:Etiquetas', async (solicitud, respuesta, next) => {
|
|
27
|
+
// try {
|
|
28
|
+
// if (await Miscelaneo.validarTokenV2(solicitud.headers.authorization) && await Miscelaneo.validarAccesoDelOrigen(solicitud)) {
|
|
29
|
+
// try {
|
|
30
|
+
// return respuesta.json({ body: await Servicio1.cargarArchivo(solicitud, solicitud.params.Etiquetas), error: undefined });
|
|
31
|
+
// } catch (error) {
|
|
32
|
+
// const MensajeDeError = 'No fue posible cargar el archivo';
|
|
33
|
+
// console.error(new ManejadorDeErrores(MensajeDeError, ManejadorDeErrores.obtenerNumeroDeLinea(), true, `Dirección IP: ${solicitud.ip}`));
|
|
34
|
+
// return respuesta.status(500).json({ body: undefined, error: MensajeDeError });
|
|
35
|
+
// }
|
|
36
|
+
// }
|
|
37
|
+
// return respuesta.status(401).json({ body: undefined, error: ManejadorDeErrores.mensajeDeError401() });
|
|
38
|
+
// } catch (error) {
|
|
39
|
+
// next(error);
|
|
40
|
+
// }
|
|
41
|
+
// });
|
|
42
|
+
|
|
26
43
|
// Router.get('/listarArchivosExterno/:Etiquetas', async (solicitud, respuesta, next) => {
|
|
27
44
|
// try {
|
|
28
45
|
// if (await Miscelaneo.validarTokenV2(solicitud.headers.authorization) && await Miscelaneo.validarAccesoDelOrigen(solicitud)) {
|
|
29
46
|
// try {
|
|
30
47
|
// const Datos = { Etiquetas: solicitud.params.Etiquetas };
|
|
31
48
|
// Datos.Token = solicitud.headers.authorization;
|
|
32
|
-
// return respuesta.json({ body: await
|
|
49
|
+
// return respuesta.json({ body: await Servicio1.listarArchivosExterno(Datos), error: undefined });
|
|
33
50
|
// } catch (error) {
|
|
34
51
|
// const MensajeDeError = 'No fue posible obtener los arcvhivos';
|
|
35
52
|
// console.error(new ManejadorDeErrores(MensajeDeError, ManejadorDeErrores.obtenerNumeroDeLinea(), true, `Dirección IP: ${solicitud.ip}`));
|
|
@@ -53,14 +53,14 @@ class InformacionDelModulo {
|
|
|
53
53
|
};
|
|
54
54
|
getUsuariosConAccesoInicial() {
|
|
55
55
|
// UsuariosConAccesoInicial es un arreglo de strings de la forma ['111050570', '111050570']
|
|
56
|
-
// Este arreglo se usa para asignar acceso a este
|
|
56
|
+
// Este arreglo se usa para asignar acceso a este módulo, suelen usarse las cédulas de los encargados del proyecto y el desarrollador
|
|
57
57
|
return ['111050570', '204540859', '602990078', '109840817', '206860639', '155821845336', 'CEDULA_DEL_DESARROLLADOR'];
|
|
58
58
|
};
|
|
59
59
|
getColorDelModulo() {
|
|
60
60
|
return 'COLOR_DEL_MODULO';
|
|
61
61
|
};
|
|
62
62
|
getCorreoParaReportes() {
|
|
63
|
-
return '
|
|
63
|
+
return 'CORREO_PARA_REPORTES';
|
|
64
64
|
};
|
|
65
65
|
getVersion() {
|
|
66
66
|
return 'VERSION';
|
|
@@ -427,8 +427,31 @@ class Miscelaneo {
|
|
|
427
427
|
SELECT COUNT(*) AS Total \
|
|
428
428
|
FROM `SIGU`.`SIGU_DireccionesUsadasPorLosUsuarios` \
|
|
429
429
|
WHERE `Identificador` = ? AND `DireccionUsadaPorElUsuario` = ?", [Identificador, ipUsuario]);
|
|
430
|
+
|
|
431
|
+
// Verificar si la fecha de cambio supera los 2 meses
|
|
432
|
+
const fechaUltimoCambio = await ConexionSigu.query(
|
|
433
|
+
"SELECT LastUpdate \
|
|
434
|
+
FROM `SIGU`.`SIGU_FechaDelUltimoCambioDeClave` \
|
|
435
|
+
WHERE `Identificador` = ?",
|
|
436
|
+
[Identificador]
|
|
437
|
+
);
|
|
438
|
+
let fechaBD = fechaUltimoCambio?.[0]?.[0]?.LastUpdate;
|
|
439
|
+
const fechaUltimo = new Date(fechaBD);
|
|
440
|
+
const fechaActual = new Date();
|
|
441
|
+
const diferenciaMs = fechaActual - fechaUltimo;
|
|
442
|
+
const diasPasados = diferenciaMs / (1000 * 60 * 60 * 24);
|
|
443
|
+
if (!fechaBD || diasPasados >= 60) {
|
|
444
|
+
await ConexionSigu.query(
|
|
445
|
+
"UPDATE`SIGU_Personas` \
|
|
446
|
+
SET`Clave` = '' \
|
|
447
|
+
where`Identificador` = ? ;",
|
|
448
|
+
[Identificador]
|
|
449
|
+
);
|
|
450
|
+
return { RequiereCambioContraseña: true };
|
|
451
|
+
|
|
452
|
+
}
|
|
453
|
+
|
|
430
454
|
if (ipExiste[0][0].Total === 0) {
|
|
431
|
-
console.log("IP nueva detectada para el usuario, iniciando 2FA");
|
|
432
455
|
// GENERAR CODIGO 2FA
|
|
433
456
|
let Codigo2FA = await ConexionSigu.query("SELECT UUID() AS `Dato`");
|
|
434
457
|
Codigo2FA = Codigo2FA[0][0].Dato;
|
|
@@ -449,7 +472,6 @@ class Miscelaneo {
|
|
|
449
472
|
WHERE `Identificador` = ? \
|
|
450
473
|
AND `Principal` = TRUE"
|
|
451
474
|
, [Identificador]);
|
|
452
|
-
|
|
453
475
|
// ENVIAR CORREO
|
|
454
476
|
await envioDeCorreo(
|
|
455
477
|
CorreoElectronico[0][0].CorreoElectronico,
|
|
@@ -460,6 +482,7 @@ class Miscelaneo {
|
|
|
460
482
|
"<p>Si usted no inició este proceso, puede ignorar este mensaje.</p>"
|
|
461
483
|
);
|
|
462
484
|
return { Requiere2FA: true };
|
|
485
|
+
|
|
463
486
|
}
|
|
464
487
|
|
|
465
488
|
// SI LA IP YA EXISTE CONTINUA
|
|
@@ -473,18 +496,16 @@ class Miscelaneo {
|
|
|
473
496
|
LastUser,
|
|
474
497
|
LastUser
|
|
475
498
|
]);
|
|
476
|
-
return { Token, Dominio: ((process.env.ENV || 'local') === 'production' ? '.sigu.utn.ac.cr' : '
|
|
499
|
+
return { Token, Dominio: ((process.env.ENV || 'local') === 'production' ? '.sigu.utn.ac.cr' : '.181.193.85.44.nip.io') };
|
|
477
500
|
|
|
478
501
|
} else {
|
|
479
502
|
console.log("La clave brindada para el usuario", Solicitud.body.Identificacion, "no conincide");
|
|
480
|
-
|
|
481
503
|
const Resultados2 = await ConexionSigu.query("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_ClavesTemporalesDeLasPersonas` WHERE `Identificador` = ? AND `Clave` = ?", [Identificador, Solicitud.body.Clave]);
|
|
482
|
-
|
|
483
504
|
if (Resultados2[0][0]['Total'] > 0) {
|
|
484
505
|
console.log("La clave brindada para el usuario", Solicitud.body.Identificacion, "no conincide, pero coincide la clave temporal");
|
|
485
506
|
await ConexionSigu.query("UPDATE `SIGU`.`SIGU_Personas` SET `Clave` = ?, `LastUpdate` = NOW(4), `LastUser` = ? WHERE `Identificacion` = ?"
|
|
486
507
|
, [await bcrypt.hash(require('crypto').createHash('md5').update(Solicitud.body.Clave).digest("hex"), 10), LastUser, Solicitud.body.Identificacion]);
|
|
487
|
-
|
|
508
|
+
await ConexionSigu.query("REPLACE INTO `SIGU`.`SIGU_FechaDelUltimoCambioDeClave` VALUES (?, NOW(), ?);", [Identificador, LastUser]);
|
|
488
509
|
await ConexionSigu.query("DELETE FROM `SIGU`.`SIGU_ClavesTemporalesDeLasPersonas`WHERE `Identificador` = ?", [Identificador]);
|
|
489
510
|
return await this.Autenticar(Solicitud);
|
|
490
511
|
|
|
@@ -17,6 +17,35 @@ class Servicio1 {
|
|
|
17
17
|
return ejecutarConsulta("SELECT ?", [ParametroDeEjemplo]);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// async cargarArchivo(Solicitud, Etiquetas) {
|
|
21
|
+
// const Partes = Etiquetas.split('--');
|
|
22
|
+
// Etiquetas = Partes.slice(0, -1).join("--");
|
|
23
|
+
// let Resultado = undefined;
|
|
24
|
+
// try {
|
|
25
|
+
// Resultado = await this.obtenerDatosDelUsuario(Solicitud.headers.authorization);
|
|
26
|
+
// } catch (error) {
|
|
27
|
+
// console.error(error);
|
|
28
|
+
// }
|
|
29
|
+
// // Validación del token para el usuario y authorización
|
|
30
|
+
// if (Resultado) {
|
|
31
|
+
// const informacionDelArchivo = await this.almacenarArchivoEnDisco(Solicitud, Resultado['uid']);
|
|
32
|
+
// const Respuesta = await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Adjuntos` (`AdjuntosId`, `Identificador`, `Modulo`, `Seccion`, `Nombre`,\
|
|
33
|
+
// `NombreOriginal`, `Ruta`, `Tipo`, `Tamanio`, `Etiqueta`, `LastUpdate`, `LastUser`)\
|
|
34
|
+
// VALUES (NULL, ?, ?, 'No aplica', ?, ?, ?, ?, ?, 'No aplica', NOW(4), ?)"
|
|
35
|
+
// , [Resultado['uid'], this.NombreCanonicoDelModulo, informacionDelArchivo.nombreDeArchivo, informacionDelArchivo.nombreDeArchivo
|
|
36
|
+
// , informacionDelArchivo.rutaDeArchivo, informacionDelArchivo.tipoDeContenido, informacionDelArchivo.tamanioTotal
|
|
37
|
+
// , Resultado['uid']]);
|
|
38
|
+
// informacionDelArchivo.insertId = Respuesta.insertId;
|
|
39
|
+
// informacionDelArchivo.Etiquetas = Etiquetas;
|
|
40
|
+
// await ejecutarConsulta("INSERT INTO `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
|
|
41
|
+
// VALUES (?, ?, ?, ?, ?, NOW(4), ?)"
|
|
42
|
+
// , [Respuesta.insertId, Resultado.uid, informacionDelArchivo.rutaDeArchivo, informacionDelArchivo.nombreDeArchivo
|
|
43
|
+
// , Etiquetas, Resultado.uid]);
|
|
44
|
+
// return informacionDelArchivo;
|
|
45
|
+
// }
|
|
46
|
+
// return;
|
|
47
|
+
// }
|
|
48
|
+
|
|
20
49
|
// async listar() {
|
|
21
50
|
// return await ejecutarConsulta("SELECT `BeneficioEstudiantilId`, `Nombre`, `Tipo`, `Estado` FROM `vve-bybe`.`BYBE_BeneficiosEstudiantiles`");
|
|
22
51
|
// }
|
package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.css
CHANGED
|
@@ -61,6 +61,17 @@ button:focus {
|
|
|
61
61
|
box-sizing: border-box;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
.zona-archivo.deshabilitado {
|
|
65
|
+
border-color: #bdc3c7;
|
|
66
|
+
background-color: #f8f9fa;
|
|
67
|
+
cursor: not-allowed;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.texto-limite {
|
|
71
|
+
color: #e74c3c;
|
|
72
|
+
font-weight: bold;
|
|
73
|
+
}
|
|
74
|
+
|
|
64
75
|
/* Centrado del mensaje vacío */
|
|
65
76
|
.mensaje-vacio {
|
|
66
77
|
display: flex;
|
package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.html
CHANGED
|
@@ -17,16 +17,20 @@
|
|
|
17
17
|
}
|
|
18
18
|
</div>
|
|
19
19
|
@if(EsEditable) {
|
|
20
|
-
<div class="zona-archivo" (click)="AbrirGestorDeArchivos()" (dragover)="ArrastrarAdentro($event)"
|
|
20
|
+
<div class="zona-archivo" [class.deshabilitado]="ListaArchivos.length >= CantidadMaximaArchivos" (click)="AbrirGestorDeArchivos()" (dragover)="ArrastrarAdentro($event)"
|
|
21
21
|
(dragleave)="ArrastrarAfuera($event)" (drop)="Soltar($event)">
|
|
22
|
-
@if(
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
@if(ListaArchivos.length >= CantidadMaximaArchivos) {
|
|
23
|
+
<p class="texto-limite">Límite de {{CantidadMaximaArchivos}} archivos alcanzado</p>
|
|
24
|
+
} @else {
|
|
25
|
+
@if(!Archivo){
|
|
26
|
+
<p class="texto">Arrastra y suelta un archivo aquí o <span class="texto-clic">haz clic para subir</span></p>
|
|
27
|
+
}
|
|
28
|
+
@else{
|
|
29
|
+
<p>Archivo seleccionado: {{ Archivo.name }}</p>
|
|
30
|
+
}
|
|
27
31
|
}
|
|
28
32
|
<!-- Input oculto para seleccionar archivos manualmente -->
|
|
29
|
-
<input type="file" #
|
|
33
|
+
<input type="file" #EntradaDeArchivo hidden (change)="ArchivoSeleccionado($event)" [accept]="FormatosPermitidos.join(',')">
|
|
30
34
|
</div>
|
|
31
35
|
} @else {
|
|
32
36
|
@if(ListaArchivos.length === 0) {
|
package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Component, ElementRef, inject, OnInit, ViewChild } from '@angular/core';
|
|
1
|
+
import { Component, ElementRef, inject, OnInit, ViewChild, Output, EventEmitter } from '@angular/core';
|
|
2
2
|
import { MatButtonModule } from '@angular/material/button';
|
|
3
3
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
|
4
4
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
5
5
|
import { MatIconModule } from '@angular/material/icon';
|
|
6
6
|
import { DatosGlobalesService } from '../../../datos-globales.service';
|
|
7
|
+
import { MensajeConfirmacionComponent } from '../mensaje-confirmacion/mensaje-confirmacion';
|
|
8
|
+
import { MatDialog } from '@angular/material/dialog';
|
|
7
9
|
|
|
8
10
|
@Component({
|
|
9
11
|
selector: 'app-subir-archivo',
|
|
@@ -15,7 +17,10 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
15
17
|
readonly dialogRef = inject(MatDialogRef<SubirArchivoComponent>);
|
|
16
18
|
Archivo: any;
|
|
17
19
|
ListaArchivos: any[] = []
|
|
18
|
-
|
|
20
|
+
HaCargadoArchivos: boolean = false;
|
|
21
|
+
CantidadMaximaDeArchivos: number = 99;
|
|
22
|
+
@Output() HaCargadoArchivosChange = new EventEmitter<boolean>();
|
|
23
|
+
@ViewChild('EntradaDeArchivo') EntradaDeArchivo!: ElementRef<HTMLInputElement>;
|
|
19
24
|
readonly data = inject(MAT_DIALOG_DATA);
|
|
20
25
|
Permiso = '--Permiso=' + this.data.Permiso;
|
|
21
26
|
Etiqueta = this.data.Etiqueta + this.Permiso;
|
|
@@ -24,7 +29,8 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
24
29
|
Token: any;
|
|
25
30
|
public RutaParaListar: string = 'misc/listarArchivos/';
|
|
26
31
|
public RutaParaDescargar: string = 'misc/descargarArchivo/';
|
|
27
|
-
|
|
32
|
+
public RutaParaCargar: string = 'misc/cargarArchivo/';
|
|
33
|
+
constructor(private dialog: MatDialog, private datosGlobalesService: DatosGlobalesService, private http: HttpClient) { }
|
|
28
34
|
|
|
29
35
|
ngOnInit(): void {
|
|
30
36
|
if (this.data.RutaParaListar) {
|
|
@@ -36,12 +42,16 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
36
42
|
if (this.data.FormatosPermitidos) {
|
|
37
43
|
this.FormatosPermitidos = this.data.FormatosPermitidos;
|
|
38
44
|
}
|
|
45
|
+
if (this.data.CantidadMaximaDeArchivos) {
|
|
46
|
+
this.CantidadMaximaDeArchivos = this.data.CantidadMaximaDeArchivos;
|
|
47
|
+
}
|
|
39
48
|
this.ListarArchivos(this.Etiqueta)
|
|
40
49
|
}
|
|
41
50
|
|
|
42
51
|
ArrastrarAdentro(event: DragEvent) {
|
|
43
52
|
event.preventDefault();
|
|
44
53
|
event.stopPropagation();
|
|
54
|
+
if (this.ListaArchivos.length >= this.CantidadMaximaDeArchivos) return;
|
|
45
55
|
const archivoZona = event.target as HTMLElement;
|
|
46
56
|
archivoZona.classList.add('arrastrar');
|
|
47
57
|
}
|
|
@@ -56,25 +66,70 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
56
66
|
event.stopPropagation();
|
|
57
67
|
const archivoZona = event.target as HTMLElement;
|
|
58
68
|
archivoZona.classList.remove('arrastrar');
|
|
69
|
+
|
|
70
|
+
if (this.ListaArchivos.length >= this.CantidadMaximaDeArchivos) {
|
|
71
|
+
this.dialog.open(MensajeConfirmacionComponent, {
|
|
72
|
+
data: {
|
|
73
|
+
titulo: 'Límite alcanzado',
|
|
74
|
+
mensaje: 'Se ha alcanzado la cantidad máxima de archivos permitidos (' + this.CantidadMaximaDeArchivos + ').',
|
|
75
|
+
textoAceptar: 'Continuar',
|
|
76
|
+
onClose: () => { },
|
|
77
|
+
onAccept: () => { },
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
59
83
|
if (event.dataTransfer?.files.length && this.EsEditable) {
|
|
60
84
|
const archivoArrastrado = event.dataTransfer.files[0];
|
|
61
85
|
if (this.ValidarFormato(archivoArrastrado)) {
|
|
62
86
|
this.Archivo = archivoArrastrado;
|
|
63
87
|
} else {
|
|
64
|
-
|
|
88
|
+
this.dialog.open(MensajeConfirmacionComponent, {
|
|
89
|
+
data: {
|
|
90
|
+
titulo: 'Formato de archivo incorrecto',
|
|
91
|
+
mensaje: 'El formato de archivo no está permitido. Los formatos permitidos son: ' + this.FormatosPermitidos.join(', '),
|
|
92
|
+
textoAceptar: 'Continuar',
|
|
93
|
+
onClose: () => { },
|
|
94
|
+
onAccept: () => { },
|
|
95
|
+
},
|
|
96
|
+
});
|
|
65
97
|
}
|
|
66
98
|
}
|
|
67
99
|
}
|
|
68
100
|
|
|
69
101
|
ArchivoSeleccionado(event: Event) {
|
|
102
|
+
if (this.ListaArchivos.length >= this.CantidadMaximaDeArchivos) {
|
|
103
|
+
this.dialog.open(MensajeConfirmacionComponent, {
|
|
104
|
+
data: {
|
|
105
|
+
titulo: 'Límite alcanzado',
|
|
106
|
+
mensaje: 'Se ha alcanzado la cantidad máxima de archivos permitidos (' + this.CantidadMaximaDeArchivos + ').',
|
|
107
|
+
textoAceptar: 'Continuar',
|
|
108
|
+
onClose: () => { },
|
|
109
|
+
onAccept: () => { },
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
const entrada = event.target as HTMLInputElement;
|
|
113
|
+
entrada.value = '';
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
70
117
|
const entrada = event.target as HTMLInputElement;
|
|
71
118
|
if (entrada.files?.length) {
|
|
72
119
|
const archivoSeleccionado = entrada.files[0];
|
|
73
120
|
if (this.ValidarFormato(archivoSeleccionado)) {
|
|
74
121
|
this.Archivo = archivoSeleccionado;
|
|
75
122
|
} else {
|
|
76
|
-
|
|
77
|
-
|
|
123
|
+
this.dialog.open(MensajeConfirmacionComponent, {
|
|
124
|
+
data: {
|
|
125
|
+
titulo: 'Formato de archivo incorrecto',
|
|
126
|
+
mensaje: 'El formato de archivo no está permitido. Los formatos permitidos son: ' + this.FormatosPermitidos.join(', '),
|
|
127
|
+
textoAceptar: 'Continuar',
|
|
128
|
+
onClose: () => { },
|
|
129
|
+
onAccept: () => { },
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
entrada.value = '';
|
|
78
133
|
}
|
|
79
134
|
}
|
|
80
135
|
}
|
|
@@ -88,13 +143,35 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
88
143
|
}
|
|
89
144
|
|
|
90
145
|
AbrirGestorDeArchivos() {
|
|
91
|
-
if (this.EsEditable) {
|
|
92
|
-
this.
|
|
146
|
+
if (this.EsEditable && this.ListaArchivos.length < this.CantidadMaximaDeArchivos) {
|
|
147
|
+
this.EntradaDeArchivo.nativeElement.click();
|
|
148
|
+
} else if (this.ListaArchivos.length >= this.CantidadMaximaDeArchivos) {
|
|
149
|
+
this.dialog.open(MensajeConfirmacionComponent, {
|
|
150
|
+
data: {
|
|
151
|
+
titulo: 'Límite alcanzado',
|
|
152
|
+
mensaje: 'Se ha alcanzado la cantidad máxima de archivos permitidos (' + this.CantidadMaximaDeArchivos + ').',
|
|
153
|
+
textoAceptar: 'Continuar',
|
|
154
|
+
onClose: () => { },
|
|
155
|
+
onAccept: () => { },
|
|
156
|
+
},
|
|
157
|
+
});
|
|
93
158
|
}
|
|
94
159
|
}
|
|
95
160
|
|
|
96
161
|
SubirArchivo() {
|
|
97
162
|
if (this.Archivo) {
|
|
163
|
+
if (this.ListaArchivos.length >= this.CantidadMaximaDeArchivos) {
|
|
164
|
+
this.dialog.open(MensajeConfirmacionComponent, {
|
|
165
|
+
data: {
|
|
166
|
+
titulo: 'Límite alcanzado',
|
|
167
|
+
mensaje: 'Se ha alcanzado la cantidad máxima de archivos permitidos (' + this.CantidadMaximaDeArchivos + ').',
|
|
168
|
+
textoAceptar: 'Continuar',
|
|
169
|
+
onClose: () => { },
|
|
170
|
+
onAccept: () => { },
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
98
175
|
let archivo = new FormData();
|
|
99
176
|
archivo.append("file", this.Archivo);
|
|
100
177
|
this.CargarArchivo(archivo, this.Etiqueta)
|
|
@@ -102,7 +179,7 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
102
179
|
}
|
|
103
180
|
|
|
104
181
|
CargarArchivo(archivo: any, Etiqueta: string) {
|
|
105
|
-
this.http.post(this.datosGlobalesService.ObtenerURL() +
|
|
182
|
+
this.http.post(this.datosGlobalesService.ObtenerURL() + this.RutaParaCargar + Etiqueta,
|
|
106
183
|
archivo)
|
|
107
184
|
.subscribe({
|
|
108
185
|
next: (data: any) => {
|
|
@@ -110,7 +187,7 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
110
187
|
this.ListarArchivos(Etiqueta)
|
|
111
188
|
},
|
|
112
189
|
error: (error) => {
|
|
113
|
-
console.error('Ocurrió un error
|
|
190
|
+
console.error('Ocurrió un error al guardar el archivo:', error);
|
|
114
191
|
}
|
|
115
192
|
})
|
|
116
193
|
}
|
|
@@ -120,9 +197,11 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
120
197
|
.subscribe({
|
|
121
198
|
next: (data: any) => {
|
|
122
199
|
this.ListaArchivos = data.body;
|
|
200
|
+
this.HaCargadoArchivos = this.ListaArchivos.length > 0;
|
|
201
|
+
this.HaCargadoArchivosChange.emit(this.HaCargadoArchivos);
|
|
123
202
|
},
|
|
124
203
|
error: (error) => {
|
|
125
|
-
console.error('Ocurrió un error
|
|
204
|
+
console.error('Ocurrió un error al listar los archivos:', error);
|
|
126
205
|
}
|
|
127
206
|
})
|
|
128
207
|
}
|
|
@@ -148,7 +227,7 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
148
227
|
this.ListarArchivos(this.Etiqueta);
|
|
149
228
|
},
|
|
150
229
|
error: (error) => {
|
|
151
|
-
console.error('Ocurrió un error
|
|
230
|
+
console.error('Ocurrió un error al borrar el archivo:', error);
|
|
152
231
|
}
|
|
153
232
|
})
|
|
154
233
|
}
|