utn-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/commands/backend.js +282 -0
  2. package/commands/db.js +49 -0
  3. package/commands/frontend.js +225 -0
  4. package/index.js +98 -0
  5. package/package.json +27 -0
  6. package/templates/backend/InformacionDelModulo.json +21 -0
  7. package/templates/backend/NOMBRE_DEL_CANONICO_DEL_PROYECTO.rest +74 -0
  8. package/templates/backend/README.md +0 -0
  9. package/templates/backend/gitignore +3 -0
  10. package/templates/backend/index.rest +288 -0
  11. package/templates/backend/package.json +30 -0
  12. package/templates/backend/reporte.pdf +0 -0
  13. package/templates/backend/rutas/API.js +49 -0
  14. package/templates/backend/rutas/Servicio1.js +184 -0
  15. package/templates/backend/rutas/misc.js +671 -0
  16. package/templates/backend/rutas/rutas.js +11 -0
  17. package/templates/backend/server.js +79 -0
  18. package/templates/backend/servicios/API.js +101 -0
  19. package/templates/backend/servicios/InformacionDelModulo.js +70 -0
  20. package/templates/backend/servicios/Nucleo/EnvioDeCorreos.js +45 -0
  21. package/templates/backend/servicios/Nucleo/ManejadorDeErrores.js +54 -0
  22. package/templates/backend/servicios/Nucleo/Miscelaneas.js +1901 -0
  23. package/templates/backend/servicios/Nucleo/Monitoreo.js +65 -0
  24. package/templates/backend/servicios/Nucleo/db.js +78 -0
  25. package/templates/backend/servicios/Servicio1.js +118 -0
  26. package/templates/backend/variables-calidad.env +6 -0
  27. package/templates/backend/variables-desarrollo.env +6 -0
  28. package/templates/backend/variables-pruebas.env +6 -0
  29. package/templates/bd/README.md +78 -0
  30. package/templates/bd/cumulodb-scripts/gitignore +1 -0
  31. package/templates/bd/docker-compose.yml +28 -0
  32. package/templates/bd/docker-scripts/1-crear estructura.sql +29 -0
  33. package/templates/bd/docker-scripts/2-cambios estructura original.sql +1 -0
  34. package/templates/bd/docker-scripts/3-insertar datos de prueba.sql +1 -0
  35. package/templates/bd/docker-scripts/4-crear eventos y rutinas.sql +1 -0
  36. package/templates/bd/docker-scripts/5-crear vistas.sql +1 -0
  37. package/templates/bd/docker-scripts/6-calidad.sql +1 -0
  38. package/templates/bd/docker-scripts/7-pruebas.sql +1 -0
  39. package/templates/bd/docker-scripts/8-local.sql +1 -0
  40. package/templates/bd/servidores-scripts/calidad.sql +1 -0
  41. package/templates/bd/servidores-scripts/datos_iniciales_produccion.sql +1 -0
  42. package/templates/bd/servidores-scripts/produccion.sql +1 -0
  43. package/templates/bd/servidores-scripts/pruebas.sql +1 -0
  44. package/templates/frontend/.vscode/extensions.json +4 -0
  45. package/templates/frontend/.vscode/launch.json +20 -0
  46. package/templates/frontend/.vscode/tasks.json +42 -0
  47. package/templates/frontend/Dockerfile +5 -0
  48. package/templates/frontend/README.md +59 -0
  49. package/templates/frontend/angular.json +101 -0
  50. package/templates/frontend/dist/frontend/3rdpartylicenses.txt +459 -0
  51. package/templates/frontend/dist/frontend/prerendered-routes.json +3 -0
  52. package/templates/frontend/docker-compose.yml +5 -0
  53. package/templates/frontend/editorconfig +17 -0
  54. package/templates/frontend/gitignore +45 -0
  55. package/templates/frontend/nginx.conf +12 -0
  56. package/templates/frontend/package.json +46 -0
  57. package/templates/frontend/public/favicon.ico +0 -0
  58. package/templates/frontend/src/app/Componentes/Nucleo/graficos/graficos.component.css +15 -0
  59. package/templates/frontend/src/app/Componentes/Nucleo/graficos/graficos.component.html +25 -0
  60. package/templates/frontend/src/app/Componentes/Nucleo/graficos/graficos.component.ts +80 -0
  61. package/templates/frontend/src/app/Componentes/Nucleo/iframe/iframe.ts +37 -0
  62. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion/mensaje-confirmacion.component.css +5 -0
  63. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion/mensaje-confirmacion.component.html +22 -0
  64. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion/mensaje-confirmacion.ts +64 -0
  65. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion-html/mensaje-confirmacion-html.component.css +5 -0
  66. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion-html/mensaje-confirmacion-html.component.html +22 -0
  67. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion-html/mensaje-confirmacion-html.ts +64 -0
  68. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-informacion/mensaje-informacion.component.css +5 -0
  69. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-informacion/mensaje-informacion.component.html +11 -0
  70. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-informacion/mensaje-informacion.ts +46 -0
  71. package/templates/frontend/src/app/Componentes/Nucleo/mensajes/mensajes.component.css +11 -0
  72. package/templates/frontend/src/app/Componentes/Nucleo/mensajes/mensajes.component.html +17 -0
  73. package/templates/frontend/src/app/Componentes/Nucleo/mensajes/mensajes.component.ts +43 -0
  74. package/templates/frontend/src/app/Componentes/Nucleo/reporte-de-incidencias/reporte-de-incidencias.component.css +37 -0
  75. package/templates/frontend/src/app/Componentes/Nucleo/reporte-de-incidencias/reporte-de-incidencias.component.html +35 -0
  76. package/templates/frontend/src/app/Componentes/Nucleo/reporte-de-incidencias/reporte-de-incidencias.component.ts +103 -0
  77. package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.css +90 -0
  78. package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.html +39 -0
  79. package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts +132 -0
  80. package/templates/frontend/src/app/Componentes/Nucleo/tabla/paginador-personalizado.ts +17 -0
  81. package/templates/frontend/src/app/Componentes/Nucleo/tabla/tabla.component.css +332 -0
  82. package/templates/frontend/src/app/Componentes/Nucleo/tabla/tabla.component.html +166 -0
  83. package/templates/frontend/src/app/Componentes/Nucleo/tabla/tabla.component.ts +228 -0
  84. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.css +129 -0
  85. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.html +35 -0
  86. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.ts +46 -0
  87. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-modulo/tarjeta-modulo.component.css +92 -0
  88. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-modulo/tarjeta-modulo.component.html +17 -0
  89. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-modulo/tarjeta-modulo.component.ts +42 -0
  90. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.css +90 -0
  91. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.html +22 -0
  92. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.ts +46 -0
  93. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.css +129 -0
  94. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.html +20 -0
  95. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.ts +25 -0
  96. package/templates/frontend/src/app/Componentes/guardar-incapacidad/guardar-incapacidad.component.css +20 -0
  97. package/templates/frontend/src/app/Componentes/guardar-incapacidad/guardar-incapacidad.component.html +46 -0
  98. package/templates/frontend/src/app/Componentes/guardar-incapacidad/guardar-incapacidad.component.ts +64 -0
  99. package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.css +142 -0
  100. package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.html +90 -0
  101. package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.ts +139 -0
  102. package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.css +4 -0
  103. package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.html +17 -0
  104. package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.ts +36 -0
  105. package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.css +4 -0
  106. package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.html +6 -0
  107. package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.ts +36 -0
  108. package/templates/frontend/src/app/Paginas/gestion-graficos/gestion-graficos.component.css +13 -0
  109. package/templates/frontend/src/app/Paginas/gestion-graficos/gestion-graficos.component.html +13 -0
  110. package/templates/frontend/src/app/Paginas/gestion-graficos/gestion-graficos.component.ts +75 -0
  111. package/templates/frontend/src/app/Paginas/gestion-iframe1/gestion-iframe1.component.css +13 -0
  112. package/templates/frontend/src/app/Paginas/gestion-iframe1/gestion-iframe1.component.html +3 -0
  113. package/templates/frontend/src/app/Paginas/gestion-iframe1/gestion-iframe1.component.ts +14 -0
  114. package/templates/frontend/src/app/Paginas/gestion-tabla/gestion-tabla.component.css +13 -0
  115. package/templates/frontend/src/app/Paginas/gestion-tabla/gestion-tabla.component.html +24 -0
  116. package/templates/frontend/src/app/Paginas/gestion-tabla/gestion-tabla.component.ts +300 -0
  117. package/templates/frontend/src/app/Paginas/gestion-tabla-XYZ/gestion-tabla-XYZ.component.css +13 -0
  118. package/templates/frontend/src/app/Paginas/gestion-tabla-XYZ/gestion-tabla-XYZ.component.html +43 -0
  119. package/templates/frontend/src/app/Paginas/gestion-tabla-XYZ/gestion-tabla-XYZ.component.ts +305 -0
  120. package/templates/frontend/src/app/Paginas/gestion-tabla-jefe/gestion-tabla-jefe.component.css +13 -0
  121. package/templates/frontend/src/app/Paginas/gestion-tabla-jefe/gestion-tabla-jefe.component.html +25 -0
  122. package/templates/frontend/src/app/Paginas/gestion-tabla-jefe/gestion-tabla-jefe.component.ts +245 -0
  123. package/templates/frontend/src/app/analytics.module.ts +45 -0
  124. package/templates/frontend/src/app/app.component.css +0 -0
  125. package/templates/frontend/src/app/app.component.html +1 -0
  126. package/templates/frontend/src/app/app.component.ts +10 -0
  127. package/templates/frontend/src/app/app.config.server.ts +14 -0
  128. package/templates/frontend/src/app/app.config.ts +27 -0
  129. package/templates/frontend/src/app/app.routes.ts +16 -0
  130. package/templates/frontend/src/app/auth.interceptor.ts +26 -0
  131. package/templates/frontend/src/app/datos-globales.service.ts +45 -0
  132. package/templates/frontend/src/assets/Puntos.svg +94 -0
  133. package/templates/frontend/src/index.html +36 -0
  134. package/templates/frontend/src/main.server.ts +7 -0
  135. package/templates/frontend/src/main.ts +6 -0
  136. package/templates/frontend/src/styles.css +14 -0
  137. package/templates/frontend/tsconfig.app.json +15 -0
  138. package/templates/frontend/tsconfig.json +27 -0
  139. package/templates/frontend/tsconfig.spec.json +15 -0
  140. package/utils/index.js +105 -0
@@ -0,0 +1,166 @@
1
+ <div class="encabezado">
2
+ <div class="izquierda">
3
+ @if(mostrarElBotonDeDescargar){
4
+ <button mat-flat-button class="descargar" (click)="DescargarInformacion.emit()">Descargar información</button>
5
+ }
6
+ @if(mostrarElBotonDeGuardado) {
7
+ <button mat-flat-button class="descargar" (click)="GuardarAccion.emit()">Agregar registro</button>
8
+ }
9
+ </div>
10
+ <div class="centro"></div>
11
+ <div class="derecha">
12
+ <input #valorFiltroInput id="valorFiltro" type="text" class="custom-input" placeholder="Filtrar"
13
+ (keydown.enter)="AplicarFiltro()">
14
+ @if(mostrarElBotonDeFiltro){
15
+ <mat-select class="custom-input" [(value)]="columnaSeleccionada" placeholder="Columna para filtrar">
16
+ <mat-option [value]="'Todas'">Todas</mat-option>
17
+ @for(columna of columnas; track $index){
18
+ @if(columna.TipoDeFiltro === 'Tabla' && !paginarResultados) {
19
+ <mat-option [value]="columna.Llave">{{columna.Alias}}</mat-option>
20
+ }
21
+ @if(columna.TipoDeFiltro === 'BaseDeDatos' && paginarResultados) {
22
+ <mat-option [value]="columna.Llave">{{columna.Alias}}</mat-option>
23
+ }
24
+ }
25
+ </mat-select>
26
+ <button mat-flat-button class="descargar" (click)="AplicarFiltro()">Filtrar</button>
27
+ }
28
+ </div>
29
+ </div>
30
+ <table mat-table [dataSource]="dataSource" matSort multiTemplateDataRows class="mat-elevation-z8">
31
+ @for(columna of columnas;track $index){
32
+ @if(columna.Llave!=='Estado'){
33
+ <ng-container [matColumnDef]="columna.Llave">
34
+ <th mat-header-cell *matHeaderCellDef mat-sort-header> {{columna.Alias}} </th>
35
+ <td mat-cell *matCellDef="let element" [attr.data-label]="columna.Alias"> {{element[columna.Llave]}} </td>
36
+ </ng-container>
37
+ }
38
+ }
39
+ @if(tieneColumnaEstado) {
40
+ <ng-container matColumnDef="Estado">
41
+ <th mat-header-cell *matHeaderCellDef mat-sort-header>Estado</th>
42
+ <td mat-cell *matCellDef="let element" data-label="Estado">
43
+ <div [class]="element.Estado">{{ element.Estado }}</div>
44
+ </td>
45
+ </ng-container>
46
+ }
47
+ @if(acciones.length>0 || accionesSiempreClickeable.length>0 || accionesDinamicas.length>0){
48
+ <ng-container matColumnDef="acciones">
49
+ <th mat-header-cell *matHeaderCellDef>Acciones</th>
50
+ <td mat-cell *matCellDef="let element">
51
+ <ng-container>
52
+ @for(accion of accionesDinamicas; track $index){
53
+ @if(accion.Mostrar(element)){
54
+ <button mat-icon-button (click)="accion.ejecutar(element)" [matTooltip]="accion.textoAyuda"
55
+ [matBadge]="accion.badge?.(element)" [matBadgeHidden]="!accion.badge || !accion.badge(element)"
56
+ matBadgeColor="warn" matBadgeSize="large">
57
+ <mat-icon [class]="accion.color">{{accion.icono}}</mat-icon>
58
+ </button>
59
+ }
60
+ }
61
+ @for(accion of acciones; track $index){
62
+ <button mat-icon-button (click)="accion.ejecutar(element)" [matTooltip]="accion.textoAyuda"
63
+ [disabled]="!estadosQuePermitenEdicion.includes(element.Estado)" [matBadge]="accion.badge?.(element)"
64
+ [matBadgeHidden]="!accion.badge || !accion.badge(element)" matBadgeColor="warn" matBadgeSize="large">
65
+ <mat-icon
66
+ [class]="!estadosQuePermitenEdicion.includes(element.Estado) ? 'color: gray' : accion.color">{{accion.icono}}</mat-icon>
67
+ </button>
68
+ }
69
+ @for(accionSiempreClickeable of accionesSiempreClickeable; track $index){
70
+ <button mat-icon-button (click)="accionSiempreClickeable.ejecutar(element)"
71
+ [matTooltip]="accionSiempreClickeable.textoAyuda" [matBadge]="accionSiempreClickeable.badge?.(element)"
72
+ [matBadgeHidden]="!accionSiempreClickeable.badge || !accionSiempreClickeable.badge(element)"
73
+ matBadgeColor="warn" matBadgeSize="large">
74
+ <mat-icon [class]="accionSiempreClickeable.color">{{accionSiempreClickeable.icono}}</mat-icon>
75
+ </button>
76
+ }
77
+ </ng-container>
78
+ </td>
79
+ </ng-container>
80
+ }
81
+ @if(desplegable){
82
+ <ng-container matColumnDef="expand">
83
+ <th mat-header-cell *matHeaderCellDef aria-label="Fila expandible"></th>
84
+ <td mat-cell *matCellDef="let element">
85
+ <button mat-icon-button aria-label="Expander fila"
86
+ (click)="(elementoExpandible = elementoExpandible === element ? null : element); $event.stopPropagation()">
87
+ @if (elementoExpandible === element) {
88
+ <mat-icon>keyboard_arrow_up</mat-icon>
89
+ } @else {
90
+ <mat-icon>keyboard_arrow_down</mat-icon>
91
+ }
92
+ </button>
93
+ </td>
94
+ </ng-container>
95
+ <ng-container matColumnDef="expandedDetail">
96
+ <td mat-cell *matCellDef="let element" [attr.colspan]="llavesColumnas.length">
97
+ <div class="example-element-detail" [@detailExpand]="element == elementoExpandible ? 'expanded' : 'collapsed'">
98
+ <table mat-table [dataSource]="element[atributoDesplegable]" multiTemplateDataRows
99
+ class="mat-elevation-z8 separador">
100
+ @for (column of subColumnas; track $index) {
101
+ <ng-container matColumnDef="{{column.Llave}}">
102
+ <th mat-header-cell *matHeaderCellDef> {{column.Alias}} </th>
103
+ <td mat-cell *matCellDef="let elementTwo" [attr.data-label]="column.Alias"> {{elementTwo[column.Llave]}}
104
+ </td>
105
+ </ng-container>
106
+ }
107
+ @if(subAcciones.length>0 ||subAccionesSiempreClickeable.length>0){
108
+ <ng-container matColumnDef="subAcciones">
109
+ <th mat-header-cell *matHeaderCellDef>Acciones</th>
110
+ <td mat-cell *matCellDef="let elementTwo">
111
+ <ng-container>
112
+ @for(subAccion of subAccionesDinamicas; track $index){
113
+ @if(subAccion.Mostrar(elementTwo)){
114
+ <button mat-icon-button (click)="subAccion.ejecutar(elementTwo)" [matTooltip]="subAccion.textoAyuda"
115
+ [matBadge]="subAccion.badge?.(element)"
116
+ [matBadgeHidden]="!subAccion.badge || !subAccion.badge(element)" matBadgeColor="warn"
117
+ matBadgeSize="large">
118
+ <mat-icon [class]="subAccion.color">{{subAccion.icono}}</mat-icon>
119
+ </button>
120
+ }
121
+ }
122
+ @for(subAccion of subAcciones; track $index){
123
+ <button mat-icon-button (click)="subAccion.ejecutar(elementTwo)" [matTooltip]="subAccion.textoAyuda"
124
+ [disabled]="!subEstadosQuePermitenEdicion.includes(elementTwo.Estado)"
125
+ [matBadge]="subAccion.badge?.(element)"
126
+ [matBadgeHidden]="!subAccion.badge || !subAccion.badge(element)" matBadgeColor="warn"
127
+ matBadgeSize="large">
128
+ <mat-icon
129
+ [class]="!subEstadosQuePermitenEdicion.includes(elementTwo.Estado) ? 'color: gray' : subAccion.color">{{subAccion.icono}}</mat-icon>
130
+ </button>
131
+ }
132
+ @for(accionSiempreClickeable of subAccionesSiempreClickeable; track $index){
133
+ <button mat-icon-button (click)="accionSiempreClickeable.ejecutar(elementTwo)"
134
+ [matTooltip]="accionSiempreClickeable.textoAyuda"
135
+ [matBadge]="accionSiempreClickeable.badge?.(element)"
136
+ [matBadgeHidden]="!accionSiempreClickeable.badge || !accionSiempreClickeable.badge(element)"
137
+ matBadgeColor="warn" matBadgeSize="large">
138
+ <mat-icon [class]="accionSiempreClickeable.color">{{accionSiempreClickeable.icono}}</mat-icon>
139
+ </button>
140
+ }
141
+ </ng-container>
142
+ </td>
143
+ </ng-container>
144
+ }
145
+ <tr mat-header-row *matHeaderRowDef="llavesSubColumnas"></tr>
146
+ <tr mat-row *matRowDef="let element; columns: llavesSubColumnas;" class="example-element-row"></tr>
147
+ </table>
148
+ </div>
149
+ </td>
150
+ </ng-container>
151
+ }
152
+ <tr mat-header-row *matHeaderRowDef="llavesColumnas"></tr>
153
+ <tr mat-row *matRowDef="let row; columns: llavesColumnas;" class="example-element-row"
154
+ [class.example-expanded-row]="elementoExpandible === row"
155
+ [style.background-color]="row.ColorDeFondo ? row.Color : null">
156
+ </tr>
157
+ @if(desplegable){
158
+ <tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"
159
+ [class.detalle-oculto]="row !== elementoExpandible" [style.background-color]="row.ColorDeFondo ? row.Color : null">
160
+ </tr>
161
+ }
162
+ </table>
163
+ @if(mostrarPaginador){
164
+ <mat-paginator [length]="TotalDeRegistros" [pageSize]="valorSeleccionadoPorElUsuario"
165
+ [pageSizeOptions]="[5,10,15,20,50,100]" showFirstLastButtons></mat-paginator>
166
+ }
@@ -0,0 +1,228 @@
1
+ import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
2
+ import { MatTableDataSource, MatTableModule } from '@angular/material/table';
3
+ import { MatIconModule } from '@angular/material/icon';
4
+ import { MatButtonModule } from '@angular/material/button';
5
+ import { MatTooltip } from '@angular/material/tooltip';
6
+ import { MatPaginator, MatPaginatorModule, PageEvent } from '@angular/material/paginator';
7
+ import { MatSort, MatSortModule } from '@angular/material/sort';
8
+ import { MatInputModule } from '@angular/material/input';
9
+ import { animate, state, style, transition, trigger } from '@angular/animations';
10
+ import { MatSelectModule } from '@angular/material/select';
11
+ import { MensajeConfirmacionComponent } from '../mensaje-confirmacion/mensaje-confirmacion';
12
+ import { MatDialog } from '@angular/material/dialog';
13
+ import { MatBadgeModule } from '@angular/material/badge';
14
+
15
+ @Component({
16
+ selector: 'app-tabla',
17
+ animations: [
18
+ trigger('detailExpand', [
19
+ state('collapsed,void', style({ height: '0px', minHeight: '0' })),
20
+ state('expanded', style({ height: '*' })),
21
+ transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
22
+ ]),
23
+ ],
24
+
25
+ imports: [
26
+ MatTableModule,
27
+ MatIconModule,
28
+ MatButtonModule,
29
+ MatTooltip,
30
+ MatPaginatorModule,
31
+ MatSortModule,
32
+ MatInputModule,
33
+ MatSelectModule,
34
+ MatBadgeModule],
35
+ templateUrl: './tabla.component.html',
36
+ styleUrl: './tabla.component.css'
37
+ })
38
+ export class TablaComponent implements OnInit, OnChanges {
39
+ @Input() columnas: { Llave: string, Alias: string, TipoDeFiltro: string }[] = [];
40
+ @Input() subColumnas: { Llave: string, Alias: string }[] = [];
41
+ @Input() datos: any[] = [];
42
+ @Input() acciones: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; }[] = [];
43
+ @Input() accionesDinamicas: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; Mostrar: (row: any) => boolean }[] = [];
44
+ @Input() accionesSiempreClickeable: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; }[] = [];
45
+ @Input() subAcciones: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; }[] = [];
46
+ @Input() subAccionesSiempreClickeable: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; }[] = [];
47
+ @Input() subAccionesDinamicas: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; Mostrar: (row: any) => boolean }[] = [];
48
+ @Input() desplegable: boolean = false
49
+ @Input() atributoDesplegable: string = ''
50
+ public llavesColumnas: string[] = [];
51
+ public llavesSubColumnas: string[] = [];
52
+ public elementoExpandible: any;
53
+ public columnaSeleccionada: string = '';
54
+
55
+ public dataSource: any;
56
+ public tieneColumnaEstado: boolean = false;
57
+ public valorSeleccionadoPorElUsuario: number = 5;
58
+ @Input() public mostrarElBotonDeGuardado: boolean = true;
59
+ @Input() public mostrarElBotonDeDescargar: boolean = true;
60
+ @Input() public mostrarElBotonDeFiltro: boolean = true;
61
+ @Input() public mostrarPaginador: boolean = true;
62
+ @Input() public estadosQuePermitenEdicion: string[] = [];
63
+ @Input() public subEstadosQuePermitenEdicion: string[] = [];
64
+
65
+ @ViewChild(MatSort) sort!: MatSort;
66
+ @ViewChild(MatPaginator) paginator!: MatPaginator;
67
+ @Output() GuardarAccion: EventEmitter<any> = new EventEmitter<any>();
68
+ @Output() DescargarInformacion: EventEmitter<any> = new EventEmitter<any>();
69
+ @ViewChild('valorFiltroInput') filtroInput!: ElementRef<HTMLInputElement>;
70
+ private ultimaPagina = 0;
71
+ private ultimoPageSize = this.valorSeleccionadoPorElUsuario;
72
+ @Input() public paginarResultados: boolean = true;
73
+ @Input() TotalDeRegistros: number = 0;
74
+ @Output() CambioDePagina: EventEmitter<{ accion: string, pageIndex: number, pageSize: number, valorParaFiltrar: string, columnaParaFiltrar: string, columnasParaFiltrar: string, ordenColumna: string, ordenDireccion: string }> = new EventEmitter();
75
+
76
+ constructor(private dialog: MatDialog) {
77
+ const pageSize = localStorage.getItem('pageSize');
78
+ if (pageSize) {
79
+ this.valorSeleccionadoPorElUsuario = parseInt(pageSize);
80
+ }
81
+ }
82
+
83
+ ngOnChanges(changes: SimpleChanges): void {
84
+ if (changes['datos']) {
85
+ this.actualizarDataSource();
86
+ }
87
+ }
88
+
89
+ ngOnInit(): void {
90
+ this.inicializarColumnas();
91
+ this.actualizarDataSource();
92
+ }
93
+
94
+ AplicarFiltro() {
95
+ const filtro = this.filtroInput.nativeElement.value.trim().toLowerCase();
96
+
97
+ if (!this.columnaSeleccionada || this.columnaSeleccionada.trim() === '') {
98
+ this.dialog.open(MensajeConfirmacionComponent, {
99
+ data: {
100
+ titulo: 'Selección de columna',
101
+ mensaje: `Debe seleccionar una columna`,
102
+ textoCerrar: 'Aceptar',
103
+ onClose: () => { },
104
+ onAccept: () => { },
105
+ },
106
+ });
107
+ return;
108
+ }
109
+
110
+ if (this.paginarResultados) {
111
+ this.ultimaPagina = 0;
112
+ this.paginator.firstPage();
113
+
114
+ this.CambioDePagina.emit({
115
+ accion: 'Filtrado de base de datos',
116
+ pageIndex: 0,
117
+ pageSize: this.ultimoPageSize,
118
+ valorParaFiltrar: filtro,
119
+ columnaParaFiltrar: this.columnaSeleccionada,
120
+ columnasParaFiltrar: this.columnas
121
+ .filter(c => c.TipoDeFiltro !== 'Ninguno')
122
+ .map(c => c.Llave)
123
+ .join(','),
124
+ ordenColumna: this.sort.active,
125
+ ordenDireccion: this.sort.direction
126
+ });
127
+ } else {
128
+ // Caso: paginación local
129
+ if (this.columnaSeleccionada && this.columnaSeleccionada !== 'Todas') {
130
+ this.dataSource.filterPredicate = (dato: any, f: string) => {
131
+ const valorColumna = dato[this.columnaSeleccionada];
132
+ return valorColumna?.toString().toLowerCase().includes(f);
133
+ };
134
+ } else {
135
+ this.dataSource.filterPredicate = (dato: any, f: string) => {
136
+ const textoPlano = Object.values(dato).join(' ').toLowerCase();
137
+ return textoPlano.includes(f);
138
+ };
139
+ }
140
+
141
+ this.dataSource.filter = filtro;
142
+
143
+ if (this.dataSource.paginator) {
144
+ this.dataSource.paginator.firstPage();
145
+ }
146
+ }
147
+ }
148
+
149
+ private inicializarColumnas(): void {
150
+ this.llavesColumnas = this.columnas.map(c => c.Llave);
151
+ this.tieneColumnaEstado = this.columnas.some(c => c.Llave === 'Estado');
152
+
153
+ if (this.acciones.length || this.accionesSiempreClickeable.length || this.accionesDinamicas.length) {
154
+ this.llavesColumnas.push('acciones');
155
+ }
156
+
157
+ if (this.desplegable) {
158
+ this.llavesColumnas.unshift('expand');
159
+ this.llavesSubColumnas = this.subColumnas.map(c => c.Llave);
160
+ if (this.subAcciones.length || this.subAccionesSiempreClickeable.length) {
161
+ this.llavesSubColumnas.push('subAcciones');
162
+ }
163
+ }
164
+ }
165
+
166
+ private actualizarDataSource(): void {
167
+ const paginaActual = this.paginator ? this.paginator.pageIndex : 0;
168
+ const tamanioPagina = this.paginator ? this.paginator.pageSize : this.valorSeleccionadoPorElUsuario;
169
+
170
+ this.dataSource = new MatTableDataSource(this.datos);
171
+
172
+ if (!this.paginarResultados && this.paginator) {
173
+ this.dataSource.paginator = this.paginator;
174
+ }
175
+ if (this.sort) {
176
+ this.dataSource.sort = this.sort;
177
+ }
178
+ if (this.paginarResultados && this.paginator) {
179
+ this.paginator.pageIndex = paginaActual;
180
+ this.paginator.pageSize = tamanioPagina;
181
+ }
182
+ }
183
+
184
+ ngAfterViewInit() {
185
+ this.dataSource.sort = this.sort;
186
+ this.paginator.page.subscribe((event: PageEvent) => {
187
+ localStorage.setItem('pageSize', event.pageSize.toString());
188
+
189
+ let accion = '';
190
+ if (event.pageSize !== this.ultimoPageSize) {
191
+ accion = 'Cambio de tamaño';
192
+ } else if (event.pageIndex > this.ultimaPagina) {
193
+ accion = event.pageIndex === this.paginator.getNumberOfPages() - 1 ? 'Última página' : 'Siguiente página';
194
+ } else if (event.pageIndex < this.ultimaPagina) {
195
+ accion = event.pageIndex === 0 ? 'Primera página' : 'Página anterior';
196
+ }
197
+
198
+ this.CambioDePagina.emit({
199
+ accion: 'Cambio de orden',
200
+ pageIndex: event.pageIndex,
201
+ pageSize: event.pageSize,
202
+ valorParaFiltrar: this.filtroInput.nativeElement.value.trim().toLowerCase(),
203
+ columnaParaFiltrar: this.columnaSeleccionada,
204
+ columnasParaFiltrar: this.columnas.map(c => c.Llave).join(','),
205
+ ordenColumna: this.sort.active,
206
+ ordenDireccion: this.sort.direction
207
+ });
208
+
209
+ this.ultimaPagina = event.pageIndex;
210
+ this.ultimoPageSize = event.pageSize;
211
+ });
212
+ this.sort.sortChange.subscribe(sort => {
213
+ if (this.paginarResultados) {
214
+ this.CambioDePagina.emit({
215
+ accion: 'Cambio de orden',
216
+ pageIndex: this.paginator.pageIndex,
217
+ pageSize: this.paginator.pageSize,
218
+ valorParaFiltrar: this.filtroInput.nativeElement.value.trim().toLowerCase(),
219
+ columnaParaFiltrar: this.columnaSeleccionada,
220
+ columnasParaFiltrar: this.columnas.map(c => c.Llave).join(','),
221
+ ordenColumna: sort.active,
222
+ ordenDireccion: sort.direction
223
+ });
224
+ }
225
+ });
226
+ this.actualizarDataSource();
227
+ }
228
+ }
@@ -0,0 +1,129 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ .contenedor {
8
+ margin-top: 3%;
9
+ width: 20vw;
10
+ background: #ffffff 0% 0% no-repeat padding-box;
11
+ box-shadow: 0px 3px 6px #00000029;
12
+ border-radius: 10px;
13
+ opacity: 1;
14
+ margin-right: 3vw;
15
+ padding: 5%;
16
+ cursor: pointer;
17
+ }
18
+
19
+ @media (max-width:480px) {
20
+ .contenedor {
21
+ width: 80vw;
22
+ }
23
+ }
24
+
25
+ @media (min-width:481px) and (max-width:1025px) {
26
+ .contenedor {
27
+ width: 50vw;
28
+ }
29
+ }
30
+
31
+ .contenedor .cabecera_contenedor {
32
+ display: flex;
33
+ flex-direction: row;
34
+ }
35
+
36
+ .contenedor .cabecera_contenedor .icono {
37
+ background: #eef2ff 0% 0% no-repeat padding-box;
38
+ opacity: 1;
39
+ border-radius: 50%;
40
+ display: flex;
41
+ align-items: center;
42
+ transform: translate(0);
43
+ height: 75%;
44
+ color: #1b3069;
45
+ font-size: x-small;
46
+ font-weight: bold;
47
+ margin-left: 5%;
48
+ padding: 2%;
49
+ }
50
+
51
+ .contenedor .cabecera_contenedor .icono .numero {
52
+ font-size: large;
53
+ }
54
+
55
+ .contenedor .cabecera {
56
+ width: 90%;
57
+ }
58
+
59
+ .contenedor .cabecera .titulo {
60
+ text-align: left;
61
+ font-family: "Roboto";
62
+ font-size: large;
63
+ font-weight: 600;
64
+ letter-spacing: 0px;
65
+ color: #000000;
66
+ opacity: 1;
67
+ }
68
+
69
+ .contenedor .cabecera .descripcion {
70
+ text-align: left;
71
+ font-family: "Roboto";
72
+ font-size: small;
73
+ letter-spacing: 0px;
74
+ color: #000000;
75
+ opacity: 1;
76
+ }
77
+
78
+ .contenedor .contenido {
79
+ text-align: left;
80
+ font-family: "Roboto";
81
+ font-size: small;
82
+ letter-spacing: 0px;
83
+ color: #000000;
84
+ opacity: 1;
85
+ margin-left: 3%;
86
+ margin-top: 5%;
87
+ }
88
+
89
+ .contenedor .cantidad {
90
+ min-height: 20px;
91
+ width: 100%;
92
+ justify-content: center;
93
+ font-family: "Roboto";
94
+ font-size: large;
95
+ font-weight: 600;
96
+ letter-spacing: 0px;
97
+ color: #000000;
98
+ opacity: 1;
99
+ }
100
+
101
+ .contenedor .izquierda {
102
+ margin-top: 20%;
103
+ align-items: start;
104
+ color: #1b3069;
105
+ font-weight: 700;
106
+ }
107
+
108
+ .contenedor .pie {
109
+ border-top: 2px solid #eef2ff;
110
+ opacity: 1;
111
+ padding: 5%;
112
+ position: relative;
113
+ }
114
+
115
+ .contenedor .linea {
116
+ width: 0%;
117
+ border: 1px solid #95d03a;
118
+ opacity: 1;
119
+ }
120
+
121
+ .contenedor .pie p {
122
+ text-align: left;
123
+ font: normal normal normal 15px/20px Roboto;
124
+ letter-spacing: 0px;
125
+ color: #1b3069;
126
+ opacity: 1;
127
+ font-size: small;
128
+ text-decoration: none;
129
+ }
@@ -0,0 +1,35 @@
1
+ <div class="contenedor" (click)="onClick()">
2
+ <div class="cabecera_contenedor">
3
+ <div class="cabecera">
4
+ <p class="titulo">
5
+ {{ titulo }}
6
+ </p>
7
+ <p class="descripcion">
8
+ {{ descripcion }}
9
+ </p>
10
+ </div>
11
+ <div class="icono">
12
+ @if(icono){
13
+ <mat-icon [fontIcon]="icono"></mat-icon>
14
+ } @if(numero){
15
+ <p class="numero">{{ numero }}</p>
16
+ }
17
+ </div>
18
+ </div>
19
+ <div class="contenido">
20
+ @if(contenido.length>0){ @for(item of contenido[0];track item){
21
+ <p>{{ item }}</p>
22
+ }
23
+ <hr />
24
+ @for(item of contenido[1];track item){
25
+ <p>{{ item }}</p>
26
+ } }
27
+ </div>
28
+ <div [class]="cantidadLugar">
29
+ <p>{{ (cantidadAMostrar !== 0 ? cantidadAMostrar : '') }}</p>
30
+ </div>
31
+ <hr [id]="'porcentaje'+titulo" class="linea" [matTooltip]="'Cantidad: ' + cantidad" matTooltipPosition="above"/>
32
+ <div class="pie">
33
+ <p>CONTINUAR</p>
34
+ </div>
35
+ </div>
@@ -0,0 +1,46 @@
1
+ import { AfterViewInit, Component, Input } from "@angular/core";
2
+ import { MatIconModule } from "@angular/material/icon";
3
+ import { MatCardModule } from "@angular/material/card";
4
+ import { MatTooltipModule } from "@angular/material/tooltip";
5
+ import { Router } from "@angular/router";
6
+
7
+ @Component({
8
+ selector: "app-tarjeta",
9
+ standalone: true,
10
+ imports: [MatIconModule, MatCardModule, MatTooltipModule],
11
+ templateUrl: "./tarjeta.component.html",
12
+ styleUrl: "./tarjeta.component.css"
13
+ })
14
+ export class TarjetaComponent implements AfterViewInit {
15
+ @Input() titulo: string = "";
16
+ @Input() descripcion: string = "";
17
+ @Input() icono: any = null;
18
+ @Input() numero: any = null;
19
+ @Input() contenido: any = [];
20
+ @Input() cantidad: number | undefined;
21
+ @Input() cantidadLugar: string = "cantidad";
22
+ @Input() rutaASeguir: string = '';
23
+ @Input() cantidadMaxima: number | undefined;
24
+ @Input() cantidadAMostrar: number = 0;
25
+
26
+ constructor(private ruta: Router) { }
27
+
28
+ onClick() {
29
+ this.ruta.navigate([this.rutaASeguir]);
30
+ }
31
+
32
+ ngOnInit() {
33
+ this.cantidadAMostrar = (this.cantidadMaxima ? this.cantidadMaxima : 0) - (this.cantidad ? this.cantidad : 0);
34
+ }
35
+
36
+ ngAfterViewInit(): void {
37
+ if (this.cantidad) {
38
+ let porcentaje = 100;
39
+ if (this.cantidadMaxima) {
40
+ porcentaje = (this.cantidad / this.cantidadMaxima) * 100;
41
+ }
42
+ const linea = document.getElementById('porcentaje' + this.titulo) as HTMLHRElement;
43
+ linea.style.width = `${porcentaje}%`;
44
+ }
45
+ }
46
+ }