utn-cli 2.1.54 → 2.1.56

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 (42) 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/angular.json +5 -5
  10. package/templates/frontend/package.json +24 -25
  11. package/templates/frontend/src/app/Componentes/Nucleo/boton-ayuda/boton-ayuda.component.css +7 -0
  12. package/templates/frontend/src/app/Componentes/Nucleo/boton-ayuda/boton-ayuda.component.html +28 -0
  13. package/templates/frontend/src/app/Componentes/Nucleo/boton-ayuda/boton-ayuda.component.ts +78 -0
  14. package/templates/frontend/src/app/Componentes/Nucleo/estadisticas-del-modulo/estadisticas-del-modulo.component.html +43 -8
  15. package/templates/frontend/src/app/Componentes/Nucleo/estadisticas-del-modulo/estadisticas-del-modulo.component.ts +5 -4
  16. package/templates/frontend/src/app/Componentes/Nucleo/gestion-actividad/gestion-actividad.component.ts +1 -0
  17. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion/mensaje-confirmacion.component.css +4 -2
  18. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-institucional/mensaje-institucional.component.html +3 -3
  19. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-institucional/mensaje-institucional.component.ts +1 -1
  20. package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts +1 -1
  21. package/templates/frontend/src/app/Paginas/Nucleo/accesibilidad/accesibilidad.component.css +25 -0
  22. package/templates/frontend/src/app/Paginas/Nucleo/accesibilidad/accesibilidad.component.html +2 -0
  23. package/templates/frontend/src/app/Paginas/Nucleo/accesibilidad/accesibilidad.component.ts +31 -2
  24. package/templates/frontend/src/app/Paginas/Nucleo/acercade/acercade.component.css +67 -18
  25. package/templates/frontend/src/app/Paginas/Nucleo/acercade/acercade.component.html +56 -46
  26. package/templates/frontend/src/app/Paginas/Nucleo/acercade/acercade.component.ts +21 -1
  27. package/templates/frontend/src/app/Paginas/Nucleo/conozcanos/conozcanos.component.css +190 -375
  28. package/templates/frontend/src/app/Paginas/Nucleo/conozcanos/conozcanos.component.html +92 -91
  29. package/templates/frontend/src/app/Paginas/Nucleo/conozcanos/conozcanos.component.ts +19 -2
  30. package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.ts +2 -2
  31. package/templates/frontend/src/app/Paginas/Nucleo/declaracion-ia/declaracion-ia.component.css +25 -0
  32. package/templates/frontend/src/app/Paginas/Nucleo/declaracion-ia/declaracion-ia.component.html +2 -0
  33. package/templates/frontend/src/app/Paginas/Nucleo/declaracion-ia/declaracion-ia.component.ts +33 -3
  34. package/templates/frontend/src/app/Paginas/Nucleo/politicas/politicas.component.css +69 -15
  35. package/templates/frontend/src/app/Paginas/Nucleo/politicas/politicas.component.html +129 -107
  36. package/templates/frontend/src/app/Paginas/Nucleo/politicas/politicas.component.ts +51 -9
  37. package/templates/frontend/src/app/Paginas/Nucleo/preguntasFrecuentes/preguntasFrecuentes.component.css +68 -15
  38. package/templates/frontend/src/app/Paginas/Nucleo/preguntasFrecuentes/preguntasFrecuentes.component.html +161 -88
  39. package/templates/frontend/src/app/Paginas/Nucleo/preguntasFrecuentes/preguntasFrecuentes.component.ts +63 -10
  40. package/templates/frontend/src/app/Paginas/Nucleo/sabiasque/sabiasque.component.css +100 -24
  41. package/templates/frontend/src/app/Paginas/Nucleo/sabiasque/sabiasque.component.html +269 -339
  42. package/templates/frontend/src/app/Paginas/Nucleo/sabiasque/sabiasque.component.ts +94 -6
@@ -11,7 +11,7 @@
11
11
  "prefix": "app",
12
12
  "architect": {
13
13
  "build": {
14
- "builder": "@angular-devkit/build-angular:application",
14
+ "builder": "@angular/build:application",
15
15
  "options": {
16
16
  "outputPath": "dist/frontend",
17
17
  "index": "src/index.html",
@@ -57,7 +57,7 @@
57
57
  "defaultConfiguration": "production"
58
58
  },
59
59
  "serve": {
60
- "builder": "@angular-devkit/build-angular:dev-server",
60
+ "builder": "@angular/build:dev-server",
61
61
  "configurations": {
62
62
  "production": {
63
63
  "buildTarget": "dgdh-incapac-s-front:build:production"
@@ -69,10 +69,10 @@
69
69
  "defaultConfiguration": "development"
70
70
  },
71
71
  "extract-i18n": {
72
- "builder": "@angular-devkit/build-angular:extract-i18n"
72
+ "builder": "@angular/build:extract-i18n"
73
73
  },
74
74
  "test": {
75
- "builder": "@angular-devkit/build-angular:karma",
75
+ "builder": "@angular/build:karma",
76
76
  "options": {
77
77
  "polyfills": [
78
78
  "zone.js",
@@ -98,4 +98,4 @@
98
98
  "cli": {
99
99
  "analytics": false
100
100
  }
101
- }
101
+ }
@@ -9,39 +9,38 @@
9
9
  "test": "ng test"
10
10
  },
11
11
  "private": true,
12
- "packageManager": "npm@10.8.2",
12
+ "packageManager": "npm@11.6.2",
13
13
  "dependencies": {
14
- "@angular/animations": "^21.0.4",
15
- "@angular/cdk": "^21.0.3",
16
- "@angular/common": "^21.0.0",
17
- "@angular/compiler": "^21.0.0",
18
- "@angular/core": "^21.0.0",
19
- "@angular/forms": "^21.2.11",
20
- "@angular/material": "^21.2.9",
21
- "@angular/platform-browser": "^21.0.0",
22
- "@angular/platform-browser-dynamic": "^21.2.11",
23
- "@angular/router": "^21.2.11",
14
+ "@angular/animations": "^22.0.2",
15
+ "@angular/cdk": "^22.0.2",
16
+ "@angular/common": "^22.0.2",
17
+ "@angular/compiler": "^22.0.2",
18
+ "@angular/core": "^22.0.2",
19
+ "@angular/forms": "^22.0.2",
20
+ "@angular/material": "^22.0.2",
21
+ "@angular/platform-browser": "^22.0.2",
22
+ "@angular/platform-browser-dynamic": "^22.0.2",
23
+ "@angular/router": "^22.0.2",
24
24
  "chart.js": "^4.5.1",
25
- "marked": "^18.0.3",
26
- "ng2-charts": "^8.0.0",
27
- "rxjs": "~7.8.0",
28
- "tslib": "^2.3.0",
29
- "zone.js": "^0.16.1"
25
+ "marked": "^18.0.5",
26
+ "ng2-charts": "^10.0.0",
27
+ "rxjs": "~7.8.2",
28
+ "tslib": "^2.8.1",
29
+ "zone.js": "^0.16.2"
30
30
  },
31
31
  "devDependencies": {
32
- "@angular-devkit/build-angular": "^21.2.9",
33
- "@angular/build": "^21.0.3",
34
- "@angular/cli": "^21.2.9",
35
- "@angular/compiler-cli": "^21.2.11",
36
- "@types/jasmine": "^5.1.15",
37
- "jasmine-core": "^5.13.0",
38
- "jsdom": "^27.4.0",
32
+ "@angular/build": "^22.0.3",
33
+ "@angular/cli": "^22.0.3",
34
+ "@angular/compiler-cli": "^22.0.2",
35
+ "@types/jasmine": "^6.0.0",
36
+ "jasmine-core": "^6.3.0",
37
+ "jsdom": "^29.1.1",
39
38
  "karma": "^6.4.4",
40
39
  "karma-chrome-launcher": "^3.2.0",
41
40
  "karma-coverage": "^2.2.1",
42
41
  "karma-jasmine": "^5.1.0",
43
42
  "karma-jasmine-html-reporter": "^2.2.0",
44
- "typescript": "~5.9.2",
45
- "vitest": "^4.1.5"
43
+ "typescript": "~6.0.0",
44
+ "vitest": "^4.1.9"
46
45
  }
47
46
  }
@@ -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
+ }