Refactor users/roles
parent
eaad62fb2e
commit
9226dd50d6
|
@ -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
|
||||
NG_APP_BASE_API_URL=http://127.0.0.1:8080
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<h1 mat-dialog-title i18n="@@dialogTitleAddRole">Añadir Rol (TBD)</h1>
|
||||
<div mat-dialog-content>
|
||||
<h1 mat-dialog-title i18n="@@dialogTitleAddRole">Añadir Rol</h1>
|
||||
<mat-dialog-content class="form-container">
|
||||
<form [formGroup]="roleForm" class="role-form">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label i18n="@@labelRoleName">Nombre</mat-label>
|
||||
<input matInput formControlName="name" required>
|
||||
</mat-form-field>
|
||||
|
@ -15,8 +15,8 @@
|
|||
<p><mat-checkbox formControlName="userRole" i18n="@@checkboxUserRole">Usuario</mat-checkbox></p>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button (click)="onNoClick()" i18n="@@buttonCancel">Cancelar</button>
|
||||
<button mat-button (click)="onSubmit()" i18n="@@buttonAdd">Añadir</button>
|
||||
</div>
|
||||
</mat-dialog-actions>
|
||||
|
|
|
@ -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<any>;
|
||||
roleId: string | null = null;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<AddRoleModalComponent>,
|
||||
@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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<any>(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<any> {
|
||||
return this.http.get<any>(`${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);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,39 @@
|
|||
<div class="header-container">
|
||||
<h1 i18n="@@headerRoleManagement">Gestión de roles</h1>
|
||||
<button mat-flat-button color="primary" (click)="addUser()" i18n="@@buttonAddRole">+ Añadir</button>
|
||||
<h2 class="title" i18n="@@adminImagesTitle">Administrar Roles</h2>
|
||||
<div class="images-button-row">
|
||||
<button mat-flat-button color="primary" (click)="addUser()">Añadir rol</button>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
<div class="search-container">
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label i18n="@@searchLabel">Buscar nombre de rol</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar</mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||
<td mat-cell *matCellDef="let role"> {{ column.cell(role) }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef i18n="@@headerActions">Acciones</th>
|
||||
<td mat-cell *matCellDef="let role">
|
||||
<button mat-button color="warn" [disabled]="role.name === 'Super Admin'" (click)="deleteRole(role)" i18n="@@buttonDelete">Eliminar</button>
|
||||
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions" style="text-align: center;">Acciones</th>
|
||||
<td mat-cell *matCellDef="let role" style="text-align: center;">
|
||||
<button mat-icon-button color="primary" (click)="editRole(role)" i18n="@@editImage"> <mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="warn" (click)="deleteRole(role)" i18n="@@buttonDelete" [disabled]="role.permissions.includes('ROLE_SUPER_ADMIN')"><mat-icon>delete</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
<div class="paginator-container">
|
||||
<mat-paginator [length]="length"
|
||||
[pageSize]="itemsPerPage"
|
||||
[pageIndex]="page"
|
||||
[pageSizeOptions]="pageSizeOptions"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
|
|
|
@ -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<any>();
|
||||
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<any>(`${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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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`);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
<h1 mat-dialog-title i18n="@@dialogTitleAddUser">Añadir Usuario</h1>
|
||||
<div mat-dialog-content>
|
||||
<h1 mat-dialog-title i18n="@@dialogTitleAddRole">Añadir Usuario</h1>
|
||||
<mat-dialog-content class="form-container">
|
||||
<form [formGroup]="userForm" class="user-form">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label i18n="@@addUserlabelUsername">Nombre de usuario</mat-label>
|
||||
<input matInput formControlName="username" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label i18n="@@addUserlabelPassword">Contraseña</mat-label>
|
||||
<input matInput formControlName="password" type="password" required>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label i18n="@@labelRole">Rol</mat-label>
|
||||
<mat-select formControlName="role">
|
||||
<mat-select formControlName="role" required>
|
||||
<mat-option *ngFor="let group of userGroups" [value]="group['@id']">
|
||||
{{ group.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label i18n="@@labelOrganizationalUnit">Unidad organiativa</mat-label>
|
||||
<mat-select multiple formControlName="organizationalUnit">
|
||||
<mat-select multiple formControlName="organizationalUnits">
|
||||
<mat-option *ngFor="let unit of organizationalUnits" [value]="unit['@id']">
|
||||
{{unit.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button (click)="onNoClick()" i18n="@@buttonCancel">Cancelar</button>
|
||||
<button mat-button [disabled]="!userForm.valid" (click)="onSubmit()" i18n="@@buttonAdd">Añadir</button>
|
||||
</div>
|
||||
<button mat-button (click)="onSubmit()" i18n="@@buttonAdd">Añadir</button>
|
||||
</mat-dialog-actions>
|
||||
|
|
|
@ -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<void>();
|
||||
userForm: FormGroup;
|
||||
userForm: FormGroup<any>;
|
||||
userGroups: UserGroup[] = [];
|
||||
organizationalUnits: any[] = [];
|
||||
userId: string | null = null;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<AddUserModalComponent>,
|
||||
@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');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<h1 mat-dialog-title i18n="@@dialogTitleEditUser">Editar Usuario</h1>
|
||||
<div mat-dialog-content>
|
||||
<mat-dialog-content class="form-container">
|
||||
<form [formGroup]="userForm" class="user-form">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label i18n="@@labelCurrentPassword">Contraseña actual</mat-label>
|
||||
|
@ -14,8 +14,6 @@
|
|||
<input matInput formControlName="repeatNewPassword" type="password">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-spinner *ngIf="loading"></mat-spinner>
|
||||
|
||||
<div class="error-message" *ngIf="passwordMismatch" i18n="@@errorPasswordMismatch">
|
||||
Las contraseñas no coinciden
|
||||
</div>
|
||||
|
@ -24,8 +22,8 @@
|
|||
{{ resetPasswordError }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button (click)="onNoClick()" i18n="@@buttonCancel">Cancelar</button>
|
||||
<button mat-button (click)="onSubmit()" [disabled]="loading" i18n="@@buttonEdit">Editar</button>
|
||||
</div>
|
||||
</mat-dialog-actions>
|
||||
|
|
|
@ -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<EditUserModalComponent>,
|
||||
public dialogRef: MatDialogRef<AddUserModalComponent>,
|
||||
@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');
|
||||
|
|
|
@ -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<any>(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<any> {
|
||||
return this.http.get<any>(`${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<any> {
|
||||
return this.http.get<any>(`${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<any> {
|
||||
return this.http.get<any>(`${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<any> {
|
||||
return this.http.put(`${this.baseUrl}/users/${userId}/reset-password`, userPayload);
|
||||
}
|
||||
}
|
|
@ -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%;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
<h1 mat-dialog-title i18n="@@dialogTitleEditUser">Editar Usuario</h1>
|
||||
<mat-spinner *ngIf="loading" class="loading-container"></mat-spinner>
|
||||
<div *ngIf="!loading" mat-dialog-content>
|
||||
<form [formGroup]="userForm" class="user-form">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label i18n="@@editUserlabelUsername">Nombre de usuario</mat-label>
|
||||
<input matInput formControlName="username">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label i18n="@@editUserlabelPassword">Contraseña</mat-label>
|
||||
<input matInput formControlName="password" type="password">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label i18n="@@labelRole">Rol</mat-label>
|
||||
<mat-select multiple formControlName="userGroups">
|
||||
<mat-option *ngFor="let group of userGroups" [value]="group['@id']">
|
||||
{{ group.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label i18n="@@labelOrgUnit">Unidad organizativa</mat-label>
|
||||
<mat-select multiple formControlName="allowedOrganizationalUnits">
|
||||
<mat-option *ngFor="let unit of organizationalUnits" [value]="unit['@id']">
|
||||
{{unit.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button (click)="onNoClick()" i18n="@@buttonCancel">Cancelar</button>
|
||||
<button mat-button (click)="onSubmit()" i18n="@@buttonEdit">Editar</button>
|
||||
</div>
|
|
@ -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<EditUserModalComponent>;
|
||||
let dialogRefSpy: jasmine.SpyObj<MatDialogRef<EditUserModalComponent>>;
|
||||
let userServiceSpy: jasmine.SpyObj<UserService>;
|
||||
let toastServiceSpy: jasmine.SpyObj<ToastrService>;
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
|
@ -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<void>();
|
||||
userForm: FormGroup;
|
||||
userGroups: any[] = [];
|
||||
organizationalUnits: any[] = [];
|
||||
loading:boolean = false;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<EditUserModalComponent>,
|
||||
@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');
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
<div class="header-container">
|
||||
<h1 i18n="@@headerUserManagement">Gestión de usuarios</h1>
|
||||
<button mat-flat-button color="primary" (click)="addUser()" i18n="@@buttonAddUser">+ Añadir</button>
|
||||
<h2 class="title" i18n="@@adminImagesTitle">Administrar usuarios</h2>
|
||||
<div class="images-button-row">
|
||||
<button mat-flat-button color="primary" (click)="addUser()">Añadir usuarios</button>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
<div class="search-container">
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label i18n="@@searchLabel">Buscar nombre de usuario</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar</mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||
|
||||
|
@ -10,13 +21,20 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions">Acciones</th>
|
||||
<td mat-cell *matCellDef="let user">
|
||||
<button mat-button color="primary" (click)="editUser(user)" i18n="@@buttonEditUser">Editar</button>
|
||||
<button mat-button color="warn" (click)="deleteUser(user)" i18n="@@buttonDeleteUser">Eliminar</button>
|
||||
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions" style="text-align: center;">Acciones</th>
|
||||
<td mat-cell *matCellDef="let user" style="text-align: center;">
|
||||
<button mat-icon-button color="primary" (click)="editUser(user)" i18n="@@editImage"> <mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="warn" (click)="deleteUser(user)" i18n="@@buttonDelete"><mat-icon>delete</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
<div class="paginator-container">
|
||||
<mat-paginator [length]="length"
|
||||
[pageSize]="itemsPerPage"
|
||||
[pageIndex]="page"
|
||||
[pageSizeOptions]="pageSizeOptions"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<any>();
|
||||
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<any>(`${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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<any> {
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/ld+json',
|
||||
});
|
||||
return this.http.post(`${this.apiUrl}/users`, userPayload, { headers });
|
||||
}
|
||||
|
||||
updateUser(userId: number, userPayload: UserPayload): Observable<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
return this.http.get<any>(`${this.apiUrl}/users?page=1&itemsPerPage=30`);
|
||||
}
|
||||
|
||||
getOrganizationalUnits(): Observable<any> {
|
||||
return this.http.get<any>(`${this.apiUrl}/organizational-units?page=1&itemsPerPage=10000`);
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
<p>{{ result.type !== 'client' ? result.type : '' }}</p>
|
||||
<p>{{ result.type === 'client' ? result.ip : '' }}</p>
|
||||
<p>{{ result.type === 'client' ? result.mac : '' }}</p>
|
||||
<p>{{ result.type === 'client' ? result.status : '' }}</p>
|
||||
<p *ngIf="result.type !== 'client'" i18n="@@internalUnits">
|
||||
Unidades internas: {{ result.type !== 'client' ? result.children.length : 0 }}
|
||||
</p>
|
||||
|
|
|
@ -410,4 +410,4 @@ export class AdvancedSearchComponent {
|
|||
const dialogRef = this.dialog.open(AcctionsModalComponent, { data: { selectedElements: this.selectedElements }, width: '700px'});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,13 @@
|
|||
<table mat-table [dataSource]="dataSource">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||
<td mat-cell *matCellDef="let image" >
|
||||
<ng-container >
|
||||
{{ column.cell(image) }}
|
||||
<td mat-cell *matCellDef="let ou" >
|
||||
<ng-container *ngIf="column.columnDef !== 'available'">
|
||||
{{ column.cell(ou) }}
|
||||
</ng-container>
|
||||
<ng-container *ngIf="column.columnDef === 'available'" >
|
||||
<mat-chip *ngIf="ou.available" class="mat-chip-success"><mat-icon style="color:white;">check</mat-icon></mat-chip>
|
||||
<mat-chip *ngIf="!ou.available" class="mat-chip-error"> <mat-icon style="color:white;">close</mat-icon></mat-chip>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -49,10 +49,10 @@
|
|||
<mat-label i18n="@@capacityLabel">Aforo</mat-label>
|
||||
<input matInput formControlName="capacity" type="number">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field class="form-field" appearance="fill">
|
||||
<mat-label>Calendario Asociado</mat-label>
|
||||
<mat-select (selectionChange)="onCalendarChange($event)">
|
||||
<mat-option *ngFor="let calendar of calendars" [value]="calendar.uuid">
|
||||
<mat-select formControlName="remoteCalendar" (selectionChange)="onCalendarChange($event)">
|
||||
<mat-option *ngFor="let calendar of calendars" [value]="calendar['@id']">
|
||||
{{ calendar.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -46,12 +46,10 @@
|
|||
<input matInput formControlName="capacity" type="number">
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Campo nuevo para seleccionar el calendario asociado -->
|
||||
<p>Calendario asociado actual {{currentCalendar.name}}</p>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field class="form-field" appearance="fill">
|
||||
<mat-label>Calendario Asociado</mat-label>
|
||||
<mat-select formControlName="calendarSelect" (selectionChange)="onCalendarChange($event)">
|
||||
<mat-option *ngFor="let calendar of calendars" [value]="calendar.uuid">
|
||||
<mat-select formControlName="remoteCalendar" (selectionChange)="onCalendarChange($event)">
|
||||
<mat-option *ngFor="let calendar of calendars" [value]="calendar['@id']">
|
||||
{{ calendar.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
@ -63,7 +61,7 @@
|
|||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
|
||||
|
||||
<!-- Step 3: Información Adicional -->
|
||||
<mat-step [stepControl]="additionalInfoFormGroup">
|
||||
|
|
|
@ -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<CreateOrganizationalUnitComponent>,
|
||||
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<any>(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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue