Some improvements. Added filter search and refactor

oggui/ogboot
Manuel Aranda Rosales 2024-09-02 10:07:35 +02:00
parent 2d6785198f
commit cf3785d863
24 changed files with 359 additions and 311 deletions

View File

@ -10,7 +10,7 @@ import { UsersComponent } from './components/admin/users/users/users.component';
import { RolesComponent } from './components/admin/roles/roles/roles.component';
import { GroupsComponent } from './components/groups/groups.component';
import { ImagesComponent } from './components/ogboot/images/images.component';
import { PxeComponent } from './components/ogboot/pxe/pxe/pxe.component';
import { PxeComponent } from './components/ogboot/pxe/pxe.component';
import { PxeBootFilesComponent } from './components/ogboot/pxe-boot-files/pxe-boot-files.component';
import {OgbootStatusComponent} from "./components/ogboot/ogboot-status/ogboot-status.component";
import { OgdhcpComponent } from './components/ogdhcp/ogdhcp.component';

View File

@ -73,9 +73,9 @@ import { ImagesComponent } from './components/ogboot/images/images.component';
import { CreateImageComponent } from './components/ogboot/images/create-image/create-image/create-image.component';
import { EditImageComponent } from './components/ogboot/images/edit-image/edit-image/edit-image.component';
import { InfoImageComponent } from './components/ogboot/images/info-image/info-image/info-image.component';
import { PxeComponent } from './components/ogboot/pxe/pxe/pxe.component';
import { CreatePxeTemplateComponent } from './components/ogboot/pxe/pxe/create-pxeTemplate/create-pxe-template/create-pxe-template.component';
import { EditPxeTemplateComponent } from './components/ogboot/pxe/pxe/edit-pxe-template/edit-pxe-template.component';
import { PxeComponent } from './components/ogboot/pxe/pxe.component';
import { CreatePxeTemplateComponent } from './components/ogboot/pxe/create-pxeTemplate/create-pxe-template.component';
import { EditPxeTemplateComponent } from './components/ogboot/pxe/edit-pxe-template/edit-pxe-template.component';
import { PxeBootFilesComponent } from './components/ogboot/pxe-boot-files/pxe-boot-files.component';
import {MatExpansionPanel, MatExpansionPanelDescription, MatExpansionPanelTitle} from "@angular/material/expansion";
import { OgbootStatusComponent } from './components/ogboot/ogboot-status/ogboot-status.component';

View File

@ -91,7 +91,6 @@ export class GroupsComponent implements OnInit {
);
}
onSelectUnidad(unidad: UnidadOrganizativa): void {
this.selectedUnidad = unidad;
this.selectedDetail = unidad;

View File

@ -0,0 +1,34 @@
import { Injectable } from '@angular/core';
import {HttpClient, HttpParams} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class DataService {
private apiUrl = 'http://127.0.0.1:8080/og-lives?page=1&itemsPerPage=1000';
constructor(private http: HttpClient) {}
getImages(search: string = ''): Observable<any[]> {
let url = `${this.apiUrl}`;
if (search) {
url += `&name=${encodeURIComponent(search)}`;
}
return this.http.get<any>(url).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);
})
);
}
}

View File

@ -1,11 +1,3 @@
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
height: 100px;
padding: 10px;
}
.title {
font-size: 24px;
}
@ -16,11 +8,6 @@
margin-top: 16px;
}
button {
margin-left: 10px;
margin-bottom: 20px;
}
.divider {
margin: 20px 0;
}
@ -50,33 +37,26 @@ button {
flex: 1;
}
.mat-icon-button {
margin-left: 16px;
align-self: center;
.image-name{
cursor: pointer;
}
.mat-menu {
min-width: 160px;
}
.image-name{
cursor: pointer;
}
table {
width: 100%;
margin-top: 50px;
}
.search-container mat-form-field {
width: 100%;
}
.header-container {
margin-top: 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.header-container h1 {
margin: 0;
height: 100px;
padding: 10px;
margin-top: 16px;
}
.mat-elevation-z8 {

View File

@ -22,27 +22,32 @@
</div>
</div>
<mat-divider class="divider"></mat-divider>
<div class="search-container">
<mat-form-field appearance="fill">
<mat-label i18n="@@searchLabel">Buscar nombre de imagen</mat-label>
<input matInput placeholder="Búsqueda" [(ngModel)]="searchTerm" (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>
</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>
<td mat-cell *matCellDef="let image" [ngClass]="{'clickable': column.columnDef === 'name'}"
(click)="column.columnDef === 'name' && showInfo(image)">
<!-- Condición para mostrar íconos para isDefault e installed -->
<ng-container *ngIf="column.columnDef === 'isDefault' || column.columnDef === 'installed'">
<mat-icon [color]="image[column.columnDef] ? 'primary' : 'warn'">
{{ image[column.columnDef] ? 'check_circle' : 'cancel' }}
</mat-icon>
</ng-container>
<!-- Mostrar el downloadUrl truncado con tooltip -->
<ng-container *ngIf="column.columnDef === 'downloadUrl'">
<span matTooltip="{{ image.downloadUrl }}">
{{ image.downloadUrl ? image.downloadUrl.substring(0, 20) + '...' : '' }}
</span>
</ng-container>
<!-- Mostrar otros campos normalmente -->
<ng-container *ngIf="column.columnDef !== 'isDefault' && column.columnDef !== 'installed' && column.columnDef !== 'downloadUrl'">
{{ column.cell(image) }}
</ng-container>
@ -50,7 +55,6 @@
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions">Acciones</th>
<td mat-cell *matCellDef="let image">

View File

@ -9,6 +9,7 @@ import {PageEvent} from "@angular/material/paginator";
import {ToastrService} from "ngx-toastr";
import { DatePipe } from "@angular/common";
import { DeleteModalComponent } from '../../../shared/delete_modal/delete-modal/delete-modal.component';
import {DataService} from "./data.service";
@Component({
selector: 'app-images',
@ -23,6 +24,8 @@ export class ImagesComponent implements OnInit {
page: number = 1;
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
selectedElements: string[] = [];
loading:boolean = false;
searchTerm: string = '';
alertMessage: string | null = null;
readonly panelOpenState = signal(false);
datePipe: DatePipe = new DatePipe('es-ES');
@ -65,26 +68,15 @@ export class ImagesComponent implements OnInit {
constructor(
public dialog: MatDialog,
private http: HttpClient,
private dataService: DataService,
private toastService: ToastrService
) {}
) {}
ngOnInit(): void {
this.loadImages();
this.search();
this.loadAlert();
}
loadImages(): 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'];
},
error: (error) => {
console.error('Error al cargar las imágenes:', error);
}
});
}
addImage(): void {
const dialogRef = this.dialog.open(CreateImageComponent, {
width: '400px'
@ -92,10 +84,24 @@ export class ImagesComponent implements OnInit {
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
this.loadImages(); // Opcional: recargar imágenes después de añadir una nueva
this.search();
});
}
search(): void {
this.loading = true;
this.dataService.getImages(this.searchTerm).subscribe(
data => {
this.dataSource.data = data;
this.loading = false;
},
error => {
console.error('Error fetching og lives', error);
this.loading = false;
}
);
}
showInfo(image: any): void {
const dialogRef = this.dialog.open(InfoImageComponent, {
width: '700px',
@ -110,7 +116,7 @@ export class ImagesComponent implements OnInit {
next: () => {
console.log('Imagen cambiada');
this.toastService.success('Petición de cambio de imagen enviada');
this.loadImages();
this.search();
},
error: (error) => {
console.error('Error al cambiar la imagen:', error);
@ -123,7 +129,7 @@ export class ImagesComponent implements OnInit {
next: () => {
console.log('Imagen cambiada');
this.toastService.success('Petición de instalación enviada');
this.loadImages();
this.search();
},
error: (error) => {
console.error('Error al instalar la imagen:', error);
@ -137,7 +143,7 @@ export class ImagesComponent implements OnInit {
console.log('Imagen cambiada');
this.toastService.success('Petición de desinstalación enviada');
/* this.deleteImage(image); */
this.loadImages();
this.search();
},
error: (error) => {
console.error('Error al desinstalar la imagen:', error);
@ -151,29 +157,6 @@ export class ImagesComponent implements OnInit {
}
}
deleteImage(image: any): void {
const dialogRef = this.dialog.open(DeleteModalComponent, {
width: '300px',
data: { name: image.name }
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
this.http.delete(`${this.apiUrl}/${image.uuid}`).subscribe({
next: () => {
console.log('Imagen eliminada');
this.toastService.success('Image deleted successfully');
this.loadImages();
},
error: (error) => {
console.error('Error al eliminar la imagen:', error);
}
});
} else {
console.log('Eliminación de imagen cancelada');
}
}); }
editImage(image: any): void {
const dialogRef = this.dialog.open(EditImageComponent, {
width: '700px',
@ -182,7 +165,7 @@ export class ImagesComponent implements OnInit {
dialogRef.afterClosed().subscribe(result => {
if (result) {
this.loadImages();
this.search();
}
});
}
@ -227,7 +210,7 @@ export class ImagesComponent implements OnInit {
this.http.post(`${this.apiUrl}/sync`, {})
.subscribe(response => {
this.toastService.success('Sincronización completada');
this.loadImages()
this.search()
}, error => {
console.error('Error al sincronizar', error);
this.toastService.error('Error al sincronizar');

View File

@ -2,7 +2,9 @@
display: flex;
justify-content: space-between;
align-items: center;
height: 100px;
padding: 10px;
margin-top: 16px;
}
.title {
@ -15,11 +17,6 @@
margin-top: 16px;
}
button {
margin-left: 10px;
margin-bottom: 20px;
}
.divider {
margin: 20px 0;
}
@ -54,26 +51,13 @@ button {
align-self: center;
}
.mat-menu {
min-width: 160px;
}
.template-name{
cursor: pointer;
}
table {
width: 100%;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
}
.header-container h1 {
margin: 0;
margin-top: 50px;
}
.mat-elevation-z8 {

View File

@ -1,27 +1,60 @@
<mat-accordion class="example-headers-align">
<mat-expansion-panel hideToggle>
<mat-expansion-panel-header>
<mat-panel-title> Sincronización ogBoot </mat-panel-title>
<mat-panel-description>
<mat-icon [style.color]="getIcon().color">{{ getIcon().name }}</mat-icon>
</mat-panel-description>
</mat-expansion-panel-header>
<p *ngIf="alertMessage">Oglives creados en servidor ogBoot: {{ alertMessage }}</p>
<p *ngIf="alertMessage">Oglives creados en servidor ogCore (base de datos): {{ length }}</p>
<div class="example-button-row">
<button mat-flat-button color="primary" (click)="syncOgCore()"> Sincronizar OgCore</button>
</div>
</mat-expansion-panel>
</mat-accordion>
<div class="header-container">
<h2 class="title" i18n="@@adminPXETitle">Administrar ficheros de arranque PXE</h2>
</div>
<mat-divider class="divider"></mat-divider>
<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>
<td mat-cell *matCellDef="let image" [ngClass]="{'clickable': column.columnDef === 'name'}"
(click)="column.columnDef === 'name' && showPxeInfo(image)">
{{ column.cell(image) }}
<th mat-header-cell *matHeaderCellDef>{{column.header}}</th>
<td mat-cell *matCellDef="let element">
<ng-container *ngIf="column.columnDef === 'clients'">
<button mat-icon-button [matMenuTriggerFor]="clientsMenu">
<mat-icon>visibility</mat-icon>
</button>
<mat-menu #clientsMenu="matMenu">
<ng-container *ngFor="let client of column.cell(element)">
<button mat-menu-item>
<mat-list>
<mat-list-item lines="3">
<span matListItemTitle>{{ client.name }}</span>
<span matListItemLine>{{ client.ip }}</span>
<span matListItemLine>{{client.mac}}</span>
</mat-list-item>
</mat-list>
</button>
</ng-container>
</mat-menu>
</ng-container>
<ng-container *ngIf="column.columnDef !== 'clients'">
{{column.cell(element)}}
</ng-container>
</td>
<td mat-cell *matCellDef="let user" > {{ column.cell(user) }} </td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions">Acciones</th>
<td mat-cell *matCellDef="let image">
<button mat-button color="primary" (click)="editPxeTemplate(image)" i18n="@@editImage">Editar</button>
<button mat-button color="warn" (click)="deletePxeTemplate(image)" i18n="@@buttonDeleteUser">Eliminar</button>
<button mat-button [matMenuTriggerFor]="menu">
Acciones (ogBoot)
<button mat-icon-button [matMenuTriggerFor]="menu">
<mat-icon>menu</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="toggleAction(image, 'create')">Crear</button>
<button mat-menu-item (click)="toggleAction(image, 'delete')">Eliminar</button>
</mat-menu>
</td>

View File

@ -2,9 +2,11 @@ import { Component } from '@angular/core';
import {MatTableDataSource} from "@angular/material/table";
import {MatDialog} from "@angular/material/dialog";
import {HttpClient} from "@angular/common/http";
import { CreatePxeTemplateComponent } from '../pxe/pxe/create-pxeTemplate/create-pxe-template/create-pxe-template.component';
import { EditPxeTemplateComponent } from '../pxe/pxe/edit-pxe-template/edit-pxe-template.component';
import { CreatePxeTemplateComponent } from '../pxe/create-pxeTemplate/create-pxe-template.component';
import { EditPxeTemplateComponent } from '../pxe/edit-pxe-template/edit-pxe-template.component';
import {PageEvent} from "@angular/material/paginator";
import {ToastrService} from "ngx-toastr";
import {DatePipe} from "@angular/common";
@Component({
selector: 'app-pxe-boot-files',
@ -16,9 +18,11 @@ export class PxeBootFilesComponent {
currentPage: number = 1;
dataSource = new MatTableDataSource<any>();
length: number = 0;
alertMessage: string | null = null;
itemsPerPage: number = 10;
page: number = 1;
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
datePipe: DatePipe = new DatePipe('es-ES');
selectedElements: string[] = [];
columns = [
{
@ -27,27 +31,38 @@ export class PxeBootFilesComponent {
cell: (user: any) => `${user.id}`
},
{
columnDef: 'name',
columnDef: 'templateName',
header: 'Nombre de la plantilla',
cell: (user: any) => `${user.name}`
cell: (user: any) => `${user.template.name}`
},
{
columnDef: 'clients',
header: 'Clientes',
cell: (user: any) => user.clients
},
{
columnDef: 'createdAt',
header: 'Fecha de creación',
cell: (user: any) => `${user.createdAt}`
cell: (user: any) => `${this.datePipe.transform(user.createdAt, 'dd/MM/yyyy hh:mm:ss')}`
}
];
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
private apiUrl = 'http://127.0.0.1:8080/pxe-boot-files';
constructor(public dialog: MatDialog, private http: HttpClient) { }
constructor(
public dialog: MatDialog,
private http: HttpClient,
private toastService: ToastrService
)
{ }
ngOnInit(): void {
this.loadPxeTemplates();
this.loadPxeBootFiles();
this.loadAlert();
}
loadPxeTemplates(): void {
loadPxeBootFiles(): void {
this.http.get<any>(`${this.apiUrl}?page=1&itemsPerPage=${this.itemsPerPage}`).subscribe({
next: (response) => {
this.dataSource.data = response['hydra:member'];
@ -65,7 +80,7 @@ export class PxeBootFilesComponent {
});
dialogRef.afterClosed().subscribe(() => {
this.loadPxeTemplates();
this.loadPxeBootFiles();
});
}
@ -79,7 +94,7 @@ export class PxeBootFilesComponent {
this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({
next: () => {
console.log('Plantilla cambiada');
this.loadPxeTemplates();
this.loadPxeBootFiles();
},
error: (error) => {
console.error('Error al cambiar la imagen:', error);
@ -90,7 +105,7 @@ export class PxeBootFilesComponent {
this.http.post(`${this.apiUrl}/server/${image.uuid}/delete`, {}).subscribe({
next: () => {
console.log('Plantilla cambiada');
this.loadPxeTemplates();
this.loadPxeBootFiles();
},
error: (error) => {
console.error('Error al cambiar la imagen:', error);
@ -113,7 +128,7 @@ export class PxeBootFilesComponent {
});
dialogRef.afterClosed().subscribe(() => {
this.loadPxeTemplates();
this.loadPxeBootFiles();
});
}
@ -135,4 +150,33 @@ export class PxeBootFilesComponent {
this.applyFilter();
}
loadAlert() {
this.http.get(`${this.apiUrl}/server/get-collection`)
.subscribe(response => {
// @ts-ignore
this.alertMessage = response.templates.length
}, error => {
console.error('Error al cargar la información del alert', error);
});
}
getIcon(): { name: string, color: string } {
if (Number(this.alertMessage) === this.length) {
return { name: 'check_circle', color: 'green' }; // Icono de check verde
} else {
return { name: 'cancel', color: 'red' }; // Icono de cruz roja
}
}
syncOgCore(): void {
this.http.post(`${this.apiUrl}/sync`, {})
.subscribe(response => {
this.toastService.success('Sincronización completada');
this.loadPxeBootFiles()
}, error => {
console.error('Error al sincronizar', error);
this.toastService.error('Error al sincronizar');
});
}
}

View File

@ -0,0 +1,35 @@
import { Injectable } from '@angular/core';
import {HttpClient, HttpParams} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class DataService {
private apiUrl = 'http://127.0.0.1:8080/pxe-templates?page=1&itemsPerPage=1000';
constructor(private http: HttpClient) {}
getPxeTemplates(search: string = ''): Observable<any[]> {
let url = `${this.apiUrl}`;
if (search) {
url += `&name=${encodeURIComponent(search)}`;
}
return this.http.get<any>(url).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 pxe templates', error);
return throwError(error);
})
);
}
}

View File

@ -0,0 +1,52 @@
form {
max-width: 600px;
margin: 20px auto;
padding: 20px;
}
mat-form-field {
width: 100%;
margin-bottom: 20px;
}
pre {
background-color: #eceff1;
padding: 15px;
border-radius: 4px;
white-space: pre-wrap;
word-wrap: break-word;
font-size: 0.9rem;
color: #333;
}
mat-dialog-actions {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
button {
margin-left: 10px;
}
button[type="submit"] {
background-color: #3f51b5;
color: #fff;
}
button[type="submit"]:disabled {
background-color: #c5cae9;
}
h2 {
margin-bottom: 20px;
font-size: 1.5rem;
color: #000000;
text-align: center;
}
h3 {
margin-top: 30px;
font-size: 1.2rem;
color: #000000;
}

View File

@ -1,26 +1,16 @@
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
height: 100px;
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
height: 100px;
padding: 10px;
margin-top: 16px;
}
.title {
font-size: 24px;
}
.templates-button-row {
display: flex;
justify-content: flex-start;
margin-top: 16px;
}
button {
margin-left: 10px;
margin-bottom: 20px;
}
.divider {
margin: 20px 0;
}
@ -55,10 +45,6 @@ button {
align-self: center;
}
.mat-menu {
min-width: 160px;
}
.template-name{
cursor: pointer;
}
@ -68,6 +54,10 @@ table {
margin-top: 50px;
}
.search-container mat-form-field {
width: 100%;
}
.header-container {
margin-top: 16px;
display: flex;
@ -75,10 +65,6 @@ table {
align-items: center;
}
.header-container h1 {
margin: 0;
}
.mat-elevation-z8 {
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
}

View File

@ -8,6 +8,9 @@
</mat-expansion-panel-header>
<p *ngIf="alertMessage">Plantillas creadsa en servidor ogBoot: {{ alertMessage }}</p>
<p *ngIf="alertMessage">Plantillas creadsa en servidor ogCore (base de datos): {{ length }}</p>
<div class="example-button-row">
<button mat-flat-button color="primary" (click)="syncOgCore()"> Sincronizar OgCore</button>
</div>
</mat-expansion-panel>
</mat-accordion>
@ -18,6 +21,14 @@
</div>
</div>
<mat-divider class="divider"></mat-divider>
<div class="search-container">
<mat-form-field appearance="fill">
<mat-label i18n="@@searchLabel">Buscar nombre de plantilla</mat-label>
<input matInput placeholder="Búsqueda" [(ngModel)]="searchTerm" (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>
</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

@ -1,13 +1,14 @@
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
import { CreatePxeTemplateComponent } from './create-pxeTemplate/create-pxe-template/create-pxe-template.component';
import { CreatePxeTemplateComponent } from './create-pxeTemplate/create-pxe-template.component';
import { MatDialog } from '@angular/material/dialog';
import { EditPxeTemplateComponent } from './edit-pxe-template/edit-pxe-template.component';
import {MatTableDataSource} from "@angular/material/table";
import {PageEvent} from "@angular/material/paginator";
import {ToastrService} from "ngx-toastr";
import {DatePipe} from "@angular/common";
import { DeleteModalComponent } from '../../../../shared/delete_modal/delete-modal/delete-modal.component';
import { DeleteModalComponent } from '../../../shared/delete_modal/delete-modal/delete-modal.component';
import {DataService} from "./data.service";
@Component({
selector: 'app-pxe',
@ -23,6 +24,8 @@ export class PxeComponent {
page: number = 1;
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
selectedElements: string[] = [];
loading:boolean = false;
searchTerm: string = ''
alertMessage: string | null = null;
datePipe: DatePipe = new DatePipe('es-ES');
selectedItem: any = null;
@ -57,24 +60,26 @@ export class PxeComponent {
public dialog: MatDialog,
private http: HttpClient,
private toastService: ToastrService,
private dataService: DataService
) { }
ngOnInit(): void {
this.loadPxeTemplates();
this.loadAlert()
this.search()
this.loadAlert();
}
loadPxeTemplates(): 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);
search(): void {
this.loading = true;
this.dataService.getPxeTemplates(this.searchTerm).subscribe(
data => {
this.dataSource.data = data;
this.loading = false;
},
error: error => {
console.error('Error al cargar plantillas PXE:', error);
error => {
console.error('Error fetching pxe templates', error);
this.loading = false;
}
});
);
}
addPxeTemplate() {
@ -83,7 +88,7 @@ export class PxeComponent {
});
dialogRef.afterClosed().subscribe(() => {
this.loadPxeTemplates();
this.search();
});
}
@ -98,7 +103,7 @@ export class PxeComponent {
case 'create':
this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({
next: (response) => {
this.loadPxeTemplates();
this.search();
// @ts-ignore
this.toastService.success(response.message);
},
@ -111,7 +116,7 @@ export class PxeComponent {
this.http.post(`${this.apiUrl}/server/${image.uuid}/delete`, {}).subscribe({
next: () => {
console.log('Plantilla cambiada');
this.loadPxeTemplates();
this.search();
},
error: (error) => {
console.error('Error al cambiar la imagen:', error);
@ -124,40 +129,14 @@ export class PxeComponent {
}
}
deletePxeTemplate(template: any) {
// Lógica para eliminar una plantilla
const dialogRef = this.dialog.open(DeleteModalComponent, {
width: '300px'
});
console.log('Eliminando pxe:', template.uuid);
dialogRef.afterClosed().subscribe(result => {
if (result) {
this.http.delete(`http://127.0.0.1:8080/pxe-templates/${template.uuid}`).subscribe({
next: () => {
console.log('pxe eliminado');
this.toastService.success('PXE deleted successfully');
this.loadPxeTemplates();
},
error: (error) => {
console.error('Error al eliminar la pxe:', error);
}
});
} else {
console.log('Eliminación de pxe cancelada');
}
});
}
editPxeTemplate(template: any) {
const dialogRef = this.dialog.open(EditPxeTemplateComponent, {
data: template
data: template,
width: '600px'
});
dialogRef.afterClosed().subscribe(() => {
this.loadPxeTemplates();
this.search();
});
}
@ -197,4 +176,14 @@ export class PxeComponent {
}
}
syncOgCore(): void {
this.http.post(`${this.apiUrl}/sync`, {})
.subscribe(response => {
this.toastService.success('Sincronización completada');
this.search()
}, error => {
console.error('Error al sincronizar', error);
this.toastService.error('Error al sincronizar');
});
}
}

View File

@ -1,86 +0,0 @@
mat-form-field {
width: 100%;
margin-bottom: 16px;
padding: 5px;
}
.button-group {
display: flex;
justify-content: space-between;
}
button {
width: 48%;
}
:host {
display: block;
padding: 20px;
background-color: #f5f5f5;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.mat-form-field {
width: 100%;
margin-bottom: 16px;
}
.mat-step-label {
font-weight: bold;
font-size: 1.1em;
}
button {
margin: 8px 0;
}
.mat-stepper-header {
background-color: #fff;
padding: 16px;
border-bottom: 1px solid #e0e0e0;
border-radius: 8px 8px 0 0;
}
.mat-stepper-horizontal-line {
border-color: #3f51b5;
}
.mat-stepper-horizontal {
background-color: #fff;
padding: 0;
border-radius: 8px;
overflow: hidden;
}
.mat-step-header {
background-color: #e8eaf6;
color: #3f51b5;
}
.mat-step-header .mat-step-icon {
background-color: #3f51b5;
color: #fff;
}
.mat-stepper-content {
padding: 16px;
background-color: #fff;
border-radius: 0 0 8px 8px;
}
pre {
background-color: #e8eaf6;
padding: 16px;
border-radius: 4px;
font-size: 12px;
overflow-x: auto;
}
.mat-raised-button {
margin-right: 8px;
}
.mat-button {
margin-right: 8px;
}