utn-cli 2.1.1 → 2.1.3
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/.claude/settings.local.json +7 -0
- package/commands/commit.js +14 -1
- package/commands/frontend.js +1 -1
- package/package.json +1 -1
- package/templates/backend/package.json +3 -3
- package/templates/backend/rutas/misc.js +69 -0
- package/templates/backend/servicios/Nucleo/Miscelaneas.js +188 -22
- package/templates/backend/servicios/Nucleo/ReportePDF.js +1 -1
- package/templates/bd/docker-scripts/1-crear estructura.sql +8 -0
- package/templates/frontend/package.json +9 -8
- package/templates/frontend/public/Manual.md +1 -0
- package/templates/frontend/src/app/Componentes/Nucleo/gestion-actividad/gestion-actividad.component.ts +11 -3
- package/templates/frontend/src/app/Componentes/Nucleo/graficos/graficos.component.ts +2 -4
- package/templates/frontend/src/app/Componentes/Nucleo/manual/manual.component.css +318 -0
- package/templates/frontend/src/app/Componentes/Nucleo/manual/manual.component.html +43 -0
- package/templates/frontend/src/app/Componentes/Nucleo/manual/manual.component.ts +77 -0
- package/templates/frontend/src/app/Componentes/Nucleo/mensajes/mensajes.component.ts +5 -3
- package/templates/frontend/src/app/Componentes/Nucleo/reporte-de-incidencias/reporte-de-incidencias.component.ts +12 -4
- package/templates/frontend/src/app/Componentes/Nucleo/reporte-de-sugerencias/reporte-de-sugerencias.component.ts +12 -3
- package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.html +13 -10
- package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts +18 -6
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.html +2 -2
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.ts +9 -13
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-personalizada/tarjeta-personalizada.component.ts +7 -9
- package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.ts +1 -6
- package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.css +72 -0
- package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.html +17 -4
- package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.ts +45 -57
- package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.css +11 -0
- package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.html +4 -4
- package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.ts +65 -69
- package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.html +14 -3
- package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.ts +52 -14
- package/templates/frontend/src/app/app.routes.ts +4 -0
- package/templates/frontend/src/app/datos-globales.service.ts +4 -1
package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { Component, OnInit } from "@angular/core";
|
|
1
|
+
import { Component, OnInit, OnDestroy } from "@angular/core";
|
|
2
2
|
import { CommonModule } from "@angular/common";
|
|
3
|
+
import { Subject } from "rxjs";
|
|
4
|
+
import { takeUntil } from "rxjs/operators";
|
|
3
5
|
import { TarjetaComponent } from "../../Componentes/Nucleo/tarjeta/tarjeta.component";
|
|
4
6
|
import { TarjetaMultipleComponent } from "../../Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component";
|
|
5
7
|
import { TarjetaReporteComponent } from "../../Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component";
|
|
@@ -58,85 +60,79 @@ type AnyTarjetaConfig = TarjetaConfig | TarjetaMultipleConfig | TarjetaReporteCo
|
|
|
58
60
|
styleUrl: "./contenedor-principal.component.css"
|
|
59
61
|
})
|
|
60
62
|
|
|
61
|
-
export class ContenedorPrincipalComponent implements OnInit {
|
|
63
|
+
export class ContenedorPrincipalComponent implements OnInit, OnDestroy {
|
|
62
64
|
public cantidad: number = 0;
|
|
63
65
|
public cantidadMaxima: number = 0;
|
|
64
66
|
public tarjetas: AnyTarjetaConfig[] = [];
|
|
67
|
+
public filtro: string = '';
|
|
68
|
+
private destroy$ = new Subject<void>();
|
|
65
69
|
|
|
66
70
|
constructor(private http: HttpClient, private datosGlobalesService: DatosGlobalesService) {
|
|
67
71
|
this.cantidad = 0;
|
|
68
72
|
this.cantidadMaxima = 0;
|
|
69
73
|
}
|
|
70
74
|
|
|
75
|
+
ngOnDestroy(): void {
|
|
76
|
+
this.destroy$.next();
|
|
77
|
+
this.destroy$.complete();
|
|
78
|
+
}
|
|
71
79
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
];
|
|
86
|
-
|
|
87
|
-
// // 2. Check for extra permissions (Personas card)
|
|
88
|
-
// this.http.get(`${this.datosGlobalesService.ObtenerURL()}Personas/PermisoExtra`).subscribe({
|
|
89
|
-
// next: (datos: any) => {
|
|
90
|
-
// if (datos.body) {
|
|
91
|
-
// const personasCard: TarjetaMultipleConfig = {
|
|
92
|
-
// type: 'multiple',
|
|
93
|
-
// position: 25,
|
|
94
|
-
// titulo: 'Personas',
|
|
95
|
-
// descripcion: 'Módulo para el mantenimiento de los datos relacionados con personas',
|
|
96
|
-
// rutas: [
|
|
97
|
-
// { nombre: 'Personas', ruta: 'tablaPersonas' },
|
|
98
|
-
// { nombre: 'Correos', ruta: 'tablaCorreosPersonas' },
|
|
99
|
-
// { nombre: 'Cuentas bancarias', ruta: 'tablaCuentasPersonas' },
|
|
100
|
-
// { nombre: 'Teléfonos', ruta: 'tablaTelefonosPersonas' },
|
|
101
|
-
// { nombre: 'Ubicación', ruta: 'tablaUbicacionPersona' },
|
|
102
|
-
// ]
|
|
103
|
-
// };
|
|
104
|
-
// baseTarjetas.push(personasCard);
|
|
105
|
-
// }
|
|
106
|
-
// },
|
|
107
|
-
// error: (error) => {
|
|
108
|
-
// console.error('Problemas al intentar obtener los datos: ', error);
|
|
109
|
-
// this.tarjetas = baseTarjetas.sort((a, b) => a.position - b.position);
|
|
110
|
-
// },
|
|
111
|
-
// });
|
|
112
|
-
|
|
113
|
-
// 3. Load user-specific positions from backend
|
|
114
|
-
this.http.get(`${this.datosGlobalesService.ObtenerURL()}ConfiguracionDeTarjetas/obtener`).subscribe({
|
|
115
|
-
next: (res: any) => {
|
|
116
|
-
if (res.body && res.body.length > 0) {
|
|
117
|
-
const savedConfigs = res.body;
|
|
118
|
-
baseTarjetas.forEach(tarjeta => {
|
|
119
|
-
const config = savedConfigs.find((c: any) => c.Titulo === tarjeta.titulo);
|
|
120
|
-
if (config) {
|
|
121
|
-
tarjeta.position = config.Posicion;
|
|
122
|
-
if (config.ColorDeBorde) {
|
|
123
|
-
tarjeta.ColorDeBorde = config.ColorDeBorde;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
this.tarjetas = baseTarjetas.sort((a, b) => a.position - b.position);
|
|
80
|
+
esDimmed(tarjeta: AnyTarjetaConfig): boolean {
|
|
81
|
+
if (!this.filtro.trim()) return false;
|
|
82
|
+
return !tarjeta.titulo.toLowerCase().includes(this.filtro.toLowerCase());
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
ngOnInit() {
|
|
86
|
+
this.datosGlobalesService.filtroDeTarjetas$
|
|
87
|
+
.pipe(takeUntil(this.destroy$))
|
|
88
|
+
.subscribe(f => this.filtro = f);
|
|
89
|
+
|
|
90
|
+
this.http.get(`${this.datosGlobalesService.ObtenerURL()}misc/obtenerTarjetasDelContenedor`).subscribe({
|
|
91
|
+
next: (datos: any) => {
|
|
92
|
+
this.tarjetas = (datos.body ?? []).map((d: any) => this.mapearTarjeta(d));
|
|
129
93
|
},
|
|
130
94
|
error: (error) => {
|
|
131
|
-
console.error('Error al obtener
|
|
132
|
-
this.tarjetas =
|
|
95
|
+
console.error('Error al obtener las tarjetas del contenedor:', error);
|
|
96
|
+
this.tarjetas = [];
|
|
133
97
|
}
|
|
134
98
|
});
|
|
135
99
|
}
|
|
136
100
|
|
|
101
|
+
private mapearTarjeta(d: any): AnyTarjetaConfig {
|
|
102
|
+
const tipoMap: Record<string, AnyTarjetaConfig['type']> = {
|
|
103
|
+
'Única': 'single',
|
|
104
|
+
'Múltiple': 'multiple',
|
|
105
|
+
'Reporte': 'report',
|
|
106
|
+
'Personalizada': 'custom'
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const base = {
|
|
110
|
+
type: tipoMap[d.Tipo] ?? 'single',
|
|
111
|
+
position: d['Posición'],
|
|
112
|
+
titulo: d['Título'],
|
|
113
|
+
descripcion: d['Descripción'],
|
|
114
|
+
ColorDeBorde: d.ColorDeBorde
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
switch (d.Tipo) {
|
|
118
|
+
case 'Única':
|
|
119
|
+
return { ...base, type: 'single', rutaASeguir: d.RutaASeguir ?? '', icono: d['Ícono'] ?? '', cantidad: d.Cantidad, cantidadMaxima: d.CantidadMaxima } as TarjetaConfig;
|
|
120
|
+
case 'Múltiple':
|
|
121
|
+
return {
|
|
122
|
+
...base, type: 'multiple',
|
|
123
|
+
rutas: (d.Rutas ?? []).map((r: any) => ({ nombre: r.Nombre, ruta: r.Ruta }))
|
|
124
|
+
} as TarjetaMultipleConfig;
|
|
125
|
+
case 'Reporte':
|
|
126
|
+
return { ...base, type: 'report', reporteAGenerar: d.ReporteAGenerar ?? '', icono: d['Ícono'] ?? '' } as TarjetaReporteConfig;
|
|
127
|
+
case 'Personalizada':
|
|
128
|
+
return { ...base, type: 'custom', icono: d['Ícono'] ?? '', etiqueta: d.Etiqueta ?? '', accion: d['Acción'] ?? '' } as TarjetaPersonalizadaConfig;
|
|
129
|
+
default:
|
|
130
|
+
return base as any;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
137
134
|
drop(event: CdkDragDrop<AnyTarjetaConfig[]>) {
|
|
138
135
|
moveItemInArray(this.tarjetas, event.previousIndex, event.currentIndex);
|
|
139
|
-
// Update positions based on new order
|
|
140
136
|
this.tarjetas.forEach((tarjeta, index) => {
|
|
141
137
|
tarjeta.position = (index + 1) * 10;
|
|
142
138
|
});
|
|
@@ -159,6 +155,12 @@ export class ContenedorPrincipalComponent implements OnInit {
|
|
|
159
155
|
});
|
|
160
156
|
}
|
|
161
157
|
|
|
158
|
+
EjecutarAccionPersonalizada(accion: string) {
|
|
159
|
+
// if (accion === 'DescargarInformacionSociodemografica') {
|
|
160
|
+
// this.DescargarInformacionSociodemografica();
|
|
161
|
+
// }
|
|
162
|
+
}
|
|
163
|
+
|
|
162
164
|
GenerarReporte(event: { reporte: string }) {
|
|
163
165
|
if (event.reporte === 'ElReporte1') {
|
|
164
166
|
this.http.get(`${this.datosGlobalesService.ObtenerURL()}misc/DatosParaReporteCSV`, {
|
|
@@ -179,10 +181,4 @@ export class ContenedorPrincipalComponent implements OnInit {
|
|
|
179
181
|
});
|
|
180
182
|
}
|
|
181
183
|
}
|
|
182
|
-
|
|
183
|
-
EjecutarAccionPersonalizada(accion: string) {
|
|
184
|
-
// if (accion === 'DescargarInformacionSociodemografica') {
|
|
185
|
-
// this.DescargarInformacionSociodemografica();
|
|
186
|
-
// }
|
|
187
|
-
}
|
|
188
|
-
}
|
|
184
|
+
}
|
package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.html
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
<h1>Reportería del módulo</h1>
|
|
2
2
|
<div class="contenido">
|
|
3
3
|
<app-tarjeta-reporte [reporteAGenerar]="'ElReporte1'" titulo="Reporte número uno"
|
|
4
|
-
descripcion="
|
|
5
|
-
|
|
6
|
-
</
|
|
4
|
+
descripcion="Descarga un CSV con los datos de prueba del módulo." icono="pie_chart" ColorDeBorde="#3498db"
|
|
5
|
+
(GenerarReporte)="GenerarReporte($event)">
|
|
6
|
+
</app-tarjeta-reporte>
|
|
7
|
+
|
|
8
|
+
<app-tarjeta-reporte [reporteAGenerar]="'ReportePersonasHTML'" titulo="Reporte de personas"
|
|
9
|
+
descripcion="Abre un reporte HTML con el listado completo de personas registradas en el sistema." icono="people"
|
|
10
|
+
ColorDeBorde="#2ecc71" (GenerarReporte)="GenerarReporte($event)">
|
|
11
|
+
</app-tarjeta-reporte>
|
|
12
|
+
|
|
13
|
+
<app-tarjeta-reporte [reporteAGenerar]="'ReportePDF'" titulo="Reporte PDF de ejemplo"
|
|
14
|
+
descripcion="Abre un reporte PDF con el listado completo de personas registradas en el sistema."
|
|
15
|
+
icono="picture_as_pdf" ColorDeBorde="#e74c3c" (GenerarReporte)="GenerarReporte($event)">
|
|
16
|
+
</app-tarjeta-reporte>
|
|
17
|
+
</div>
|
package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.ts
CHANGED
|
@@ -17,20 +17,58 @@ export class GestionDeReportesComponent {
|
|
|
17
17
|
|
|
18
18
|
GenerarReporte(event: { reporte: string }) {
|
|
19
19
|
if (event.reporte === 'ElReporte1') {
|
|
20
|
-
this.
|
|
21
|
-
responseType: 'text'
|
|
22
|
-
}).subscribe({
|
|
23
|
-
next: (datos: any) => {
|
|
24
|
-
const blob = new Blob([decodeURIComponent(datos)], { type: 'text/csv;charset=utf-8;' });
|
|
25
|
-
const enlace = document.createElement('a');
|
|
26
|
-
enlace.href = URL.createObjectURL(blob);
|
|
27
|
-
enlace.download = 'datos.csv';
|
|
28
|
-
enlace.click();
|
|
29
|
-
},
|
|
30
|
-
error: (error) => {
|
|
31
|
-
console.error('Problemas al intentar descargar el reporte: ', error);
|
|
32
|
-
},
|
|
33
|
-
});
|
|
20
|
+
this.descargarCSV(`${this.datosGlobalesService.ObtenerURL()}misc/DatosParaReporteCSV`, 'datos.csv');
|
|
34
21
|
}
|
|
22
|
+
if (event.reporte === 'ReportePersonasHTML') {
|
|
23
|
+
this.abrirReporteHTML(`${this.datosGlobalesService.ObtenerURL()}Personas/reporteHTML`);
|
|
24
|
+
}
|
|
25
|
+
if (event.reporte === 'ReportePDF') {
|
|
26
|
+
this.abrirReportePDF(`${this.datosGlobalesService.ObtenerURL()}Personas/reportePDF`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private descargarCSV(url: string, nombreArchivo: string): void {
|
|
31
|
+
this.http.get(url, { responseType: 'text' }).subscribe({
|
|
32
|
+
next: (datos: any) => {
|
|
33
|
+
const blob = new Blob([decodeURIComponent(datos)], { type: 'text/csv;charset=utf-8;' });
|
|
34
|
+
const enlace = document.createElement('a');
|
|
35
|
+
enlace.href = URL.createObjectURL(blob);
|
|
36
|
+
enlace.download = nombreArchivo;
|
|
37
|
+
enlace.click();
|
|
38
|
+
URL.revokeObjectURL(enlace.href);
|
|
39
|
+
},
|
|
40
|
+
error: (error) => {
|
|
41
|
+
console.error('Problemas al intentar descargar el reporte: ', error);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private abrirReporteHTML(url: string): void {
|
|
47
|
+
this.http.get(url, { responseType: 'text' }).subscribe({
|
|
48
|
+
next: (html: string) => {
|
|
49
|
+
const nuevaPestana = window.open('', '_blank');
|
|
50
|
+
if (nuevaPestana) {
|
|
51
|
+
nuevaPestana.document.write(decodeURI(html));
|
|
52
|
+
nuevaPestana.document.close();
|
|
53
|
+
} else {
|
|
54
|
+
console.error('No se pudo abrir la nueva pestaña. Verifica que no esté bloqueada.');
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
error: (error) => {
|
|
58
|
+
console.error('Problemas al obtener el reporte HTML: ', error);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private abrirReportePDF(url: string): void {
|
|
64
|
+
this.http.get(url, { responseType: 'blob' }).subscribe({
|
|
65
|
+
next: (pdfBlob: Blob) => {
|
|
66
|
+
const urlBlob = window.URL.createObjectURL(pdfBlob);
|
|
67
|
+
window.open(urlBlob, '_blank');
|
|
68
|
+
},
|
|
69
|
+
error: (error) => {
|
|
70
|
+
console.error('Problemas al obtener el reporte PDF: ', error);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
35
73
|
}
|
|
36
74
|
}
|
|
@@ -9,6 +9,10 @@ export const routes: Routes = [
|
|
|
9
9
|
path: 'Actividad',
|
|
10
10
|
loadComponent: () => import('./Componentes/Nucleo/gestion-actividad/gestion-actividad.component').then(m => m.GestionActividadComponent)
|
|
11
11
|
},
|
|
12
|
+
{
|
|
13
|
+
path: 'manual',
|
|
14
|
+
loadComponent: () => import('./Componentes/Nucleo/manual/manual.component').then(m => m.ManualComponent)
|
|
15
|
+
},
|
|
12
16
|
{
|
|
13
17
|
path: 'tabla',
|
|
14
18
|
loadComponent: () => import('./Paginas/gestion-tabla/gestion-tabla.component').then(m => m.GestionTablaComponent)
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { Injectable } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
2
3
|
|
|
3
4
|
@Injectable({
|
|
4
5
|
providedIn: 'root'
|
|
5
6
|
})
|
|
6
7
|
export class DatosGlobalesService {
|
|
7
8
|
|
|
9
|
+
readonly filtroDeTarjetas$ = new BehaviorSubject<string>('');
|
|
10
|
+
|
|
8
11
|
constructor() { }
|
|
9
12
|
|
|
10
13
|
ObtenerToken() {
|
|
11
14
|
const baseUrl = this.ObtenerURL();
|
|
12
15
|
if (baseUrl === 'http://localhost/') {
|
|
13
|
-
return 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
|
|
16
|
+
return 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxMiIsIklkZW50aWZpY2Fkb3IiOiIxMiIsImlhdCI6MTc3Nzk4OTgwOSwiZXhwIjoxNzc4MDI1ODA5fQ.T1kUm7H4hwbapQ3eFok31GVvezkPitdTlJL96MorozY';
|
|
14
17
|
}
|
|
15
18
|
const match = document.cookie.match(/(?:^|;\s*)_siguid=([^;]+)/);
|
|
16
19
|
let token = match ? decodeURIComponent(match[1]) : '';
|