utn-cli 2.0.27 → 2.0.29

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.
@@ -46,8 +46,8 @@ async function inicializarProyectoBackend() {
46
46
  const oldFileName = path.join(process.cwd(), 'NOMBRE_DEL_CANONICO_DEL_PROYECTO.rest');
47
47
  const newFileName = path.join(process.cwd(), `${val}.rest`);
48
48
  if (fs.existsSync(newFileName)) {
49
- // If the new file name already exists, do nothing.
50
- return;
49
+ // If the new file name already exists, do nothing.
50
+ return;
51
51
  }
52
52
  if (fs.existsSync(oldFileName)) {
53
53
  fs.renameSync(oldFileName, newFileName);
@@ -124,7 +124,7 @@ async function inicializarProyectoBackend() {
124
124
 
125
125
  export async function initBackend() {
126
126
  console.log('Limpiando directorio actual...');
127
- limpiarDirectorioActual(['commit-message.txt']);
127
+ limpiarDirectorioActual(['commit-message.txt', '.git']);
128
128
  console.log('Inicializando el proyecto de backend...');
129
129
 
130
130
  const directoriodePlantillas = path.join(__dirname, '../templates/backend');
package/commands/db.js CHANGED
@@ -8,7 +8,7 @@ const __dirname = path.dirname(__filename);
8
8
 
9
9
  export async function initDb() {
10
10
  console.log('Limpiando directorio actual...');
11
- limpiarDirectorioActual(['commit-message.txt']); // Assuming this is still relevant for DB
11
+ limpiarDirectorioActual(['commit-message.txt', '.git']); // Assuming this is still relevant for DB
12
12
  console.log('Inicializando el proyecto de base de datos...');
13
13
 
14
14
  const directoriodePlantillas = path.join(__dirname, '../templates/bd');
@@ -19,9 +19,9 @@ export async function initDb() {
19
19
  closeReadLine();
20
20
  process.exit(1);
21
21
  }
22
-
22
+
23
23
  copiarDirectorios(directoriodePlantillas, directorioDestino);
24
-
24
+
25
25
  // Specific renames for DB
26
26
  // This needs to be handled carefully, as original was 'cumulodb-scripts/gitignore' to 'cumulodb-scripts/.gitignore'
27
27
  // and now templates are nested.
@@ -9,7 +9,7 @@ const __dirname = path.dirname(__filename);
9
9
 
10
10
  export async function initFrontend() {
11
11
  console.log('Limpiando directorio actual...');
12
- limpiarDirectorioActual(['commit-message.txt']);
12
+ limpiarDirectorioActual(['commit-message.txt', '.git']);
13
13
  console.log('Inicializando el proyecto de frontend...');
14
14
  const directoriodePlantillas = path.join(__dirname, '../templates/frontend');
15
15
  const directorioDestino = process.cwd();
@@ -21,7 +21,7 @@ export async function initFrontend() {
21
21
  }
22
22
 
23
23
  copiarDirectorios(directoriodePlantillas, directorioDestino);
24
-
24
+
25
25
  // Specific renames for Frontend
26
26
  const gitignorePath = path.join(directorioDestino, 'gitignore');
27
27
  if (fs.existsSync(gitignorePath)) {
@@ -67,7 +67,7 @@ export async function cloneFrontendComponent() {
67
67
  closeReadLine();
68
68
  process.exit(1);
69
69
  }
70
-
70
+
71
71
  const titulo = await hacerPreguntaTrim('Ingrese el título para la tarjeta: ');
72
72
  const descripcion = await hacerPreguntaTrim('Ingrese la descripción para la tarjeta: ');
73
73
 
@@ -75,7 +75,7 @@ export async function cloneFrontendComponent() {
75
75
  const nombreCapitalizado = nombre.charAt(0).toUpperCase() + nombre.slice(1);
76
76
  const nombreClase = `GestionTabla${nombreCapitalizado}Component`;
77
77
  const nombreRuta = `gestion-tabla-${nombreLower}`;
78
-
78
+
79
79
  const rutaFuente = path.join(__dirname, '../templates/frontend', 'src', 'app', 'Paginas', 'gestion-tabla-XYZ');
80
80
  const rutaDestino = path.join(process.cwd(), 'src', 'app', 'Paginas', nombreRuta);
81
81
 
@@ -99,19 +99,19 @@ export async function cloneFrontendComponent() {
99
99
  }
100
100
  const entradas = fs.readdirSync(fuente, { withFileTypes: true });
101
101
  entradas.forEach((entrada) => {
102
- const nombreOriginal = entrada.name;
103
- const nombreNuevo = nombreOriginal.replace(/XYZ/g, nombreLower);
104
- const rutaFuente = path.join(fuente, nombreOriginal);
105
- const rutaDestino = path.join(destino, nombreNuevo);
106
-
107
- if (entrada.isDirectory()) {
108
- copiarYReemplazar(rutaFuente, rutaDestino);
109
- } else if (entrada.isFile()) {
110
- let contenido = fs.readFileSync(rutaFuente, 'utf-8');
111
- contenido = contenido.replace(/GestionTablaXYZComponent/g, nombreClase);
112
- contenido = contenido.replace(/XYZ/g, nombreLower);
113
- fs.writeFileSync(rutaDestino, contenido);
114
- }
102
+ const nombreOriginal = entrada.name;
103
+ const nombreNuevo = nombreOriginal.replace(/XYZ/g, nombreLower);
104
+ const rutaFuente = path.join(fuente, nombreOriginal);
105
+ const rutaDestino = path.join(destino, nombreNuevo);
106
+
107
+ if (entrada.isDirectory()) {
108
+ copiarYReemplazar(rutaFuente, rutaDestino);
109
+ } else if (entrada.isFile()) {
110
+ let contenido = fs.readFileSync(rutaFuente, 'utf-8');
111
+ contenido = contenido.replace(/GestionTablaXYZComponent/g, nombreClase);
112
+ contenido = contenido.replace(/XYZ/g, nombreLower);
113
+ fs.writeFileSync(rutaDestino, contenido);
114
+ }
115
115
  });
116
116
  }
117
117
 
@@ -123,56 +123,56 @@ export async function cloneFrontendComponent() {
123
123
  const rutaRoutes = path.join(process.cwd(), 'src', 'app', 'app.routes.ts');
124
124
  if (fs.existsSync(rutaRoutes)) {
125
125
  let contenidoRoutes = fs.readFileSync(rutaRoutes, 'utf-8');
126
-
126
+
127
127
  const lineaImport = `import { ${nombreClase} } from './Paginas/${nombreRuta}/${nombreRuta}.component';`;
128
128
  const ultimoImportIndex = contenidoRoutes.lastIndexOf('import {');
129
129
  const finUltimoImport = contenidoRoutes.indexOf(';', ultimoImportIndex);
130
-
130
+
131
131
  if (finUltimoImport !== -1) {
132
- contenidoRoutes = contenidoRoutes.slice(0, finUltimoImport + 1) + '\n' + lineaImport + contenidoRoutes.slice(finUltimoImport + 1);
132
+ contenidoRoutes = contenidoRoutes.slice(0, finUltimoImport + 1) + '\n' + lineaImport + contenidoRoutes.slice(finUltimoImport + 1);
133
133
  } else {
134
- contenidoRoutes = lineaImport + '\n' + contenidoRoutes;
134
+ contenidoRoutes = lineaImport + '\n' + contenidoRoutes;
135
135
  }
136
136
 
137
137
  const cierreArray = contenidoRoutes.lastIndexOf('];');
138
138
  if (cierreArray !== -1) {
139
- const nuevaRuta = ` { path: '${nombreRuta}', component: ${nombreClase} },`;
140
- const textoAntesDeCierre = contenidoRoutes.slice(0, cierreArray).trimEnd();
141
- const necesitaComa = !textoAntesDeCierre.endsWith(',') && !textoAntesDeCierre.endsWith('[');
142
-
143
- contenidoRoutes = contenidoRoutes.slice(0, cierreArray) +
144
- (necesitaComa ? ',' : '') + '\n' +
145
- nuevaRuta + '\n' +
146
- contenidoRoutes.slice(cierreArray);
147
-
148
- fs.writeFileSync(rutaRoutes, contenidoRoutes);
149
- console.log('Ruta agregada exitosamente.');
139
+ const nuevaRuta = ` { path: '${nombreRuta}', component: ${nombreClase} },`;
140
+ const textoAntesDeCierre = contenidoRoutes.slice(0, cierreArray).trimEnd();
141
+ const necesitaComa = !textoAntesDeCierre.endsWith(',') && !textoAntesDeCierre.endsWith('[');
142
+
143
+ contenidoRoutes = contenidoRoutes.slice(0, cierreArray) +
144
+ (necesitaComa ? ',' : '') + '\n' +
145
+ nuevaRuta + '\n' +
146
+ contenidoRoutes.slice(cierreArray);
147
+
148
+ fs.writeFileSync(rutaRoutes, contenidoRoutes);
149
+ console.log('Ruta agregada exitosamente.');
150
150
  } else {
151
- console.error('No se pudo encontrar el array de rutas en app.routes.ts');
151
+ console.error('No se pudo encontrar el array de rutas en app.routes.ts');
152
152
  }
153
153
  } else {
154
- console.error(`No se encontró el archivo de rutas en: ${rutaRoutes}`);
154
+ console.error(`No se encontró el archivo de rutas en: ${rutaRoutes}`);
155
155
  }
156
156
 
157
157
  // --- Modificar contenedor-principal.component.html ---
158
158
  console.log('Actualizando contenedor-principal.component.html...');
159
159
  const rutaHtml = path.join(process.cwd(), 'src', 'app', 'Paginas', 'contenedor-principal', 'contenedor-principal.component.html');
160
160
  if (fs.existsSync(rutaHtml)) {
161
- let contenidoHtml = fs.readFileSync(rutaHtml, 'utf-8');
162
-
163
- const nuevaTarjeta = ` <app-tarjeta [rutaASeguir]="'${nombreRuta}'" titulo="${titulo}" descripcion="${descripcion}" icono="table_chart"></app-tarjeta>`;
164
-
165
- const ultimoDiv = contenidoHtml.lastIndexOf('</div>');
166
-
167
- if (ultimoDiv !== -1) {
168
- contenidoHtml = contenidoHtml.slice(0, ultimoDiv) + '\n' + nuevaTarjeta + '\n' + contenidoHtml.slice(ultimoDiv);
169
- fs.writeFileSync(rutaHtml, contenidoHtml);
170
- console.log('Tarjeta agregada exitosamente.');
171
- } else {
172
- console.error('No se encontró un </div> de cierre en el HTML del contenedor principal.');
173
- }
161
+ let contenidoHtml = fs.readFileSync(rutaHtml, 'utf-8');
162
+
163
+ const nuevaTarjeta = ` <app-tarjeta [rutaASeguir]="'${nombreRuta}'" titulo="${titulo}" descripcion="${descripcion}" icono="table_chart"></app-tarjeta>`;
164
+
165
+ const ultimoDiv = contenidoHtml.lastIndexOf('</div>');
166
+
167
+ if (ultimoDiv !== -1) {
168
+ contenidoHtml = contenidoHtml.slice(0, ultimoDiv) + '\n' + nuevaTarjeta + '\n' + contenidoHtml.slice(ultimoDiv);
169
+ fs.writeFileSync(rutaHtml, contenidoHtml);
170
+ console.log('Tarjeta agregada exitosamente.');
171
+ } else {
172
+ console.error('No se encontró un </div> de cierre en el HTML del contenedor principal.');
173
+ }
174
174
  } else {
175
- console.error(`No se encontró el archivo HTML en: ${rutaHtml}`);
175
+ console.error(`No se encontró el archivo HTML en: ${rutaHtml}`);
176
176
  }
177
177
  closeReadLine();
178
178
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utn-cli",
3
- "version": "2.0.27",
3
+ "version": "2.0.29",
4
4
  "description": "Herramienta CLI unificada para la gestión de plantillas en SIGU.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -299,6 +299,11 @@ tr.example-element-row:hover {
299
299
  gap: 10px !important; /* Espacio uniforme entre elementos */
300
300
  }
301
301
 
302
+ .contenedor-columnas {
303
+ width: 100%;
304
+ justify-content: center;
305
+ }
306
+
302
307
  /* Forzamos que Input, Select y Botón sean idénticos en ancho */
303
308
  .custom-input,
304
309
  mat-select.custom-input,
@@ -9,6 +9,20 @@
9
9
  </div>
10
10
  <div class="centro"></div>
11
11
  <div class="derecha">
12
+ <mat-menu #menuColumnas="matMenu">
13
+ @for(col of columnas; track $index){
14
+ <button mat-menu-item>
15
+ <mat-checkbox [(ngModel)]="col.Visible" (change)="recalcularColumnas()">
16
+ {{ col.Alias }}
17
+ </mat-checkbox>
18
+ </button>
19
+ }
20
+ </mat-menu>
21
+ <div class="contenedor-columnas">
22
+ <button mat-icon-button [matMenuTriggerFor]="menuColumnas" matTooltip="Mostrar/Ocultar columnas">
23
+ <mat-icon>view_column</mat-icon>
24
+ </button>
25
+ </div>
12
26
  <input #valorFiltroInput id="valorFiltro" type="text" class="custom-input" placeholder="Filtrar"
13
27
  (keydown.enter)="AplicarFiltro()">
14
28
  @if(mostrarElBotonDeFiltro){
@@ -11,6 +11,9 @@ import { MatSelectModule } from '@angular/material/select';
11
11
  import { MensajeConfirmacionComponent } from '../mensaje-confirmacion/mensaje-confirmacion';
12
12
  import { MatDialog } from '@angular/material/dialog';
13
13
  import { MatBadgeModule } from '@angular/material/badge';
14
+ import { MatMenuModule } from '@angular/material/menu';
15
+ import { MatCheckboxModule } from '@angular/material/checkbox';
16
+ import { FormsModule } from '@angular/forms';
14
17
 
15
18
  @Component({
16
19
  selector: 'app-tabla',
@@ -31,20 +34,24 @@ import { MatBadgeModule } from '@angular/material/badge';
31
34
  MatSortModule,
32
35
  MatInputModule,
33
36
  MatSelectModule,
34
- MatBadgeModule],
37
+ MatBadgeModule,
38
+ MatMenuModule,
39
+ MatCheckboxModule,
40
+ FormsModule,
41
+ ],
35
42
  templateUrl: './tabla.component.html',
36
43
  styleUrl: './tabla.component.css'
37
44
  })
38
45
  export class TablaComponent implements OnInit, OnChanges {
39
- @Input() columnas: { Llave: string, Alias: string, TipoDeFiltro: string }[] = [];
46
+ @Input() columnas: { Llave: string, Alias: string, TipoDeFiltro: string, Visible?: boolean }[] = [];
40
47
  @Input() subColumnas: { Llave: string, Alias: string }[] = [];
41
48
  @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; }[] = [];
49
+ @Input() acciones: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; }[] = [];
50
+ @Input() accionesDinamicas: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; Mostrar: (row: any) => boolean }[] = [];
51
+ @Input() accionesSiempreClickeable: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; }[] = [];
52
+ @Input() subAcciones: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; }[] = [];
46
53
  @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 }[] = [];
54
+ @Input() subAccionesDinamicas: { icono: string; color: string; textoAyuda: string; ejecutar: (row: any) => void; badge?: (row: any) => string | number | undefined | null; Mostrar: (row: any) => boolean }[] = [];
48
55
  @Input() desplegable: boolean = false
49
56
  @Input() atributoDesplegable: string = ''
50
57
  public llavesColumnas: string[] = [];
@@ -147,17 +154,31 @@ export class TablaComponent implements OnInit, OnChanges {
147
154
  }
148
155
 
149
156
  private inicializarColumnas(): void {
150
- this.llavesColumnas = this.columnas.map(c => c.Llave);
151
- this.tieneColumnaEstado = this.columnas.some(c => c.Llave === 'Estado');
157
+ this.columnas.forEach(c => {
158
+ if (c.Visible === undefined) {
159
+ c.Visible = true;
160
+ }
161
+ });
162
+ this.recalcularColumnas();
163
+ }
152
164
 
153
- if (this.acciones.length || this.accionesSiempreClickeable.length || this.accionesDinamicas.length) {
165
+ public recalcularColumnas(): void {
166
+ const columnasVisibles = this.columnas.filter(c => c.Visible).map(c => c.Llave);
167
+ this.llavesColumnas = [];
168
+ if (this.desplegable) {
169
+ this.llavesColumnas.push('expand');
170
+ }
171
+ this.llavesColumnas.push(...columnasVisibles);
172
+ this.tieneColumnaEstado = this.columnas.some(c => c.Llave === 'Estado');
173
+ if (this.acciones.length ||
174
+ this.accionesSiempreClickeable.length ||
175
+ this.accionesDinamicas.length) {
154
176
  this.llavesColumnas.push('acciones');
155
177
  }
156
-
157
178
  if (this.desplegable) {
158
- this.llavesColumnas.unshift('expand');
159
179
  this.llavesSubColumnas = this.subColumnas.map(c => c.Llave);
160
- if (this.subAcciones.length || this.subAccionesSiempreClickeable.length) {
180
+ if (this.subAcciones.length ||
181
+ this.subAccionesSiempreClickeable.length) {
161
182
  this.llavesSubColumnas.push('subAcciones');
162
183
  }
163
184
  }