utn-cli 2.1.39 → 2.1.40
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 +1 -1
- package/templates/frontend/src/app/Componentes/Nucleo/reordenar-menu/reordenar-menu.component.css +65 -0
- package/templates/frontend/src/app/Componentes/Nucleo/reordenar-menu/reordenar-menu.component.html +17 -0
- package/templates/frontend/src/app/Componentes/Nucleo/reordenar-menu/reordenar-menu.component.ts +41 -0
- package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.html +8 -19
- package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.ts +89 -1
package/package.json
CHANGED
package/templates/frontend/src/app/Componentes/Nucleo/reordenar-menu/reordenar-menu.component.css
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
.instruccion {
|
|
2
|
+
font-size: 0.875rem;
|
|
3
|
+
color: #555;
|
|
4
|
+
margin: 0 0 1rem 0;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.lista-items {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
gap: 0.5rem;
|
|
11
|
+
min-width: 280px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.item {
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
gap: 0.75rem;
|
|
18
|
+
padding: 0.75rem 1rem;
|
|
19
|
+
border-radius: 8px;
|
|
20
|
+
background: #f5f8ff;
|
|
21
|
+
border-left: 4px solid #1976d2;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.handle {
|
|
25
|
+
color: #999;
|
|
26
|
+
cursor: grab;
|
|
27
|
+
flex-shrink: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.handle:active {
|
|
31
|
+
cursor: grabbing;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.item-icono {
|
|
35
|
+
color: #1976d2;
|
|
36
|
+
flex-shrink: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.item-etiqueta {
|
|
40
|
+
flex: 1;
|
|
41
|
+
font-size: 0.95rem;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.cdk-drag-preview {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: 0.75rem;
|
|
48
|
+
padding: 0.75rem 1rem;
|
|
49
|
+
border-radius: 8px;
|
|
50
|
+
background: white;
|
|
51
|
+
border-left: 4px solid #1976d2;
|
|
52
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.cdk-drag-placeholder {
|
|
56
|
+
opacity: 0.3;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.cdk-drag-animating {
|
|
60
|
+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.lista-items.cdk-drop-list-dragging .item:not(.cdk-drag-placeholder) {
|
|
64
|
+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
|
65
|
+
}
|
package/templates/frontend/src/app/Componentes/Nucleo/reordenar-menu/reordenar-menu.component.html
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<h2 mat-dialog-title>Reordenar menú</h2>
|
|
2
|
+
<mat-dialog-content>
|
|
3
|
+
<p class="instruccion">Arrastrá los elementos para cambiar el orden.</p>
|
|
4
|
+
<div cdkDropList (cdkDropListDropped)="drop($event)" class="lista-items">
|
|
5
|
+
@for (item of items; track item.id) {
|
|
6
|
+
<div cdkDrag class="item">
|
|
7
|
+
<mat-icon cdkDragHandle class="handle">drag_indicator</mat-icon>
|
|
8
|
+
<mat-icon class="item-icono">{{ item.icono }}</mat-icon>
|
|
9
|
+
<span class="item-etiqueta">{{ item.etiqueta }}</span>
|
|
10
|
+
</div>
|
|
11
|
+
}
|
|
12
|
+
</div>
|
|
13
|
+
</mat-dialog-content>
|
|
14
|
+
<mat-dialog-actions>
|
|
15
|
+
<button mat-button (click)="cancelar()">Cancelar</button>
|
|
16
|
+
<button mat-flat-button color="primary" (click)="guardar()">Guardar</button>
|
|
17
|
+
</mat-dialog-actions>
|
package/templates/frontend/src/app/Componentes/Nucleo/reordenar-menu/reordenar-menu.component.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Component, Inject } from '@angular/core';
|
|
2
|
+
import { MAT_DIALOG_DATA, MatDialogRef, MatDialogTitle, MatDialogContent, MatDialogActions } from '@angular/material/dialog';
|
|
3
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
4
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
5
|
+
import { DragDropModule, CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
|
6
|
+
|
|
7
|
+
export interface ItemDeMenuDialog {
|
|
8
|
+
id: string;
|
|
9
|
+
etiqueta: string;
|
|
10
|
+
icono: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@Component({
|
|
14
|
+
selector: 'app-reordenar-menu',
|
|
15
|
+
standalone: true,
|
|
16
|
+
imports: [MatDialogTitle, MatDialogContent, MatDialogActions, MatButtonModule, MatIconModule, DragDropModule],
|
|
17
|
+
templateUrl: './reordenar-menu.component.html',
|
|
18
|
+
styleUrl: './reordenar-menu.component.css'
|
|
19
|
+
})
|
|
20
|
+
export class ReordenarMenuComponent {
|
|
21
|
+
items: ItemDeMenuDialog[];
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
@Inject(MAT_DIALOG_DATA) public data: { items: ItemDeMenuDialog[] },
|
|
25
|
+
private dialogRef: MatDialogRef<ReordenarMenuComponent>
|
|
26
|
+
) {
|
|
27
|
+
this.items = [...data.items];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
drop(event: CdkDragDrop<ItemDeMenuDialog[]>): void {
|
|
31
|
+
moveItemInArray(this.items, event.previousIndex, event.currentIndex);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
guardar(): void {
|
|
35
|
+
this.dialogRef.close(this.items);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
cancelar(): void {
|
|
39
|
+
this.dialogRef.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -130,27 +130,16 @@
|
|
|
130
130
|
</button>
|
|
131
131
|
|
|
132
132
|
<mat-menu #menuAplicaciones="matMenu">
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
@if(TienePermiso) {
|
|
138
|
-
<button mat-menu-item (click)="irAActividad()" title="Actividad de la cuenta">
|
|
139
|
-
<mat-icon>history</mat-icon>
|
|
140
|
-
<span>Actividad de la cuenta</span>
|
|
141
|
-
</button>
|
|
142
|
-
<button mat-menu-item (click)="irAEstadisticasDelModulo()" title="Estadísticas del módulo">
|
|
143
|
-
<mat-icon>bar_chart</mat-icon>
|
|
144
|
-
<span>Estadísticas del módulo</span>
|
|
133
|
+
@for (item of itemsDeMenuVisibles; track item.id) {
|
|
134
|
+
<button mat-menu-item (click)="item.accion()" [title]="item.etiqueta">
|
|
135
|
+
<mat-icon>{{ item.icono }}</mat-icon>
|
|
136
|
+
<span>{{ item.etiqueta }}</span>
|
|
145
137
|
</button>
|
|
146
138
|
}
|
|
147
|
-
<
|
|
148
|
-
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
<button mat-menu-item (click)="irADeclaracionIA()" title="Declaración de uso de inteligencia artificial">
|
|
152
|
-
<mat-icon>smart_toy</mat-icon>
|
|
153
|
-
<span>Declaración de IA</span>
|
|
139
|
+
<mat-divider></mat-divider>
|
|
140
|
+
<button mat-menu-item (click)="abrirDialogReordenarMenu()" title="Reordenar elementos del menú">
|
|
141
|
+
<mat-icon>sort</mat-icon>
|
|
142
|
+
<span>Reordenar</span>
|
|
154
143
|
</button>
|
|
155
144
|
</mat-menu>
|
|
156
145
|
|
|
@@ -6,17 +6,28 @@ import { Location, CommonModule } from '@angular/common';
|
|
|
6
6
|
import { MatIconModule } from '@angular/material/icon';
|
|
7
7
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
8
8
|
import { MatDialog } from '@angular/material/dialog';
|
|
9
|
+
import { MatDividerModule } from '@angular/material/divider';
|
|
9
10
|
import { ReporteDeIncidenciasComponent } from '../../../Componentes/Nucleo/reporte-de-incidencias/reporte-de-incidencias.component';
|
|
10
11
|
import { MensajesComponent } from '../../../Componentes/Nucleo/mensajes/mensajes.component';
|
|
11
12
|
import { MensajeConfirmacionHTMLComponent } from '../../../Componentes/Nucleo/mensaje-confirmacion-html/mensaje-confirmacion-html';
|
|
12
13
|
import { ReporteDeSugerenciasComponent } from '../../../Componentes/Nucleo/reporte-de-sugerencias/reporte-de-sugerencias.component';
|
|
13
14
|
import { EstadisticasDelModuloComponent } from '../../../Componentes/Nucleo/estadisticas-del-modulo/estadisticas-del-modulo.component';
|
|
15
|
+
import { ReordenarMenuComponent, ItemDeMenuDialog } from '../../../Componentes/Nucleo/reordenar-menu/reordenar-menu.component';
|
|
14
16
|
|
|
15
17
|
import { MatMenuModule } from '@angular/material/menu';
|
|
16
18
|
|
|
19
|
+
interface ItemDeMenu {
|
|
20
|
+
id: string;
|
|
21
|
+
etiqueta: string;
|
|
22
|
+
icono: string;
|
|
23
|
+
accion: () => void;
|
|
24
|
+
requierePermiso: boolean;
|
|
25
|
+
posicion: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
17
28
|
@Component({
|
|
18
29
|
selector: 'app-contenedor-componentes',
|
|
19
|
-
imports: [RouterOutlet, MatIconModule, MatTooltipModule, CommonModule, MatMenuModule],
|
|
30
|
+
imports: [RouterOutlet, MatIconModule, MatTooltipModule, CommonModule, MatMenuModule, MatDividerModule],
|
|
20
31
|
templateUrl: './contenedor-componentes.component.html',
|
|
21
32
|
styleUrl: './contenedor-componentes.component.css'
|
|
22
33
|
})
|
|
@@ -41,6 +52,12 @@ export class ContenedorComponentesComponent implements OnInit, OnDestroy, AfterV
|
|
|
41
52
|
public AnimarUsuariosActivos: boolean = true;
|
|
42
53
|
private intervaloUsuarios: any;
|
|
43
54
|
|
|
55
|
+
public itemsDeMenu: ItemDeMenu[] = [];
|
|
56
|
+
|
|
57
|
+
get itemsDeMenuVisibles(): ItemDeMenu[] {
|
|
58
|
+
return this.itemsDeMenu.filter(i => !i.requierePermiso || this.TienePermiso);
|
|
59
|
+
}
|
|
60
|
+
|
|
44
61
|
get esDashboard(): boolean { return this.router.url === '/'; }
|
|
45
62
|
get tieneTarjetas(): boolean { return this.datosGlobalesService.cantidadDeTarjetas$.value > 0; }
|
|
46
63
|
get filtro(): string { return this.datosGlobalesService.filtroDeTarjetas$.value; }
|
|
@@ -69,7 +86,78 @@ export class ContenedorComponentesComponent implements OnInit, OnDestroy, AfterV
|
|
|
69
86
|
return datos ? JSON.parse(datos) : [];
|
|
70
87
|
}
|
|
71
88
|
|
|
89
|
+
private inicializarItemsDeMenu(): void {
|
|
90
|
+
this.itemsDeMenu = [
|
|
91
|
+
{ id: 'nav_sugerencias', etiqueta: 'Sugerencias', icono: 'lightbulb', accion: () => this.irASugerencias(), requierePermiso: false, posicion: 10 },
|
|
92
|
+
{ id: 'nav_actividad', etiqueta: 'Actividad de la cuenta', icono: 'history', accion: () => this.irAActividad(), requierePermiso: true, posicion: 20 },
|
|
93
|
+
{ id: 'nav_estadisticas', etiqueta: 'Estadísticas del módulo', icono: 'bar_chart', accion: () => this.irAEstadisticasDelModulo(), requierePermiso: true, posicion: 30 },
|
|
94
|
+
{ id: 'nav_accesibilidad', etiqueta: 'Accesibilidad', icono: 'accessibility', accion: () => this.irAAccesibilidad(), requierePermiso: false, posicion: 40 },
|
|
95
|
+
{ id: 'nav_declaracion_ia', etiqueta: 'Declaración de IA', icono: 'smart_toy', accion: () => this.irADeclaracionIA(), requierePermiso: false, posicion: 50 },
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private cargarOrdenDelMenu(): void {
|
|
100
|
+
this.http.get(`${this.datosGlobalesService.ObtenerURL()}ConfiguracionDeTarjetas/obtener`).subscribe({
|
|
101
|
+
next: (datos: any) => {
|
|
102
|
+
const config: { Titulo: string; Posicion: number }[] = datos.body ?? [];
|
|
103
|
+
const navConfig = config.filter((c: any) => c.Titulo.startsWith('nav_'));
|
|
104
|
+
if (navConfig.length === 0) return;
|
|
105
|
+
navConfig.forEach((c: any) => {
|
|
106
|
+
const item = this.itemsDeMenu.find(i => i.id === c.Titulo);
|
|
107
|
+
if (item) item.posicion = c.Posicion;
|
|
108
|
+
});
|
|
109
|
+
this.itemsDeMenu.sort((a, b) => a.posicion - b.posicion);
|
|
110
|
+
},
|
|
111
|
+
error: () => { }
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
abrirDialogReordenarMenu(): void {
|
|
116
|
+
const itemsVisibles: ItemDeMenuDialog[] = this.itemsDeMenuVisibles.map(i => ({
|
|
117
|
+
id: i.id,
|
|
118
|
+
etiqueta: i.etiqueta,
|
|
119
|
+
icono: i.icono
|
|
120
|
+
}));
|
|
121
|
+
|
|
122
|
+
this.dialog.open(ReordenarMenuComponent, { data: { items: itemsVisibles } })
|
|
123
|
+
.afterClosed()
|
|
124
|
+
.subscribe((resultado: ItemDeMenuDialog[] | undefined) => {
|
|
125
|
+
if (!resultado) return;
|
|
126
|
+
this.persistirOrdenDelMenu(resultado);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private persistirOrdenDelMenu(itemsOrdenados: ItemDeMenuDialog[]): void {
|
|
131
|
+
const idsOrdenados = itemsOrdenados.map(i => i.id);
|
|
132
|
+
const itemsNoVisibles = this.itemsDeMenu.filter(i => !idsOrdenados.includes(i.id));
|
|
133
|
+
const itemsVisiblesReordenados = idsOrdenados
|
|
134
|
+
.map(id => this.itemsDeMenu.find(i => i.id === id)!)
|
|
135
|
+
.filter(Boolean);
|
|
136
|
+
|
|
137
|
+
itemsVisiblesReordenados.forEach((item, index) => {
|
|
138
|
+
item.posicion = (index + 1) * 10;
|
|
139
|
+
});
|
|
140
|
+
itemsNoVisibles.forEach((item, index) => {
|
|
141
|
+
item.posicion = (itemsVisiblesReordenados.length + index + 1) * 10;
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
this.itemsDeMenu = [...itemsVisiblesReordenados, ...itemsNoVisibles];
|
|
145
|
+
|
|
146
|
+
const Configuraciones = this.itemsDeMenu.map(i => ({
|
|
147
|
+
Titulo: i.id,
|
|
148
|
+
Posicion: i.posicion,
|
|
149
|
+
ColorDeBorde: null
|
|
150
|
+
}));
|
|
151
|
+
|
|
152
|
+
this.http.post(`${this.datosGlobalesService.ObtenerURL()}ConfiguracionDeTarjetas/actualizar`, {
|
|
153
|
+
Configuraciones
|
|
154
|
+
}).subscribe({ error: () => { } });
|
|
155
|
+
}
|
|
156
|
+
|
|
72
157
|
ngOnInit() {
|
|
158
|
+
this.inicializarItemsDeMenu();
|
|
159
|
+
this.cargarOrdenDelMenu();
|
|
160
|
+
|
|
73
161
|
const url = window.location.href.toLowerCase();
|
|
74
162
|
if (url.includes('calidad')) {
|
|
75
163
|
this.claseDelContenedor = 'contenedor calidad';
|