From 9226dd50d65e25f585c8a5d3bf3fad671c685dd5 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Thu, 3 Oct 2024 13:02:36 +0200 Subject: [PATCH] Refactor users/roles --- ogWebconsole/.env | 2 +- ogWebconsole/src/app/app.module.ts | 2 - .../add-role-modal.component.css | 40 ++++++--- .../add-role-modal.component.html | 12 +-- .../add-role-modal.component.ts | 75 ++++++++++++---- .../admin/roles/roles/data.service.ts | 51 +++++++++++ .../admin/roles/roles/roles.component.css | 34 +++++-- .../admin/roles/roles/roles.component.html | 31 +++++-- .../admin/roles/roles/roles.component.ts | 77 ++++++++++++---- .../admin/roles/roles/roles.service.ts | 24 ----- .../add-user-modal.component.css | 33 +++++-- .../add-user-modal.component.html | 24 ++--- .../add-user-modal.component.ts | 86 ++++++++++++------ .../change-password-modal.component.html | 10 +-- .../change-password-modal.component.ts | 32 +++---- .../admin/users/users/data.service.ts | 88 +++++++++++++++++++ .../edit-user-modal.component.css | 16 ---- .../edit-user-modal.component.html | 35 -------- .../edit-user-modal.component.spec.ts | 40 --------- .../edit-user-modal.component.ts | 82 ----------------- .../admin/users/users/users.component.css | 35 ++++++-- .../admin/users/users/users.component.html | 32 +++++-- .../admin/users/users/users.component.spec.ts | 5 +- .../admin/users/users/users.component.ts | 72 ++++++++++----- .../admin/users/users/users.service.ts | 66 -------------- .../calendar/calendar.component.css | 19 ---- .../components/calendar/calendar.component.ts | 1 - .../create-calendar-rule.component.ts | 16 ++-- .../create-calendar.component.ts | 1 - .../advanced-search.component.html | 1 + .../advanced-search.component.ts | 2 +- .../client-tab-view.component.ts | 5 ++ ...organizational-unit-tab-view.component.css | 11 +++ ...rganizational-unit-tab-view.component.html | 10 ++- .../organizational-unit-tab-view.component.ts | 11 ++- .../create-organizational-unit.component.html | 6 +- .../create-organizational-unit.component.ts | 13 ++- .../edit-organizational-unit.component.html | 10 +-- .../edit-organizational-unit.component.ts | 25 +++--- 39 files changed, 643 insertions(+), 492 deletions(-) create mode 100644 ogWebconsole/src/app/components/admin/roles/roles/data.service.ts delete mode 100644 ogWebconsole/src/app/components/admin/roles/roles/roles.service.ts create mode 100644 ogWebconsole/src/app/components/admin/users/users/data.service.ts delete mode 100644 ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.css delete mode 100644 ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.html delete mode 100644 ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.spec.ts delete mode 100644 ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.ts delete mode 100644 ogWebconsole/src/app/components/admin/users/users/users.service.ts diff --git a/ogWebconsole/.env b/ogWebconsole/.env index 0da820a..454cc0f 100644 --- a/ogWebconsole/.env +++ b/ogWebconsole/.env @@ -1,2 +1,2 @@ #NG_APP_BASE_API_URL=http://127.0.0.1:8090 -NG_APP_BASE_API_URL=http://127.0.0.1:8001 \ No newline at end of file +NG_APP_BASE_API_URL=http://127.0.0.1:8080 diff --git a/ogWebconsole/src/app/app.module.ts b/ogWebconsole/src/app/app.module.ts index a462ce1..8773ebc 100644 --- a/ogWebconsole/src/app/app.module.ts +++ b/ogWebconsole/src/app/app.module.ts @@ -28,7 +28,6 @@ import { MatTableModule } from '@angular/material/table'; import { MatDialogModule } from '@angular/material/dialog'; import { AddUserModalComponent } from './components/admin/users/users/add-user-modal/add-user-modal.component'; import { MatSelectModule } from '@angular/material/select'; -import { EditUserModalComponent } from './components/admin/users/users/edit-user-modal/edit-user-modal.component'; import { AddRoleModalComponent } from './components/admin/roles/roles/add-role-modal/add-role-modal.component'; import { ChangePasswordModalComponent } from './components/admin/users/users/change-password-modal/change-password-modal.component'; import { GroupsComponent } from './components/groups/groups.component'; @@ -114,7 +113,6 @@ import { OrganizationalUnitTabViewComponent } from './components/groups/componen UsersComponent, RolesComponent, AddUserModalComponent, - EditUserModalComponent, AddRoleModalComponent, ChangePasswordModalComponent, GroupsComponent, diff --git a/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.css b/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.css index de8f3c7..13e2689 100644 --- a/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.css +++ b/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.css @@ -1,10 +1,30 @@ -.role-form .form-field { - display: block; - margin-bottom: 10px; /* Puedes ajustar el valor para cambiar la separación */ - } - - .checkbox-group label { - display: block; - margin-bottom: 8px; /* Ajusta este valor según necesites */ - } - \ No newline at end of file +.full-width { + width: 100%; +} +.form-container { + padding: 40px; +} + +.form-group { + margin-top: 20px; + margin-bottom: 26px; +} + +.full-width { + width: 100%; + margin-bottom: 16px; +} + +.checkbox-group { + margin: 15px 0; + align-items: flex-start; +} + +.time-fields { + display: flex; + gap: 15px; /* Espacio entre los campos */ +} + +.time-field { + flex: 1; +} diff --git a/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.html b/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.html index 344162f..3f621b1 100644 --- a/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.html +++ b/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.html @@ -1,7 +1,7 @@ -

Añadir Rol (TBD)

-
+

Añadir Rol

+
- + Nombre @@ -15,8 +15,8 @@

Usuario

-
-
+ + -
+ diff --git a/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.ts b/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.ts index 6f928e8..d8255fc 100644 --- a/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.ts +++ b/ogWebconsole/src/app/components/admin/roles/roles/add-role-modal/add-role-modal.component.ts @@ -1,7 +1,9 @@ import { HttpClient } from '@angular/common/http'; import { Component, Inject } from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import { FormBuilder, FormGroup } from '@angular/forms'; +import {FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {DataService} from "../data.service"; +import {ToastrService} from "ngx-toastr"; @Component({ selector: 'app-add-role-modal', @@ -10,21 +12,49 @@ import { FormBuilder, FormGroup } from '@angular/forms'; }) export class AddRoleModalComponent { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; - roleForm: FormGroup; + roleForm: FormGroup; + roleId: string | null = null; constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, private http: HttpClient, - private fb: FormBuilder + private fb: FormBuilder, + private dataService: DataService, + private toastService: ToastrService ) { this.roleForm = this.fb.group({ - name: [''], + name: ['', Validators.required], superAdmin: [false], orgAdmin: [false], orgOperator: [false], orgMinimal: [false], - userRole: [false] + userRole: [false], + }); + } + + ngOnInit(): void { + if (this.data) { + this.load() + } + } + + load(): void { + this.dataService.getUserGroup(this.data).subscribe({ + next: (response) => { + this.roleForm.patchValue({ + name: response.name, + superAdmin: response.permissions.includes('ROLE_SUPER_ADMIN'), + orgAdmin: response.permissions.includes('ROLE_ORGANIZATIONAL_UNIT_ADMIN'), + orgOperator: response.permissions.includes('ROLE_ORGANIZATIONAL_UNIT_OPERATOR'), + orgMinimal: response.permissions.includes('ROLE_ORGANIZATIONAL_UNIT_MINIMAL'), + userRole: response.permissions.includes('ROLE_USER'), + }); + this.roleId = response['@id']; + }, + error: (err) => { + console.error('Error fetching remote calendar:', err); + } }); } @@ -43,21 +73,36 @@ export class AddRoleModalComponent { if (formValues.orgMinimal) selectedPermissions.push('ROLE_ORGANIZATIONAL_UNIT_MINIMAL'); if (formValues.userRole) selectedPermissions.push('ROLE_USER'); - const payload = { name: formValues.name, permissions: selectedPermissions, - enabled: true + enabled: true }; - this.http.post(`${this.baseUrl}/user-groups`, payload).subscribe( - (response) => { - this.dialogRef.close(); - }, - (error) => { - console.error('Error al añadir rol', error); - } - ); + if (this.roleId) { + this.http.put(`${this.baseUrl}${this.roleId}`, payload).subscribe( + (response) => { + this.toastService.success('Rol actualizado correctamente'); + this.dialogRef.close(); + }, + (error) => { + this.toastService.error('Error al editar el rol:', error); + console.error('Error al editar el rol', error); + } + ); + } else { + this.http.post(`${this.baseUrl}/user-groups`, payload).subscribe( + (response) => { + this.toastService.success('Rol añadido correctamente'); + this.dialogRef.close(); + }, + (error) => { + this.toastService.error('Error al añadir rol:', error); + console.error('Error al añadir rol', error); + } + ); + } } } + } diff --git a/ogWebconsole/src/app/components/admin/roles/roles/data.service.ts b/ogWebconsole/src/app/components/admin/roles/roles/data.service.ts new file mode 100644 index 0000000..1d48441 --- /dev/null +++ b/ogWebconsole/src/app/components/admin/roles/roles/data.service.ts @@ -0,0 +1,51 @@ +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 { + baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; + private apiUrl = `${this.baseUrl}/user-groups?page=1&itemsPerPage=1000`; + + constructor(private http: HttpClient) {} + + getUserGroups(filters: { [key: string]: string }): Observable<{ totalItems: any; data: any }> { + const params = new HttpParams({ fromObject: filters }); + + return this.http.get(this.apiUrl, { params }).pipe( + map(response => { + if (response['hydra:member'] && Array.isArray(response['hydra:member'])) { + return { + data: response['hydra:member'], + totalItems: response['hydra:totalItems'] + } + } else { + throw new Error('Unexpected response format'); + } + }), + catchError(error => { + console.error('Error fetching user groups', error); + return throwError(error); + }) + ); + } + + getUserGroup(id: string): Observable { + return this.http.get(`${this.baseUrl}${id}`).pipe( + map(response => { + if (response.name && response.permissions) { + return response; + } else { + throw new Error('Unexpected response format'); + } + }), + catchError(error => { + console.error('Error fetching user group', error); + return throwError(error); + }) + ); + } +} diff --git a/ogWebconsole/src/app/components/admin/roles/roles/roles.component.css b/ogWebconsole/src/app/components/admin/roles/roles/roles.component.css index 5c924e8..f658cc1 100644 --- a/ogWebconsole/src/app/components/admin/roles/roles/roles.component.css +++ b/ogWebconsole/src/app/components/admin/roles/roles/roles.component.css @@ -3,19 +3,43 @@ table { margin-top: 50px; } -.header-container { - margin-top: 16px; +.search-container { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 16px; + width: 100%; + padding: 0 5px; + box-sizing: border-box; } -.header-container h1 { - margin: 0; +.divider { + margin: 20px 0; +} + +.search-string { + flex: 2; + padding: 5px; +} + +.search-boolean { + flex: 1; + padding: 5px; +} + +.header-container { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; } .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/admin/roles/roles/roles.component.html b/ogWebconsole/src/app/components/admin/roles/roles/roles.component.html index d45ff57..0307328 100644 --- a/ogWebconsole/src/app/components/admin/roles/roles/roles.component.html +++ b/ogWebconsole/src/app/components/admin/roles/roles/roles.component.html @@ -1,20 +1,39 @@
-

Gestión de roles

- +

Administrar Roles

+
+ +
+
+ +
+ + Buscar nombre de rol + + search + Pulsar 'enter' para buscar +
- - - +
{{ column.header }} {{ column.cell(role) }} Acciones - + Acciones + +
+
+ + +
diff --git a/ogWebconsole/src/app/components/admin/roles/roles/roles.component.ts b/ogWebconsole/src/app/components/admin/roles/roles/roles.component.ts index 2541a97..1578413 100644 --- a/ogWebconsole/src/app/components/admin/roles/roles/roles.component.ts +++ b/ogWebconsole/src/app/components/admin/roles/roles/roles.component.ts @@ -1,11 +1,13 @@ import { Component, OnInit } from '@angular/core'; -import { RoleService } from './roles.service'; import { MatTableDataSource } from '@angular/material/table'; import { MatDialog } from '@angular/material/dialog'; import { AddRoleModalComponent } from './add-role-modal/add-role-modal.component'; import { DeleteModalComponent } from '../../../../shared/delete_modal/delete-modal/delete-modal.component'; import { HttpClient } from '@angular/common/http'; import { ToastrService } from 'ngx-toastr'; +import {DataService} from "./data.service"; +import {CreateCalendarComponent} from "../../../calendar/create-calendar/create-calendar.component"; +import {PageEvent} from "@angular/material/paginator"; @Component({ selector: 'app-roles', @@ -15,6 +17,13 @@ import { ToastrService } from 'ngx-toastr'; export class RolesComponent implements OnInit { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; dataSource = new MatTableDataSource(); + filters: { [key: string]: string } = {}; + loading:boolean = false; + length: number = 0; + itemsPerPage: number = 10; + page: number = 0; + pageSizeOptions: number[] = [5, 10, 20, 40, 100]; + columns = [ { columnDef: 'id', @@ -34,49 +43,81 @@ export class RolesComponent implements OnInit { ]; displayedColumns = [...this.columns.map(column => column.columnDef), 'actions']; - constructor(private roleService: RoleService, public dialog: MatDialog, private http: HttpClient, - private toastService: ToastrService) {} + private apiUrl = `${this.baseUrl}/user-groups`; + + constructor( + public dialog: MatDialog, + private http: HttpClient, + private dataService: DataService, + private toastService: ToastrService + ) {} ngOnInit() { - this.loadRoles(); + this.search(); } - loadRoles() { - this.roleService.getRoles().subscribe(response => { - console.log(response); - this.dataSource.data = response['hydra:member']; - }); + search() { + this.http.get(`${this.apiUrl}?&page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}`, { params: this.filters }).subscribe( + (data) => { + this.dataSource.data = data['hydra:member']; + this.length = data['hydra:totalItems']; + }, + (error) => { + console.error('Error fetching commands', error); + } + ); } addUser() { - const dialogRef = this.dialog.open(AddRoleModalComponent); + const dialogRef = this.dialog.open(AddRoleModalComponent, { + width: '600px' + }); dialogRef.afterClosed().subscribe((result) => { - this.loadRoles(); + this.search(); + }); + } + + editRole(role: any): void { + const dialogRef = this.dialog.open(AddRoleModalComponent, { + width: '600px', + data: role['@id'] + }); + + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.search(); + } }); } deleteRole(role: any): void { const dialogRef = this.dialog.open(DeleteModalComponent, { - width: '300px', - data: { name: role.name } + width: '500px', + data: { name: role.name } }); dialogRef.afterClosed().subscribe(result => { if (result) { const apiUrl = `${this.baseUrl}/user-groups/${role.uuid}`; - + this.http.delete(apiUrl).subscribe({ next: () => { - this.loadRoles(); - this.toastService.success('Role deleted successfully'); + this.search(); + this.toastService.success('Role deleted successfully'); }, error: (error) => { - this.toastService.error('Error deleting role:', error); + this.toastService.error('Error deleting role:', error); } }); } }); } - + + onPageChange(event: any): void { + this.page = event.pageIndex; + this.itemsPerPage = event.pageSize; + this.length = event.length; + this.search(); + } } diff --git a/ogWebconsole/src/app/components/admin/roles/roles/roles.service.ts b/ogWebconsole/src/app/components/admin/roles/roles/roles.service.ts deleted file mode 100644 index c978c62..0000000 --- a/ogWebconsole/src/app/components/admin/roles/roles/roles.service.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Observable } from 'rxjs'; - -interface Role { - '@id': string; - name: string; - permissions: string[]; -} - -@Injectable({ - providedIn: 'root' -}) -export class RoleService { - private apiUrl = import.meta.env.NG_APP_BASE_API_URL; - - - constructor(private http: HttpClient) {} - - getRoles(): Observable<{ 'hydra:member': Role[] }> { - return this.http.get<{ 'hydra:member': Role[] }>(`${this.apiUrl}/user-groups?page=1&itemsPerPage=30`); - } - -} diff --git a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.css b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.css index 4eb0278..13e2689 100644 --- a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.css +++ b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.css @@ -1,9 +1,30 @@ -.user-form .form-field { - display: block; - margin-bottom: 10px; /* Puedes ajustar el valor para cambiar la separación */ +.full-width { + width: 100%; +} +.form-container { + padding: 40px; } -.checkbox-group label { - display: block; - margin-bottom: 8px; /* Ajusta este valor según necesites */ +.form-group { + margin-top: 20px; + margin-bottom: 26px; +} + +.full-width { + width: 100%; + margin-bottom: 16px; +} + +.checkbox-group { + margin: 15px 0; + align-items: flex-start; +} + +.time-fields { + display: flex; + gap: 15px; /* Espacio entre los campos */ +} + +.time-field { + flex: 1; } diff --git a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.html b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.html index 1b5684c..fa79517 100644 --- a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.html +++ b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.html @@ -1,35 +1,35 @@ -

Añadir Usuario

-
+

Añadir Usuario

+
- + Nombre de usuario - + Contraseña - + Rol - + {{ group.name }} - + Unidad organiativa - + {{unit.name}} -
-
+ + - -
+ + diff --git a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts index 8e0ffe8..a785e39 100644 --- a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts +++ b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts @@ -1,8 +1,9 @@ import { Component, EventEmitter, Inject, OnInit, Output } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { UserService } from '../users.service'; import {ToastrService} from "ngx-toastr"; +import {HttpClient} from "@angular/common/http"; +import {DataService} from "../data.service"; interface UserGroup { '@id': string; @@ -16,34 +17,61 @@ interface UserGroup { styleUrls: ['./add-user-modal.component.css'] }) export class AddUserModalComponent implements OnInit { + baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; @Output() userAdded = new EventEmitter(); - userForm: FormGroup; + userForm: FormGroup; userGroups: UserGroup[] = []; organizationalUnits: any[] = []; + userId: string | null = null; constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, + private http: HttpClient, private fb: FormBuilder, - private userService: UserService, + private dataService: DataService, private toastService: ToastrService ) { this.userForm = this.fb.group({ username: ['', Validators.required], password: ['', Validators.required], role: ['', Validators.required], - organizationalUnit: [[], Validators.required] + organizationalUnits: [[]] }); } ngOnInit(): void { - this.userService.getUserGroups().subscribe((data) => { + this.dataService.getUserGroups().subscribe((data) => { this.userGroups = data['hydra:member']; }); - this.userService.getOrganizationalUnits().subscribe((data) => { + this.dataService.getOrganizationalUnits().subscribe((data) => { this.organizationalUnits = data['hydra:member'].filter((item: any) => item.type === 'organizational-unit'); }); + if (this.data) { + this.load() + } + } + load(): void { + this.dataService.getUser(this.data).subscribe({ + next: (response) => { + console.log(response); + + const organizationalUnitIds = response.allowedOrganizationalUnits.map((unit: any) => unit['@id']); + + // Patch the values to the form + this.userForm.patchValue({ + username: response.username, + role: response.userGroups[0]['@id'], + organizationalUnits: organizationalUnitIds + }); + + this.userId = response['@id']; + }, + error: (err) => { + console.error('Error fetching remote calendar:', err); + } + }); } onNoClick(): void { @@ -52,7 +80,7 @@ export class AddUserModalComponent implements OnInit { onSubmit(): void { if (this.userForm.valid) { - const userPayload = { + const payload = { username: this.userForm.value.username, allowedOrganizationalUnits: this.userForm.value.organizationalUnit, password: this.userForm.value.password, @@ -60,27 +88,29 @@ export class AddUserModalComponent implements OnInit { userGroups: [this.userForm.value.role ] }; - this.userService.addUser(userPayload).subscribe( - response => { - console.log('User playload:', userPayload); - console.log('User added successfully:', response); - this.userAdded.emit(); - this.dialogRef.close(this.userForm.value); - this.openSnackBar(false, 'Usuario creado correctamente') - }, - error => { - console.error('Error adding user:', error); - this.openSnackBar(true, error.error['hydra:description']); - // Agregar alguna lógica para manejar el error en la interfaz de usuario - } - ); + if (this.userId) { + this.http.put(`${this.baseUrl}${this.userId}`, payload).subscribe( + (response) => { + this.toastService.success('Usuario editado correctamente'); + this.dialogRef.close(); + }, + (error) => { + this.toastService.error(error['error']['hydra:description']); + console.error('Error al editar el rol', error); + } + ); + } else { + this.http.post(`${this.baseUrl}/users`, payload).subscribe( + (response) => { + this.toastService.success('Usuario añadido correctamente'); + this.dialogRef.close(); + }, + (error) => { + this.toastService.error(error['error']['hydra:description']); + console.error('Error al añadir añadido', error); + } + ); + } } } - - openSnackBar(isError: boolean, message: string) { - if (isError) { - this.toastService.error(' Error al eliminar la entidad: ' + message, 'Error'); - } else - this.toastService.success(message, 'Éxito'); - } } diff --git a/ogWebconsole/src/app/components/admin/users/users/change-password-modal/change-password-modal.component.html b/ogWebconsole/src/app/components/admin/users/users/change-password-modal/change-password-modal.component.html index 8eff0f1..c3bea94 100644 --- a/ogWebconsole/src/app/components/admin/users/users/change-password-modal/change-password-modal.component.html +++ b/ogWebconsole/src/app/components/admin/users/users/change-password-modal/change-password-modal.component.html @@ -1,5 +1,5 @@

Editar Usuario

-
+
Contraseña actual @@ -14,8 +14,6 @@ - -
Las contraseñas no coinciden
@@ -24,8 +22,8 @@ {{ resetPasswordError }}
- -
+ + -
+ diff --git a/ogWebconsole/src/app/components/admin/users/users/change-password-modal/change-password-modal.component.ts b/ogWebconsole/src/app/components/admin/users/users/change-password-modal/change-password-modal.component.ts index 49b8864..5e99ff5 100644 --- a/ogWebconsole/src/app/components/admin/users/users/change-password-modal/change-password-modal.component.ts +++ b/ogWebconsole/src/app/components/admin/users/users/change-password-modal/change-password-modal.component.ts @@ -1,9 +1,9 @@ import { Component, EventEmitter, Inject, Output } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import { EditUserModalComponent } from '../edit-user-modal/edit-user-modal.component'; -import { UserService } from '../users.service'; - +import { DataService } from '../data.service'; +import {AddUserModalComponent} from "../add-user-modal/add-user-modal.component"; +import {ToastrService} from "ngx-toastr"; @Component({ selector: 'app-change-password-modal', templateUrl: './change-password-modal.component.html', @@ -18,10 +18,11 @@ export class ChangePasswordModalComponent { resetPasswordError: string = ''; constructor( - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, private fb: FormBuilder, - private userService: UserService + private dataService: DataService, + private toastService: ToastrService ) { this.userForm = this.fb.group({ currentPassword: ['', Validators.required], @@ -49,20 +50,21 @@ export class ChangePasswordModalComponent { newPassword: this.userForm.value.newPassword, repeatNewPassword: this.userForm.value.repeatNewPassword }; - console.log("THIS IS THE USER PAYLOAD: ", userPayload); - this.userService.changePassword(this.data.uuid, userPayload).subscribe( - response => { - console.log('User updated successfully:', response); + + this.dataService.changePassword(this.data.uuid, userPayload).subscribe({ + next: () => { this.userEdited.emit(); - this.dialogRef.close(this.userForm.value); + this.dialogRef.close(); + this.toastService.success('Contraseña cambiada con éxito'); }, - error => { - console.error('Error updating user:', error.error['hydra:description']); - this.resetPasswordError = error.error['hydra:description'] + error: (err) => { + console.error('Error changing password:', err); + this.toastService.error(err.error['hydra:description']); + this.resetPasswordError = err.error.message; this.updateError = true; - this.loading = false + this.loading = false; } - ); + }); } else { console.error('Form is invalid'); this.passwordMismatch = this.userForm.hasError('mismatch'); diff --git a/ogWebconsole/src/app/components/admin/users/users/data.service.ts b/ogWebconsole/src/app/components/admin/users/users/data.service.ts new file mode 100644 index 0000000..732987e --- /dev/null +++ b/ogWebconsole/src/app/components/admin/users/users/data.service.ts @@ -0,0 +1,88 @@ + +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 { + baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; + private apiUrl = `${this.baseUrl}/users?page=1&itemsPerPage=1000`; + + constructor(private http: HttpClient) {} + + getUsers(filters: { [key: string]: string }): Observable<{ totalItems: any; data: any }> { + const params = new HttpParams({ fromObject: filters }); + + return this.http.get(this.apiUrl, { params }).pipe( + map(response => { + if (response['hydra:member'] && Array.isArray(response['hydra:member'])) { + return { + data: response['hydra:member'], + totalItems: response['hydra:totalItems'] + } + } else { + throw new Error('Unexpected response format'); + } + }), + catchError(error => { + console.error('Error fetching users', error); + return throwError(error); + }) + ); + } + + getUser(id: string): Observable { + return this.http.get(`${this.baseUrl}${id}`).pipe( + map(response => { + if (response.username) { + return response; + } else { + throw new Error('Unexpected response format'); + } + }), + catchError(error => { + console.error('Error fetching user group', error); + return throwError(error); + }) + ); + } + + getUserGroups(): Observable { + return this.http.get(`${this.baseUrl}/user-groups`).pipe( + map(response => { + if (response['hydra:member'] && Array.isArray(response['hydra:member'])) { + return response; + } else { + throw new Error('Unexpected response format'); + } + }), + catchError(error => { + console.error('Error fetching user groups', error); + return throwError(error); + }) + ); + } + + getOrganizationalUnits(): Observable { + return this.http.get(`${this.baseUrl}/organizational-units`).pipe( + map(response => { + if (response['hydra:member'] && Array.isArray(response['hydra:member'])) { + return response; + } else { + throw new Error('Unexpected response format'); + } + }), + catchError(error => { + console.error('Error fetching organizational units', error); + return throwError(error); + }) + ); + } + + changePassword(userId: number, userPayload: any): Observable { + return this.http.put(`${this.baseUrl}/users/${userId}/reset-password`, userPayload); + } +} diff --git a/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.css b/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.css deleted file mode 100644 index 44b82d0..0000000 --- a/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.css +++ /dev/null @@ -1,16 +0,0 @@ -.user-form .form-field { - display: block; - margin-bottom: 10px; /* Puedes ajustar el valor para cambiar la separación */ -} - -.checkbox-group label { - display: block; - margin-bottom: 8px; /* Ajusta este valor según necesites */ -} - -.loading-container{ - display: flex; - justify-content: center; - align-items: center; - height: 100%; -} diff --git a/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.html b/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.html deleted file mode 100644 index b2e04cc..0000000 --- a/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.html +++ /dev/null @@ -1,35 +0,0 @@ -

Editar Usuario

- -
-
- - Nombre de usuario - - - - Contraseña - - - - Rol - - - {{ group.name }} - - - - - - Unidad organizativa - - - {{unit.name}} - - - -
-
-
- - -
diff --git a/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.spec.ts b/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.spec.ts deleted file mode 100644 index 4cd660a..0000000 --- a/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import { ReactiveFormsModule } from '@angular/forms'; -import { EditUserModalComponent } from './edit-user-modal.component'; -import { UserService } from '../users.service'; -import { ToastrService } from 'ngx-toastr'; -import { of } from 'rxjs'; - -describe('EditUserModalComponent', () => { - let component: EditUserModalComponent; - let fixture: ComponentFixture; - let dialogRefSpy: jasmine.SpyObj>; - let userServiceSpy: jasmine.SpyObj; - let toastServiceSpy: jasmine.SpyObj; - - beforeEach(async () => { - dialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']); - userServiceSpy = jasmine.createSpyObj('UserService', ['getUserGroups', 'getOrganizationalUnits']); - toastServiceSpy = jasmine.createSpyObj('ToastrService', ['success', 'error']); - - await TestBed.configureTestingModule({ - declarations: [EditUserModalComponent], - imports: [ReactiveFormsModule], - providers: [ - { provide: MatDialogRef, useValue: dialogRefSpy }, - { provide: MAT_DIALOG_DATA, useValue: { user: { username: 'testUser', userGroups: [], allowedOrganizationalUnits: [] } } }, - { provide: UserService, useValue: userServiceSpy }, - { provide: ToastrService, useValue: toastServiceSpy } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(EditUserModalComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.ts b/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.ts deleted file mode 100644 index 0cbd03c..0000000 --- a/ogWebconsole/src/app/components/admin/users/users/edit-user-modal/edit-user-modal.component.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Component, EventEmitter, Inject, OnInit, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { UserService } from '../users.service'; -import {ToastrService} from "ngx-toastr"; - -@Component({ - selector: 'app-edit-user-modal', - templateUrl: './edit-user-modal.component.html', - styleUrls: ['./edit-user-modal.component.css'] -}) -export class EditUserModalComponent implements OnInit {@Output() userEdited = new EventEmitter(); - userForm: FormGroup; - userGroups: any[] = []; - organizationalUnits: any[] = []; - loading:boolean = false; - - constructor( - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any, - private fb: FormBuilder, - private userService: UserService, // Inyecta el servicio - private toastService: ToastrService - ) { - this.userForm = this.fb.group({ - username: [this.data.user.username], - password: [null], - userGroups: [this.data.user.userGroups.map((group: { '@id': any; }) => group['@id'])], - allowedOrganizationalUnits: [this.data.user.allowedOrganizationalUnits.map((unit: { '@id': any; }) => unit['@id'])] - }); - } - - ngOnInit(): void { - this.loading = true - this.userService.getUserGroups().subscribe((data) => { - this.userGroups = data['hydra:member']; - }); - this.userService.getOrganizationalUnits().subscribe((data) => { - this.organizationalUnits = data['hydra:member'].filter((item: any) => item.type === 'organizational-unit'); - this.loading = false - }, (error) => { - console.error('Error fetching organizational units', error); - this.loading = false - }); - } - - onNoClick(): void { - this.dialogRef.close(); - } - - 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 - }; - - 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); - this.openSnackBar(false, 'Usuario actualizado correctamente') - }, - error => { - console.error('Error adding user:', error); - this.openSnackBar(true, error.message); - // Agregar alguna lógica para manejar el error en la interfaz de usuario - } - ); - } - - openSnackBar(isError: boolean, message: string) { - if (isError) { - this.toastService.error(' Error al eliminar la entidad: ' + message, 'Error'); - } else - this.toastService.success(message, 'Éxito'); - } -} diff --git a/ogWebconsole/src/app/components/admin/users/users/users.component.css b/ogWebconsole/src/app/components/admin/users/users/users.component.css index 42bdbdf..f658cc1 100644 --- a/ogWebconsole/src/app/components/admin/users/users/users.component.css +++ b/ogWebconsole/src/app/components/admin/users/users/users.component.css @@ -3,18 +3,43 @@ table { margin-top: 50px; } -.header-container { - margin-top: 16px; +.search-container { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 16px; + width: 100%; + padding: 0 5px; + box-sizing: border-box; } -.header-container h1 { - margin: 0; +.divider { + margin: 20px 0; +} + +.search-string { + flex: 2; + padding: 5px; +} + +.search-boolean { + flex: 1; + padding: 5px; +} + +.header-container { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; } .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/admin/users/users/users.component.html b/ogWebconsole/src/app/components/admin/users/users/users.component.html index 8d58c00..59e47fd 100644 --- a/ogWebconsole/src/app/components/admin/users/users/users.component.html +++ b/ogWebconsole/src/app/components/admin/users/users/users.component.html @@ -1,6 +1,17 @@
-

Gestión de usuarios

- +

Administrar usuarios

+
+ +
+
+ +
+ + Buscar nombre de usuario + + search + Pulsar 'enter' para buscar +
@@ -10,13 +21,20 @@ - - + -
Acciones - - + Acciones + +
+
+ + +
diff --git a/ogWebconsole/src/app/components/admin/users/users/users.component.spec.ts b/ogWebconsole/src/app/components/admin/users/users/users.component.spec.ts index c22cd60..df4f32b 100644 --- a/ogWebconsole/src/app/components/admin/users/users/users.component.spec.ts +++ b/ogWebconsole/src/app/components/admin/users/users/users.component.spec.ts @@ -5,7 +5,6 @@ import { MatDialogModule } from '@angular/material/dialog'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ToastrService } from 'ngx-toastr'; import { of } from 'rxjs'; -import { UserService } from './users.service'; import { NO_ERRORS_SCHEMA } from '@angular/core'; // Add this import for schema // Create a mock for UserService @@ -33,13 +32,13 @@ describe('UsersComponent', () => { HttpClientTestingModule, ], providers: [ - { provide: UserService, useClass: MockUserService }, + { useClass: MockUserService }, { provide: ToastrService, useValue: { success: () => {} } }, // Mock ToastrService ], schemas: [NO_ERRORS_SCHEMA], // Use this to ignore unrecognized components in template }) .compileComponents(); - + fixture = TestBed.createComponent(UsersComponent); component = fixture.componentInstance; fixture.detectChanges(); diff --git a/ogWebconsole/src/app/components/admin/users/users/users.component.ts b/ogWebconsole/src/app/components/admin/users/users/users.component.ts index b8da04b..23144f2 100644 --- a/ogWebconsole/src/app/components/admin/users/users/users.component.ts +++ b/ogWebconsole/src/app/components/admin/users/users/users.component.ts @@ -1,12 +1,12 @@ import { Component, OnInit } from '@angular/core'; -import { UserService } from './users.service'; import { MatTableDataSource } from '@angular/material/table'; import { MatDialog } from '@angular/material/dialog'; import { AddUserModalComponent } from './add-user-modal/add-user-modal.component'; -import { EditUserModalComponent } from './edit-user-modal/edit-user-modal.component'; import { DeleteModalComponent } from '../../../../shared/delete_modal/delete-modal/delete-modal.component'; import { HttpClient } from '@angular/common/http'; import { ToastrService } from 'ngx-toastr'; +import {DataService} from "./data.service"; +import {AddRoleModalComponent} from "../../roles/roles/add-role-modal/add-role-modal.component"; @Component({ selector: 'app-users', @@ -17,6 +17,12 @@ import { ToastrService } from 'ngx-toastr'; export class UsersComponent implements OnInit { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; dataSource = new MatTableDataSource(); + filters: { [key: string]: string } = {}; + loading:boolean = false; + length: number = 0; + itemsPerPage: number = 10; + page: number = 0; + pageSizeOptions: number[] = [5, 10, 20, 40, 100]; columns = [ { columnDef: 'id', @@ -41,55 +47,68 @@ export class UsersComponent implements OnInit { ]; displayedColumns = [...this.columns.map(column => column.columnDef), 'actions']; - constructor(private userService: UserService, public dialog: MatDialog, + private apiUrl = `${this.baseUrl}/users`; + + constructor( + public dialog: MatDialog, private http: HttpClient, - private toastService: ToastrService) {} + private dataService: DataService, + private toastService: ToastrService + ) {} ngOnInit() { - this.loadUsers(); + this.search(); } - loadUsers() { - this.userService.getUsers().subscribe(response => { - this.dataSource.data = response['hydra:member']; - }); + search() { + this.http.get(`${this.apiUrl}?&page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}`, { params: this.filters }).subscribe( + (data) => { + this.dataSource.data = data['hydra:member']; + this.length = data['hydra:totalItems']; + }, + (error) => { + console.error('Error fetching commands', error); + } + ); } addUser() { const dialogRef = this.dialog.open(AddUserModalComponent, { width: '500px' }); dialogRef.componentInstance.userAdded.subscribe(() => { - this.loadUsers(); + this.search(); }); } - editUser(user: any) { - // Implementar la lógica de edición - const dialogRef = this.dialog.open(EditUserModalComponent, { - data: { user: user }, - width: '500px' + editUser(user: any): void { + const dialogRef = this.dialog.open(AddUserModalComponent, { + width: '600px', + data: user['@id'] }); - dialogRef.componentInstance.userEdited.subscribe(() => { - this.loadUsers(); + + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.search(); + } }); } deleteUser(user: any): void { const dialogRef = this.dialog.open(DeleteModalComponent, { - width: '300px', - data: { name: user.name } + width: '500px', + data: { name: user.username } }); - + dialogRef.afterClosed().subscribe(result => { if (result) { const apiUrl = `${this.baseUrl}/users/${user.uuid}`; - + this.http.delete(apiUrl).subscribe({ next: () => { console.log('User deleted successfully'); this.toastService.success('User deleted successfully'); - this.loadUsers(); + this.search(); }, error: (error) => { console.error('Error deleting user:', error); @@ -100,5 +119,12 @@ export class UsersComponent implements OnInit { } }); } - + + onPageChange(event: any): void { + this.page = event.pageIndex; + this.itemsPerPage = event.pageSize; + this.length = event.length; + this.search(); + } + } diff --git a/ogWebconsole/src/app/components/admin/users/users/users.service.ts b/ogWebconsole/src/app/components/admin/users/users/users.service.ts deleted file mode 100644 index c11de16..0000000 --- a/ogWebconsole/src/app/components/admin/users/users/users.service.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Observable } from 'rxjs'; - -interface UserPayload { - username: string; - password: string; - enabled: boolean; - userGroups: string[]; - allowedOrganizationalUnits: any[]; -} - -interface ChangePasswordPayload { - currentPassword: string; - newPassword: string; - repeatNewPassword: string; -} - -interface UserGroup { - '@id': string; - name: string; - role: string[]; -} - -@Injectable({ - providedIn: 'root' -}) -export class UserService { - private apiUrl = import.meta.env.NG_APP_BASE_API_URL; - - constructor(private http: HttpClient) {} - - addUser(userPayload: UserPayload): Observable { - const headers = new HttpHeaders({ - 'Content-Type': 'application/ld+json', - }); - return this.http.post(`${this.apiUrl}/users`, userPayload, { headers }); - } - - updateUser(userId: number, userPayload: UserPayload): Observable { - const headers = new HttpHeaders({ - 'Content-Type': 'application/ld+json', - }); - 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`); - } - - getUsers(): Observable { - return this.http.get(`${this.apiUrl}/users?page=1&itemsPerPage=30`); - } - - getOrganizationalUnits(): Observable { - return this.http.get(`${this.apiUrl}/organizational-units?page=1&itemsPerPage=10000`); - - } -} diff --git a/ogWebconsole/src/app/components/calendar/calendar.component.css b/ogWebconsole/src/app/components/calendar/calendar.component.css index 16117cb..cbdd6d8 100644 --- a/ogWebconsole/src/app/components/calendar/calendar.component.css +++ b/ogWebconsole/src/app/components/calendar/calendar.component.css @@ -81,22 +81,3 @@ table { 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; -} - -.example-button-row { - display: table-cell; - max-width: 600px; -} - -.example-button-row .mat-mdc-button-base { - margin: 8px 8px 8px 0; -} - diff --git a/ogWebconsole/src/app/components/calendar/calendar.component.ts b/ogWebconsole/src/app/components/calendar/calendar.component.ts index d21d2d4..0a7e6fd 100644 --- a/ogWebconsole/src/app/components/calendar/calendar.component.ts +++ b/ogWebconsole/src/app/components/calendar/calendar.component.ts @@ -23,7 +23,6 @@ export class CalendarComponent implements OnInit { itemsPerPage: number = 10; page: number = 1; pageSizeOptions: number[] = [5, 10, 20, 40, 100]; - selectedElements: string[] = []; loading:boolean = false; filters: { [key: string]: string } = {}; alertMessage: string | null = null; diff --git a/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.ts b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.ts index 6711779..7433292 100644 --- a/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.ts +++ b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.ts @@ -37,13 +37,13 @@ export class CreateCalendarRuleComponent { this.calendarId = this.data.calendar if (this.data) { this.isEditMode = true; - this.availableFromDate = this.data.rule.availableFromDate; - this.availableToDate = this.data.rule.availableToDate; - this.isRemoteAvailable = this.data.rule.isRemoteAvailable; - this.availableReason = this.data.rule.availableReason; - this.busyFromHour = this.data.rule.busyFromHour; - this.busyToHour = this.data.rule.busyToHour; - if (this.data.rule.busyWeekDays) { + this.availableFromDate = this.data.rule? this.data.rule.availableFromDate : null; + this.availableToDate = this.data.rule? this.data.rule.availableToDate : null; + this.isRemoteAvailable = this.data.rule? this.data.rule.isRemoteAvailable : false; + this.availableReason = this.data.rule? this.data.rule.availableReason : null; + this.busyFromHour = this.data.rule? this.data.rule.busyFromHour : null; + this.busyToHour = this.data.rule? this.data.rule.busyToHour : null; + if (this.data.rule && this.data.rule.busyWeekDays) { this.busyWeekDays = this.data.rule.busyWeekDays.reduce((acc: { [x: string]: boolean; }, day: string | number) => { @@ -52,7 +52,7 @@ export class CreateCalendarRuleComponent { return acc; }, {}); } - this.ruleId = this.data.rule['@id'] + this.ruleId = this.data.rule ? this.data.rule['@id'] : null } } diff --git a/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.ts b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.ts index bf579f9..7b049a2 100644 --- a/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.ts +++ b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.ts @@ -51,7 +51,6 @@ export class CreateCalendarComponent implements OnInit { }); } - getBusyWeekDaysMap(indices: number[]): string[] { console.log(indices) const weekDays = ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo']; diff --git a/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.html b/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.html index 856edcd..5f9c6bc 100644 --- a/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.html +++ b/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.html @@ -113,6 +113,7 @@

{{ result.type !== 'client' ? result.type : '' }}

{{ result.type === 'client' ? result.ip : '' }}

{{ result.type === 'client' ? result.mac : '' }}

+

{{ result.type === 'client' ? result.status : '' }}

Unidades internas: {{ result.type !== 'client' ? result.children.length : 0 }}

diff --git a/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.ts b/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.ts index 9fa3b34..a21b6d4 100644 --- a/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.ts +++ b/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.ts @@ -410,4 +410,4 @@ export class AdvancedSearchComponent { const dialogRef = this.dialog.open(AcctionsModalComponent, { data: { selectedElements: this.selectedElements }, width: '700px'}); } -} \ No newline at end of file +} diff --git a/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.ts b/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.ts index cc4b819..1e178cd 100644 --- a/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.ts +++ b/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.ts @@ -52,6 +52,11 @@ export class ClientTabViewComponent { header: 'Mac', cell: (client: any) => `${client.mac}` }, + { + columnDef: 'status', + header: 'Estado', + cell: (client: any) => `${client.status}` + }, { columnDef: 'organizationalUnit', header: 'Pertenece a', diff --git a/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.css b/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.css index 27cd5b5..e4feb8b 100644 --- a/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.css +++ b/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.css @@ -34,3 +34,14 @@ button{ margin-left: 10px; } + +.mat-chip-success { + background-color: #4CAF50 !important; + color: white !important; +} + +.mat-chip-error { + background-color: #F44336 !important; + color: white !important; +} + diff --git a/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.html b/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.html index b781fd6..8f8479b 100644 --- a/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.html +++ b/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.html @@ -27,9 +27,13 @@ - diff --git a/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.ts b/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.ts index 788d0d2..81bb8aa 100644 --- a/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.ts +++ b/ogWebconsole/src/app/components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component.ts @@ -55,6 +55,16 @@ export class OrganizationalUnitTabViewComponent { header: 'Tipo', cell: (ou: any) => `${ou.type}` }, + { + columnDef: 'remoteCalendar', + header: 'Calendario', + cell: (ou: any) => `${ou.remoteCalendar ? ou.remoteCalendar.name : '-'}` + }, + { + columnDef: 'available', + header: 'Aula Reservada', + cell: (ou: any) => `${ou.available ? 'No' : 'Si'}` + }, { columnDef: 'createdAt', header: 'Fecha de creación', @@ -134,7 +144,6 @@ export class OrganizationalUnitTabViewComponent { this.getOrganizationalUnits(); } - search(): void { this.loading = true; this.getOrganizationalUnits() diff --git a/ogWebconsole/src/app/components/groups/shared/organizational-units/create-organizational-unit/create-organizational-unit.component.html b/ogWebconsole/src/app/components/groups/shared/organizational-units/create-organizational-unit/create-organizational-unit.component.html index 3195b81..8f97427 100644 --- a/ogWebconsole/src/app/components/groups/shared/organizational-units/create-organizational-unit/create-organizational-unit.component.html +++ b/ogWebconsole/src/app/components/groups/shared/organizational-units/create-organizational-unit/create-organizational-unit.component.html @@ -49,10 +49,10 @@ Aforo - + Calendario Asociado - - + + {{ calendar.name }} diff --git a/ogWebconsole/src/app/components/groups/shared/organizational-units/create-organizational-unit/create-organizational-unit.component.ts b/ogWebconsole/src/app/components/groups/shared/organizational-units/create-organizational-unit/create-organizational-unit.component.ts index 744f925..86fa72f 100644 --- a/ogWebconsole/src/app/components/groups/shared/organizational-units/create-organizational-unit/create-organizational-unit.component.ts +++ b/ogWebconsole/src/app/components/groups/shared/organizational-units/create-organizational-unit/create-organizational-unit.component.ts @@ -74,14 +74,14 @@ export class CreateOrganizationalUnitComponent implements OnInit { mcastMode: [''], menu: [''], hardwareProfile: [''], - validation: [false], - remoteCalendar: [''] + validation: [false] }); this.classroomInfoFormGroup = this._formBuilder.group({ location: [''], projector: [false], board: [false], - capacity: [0, Validators.min(0)] + capacity: [0, Validators.min(0)], + remoteCalendar: [''] }); } @@ -149,9 +149,9 @@ export class CreateOrganizationalUnitComponent implements OnInit { } private isFormValid(): boolean { - return this.generalFormGroup.valid && - this.additionalInfoFormGroup.valid && - this.networkSettingsFormGroup.valid && + return this.generalFormGroup.valid && + this.additionalInfoFormGroup.valid && + this.networkSettingsFormGroup.valid && (this.generalFormGroup.value.type !== 'classroom' || this.classroomInfoFormGroup.valid); } @@ -166,7 +166,6 @@ export class CreateOrganizationalUnitComponent implements OnInit { ...classroomInfoFormValues, comments: additionalInfoFormValues.comments, networkSettings: { ...networkSettingsFormValues }, - remoteCalendar: this.selectedCalendarUuid ? `/remote-calendars/${this.selectedCalendarUuid}` : null, menu: networkSettingsFormValues.menu || null, hardwareProfile: networkSettingsFormValues.hardwareProfile || null, }; diff --git a/ogWebconsole/src/app/components/groups/shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component.html b/ogWebconsole/src/app/components/groups/shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component.html index cece434..1929cbb 100644 --- a/ogWebconsole/src/app/components/groups/shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component.html +++ b/ogWebconsole/src/app/components/groups/shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component.html @@ -46,12 +46,10 @@ - -

Calendario asociado actual {{currentCalendar.name}}

- + Calendario Asociado - - + + {{ calendar.name }} @@ -63,7 +61,7 @@ - + diff --git a/ogWebconsole/src/app/components/groups/shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component.ts b/ogWebconsole/src/app/components/groups/shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component.ts index 73a7024..f5419fe 100644 --- a/ogWebconsole/src/app/components/groups/shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component.ts +++ b/ogWebconsole/src/app/components/groups/shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component.ts @@ -19,9 +19,9 @@ export class EditOrganizationalUnitComponent implements OnInit { networkSettingsFormGroup: FormGroup; classroomInfoFormGroup: FormGroup; types: string[] = ['organizational-unit', 'classrooms-group', 'classroom', 'clients-group']; - parentUnits: any[] = []; + parentUnits: any[] = []; hardwareProfiles: any[] = []; - isEditMode: boolean; + isEditMode: boolean; currentCalendar: any = []; protected p2pModeOptions = [ {"name": 'Leecher', "value": "p2p-mode-leecher"}, @@ -32,18 +32,18 @@ export class EditOrganizationalUnitComponent implements OnInit { {"name": 'Half duplex', "value": "half-duplex"}, {"name": 'Full duplex', "value": "full-duplex"}, ]; - @Output() unitAdded = new EventEmitter(); + @Output() unitAdded = new EventEmitter(); calendars: any; constructor( private _formBuilder: FormBuilder, private dialogRef: MatDialogRef, - private http: HttpClient, + private http: HttpClient, private dataService: DataService, private toastService: ToastrService, - @Inject(MAT_DIALOG_DATA) public data: any + @Inject(MAT_DIALOG_DATA) public data: any ) { - this.isEditMode = !!data?.uuid; + this.isEditMode = !!data?.uuid; this.generalFormGroup = this._formBuilder.group({ name: ['', Validators.required], @@ -78,7 +78,7 @@ export class EditOrganizationalUnitComponent implements OnInit { projector: [false], board: [false], capacity: [0, Validators.min(0)], - calendarSelect: [null] + remoteCalendar: [null] }); if (this.isEditMode) { @@ -130,7 +130,7 @@ export class EditOrganizationalUnitComponent implements OnInit { loadCurrentCalendar(uuid: string): void { const apiUrl = `${this.baseUrl}/remote-calendars/${uuid}`; this.http.get(apiUrl).subscribe( - response => this.currentCalendar = response, + response => this.currentCalendar = response, error => { console.error('Error loading current calendar', error); this.openSnackBar(true, 'Error loading current calendar'); @@ -140,7 +140,7 @@ export class EditOrganizationalUnitComponent implements OnInit { onCalendarChange(event: any) { const selectedCalendarId = event.value; console.log('Selected calendar ID:', selectedCalendarId); - // Aquí puedes agregar la lógica adicional para manejar el cambio de calendario si es necesario + this.generalFormGroup.value.remoteCalendar = selectedCalendarId; } loadData(uuid: string) { @@ -179,27 +179,30 @@ export class EditOrganizationalUnitComponent implements OnInit { projector: data.projector, board: data.board, capacity: data.capacity, - calendarSelect: data.remoteCalendar['@id'] + remoteCalendar: data.remoteCalendar ? data.remoteCalendar['@id'] : null }); - this.loadCurrentCalendar(data.remoteCalendar.uuid); }, + error => { console.error('Error fetching data for edit:', error); this.openSnackBar(true, 'Error al cargar la unidad organizativa: ' + error.error['hydra:description']) this.onNoClick() } ); + console.log(this.classroomInfoFormGroup.value); } onSubmit() { if (this.generalFormGroup.valid && this.additionalInfoFormGroup.valid && this.networkSettingsFormGroup.valid) { const parentValue = this.generalFormGroup.value.parent; + console.log(this.generalFormGroup.value.remoetCalendar); const formData = { name: this.generalFormGroup.value.name, parent: parentValue || null, description: this.generalFormGroup.value.description, comments: this.additionalInfoFormGroup.value.comments, + remoteCalendar: this.generalFormGroup.value.remoteCalendar, type: this.generalFormGroup.value.type, networkSettings: this.networkSettingsFormGroup.value };
{{ column.header }} - - {{ column.cell(image) }} + + + {{ column.cell(ou) }} + + + check + close