utn-cli 2.0.70 → 2.0.72
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/package.json +1 -1
- package/templates/backend/rutas/ConfiguracionDeTarjetas.js +52 -0
- package/templates/backend/rutas/rutas.js +2 -0
- package/templates/backend/servicios/Nucleo/ConfiguracionDeTarjetas.js +46 -0
- package/templates/bd/docker-scripts/1-crear estructura.sql +10 -0
- package/templates/frontend/src/app/Componentes/Nucleo/tabla/tabla.component.ts +13 -6
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.css +24 -20
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.css +11 -16
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.html +1 -1
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.ts +1 -0
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.css +16 -20
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.html +1 -1
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.ts +1 -0
- package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.ts +30 -26
- package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.css +49 -1
- package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.html +33 -15
- package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.ts +267 -20
- package/templates/frontend/src/app/app.config.ts +2 -4
package/package.json
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const Router = express.Router();
|
|
3
|
+
|
|
4
|
+
const ConfiguracionDeTarjetas = require('../servicios/Nucleo/ConfiguracionDeTarjetas.js');
|
|
5
|
+
const Miscelaneo = require('../servicios/Nucleo/Miscelaneas.js');
|
|
6
|
+
const ManejadorDeErrores = require('../servicios/Nucleo/ManejadorDeErrores.js');
|
|
7
|
+
|
|
8
|
+
Router.get("/obtener", async (solicitud, respuesta, next) => {
|
|
9
|
+
try {
|
|
10
|
+
if (await Miscelaneo.validarTokenV2(solicitud.headers.authorization) && await Miscelaneo.validarAccesoDelOrigen(solicitud)) {
|
|
11
|
+
try {
|
|
12
|
+
const Usuario = await Miscelaneo.obtenerDatosDelUsuario(solicitud.headers.authorization);
|
|
13
|
+
const Datos = {
|
|
14
|
+
Identificador: Usuario.uid
|
|
15
|
+
};
|
|
16
|
+
return respuesta.json({ body: await ConfiguracionDeTarjetas.obtener(Datos), error: undefined });
|
|
17
|
+
} catch (error) {
|
|
18
|
+
const MensajeDeError = "No fue posible obtener la configuración de las tarjetas";
|
|
19
|
+
console.error(new ManejadorDeErrores(MensajeDeError, ManejadorDeErrores.obtenerNumeroDeLinea(), true, `Dirección IP: ${solicitud.ip}`));
|
|
20
|
+
return respuesta.status(500).json({ body: undefined, error: MensajeDeError });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return respuesta.status(401).json({ body: undefined, error: ManejadorDeErrores.mensajeDeError401() });
|
|
24
|
+
} catch (error) {
|
|
25
|
+
next(error);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
Router.post("/actualizar", async (solicitud, respuesta, next) => {
|
|
30
|
+
try {
|
|
31
|
+
if (await Miscelaneo.validarTokenV2(solicitud.headers.authorization) && await Miscelaneo.validarAccesoDelOrigen(solicitud)) {
|
|
32
|
+
try {
|
|
33
|
+
const Usuario = await Miscelaneo.obtenerDatosDelUsuario(solicitud.headers.authorization);
|
|
34
|
+
const Datos = {
|
|
35
|
+
Identificador: Usuario.uid,
|
|
36
|
+
Configuraciones: solicitud.body.Configuraciones,
|
|
37
|
+
LastUser: await Miscelaneo.generarLastUser(solicitud)
|
|
38
|
+
};
|
|
39
|
+
return respuesta.json({ body: await ConfiguracionDeTarjetas.actualizar(Datos), error: undefined });
|
|
40
|
+
} catch (error) {
|
|
41
|
+
const MensajeDeError = "No fue posible actualizar la configuración de las tarjetas";
|
|
42
|
+
console.error(new ManejadorDeErrores(MensajeDeError, ManejadorDeErrores.obtenerNumeroDeLinea(), true, `Dirección IP: ${solicitud.ip}`));
|
|
43
|
+
return respuesta.status(500).json({ body: undefined, error: MensajeDeError });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return respuesta.status(401).json({ body: undefined, error: ManejadorDeErrores.mensajeDeError401() });
|
|
47
|
+
} catch (error) {
|
|
48
|
+
next(error);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
module.exports = Router;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
const rutasMiscelaneas = require('./misc.js');
|
|
2
2
|
const rutasDeAPI = require('./API.js');
|
|
3
3
|
const rutasDeConsentimientoInformado = require('./ConsentimientoInformado.js');
|
|
4
|
+
const rutasDeLaConfiguracionDeTarjetas = require('./ConfiguracionDeTarjetas.js');
|
|
4
5
|
const rutasDelServicio1 = require('./Servicio1.js');
|
|
5
6
|
|
|
6
7
|
function asignarRutasAExpress(app) {
|
|
7
8
|
app.use('/misc', rutasMiscelaneas);
|
|
8
9
|
app.use('/api', rutasDeAPI);
|
|
9
10
|
app.use('/ConsentimientoInformado', rutasDeConsentimientoInformado);
|
|
11
|
+
app.use('/ConfiguracionDeTarjetas', rutasDeLaConfiguracionDeTarjetas);
|
|
10
12
|
app.use('/Servicio1', rutasDelServicio1);
|
|
11
13
|
}
|
|
12
14
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const { ejecutarConsulta } = require('./db.js');
|
|
2
|
+
const Miscelaneas = require('./Miscelaneas.js');
|
|
3
|
+
|
|
4
|
+
class ConfiguracionDeTarjetas {
|
|
5
|
+
constructor() {
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async obtener(Datos) {
|
|
9
|
+
return await ejecutarConsulta(
|
|
10
|
+
"SELECT Titulo, Posicion, ColorDeBorde FROM `framework-mantenimientosv2`.`ConfiguracionDeTarjetas` WHERE Identificador = ? ORDER BY Posicion",
|
|
11
|
+
[Datos.Identificador]
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async actualizar(Datos) {
|
|
16
|
+
const { Identificador, Configuraciones, LastUser } = Datos;
|
|
17
|
+
|
|
18
|
+
// Configuraciones is expected to be an array of { Titulo, Posicion, ColorDeBorde }
|
|
19
|
+
if (!Array.isArray(Configuraciones) || Configuraciones.length === 0) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const values = [];
|
|
24
|
+
const placeholders = [];
|
|
25
|
+
|
|
26
|
+
Configuraciones.forEach(config => {
|
|
27
|
+
placeholders.push('(?, ?, ?, ?, CURRENT_TIMESTAMP(4), ?)');
|
|
28
|
+
values.push(Identificador, config.Titulo, config.Posicion, config.ColorDeBorde || null, LastUser);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const sql = "\
|
|
32
|
+
INSERT INTO `framework-mantenimientosv2`.`ConfiguracionDeTarjetas` \
|
|
33
|
+
(Identificador, Titulo, Posicion, ColorDeBorde, LastUpdate, LastUser) \
|
|
34
|
+
VALUES " + placeholders.join(', ') +
|
|
35
|
+
" ON DUPLICATE KEY UPDATE \
|
|
36
|
+
Posicion = VALUES(Posicion), \
|
|
37
|
+
ColorDeBorde = VALUES(ColorDeBorde), \
|
|
38
|
+
LastUpdate = VALUES(LastUpdate), \
|
|
39
|
+
LastUser = VALUES(LastUser) \
|
|
40
|
+
";
|
|
41
|
+
|
|
42
|
+
return await ejecutarConsulta(sql, values);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = new ConfiguracionDeTarjetas();
|
|
@@ -27,3 +27,13 @@ CREATE OR REPLACE TABLE `NOMBRE_DEL_REPOSITORIO_DE_BASE_DE_DATOS`.`AceptacionesD
|
|
|
27
27
|
PRIMARY KEY(`AceptacionDeConsentimientoInformadoId`),
|
|
28
28
|
KEY (`Identificador`)
|
|
29
29
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_spanish_ci COMMENT = 'Almacena las aceptaciones de los consentimientos informados';
|
|
30
|
+
|
|
31
|
+
CREATE OR REPLACE TABLE `NOMBRE_DEL_REPOSITORIO_DE_BASE_DE_DATOS`.`framework-mantenimientosv2`.`ConfiguracionDeTarjetas` (
|
|
32
|
+
`Identificador` INT UNSIGNED NOT NULL COMMENT 'Llave foránea virtual correspondiente a `Identificador` en la tabla `SIGU`.`SIGU_Personas`',
|
|
33
|
+
`Titulo` VARCHAR(200) NOT NULL COMMENT 'Título de la tarjeta que sirve como identificador único por usuario',
|
|
34
|
+
`Posicion` SMALLINT UNSIGNED NOT NULL COMMENT 'Posición de la tarjeta',
|
|
35
|
+
`ColorDeBorde` VARCHAR(10) DEFAULT NULL COMMENT 'Color de borde de la tarjeta',
|
|
36
|
+
`LastUpdate` DATETIME(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(4) COMMENT 'Fecha de la última actualización de la fila',
|
|
37
|
+
`LastUser` VARCHAR(1000) NOT NULL DEFAULT '-' COMMENT 'Último usuario que modificó la fila',
|
|
38
|
+
PRIMARY KEY (`Identificador`, `Titulo`)
|
|
39
|
+
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_spanish_ci COMMENT = 'Almacena la configuración de las tarjetas del contenedor principal por usuario';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
|
|
1
|
+
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, OnDestroy, Output, SimpleChanges, ViewChild } from '@angular/core';
|
|
2
2
|
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
|
3
3
|
import { MatIconModule } from '@angular/material/icon';
|
|
4
4
|
import { MatButtonModule } from '@angular/material/button';
|
|
@@ -14,6 +14,7 @@ import { MatBadgeModule } from '@angular/material/badge';
|
|
|
14
14
|
import { MatMenuModule } from '@angular/material/menu';
|
|
15
15
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
16
16
|
import { FormsModule } from '@angular/forms';
|
|
17
|
+
import { Subscription } from 'rxjs';
|
|
17
18
|
|
|
18
19
|
@Component({
|
|
19
20
|
selector: 'app-tabla',
|
|
@@ -42,7 +43,7 @@ import { FormsModule } from '@angular/forms';
|
|
|
42
43
|
templateUrl: './tabla.component.html',
|
|
43
44
|
styleUrl: './tabla.component.css'
|
|
44
45
|
})
|
|
45
|
-
export class TablaComponent implements OnInit, OnChanges {
|
|
46
|
+
export class TablaComponent implements OnInit, OnChanges, OnDestroy {
|
|
46
47
|
@Input() columnas: { Llave: string, Alias: string, TipoDeFiltro: string, Visible?: boolean }[] = [];
|
|
47
48
|
@Input() subColumnas: { Llave: string, Alias: string }[] = [];
|
|
48
49
|
@Input() datos: any[] = [];
|
|
@@ -80,6 +81,8 @@ export class TablaComponent implements OnInit, OnChanges {
|
|
|
80
81
|
@Input() TotalDeRegistros: number = 0;
|
|
81
82
|
@Output() CambioDePagina: EventEmitter<{ accion: string, pageIndex: number, pageSize: number, valorParaFiltrar: string, columnaParaFiltrar: string, columnasParaFiltrar: string, ordenColumna: string, ordenDireccion: string }> = new EventEmitter();
|
|
82
83
|
|
|
84
|
+
private subscriptions: Subscription = new Subscription();
|
|
85
|
+
|
|
83
86
|
constructor(private dialog: MatDialog) {
|
|
84
87
|
const pageSize = localStorage.getItem('pageSize');
|
|
85
88
|
if (pageSize) {
|
|
@@ -204,7 +207,7 @@ export class TablaComponent implements OnInit, OnChanges {
|
|
|
204
207
|
|
|
205
208
|
ngAfterViewInit() {
|
|
206
209
|
this.dataSource.sort = this.sort;
|
|
207
|
-
this.paginator.page.subscribe((event: PageEvent) => {
|
|
210
|
+
this.subscriptions.add(this.paginator.page.subscribe((event: PageEvent) => {
|
|
208
211
|
localStorage.setItem('pageSize', event.pageSize.toString());
|
|
209
212
|
|
|
210
213
|
let accion = '';
|
|
@@ -229,8 +232,8 @@ export class TablaComponent implements OnInit, OnChanges {
|
|
|
229
232
|
|
|
230
233
|
this.ultimaPagina = event.pageIndex;
|
|
231
234
|
this.ultimoPageSize = event.pageSize;
|
|
232
|
-
});
|
|
233
|
-
this.sort.sortChange.subscribe(sort => {
|
|
235
|
+
}));
|
|
236
|
+
this.subscriptions.add(this.sort.sortChange.subscribe(sort => {
|
|
234
237
|
if (this.paginarResultados) {
|
|
235
238
|
this.CambioDePagina.emit({
|
|
236
239
|
accion: 'Cambio de orden',
|
|
@@ -243,7 +246,11 @@ export class TablaComponent implements OnInit, OnChanges {
|
|
|
243
246
|
ordenDireccion: sort.direction
|
|
244
247
|
});
|
|
245
248
|
}
|
|
246
|
-
});
|
|
249
|
+
}));
|
|
247
250
|
this.actualizarDataSource();
|
|
248
251
|
}
|
|
252
|
+
|
|
253
|
+
ngOnDestroy() {
|
|
254
|
+
this.subscriptions.unsubscribe();
|
|
255
|
+
}
|
|
249
256
|
}
|
|
@@ -5,32 +5,32 @@
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
.contenedor {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
width: 100%;
|
|
9
|
+
/* Ocupa todo el espacio que le dé el padre (cdkDrag) */
|
|
10
10
|
background: #ffffff 0% 0% no-repeat padding-box;
|
|
11
11
|
box-shadow: 0px 3px 6px #00000029;
|
|
12
12
|
border-radius: 10px;
|
|
13
13
|
opacity: 1;
|
|
14
|
-
|
|
15
|
-
padding: 5%;
|
|
14
|
+
padding: 16px;
|
|
16
15
|
cursor: pointer;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
height: 100%;
|
|
19
|
+
/* Asegura que todas las tarjetas tengan la misma altura si se desea */
|
|
20
|
+
box-sizing: border-box;
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
.contenedor {
|
|
21
|
-
width: 80vw;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@media (min-width:481px) and (max-width:1025px) {
|
|
26
|
-
.contenedor {
|
|
27
|
-
width: 50vw;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
23
|
+
/* Eliminamos los media queries antiguos que forzaban anchos en vw */
|
|
30
24
|
|
|
31
25
|
.contenedor .cabecera_contenedor {
|
|
32
26
|
display: flex;
|
|
33
27
|
flex-direction: row;
|
|
28
|
+
align-items: flex-start;
|
|
29
|
+
/* Alinea los elementos al inicio (arriba) */
|
|
30
|
+
justify-content: space-between;
|
|
31
|
+
/* Separa el texto del icono */
|
|
32
|
+
gap: 8px;
|
|
33
|
+
/* Espacio mínimo entre texto e icono */
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
.contenedor .cabecera_contenedor .icono {
|
|
@@ -39,13 +39,14 @@
|
|
|
39
39
|
border-radius: 50%;
|
|
40
40
|
display: flex;
|
|
41
41
|
align-items: center;
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
justify-content: center;
|
|
43
|
+
width: 48px;
|
|
44
|
+
height: 48px;
|
|
45
|
+
min-width: 48px;
|
|
46
|
+
/* Evita que flexbox lo encoja */
|
|
44
47
|
color: #1b3069;
|
|
45
48
|
font-size: x-small;
|
|
46
49
|
font-weight: bold;
|
|
47
|
-
margin-left: 5%;
|
|
48
|
-
padding: 2%;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
.contenedor .cabecera_contenedor .icono .numero {
|
|
@@ -53,7 +54,10 @@
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
.contenedor .cabecera {
|
|
56
|
-
|
|
57
|
+
flex: 1;
|
|
58
|
+
/* Permite que el texto ocupe todo el espacio sobrante */
|
|
59
|
+
min-width: 0;
|
|
60
|
+
/* Permite truncar texto si es muy largo en móviles */
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
.contenedor .cabecera .titulo {
|
|
@@ -5,27 +5,19 @@
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
.contenedor {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
width: 20vw;
|
|
11
|
-
padding: 5%;
|
|
8
|
+
width: 100%;
|
|
9
|
+
padding: 16px;
|
|
12
10
|
background: #ffffff;
|
|
13
11
|
box-shadow: 0px 3px 6px #00000029;
|
|
14
12
|
border-radius: 10px;
|
|
15
13
|
cursor: pointer;
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
height: 100%;
|
|
17
|
+
box-sizing: border-box;
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
.contenedor {
|
|
20
|
-
width: 80vw;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@media (min-width: 481px) and (max-width: 1025px) {
|
|
25
|
-
.contenedor {
|
|
26
|
-
width: 50vw;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
20
|
+
/* Eliminamos los media queries antiguos que forzaban anchos en vw */
|
|
29
21
|
|
|
30
22
|
.cabecera_contenedor {
|
|
31
23
|
display: flex;
|
|
@@ -59,10 +51,13 @@
|
|
|
59
51
|
display: flex;
|
|
60
52
|
align-items: center;
|
|
61
53
|
justify-content: center;
|
|
54
|
+
width: 48px;
|
|
55
|
+
height: 48px;
|
|
56
|
+
min-width: 48px; /* Evita que flexbox lo encoja */
|
|
62
57
|
color: #1b3069;
|
|
63
|
-
padding: 8px;
|
|
64
58
|
cursor: pointer;
|
|
65
59
|
position: relative;
|
|
60
|
+
margin-left: auto; /* Empuja el icono a la derecha si es necesario */
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
.menu-rutas {
|
package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.css
CHANGED
|
@@ -5,32 +5,27 @@
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
.contenedor {
|
|
8
|
-
|
|
9
|
-
width: 20vw;
|
|
8
|
+
width: 100%;
|
|
10
9
|
background: #ffffff 0% 0% no-repeat padding-box;
|
|
11
10
|
box-shadow: 0px 3px 6px #00000029;
|
|
12
11
|
border-radius: 10px;
|
|
13
12
|
opacity: 1;
|
|
14
|
-
|
|
15
|
-
padding: 5%;
|
|
13
|
+
padding: 16px;
|
|
16
14
|
cursor: pointer;
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
height: 100%;
|
|
18
|
+
box-sizing: border-box;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
.contenedor {
|
|
21
|
-
width: 80vw;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@media (min-width:481px) and (max-width:1025px) {
|
|
26
|
-
.contenedor {
|
|
27
|
-
width: 50vw;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
21
|
+
/* Eliminamos los media queries antiguos que forzaban anchos en vw */
|
|
30
22
|
|
|
31
23
|
.contenedor .cabecera_contenedor {
|
|
32
24
|
display: flex;
|
|
33
25
|
flex-direction: row;
|
|
26
|
+
align-items: flex-start;
|
|
27
|
+
justify-content: space-between;
|
|
28
|
+
gap: 8px;
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
.contenedor .cabecera_contenedor .icono {
|
|
@@ -39,13 +34,13 @@
|
|
|
39
34
|
border-radius: 50%;
|
|
40
35
|
display: flex;
|
|
41
36
|
align-items: center;
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
justify-content: center;
|
|
38
|
+
width: 48px;
|
|
39
|
+
height: 48px;
|
|
40
|
+
min-width: 48px; /* Evita que flexbox lo encoja */
|
|
44
41
|
color: #1b3069;
|
|
45
42
|
font-size: x-small;
|
|
46
43
|
font-weight: bold;
|
|
47
|
-
margin-left: 5%;
|
|
48
|
-
padding: 2%;
|
|
49
44
|
}
|
|
50
45
|
|
|
51
46
|
.contenedor .cabecera_contenedor .icono .numero {
|
|
@@ -53,7 +48,8 @@
|
|
|
53
48
|
}
|
|
54
49
|
|
|
55
50
|
.contenedor .cabecera {
|
|
56
|
-
|
|
51
|
+
flex: 1;
|
|
52
|
+
min-width: 0;
|
|
57
53
|
}
|
|
58
54
|
|
|
59
55
|
.contenedor .cabecera .titulo {
|
package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.ts
CHANGED
|
@@ -12,6 +12,7 @@ export class TarjetaReporteComponent {
|
|
|
12
12
|
@Input() descripcion: string = "";
|
|
13
13
|
@Input() icono: any = null;
|
|
14
14
|
@Input() reporteAGenerar: string = '';
|
|
15
|
+
@Input() ColorDeBorde: string = '';
|
|
15
16
|
@Output() GenerarReporte: EventEmitter<{ reporte: string }> = new EventEmitter();
|
|
16
17
|
|
|
17
18
|
constructor() { }
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
2
|
-
import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
2
|
+
import { Component, OnInit, OnDestroy, NgZone } from '@angular/core';
|
|
3
3
|
import { RouterOutlet, Router } from '@angular/router';
|
|
4
4
|
import { DatosGlobalesService } from '../../../datos-globales.service';
|
|
5
5
|
import { Location, CommonModule } from '@angular/common';
|
|
@@ -36,7 +36,7 @@ export class ContenedorComponentesComponent implements OnInit, OnDestroy {
|
|
|
36
36
|
public AnimarUsuariosActivos: boolean = true;
|
|
37
37
|
private intervaloUsuarios: any;
|
|
38
38
|
|
|
39
|
-
constructor(private http: HttpClient, private datosGlobalesService: DatosGlobalesService, private location: Location, private dialog: MatDialog, private router: Router) {
|
|
39
|
+
constructor(private http: HttpClient, private datosGlobalesService: DatosGlobalesService, private location: Location, private dialog: MatDialog, private router: Router, private ngZone: NgZone) {
|
|
40
40
|
if (datosGlobalesService.ObtenerToken() === '') {
|
|
41
41
|
datosGlobalesService.RedirigirALogin();
|
|
42
42
|
}
|
|
@@ -57,10 +57,12 @@ export class ContenedorComponentesComponent implements OnInit, OnDestroy {
|
|
|
57
57
|
this.claseDelContenedor = 'contenedor';
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
this.
|
|
61
|
-
this.intervaloUsuarios = setInterval(() => {
|
|
60
|
+
this.ngZone.runOutsideAngular(() => {
|
|
62
61
|
this.obtenerUsuariosActuales();
|
|
63
|
-
|
|
62
|
+
this.intervaloUsuarios = setInterval(() => {
|
|
63
|
+
this.obtenerUsuariosActuales();
|
|
64
|
+
}, 60000);
|
|
65
|
+
});
|
|
64
66
|
|
|
65
67
|
this.http.get(this.datosGlobalesService.ObtenerURL() + 'misc/validarToken').subscribe((datos: any) => {
|
|
66
68
|
this.TienePermiso = datos.body;
|
|
@@ -224,31 +226,33 @@ export class ContenedorComponentesComponent implements OnInit, OnDestroy {
|
|
|
224
226
|
|
|
225
227
|
obtenerUsuariosActuales(): void {
|
|
226
228
|
this.http.get(this.datosGlobalesService.ObtenerURL() + 'misc/UsuariosActuales').subscribe((datos: any) => {
|
|
227
|
-
|
|
229
|
+
this.ngZone.run(() => {
|
|
230
|
+
const data = datos.body;
|
|
228
231
|
|
|
229
|
-
|
|
230
|
-
|
|
232
|
+
let actuales = data.UsuariosActuales;
|
|
233
|
+
let activos = data.UsuariosActivos;
|
|
231
234
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
235
|
+
// Si activos es mayor a actuales, igualamos activos a actuales
|
|
236
|
+
if (activos > actuales) {
|
|
237
|
+
activos = actuales;
|
|
238
|
+
}
|
|
236
239
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
240
|
+
if (this.UsuariosActuales !== actuales) {
|
|
241
|
+
this.UsuariosActuales = actuales;
|
|
242
|
+
this.AnimarUsuarios = false;
|
|
243
|
+
setTimeout(() => {
|
|
244
|
+
this.AnimarUsuarios = true;
|
|
245
|
+
}, 50);
|
|
246
|
+
}
|
|
244
247
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
248
|
+
if (this.UsuariosActivos !== activos) {
|
|
249
|
+
this.UsuariosActivos = activos;
|
|
250
|
+
this.AnimarUsuariosActivos = false;
|
|
251
|
+
setTimeout(() => {
|
|
252
|
+
this.AnimarUsuariosActivos = true;
|
|
253
|
+
}, 50);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
252
256
|
});
|
|
253
257
|
}
|
|
254
258
|
}
|
package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.css
CHANGED
|
@@ -1,4 +1,52 @@
|
|
|
1
1
|
.contenido {
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-wrap: wrap;
|
|
4
|
-
|
|
4
|
+
gap: 16px;
|
|
5
|
+
padding: 16px;
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
width: 100%;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* Forzamos 4 columnas calculando el espacio disponible */
|
|
11
|
+
.contenido > div[cdkDrag] {
|
|
12
|
+
width: calc(25% - 12px); /* 25% menos una parte del gap (16px * 3 / 4) */
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.cdk-drag-preview {
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
border-radius: 8px;
|
|
19
|
+
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
|
|
20
|
+
pointer-events: none;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.cdk-drag-placeholder {
|
|
24
|
+
opacity: 0.3;
|
|
25
|
+
background: #ccc;
|
|
26
|
+
border: 2px dashed #999;
|
|
27
|
+
border-radius: 8px;
|
|
28
|
+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
|
29
|
+
/* El placeholder debe mantener el tamaño de la tarjeta */
|
|
30
|
+
min-height: 150px; /* Ajustar según la altura promedio de tus tarjetas */
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.cdk-drag-animating {
|
|
34
|
+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.contenido.cdk-drop-list-dragging div:not(.cdk-drag-placeholder) {
|
|
38
|
+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Responsividad: 2 columnas en tablets, 1 en móviles */
|
|
42
|
+
@media (max-width: 1200px) {
|
|
43
|
+
.contenido > div[cdkDrag] {
|
|
44
|
+
width: calc(50% - 8px);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@media (max-width: 600px) {
|
|
49
|
+
.contenido > div[cdkDrag] {
|
|
50
|
+
width: 100%;
|
|
51
|
+
}
|
|
52
|
+
}
|
package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.html
CHANGED
|
@@ -1,17 +1,35 @@
|
|
|
1
|
-
<div class="contenido">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
<div class="contenido" cdkDropList cdkDropListOrientation="mixed" (cdkDropListDropped)="drop($event)">
|
|
2
|
+
@for (tarjeta of tarjetas; track tarjeta.titulo) {
|
|
3
|
+
<div cdkDrag>
|
|
4
|
+
@switch (tarjeta.type) {
|
|
5
|
+
@case ('single') {
|
|
6
|
+
<app-tarjeta
|
|
7
|
+
[rutaASeguir]="tarjeta.rutaASeguir"
|
|
8
|
+
[titulo]="tarjeta.titulo"
|
|
9
|
+
[descripcion]="tarjeta.descripcion"
|
|
10
|
+
[icono]="tarjeta.icono"
|
|
11
|
+
[ColorDeBorde]="tarjeta.ColorDeBorde ? tarjeta.ColorDeBorde : ''">
|
|
12
|
+
</app-tarjeta>
|
|
13
|
+
}
|
|
14
|
+
@case ('multiple') {
|
|
15
|
+
<app-tarjeta-multiple
|
|
16
|
+
[titulo]="tarjeta.titulo"
|
|
17
|
+
[descripcion]="tarjeta.descripcion"
|
|
18
|
+
[rutas]="tarjeta.rutas"
|
|
19
|
+
[ColorDeBorde]="tarjeta.ColorDeBorde ? tarjeta.ColorDeBorde : ''">
|
|
20
|
+
</app-tarjeta-multiple>
|
|
21
|
+
}
|
|
22
|
+
@case ('report') {
|
|
23
|
+
<app-tarjeta-reporte
|
|
24
|
+
[reporteAGenerar]="tarjeta.reporteAGenerar"
|
|
25
|
+
[titulo]="tarjeta.titulo"
|
|
26
|
+
[descripcion]="tarjeta.descripcion"
|
|
27
|
+
[icono]="tarjeta.icono"
|
|
28
|
+
[ColorDeBorde]="tarjeta.ColorDeBorde ? tarjeta.ColorDeBorde : ''"
|
|
29
|
+
(GenerarReporte)="GenerarReporte($event)">
|
|
30
|
+
</app-tarjeta-reporte>
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
</div>
|
|
16
34
|
}
|
|
17
35
|
</div>
|
package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.ts
CHANGED
|
@@ -1,36 +1,283 @@
|
|
|
1
|
-
import { Component } from "@angular/core";
|
|
1
|
+
import { Component, OnInit } from "@angular/core";
|
|
2
|
+
import { CommonModule } from "@angular/common";
|
|
2
3
|
import { TarjetaComponent } from "../../Componentes/Nucleo/tarjeta/tarjeta.component";
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import { TarjetaMultipleComponent } from "../../Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component";
|
|
5
|
+
import { TarjetaReporteComponent } from "../../Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component";
|
|
6
|
+
import { HttpClient } from "@angular/common/http";
|
|
7
|
+
import { DatosGlobalesService } from '../../datos-globales.service';
|
|
8
|
+
import { DragDropModule, CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
|
9
|
+
|
|
10
|
+
interface BaseTarjetaConfig {
|
|
11
|
+
type: 'single' | 'multiple' | 'report';
|
|
12
|
+
position: number;
|
|
13
|
+
titulo: string;
|
|
14
|
+
descripcion: string;
|
|
15
|
+
acceso?: boolean;
|
|
16
|
+
ColorDeBorde?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface TarjetaConfig extends BaseTarjetaConfig {
|
|
20
|
+
type: 'single';
|
|
21
|
+
rutaASeguir: string;
|
|
22
|
+
icono: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface RutaMenuItem {
|
|
26
|
+
nombre: string;
|
|
27
|
+
ruta: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface TarjetaMultipleConfig extends BaseTarjetaConfig {
|
|
31
|
+
type: 'multiple';
|
|
32
|
+
rutas: RutaMenuItem[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface TarjetaReporteConfig extends BaseTarjetaConfig {
|
|
36
|
+
type: 'report';
|
|
37
|
+
reporteAGenerar: string;
|
|
38
|
+
icono: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type AnyTarjetaConfig = TarjetaConfig | TarjetaMultipleConfig | TarjetaReporteConfig;
|
|
5
42
|
|
|
6
43
|
@Component({
|
|
7
44
|
selector: "app-contenedor-principal",
|
|
8
|
-
|
|
45
|
+
standalone: true,
|
|
46
|
+
imports: [TarjetaComponent, TarjetaMultipleComponent, TarjetaReporteComponent, CommonModule, DragDropModule],
|
|
9
47
|
templateUrl: "./contenedor-principal.component.html",
|
|
10
48
|
styleUrl: "./contenedor-principal.component.css"
|
|
11
49
|
})
|
|
12
|
-
|
|
50
|
+
|
|
51
|
+
export class ContenedorPrincipalComponent implements OnInit {
|
|
13
52
|
public cantidad: number = 0;
|
|
14
53
|
public cantidadMaxima: number = 0;
|
|
54
|
+
public tarjetas: AnyTarjetaConfig[] = [];
|
|
15
55
|
|
|
16
|
-
constructor(
|
|
56
|
+
constructor(private http: HttpClient, private datosGlobalesService: DatosGlobalesService) {
|
|
17
57
|
this.cantidad = 0;
|
|
18
58
|
this.cantidadMaxima = 0;
|
|
19
59
|
}
|
|
20
60
|
|
|
21
|
-
ngOnInit() {
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
61
|
+
async ngOnInit() {
|
|
62
|
+
// 1. Define base cards
|
|
63
|
+
let baseTarjetas: AnyTarjetaConfig[] = [
|
|
64
|
+
{
|
|
65
|
+
type: 'single',
|
|
66
|
+
position: 10,
|
|
67
|
+
rutaASeguir: 'FRM-ModulosV2',
|
|
68
|
+
titulo: 'Módulos',
|
|
69
|
+
descripcion: 'Módulo para el mantenimiento de los módulosV2',
|
|
70
|
+
icono: 'dashboard_2',
|
|
71
|
+
ColorDeBorde: '#0B4FCE'
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
type: 'single',
|
|
75
|
+
position: 20,
|
|
76
|
+
rutaASeguir: 'tablaTareasProgramadas',
|
|
77
|
+
titulo: 'Tareas programadas',
|
|
78
|
+
descripcion: 'Módulo para el mantenimiento de las tareas programadas',
|
|
79
|
+
icono: 'grading'
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: 'multiple',
|
|
83
|
+
position: 30,
|
|
84
|
+
titulo: 'Permisos',
|
|
85
|
+
descripcion: 'Módulo para el mantenimiento de los permisos',
|
|
86
|
+
rutas: [
|
|
87
|
+
{ nombre: 'Permisos', ruta: 'tablaPermisos' },
|
|
88
|
+
{ nombre: 'Permisos de personas', ruta: 'tablaPermisosDePersonas' },
|
|
89
|
+
{ nombre: 'Permisos padres de personas', ruta: 'tablaPermisosDePersonasPadres' }
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: 'multiple',
|
|
94
|
+
position: 40,
|
|
95
|
+
titulo: 'Permisos extra',
|
|
96
|
+
descripcion: 'Módulo para el mantenimiento de los permisos extra',
|
|
97
|
+
rutas: [
|
|
98
|
+
{ nombre: 'Permisos extra', ruta: 'tablaPermisosExtra' },
|
|
99
|
+
{ nombre: 'Permisos extra de personas', ruta: 'tablaPermisosExtraDePersonas' },
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: 'single',
|
|
104
|
+
position: 50,
|
|
105
|
+
rutaASeguir: 'tablaMensajesInstitucionales',
|
|
106
|
+
titulo: 'Mensajes institucionales',
|
|
107
|
+
descripcion: 'Módulo para el mantenimiento de mensajes institucionales',
|
|
108
|
+
icono: 'mark_unread_chat_alt'
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: 'single',
|
|
112
|
+
position: 60,
|
|
113
|
+
rutaASeguir: 'tablaMensajesModulares',
|
|
114
|
+
titulo: 'Mensajes modulares',
|
|
115
|
+
descripcion: 'Módulo para el mantenimiento de mensajes modulares',
|
|
116
|
+
icono: 'mark_unread_chat_alt'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
type: 'single',
|
|
120
|
+
position: 70,
|
|
121
|
+
rutaASeguir: 'tablaPeriodos',
|
|
122
|
+
titulo: 'Periodos',
|
|
123
|
+
descripcion: 'Módulo para el mantenimiento de periodos',
|
|
124
|
+
icono: 'edit_calendar'
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: 'single',
|
|
128
|
+
position: 80,
|
|
129
|
+
rutaASeguir: 'tablaSedes',
|
|
130
|
+
titulo: 'Sedes y recintos',
|
|
131
|
+
descripcion: 'Módulo para el mantenimiento de sedes y recintos',
|
|
132
|
+
icono: 'home_work'
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: 'single',
|
|
136
|
+
position: 90,
|
|
137
|
+
rutaASeguir: 'tablaFlujosAprobacion',
|
|
138
|
+
titulo: 'Flujos de aprobación',
|
|
139
|
+
descripcion: 'Módulo para el mantenimiento de flujos de aprobación, pasos y movimientos',
|
|
140
|
+
icono: 'library_add_check'
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: 'single',
|
|
144
|
+
position: 100,
|
|
145
|
+
rutaASeguir: 'tablaLocalidades',
|
|
146
|
+
titulo: 'Localidades',
|
|
147
|
+
descripcion: 'Módulo para la revisión de las diferentes localidades',
|
|
148
|
+
icono: 'location_on'
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
type: 'multiple',
|
|
152
|
+
position: 110,
|
|
153
|
+
titulo: 'Repositorios',
|
|
154
|
+
descripcion: 'Módulo para el mantenimiento de repositorios, variables del sistema y tareas programadas',
|
|
155
|
+
rutas: [
|
|
156
|
+
{ nombre: 'Consentimientos informados', ruta: 'tablaConsentimientosInformados' },
|
|
157
|
+
{ nombre: 'Repositorios', ruta: 'tablaRepositorios' },
|
|
158
|
+
{ nombre: 'Accesos a repositorios', ruta: 'tablaRepositoriosAccesos' },
|
|
159
|
+
{ nombre: 'Variables del sistema', ruta: 'tablaVariablesDeSistema' },
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'single',
|
|
164
|
+
position: 120,
|
|
165
|
+
rutaASeguir: 'gestionGrafico',
|
|
166
|
+
titulo: 'Gráfico de solicitudes mensuales',
|
|
167
|
+
descripcion: 'Módulo para la visualización del gráfico de solicitudes por el mes actual',
|
|
168
|
+
icono: 'leaderboard'
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
type: 'single',
|
|
172
|
+
position: 130,
|
|
173
|
+
rutaASeguir: 'gestionGraficoSesiones',
|
|
174
|
+
titulo: 'Gráfico de las sesiones',
|
|
175
|
+
descripcion: 'Módulo para la visualización del gráfico de sesiones',
|
|
176
|
+
icono: 'pie_chart'
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'single',
|
|
180
|
+
position: 140,
|
|
181
|
+
rutaASeguir: 'tablaAdministradores',
|
|
182
|
+
titulo: 'Administradores',
|
|
183
|
+
descripcion: 'Módulo para el mantenimiento de administradores',
|
|
184
|
+
icono: 'supervisor_account'
|
|
185
|
+
}
|
|
186
|
+
];
|
|
187
|
+
|
|
188
|
+
// 2. Check for extra permissions (Personas card)
|
|
189
|
+
this.http.get(`${this.datosGlobalesService.ObtenerURL()}Personas/PermisoExtra`).subscribe({
|
|
190
|
+
next: (datos: any) => {
|
|
191
|
+
if (datos.body) {
|
|
192
|
+
const personasCard: TarjetaMultipleConfig = {
|
|
193
|
+
type: 'multiple',
|
|
194
|
+
position: 25,
|
|
195
|
+
titulo: 'Personas',
|
|
196
|
+
descripcion: 'Módulo para el mantenimiento de los datos relacionados con personas',
|
|
197
|
+
rutas: [
|
|
198
|
+
{ nombre: 'Personas', ruta: 'tablaPersonas' },
|
|
199
|
+
{ nombre: 'Correos', ruta: 'tablaCorreosPersonas' },
|
|
200
|
+
{ nombre: 'Cuentas bancarias', ruta: 'tablaCuentasPersonas' },
|
|
201
|
+
{ nombre: 'Teléfonos', ruta: 'tablaTelefonosPersonas' },
|
|
202
|
+
{ nombre: 'Ubicación', ruta: 'tablaUbicacionPersona' },
|
|
203
|
+
]
|
|
204
|
+
};
|
|
205
|
+
baseTarjetas.push(personasCard);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 3. Load user-specific positions from backend
|
|
209
|
+
this.http.get(`${this.datosGlobalesService.ObtenerURL()}ConfiguracionDeTarjetas/obtener`).subscribe({
|
|
210
|
+
next: (res: any) => {
|
|
211
|
+
if (res.body && res.body.length > 0) {
|
|
212
|
+
const savedConfigs = res.body;
|
|
213
|
+
baseTarjetas.forEach(tarjeta => {
|
|
214
|
+
const config = savedConfigs.find((c: any) => c.Titulo === tarjeta.titulo);
|
|
215
|
+
if (config) {
|
|
216
|
+
tarjeta.position = config.Posicion;
|
|
217
|
+
if (config.ColorDeBorde) {
|
|
218
|
+
tarjeta.ColorDeBorde = config.ColorDeBorde;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
this.tarjetas = baseTarjetas.sort((a, b) => a.position - b.position);
|
|
224
|
+
},
|
|
225
|
+
error: (error) => {
|
|
226
|
+
console.error('Error al obtener configuración de tarjetas:', error);
|
|
227
|
+
this.tarjetas = baseTarjetas.sort((a, b) => a.position - b.position);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
error: (error) => {
|
|
232
|
+
console.error('Problemas al intentar obtener los datos: ', error);
|
|
233
|
+
this.tarjetas = baseTarjetas.sort((a, b) => a.position - b.position);
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
drop(event: CdkDragDrop<AnyTarjetaConfig[]>) {
|
|
239
|
+
moveItemInArray(this.tarjetas, event.previousIndex, event.currentIndex);
|
|
240
|
+
// Update positions based on new order
|
|
241
|
+
this.tarjetas.forEach((tarjeta, index) => {
|
|
242
|
+
tarjeta.position = (index + 1) * 10;
|
|
243
|
+
});
|
|
244
|
+
this.persistirConfiguracion();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
persistirConfiguracion() {
|
|
248
|
+
const Configuraciones = this.tarjetas.map(t => ({
|
|
249
|
+
Titulo: t.titulo,
|
|
250
|
+
Posicion: t.position,
|
|
251
|
+
ColorDeBorde: t.ColorDeBorde
|
|
252
|
+
}));
|
|
253
|
+
|
|
254
|
+
this.http.post(`${this.datosGlobalesService.ObtenerURL()}ConfiguracionDeTarjetas/actualizar`, {
|
|
255
|
+
Configuraciones
|
|
256
|
+
}).subscribe({
|
|
257
|
+
error: (error) => {
|
|
258
|
+
console.error('Error al persistir la configuración de tarjetas:', error);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
GenerarReporte(event: { reporte: string }) {
|
|
264
|
+
if (event.reporte === 'ElReporte1') {
|
|
265
|
+
this.http.get(`${this.datosGlobalesService.ObtenerURL()}misc/DatosParaReporteCSV`, {
|
|
266
|
+
responseType: 'text'
|
|
267
|
+
}).subscribe({
|
|
268
|
+
next: (datos: any) => {
|
|
269
|
+
const blob = new Blob([datos], { type: 'text/csv' });
|
|
270
|
+
const url = window.URL.createObjectURL(blob);
|
|
271
|
+
const a = document.createElement('a');
|
|
272
|
+
a.href = url;
|
|
273
|
+
a.download = 'ReporteDePrueba.csv';
|
|
274
|
+
a.click();
|
|
275
|
+
window.URL.revokeObjectURL(url);
|
|
276
|
+
},
|
|
277
|
+
error: (error) => {
|
|
278
|
+
console.error('Problemas al intentar obtener los datos para el reporte: ', error);
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
}
|
|
35
282
|
}
|
|
36
283
|
}
|
|
@@ -18,10 +18,8 @@ export const appConfig: ApplicationConfig = {
|
|
|
18
18
|
provideRouter(routes),
|
|
19
19
|
provideClientHydration(withEventReplay()),
|
|
20
20
|
provideAnimationsAsync(),
|
|
21
|
-
provideHttpClient(withFetch()),
|
|
22
|
-
provideClientHydration(),
|
|
21
|
+
provideHttpClient(withFetch(), withInterceptors([AuthInterceptor])),
|
|
23
22
|
provideCharts(withDefaultRegisterables()),
|
|
24
|
-
...AnalyticsModule.forRoot().providers
|
|
25
|
-
provideHttpClient(withInterceptors([AuthInterceptor]))
|
|
23
|
+
...AnalyticsModule.forRoot().providers!
|
|
26
24
|
]
|
|
27
25
|
};
|