Some improvements. Added filter search and refactor
parent
2d6785198f
commit
cf3785d863
|
@ -10,7 +10,7 @@ import { UsersComponent } from './components/admin/users/users/users.component';
|
||||||
import { RolesComponent } from './components/admin/roles/roles/roles.component';
|
import { RolesComponent } from './components/admin/roles/roles/roles.component';
|
||||||
import { GroupsComponent } from './components/groups/groups.component';
|
import { GroupsComponent } from './components/groups/groups.component';
|
||||||
import { ImagesComponent } from './components/ogboot/images/images.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 { PxeBootFilesComponent } from './components/ogboot/pxe-boot-files/pxe-boot-files.component';
|
||||||
import {OgbootStatusComponent} from "./components/ogboot/ogboot-status/ogboot-status.component";
|
import {OgbootStatusComponent} from "./components/ogboot/ogboot-status/ogboot-status.component";
|
||||||
import { OgdhcpComponent } from './components/ogdhcp/ogdhcp.component';
|
import { OgdhcpComponent } from './components/ogdhcp/ogdhcp.component';
|
||||||
|
|
|
@ -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 { 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 { 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 { InfoImageComponent } from './components/ogboot/images/info-image/info-image/info-image.component';
|
||||||
import { PxeComponent } from './components/ogboot/pxe/pxe/pxe.component';
|
import { PxeComponent } from './components/ogboot/pxe/pxe.component';
|
||||||
import { CreatePxeTemplateComponent } from './components/ogboot/pxe/pxe/create-pxeTemplate/create-pxe-template/create-pxe-template.component';
|
import { CreatePxeTemplateComponent } from './components/ogboot/pxe/create-pxeTemplate/create-pxe-template.component';
|
||||||
import { EditPxeTemplateComponent } from './components/ogboot/pxe/pxe/edit-pxe-template/edit-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 { PxeBootFilesComponent } from './components/ogboot/pxe-boot-files/pxe-boot-files.component';
|
||||||
import {MatExpansionPanel, MatExpansionPanelDescription, MatExpansionPanelTitle} from "@angular/material/expansion";
|
import {MatExpansionPanel, MatExpansionPanelDescription, MatExpansionPanelTitle} from "@angular/material/expansion";
|
||||||
import { OgbootStatusComponent } from './components/ogboot/ogboot-status/ogboot-status.component';
|
import { OgbootStatusComponent } from './components/ogboot/ogboot-status/ogboot-status.component';
|
||||||
|
|
|
@ -91,7 +91,6 @@ export class GroupsComponent implements OnInit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onSelectUnidad(unidad: UnidadOrganizativa): void {
|
onSelectUnidad(unidad: UnidadOrganizativa): void {
|
||||||
this.selectedUnidad = unidad;
|
this.selectedUnidad = unidad;
|
||||||
this.selectedDetail = unidad;
|
this.selectedDetail = unidad;
|
||||||
|
|
|
@ -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);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,3 @@
|
||||||
.header-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
height: 100px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +8,6 @@
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
margin-left: 10px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
@ -50,33 +37,26 @@ button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-icon-button {
|
.image-name{
|
||||||
margin-left: 16px;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mat-menu {
|
|
||||||
min-width: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-name{
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-container mat-form-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.header-container {
|
.header-container {
|
||||||
margin-top: 16px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
height: 100px;
|
||||||
|
padding: 10px;
|
||||||
.header-container h1 {
|
margin-top: 16px;
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-elevation-z8 {
|
.mat-elevation-z8 {
|
||||||
|
|
|
@ -22,27 +22,32 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mat-divider class="divider"></mat-divider>
|
<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">
|
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||||
<td mat-cell *matCellDef="let image" [ngClass]="{'clickable': column.columnDef === 'name'}"
|
<td mat-cell *matCellDef="let image" [ngClass]="{'clickable': column.columnDef === 'name'}"
|
||||||
(click)="column.columnDef === 'name' && showInfo(image)">
|
(click)="column.columnDef === 'name' && showInfo(image)">
|
||||||
|
|
||||||
<!-- Condición para mostrar íconos para isDefault e installed -->
|
|
||||||
<ng-container *ngIf="column.columnDef === 'isDefault' || column.columnDef === 'installed'">
|
<ng-container *ngIf="column.columnDef === 'isDefault' || column.columnDef === 'installed'">
|
||||||
<mat-icon [color]="image[column.columnDef] ? 'primary' : 'warn'">
|
<mat-icon [color]="image[column.columnDef] ? 'primary' : 'warn'">
|
||||||
{{ image[column.columnDef] ? 'check_circle' : 'cancel' }}
|
{{ image[column.columnDef] ? 'check_circle' : 'cancel' }}
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Mostrar el downloadUrl truncado con tooltip -->
|
|
||||||
<ng-container *ngIf="column.columnDef === 'downloadUrl'">
|
<ng-container *ngIf="column.columnDef === 'downloadUrl'">
|
||||||
<span matTooltip="{{ image.downloadUrl }}">
|
<span matTooltip="{{ image.downloadUrl }}">
|
||||||
{{ image.downloadUrl ? image.downloadUrl.substring(0, 20) + '...' : '' }}
|
{{ image.downloadUrl ? image.downloadUrl.substring(0, 20) + '...' : '' }}
|
||||||
</span>
|
</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Mostrar otros campos normalmente -->
|
|
||||||
<ng-container *ngIf="column.columnDef !== 'isDefault' && column.columnDef !== 'installed' && column.columnDef !== 'downloadUrl'">
|
<ng-container *ngIf="column.columnDef !== 'isDefault' && column.columnDef !== 'installed' && column.columnDef !== 'downloadUrl'">
|
||||||
{{ column.cell(image) }}
|
{{ column.cell(image) }}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -50,7 +55,6 @@
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
<ng-container matColumnDef="actions">
|
||||||
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions">Acciones</th>
|
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions">Acciones</th>
|
||||||
<td mat-cell *matCellDef="let image">
|
<td mat-cell *matCellDef="let image">
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {PageEvent} from "@angular/material/paginator";
|
||||||
import {ToastrService} from "ngx-toastr";
|
import {ToastrService} from "ngx-toastr";
|
||||||
import { DatePipe } from "@angular/common";
|
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({
|
@Component({
|
||||||
selector: 'app-images',
|
selector: 'app-images',
|
||||||
|
@ -23,6 +24,8 @@ export class ImagesComponent implements OnInit {
|
||||||
page: number = 1;
|
page: number = 1;
|
||||||
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
|
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
|
||||||
selectedElements: string[] = [];
|
selectedElements: string[] = [];
|
||||||
|
loading:boolean = false;
|
||||||
|
searchTerm: string = '';
|
||||||
alertMessage: string | null = null;
|
alertMessage: string | null = null;
|
||||||
readonly panelOpenState = signal(false);
|
readonly panelOpenState = signal(false);
|
||||||
datePipe: DatePipe = new DatePipe('es-ES');
|
datePipe: DatePipe = new DatePipe('es-ES');
|
||||||
|
@ -65,26 +68,15 @@ export class ImagesComponent implements OnInit {
|
||||||
constructor(
|
constructor(
|
||||||
public dialog: MatDialog,
|
public dialog: MatDialog,
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
|
private dataService: DataService,
|
||||||
private toastService: ToastrService
|
private toastService: ToastrService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loadImages();
|
this.search();
|
||||||
this.loadAlert();
|
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 {
|
addImage(): void {
|
||||||
const dialogRef = this.dialog.open(CreateImageComponent, {
|
const dialogRef = this.dialog.open(CreateImageComponent, {
|
||||||
width: '400px'
|
width: '400px'
|
||||||
|
@ -92,10 +84,24 @@ export class ImagesComponent implements OnInit {
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe(result => {
|
dialogRef.afterClosed().subscribe(result => {
|
||||||
console.log('The dialog was closed');
|
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 {
|
showInfo(image: any): void {
|
||||||
const dialogRef = this.dialog.open(InfoImageComponent, {
|
const dialogRef = this.dialog.open(InfoImageComponent, {
|
||||||
width: '700px',
|
width: '700px',
|
||||||
|
@ -110,7 +116,7 @@ export class ImagesComponent implements OnInit {
|
||||||
next: () => {
|
next: () => {
|
||||||
console.log('Imagen cambiada');
|
console.log('Imagen cambiada');
|
||||||
this.toastService.success('Petición de cambio de imagen enviada');
|
this.toastService.success('Petición de cambio de imagen enviada');
|
||||||
this.loadImages();
|
this.search();
|
||||||
},
|
},
|
||||||
error: (error) => {
|
error: (error) => {
|
||||||
console.error('Error al cambiar la imagen:', error);
|
console.error('Error al cambiar la imagen:', error);
|
||||||
|
@ -123,7 +129,7 @@ export class ImagesComponent implements OnInit {
|
||||||
next: () => {
|
next: () => {
|
||||||
console.log('Imagen cambiada');
|
console.log('Imagen cambiada');
|
||||||
this.toastService.success('Petición de instalación enviada');
|
this.toastService.success('Petición de instalación enviada');
|
||||||
this.loadImages();
|
this.search();
|
||||||
},
|
},
|
||||||
error: (error) => {
|
error: (error) => {
|
||||||
console.error('Error al instalar la imagen:', error);
|
console.error('Error al instalar la imagen:', error);
|
||||||
|
@ -137,7 +143,7 @@ export class ImagesComponent implements OnInit {
|
||||||
console.log('Imagen cambiada');
|
console.log('Imagen cambiada');
|
||||||
this.toastService.success('Petición de desinstalación enviada');
|
this.toastService.success('Petición de desinstalación enviada');
|
||||||
/* this.deleteImage(image); */
|
/* this.deleteImage(image); */
|
||||||
this.loadImages();
|
this.search();
|
||||||
},
|
},
|
||||||
error: (error) => {
|
error: (error) => {
|
||||||
console.error('Error al desinstalar la imagen:', 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 {
|
editImage(image: any): void {
|
||||||
const dialogRef = this.dialog.open(EditImageComponent, {
|
const dialogRef = this.dialog.open(EditImageComponent, {
|
||||||
width: '700px',
|
width: '700px',
|
||||||
|
@ -182,7 +165,7 @@ export class ImagesComponent implements OnInit {
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe(result => {
|
dialogRef.afterClosed().subscribe(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
this.loadImages();
|
this.search();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -227,7 +210,7 @@ export class ImagesComponent implements OnInit {
|
||||||
this.http.post(`${this.apiUrl}/sync`, {})
|
this.http.post(`${this.apiUrl}/sync`, {})
|
||||||
.subscribe(response => {
|
.subscribe(response => {
|
||||||
this.toastService.success('Sincronización completada');
|
this.toastService.success('Sincronización completada');
|
||||||
this.loadImages()
|
this.search()
|
||||||
}, error => {
|
}, error => {
|
||||||
console.error('Error al sincronizar', error);
|
console.error('Error al sincronizar', error);
|
||||||
this.toastService.error('Error al sincronizar');
|
this.toastService.error('Error al sincronizar');
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
height: 100px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
@ -15,11 +17,6 @@
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
margin-left: 10px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
@ -54,26 +51,13 @@ button {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-menu {
|
|
||||||
min-width: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.template-name{
|
.template-name{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
margin-top: 50px;
|
||||||
|
|
||||||
.header-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-container h1 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-elevation-z8 {
|
.mat-elevation-z8 {
|
||||||
|
|
|
@ -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">
|
<div class="header-container">
|
||||||
<h2 class="title" i18n="@@adminPXETitle">Administrar ficheros de arranque PXE</h2>
|
<h2 class="title" i18n="@@adminPXETitle">Administrar ficheros de arranque PXE</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-divider class="divider"></mat-divider>
|
<mat-divider class="divider"></mat-divider>
|
||||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
<th mat-header-cell *matHeaderCellDef>{{column.header}}</th>
|
||||||
<td mat-cell *matCellDef="let image" [ngClass]="{'clickable': column.columnDef === 'name'}"
|
<td mat-cell *matCellDef="let element">
|
||||||
(click)="column.columnDef === 'name' && showPxeInfo(image)">
|
<ng-container *ngIf="column.columnDef === 'clients'">
|
||||||
{{ column.cell(image) }}
|
<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>
|
||||||
<td mat-cell *matCellDef="let user" > {{ column.cell(user) }} </td>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
<ng-container matColumnDef="actions">
|
||||||
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions">Acciones</th>
|
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions">Acciones</th>
|
||||||
<td mat-cell *matCellDef="let image">
|
<td mat-cell *matCellDef="let image">
|
||||||
<button mat-button color="primary" (click)="editPxeTemplate(image)" i18n="@@editImage">Editar</button>
|
<button mat-icon-button [matMenuTriggerFor]="menu">
|
||||||
<button mat-button color="warn" (click)="deletePxeTemplate(image)" i18n="@@buttonDeleteUser">Eliminar</button>
|
<mat-icon>menu</mat-icon>
|
||||||
<button mat-button [matMenuTriggerFor]="menu">
|
|
||||||
Acciones (ogBoot)
|
|
||||||
</button>
|
</button>
|
||||||
<mat-menu #menu="matMenu">
|
<mat-menu #menu="matMenu">
|
||||||
<button mat-menu-item (click)="toggleAction(image, 'create')">Crear</button>
|
|
||||||
<button mat-menu-item (click)="toggleAction(image, 'delete')">Eliminar</button>
|
<button mat-menu-item (click)="toggleAction(image, 'delete')">Eliminar</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -2,9 +2,11 @@ import { Component } from '@angular/core';
|
||||||
import {MatTableDataSource} from "@angular/material/table";
|
import {MatTableDataSource} from "@angular/material/table";
|
||||||
import {MatDialog} from "@angular/material/dialog";
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
import {HttpClient} from "@angular/common/http";
|
import {HttpClient} from "@angular/common/http";
|
||||||
import { CreatePxeTemplateComponent } from '../pxe/pxe/create-pxeTemplate/create-pxe-template/create-pxe-template.component';
|
import { CreatePxeTemplateComponent } from '../pxe/create-pxeTemplate/create-pxe-template.component';
|
||||||
import { EditPxeTemplateComponent } from '../pxe/pxe/edit-pxe-template/edit-pxe-template.component';
|
import { EditPxeTemplateComponent } from '../pxe/edit-pxe-template/edit-pxe-template.component';
|
||||||
import {PageEvent} from "@angular/material/paginator";
|
import {PageEvent} from "@angular/material/paginator";
|
||||||
|
import {ToastrService} from "ngx-toastr";
|
||||||
|
import {DatePipe} from "@angular/common";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pxe-boot-files',
|
selector: 'app-pxe-boot-files',
|
||||||
|
@ -16,9 +18,11 @@ export class PxeBootFilesComponent {
|
||||||
currentPage: number = 1;
|
currentPage: number = 1;
|
||||||
dataSource = new MatTableDataSource<any>();
|
dataSource = new MatTableDataSource<any>();
|
||||||
length: number = 0;
|
length: number = 0;
|
||||||
|
alertMessage: string | null = null;
|
||||||
itemsPerPage: number = 10;
|
itemsPerPage: number = 10;
|
||||||
page: number = 1;
|
page: number = 1;
|
||||||
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
|
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
|
||||||
|
datePipe: DatePipe = new DatePipe('es-ES');
|
||||||
selectedElements: string[] = [];
|
selectedElements: string[] = [];
|
||||||
columns = [
|
columns = [
|
||||||
{
|
{
|
||||||
|
@ -27,27 +31,38 @@ export class PxeBootFilesComponent {
|
||||||
cell: (user: any) => `${user.id}`
|
cell: (user: any) => `${user.id}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
columnDef: 'name',
|
columnDef: 'templateName',
|
||||||
header: 'Nombre de la plantilla',
|
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',
|
columnDef: 'createdAt',
|
||||||
header: 'Fecha de creación',
|
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'];
|
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
|
||||||
|
|
||||||
private apiUrl = 'http://127.0.0.1:8080/pxe-boot-files';
|
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 {
|
ngOnInit(): void {
|
||||||
this.loadPxeTemplates();
|
this.loadPxeBootFiles();
|
||||||
|
this.loadAlert();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPxeTemplates(): void {
|
loadPxeBootFiles(): void {
|
||||||
this.http.get<any>(`${this.apiUrl}?page=1&itemsPerPage=${this.itemsPerPage}`).subscribe({
|
this.http.get<any>(`${this.apiUrl}?page=1&itemsPerPage=${this.itemsPerPage}`).subscribe({
|
||||||
next: (response) => {
|
next: (response) => {
|
||||||
this.dataSource.data = response['hydra:member'];
|
this.dataSource.data = response['hydra:member'];
|
||||||
|
@ -65,7 +80,7 @@ export class PxeBootFilesComponent {
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe(() => {
|
dialogRef.afterClosed().subscribe(() => {
|
||||||
this.loadPxeTemplates();
|
this.loadPxeBootFiles();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +94,7 @@ export class PxeBootFilesComponent {
|
||||||
this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({
|
this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
console.log('Plantilla cambiada');
|
console.log('Plantilla cambiada');
|
||||||
this.loadPxeTemplates();
|
this.loadPxeBootFiles();
|
||||||
},
|
},
|
||||||
error: (error) => {
|
error: (error) => {
|
||||||
console.error('Error al cambiar la imagen:', 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({
|
this.http.post(`${this.apiUrl}/server/${image.uuid}/delete`, {}).subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
console.log('Plantilla cambiada');
|
console.log('Plantilla cambiada');
|
||||||
this.loadPxeTemplates();
|
this.loadPxeBootFiles();
|
||||||
},
|
},
|
||||||
error: (error) => {
|
error: (error) => {
|
||||||
console.error('Error al cambiar la imagen:', error);
|
console.error('Error al cambiar la imagen:', error);
|
||||||
|
@ -113,7 +128,7 @@ export class PxeBootFilesComponent {
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe(() => {
|
dialogRef.afterClosed().subscribe(() => {
|
||||||
this.loadPxeTemplates();
|
this.loadPxeBootFiles();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,4 +150,33 @@ export class PxeBootFilesComponent {
|
||||||
this.applyFilter();
|
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');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -4,23 +4,13 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.templates-button-row {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-left: 10px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
@ -55,10 +45,6 @@ button {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-menu {
|
|
||||||
min-width: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.template-name{
|
.template-name{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +54,10 @@ table {
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-container mat-form-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.header-container {
|
.header-container {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -75,10 +65,6 @@ table {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-container h1 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mat-elevation-z8 {
|
.mat-elevation-z8 {
|
||||||
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
|
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
|
||||||
}
|
}
|
|
@ -8,6 +8,9 @@
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
<p *ngIf="alertMessage">Plantillas creadsa en servidor ogBoot: {{ alertMessage }}</p>
|
<p *ngIf="alertMessage">Plantillas creadsa en servidor ogBoot: {{ alertMessage }}</p>
|
||||||
<p *ngIf="alertMessage">Plantillas creadsa en servidor ogCore (base de datos): {{ length }}</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-expansion-panel>
|
||||||
</mat-accordion>
|
</mat-accordion>
|
||||||
|
|
||||||
|
@ -18,6 +21,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mat-divider class="divider"></mat-divider>
|
<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">
|
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
|
@ -1,13 +1,14 @@
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Component } from '@angular/core';
|
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 { MatDialog } from '@angular/material/dialog';
|
||||||
import { EditPxeTemplateComponent } from './edit-pxe-template/edit-pxe-template.component';
|
import { EditPxeTemplateComponent } from './edit-pxe-template/edit-pxe-template.component';
|
||||||
import {MatTableDataSource} from "@angular/material/table";
|
import {MatTableDataSource} from "@angular/material/table";
|
||||||
import {PageEvent} from "@angular/material/paginator";
|
import {PageEvent} from "@angular/material/paginator";
|
||||||
import {ToastrService} from "ngx-toastr";
|
import {ToastrService} from "ngx-toastr";
|
||||||
import {DatePipe} from "@angular/common";
|
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({
|
@Component({
|
||||||
selector: 'app-pxe',
|
selector: 'app-pxe',
|
||||||
|
@ -23,6 +24,8 @@ export class PxeComponent {
|
||||||
page: number = 1;
|
page: number = 1;
|
||||||
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
|
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
|
||||||
selectedElements: string[] = [];
|
selectedElements: string[] = [];
|
||||||
|
loading:boolean = false;
|
||||||
|
searchTerm: string = ''
|
||||||
alertMessage: string | null = null;
|
alertMessage: string | null = null;
|
||||||
datePipe: DatePipe = new DatePipe('es-ES');
|
datePipe: DatePipe = new DatePipe('es-ES');
|
||||||
selectedItem: any = null;
|
selectedItem: any = null;
|
||||||
|
@ -57,24 +60,26 @@ export class PxeComponent {
|
||||||
public dialog: MatDialog,
|
public dialog: MatDialog,
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
private toastService: ToastrService,
|
private toastService: ToastrService,
|
||||||
|
private dataService: DataService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loadPxeTemplates();
|
this.search()
|
||||||
this.loadAlert()
|
this.loadAlert();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPxeTemplates(): void {
|
search(): void {
|
||||||
this.http.get<any>(`${this.apiUrl}?page=1&itemsPerPage=${this.itemsPerPage}`).subscribe({
|
this.loading = true;
|
||||||
next: (response) => {
|
this.dataService.getPxeTemplates(this.searchTerm).subscribe(
|
||||||
this.dataSource.data = response['hydra:member'];
|
data => {
|
||||||
this.length = response['hydra:totalItems'];
|
this.dataSource.data = data;
|
||||||
console.log('Plantillas PXE cargadas:', this.pxeTemplates);
|
this.loading = false;
|
||||||
},
|
},
|
||||||
error: error => {
|
error => {
|
||||||
console.error('Error al cargar plantillas PXE:', error);
|
console.error('Error fetching pxe templates', error);
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addPxeTemplate() {
|
addPxeTemplate() {
|
||||||
|
@ -83,7 +88,7 @@ export class PxeComponent {
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe(() => {
|
dialogRef.afterClosed().subscribe(() => {
|
||||||
this.loadPxeTemplates();
|
this.search();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +103,7 @@ export class PxeComponent {
|
||||||
case 'create':
|
case 'create':
|
||||||
this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({
|
this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({
|
||||||
next: (response) => {
|
next: (response) => {
|
||||||
this.loadPxeTemplates();
|
this.search();
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.toastService.success(response.message);
|
this.toastService.success(response.message);
|
||||||
},
|
},
|
||||||
|
@ -111,7 +116,7 @@ export class PxeComponent {
|
||||||
this.http.post(`${this.apiUrl}/server/${image.uuid}/delete`, {}).subscribe({
|
this.http.post(`${this.apiUrl}/server/${image.uuid}/delete`, {}).subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
console.log('Plantilla cambiada');
|
console.log('Plantilla cambiada');
|
||||||
this.loadPxeTemplates();
|
this.search();
|
||||||
},
|
},
|
||||||
error: (error) => {
|
error: (error) => {
|
||||||
console.error('Error al cambiar la imagen:', 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) {
|
editPxeTemplate(template: any) {
|
||||||
const dialogRef = this.dialog.open(EditPxeTemplateComponent, {
|
const dialogRef = this.dialog.open(EditPxeTemplateComponent, {
|
||||||
data: template
|
data: template,
|
||||||
|
width: '600px'
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe(() => {
|
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');
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue