From 45e1679e83388a932c8624691fcb751c2bd25979 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Fri, 16 Aug 2024 15:39:54 +0200 Subject: [PATCH] Added new styles, and ogboot endpoints --- ogWebconsole/src/app/app-routing.module.ts | 6 +- ogWebconsole/src/app/app.module.ts | 11 +- .../src/app/components/groups/data.service.ts | 8 +- .../edit-image/edit-image.component.css | 16 ++ .../edit-image/edit-image.component.html | 8 +- .../images/images/images.component.css | 43 ++++- .../images/images/images.component.html | 71 +++++--- .../images/images/images.component.ts | 153 +++++++++++++++--- .../layout/sidebar/sidebar.component.html | 14 +- .../ogboot-status/ogboot-status.component.css | 0 .../ogboot-status.component.html | 1 + .../ogboot-status.component.spec.ts | 23 +++ .../ogboot-status/ogboot-status.component.ts | 10 ++ .../admin/users/users/users.component.ts | 1 - .../pxe-boot-files.component.css | 87 ++++++++++ .../pxe-boot-files.component.html | 40 +++++ .../pxe-boot-files.component.spec.ts | 23 +++ .../pxe-boot-files.component.ts | 140 ++++++++++++++++ .../app/components/pxe/pxe/pxe.component.css | 36 ++++- .../app/components/pxe/pxe/pxe.component.html | 84 ++++++---- .../app/components/pxe/pxe/pxe.component.ts | 123 +++++++++++++- 21 files changed, 792 insertions(+), 106 deletions(-) create mode 100644 ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.css create mode 100644 ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.html create mode 100644 ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.spec.ts create mode 100644 ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.ts create mode 100644 ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.css create mode 100644 ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.html create mode 100644 ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.spec.ts create mode 100644 ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.ts diff --git a/ogWebconsole/src/app/app-routing.module.ts b/ogWebconsole/src/app/app-routing.module.ts index 275c5e6..d6432c8 100644 --- a/ogWebconsole/src/app/app-routing.module.ts +++ b/ogWebconsole/src/app/app-routing.module.ts @@ -11,6 +11,8 @@ import { RolesComponent } from './components/pages/admin/roles/roles/roles.compo import { GroupsComponent } from './components/groups/groups.component'; import { ImagesComponent } from './components/images/images/images.component'; import { PxeComponent } from './components/pxe/pxe/pxe.component'; +import {PxeBootFilesComponent} from "./components/pxe-boot-files/pxe-boot-files.component"; +import {OgbootStatusComponent} from "./components/ogboot-status/ogboot-status.component"; const routes: Routes = [ { path: '', redirectTo: 'auth/login', pathMatch: 'full' }, { @@ -24,6 +26,8 @@ const routes: Routes = [ { path: 'groups', component: GroupsComponent }, { path: 'images', component: ImagesComponent }, { path: 'pxe', component: PxeComponent }, + { path: 'pxe-boot-file', component: PxeBootFilesComponent }, + { path: 'ogboot-status', component: OgbootStatusComponent }, ], }, { @@ -33,7 +37,7 @@ const routes: Routes = [ { path: 'login', component: LoginComponent }, ], }, -{ path: '**', component: PageNotFoundComponent }, +{ path: '**', component: PageNotFoundComponent }, ]; @NgModule({ diff --git a/ogWebconsole/src/app/app.module.ts b/ogWebconsole/src/app/app.module.ts index 3aefc39..618586e 100644 --- a/ogWebconsole/src/app/app.module.ts +++ b/ogWebconsole/src/app/app.module.ts @@ -52,6 +52,7 @@ import { MatChip, MatChipListbox, MatChipOption, MatChipSet, MatChipsModule } fr import { ClientViewComponent } from './components/groups/client-view/client-view.component'; import { MatTab, MatTabGroup } from "@angular/material/tabs"; import { MatTooltip } from "@angular/material/tooltip"; +import { MatExpansionModule } from '@angular/material/expansion'; import { DeleteGroupsModalComponent } from './components/groups/delete-groups-modal/delete-groups-modal.component'; import { DragDropModule } from '@angular/cdk/drag-drop'; import { ToastrModule } from 'ngx-toastr'; @@ -78,6 +79,9 @@ import { InfoImageComponent } from './components/images/images/info-image/info-i import { PxeComponent } from './components/pxe/pxe/pxe.component'; import { CreatePxeTemplateComponent } from './components/pxe/pxe/create-pxeTemplate/create-pxe-template/create-pxe-template.component'; import { EditPxeTemplateComponent } from './components/pxe/pxe/edit-pxe-template/edit-pxe-template.component'; +import { PxeBootFilesComponent } from './components/pxe-boot-files/pxe-boot-files.component'; +import {MatExpansionPanel, MatExpansionPanelDescription, MatExpansionPanelTitle} from "@angular/material/expansion"; +import { OgbootStatusComponent } from './components/ogboot-status/ogboot-status.component'; @NgModule({ declarations: [ @@ -118,7 +122,9 @@ import { EditPxeTemplateComponent } from './components/pxe/pxe/edit-pxe-template InfoImageComponent, PxeComponent, CreatePxeTemplateComponent, - EditPxeTemplateComponent + EditPxeTemplateComponent, + PxeBootFilesComponent, + OgbootStatusComponent ], bootstrap: [AppComponent], imports: [BrowserModule, @@ -142,6 +148,7 @@ import { EditPxeTemplateComponent } from './components/pxe/pxe/edit-pxe-template MatStepperModule, DragDropModule, MatSlideToggleModule, MatMenu, MatMenuTrigger, MatMenuItem, MatAutocomplete, MatChipListbox, MatChipOption, MatChipSet, MatChipsModule, MatChip, MatProgressSpinner, MatTabGroup, MatTab, MatTooltip, + MatExpansionModule, ToastrModule.forRoot( { timeOut: 5000, @@ -151,7 +158,7 @@ import { EditPxeTemplateComponent } from './components/pxe/pxe/edit-pxe-template progressAnimation: 'increasing', closeButton: true } - ), MatGridList, MatTree, MatTreeNode, MatNestedTreeNode, MatTreeNodeToggle, MatTreeNodeDef, MatTreeNodePadding, MatTreeNodeOutlet, MatPaginator, MatGridTile + ), MatGridList, MatTree, MatTreeNode, MatNestedTreeNode, MatTreeNodeToggle, MatTreeNodeDef, MatTreeNodePadding, MatTreeNodeOutlet, MatPaginator, MatGridTile, MatExpansionPanel, MatExpansionPanelTitle, MatExpansionPanelDescription ], schemas: [ CUSTOM_ELEMENTS_SCHEMA, diff --git a/ogWebconsole/src/app/components/groups/data.service.ts b/ogWebconsole/src/app/components/groups/data.service.ts index 89863aa..22b5293 100644 --- a/ogWebconsole/src/app/components/groups/data.service.ts +++ b/ogWebconsole/src/app/components/groups/data.service.ts @@ -159,8 +159,8 @@ export class DataService { getFilter(id: string): Observable { return this.http.get('http://127.0.0.1:8080/views/' + id).pipe( map(response => { - - + + if (response.name && response.filters) { return response; } else { @@ -173,6 +173,6 @@ export class DataService { }) ); } - - + + } diff --git a/ogWebconsole/src/app/components/images/images/edit-image/edit-image/edit-image.component.css b/ogWebconsole/src/app/components/images/images/edit-image/edit-image/edit-image.component.css index e69de29..16289b6 100644 --- a/ogWebconsole/src/app/components/images/images/edit-image/edit-image/edit-image.component.css +++ b/ogWebconsole/src/app/components/images/images/edit-image/edit-image/edit-image.component.css @@ -0,0 +1,16 @@ +.form-container { + display: flex; + flex-direction: column; + gap: 16px; /* Espacio entre los campos */ +} + +.form-field { + width: 100%; /* Para que cada campo ocupe todo el ancho disponible */ +} + +.actions-container { + display: flex; + justify-content: flex-end; + gap: 8px; /* Espacio entre los botones */ + margin-top: 16px; /* Separación superior para los botones */ +} diff --git a/ogWebconsole/src/app/components/images/images/edit-image/edit-image/edit-image.component.html b/ogWebconsole/src/app/components/images/images/edit-image/edit-image/edit-image.component.html index 2a9cc40..d19e0df 100644 --- a/ogWebconsole/src/app/components/images/images/edit-image/edit-image/edit-image.component.html +++ b/ogWebconsole/src/app/components/images/images/edit-image/edit-image/edit-image.component.html @@ -1,15 +1,15 @@

Editar Imagen

-
- +
+ Nombre - + URL de descarga
-
+
diff --git a/ogWebconsole/src/app/components/images/images/images.component.css b/ogWebconsole/src/app/components/images/images/images.component.css index 370f169..de78773 100644 --- a/ogWebconsole/src/app/components/images/images/images.component.css +++ b/ogWebconsole/src/app/components/images/images/images.component.css @@ -59,12 +59,41 @@ button { min-width: 160px; } -.cd-icon { - color: #888888; - margin-right: 20px; - transform: scale(1.5); - } - .image-name{ cursor: pointer; - } \ No newline at end of file + } + +table { + width: 100%; + margin-top: 50px; +} + +.header-container { + margin-top: 16px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.header-container h1 { + margin: 0; +} + +.mat-elevation-z8 { + box-shadow: 0px 0px 0px rgba(0,0,0,0.2); +} + +.paginator-container { + display: flex; + justify-content: end; + margin-bottom: 30px; +} + +.example-headers-align .mat-expansion-panel-header-description { + justify-content: space-between; + align-items: center; +} + +.example-headers-align .mat-mdc-form-field + .mat-mdc-form-field { + margin-left: 8px; +} diff --git a/ogWebconsole/src/app/components/images/images/images.component.html b/ogWebconsole/src/app/components/images/images/images.component.html index 1e25ac3..709cc21 100644 --- a/ogWebconsole/src/app/components/images/images/images.component.html +++ b/ogWebconsole/src/app/components/images/images/images.component.html @@ -1,3 +1,16 @@ + + + + Sincronización ogBoot + + {{ getIcon().name }} + + +

Isos alojadas en servidor ogBoot: {{ alertMessage }}

+

Isos alojadas en servidor ogCore (base de datos): {{ length }}

+
+
+

Administrar imágenes

@@ -5,28 +18,40 @@
+ + + + + + -
-
- - Imágenes disponibles - -
No hay imágenes disponibles.
-
-
- album -

{{ image.name }}

- - - - - - -
-
-
-
-
+ +
+ + + + + +
{{ column.header }} + {{ column.cell(image) }} + {{ column.cell(user) }} Acciones + + + + + + + + +
+
+ +
diff --git a/ogWebconsole/src/app/components/images/images/images.component.ts b/ogWebconsole/src/app/components/images/images/images.component.ts index cd0704a..baa0e20 100644 --- a/ogWebconsole/src/app/components/images/images/images.component.ts +++ b/ogWebconsole/src/app/components/images/images/images.component.ts @@ -1,9 +1,13 @@ -import { Component, OnInit } from '@angular/core'; +import {Component, OnInit, signal} from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { HttpClient } from '@angular/common/http'; import { CreateImageComponent } from './create-image/create-image/create-image.component'; import { EditImageComponent } from './edit-image/edit-image/edit-image.component'; import { InfoImageComponent } from './info-image/info-image/info-image.component'; +import { MatTableDataSource } from "@angular/material/table"; +import {PageEvent} from "@angular/material/paginator"; +import {ToastrService} from "ngx-toastr"; +import { DatePipe } from "@angular/common"; @Component({ selector: 'app-images', @@ -12,23 +16,62 @@ import { InfoImageComponent } from './info-image/info-image/info-image.component }) export class ImagesComponent implements OnInit { images: { downloadUrl: string; name: string; uuid: string }[] = []; + dataSource = new MatTableDataSource(); + length: number = 0; + itemsPerPage: number = 10; + page: number = 1; + pageSizeOptions: number[] = [5, 10, 20, 40, 100]; + selectedElements: string[] = []; + alertMessage: string | null = null; + readonly panelOpenState = signal(false); + datePipe: DatePipe = new DatePipe('es-ES'); + columns = [ + { + columnDef: 'id', + header: 'ID', + cell: (user: any) => `${user.id}` + }, + { + columnDef: 'name', + header: 'Nombre de imagen', + cell: (user: any) => `${user.name}` + }, + { + columnDef: 'downloadUrl', + header: 'Url descarga', + cell: (user: any) => `${user.downloadUrl}` + }, + { + columnDef: 'default', + header: 'Imagen por defecto', + cell: (user: any) => `${user.default}` + }, + { + columnDef: 'createdAt', + header: 'Fecha de creación', + 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/og-lives'; - constructor(public dialog: MatDialog, private http: HttpClient) {} + constructor( + public dialog: MatDialog, + private http: HttpClient, + private toastService: ToastrService + ) {} ngOnInit(): void { this.loadImages(); + this.loadAlert(); } loadImages(): void { - this.http.get(`${this.apiUrl}?page=1&itemsPerPage=30`).subscribe({ + this.http.get(`${this.apiUrl}?page=1&itemsPerPage=${this.itemsPerPage}`).subscribe({ next: (response) => { - this.images = response['hydra:member'].map((item: any) => ({ - downloadUrl: item.downloadUrl, - name: item.name, - uuid: item.uuid - })); + this.dataSource.data = response['hydra:member']; + this.length = response['hydra:totalItems']; }, error: (error) => { console.error('Error al cargar las imágenes:', error); @@ -49,20 +92,57 @@ export class ImagesComponent implements OnInit { showInfo(image: any): void { const dialogRef = this.dialog.open(InfoImageComponent, { - width: '300px', - data: image + width: '700px', + data: image }); } - toggleStatus(image: any): void { - // Implementar lógica para montar/desmontar - console.log('Montar/Desmontar:', image); + toggleAction(image: any, action:string): void { + switch (action) { + case 'set-default': + this.http.post(`${this.apiUrl}/server/${image.uuid}/set-default`, {}).subscribe({ + next: () => { + console.log('Imagen cambiada'); + this.loadImages(); + }, + error: (error) => { + console.error('Error al cambiar la imagen:', error); + } + }); + break; + case 'install': + this.http.post(`${this.apiUrl}/server/${image.uuid}/install`, {}).subscribe({ + next: () => { + console.log('Imagen cambiada'); + this.loadImages(); + }, + error: (error) => { + console.error('Error al cambiar la imagen:', error); + } + }); + break; + case 'uninstall': + this.http.post(`${this.apiUrl}/server/${image.uuid}/uninstall`, {}).subscribe({ + next: () => { + console.log('Imagen cambiada'); + this.loadImages(); + }, + error: (error) => { + console.error('Error al cambiar la imagen:', error); + } + }); + break; + default: + console.error('Acción no soportada:', action); + break; + } } - deleteImage(uuid: string): void { - this.http.delete(`${this.apiUrl}/${uuid}`).subscribe({ + deleteImage(image: any): void { + this.http.delete(`${this.apiUrl}/${image.uuid}`).subscribe({ next: () => { console.log('Imagen eliminada'); + this.toastService.success('Image deleted successfully'); this.loadImages(); }, error: (error) => { @@ -73,15 +153,50 @@ export class ImagesComponent implements OnInit { editImage(image: any): void { const dialogRef = this.dialog.open(EditImageComponent, { - width: '300px', - data: image + width: '700px', + data: image }); - + dialogRef.afterClosed().subscribe(result => { if (result) { this.loadImages(); } }); } - + + applyFilter() { + this.http.get(`${this.apiUrl}?page=${this.page}&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); + } + }); + } + + onPageChange(event: PageEvent) { + this.page = event.pageIndex; + this.itemsPerPage = event.pageSize; + this.applyFilter(); + } + + loadAlert() { + this.http.get(`${this.apiUrl}/server/get-isos`) + .subscribe(response => { + // @ts-ignore + this.alertMessage = response.data.downloads.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 + } + } } diff --git a/ogWebconsole/src/app/components/layout/sidebar/sidebar.component.html b/ogWebconsole/src/app/components/layout/sidebar/sidebar.component.html index ee0287f..b9fc935 100644 --- a/ogWebconsole/src/app/components/layout/sidebar/sidebar.component.html +++ b/ogWebconsole/src/app/components/layout/sidebar/sidebar.component.html @@ -31,6 +31,12 @@ + + + analytics + Estado de servidor + + album @@ -40,7 +46,13 @@ assignment - PXE + Plantillas PXE + + + + + save + Arranque PXE diff --git a/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.css b/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.css new file mode 100644 index 0000000..e69de29 diff --git a/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.html b/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.html new file mode 100644 index 0000000..cd790e5 --- /dev/null +++ b/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.html @@ -0,0 +1 @@ +

ogboot-status works!

diff --git a/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.spec.ts b/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.spec.ts new file mode 100644 index 0000000..145205d --- /dev/null +++ b/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OgbootStatusComponent } from './ogboot-status.component'; + +describe('OgbootStatusComponent', () => { + let component: OgbootStatusComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OgbootStatusComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(OgbootStatusComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.ts b/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.ts new file mode 100644 index 0000000..5f60dbb --- /dev/null +++ b/ogWebconsole/src/app/components/ogboot-status/ogboot-status.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-ogboot-status', + templateUrl: './ogboot-status.component.html', + styleUrl: './ogboot-status.component.css' +}) +export class OgbootStatusComponent { + +} diff --git a/ogWebconsole/src/app/components/pages/admin/users/users/users.component.ts b/ogWebconsole/src/app/components/pages/admin/users/users/users.component.ts index 2e597b4..8b3828e 100644 --- a/ogWebconsole/src/app/components/pages/admin/users/users/users.component.ts +++ b/ogWebconsole/src/app/components/pages/admin/users/users/users.component.ts @@ -46,7 +46,6 @@ export class UsersComponent implements OnInit { loadUsers() { this.userService.getUsers().subscribe(response => { this.dataSource.data = response['hydra:member']; - console.log(this.dataSource.data); }); } diff --git a/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.css b/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.css new file mode 100644 index 0000000..c26379f --- /dev/null +++ b/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.css @@ -0,0 +1,87 @@ +.header-container { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; +} + +.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; +} + +.lists-container { + padding: 16px; +} + +.templatesLists-container { + flex: 1; +} + +.card.unidad-card { + height: 100%; + box-sizing: border-box; +} + +.template-container { + display: flex; + align-items: center; + margin-bottom: 16px; + border-bottom: 1px solid rgba(122, 122, 122, 0.555); +} + +.template-container h4 { + margin: 0; + flex: 1; +} + +.mat-icon-button { + margin-left: 16px; + 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; +} + +.mat-elevation-z8 { + box-shadow: 0px 0px 0px rgba(0,0,0,0.2); +} + +.paginator-container { + display: flex; + justify-content: end; + margin-bottom: 30px; +} diff --git a/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.html b/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.html new file mode 100644 index 0000000..7ed0c5f --- /dev/null +++ b/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.html @@ -0,0 +1,40 @@ +
+

Administrar ficheros de arranque PXE

+
+ + + + + + + + + + + + + + + +
{{ column.header }} + {{ column.cell(image) }} + {{ column.cell(user) }} Acciones + + + + + + + +
+
+ + +
diff --git a/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.spec.ts b/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.spec.ts new file mode 100644 index 0000000..54406d5 --- /dev/null +++ b/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PxeBootFilesComponent } from './pxe-boot-files.component'; + +describe('PxeBootFilesComponent', () => { + let component: PxeBootFilesComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PxeBootFilesComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(PxeBootFilesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.ts b/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.ts new file mode 100644 index 0000000..4af2d65 --- /dev/null +++ b/ogWebconsole/src/app/components/pxe-boot-files/pxe-boot-files.component.ts @@ -0,0 +1,140 @@ +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 {PageEvent} from "@angular/material/paginator"; + +@Component({ + selector: 'app-pxe-boot-files', + templateUrl: './pxe-boot-files.component.html', + styleUrl: './pxe-boot-files.component.css' +}) +export class PxeBootFilesComponent { + pxeTemplates: any[] = []; // Inicializa el array de plantillas + currentPage: number = 1; + dataSource = new MatTableDataSource(); + length: number = 0; + itemsPerPage: number = 10; + page: number = 1; + pageSizeOptions: number[] = [5, 10, 20, 40, 100]; + selectedElements: string[] = []; + columns = [ + { + columnDef: 'id', + header: 'ID', + cell: (user: any) => `${user.id}` + }, + { + columnDef: 'name', + header: 'Nombre de la plantilla', + cell: (user: any) => `${user.name}` + }, + { + columnDef: 'createdAt', + header: 'Fecha de creación', + cell: (user: any) => `${user.createdAt}` + } + ]; + 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) { } + + ngOnInit(): void { + this.loadPxeTemplates(); + } + + loadPxeTemplates(): void { + this.http.get(`${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); + }, + error: error => { + console.error('Error al cargar plantillas PXE:', error); + } + }); + } + + addPxeTemplate() { + const dialogRef = this.dialog.open(CreatePxeTemplateComponent, { + }); + + dialogRef.afterClosed().subscribe(() => { + this.loadPxeTemplates(); + }); + } + + showPxeInfo(template: any) { + + } + + toggleAction(image: any, action:string): void { + switch (action) { + case 'create': + this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({ + next: () => { + console.log('Plantilla cambiada'); + this.loadPxeTemplates(); + }, + error: (error) => { + console.error('Error al cambiar la imagen:', error); + } + }); + break; + case 'delete': + this.http.post(`${this.apiUrl}/server/${image.uuid}/delete`, {}).subscribe({ + next: () => { + console.log('Plantilla cambiada'); + this.loadPxeTemplates(); + }, + error: (error) => { + console.error('Error al cambiar la imagen:', error); + } + }); + break; + default: + console.error('Acción no soportada:', action); + break; + } + } + + deletePxeTemplate(uuid: string) { + // Lógica para eliminar una plantilla + } + + editPxeTemplate(template: any) { + const dialogRef = this.dialog.open(EditPxeTemplateComponent, { + data: template + }); + + dialogRef.afterClosed().subscribe(() => { + this.loadPxeTemplates(); + }); + } + + applyFilter() { + this.http.get(`${this.apiUrl}?page=${this.page}&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); + } + }); + } + + onPageChange(event: PageEvent) { + this.page = event.pageIndex; + this.itemsPerPage = event.pageSize; + this.applyFilter(); + } + +} diff --git a/ogWebconsole/src/app/components/pxe/pxe/pxe.component.css b/ogWebconsole/src/app/components/pxe/pxe/pxe.component.css index d1f78bf..c25b942 100644 --- a/ogWebconsole/src/app/components/pxe/pxe/pxe.component.css +++ b/ogWebconsole/src/app/components/pxe/pxe/pxe.component.css @@ -59,12 +59,32 @@ button { min-width: 160px; } -.cd-icon { - color: #888888; - margin-right: 20px; - transform: scale(1.5); - } +.template-name{ + cursor: pointer; +} - .template-name{ - cursor: pointer; - } \ No newline at end of file +table { + width: 100%; + margin-top: 50px; +} + +.header-container { + margin-top: 16px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.header-container h1 { + margin: 0; +} + +.mat-elevation-z8 { + box-shadow: 0px 0px 0px rgba(0,0,0,0.2); +} + +.paginator-container { + display: flex; + justify-content: end; + margin-bottom: 30px; +} diff --git a/ogWebconsole/src/app/components/pxe/pxe/pxe.component.html b/ogWebconsole/src/app/components/pxe/pxe/pxe.component.html index dea15da..5812841 100644 --- a/ogWebconsole/src/app/components/pxe/pxe/pxe.component.html +++ b/ogWebconsole/src/app/components/pxe/pxe/pxe.component.html @@ -1,31 +1,57 @@ + + + + Sincronización ogBoot + + {{ getIcon().name }} + + +

Plantillas creadsa en servidor ogBoot: {{ alertMessage }}

+

Plantillas creadsa en servidor ogCore (base de datos): {{ length }}

+
+
+
-

Administrar plantillas PXE

-
- -
+

Administrar plantillas PXE

+
+
- - -
-
- - Plantillas PXE disponibles - -
No hay plantillas PXE disponibles.
-
-
- insert_drive_file -

{{ template.name }}

- - - - - -
-
-
-
-
-
\ No newline at end of file +
+ + + + + + + + + + + + + + + +
{{ column.header }} + {{ column.cell(image) }} + {{ column.cell(user) }} Acciones + + + + + + + + +
+
+ + +
diff --git a/ogWebconsole/src/app/components/pxe/pxe/pxe.component.ts b/ogWebconsole/src/app/components/pxe/pxe/pxe.component.ts index 7d85978..8a5126d 100644 --- a/ogWebconsole/src/app/components/pxe/pxe/pxe.component.ts +++ b/ogWebconsole/src/app/components/pxe/pxe/pxe.component.ts @@ -3,6 +3,10 @@ import { Component } from '@angular/core'; import { CreatePxeTemplateComponent } from './create-pxeTemplate/create-pxe-template/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"; @Component({ selector: 'app-pxe', @@ -11,20 +15,57 @@ import { EditPxeTemplateComponent } from './edit-pxe-template/edit-pxe-template. }) export class PxeComponent { pxeTemplates: any[] = []; // Inicializa el array de plantillas - itemsPerPage: number = 30; currentPage: number = 1; + dataSource = new MatTableDataSource(); + length: number = 0; + itemsPerPage: number = 10; + page: number = 1; + pageSizeOptions: number[] = [5, 10, 20, 40, 100]; + selectedElements: string[] = []; + alertMessage: string | null = null; + datePipe: DatePipe = new DatePipe('es-ES'); + columns = [ + { + columnDef: 'id', + header: 'ID', + cell: (user: any) => `${user.id}` + }, + { + columnDef: 'name', + header: 'Nombre de la plantilla', + cell: (user: any) => `${user.name}` + }, + { + columnDef: 'synchronized', + header: 'Creado en ogBoot', + cell: (user: any) => `${user.name}` + }, + { + columnDef: 'createdAt', + header: 'Fecha de creación', + cell: (user: any) => `${this.datePipe.transform(user.createdAt, 'dd/MM/yyyy hh:mm:ss')}` + } + ]; + displayedColumns = [...this.columns.map(column => column.columnDef), 'actions']; - constructor(public dialog: MatDialog, private http: HttpClient) { } + private apiUrl = 'http://127.0.0.1:8080/pxe-templates'; + + constructor( + public dialog: MatDialog, + private http: HttpClient, + private toastService: ToastrService, + ) { } ngOnInit(): void { this.loadPxeTemplates(); + this.loadAlert() } loadPxeTemplates(): void { - const url = `http://127.0.0.1:8080/pxe-templates?page=${this.currentPage}&itemsPerPage=${this.itemsPerPage}`; - this.http.get(url).subscribe({ - next: data => { - this.pxeTemplates = data['hydra:member']; + this.http.get(`${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); }, error: error => { @@ -43,7 +84,38 @@ export class PxeComponent { } showPxeInfo(template: any) { - // Lógica para mostrar información de una plantilla + + } + + toggleAction(image: any, action:string): void { + switch (action) { + case 'create': + this.http.post(`${this.apiUrl}/server/${image.uuid}/post`, {}).subscribe({ + next: (response) => { + this.loadPxeTemplates(); + // @ts-ignore + this.toastService.success(response.message); + }, + error: (error) => { + this.toastService.error(error.error.error); + } + }); + break; + case 'delete': + this.http.post(`${this.apiUrl}/server/${image.uuid}/delete`, {}).subscribe({ + next: () => { + console.log('Plantilla cambiada'); + this.loadPxeTemplates(); + }, + error: (error) => { + console.error('Error al cambiar la imagen:', error); + } + }); + break; + default: + console.error('Acción no soportada:', action); + break; + } } deletePxeTemplate(uuid: string) { @@ -59,4 +131,41 @@ export class PxeComponent { this.loadPxeTemplates(); }); } + + applyFilter() { + this.http.get(`${this.apiUrl}?page=${this.page}&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); + } + }); + } + + onPageChange(event: PageEvent) { + this.page = event.pageIndex; + this.itemsPerPage = event.pageSize; + 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 + } + } + }