utn-cli 2.0.43 → 2.0.45

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utn-cli",
3
- "version": "2.0.43",
3
+ "version": "2.0.45",
4
4
  "description": "Herramienta CLI unificada para la gestión de plantillas en SIGU.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -40,6 +40,178 @@ class Miscelaneo {
40
40
  this.EnlaceDeAcceso = undefined;
41
41
  };
42
42
 
43
+ //REPORTE INICIA AQUÍ
44
+ GenerarReporteHTMLEncabezado(InformacionDeLaDerecha, titulares, marcaDeAgua = '') {
45
+ const date = new Date();
46
+ const year = date.getFullYear();
47
+
48
+ return ` <!DOCTYPE html>
49
+ <html lang="es">
50
+ <head>
51
+ <meta charset="UTF-8">
52
+ <title>${titulares.titulo}</title>
53
+
54
+ <style>
55
+ @media print {
56
+ * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
57
+ }
58
+ body { font-family: Roboto, "Helvetica Neue", sans-serif; margin: 8px; }
59
+ .header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px; min-height: 70px; }
60
+ .header > div { flex: 1; }
61
+ .logo { flex-shrink: 0; }
62
+ .title-container { text-align: center; flex-grow: 1; }
63
+ .title { font-size: 16px; font-weight: bold; white-space: nowrap; flex-shrink: 0; }
64
+ .subtitle { font-size: 13px; font-weight: bold; margin-top: 4px; }
65
+ .info { text-align: right; font-size: 11px; margin-left: 10px; flex-shrink: 0; }
66
+ table { width: 100%; border-collapse: separate; border-spacing: 0; border-radius: 10px; overflow: hidden; }
67
+ th, td { border: 1px solid #ccc; padding: 4px; text-align: left; font-size: 12px; }
68
+ th { background-color: #002f6b; color: white; }
69
+ tr:nth-child(even) { background-color: #f9f9f9; }
70
+ td:last-child { width: 100px; }
71
+ hr { border: none; border-top: 2px solid #838383; margin: 8px 0; }
72
+ .watermark { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(-45deg); font-size: 80px; color: rgba(100, 100, 100, 0.09); font-weight: bold; z-index: 999; white-space: nowrap; pointer-events: none; }
73
+ </style>
74
+
75
+ </head>
76
+ <body>
77
+ <div class="watermark">${marcaDeAgua}</div>
78
+ <div class="header">
79
+ <div class="logo">
80
+ <img src="https://storage.sigu.utn.ac.cr/images/cards/LogoUTN.svg" alt="Logo UTN" style="height:50px;">
81
+ </div>
82
+ <div class="title-container">
83
+ <div class="title">Universidad Técnica Nacional</div>
84
+ <div class="subtitle">${titulares.primerSubtitulo}</div>
85
+ <div class="subtitle">${titulares.segundoSubtitulo}</div>
86
+ </div>
87
+ <div class="info">
88
+ ${InformacionDeLaDerecha}
89
+ </div>
90
+
91
+ </div> `;
92
+ }
93
+ GenerarReporteHTMLFecha() {
94
+ const now = new Date();
95
+
96
+ const day = now.getDate().toString().padStart(2, '0');
97
+ const month = (now.getMonth() + 1).toString().padStart(2, '0');
98
+ const year = now.getFullYear();
99
+
100
+ let hours = now.getHours();
101
+ const minutes = now.getMinutes().toString().padStart(2, '0');
102
+ const ampm = hours >= 12 ? 'PM' : 'AM';
103
+
104
+ hours = hours % 12;
105
+ hours = hours ? hours : 12;
106
+ hours = hours.toString().padStart(2, '0');
107
+
108
+ const fechaFormateada = `${day}-${month}-${year} ${hours}:${minutes} ${ampm}`;
109
+
110
+ return ` <div style="margin-left: 0; font-size: 11px; margin-top:4px;">
111
+ <strong>Fecha:</strong>
112
+ <span style="
113
+ border-bottom: 1px solid #000;
114
+ margin-left: 10px;
115
+ display: inline-block;
116
+ padding: 0 4px 2px 4px;
117
+ vertical-align: middle;
118
+ text-align: center;
119
+ min-width: 120px;
120
+ ">${fechaFormateada}
121
+ </span>
122
+ </div>
123
+ `
124
+ }
125
+ GenerarReporteHTMLTablas(ElementosParaLaTabla, ParametrosExcluidos = [], ParametrosExtra = []) {
126
+ //Ejemplo ElementosParaLaTabla:
127
+ // [
128
+ // {
129
+ // "Fecha del traslado": "16-03-2026",
130
+ // "Justificacion": "Traslado por mantenimiento",
131
+ // "Dependencia que entrega": "Juan Pérez",
132
+ // "Dependencia que recibe": "María Gómez",
133
+ // Placa: "ABC123",
134
+ // "Descripción": "Laptop Dell",
135
+ // "Código de activo": "ACT-001",
136
+ // "N° de serie": "SN123456",
137
+ // Marca: "Dell",
138
+ // Modelo: "Latitude 5420",
139
+ // Estado: "Bueno",
140
+ // IdentificadorOrigen: 101,
141
+ // IdentificadorDestino: 202
142
+ // },
143
+ // {
144
+ // "Fecha del traslado": "16-03-2026",
145
+ // "Justificacion": "Traslado por mantenimiento",
146
+ // "Dependencia que entrega": "Juan Pérez",
147
+ // "Dependencia que recibe": "María Gómez",
148
+ // Placa: "XYZ789",
149
+ // "Descripción": "Monitor Samsung",
150
+ // "Código de activo": "ACT-002",
151
+ // "N° de serie": "SN654321",
152
+ // Marca: "Samsung",
153
+ // Modelo: "S24F350",
154
+ // Estado: "Excelente",
155
+ // IdentificadorOrigen: 101,
156
+ // IdentificadorDestino: 202
157
+ // }
158
+ // ]
159
+ // Espera un Array
160
+ //Ejemplo ParametrosExcluidos:
161
+ //const ParametrosExcluidos = ['IdentificadorOrigen', 'Justificacion', 'IdentificadorDestino'];
162
+ //Valores devueltos por el QUERY que no sean necesarios mostrar en la tabla.
163
+
164
+ //Ejemplo ParametrosExtra:
165
+ //const ParametrosExtra = ['Toma física'];
166
+ //En caso de necesitar un espacio extra en la tabla que no se encuentra en la lista principal.
167
+
168
+ if (!ElementosParaLaTabla?.length) return '';
169
+
170
+ const baseColumnas = Object.keys(ElementosParaLaTabla[0]).filter(col => !ParametrosExcluidos.includes(col));
171
+ const columnas = [...baseColumnas, ...ParametrosExtra.filter(p => !baseColumnas.includes(p))];
172
+
173
+ const tableHeaders = `<th>N°</th>` + columnas.map(col => `<th>${col}</th>`).join('');
174
+
175
+ const rows = ElementosParaLaTabla.map((fila, index) => {
176
+ const rowCells = columnas.map(col => {
177
+ const valor = fila[col] ?? '';
178
+ return `<td>${valor}</td>`;
179
+ }).join('');
180
+ return `<tr><td><strong>${index + 1}</strong></td>${rowCells}</tr>`;
181
+ });
182
+
183
+ const colCount = columnas.length + 1;
184
+ const minRows = 8;
185
+ let currentIndex = rows.length;
186
+ while (rows.length < minRows) {
187
+ let emptyCells = `<td><strong>${currentIndex + 1}</strong></td>`;
188
+ for (let i = 0; i < colCount - 1; i++) {
189
+ emptyCells += '<td></td>';
190
+ }
191
+ rows.push(`<tr style="height:40px">${emptyCells}</tr>`);
192
+ currentIndex++;
193
+ }
194
+
195
+ const tableRows = rows.join('');
196
+ return `
197
+ <table>
198
+ <thead>
199
+ <tr>${tableHeaders}</tr>
200
+ </thead>
201
+ <tbody>
202
+ ${tableRows}
203
+ </tbody>
204
+ </table>`;
205
+ }
206
+
207
+ GenerarReporteHTMLPie() {
208
+ return `
209
+ </body>
210
+ </html>`;
211
+ }
212
+ //la información adicional se concatena desde la llamada
213
+ //REPORTE TERMINA AQUÍ
214
+
43
215
  obtenerNombreLaBaseDeDatos() {
44
216
  return this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3);
45
217
  }
@@ -9,15 +9,15 @@ services:
9
9
  volumes:
10
10
  - ./docker-scripts:/docker-entrypoint-initdb.d
11
11
 
12
- CumuloDB:
13
- image: mariadb:lts
14
- ports:
15
- - "3308:3306"
16
- environment:
17
- MYSQL_ROOT_PASSWORD: root
18
- MYSQL_DATABASE: DatosFederados
19
- volumes:
20
- - ./cumulodb-scripts:/docker-entrypoint-initdb.d
12
+ # CumuloDB:
13
+ # image: mariadb:lts
14
+ # ports:
15
+ # - "3308:3306"
16
+ # environment:
17
+ # MYSQL_ROOT_PASSWORD: root
18
+ # MYSQL_DATABASE: DatosFederados
19
+ # volumes:
20
+ # - ./cumulodb-scripts:/docker-entrypoint-initdb.d
21
21
 
22
22
  SIGU:
23
23
  image: registry.git.utn.ac.cr/sistema-integrado-de-gesti-n-universitaria-sigu/sigu-framework/framework-base-de-datos:desarrollo-latest
@@ -17,10 +17,10 @@
17
17
  }
18
18
  </div>
19
19
  @if(EsEditable) {
20
- <div class="zona-archivo" [class.deshabilitado]="ListaArchivos.length >= CantidadMaximaArchivos" (click)="AbrirGestorDeArchivos()" (dragover)="ArrastrarAdentro($event)"
20
+ <div class="zona-archivo" [class.deshabilitado]="ListaArchivos.length >= CantidadMaximaDeArchivos" (click)="AbrirGestorDeArchivos()" (dragover)="ArrastrarAdentro($event)"
21
21
  (dragleave)="ArrastrarAfuera($event)" (drop)="Soltar($event)">
22
- @if(ListaArchivos.length >= CantidadMaximaArchivos) {
23
- <p class="texto-limite">Límite de {{CantidadMaximaArchivos}} archivos alcanzado</p>
22
+ @if(ListaArchivos.length >= CantidadMaximaDeArchivos) {
23
+ <p class="texto-limite">Límite de {{CantidadMaximaDeArchivos}} archivos alcanzado</p>
24
24
  } @else {
25
25
  @if(!Archivo){
26
26
  <p class="texto">Arrastra y suelta un archivo aquí o <span class="texto-clic">haz clic para subir</span></p>
@@ -33,6 +33,9 @@ export class SubirArchivoComponent implements OnInit {
33
33
  constructor(private dialog: MatDialog, private datosGlobalesService: DatosGlobalesService, private http: HttpClient) { }
34
34
 
35
35
  ngOnInit(): void {
36
+ if (this.data.RutaParaCargar) {
37
+ this.RutaParaCargar = this.data.RutaParaCargar;
38
+ }
36
39
  if (this.data.RutaParaListar) {
37
40
  this.RutaParaListar = this.data.RutaParaListar;
38
41
  }