Merge branch 'oggui/ogboot' into oggui/ogdhcp

oggui/ogdhcp
Alvaro Puente Mella 2024-09-02 14:21:18 +02:00
commit 6be00b2e22
12 changed files with 168 additions and 52 deletions

View File

@ -11,13 +11,10 @@ export class DataService {
constructor(private http: HttpClient) {}
getImages(search: string = ''): Observable<any[]> {
let url = `${this.apiUrl}`;
if (search) {
url += `&name=${encodeURIComponent(search)}`;
}
getImages(filters: { [key: string]: string }): Observable<any[]> {
const params = new HttpParams({ fromObject: filters });
return this.http.get<any>(url).pipe(
return this.http.get<any>(this.apiUrl, { params }).pipe(
map(response => {
if (response['hydra:member'] && Array.isArray(response['hydra:member'])) {
return response['hydra:member'];

View File

@ -46,8 +46,23 @@ table {
margin-top: 50px;
}
.search-container mat-form-field {
.search-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 0 5px;
box-sizing: border-box;
}
.search-string {
flex: 2;
padding: 5px;
}
.search-boolean {
flex: 1;
padding: 5px;
}
.header-container {

View File

@ -23,12 +23,28 @@
</div>
<mat-divider class="divider"></mat-divider>
<div class="search-container">
<mat-form-field appearance="fill">
<mat-form-field appearance="fill" class="search-string">
<mat-label i18n="@@searchLabel">Buscar nombre de imagen</mat-label>
<input matInput placeholder="Búsqueda" [(ngModel)]="searchTerm" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
<mat-icon matSuffix>search</mat-icon>
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill" class="search-boolean">
<mat-label i18n="@@searchLabel">Imagen por defecto</mat-label>
<mat-select [(ngModel)]="filters['isDefault']" (selectionChange)="search()" placeholder="Seleccionar opción" >
<mat-option [value]="''">Todos</mat-option>
<mat-option [value]="true"></mat-option>
<mat-option [value]="false">No</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill" class="search-boolean">
<mat-label i18n="@@searchLabel">Instalado servidor ogBoot</mat-label>
<mat-select [(ngModel)]="filters['installed']" (selectionChange)="search()" placeholder="Seleccionar opción">
<mat-option [value]="''">Todos</mat-option>
<mat-option [value]="true"></mat-option>
<mat-option [value]="false">No</mat-option>
</mat-select>
</mat-form-field>
</div>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">

View File

@ -24,7 +24,7 @@ export class ImagesComponent implements OnInit {
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
selectedElements: string[] = [];
loading:boolean = false;
searchTerm: string = '';
filters: { [key: string]: string } = {};
alertMessage: string | null = null;
readonly panelOpenState = signal(false);
datePipe: DatePipe = new DatePipe('es-ES');
@ -89,7 +89,7 @@ export class ImagesComponent implements OnInit {
search(): void {
this.loading = true;
this.dataService.getImages(this.searchTerm).subscribe(
this.dataService.getImages(this.filters).subscribe(
data => {
this.dataSource.data = data;
this.loading = false;

View File

@ -0,0 +1,39 @@
import { Injectable } from '@angular/core';
import {HttpClient, HttpParams} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { DataService as TemplateDataService } from './../pxe/data.service';
@Injectable({
providedIn: 'root'
})
export class DataService {
private apiUrl = 'http://127.0.0.1:8080/pxe-boot-files?page=1&itemsPerPage=1000';
constructor(
private http: HttpClient,
private templateDataService: TemplateDataService
) {}
getPxeBootFiles(filters: { [key: string]: string }): Observable<any[]> {
const params = new HttpParams({ fromObject: filters });
return this.http.get<any>(this.apiUrl, { params }).pipe(
map(response => {
if (response['hydra:member'] && Array.isArray(response['hydra:member'])) {
return response['hydra:member'];
} else {
throw new Error('Unexpected response format');
}
}),
catchError(error => {
console.error('Error fetching images', error);
return throwError(error);
})
);
}
getPxeTemplateOptions(): Observable<any[]> {
return this.templateDataService.getPxeTemplates({});
}
}

View File

@ -60,6 +60,25 @@ table {
margin-top: 50px;
}
.search-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 0 5px;
box-sizing: border-box;
}
.search-string {
flex: 2;
padding: 5px;
}
.search-entity {
flex: 1;
padding: 5px;
}
.mat-elevation-z8 {
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
}

View File

@ -20,6 +20,15 @@
</div>
<mat-divider class="divider"></mat-divider>
<div class="search-container">
<mat-form-field appearance="fill" class="search-entity">
<mat-label i18n="@@searchLabel">Plantilla</mat-label>
<mat-select [(ngModel)]="filters['template']" (selectionChange)="search()" placeholder="Seleccionar entidad">
<mat-option [value]="''">Todos</mat-option>
<mat-option *ngFor="let template of templateOptions" [value]="template.id">{{ template.name }}</mat-option>
</mat-select>
</mat-form-field>
</div>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
<th mat-header-cell *matHeaderCellDef>{{column.header}}</th>

View File

@ -6,6 +6,7 @@ import { CreatePxeTemplateComponent } from '../pxe/create-pxeTemplate/create-pxe
import {PageEvent} from "@angular/material/paginator";
import {ToastrService} from "ngx-toastr";
import {DatePipe} from "@angular/common";
import {DataService} from "./data.service";
@Component({
selector: 'app-pxe-boot-files',
@ -19,10 +20,13 @@ export class PxeBootFilesComponent {
length: number = 0;
alertMessage: string | null = null;
itemsPerPage: number = 10;
loading:boolean = false;
filters: { [key: string]: string } = {};
page: number = 1;
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
datePipe: DatePipe = new DatePipe('es-ES');
selectedElements: string[] = [];
templateOptions: any[] = [];
columns = [
{
columnDef: 'id',
@ -52,39 +56,36 @@ export class PxeBootFilesComponent {
constructor(
public dialog: MatDialog,
private http: HttpClient,
private toastService: ToastrService
private toastService: ToastrService,
private dataService: DataService
)
{ }
ngOnInit(): void {
this.loadPxeBootFiles();
this.search();
this.loadAlert();
}
loadPxeBootFiles(): void {
this.http.get<any>(`${this.apiUrl}?page=1&itemsPerPage=${this.itemsPerPage}`).subscribe({
next: (response) => {
this.dataSource.data = response['hydra:member'];
this.length = response['hydra:totalItems'];
console.log('Plantillas PXE cargadas:', this.pxeTemplates);
this.dataService.getPxeTemplateOptions().subscribe(
data => {
this.templateOptions = data;
},
error: error => {
console.error('Error al cargar plantillas PXE:', error);
error => {
console.error('Error fetching template options', error);
}
});
);
}
addPxeTemplate() {
const dialogRef = this.dialog.open(CreatePxeTemplateComponent, {
});
dialogRef.afterClosed().subscribe(() => {
this.loadPxeBootFiles();
});
}
showPxeInfo(template: any) {
search(): void {
this.loading = true;
this.dataService.getPxeBootFiles(this.filters).subscribe(
data => {
this.dataSource.data = data;
this.loading = false;
},
error => {
console.error('Error fetching pxe boot files', error);
this.loading = false;
}
);
}
toggleAction(image: any, action:string): void {
@ -93,7 +94,7 @@ export class PxeBootFilesComponent {
this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({
next: () => {
console.log('Plantilla cambiada');
this.loadPxeBootFiles();
this.search();
},
error: (error) => {
console.error('Error al cambiar la imagen:', error);
@ -104,7 +105,7 @@ export class PxeBootFilesComponent {
this.http.post(`${this.apiUrl}/server/${image.uuid}/delete`, {}).subscribe({
next: () => {
console.log('Plantilla cambiada');
this.loadPxeBootFiles();
this.search();
},
error: (error) => {
console.error('Error al cambiar la imagen:', error);
@ -127,7 +128,7 @@ export class PxeBootFilesComponent {
});
dialogRef.afterClosed().subscribe(() => {
this.loadPxeBootFiles();
this.search();
});
}
@ -186,7 +187,7 @@ export class PxeBootFilesComponent {
this.http.post(`${this.apiUrl}/sync`, {})
.subscribe(response => {
this.toastService.success('Sincronización completada');
this.loadPxeBootFiles()
this.search()
}, error => {
console.error('Error al sincronizar', error);
this.toastService.error('Error al sincronizar');

View File

@ -12,13 +12,10 @@ export class DataService {
constructor(private http: HttpClient) {}
getPxeTemplates(search: string = ''): Observable<any[]> {
let url = `${this.apiUrl}`;
if (search) {
url += `&name=${encodeURIComponent(search)}`;
}
getPxeTemplates(filters: { [key: string]: string }): Observable<any[]> {
const params = new HttpParams({ fromObject: filters });
return this.http.get<any>(url).pipe(
return this.http.get<any>(this.apiUrl, { params }).pipe(
map(response => {
if (response['hydra:member'] && Array.isArray(response['hydra:member'])) {
return response['hydra:member'];

View File

@ -54,8 +54,23 @@ table {
margin-top: 50px;
}
.search-container mat-form-field {
.search-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 0 5px;
box-sizing: border-box;
}
.search-string {
flex: 2;
padding: 5px;
}
.search-boolean {
flex: 1;
padding: 5px;
}
.header-container {

View File

@ -22,11 +22,19 @@
</div>
<mat-divider class="divider"></mat-divider>
<div class="search-container">
<mat-form-field appearance="fill">
<mat-form-field appearance="fill" class="search-string">
<mat-label i18n="@@searchLabel">Buscar nombre de plantilla</mat-label>
<input matInput placeholder="Búsqueda" [(ngModel)]="searchTerm" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
<mat-icon matSuffix>search</mat-icon>
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar </mat-hint>
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill" class="search-boolean">
<mat-label i18n="@@searchLabel">Creada en ogBoot</mat-label>
<mat-select [(ngModel)]="filters['synchronized']" (selectionChange)="search()" placeholder="Seleccionar opción" >
<mat-option [value]="''">Todos</mat-option>
<mat-option [value]="true"></mat-option>
<mat-option [value]="false">No</mat-option>
</mat-select>
</mat-form-field>
</div>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

View File

@ -23,8 +23,8 @@ export class PxeComponent {
page: number = 1;
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
selectedElements: string[] = [];
loading: boolean = false;
searchTerm: string = '';
loading:boolean = false;
filters: { [key: string]: string } = {};
alertMessage: string | null = null;
datePipe: DatePipe = new DatePipe('es-ES');
selectedItem: any = null;
@ -69,7 +69,7 @@ export class PxeComponent {
search(): void {
this.loading = true;
this.dataService.getPxeTemplates(this.searchTerm).subscribe(
this.dataService.getPxeTemplates(this.filters).subscribe(
data => {
this.dataSource.data = data;
this.loading = false;