From a1e2b7aec12e2af5fa1314015e1424dcaddc39bf Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Wed, 10 Jul 2024 16:13:29 +0200 Subject: [PATCH] refs #486. Some several improvements. Change in UX, and added new client-classroom view --- ogWebconsole/src/app/app.component.css | 1 + ogWebconsole/src/app/app.module.ts | 16 +- .../classroom-view.component.css | 29 ++-- .../classroom-view.component.html | 20 ++- .../classroom-view.component.ts | 13 +- .../client-view/client-view.component.css | 41 +++++ .../client-view/client-view.component.html | 40 +++++ .../client-view/client-view.component.spec.ts | 23 +++ .../client-view/client-view.component.ts | 14 ++ .../create-client/create-client.component.css | 85 +++++----- .../create-client.component.html | 19 ++- .../create-client/create-client.component.ts | 58 +++++-- .../edit-client/edit-client.component.css | 75 +++++---- .../edit-client/edit-client.component.html | 36 ++++- .../edit-client/edit-client.component.ts | 39 +++-- .../src/app/components/groups/data.service.ts | 36 +++-- .../delete-groups-modal.component.css | 0 .../delete-groups-modal.component.spec.ts | 23 +++ .../delete-groups-modal.component.ts | 30 ++++ .../components/groups/groups.component.css | 32 +++- .../components/groups/groups.component.html | 94 ++++++----- .../app/components/groups/groups.component.ts | 149 ++++++++++-------- .../src/app/components/groups/model.ts | 8 +- .../create-organizational-unit.component.html | 12 +- .../create-organizational-unit.component.ts | 35 ++-- .../edit-organizational-unit.component.ts | 30 ++-- .../layout/header/header.component.css | 8 +- .../layout/header/header.component.html | 3 +- .../layout/header/header.component.ts | 36 ++++- .../main-layout/main-layout.component.css | 5 +- .../main-layout/main-layout.component.html | 2 +- .../layout/sidebar/sidebar.component.css | 2 + .../layout/sidebar/sidebar.component.ts | 12 +- .../app/components/login/login.component.css | 46 ++---- .../app/components/login/login.component.html | 25 ++- .../app/components/login/login.component.ts | 18 ++- .../change-password-modal.component.css | 30 ++-- .../change-password-modal.component.html | 18 +-- .../change-password-modal.component.ts | 26 +-- .../edit-user-modal.component.html | 8 +- .../edit-user-modal.component.ts | 53 +++---- .../admin/users/users/users.component.ts | 5 +- .../pages/admin/users/users/users.service.ts | 15 +- 43 files changed, 843 insertions(+), 427 deletions(-) create mode 100644 ogWebconsole/src/app/components/groups/client-view/client-view.component.css create mode 100644 ogWebconsole/src/app/components/groups/client-view/client-view.component.html create mode 100644 ogWebconsole/src/app/components/groups/client-view/client-view.component.spec.ts create mode 100644 ogWebconsole/src/app/components/groups/client-view/client-view.component.ts create mode 100644 ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.css create mode 100644 ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.spec.ts create mode 100644 ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.ts diff --git a/ogWebconsole/src/app/app.component.css b/ogWebconsole/src/app/app.component.css index aac26c0..ee894d6 100644 --- a/ogWebconsole/src/app/app.component.css +++ b/ogWebconsole/src/app/app.component.css @@ -2,6 +2,7 @@ height: 100%; } + .content { padding: 16px; } diff --git a/ogWebconsole/src/app/app.module.ts b/ogWebconsole/src/app/app.module.ts index ae1361b..3b27cb0 100644 --- a/ogWebconsole/src/app/app.module.ts +++ b/ogWebconsole/src/app/app.module.ts @@ -11,8 +11,8 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; import { CustomInterceptor } from './services/custom.interceptor'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; -import {MatToolbarModule} from '@angular/material/toolbar'; -import {MatIconModule} from '@angular/material/icon'; +import {MatToolbarModule} from '@angular/material/toolbar'; +import {MatIconModule} from '@angular/material/icon'; import { MatButtonModule } from '@angular/material/button'; import { MatSidenavModule } from '@angular/material/sidenav'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @@ -46,6 +46,12 @@ import { ClassroomViewComponent } from './components/groups/classroom-view/class import {MatProgressSpinner} from "@angular/material/progress-spinner"; import {MatMenu, MatMenuItem, MatMenuTrigger} from "@angular/material/menu"; +import {MatAutocomplete} from "@angular/material/autocomplete"; +import {MatChip, MatChipListbox, MatChipOption, MatChipSet} from "@angular/material/chips"; +import { ClientViewComponent } from './components/groups/client-view/client-view.component'; +import {MatTab, MatTabGroup} from "@angular/material/tabs"; +import {MatTooltip} from "@angular/material/tooltip"; +import { DeleteGroupsModalComponent } from './components/groups/delete-groups-modal/delete-groups-modal.component'; @NgModule({ declarations: [ AppComponent, @@ -70,7 +76,9 @@ import {MatMenu, MatMenuItem, MatMenuTrigger} from "@angular/material/menu"; DeleteModalComponent, EditOrganizationalUnitComponent, EditClientComponent, - ClassroomViewComponent + ClassroomViewComponent, + ClientViewComponent, + DeleteGroupsModalComponent ], bootstrap: [AppComponent], imports: [BrowserModule, @@ -92,7 +100,7 @@ import {MatMenu, MatMenuItem, MatMenuTrigger} from "@angular/material/menu"; MatSelectModule, MatDividerModule, MatStepperModule, - MatSlideToggleModule, MatMenu, MatMenuTrigger, MatMenuItem], + MatSlideToggleModule, MatMenu, MatMenuTrigger, MatMenuItem, MatAutocomplete, MatChipListbox, MatChipOption, MatChipSet, MatChip, MatProgressSpinner, MatTabGroup, MatTab, MatTooltip], providers: [ { provide: HTTP_INTERCEPTORS, diff --git a/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.css b/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.css index b701ae8..ea072ec 100644 --- a/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.css +++ b/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.css @@ -1,7 +1,9 @@ .classroom { display: flex; - flex-direction: column; - align-items: center; + flex-wrap: wrap; + gap: 10px; + height: 57vh; + overflow-y: auto; } .classroom-group { @@ -9,12 +11,11 @@ background-color: #fafafa; } -.organizational-unit-name { - font-weight: bold; - font-size: 18px; - margin-bottom: 10px; +mat-card-title { + display: flex; + justify-content: space-between; + margin: 10px; } - .client-row { display: flex; justify-content: center; @@ -27,18 +28,20 @@ } .client-box { - width: 100px; - height: 100px; + width: 100%; + height: auto; background-color: lightblue; - display: flex; - justify-content: center; - align-items: center; - border: 1px solid #000; box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1); border-radius: 5px; cursor: pointer; } +.client-box:hover { + box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); + scale: 1.1; + transition: 0.3s ease-in-out; +} + .client-box p { margin: 0; } diff --git a/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.html b/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.html index 382e3b1..5243026 100644 --- a/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.html +++ b/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.html @@ -1,12 +1,26 @@
-

Disposición {{ group.organizationalUnitName }}

+ Clientes dentro de: {{ group.organizationalUnitName }}
-

{{ client.name }}

+ + + {{ client.name }} + + + + + {{ client.ip }} + + + {{ client.mac }} + + + +
-
\ No newline at end of file + diff --git a/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.ts b/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.ts index 48f799b..0549a65 100644 --- a/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.ts +++ b/ogWebconsole/src/app/components/groups/classroom-view/classroom-view.component.ts @@ -1,6 +1,12 @@ // src/app/classroom-view/classroom-view.component.ts import { Component, Input, OnInit } from '@angular/core'; +import { + ChangePasswordModalComponent +} from "../../pages/admin/users/users/change-password-modal/change-password-modal.component"; +import {MatDialog} from "@angular/material/dialog"; +import {CreateClientComponent} from "../clients/create-client/create-client.component"; +import {ClientViewComponent} from "../client-view/client-view.component"; interface GroupedClients { organizationalUnitName: string; @@ -12,19 +18,19 @@ interface GroupedClients { templateUrl: './classroom-view.component.html', styleUrls: ['./classroom-view.component.css'] }) -export class ClassroomViewComponent implements OnInit { +export class ClassroomViewComponent implements OnInit { @Input() clients: any[] = []; @Input() pcInTable: number = 3; groupedClients: GroupedClients[] = []; - constructor() {} + constructor(public dialog: MatDialog) {} ngOnInit(): void { this.groupClientsByOrganizationalUnit(); } ngOnChanges(): void { - this.groupClientsByOrganizationalUnit(); + this.groupClientsByOrganizationalUnit(); } groupClientsByOrganizationalUnit(): void { @@ -53,5 +59,6 @@ export class ClassroomViewComponent implements OnInit { handleClientClick(client: any): void { console.log('Client clicked:', client); + const dialogRef = this.dialog.open(ClientViewComponent, { data: { client }, width: '700px', height:'700px'}); } } diff --git a/ogWebconsole/src/app/components/groups/client-view/client-view.component.css b/ogWebconsole/src/app/components/groups/client-view/client-view.component.css new file mode 100644 index 0000000..0ce046b --- /dev/null +++ b/ogWebconsole/src/app/components/groups/client-view/client-view.component.css @@ -0,0 +1,41 @@ +.mat-dialog-content { + padding: 20px; +} + +.button-column { + display: flex; + flex-direction: column; + gap: 20px; + margin: 20px; + padding: 20px; +} + +.button-encender { + background-color: #3f51b5; /* Azul */ + color: white; +} + +.button-apagar { + background-color: #e91e63; /* Rosa */ + color: white; +} + +.button-resetear { + background-color: #f44336; /* Rojo */ + color: white; +} + +.button-otros-1 { + background-color: #4caf50; /* Verde */ + color: white; +} + +.button-otros-2 { + background-color: #ff9800; /* Naranja */ + color: white; +} + +.button-otros-3 { + background-color: #9c27b0; /* Púrpura */ + color: white; +} diff --git a/ogWebconsole/src/app/components/groups/client-view/client-view.component.html b/ogWebconsole/src/app/components/groups/client-view/client-view.component.html new file mode 100644 index 0000000..3e02ffa --- /dev/null +++ b/ogWebconsole/src/app/components/groups/client-view/client-view.component.html @@ -0,0 +1,40 @@ +

Propiedades cliente

+
+ + + + Nombre: {{ data.client.name }} + IP: {{ data.client.ip }} + MAC: {{data.client.mac }} + Nº de serie: {{data.client.serialNumber }} + Netiface: {{data.client.netiface }} + Fecha de creación: {{data.client.createdAt | date }} + Creado por: {{data.client.createdBy }} + + + + + Menu: {{ data.client.menu }} + Perfil hardware: {{ data.client.hardwareProfile }} + OGlive: {{data.client.mac }} + Autoexec: {{data.client.serialNumber }} + Repositorio: {{data.client.netiface }} + Validacion: {{data.client.netiface }} + Página login: {{data.client.netiface }} + Página validacion: {{data.client.netiface }} + Fecha de creación: {{data.client.createdAt | date }} + Creado por: {{data.client.createdBy }} + + + +
+ + + + + + +
+
+
+
diff --git a/ogWebconsole/src/app/components/groups/client-view/client-view.component.spec.ts b/ogWebconsole/src/app/components/groups/client-view/client-view.component.spec.ts new file mode 100644 index 0000000..4ec9b84 --- /dev/null +++ b/ogWebconsole/src/app/components/groups/client-view/client-view.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ClientViewComponent } from './client-view.component'; + +describe('ClientViewComponent', () => { + let component: ClientViewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ClientViewComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ClientViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ogWebconsole/src/app/components/groups/client-view/client-view.component.ts b/ogWebconsole/src/app/components/groups/client-view/client-view.component.ts new file mode 100644 index 0000000..f31c7d3 --- /dev/null +++ b/ogWebconsole/src/app/components/groups/client-view/client-view.component.ts @@ -0,0 +1,14 @@ +import {Component, Inject} from '@angular/core'; +import {MAT_DIALOG_DATA} from "@angular/material/dialog"; + +@Component({ + selector: 'app-client-view', + templateUrl: './client-view.component.html', + styleUrl: './client-view.component.css' +}) +export class ClientViewComponent { + constructor( + @Inject(MAT_DIALOG_DATA) public data: any // Inject data for edit mode + ) { + } +} diff --git a/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.css b/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.css index 40124bd..ceac8f6 100644 --- a/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.css +++ b/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.css @@ -1,39 +1,48 @@ h1 { - text-align: center; - font-family: 'Roboto', sans-serif; - font-weight: 400; - color: #3f51b5; - margin-bottom: 20px; - } - - .network-form { - display: flex; - flex-direction: column; - gap: 15px; - } - - .form-field { - width: 100%; - margin-top: 10px; - } - - .mat-dialog-content { - padding: 20px; - } - - .mat-dialog-actions { - display: flex; - justify-content: flex-end; - padding: 10px 20px; - } - - button { - text-transform: none; - font-size: 16px; - font-weight: 500; - } - - .mat-slide-toggle { - margin-top: 20px; - } - \ No newline at end of file + text-align: center; + font-family: 'Roboto', sans-serif; + font-weight: 400; + color: #3f51b5; + margin-bottom: 20px; +} + +.network-form { + display: flex; + flex-direction: column; + gap: 15px; +} + +.form-field { + width: 100%; + margin-top: 10px; +} + +.mat-dialog-content { + padding: 50px; +} + +.mat-dialog-actions { + display: flex; + justify-content: flex-end; + padding: 10px 20px; +} + +button { + text-transform: none; + font-size: 16px; + font-weight: 500; +} + +.mat-slide-toggle { + margin-top: 20px; +} + +mat-option .unit-name { + display: block; +} + +mat-option .unit-path { + display: block; + font-size: 0.8em; + color: gray; +} diff --git a/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.html b/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.html index 6061f94..8044bc3 100644 --- a/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.html +++ b/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.html @@ -1,10 +1,13 @@

Añadir Cliente

-
+
Padre - {{ unit.name }} + +
{{ unit.name }}
+
{{ unit.path }}
+
@@ -17,26 +20,26 @@ Interfaz de Red + Ejemplo: eth0 Controlador de Red + Ejemplo: e1000e MAC + Ejemplo: 00:11:22:33:44:55 Formato de MAC inválido. Ejemplo válido: 00:11:22:33:44:55 Dirección IP + Ejemplo: 127.0.0.1 Formato de dirección IP inválido. Ejemplo válido: 127.0.0.1 - - Estado - - Menú URL @@ -44,7 +47,9 @@ Perfil de Hardware - + + {{ unit.name }} + Formato de URL inválido.
diff --git a/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.ts b/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.ts index 857c62e..78bfea9 100644 --- a/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.ts +++ b/ogWebconsole/src/app/components/groups/clients/create-client/create-client.component.ts @@ -1,7 +1,8 @@ import { HttpClient } from '@angular/common/http'; -import { Component, OnInit } from '@angular/core'; +import {Component, Inject, OnInit} from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MatDialogRef } from '@angular/material/dialog'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {MatSnackBar} from "@angular/material/snack-bar"; @Component({ selector: 'app-create-client', @@ -11,31 +12,36 @@ import { MatDialogRef } from '@angular/material/dialog'; export class CreateClientComponent implements OnInit { clientForm!: FormGroup; parentUnits: any[] = []; // Array to store parent units fetched from API + hardwareProfiles: any[] = []; // Array to store hardware profiles fetched from API + private errorForm: boolean = false; constructor( private fb: FormBuilder, private dialogRef: MatDialogRef, - private http: HttpClient - ) { } + private http: HttpClient, + private snackBar: MatSnackBar, + @Inject(MAT_DIALOG_DATA) public data: any // Inject data for edit mode + ) { + } ngOnInit(): void { this.loadParentUnits(); // Load parent units when component initializes + this.loadHardwareProfiles(); // Load hardware profiles when component initializes this.clientForm = this.fb.group({ - organizationalUnit: [''], + organizationalUnit: [this.data.organizationalUnit ? this.data.organizationalUnit['@id'] : null, Validators.required], name: ['', Validators.required], - serialNumber: [''], - netiface: "eth0", - netDriver: "e1000e", - mac: "00:11:22:33:44:55", - ip: "127.0.0.1", - status: "test", - menu: null, - hardwareProfile: null, + serialNumber: ['', Validators.required], + netiface: null, + netDriver: null, + mac: ['', Validators.required], + ip: ['', Validators.required], + menu: [this.data.organizationalUnit && this.data.organizationalUnit.menu ? this.data.organizationalUnit.menu['@id'] : null], + hardwareProfile: [this.data.organizationalUnit && this.data.organizationalUnit.hardwareProfile ? this.data.organizationalUnit.hardwareProfile['@id'] : null], }); } loadParentUnits() { - const url = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=30'; + const url = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=10000'; this.http.get(url).subscribe( response => { @@ -47,15 +53,31 @@ export class CreateClientComponent implements OnInit { ); } + loadHardwareProfiles() { + const url = 'http://127.0.0.1:8080/hardware-profiles'; + + this.http.get(url).subscribe( + response => { + this.hardwareProfiles = response['hydra:member']; + }, + error => { + console.error('Error fetching hardware profiles:', error); + } + ); + } + onSubmit() { if (this.clientForm.valid) { + this.errorForm = false const formData = this.clientForm.value; this.http.post('http://127.0.0.1:8080/clients', formData).subscribe( response => { this.dialogRef.close(response); - }, + this.openSnackBar(false, 'Cliente creado exitosamente'); }, error => { console.error('Error during POST:', error); + this.errorForm = true + this.openSnackBar(true, 'Error al crear el cliente: ' + error.error['hydra:description']); } ); } @@ -64,4 +86,10 @@ export class CreateClientComponent implements OnInit { onNoClick(): void { this.dialogRef.close(); } + + openSnackBar(isError: boolean, message: string) { + this.snackBar.open(message, 'Cerrar', { + panelClass: isError ? ['snackbar-error'] : ['snackbar-success'] + }); + } } diff --git a/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.css b/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.css index 40124bd..39cb26a 100644 --- a/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.css +++ b/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.css @@ -1,39 +1,38 @@ h1 { - text-align: center; - font-family: 'Roboto', sans-serif; - font-weight: 400; - color: #3f51b5; - margin-bottom: 20px; - } - - .network-form { - display: flex; - flex-direction: column; - gap: 15px; - } - - .form-field { - width: 100%; - margin-top: 10px; - } - - .mat-dialog-content { - padding: 20px; - } - - .mat-dialog-actions { - display: flex; - justify-content: flex-end; - padding: 10px 20px; - } - - button { - text-transform: none; - font-size: 16px; - font-weight: 500; - } - - .mat-slide-toggle { - margin-top: 20px; - } - \ No newline at end of file + text-align: center; + font-family: 'Roboto', sans-serif; + font-weight: 400; + color: #3f51b5; + margin-bottom: 20px; +} + +.network-form { + display: flex; + flex-direction: column; + gap: 15px; +} + +.form-field { + width: 100%; + margin-top: 10px; +} + +.mat-dialog-content { + padding: 50px; +} + +.mat-dialog-actions { + display: flex; + justify-content: flex-end; + padding: 10px 20px; +} + +button { + text-transform: none; + font-size: 16px; + font-weight: 500; +} + +.mat-slide-toggle { + margin-top: 20px; +} diff --git a/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.html b/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.html index 6a520fd..022cd3c 100644 --- a/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.html +++ b/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.html @@ -1,5 +1,5 @@

Editar Cliente

-
+
Padre @@ -11,6 +11,40 @@ Nombre + + Número de Serie + + + + Interfaz de Red + + + + Controlador de Red + + + + MAC + + Formato de MAC inválido. Ejemplo válido: 00:11:22:33:44:55 + + + Dirección IP + + Formato de dirección IP inválido. Ejemplo válido: 127.0.0.1 + + + Menú URL + + Formato de URL inválido. + + + Perfil de Hardware + + {{ unit.name }} + + Formato de URL inválido. +
diff --git a/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.ts b/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.ts index 60d38d3..584fe69 100644 --- a/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.ts +++ b/ogWebconsole/src/app/components/groups/clients/edit-client/edit-client.component.ts @@ -12,6 +12,7 @@ import { CreateClientComponent } from '../create-client/create-client.component' export class EditClientComponent { clientForm!: FormGroup; parentUnits: any[] = []; // Array to store parent units fetched from API + hardwareProfiles: any[] = []; // Array to store hardware profiles fetched from API isEditMode: boolean; // Flag to check if it's edit mode constructor( @@ -19,7 +20,6 @@ export class EditClientComponent { private dialogRef: MatDialogRef, private http: HttpClient, @Inject(MAT_DIALOG_DATA) public data: any // Inject data for edit mode - ) { this.isEditMode = !!data?.uuid; // Check if uuid is passed to determine edit mode if (this.isEditMode) { @@ -29,22 +29,22 @@ export class EditClientComponent { ngOnInit(): void { this.loadParentUnits(); // Load parent units when component initializes + this.loadHardwareProfiles(); // Load hardware profiles when component initializes this.clientForm = this.fb.group({ - organizationalUnit: [''], + organizationalUnit: [null,Validators.required], name: ['', Validators.required], - serialNumber: [''], - netiface: "eth0", - netDriver: "e1000e", - mac: "00:11:22:33:44:55", - ip: "127.0.0.1", - status: "test", + serialNumber: null, + netiface: null, + netDriver: null, + mac: null, + ip: null, menu: null, hardwareProfile: null, }); } loadParentUnits() { - const url = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=30'; + const url = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=10000'; this.http.get(url).subscribe( response => { @@ -56,6 +56,19 @@ export class EditClientComponent { ); } + loadHardwareProfiles() { + const url = 'http://127.0.0.1:8080/hardware-profiles'; + + this.http.get(url).subscribe( + response => { + this.hardwareProfiles = response['hydra:member']; + }, + error => { + console.error('Error fetching hardware profiles:', error); + } + ); + } + loadData(uuid: string) { const url = `http://127.0.0.1:8080/clients/${uuid}`; @@ -63,7 +76,13 @@ export class EditClientComponent { data => { this.clientForm.patchValue({ name: data.name, - organizationalUnit: data.organizationalUnit ? data.organizationalUnit['@id'] : '' + ip: data.ip, + mac: data.mac, + netiface: data.netiface, + netDriver: data.netDriver, + serialNumber: data.serialNumber, + hardwareProfile: data.hardwareProfile ? data.hardwareProfile['@id'] : null, + organizationalUnit: data.organizationalUnit ? data.organizationalUnit['@id'] : null }); }); } diff --git a/ogWebconsole/src/app/components/groups/data.service.ts b/ogWebconsole/src/app/components/groups/data.service.ts index 4b56083..2b9ace5 100644 --- a/ogWebconsole/src/app/components/groups/data.service.ts +++ b/ogWebconsole/src/app/components/groups/data.service.ts @@ -9,24 +9,16 @@ import { UnidadOrganizativa } from './model'; }) export class DataService { - private apiUrl = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=30'; + private apiUrl = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=1000'; private clientsUrl = 'http://127.0.0.1:8080/clients?page=1&itemsPerPage=30'; constructor(private http: HttpClient) {} - getUnidadesOrganizativas(): Observable { - return this.http.get(this.apiUrl).pipe( + getOrganizationalUnits(): Observable { + return this.http.get(`${this.apiUrl}&type=organizational-unit`).pipe( map(response => { if (response['hydra:member'] && Array.isArray(response['hydra:member'])) { return response['hydra:member'] - .filter((unidad: any) => unidad.type === 'organizational-unit') - .map((unidad: any) => ({ - id: unidad.id, - nombre: unidad.name, - uuid: unidad.uuid, - type: unidad.type, - aulas: [] - })); } else { throw new Error('Unexpected response format'); } @@ -38,11 +30,11 @@ export class DataService { ); } - getChildren(uuid: string): Observable { - return this.http.get(`${this.apiUrl}&parent=${uuid}`).pipe( + getChildren(id: string): Observable { + return this.http.get(`${this.apiUrl}&parent.id=${id}`).pipe( map(response => { if (response['hydra:member'] && Array.isArray(response['hydra:member'])) { - return response['hydra:member'].filter((element: any) => element.parent && element.parent['@id'] === `/organizational-units/${uuid}`); + return response['hydra:member'] } else { throw new Error('Unexpected response format'); } @@ -54,11 +46,11 @@ export class DataService { ); } - getClients(uuid: string): Observable { - return this.http.get(this.clientsUrl).pipe( + getClients(id: string): Observable { + return this.http.get(`${this.clientsUrl}&organizationalUnit.id=${id}`).pipe( map(response => { if (response['hydra:member'] && Array.isArray(response['hydra:member'])) { - return response['hydra:member'].filter((client: any) => client.organizationalUnit && client.organizationalUnit['@id'] === `/organizational-units/${uuid}`); + return response['hydra:member'] } else { throw new Error('Unexpected response format'); } @@ -82,6 +74,16 @@ export class DataService { ); } + changeParent(uuid: string): Observable { + const url = `http://127.0.0.1:8080/organizational-units/${uuid}/change-parent`; + // @ts-ignore + return this.http.post(url).pipe( + catchError(error => { + console.error('Error deleting element', error); + return throwError(error); + }) + ); + } } diff --git a/ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.css b/ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.css new file mode 100644 index 0000000..e69de29 diff --git a/ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.spec.ts b/ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.spec.ts new file mode 100644 index 0000000..9f88c39 --- /dev/null +++ b/ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DeleteGroupsModalComponent } from './delete-groups-modal.component'; + +describe('DeleteGroupsModalComponent', () => { + let component: DeleteGroupsModalComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DeleteGroupsModalComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(DeleteGroupsModalComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.ts b/ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.ts new file mode 100644 index 0000000..524987f --- /dev/null +++ b/ogWebconsole/src/app/components/groups/delete-groups-modal/delete-groups-modal.component.ts @@ -0,0 +1,30 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-delete-confirm-dialog', + template: ` +

Eliminar

+
+

¿Quiere borrar los clientes situados en {{data.name}} o quiere resituarlos en el nivel superior?

+
+
+ + +
+ ` +}) +export class DeleteGroupsModalComponent { + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { name: string } + ) {} + + deleteClick(): void { + this.dialogRef.close('delete'); + } + + changeClick(): void { + this.dialogRef.close('change'); + } +} diff --git a/ogWebconsole/src/app/components/groups/groups.component.css b/ogWebconsole/src/app/components/groups/groups.component.css index 8696ff5..bf6b4bd 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.css +++ b/ogWebconsole/src/app/components/groups/groups.component.css @@ -8,13 +8,24 @@ margin: 10px; } +.header-container { + height: 100px; +} + .unidad-card, .elements-card { flex: 1 1 45%; background-color: #fafafa; - max-height: 300px; + max-height: 400px; +} + +.element-content { overflow-y: auto; } +.title { + margin-left: 10px; +} + .details-card, .classroom-view { flex: 1 1 25%; } @@ -60,6 +71,10 @@ button { width: 100%; } +.item-content mat-icon { + margin-right: 10px; +} + .clickable-item:hover { cursor: pointer; } @@ -71,6 +86,7 @@ button { .actions { display: flex; margin-left: auto; + align-self: center; } .actions mat-icon { @@ -81,4 +97,16 @@ button { .actions mat-icon:hover { color: #212121; -} \ No newline at end of file +} + +.empty-list { + display: flex; + justify-content: center; + align-items: center; + height: 100%; +} + +mat-spinner { + margin: 0 auto; + align-self: center; +} diff --git a/ogWebconsole/src/app/components/groups/groups.component.html b/ogWebconsole/src/app/components/groups/groups.component.html index d97103a..d655b26 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.html +++ b/ogWebconsole/src/app/components/groups/groups.component.html @@ -1,24 +1,41 @@ -

Crear

-
- - +
+

Administrar grupos

+
+ + +
- -

Grupos

Unidad organizativa - - + +
- - apartment - {{ unidad.nombre }} - + apartment + {{ unidad.name }} - edit + edit + + add_home_work + + devices +
@@ -29,7 +46,7 @@
- Elementos + Elementos internos {{ crumb }} @@ -38,19 +55,28 @@
- - - + + + +
+ info + No hay elementos internos +
+
- - - - - {{ child.name || child.nombre }} - + + apartment + groups + school + computer + lan + help_outline + + {{child.name}} edit - delete + devices + delete
@@ -58,19 +84,5 @@
- - Detalles del elemento - -

Nombre: {{ selectedDetail.name || selectedDetail.nombre }}

-

Tipo: {{ selectedDetail.type }}

-

ID: {{ selectedDetail.id }}

-

UUID: {{ selectedDetail.uuid }}

- -
- -

Selecciona un elemento para ver sus detalles.

-
-
- - -
\ No newline at end of file + +
diff --git a/ogWebconsole/src/app/components/groups/groups.component.ts b/ogWebconsole/src/app/components/groups/groups.component.ts index ce0b6f5..e34873a 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.ts +++ b/ogWebconsole/src/app/components/groups/groups.component.ts @@ -7,6 +7,7 @@ import { DeleteModalComponent } from './delete-modal/delete-modal.component'; import { CreateClientComponent } from './clients/create-client/create-client.component'; import { EditOrganizationalUnitComponent } from './organizational-units/edit-organizational-unit/edit-organizational-unit.component'; import { EditClientComponent } from './clients/edit-client/edit-client.component'; +import {DeleteGroupsModalComponent} from "./delete-groups-modal/delete-groups-modal.component"; @Component({ selector: 'app-groups', @@ -14,21 +15,19 @@ import { EditClientComponent } from './clients/edit-client/edit-client.component styleUrls: ['./groups.component.css'] }) export class GroupsComponent implements OnInit { - unidadesOrganizativas: UnidadOrganizativa[] = []; + organizationalUnits: UnidadOrganizativa[] = []; selectedUnidad: UnidadOrganizativa | null = null; selectedDetail: any | null = null; // Nueva variable para el detalle del elemento seleccionado children: any[] = []; breadcrumb: string[] = []; clientsData: any[] = []; // Nueva variable para almacenar los datos de clients - - - breadcrumbData: any[] = []; // Almacenar datos de breadcrumb para navegar + loading:boolean = false; constructor(private dataService: DataService, public dialog: MatDialog) {} ngOnInit(): void { - this.dataService.getUnidadesOrganizativas().subscribe( - data => this.unidadesOrganizativas = data, + this.dataService.getOrganizationalUnits().subscribe( + data => this.organizationalUnits = data, error => console.error('Error fetching unidades organizativas', error) ); } @@ -36,17 +35,17 @@ constructor(private dataService: DataService, public dialog: MatDialog) {} onSelectUnidad(unidad: UnidadOrganizativa): void { this.selectedUnidad = unidad; this.selectedDetail = unidad; // Mostrar detalles de la unidad seleccionada - this.breadcrumb = [unidad.nombre]; + this.breadcrumb = [unidad.name]; this.breadcrumbData = [unidad]; - this.loadChildrenAndClients(unidad.uuid); + this.loadChildrenAndClients(unidad.id); } onSelectChild(child: any): void { this.selectedDetail = child; // Mostrar detalles del niño seleccionado if (child.type !== 'client' && child.uuid && child.id) { - this.breadcrumb.push(child.name || child.nombre); + this.breadcrumb.push(child.name || child.name); this.breadcrumbData.push(child); - this.loadChildrenAndClients(child.uuid); + this.loadChildrenAndClients(child.id); } } @@ -57,25 +56,25 @@ constructor(private dataService: DataService, public dialog: MatDialog) {} if (target.type === 'client') { this.selectedDetail = target; } else { - this.loadChildrenAndClients(target.uuid); + this.loadChildrenAndClients(target.id); } } - loadChildrenAndClients(uuid: string): void { - this.dataService.getChildren(uuid).subscribe( + loadChildrenAndClients(id: string): void { + this.loading = true + this.dataService.getChildren(id).subscribe( childrenData => { console.log('Children data:', childrenData); - this.dataService.getClients(uuid).subscribe( + this.dataService.getClients(id).subscribe( clientsData => { this.clientsData = clientsData; // Almacenar clientsData para pasarlo al componente hijo const newChildren = [...childrenData, ...clientsData]; - + if (newChildren.length > 0) { this.children = newChildren; } else { this.children = []; // Limpiar card2 cuando no hay elementos - this.breadcrumb.pop(); // Revertir breadcrumb solo si no hay elementos - + // Si deseas que la unidad organizativa se limpie completamente, descomenta la línea siguiente: // this.selectedUnidad = null; } @@ -92,79 +91,97 @@ constructor(private dataService: DataService, public dialog: MatDialog) {} this.children = []; // Limpiar card2 en caso de error } ); + this.loading = false } - - addOU(): void { - const dialogRef = this.dialog.open(CreateOrganizationalUnitComponent); + + addOU(parent:any = null): void { + console.log('Parent:', parent); + const dialogRef = this.dialog.open(CreateOrganizationalUnitComponent, { data: { parent }, width: '700px'}); dialogRef.afterClosed().subscribe(() => { - this.dataService.getUnidadesOrganizativas().subscribe( - data => this.unidadesOrganizativas = data, + this.dataService.getOrganizationalUnits().subscribe( + data => this.organizationalUnits = data, error => console.error('Error fetching unidades organizativas', error) ); }); } - addClient(): void { - const dialogRef = this.dialog.open(CreateClientComponent); + addClient(organizationalUnit:any = null): void { + const dialogRef = this.dialog.open(CreateClientComponent, { data: { organizationalUnit }, width: '700px'}); // Subscribirse al evento unitAdded del componente de creación después de cerrar el diálogo dialogRef.afterClosed().subscribe(() => { - this.dataService.getUnidadesOrganizativas().subscribe( - data => this.unidadesOrganizativas = data, + this.dataService.getOrganizationalUnits().subscribe( + data => this.organizationalUnits = data, error => console.error('Error fetching unidades organizativas', error) ); }); } + onDeleteClick(event: MouseEvent, uuid: string, name: string, type: string): void { + event.stopPropagation(); + if (type === 'client') { + const dialogRef = this.dialog.open(DeleteModalComponent, { + width: '400px', + data: { name } + }); - getIcon(type: string): string { - switch(type) { - case 'organizational-unit': - return 'apartment'; - case 'classroom-group': - return 'classrooms-group-icon'; - case 'classroom': - return 'classroom-icon'; - case 'client': - return 'client-icon'; - case 'clients-group': - return 'clients-group-icon'; - default: - return ''; + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.dataService.deleteElement(uuid, type).subscribe( + () => { + this.loadChildrenAndClients(this.selectedUnidad?.id || ''); + + this.dataService.getOrganizationalUnits().subscribe( + data => this.organizationalUnits = data, + error => console.error('Error fetching unidades organizativas', error) + ); + + }, + error => console.error('Error deleting element', error) + ); + } + }); + } else { + const dialogDeleteGroupRef = this.dialog.open(DeleteGroupsModalComponent, { + width: '400px', + data: { name } + }); + + dialogDeleteGroupRef.afterClosed().subscribe(result => { + if (result && result === 'delete') { + this.dataService.deleteElement(uuid, type).subscribe( + () => { + this.loadChildrenAndClients(this.selectedUnidad?.id || ''); + this.dataService.getOrganizationalUnits().subscribe( + data => this.organizationalUnits = data, + error => console.error('Error fetching unidades organizativas', error) + ); + }, + error => console.error('Error deleting element', error) + ); + } else if (result && result === 'change') { + this.dataService.changeParent(uuid).subscribe( + () => { + this.loadChildrenAndClients(this.selectedUnidad?.id || ''); + this.dataService.getOrganizationalUnits().subscribe( + data => this.organizationalUnits = data, + error => console.error('Error fetching unidades organizativas', error) + ); + }, + error => console.error('Error deleting element', error) + ); + } + }); } } - onDeleteClick(uuid: string, name: string, type: string): void { - const dialogRef = this.dialog.open(DeleteModalComponent, { - width: '250px', - data: { name } - }); - - dialogRef.afterClosed().subscribe(result => { - if (result) { - this.dataService.deleteElement(uuid, type).subscribe( - () => { - this.loadChildrenAndClients(this.selectedUnidad?.uuid || ''); - - this.dataService.getUnidadesOrganizativas().subscribe( - data => this.unidadesOrganizativas = data, - error => console.error('Error fetching unidades organizativas', error) - ); - - }, - error => console.error('Error deleting element', error) - ); - } - }); - } - onEditClick(type: any, uuid: string): void { console.log('Tipo del elemento a editar:', type); console.log('UUID del elemento a editar:', uuid); if (type != "client") { - const dialogRef = this.dialog.open(EditOrganizationalUnitComponent); + const dialogRef = this.dialog.open(EditOrganizationalUnitComponent, { data: { uuid }, width: '700px'}); } else { console.log('Editar cliente'); - const dialogRef = this.dialog.open(EditClientComponent); + const dialogRef = this.dialog.open(EditClientComponent, { data: { uuid }, width: '700px' } ); } } } diff --git a/ogWebconsole/src/app/components/groups/model.ts b/ogWebconsole/src/app/components/groups/model.ts index f90b50d..b37b389 100644 --- a/ogWebconsole/src/app/components/groups/model.ts +++ b/ogWebconsole/src/app/components/groups/model.ts @@ -9,11 +9,11 @@ export interface Aula { } export interface UnidadOrganizativa { - id: number; - nombre: string; + id: string; + name: string; uuid: string; type: string; - aulas: Aula[]; + parent: UnidadOrganizativa[]; } export interface OrganizationalUnit { @@ -50,4 +50,4 @@ export interface ClientCollection { "@id": string; "@type": string; }; -} \ No newline at end of file +} diff --git a/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.html b/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.html index 2c4fafa..9143c20 100644 --- a/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.html +++ b/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.html @@ -9,7 +9,9 @@ Tipo - {{ type }} + + {{ typeTranslations[type] }} + @@ -17,8 +19,9 @@ - Padre + Unidad organizativa padre + -- {{ unit.name }} @@ -46,10 +49,6 @@ Aforo - - Foto (URL) (string de prueba) - -
@@ -128,7 +127,6 @@ Perfil de Hardware - Validación
diff --git a/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.ts b/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.ts index 43229eb..c5ce903 100644 --- a/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.ts +++ b/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.ts @@ -1,6 +1,6 @@ -import { Component, OnInit, Output, EventEmitter } from '@angular/core'; +import {Component, OnInit, Output, EventEmitter, Inject} from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MatDialogRef } from '@angular/material/dialog'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import { HttpClient, HttpHeaders } from '@angular/common/http'; @Component({ @@ -13,20 +13,27 @@ export class CreateOrganizationalUnitComponent implements OnInit { generalFormGroup: FormGroup; additionalInfoFormGroup: FormGroup; networkSettingsFormGroup: FormGroup; - classroomInfoFormGroup: FormGroup; + classroomInfoFormGroup: FormGroup; types: string[] = ['organizational-unit', 'classrooms-group', 'classroom', 'clients-group']; - parentUnits: any[] = []; + typeTranslations: { [key: string]: string } = { + 'organizational-unit': 'Unidad organizativa', + 'classrooms-group': 'Grupo de aulas', + 'classroom': 'Aula', + 'clients-group': 'Grupo de clientes' + }; + parentUnits: any[] = []; - @Output() unitAdded = new EventEmitter(); + @Output() unitAdded = new EventEmitter(); constructor( private _formBuilder: FormBuilder, private dialogRef: MatDialogRef, - private http: HttpClient + private http: HttpClient, + @Inject(MAT_DIALOG_DATA) public data: any // Inject data for edit mode ) { this.generalFormGroup = this._formBuilder.group({ name: ['', Validators.required], - parent: [''], + parent: [this.data.parent ? this.data.parent['@id'] : null], description: [''], type: ['', Validators.required] }); @@ -53,17 +60,16 @@ export class CreateOrganizationalUnitComponent implements OnInit { location: [''], projector: [false], board: [false], - capacity: [0, Validators.min(0)], - photo: ['', Validators.pattern('https?://.+')] + capacity: [0, Validators.min(0)] }); } ngOnInit() { - this.loadParentUnits(); + this.loadParentUnits(); } loadParentUnits() { - const url = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=30'; + const url = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=10000'; this.http.get(url).subscribe( response => { @@ -106,11 +112,8 @@ export class CreateOrganizationalUnitComponent implements OnInit { if (classroomInfoFormValues.capacity !== undefined) { formData.capacity = classroomInfoFormValues.capacity; } - if (classroomInfoFormValues.photo !== undefined) { - formData.photo = classroomInfoFormValues.photo; - } } - + console.log('POST data:', formData); const postUrl = 'http://127.0.0.1:8080/organizational-units'; const headers = new HttpHeaders({ 'Content-Type': 'application/json' }); @@ -119,7 +122,7 @@ export class CreateOrganizationalUnitComponent implements OnInit { response => { console.log('POST successful:', response); this.unitAdded.emit(); - this.dialogRef.close(); + this.dialogRef.close(); }, error => { console.error('Error al realizar POST:', error); diff --git a/ogWebconsole/src/app/components/groups/organizational-units/edit-organizational-unit/edit-organizational-unit.component.ts b/ogWebconsole/src/app/components/groups/organizational-units/edit-organizational-unit/edit-organizational-unit.component.ts index 6c86f66..6e2de73 100644 --- a/ogWebconsole/src/app/components/groups/organizational-units/edit-organizational-unit/edit-organizational-unit.component.ts +++ b/ogWebconsole/src/app/components/groups/organizational-units/edit-organizational-unit/edit-organizational-unit.component.ts @@ -66,7 +66,7 @@ export class EditOrganizationalUnitComponent implements OnInit { } loadParentUnits() { - const url = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=30'; + const url = 'http://127.0.0.1:8080/organizational-units?page=1&itemsPerPage=10000'; this.http.get(url).subscribe( response => { @@ -93,20 +93,20 @@ export class EditOrganizationalUnitComponent implements OnInit { comments: data.comments }); this.networkSettingsFormGroup.patchValue({ - proxy: data.proxy, - dns: data.dns, - netmask: data.netmask, - router: data.router, - ntp: data.ntp, - p2pMode: data.p2pMode, - p2pTime: data.p2pTime, - mcastIp: data.mcastIp, - mcastSpeed: data.mcastSpeed, - mcastPort: data.mcastPort, - mcastMode: data.mcastMode, - menu: data.menu, - hardwareProfile: data.hardwareProfile, - validation: data.validation + proxy: data.networkSettings.proxy, + dns: data.networkSettings.dns, + netmask: data.networkSettings.netmask, + router: data.networkSettings.router, + ntp: data.networkSettings.ntp, + p2pMode: data.networkSettings.p2pMode, + p2pTime: data.networkSettings.p2pTime, + mcastIp: data.networkSettings.mcastIp, + mcastSpeed: data.networkSettings.mcastSpeed, + mcastPort: data.networkSettings.mcastPort, + mcastMode: data.networkSettings.mcastMode, + menu: data.networkSettings.menu, + hardwareProfile: data.networkSettings.hardwareProfile, + validation: data.networkSettings.validation }); }, error => { diff --git a/ogWebconsole/src/app/components/layout/header/header.component.css b/ogWebconsole/src/app/components/layout/header/header.component.css index 6c84df7..6e944a1 100644 --- a/ogWebconsole/src/app/components/layout/header/header.component.css +++ b/ogWebconsole/src/app/components/layout/header/header.component.css @@ -1,10 +1,15 @@ mat-toolbar { - height: 50px; + height: 60px; background-color: #3f51b5; color: white; } +.admin-button, +.user-button{ + background-color: #e0e0e0; +} + .navbar-button-row { display: flex; justify-content: end; @@ -16,6 +21,5 @@ button[mat-flat-button] { } .navbar-tittle{ - padding-left: 20px; cursor: pointer; } diff --git a/ogWebconsole/src/app/components/layout/header/header.component.html b/ogWebconsole/src/app/components/layout/header/header.component.html index 6a54ed5..cb93cff 100644 --- a/ogWebconsole/src/app/components/layout/header/header.component.html +++ b/ogWebconsole/src/app/components/layout/header/header.component.html @@ -1,7 +1,8 @@ Opengnsys webconsole
diff --git a/ogWebconsole/src/app/components/pages/admin/users/users/edit-user-modal/edit-user-modal.component.ts b/ogWebconsole/src/app/components/pages/admin/users/users/edit-user-modal/edit-user-modal.component.ts index 3b7fdb5..3a18cf1 100644 --- a/ogWebconsole/src/app/components/pages/admin/users/users/edit-user-modal/edit-user-modal.component.ts +++ b/ogWebconsole/src/app/components/pages/admin/users/users/edit-user-modal/edit-user-modal.component.ts @@ -3,12 +3,6 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { UserService } from '../users.service'; -interface UserGroup { - '@id': string; - name: string; - role: string[]; -} - @Component({ selector: 'app-edit-user-modal', templateUrl: './edit-user-modal.component.html', @@ -16,7 +10,7 @@ interface UserGroup { }) export class EditUserModalComponent implements OnInit {@Output() userEdited = new EventEmitter(); userForm: FormGroup; - userGroups: UserGroup[] = []; + userGroups: any[] = []; organizationalUnits: any[] = []; constructor( @@ -26,11 +20,12 @@ export class EditUserModalComponent implements OnInit {@Output() userEdited = ne private userService: UserService // Inyecta el servicio ) { this.userForm = this.fb.group({ - username: [this.data], + username: [this.data.user.username], password: [''], - role: this.data.user.allowedOrganizationalUnits, - organizationalUnit: [[this.data.user.allowedOrganizationalUnits], Validators.required] + userGroups: [this.data.user.userGroups.map((group: { '@id': any; }) => group['@id'])], + allowedOrganizationalUnits: [this.data.user.allowedOrganizationalUnits.map((unit: { '@id': any; }) => unit['@id'])] }); + console.log(this.userForm.value) } ngOnInit(): void { @@ -47,25 +42,25 @@ export class EditUserModalComponent implements OnInit {@Output() userEdited = ne } onSubmit(): void { + console.log(this.userForm.value); + const userPayload = { + username: this.userForm.value.username, + allowedOrganizationalUnits: this.userForm.value.allowedOrganizationalUnits, + password: this.userForm.value.password, + enabled: true, + userGroups: this.userForm.value.userGroups + }; - const userPayload = { - username: this.userForm.value.username, - allowedOrganizationalUnits: [], - password: this.userForm.value.password, - enabled: true, - userGroups: [this.userForm.value.role ] - }; - - this.userService.updateUser(this.data.user.uuid, userPayload).subscribe( - response => { - console.log('User added successfully:', response); - this.userEdited.emit(); - this.dialogRef.close(this.userForm.value); - }, - error => { - console.error('Error adding user:', error); - // Agregar alguna lógica para manejar el error en la interfaz de usuario - } - ); + this.userService.updateUser(this.data.user.uuid, userPayload).subscribe( + response => { + console.log('User added successfully:', response); + this.userEdited.emit(); + this.dialogRef.close(this.userForm.value); + }, + error => { + console.error('Error adding user:', error); + // Agregar alguna lógica para manejar el error en la interfaz de usuario + } + ); } } 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 078193a..35bbdf8 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 @@ -62,7 +62,8 @@ export class UsersComponent implements OnInit { editUser(user: any) { // Implementar la lógica de edición const dialogRef = this.dialog.open(EditUserModalComponent, { - data: { user: user } + data: { user: user }, + width: '400px' }); dialogRef.componentInstance.userEdited.subscribe(() => { this.loadUsers(); @@ -71,7 +72,7 @@ export class UsersComponent implements OnInit { deleteUser(user: any) { const dialogRef = this.dialog.open(DeleteUserModalComponent, { - data: user + data: user, }); dialogRef.afterClosed().subscribe(result => { diff --git a/ogWebconsole/src/app/components/pages/admin/users/users/users.service.ts b/ogWebconsole/src/app/components/pages/admin/users/users/users.service.ts index e64f772..3e0811a 100644 --- a/ogWebconsole/src/app/components/pages/admin/users/users/users.service.ts +++ b/ogWebconsole/src/app/components/pages/admin/users/users/users.service.ts @@ -10,6 +10,12 @@ interface UserPayload { allowedOrganizationalUnits: any[]; } +interface ChangePasswordPayload { + currentPassword: string; + newPassword: string; + repeatNewPassword: string; +} + interface UserGroup { '@id': string; name: string; @@ -38,6 +44,13 @@ export class UserService { return this.http.put(`${this.apiUrl}/users/${userId}`, userPayload, { headers }); } + changePassword(userId: number, userPayload: ChangePasswordPayload): Observable { + const headers = new HttpHeaders({ + 'Content-Type': 'application/ld+json', + }); + return this.http.put(`${this.apiUrl}/users/${userId}/reset-password`, userPayload, { headers }); + } + getUserGroups(): Observable<{ 'hydra:member': UserGroup[] }> { return this.http.get<{ 'hydra:member': UserGroup[] }>(`${this.apiUrl}/user-groups`); } @@ -48,6 +61,6 @@ export class UserService { getOrganizationalUnits(): Observable { return this.http.get(`${this.apiUrl}/organizational-units?page=1&itemsPerPage=30`); - + } }