utn-cli 2.1.54 → 2.1.55

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 (40) hide show
  1. package/package.json +1 -1
  2. package/templates/backend/package.json +3 -3
  3. package/templates/backend/rutas/DatosMiscelaneos.js +50 -0
  4. package/templates/backend/rutas/misc.js +177 -5
  5. package/templates/backend/rutas/rutas.js +2 -0
  6. package/templates/backend/servicios/Nucleo/DatosMiscelaneos.js +36 -0
  7. package/templates/backend/servicios/Nucleo/Miscelaneas.js +192 -25
  8. package/templates/frontend/Dockerfile +1 -0
  9. package/templates/frontend/src/app/Componentes/Nucleo/boton-ayuda/boton-ayuda.component.css +7 -0
  10. package/templates/frontend/src/app/Componentes/Nucleo/boton-ayuda/boton-ayuda.component.html +28 -0
  11. package/templates/frontend/src/app/Componentes/Nucleo/boton-ayuda/boton-ayuda.component.ts +78 -0
  12. package/templates/frontend/src/app/Componentes/Nucleo/estadisticas-del-modulo/estadisticas-del-modulo.component.html +43 -8
  13. package/templates/frontend/src/app/Componentes/Nucleo/estadisticas-del-modulo/estadisticas-del-modulo.component.ts +5 -4
  14. package/templates/frontend/src/app/Componentes/Nucleo/gestion-actividad/gestion-actividad.component.ts +1 -0
  15. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion/mensaje-confirmacion.component.css +4 -2
  16. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-institucional/mensaje-institucional.component.html +3 -3
  17. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-institucional/mensaje-institucional.component.ts +1 -1
  18. package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts +1 -1
  19. package/templates/frontend/src/app/Paginas/Nucleo/accesibilidad/accesibilidad.component.css +25 -0
  20. package/templates/frontend/src/app/Paginas/Nucleo/accesibilidad/accesibilidad.component.html +2 -0
  21. package/templates/frontend/src/app/Paginas/Nucleo/accesibilidad/accesibilidad.component.ts +31 -2
  22. package/templates/frontend/src/app/Paginas/Nucleo/acercade/acercade.component.css +67 -18
  23. package/templates/frontend/src/app/Paginas/Nucleo/acercade/acercade.component.html +56 -46
  24. package/templates/frontend/src/app/Paginas/Nucleo/acercade/acercade.component.ts +21 -1
  25. package/templates/frontend/src/app/Paginas/Nucleo/conozcanos/conozcanos.component.css +190 -375
  26. package/templates/frontend/src/app/Paginas/Nucleo/conozcanos/conozcanos.component.html +92 -91
  27. package/templates/frontend/src/app/Paginas/Nucleo/conozcanos/conozcanos.component.ts +19 -2
  28. package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.ts +2 -2
  29. package/templates/frontend/src/app/Paginas/Nucleo/declaracion-ia/declaracion-ia.component.css +25 -0
  30. package/templates/frontend/src/app/Paginas/Nucleo/declaracion-ia/declaracion-ia.component.html +2 -0
  31. package/templates/frontend/src/app/Paginas/Nucleo/declaracion-ia/declaracion-ia.component.ts +33 -3
  32. package/templates/frontend/src/app/Paginas/Nucleo/politicas/politicas.component.css +69 -15
  33. package/templates/frontend/src/app/Paginas/Nucleo/politicas/politicas.component.html +129 -107
  34. package/templates/frontend/src/app/Paginas/Nucleo/politicas/politicas.component.ts +51 -9
  35. package/templates/frontend/src/app/Paginas/Nucleo/preguntasFrecuentes/preguntasFrecuentes.component.css +68 -15
  36. package/templates/frontend/src/app/Paginas/Nucleo/preguntasFrecuentes/preguntasFrecuentes.component.html +161 -88
  37. package/templates/frontend/src/app/Paginas/Nucleo/preguntasFrecuentes/preguntasFrecuentes.component.ts +63 -10
  38. package/templates/frontend/src/app/Paginas/Nucleo/sabiasque/sabiasque.component.css +100 -24
  39. package/templates/frontend/src/app/Paginas/Nucleo/sabiasque/sabiasque.component.html +269 -339
  40. package/templates/frontend/src/app/Paginas/Nucleo/sabiasque/sabiasque.component.ts +94 -6
@@ -0,0 +1,7 @@
1
+ .campo-completo {
2
+ width: 100%;
3
+ }
4
+
5
+ .sin-texto {
6
+ opacity: 0.3;
7
+ }
@@ -0,0 +1,28 @@
1
+ <button mat-icon-button type="button"
2
+ [class.sin-texto]="!textoAyuda"
3
+ #tooltip="matTooltip"
4
+ [matTooltip]="textoAyuda || 'Sin información disponible.'"
5
+ matTooltipPosition="above"
6
+ (mouseenter)="cargarTexto()"
7
+ (dblclick)="abrirEdicion()">
8
+ <mat-icon>{{ textoAyuda ? 'help' : 'help_outline' }}</mat-icon>
9
+ </button>
10
+
11
+ <ng-template #dialogEdicion>
12
+ <h2 mat-dialog-title>Texto de ayuda</h2>
13
+ <mat-dialog-content>
14
+ <mat-form-field class="campo-completo">
15
+ <mat-label>Descripción</mat-label>
16
+ <textarea matInput [(ngModel)]="textoEdicion" rows="5"
17
+ placeholder="Escriba el texto de ayuda para este campo..."></textarea>
18
+ </mat-form-field>
19
+ </mat-dialog-content>
20
+ <mat-dialog-actions align="end">
21
+ <button mat-button mat-dialog-close>Cancelar</button>
22
+ <button mat-flat-button color="primary"
23
+ [disabled]="guardando"
24
+ (click)="guardarYCerrar()">
25
+ {{ guardando ? 'Guardando...' : 'Guardar' }}
26
+ </button>
27
+ </mat-dialog-actions>
28
+ </ng-template>
@@ -0,0 +1,78 @@
1
+ import { Component, inject, Input, OnInit, TemplateRef, ViewChild } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+ import { HttpClient } from '@angular/common/http';
4
+ import { firstValueFrom } from 'rxjs';
5
+ import { MatButtonModule } from '@angular/material/button';
6
+ import { MatDialog, MatDialogActions, MatDialogClose, MatDialogContent, MatDialogTitle } from '@angular/material/dialog';
7
+ import { MatFormFieldModule } from '@angular/material/form-field';
8
+ import { MatIconModule } from '@angular/material/icon';
9
+ import { MatInputModule } from '@angular/material/input';
10
+ import { MatTooltipModule } from '@angular/material/tooltip';
11
+ import { DatosGlobalesService } from '../../../datos-globales.service';
12
+
13
+ @Component({
14
+ selector: 'app-boton-ayuda',
15
+ imports: [
16
+ FormsModule,
17
+ MatButtonModule,
18
+ MatDialogActions,
19
+ MatDialogClose,
20
+ MatDialogContent,
21
+ MatDialogTitle,
22
+ MatFormFieldModule,
23
+ MatIconModule,
24
+ MatInputModule,
25
+ MatTooltipModule,
26
+ ],
27
+ templateUrl: './boton-ayuda.component.html',
28
+ styleUrl: './boton-ayuda.component.css'
29
+ })
30
+ export class BotonAyudaComponent implements OnInit {
31
+ @Input({ required: true }) campo!: string;
32
+ @Input() EsEditable: boolean = false;
33
+ @ViewChild('dialogEdicion') dialogEdicion!: TemplateRef<any>;
34
+
35
+ textoAyuda = '';
36
+ textoEdicion = '';
37
+ guardando = false;
38
+
39
+ private cargando = false;
40
+ private dialogRef: any;
41
+ private http = inject(HttpClient);
42
+ private datosGlobales = inject(DatosGlobalesService);
43
+ private dialog = inject(MatDialog);
44
+
45
+ ngOnInit() {
46
+ this.cargarTexto();
47
+ }
48
+
49
+ async cargarTexto() {
50
+ if (this.cargando) return;
51
+ this.cargando = true;
52
+ try {
53
+ const url = `${this.datosGlobales.ObtenerURL()}DatosMiscelaneos/detalle/${this.campo}`;
54
+ const resultado: any = await firstValueFrom(this.http.get(url));
55
+ this.textoAyuda = resultado?.body ?? '';
56
+ } finally {
57
+ this.cargando = false;
58
+ }
59
+ }
60
+
61
+ abrirEdicion() {
62
+ if (!this.EsEditable) return;
63
+ this.textoEdicion = this.textoAyuda;
64
+ this.dialogRef = this.dialog.open(this.dialogEdicion, { width: '400px' });
65
+ }
66
+
67
+ async guardarYCerrar() {
68
+ this.guardando = true;
69
+ try {
70
+ const url = `${this.datosGlobales.ObtenerURL()}DatosMiscelaneos/guardar`;
71
+ await firstValueFrom(this.http.post(url, { Llave: this.campo, Texto: this.textoEdicion }));
72
+ this.textoAyuda = this.textoEdicion;
73
+ this.dialogRef?.close();
74
+ } finally {
75
+ this.guardando = false;
76
+ }
77
+ }
78
+ }
@@ -1,8 +1,4 @@
1
- <div class="dialogo-header">
2
- <mat-icon class="dialogo-icono">bar_chart</mat-icon>
3
- <span class="dialogo-titulo">Estadísticas del módulo</span>
4
- </div>
5
-
1
+ <h2 mat-dialog-title>Estadísticas del módulo</h2>
6
2
  <mat-dialog-content>
7
3
  <div class="contenedor">
8
4
  <div class="estadistica">
@@ -19,11 +15,50 @@
19
15
  <span class="estadistica-valor">{{ datos.VistasDelManual | number }}</span>
20
16
  </div>
21
17
  </div>
18
+ <div class="estadistica">
19
+ <mat-icon class="estadistica-icono">info</mat-icon>
20
+ <div class="estadistica-info">
21
+ <span class="estadistica-label">Vistas de Acerca de</span>
22
+ <span class="estadistica-valor">{{ datos.VistasDeAcercaDe | number }}</span>
23
+ </div>
24
+ </div>
25
+ <div class="estadistica">
26
+ <mat-icon class="estadistica-icono">security</mat-icon>
27
+ <div class="estadistica-info">
28
+ <span class="estadistica-label">Vistas de Políticas</span>
29
+ <span class="estadistica-valor">{{ datos.VistasDePoliticas | number }}</span>
30
+ </div>
31
+ </div>
32
+ <div class="estadistica">
33
+ <mat-icon class="estadistica-icono">groups</mat-icon>
34
+ <div class="estadistica-info">
35
+ <span class="estadistica-label">Vistas de Conózcanos</span>
36
+ <span class="estadistica-valor">{{ datos.VistasDeConozcanos | number }}</span>
37
+ </div>
38
+ </div>
39
+ <div class="estadistica">
40
+ <mat-icon class="estadistica-icono">lightbulb</mat-icon>
41
+ <div class="estadistica-info">
42
+ <span class="estadistica-label">Vistas de Sabías qué</span>
43
+ <span class="estadistica-valor">{{ datos.VistasDeSabiasQue| number }}</span>
44
+ </div>
45
+ </div>
46
+ <div class="estadistica">
47
+ <mat-icon class="estadistica-icono">question_answer</mat-icon>
48
+ <div class="estadistica-info">
49
+ <span class="estadistica-label">Vistas de Preguntas Frecuentes</span>
50
+ <span class="estadistica-valor">{{ datos.VistasDePreguntasFrecuentes| number }}</span>
51
+ </div>
52
+ </div>
53
+
54
+
22
55
  </div>
23
56
  </mat-dialog-content>
24
-
25
57
  <mat-dialog-actions>
26
- <button mat-stroked-button class="btn-cerrar" (click)="Cerrar()">Cerrar</button>
58
+ <button mat-button (click)="Cerrar()">Cerrar</button>
27
59
  </mat-dialog-actions>
28
60
 
29
- <div class="dialogo-pie"></div>
61
+
62
+
63
+
64
+
@@ -1,5 +1,5 @@
1
1
  import { Component, Inject, inject } from '@angular/core';
2
- import { MAT_DIALOG_DATA, MatDialogActions, MatDialogContent, MatDialogRef } from '@angular/material/dialog';
2
+ import { MAT_DIALOG_DATA, MatDialogActions, MatDialogContent, MatDialogRef, MatDialogTitle } from '@angular/material/dialog';
3
3
  import { MatButtonModule } from '@angular/material/button';
4
4
  import { MatIconModule } from '@angular/material/icon';
5
5
  import { CommonModule } from '@angular/common';
@@ -8,14 +8,15 @@ import { CommonModule } from '@angular/common';
8
8
  selector: 'app-estadisticas-del-modulo',
9
9
  templateUrl: './estadisticas-del-modulo.component.html',
10
10
  styleUrl: './estadisticas-del-modulo.component.css',
11
- imports: [MatDialogContent, MatDialogActions, MatButtonModule, MatIconModule, CommonModule]
11
+ imports: [MatDialogContent, MatDialogActions, MatDialogTitle, MatButtonModule, MatIconModule, CommonModule]
12
12
  })
13
+
13
14
  export class EstadisticasDelModuloComponent {
14
15
  readonly dialogRef = inject(MatDialogRef<EstadisticasDelModuloComponent>);
15
16
 
16
- constructor(@Inject(MAT_DIALOG_DATA) public datos: { VistasDelModulo: number, VistasDelManual: number }) { }
17
+ constructor(@Inject(MAT_DIALOG_DATA) public datos: { VistasDelModulo: number, VistasDelManual: number, VistasDeAcercaDe: number, VistasDePoliticas: number,VistasDeConozcanos: number, VistasDeSabiasQue: number,VistasDePreguntasFrecuentes: number }) { }
17
18
 
18
19
  Cerrar(): void {
19
20
  this.dialogRef.close();
20
21
  }
21
- }
22
+ }
@@ -28,6 +28,7 @@ export class GestionActividadComponent implements OnInit, OnDestroy {
28
28
 
29
29
  ngOnInit(): void {
30
30
  this.tokenActual = this.datosGlobalesService.ObtenerToken().split(' ')[1] || '';
31
+ this.http.get(`${this.datosGlobalesService.ObtenerURL()}misc/VistaDeActividad`).pipe(takeUntil(this._destroy$)).subscribe({ error: () => { } });
31
32
  this.obtenerActividad();
32
33
  }
33
34
 
@@ -6,7 +6,6 @@
6
6
  background: linear-gradient(90deg, rgba(1, 33, 105, 1) 0%, rgba(63, 97, 171, 1) 100%);
7
7
  color: white;
8
8
  padding: 24px 20px 16px;
9
- margin: -8px -8px 0;
10
9
  }
11
10
 
12
11
  .dialogo-icono {
@@ -69,5 +68,8 @@ mat-dialog-actions {
69
68
  .dialogo-pie {
70
69
  height: 20px;
71
70
  background: linear-gradient(90deg, rgba(1, 33, 105, 1) 0%, rgba(63, 97, 171, 1) 100%);
72
- margin: 0 -8px;
73
71
  }
72
+
73
+ :host ::ng-deep .mat-mdc-dialog-container .mat-mdc-dialog-surface {
74
+ padding: 0;
75
+ }
@@ -1,5 +1,5 @@
1
1
  <div class="mensaje-banner">
2
- <img src="https://storage.sigu.utn.ac.cr/images/MensajesInstitucionales/Banner.png"
2
+ <img src="https://framework-mantenimientosv2-storage.sigu.utn.ac.cr/framework-mantenimientosv2/Banner.png"
3
3
  alt="Información SIGU"
4
4
  class="mensaje-banner-imagen" />
5
5
  </div>
@@ -8,8 +8,8 @@
8
8
  <h1 class="mensaje-titulo">{{ datos.Titulo }}</h1>
9
9
 
10
10
  <figure class="mensaje-figura">
11
- <img src="https://storage.sigu.utn.ac.cr/images/MensajesInstitucionales/Carnet.png"
12
- alt="Carnet institucional"
11
+ <img [src]="datos.ImagenURL"
12
+ alt="Imagen del mensaje institucional"
13
13
  class="mensaje-imagen" />
14
14
  </figure>
15
15
 
@@ -11,7 +11,7 @@ import { MatButtonModule } from '@angular/material/button';
11
11
  export class MensajeInstitucionalComponent {
12
12
  readonly dialogRef = inject(MatDialogRef<MensajeInstitucionalComponent>);
13
13
 
14
- constructor(@Inject(MAT_DIALOG_DATA) public datos: { Titulo: string, Texto: string }) { }
14
+ constructor(@Inject(MAT_DIALOG_DATA) public datos: { Titulo: string, Texto: string, ImagenURL: string | null }) { }
15
15
 
16
16
  Cerrar(): void {
17
17
  this.dialogRef.close();
@@ -275,7 +275,7 @@ export class SubirArchivoComponent implements OnInit, OnDestroy {
275
275
  // ── Visor inline ─────────────────────────────────────────────────────────
276
276
 
277
277
  obtenerTipoDeVista(nombre: string): TipoDeVista | null {
278
- const n = nombre.split(' (')[0].trim().toLowerCase();
278
+ const n = nombre.replace(/\s*\([^)]*\)\s*$/, '').trim().toLowerCase();
279
279
  if (n.endsWith('.diff')) return 'diff';
280
280
  if (n.endsWith('.txt')) return 'texto';
281
281
  if (n.endsWith('.csv')) return 'csv';
@@ -256,3 +256,28 @@ kbd {
256
256
  text-align: center;
257
257
  }
258
258
  }
259
+
260
+
261
+ /* Botón volver arriba */
262
+ .btn-volver-arriba {
263
+ display: none;
264
+ }
265
+
266
+ @media (max-width: 768px) {
267
+ .btn-volver-arriba {
268
+ display: flex;
269
+ align-items: center;
270
+ justify-content: center;
271
+ margin: 2rem auto 1rem;
272
+ padding: 0.6rem 1.4rem;
273
+ background: linear-gradient(90deg, rgba(1, 33, 105, 1) 0%, rgba(63, 97, 171, 1) 100%);
274
+ color: white;
275
+ border: none;
276
+ border-radius: 24px;
277
+ font-family: 'Roboto', sans-serif;
278
+ font-size: 0.9rem;
279
+ font-weight: 500;
280
+ cursor: pointer;
281
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
282
+ }
283
+ }
@@ -285,5 +285,7 @@
285
285
  </table>
286
286
  </section>
287
287
 
288
+ <button *ngIf="mostrarBotonInicio" class="btn-volver-arriba" (click)="irAlInicio()" title="Volver arriba">↑ Volver arriba</button>
289
+
288
290
  </main>
289
291
  </div>
@@ -1,6 +1,10 @@
1
- import { Component } from '@angular/core';
1
+ import { Component, OnInit } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { MatIconModule } from '@angular/material/icon';
4
+ import { HttpClient } from '@angular/common/http';
5
+ import { DatosGlobalesService } from '../../../datos-globales.service';
6
+ import { Subject } from 'rxjs';
7
+ import { takeUntil } from 'rxjs/operators';
4
8
 
5
9
  interface SeccionToc {
6
10
  id: string;
@@ -14,7 +18,27 @@ interface SeccionToc {
14
18
  templateUrl: './accesibilidad.component.html',
15
19
  styleUrl: './accesibilidad.component.css'
16
20
  })
17
- export class AccesibilidadComponent {
21
+ export class AccesibilidadComponent implements OnInit {
22
+ private _destroy$ = new Subject<void>();
23
+ mostrarBotonInicio = false;
24
+ private _scrollListener?: EventListener;
25
+
26
+ constructor(private http: HttpClient, private datosGlobalesService: DatosGlobalesService) { }
27
+ ngOnInit(): void {
28
+ this.http.get(`${this.datosGlobalesService.ObtenerURL()}misc/VistaDeAccesibilidad`).pipe(takeUntil(this._destroy$)).subscribe({ error: () => { } });
29
+ setTimeout(() => {
30
+ const c = document.querySelector('.zona-scrollable');
31
+ if (c) {
32
+ this._scrollListener = () => { this.mostrarBotonInicio = (c as HTMLElement).scrollTop > 200; };
33
+ c.addEventListener('scroll', this._scrollListener);
34
+ }
35
+ }, 0);
36
+ }
37
+
38
+ ngOnDestroy(): void {
39
+ this._destroy$.next(); this._destroy$.complete();
40
+ if (this._scrollListener) { document.querySelector('.zona-scrollable')?.removeEventListener('scroll', this._scrollListener); }
41
+ }
18
42
  public secciones: SeccionToc[] = [
19
43
  { id: 'navegacion-teclado', titulo: 'Navegación con teclado' },
20
44
  { id: 'atajos-navegadores', titulo: 'Atajos por navegador y sistema operativo' },
@@ -25,4 +49,9 @@ export class AccesibilidadComponent {
25
49
  irA(id: string): void {
26
50
  document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' });
27
51
  }
52
+ irAlInicio(): void {
53
+ const contenedor = document.querySelector('.zona-scrollable');
54
+ if (contenedor) { contenedor.scrollTo({ top: 0, behavior: 'smooth' }); this.mostrarBotonInicio = false; }
55
+ else { window.scrollTo({ top: 0, behavior: 'smooth' }); }
56
+ }
28
57
  }
@@ -1,37 +1,61 @@
1
- .politicas-container {
2
- max-width: 1000px;
3
- padding-bottom: 20px;
4
- font-family: 'Roboto', sans-serif;
5
- background-color: white;
6
- text-align: left;
1
+ .ia-layout {
2
+ max-width: 820px;
7
3
  margin: 0 auto;
4
+ padding: 24px 16px;
5
+ font-family: 'Roboto', sans-serif;
8
6
  }
9
7
 
10
- .subtitle {
11
- background-color: #0b4794;
12
- font-size: 25px;
8
+ .ia-main {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: 28px;
12
+ }
13
+
14
+ .ia-encabezado {
15
+ display: flex;
16
+ align-items: center;
17
+ gap: 14px;
18
+ padding: 20px 24px;
19
+ background: linear-gradient(90deg, rgba(1, 33, 105, 1) 0%, rgba(63, 97, 171, 1) 100%);
13
20
  color: white;
14
- padding: 18px;
15
- margin: 20px 0;
16
- text-align: center;
21
+ border-radius: 12px;
17
22
  }
18
- .subtitle p {
19
- margin: 5px 0;
23
+
24
+ .ia-icono-header {
25
+ font-size: 40px !important;
26
+ width: 40px !important;
27
+ height: 40px !important;
28
+ flex-shrink: 0;
29
+ opacity: 0.9;
30
+ }
31
+
32
+ .ia-encabezado h1 {
33
+ margin: 0;
34
+ font-size: 22px;
35
+ font-weight: 700;
36
+ line-height: 1.2;
37
+ }
38
+
39
+ .ia-seccion {
40
+ background: white;
41
+ border: 1px solid #d0daea;
42
+ border-radius: 10px;
43
+ padding: 20px 24px;
20
44
  }
21
45
  .description {
22
46
  width: 100%;
23
- padding-left: 30px;
24
- padding-right: 30px;
47
+ max-width: 680px;
48
+ margin: 0 auto;
25
49
  box-sizing: border-box;
26
- margin-top: 30px;
27
50
  }
28
51
 
29
52
  .description p {
30
- margin: 15px 0;
53
+ margin: 0 0 20px 0;
31
54
  font-size: 16px;
32
55
  font-weight: 400;
33
56
  color: #4D4D4D;
34
57
  line-height: 1.6;
58
+ text-align: justify;
35
59
  }
36
60
 
37
61
  .description ul {
@@ -63,3 +87,28 @@
63
87
  }
64
88
  }
65
89
 
90
+
91
+
92
+ /* Botón volver arriba */
93
+ .btn-volver-arriba {
94
+ display: none;
95
+ }
96
+
97
+ @media (max-width: 768px) {
98
+ .btn-volver-arriba {
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: center;
102
+ margin: 2rem auto 1rem;
103
+ padding: 0.6rem 1.4rem;
104
+ background: linear-gradient(90deg, rgba(1, 33, 105, 1) 0%, rgba(63, 97, 171, 1) 100%);
105
+ color: white;
106
+ border: none;
107
+ border-radius: 24px;
108
+ font-family: 'Roboto', sans-serif;
109
+ font-size: 0.9rem;
110
+ font-weight: 500;
111
+ cursor: pointer;
112
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
113
+ }
114
+ }
@@ -1,49 +1,59 @@
1
- <div class="subtitle">
2
- <p>¿Qué es SIGU?</p>
3
- </div>
4
- <div class="politicas-container">
1
+ <div class="ia-layout">
2
+ <main class="ia-main">
3
+
4
+ <header class="ia-encabezado">
5
+ <mat-icon class="ia-icono-header">info</mat-icon>
6
+ <div>
7
+ <h1>¿Qué es SIGU?</h1>
8
+ </div>
9
+ </header>
5
10
 
6
- <div class="description">
7
- <p>El Sistema Integrado de Gestión Universitaria (SIGU) es la plataforma digital de la Universidad Técnica Nacional
8
- diseñada para centralizar y facilitar la gestión de servicios académicos, administrativos e institucionales.
9
- </p>
10
- <p>SIGU nace con el propósito de modernizar y optimizar los procesos institucionales que permitan a estudiantes,
11
- docentes, personal administrativo, aspirantes, clientes y público en general acceder a distintos servicios
12
- universitarios desde una plataforma segura, accesible y eficiente.
13
- </p>
14
- <P>
15
- La plataforma integra funcionalidades relacionadas con procesos académicos, solicitudes institucionales, gestión
16
- administrativa, autenticación de usuarios y acceso a información universitaria, permitiendo centralizar y mejorar
17
- la experiencia digital y fortalecer la interacción entre la Universidad y sus usuarios.
18
- </P>
19
- <P>
20
- Asimismo, SIGU busca ser una plataforma universitaria moderna, innovadora, accesible y en constante evolución,
21
- comprometida con la mejora continua de los servicios digitales institucionales, el fortalecimiento de la gestión
22
- universitaria y el uso responsable y seguro de la información, contribuyendo así a una experiencia tecnológica más
23
- eficiente, transparente y orientada a las necesidades de la comunidad universitaria.
24
- </P>
25
- <P><strong>
26
- El Sistema Integrado de Gestión Universitaria (SIGU) ofrece principios enfocados en la mejora continua de los
27
- servicios digitales universitarios como:
28
- </strong>
29
- </P>
30
- <ul>
31
- <li>Eficiencia: SIGU busca optimizar los procesos académicos y administrativos mediante herramientas tecnológicas
32
- que faciliten el acceso ágil y centralizado a los servicios institucionales.</li>
33
- <li>Confiabilidad: La plataforma procura garantizar integridad y disponibilidad de la información, permitiendo a
34
- los usuarios realizar sus gestiones dentro de un entorno confiable.
35
- </li>
36
- <li>Accesibilidad: SIGU facilita el acceso inmediato a la información y a los módulos de servicios, asegurando una
37
- experiencia digital fluida para todos los usuarios registrados.</li>
38
- <li>Seguridad: La plataforma incorpora medidas de seguridad informática y protección de datos personales, con el
39
- fin de resguardar la información institucional y la privacidad de los usuarios.</li>
40
- <li>Organización: SIGU centraliza distintos procesos y servicios universitarios en una única plataforma digital,
41
- permitiendo una gestión más ordenada y eficiente de la información.</li>
42
- </ul>
11
+ <section class="ia-seccion">
12
+ <div class="description">
13
+ <p>El Sistema Integrado de Gestión Universitaria (SIGU) es la plataforma digital de la Universidad Técnica Nacional
14
+ diseñada para centralizar y facilitar la gestión de servicios académicos, administrativos e institucionales.
15
+ </p>
16
+ <p>SIGU nace con el propósito de modernizar y optimizar los procesos institucionales que permitan a estudiantes,
17
+ docentes, personal administrativo, aspirantes, clientes y público en general acceder a distintos servicios
18
+ universitarios desde una plataforma segura, accesible y eficiente.
19
+ </p>
20
+ <P>
21
+ La plataforma integra funcionalidades relacionadas con procesos académicos, solicitudes institucionales, gestión
22
+ administrativa, autenticación de usuarios y acceso a información universitaria, permitiendo centralizar y mejorar
23
+ la experiencia digital y fortalecer la interacción entre la Universidad y sus usuarios.
24
+ </P>
25
+ <P>
26
+ Asimismo, SIGU busca ser una plataforma universitaria moderna, innovadora, accesible y en constante evolución,
27
+ comprometida con la mejora continua de los servicios digitales institucionales, el fortalecimiento de la gestión
28
+ universitaria y el uso responsable y seguro de la información, contribuyendo así a una experiencia tecnológica más
29
+ eficiente, transparente y orientada a las necesidades de la comunidad universitaria.
30
+ </P>
31
+ <P><strong>
32
+ El Sistema Integrado de Gestión Universitaria (SIGU) ofrece principios enfocados en la mejora continua de los
33
+ servicios digitales universitarios como:
34
+ </strong>
35
+ </P>
36
+ <ul>
37
+ <li>Eficiencia: SIGU busca optimizar los procesos académicos y administrativos mediante herramientas tecnológicas
38
+ que faciliten el acceso ágil y centralizado a los servicios institucionales.</li>
39
+ <li>Confiabilidad: La plataforma procura garantizar integridad y disponibilidad de la información, permitiendo a
40
+ los usuarios realizar sus gestiones dentro de un entorno confiable.
41
+ </li>
42
+ <li>Accesibilidad: SIGU facilita el acceso inmediato a la información y a los módulos de servicios, asegurando una
43
+ experiencia digital fluida para todos los usuarios registrados.</li>
44
+ <li>Seguridad: La plataforma incorpora medidas de seguridad informática y protección de datos personales, con el
45
+ fin de resguardar la información institucional y la privacidad de los usuarios.</li>
46
+ <li>Organización: SIGU centraliza distintos procesos y servicios universitarios en una única plataforma digital,
47
+ permitiendo una gestión más ordenada y eficiente de la información.</li>
48
+ </ul>
43
49
 
44
- <P>La Universidad Técnica Nacional trabaja continuamente en el desarrollo y actualización de la plataforma, con el
45
- objetivo de ofrecer servicios digitales más modernos y adaptados a las necesidades de la comunidad universitaria.
46
- </P>
47
- </div>
50
+ <P>La Universidad Técnica Nacional trabaja continuamente en el desarrollo y actualización de la plataforma, con el
51
+ objetivo de ofrecer servicios digitales más modernos y adaptados a las necesidades de la comunidad universitaria.
52
+ </P>
53
+ </div>
54
+ </section>
48
55
 
49
- </div>
56
+ <button *ngIf="mostrarBotonInicio" class="btn-volver-arriba" (click)="irAlInicio()" title="Volver arriba">↑ Volver arriba</button>
57
+
58
+ </main>
59
+ </div>
@@ -1,5 +1,6 @@
1
1
  import { Component, OnInit } from '@angular/core';
2
2
  import { MatIconModule } from '@angular/material/icon';
3
+ import { CommonModule } from '@angular/common';
3
4
  import { DatosGlobalesService } from '../../../datos-globales.service';
4
5
  import { HttpClient } from '@angular/common/http';
5
6
  import { takeUntil } from 'rxjs/operators';
@@ -7,14 +8,33 @@ import { Subject } from 'rxjs';
7
8
  @Component({
8
9
  selector: 'app-acercade',
9
10
  standalone: true,
10
- imports: [MatIconModule],
11
+ imports: [MatIconModule, CommonModule],
11
12
  templateUrl: './acercade.component.html',
12
13
  styleUrl: './acercade.component.css'
13
14
  })
14
15
  export class AcercadeComponent implements OnInit {
15
16
  private _destroy$ = new Subject<void>();
17
+ mostrarBotonInicio = false;
18
+ private _scrollListener?: EventListener;
19
+
16
20
  constructor(private http: HttpClient, private datosGlobalesService: DatosGlobalesService) { }
17
21
  ngOnInit(): void {
18
22
  this.http.get(`${this.datosGlobalesService.ObtenerURL()}misc/VistaDeAcercaDe`).pipe(takeUntil(this._destroy$)).subscribe({ error: () => { } });
23
+ setTimeout(() => {
24
+ const c = document.querySelector('.zona-scrollable');
25
+ if (c) {
26
+ this._scrollListener = () => { this.mostrarBotonInicio = (c as HTMLElement).scrollTop > 200; };
27
+ c.addEventListener('scroll', this._scrollListener);
28
+ }
29
+ }, 0);
30
+ }
31
+ ngOnDestroy(): void {
32
+ this._destroy$.next(); this._destroy$.complete();
33
+ if (this._scrollListener) { document.querySelector('.zona-scrollable')?.removeEventListener('scroll', this._scrollListener); }
34
+ }
35
+ irAlInicio(): void {
36
+ const contenedor = document.querySelector('.zona-scrollable');
37
+ if (contenedor) { contenedor.scrollTo({ top: 0, behavior: 'smooth' }); this.mostrarBotonInicio = false; }
38
+ else { window.scrollTo({ top: 0, behavior: 'smooth' }); }
19
39
  }
20
40
  }