Refactor extract component logic from Employee api service
Merge in TEA/mina-sidor-fa-web from Refactor-extract-component-logic-from-Employee-api-service to develop Squashed commit of the following: commit e57ac1b6f34bee042f53f21166feedcef0d72ac2 Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se> Date: Tue Dec 28 14:29:50 2021 +0100 refactor commit e4d9bfd514576f6de8ae7095a0b1e41a096d39c2 Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se> Date: Tue Dec 28 09:02:16 2021 +0100 remove reduntant component commit 2b624a7e99e76e8eece3e59720f2de99f44ec9ba Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se> Date: Mon Dec 27 15:40:27 2021 +0100 rename commit ec87d82063bef38325255e168485962a5d988575 Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se> Date: Mon Dec 27 15:38:35 2021 +0100 refactor: extract component logic from Employee-api-service
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AdministrationComponent } from './administration.component';
|
||||
|
||||
describe('AdministrationComponent', () => {
|
||||
let component: AdministrationComponent;
|
||||
let fixture: ComponentFixture<AdministrationComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
void TestBed.configureTestingModule({
|
||||
declarations: [AdministrationComponent],
|
||||
imports: [RouterTestingModule],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AdministrationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'msfa-administration',
|
||||
templateUrl: './administration.component.html',
|
||||
styleUrls: ['./administration.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AdministrationComponent {}
|
||||
@@ -1,10 +1,9 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { AdministrationRoutingModule } from './administration-routing.module';
|
||||
import { AdministrationComponent } from './administration.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AdministrationComponent],
|
||||
declarations: [],
|
||||
imports: [CommonModule, AdministrationRoutingModule],
|
||||
})
|
||||
export class AdministrationModule {}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive';
|
||||
import { SortOrder } from '@msfa-enums/sort-order.enum';
|
||||
import { EmployeeEditRequest } from '@msfa-models/api/employee-edit.request.model';
|
||||
import { EmployeeInviteResponse } from '@msfa-models/api/employee-invite.response.model';
|
||||
import { EmployeeCompactResponse } from '@msfa-models/api/employee.response.model';
|
||||
import { EmployeeParams } from '@msfa-models/api/params.model';
|
||||
import { Employee, EmployeesData } from '@msfa-models/employee.model';
|
||||
import { Sort } from '@msfa-models/sort.model';
|
||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { EmployeeApiService } from '@msfa-services/api/employee.api.service';
|
||||
|
||||
const DEFAULT_PARAMS: EmployeeParams = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
sort: 'name',
|
||||
order: SortOrder.ASC,
|
||||
search: '',
|
||||
onlyEmployeesWithoutAuthorization: false,
|
||||
};
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AdministrationService extends UnsubscribeDirective {
|
||||
private _currentEmployeeId$ = new BehaviorSubject<string>(null);
|
||||
private _params$ = new BehaviorSubject<EmployeeParams>(DEFAULT_PARAMS);
|
||||
sort$: Observable<Sort<keyof EmployeeCompactResponse>> = this._params$.pipe(
|
||||
map(({ sort, order }) => ({ key: sort, order }))
|
||||
);
|
||||
onlyEmployeesWithoutAuthorization$: Observable<boolean> = this._params$.pipe(
|
||||
map(({ onlyEmployeesWithoutAuthorization }) => onlyEmployeesWithoutAuthorization)
|
||||
);
|
||||
private _employee$ = new BehaviorSubject<Employee>(null);
|
||||
employee$: Observable<Employee> = this._employee$.asObservable();
|
||||
private _lastUpdatedEmployeeId$ = new BehaviorSubject<string>(null);
|
||||
lastUpdatedEmployeeId$: Observable<string> = this._lastUpdatedEmployeeId$.asObservable();
|
||||
private _lastDeletedEmployee$ = new BehaviorSubject<Employee>(null);
|
||||
lastDeletedEmployee$: Observable<Employee> = this._lastDeletedEmployee$.asObservable();
|
||||
private _employeeToDelete$ = new BehaviorSubject<Employee>(null);
|
||||
employeeToDelete$: Observable<Employee> = this._employeeToDelete$.asObservable();
|
||||
private _employeesLoading$ = new BehaviorSubject<boolean>(false);
|
||||
employeesLoading$: Observable<boolean> = this._employeesLoading$.asObservable();
|
||||
|
||||
constructor(private employeeApiService: EmployeeApiService) {
|
||||
super();
|
||||
super.unsubscribeOnDestroy(
|
||||
combineLatest([this._currentEmployeeId$, this._lastUpdatedEmployeeId$])
|
||||
.pipe(
|
||||
distinctUntilChanged(
|
||||
([prevEmployeeId], [currEmployeeId, currLastUpdatedEmployeeId]) =>
|
||||
!currLastUpdatedEmployeeId && prevEmployeeId === currEmployeeId
|
||||
),
|
||||
filter(([currentEmployeeId]) => !!currentEmployeeId),
|
||||
switchMap(([currentEmployeeId]) =>
|
||||
this._fetchEmployee$(currentEmployeeId).pipe(filter(employee => !!employee))
|
||||
)
|
||||
)
|
||||
.subscribe(employee => {
|
||||
this._employee$.next(employee);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
employeesData$: Observable<EmployeesData> = combineLatest([this._params$, this._lastDeletedEmployee$]).pipe(
|
||||
switchMap(([params]) => this._fetchEmployees$(params))
|
||||
);
|
||||
|
||||
resetParams(): void {
|
||||
this._params$.next(DEFAULT_PARAMS);
|
||||
}
|
||||
|
||||
setCurrentEmployeeId(currentEmployeeId: string): void {
|
||||
if (this._currentEmployeeId$.getValue() !== currentEmployeeId) {
|
||||
this._employee$.next(null);
|
||||
this._currentEmployeeId$.next(currentEmployeeId);
|
||||
}
|
||||
}
|
||||
|
||||
resetLastUpdatedEmployeeId(): void {
|
||||
this._lastUpdatedEmployeeId$.next(null);
|
||||
}
|
||||
|
||||
private _fetchEmployees$(employeeParams: EmployeeParams): Observable<EmployeesData> {
|
||||
this._employeesLoading$.next(true);
|
||||
|
||||
return this.employeeApiService.fetchEmployees$(employeeParams).pipe(tap(() => this._employeesLoading$.next(false)));
|
||||
}
|
||||
|
||||
private _fetchEmployee$(ciamUserId: string): Observable<Employee> {
|
||||
return this.employeeApiService.fetchEmployee$(ciamUserId);
|
||||
}
|
||||
|
||||
setSearchString(value: string): void {
|
||||
this._params$.next({
|
||||
...this._params$.getValue(),
|
||||
search: value,
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
|
||||
setOnlyEmployeesWithoutAuthorization(value: boolean): void {
|
||||
this._params$.next({
|
||||
...this._params$.getValue(),
|
||||
onlyEmployeesWithoutAuthorization: value,
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
|
||||
setEmployeeToDelete(employee: Employee): void {
|
||||
this._employeeToDelete$.next(employee);
|
||||
}
|
||||
|
||||
deleteEmployee(employee: Employee): Observable<Employee> {
|
||||
return this.employeeApiService.deleteEmployee(employee).pipe(
|
||||
tap(() => {
|
||||
this._lastDeletedEmployee$.next(employee);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
setSort(sort: keyof EmployeeCompactResponse): void {
|
||||
const params = this._params$.getValue();
|
||||
const order = params.sort === sort && params.order === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
||||
|
||||
this._params$.next({ ...params, sort, order });
|
||||
}
|
||||
|
||||
setPage(page: number): void {
|
||||
this._params$.next({ ...this._params$.getValue(), page });
|
||||
}
|
||||
|
||||
postEmployeeInvitation$(emails: string[]): Observable<EmployeeInviteResponse | null> {
|
||||
return this.employeeApiService.postEmployeeInvitation(emails);
|
||||
}
|
||||
|
||||
updateEmployee$(ciamUserId: string, data: EmployeeEditRequest): Observable<boolean> {
|
||||
return this.employeeApiService.updateEmployee$(ciamUserId, data);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Employee } from '@msfa-models/employee.model';
|
||||
import { CustomError } from '@msfa-models/error/custom-error';
|
||||
import { EmployeeService } from '@msfa-services/api/employee.service';
|
||||
import { AdministrationService } from '../../administration.service';
|
||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@@ -21,8 +21,8 @@ export class EmployeeDeleteComponent {
|
||||
@Input() returnToEmployeeList = false;
|
||||
|
||||
deleteEmployeeData$: Observable<DeleteEmployeeData> = combineLatest([
|
||||
this.employeeService.employeeToDelete$,
|
||||
this.employeeService.lastDeletedEmployee$,
|
||||
this.administrationService.employeeToDelete$,
|
||||
this.administrationService.lastDeletedEmployee$,
|
||||
]).pipe(
|
||||
map(([employeeToDelete, lastDeletedEmployee]) => {
|
||||
return {
|
||||
@@ -42,7 +42,7 @@ export class EmployeeDeleteComponent {
|
||||
return lastDeleted ? null : 'Avbryt';
|
||||
}
|
||||
|
||||
constructor(private employeeService: EmployeeService, private router: Router) {}
|
||||
constructor(private administrationService: AdministrationService, private router: Router) {}
|
||||
|
||||
deleteEmployeeModelPrimaryClick(deleteEmployeeData: DeleteEmployeeData): void {
|
||||
const { lastDeleted, toDelete } = deleteEmployeeData;
|
||||
@@ -54,7 +54,7 @@ export class EmployeeDeleteComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
const deleteEmployeeSubscription = this.employeeService.deleteEmployee(toDelete).subscribe({
|
||||
const deleteEmployeeSubscription = this.administrationService.deleteEmployee(toDelete).subscribe({
|
||||
error: (error: CustomError) => {
|
||||
this._errorDuringDeletion$.next(error);
|
||||
},
|
||||
@@ -65,7 +65,7 @@ export class EmployeeDeleteComponent {
|
||||
}
|
||||
|
||||
closeDeleteEmployeeModal(): void {
|
||||
this.employeeService.setEmployeeToDelete(null);
|
||||
this.administrationService.setEmployeeToDelete(null);
|
||||
this._errorDuringDeletion$.next(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Employee } from '@msfa-models/employee.model';
|
||||
import { Role } from '@msfa-models/role.model';
|
||||
import { EmployeeService } from '@msfa-services/api/employee.service';
|
||||
import { AdministrationService } from '../../administration.service';
|
||||
import { RoleService } from '@msfa-services/role.service';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
|
||||
@@ -14,22 +14,22 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
||||
})
|
||||
export class EmployeeCardComponent implements OnDestroy {
|
||||
private _employeeId$ = new BehaviorSubject<string>(this.activatedRoute.snapshot.params['employeeId']);
|
||||
employee$: Observable<Employee> = this.employeeService.employee$;
|
||||
lastUpdatedEmployeeId$: Observable<string> = this.employeeService.lastUpdatedEmployeeId$;
|
||||
employee$: Observable<Employee> = this.administrationService.employee$;
|
||||
lastUpdatedEmployeeId$: Observable<string> = this.administrationService.lastUpdatedEmployeeId$;
|
||||
allRoles: Role[] = this.roleService.allRoles;
|
||||
accordionsExpanded = [];
|
||||
|
||||
constructor(
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private employeeService: EmployeeService,
|
||||
private administrationService: AdministrationService,
|
||||
private roleService: RoleService
|
||||
) {
|
||||
this.employeeService.setCurrentEmployeeId(this.employeeId);
|
||||
this.administrationService.setCurrentEmployeeId(this.employeeId);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.employeeService.resetLastUpdatedEmployeeId();
|
||||
this.employeeService.setCurrentEmployeeId(null);
|
||||
this.administrationService.resetLastUpdatedEmployeeId();
|
||||
this.administrationService.setCurrentEmployeeId(null);
|
||||
}
|
||||
|
||||
get employeeId(): string {
|
||||
@@ -41,7 +41,7 @@ export class EmployeeCardComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
closeUpdatedNotificationAlert(): void {
|
||||
this.employeeService.resetLastUpdatedEmployeeId();
|
||||
this.administrationService.resetLastUpdatedEmployeeId();
|
||||
}
|
||||
|
||||
toggleAccordionExpanded(currentId: number): void {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { CustomError } from '@msfa-models/error/custom-error';
|
||||
import { Role } from '@msfa-models/role.model';
|
||||
import { Tjanst } from '@msfa-models/tjanst.model';
|
||||
import { UtforandeVerksamhet } from '@msfa-models/utforande-verksamhet.model';
|
||||
import { EmployeeService } from '@msfa-services/api/employee.service';
|
||||
import { AdministrationService } from '../../administration.service';
|
||||
import { RoleService } from '@msfa-services/role.service';
|
||||
import { UtforandeVerksamheterService } from '@msfa-services/utforande-verksamheter/utforande-verksamheter.service';
|
||||
import { BehaviorSubject, Observable, of } from 'rxjs';
|
||||
@@ -29,14 +29,14 @@ export class EmployeeFormComponent implements OnInit {
|
||||
);
|
||||
|
||||
errorWhileUpdating$: Observable<CustomError> = this._errorWhileUpdating$.asObservable();
|
||||
employee$ = this.employeeService.employee$;
|
||||
employee$ = this.administrationService.employee$;
|
||||
tjanster$: Observable<Tjanst[]> = this.employeeFormService.fetchTjanster$();
|
||||
availableRoles: Role[] = this.roleService.allRoles;
|
||||
|
||||
isLoadingUtforandeVerksamheter$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private employeeService: EmployeeService,
|
||||
private administrationService: AdministrationService,
|
||||
private roleService: RoleService,
|
||||
private employeeFormService: EmployeeFormService,
|
||||
private utforandeVerksamheterService: UtforandeVerksamheterService,
|
||||
@@ -49,11 +49,11 @@ export class EmployeeFormComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.employeeService.setCurrentEmployeeId(this.employeeId);
|
||||
this.administrationService.setCurrentEmployeeId(this.employeeId);
|
||||
}
|
||||
|
||||
updateEmployee(employeeFormData: EmployeeEditRequest): void {
|
||||
const updateEmployeeSubscription = this.employeeService
|
||||
const updateEmployeeSubscription = this.administrationService
|
||||
.updateEmployee$(this.employeeId, employeeFormData)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
@@ -78,7 +78,7 @@ export class EmployeeFormComponent implements OnInit {
|
||||
);
|
||||
}
|
||||
setEmployeeToDelete(employee: Employee): void {
|
||||
this.employeeService.setEmployeeToDelete(employee);
|
||||
this.administrationService.setEmployeeToDelete(employee);
|
||||
}
|
||||
|
||||
closeError(): void {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
|
||||
import { EmployeeInviteResponse } from '@msfa-models/api/employee-invite.response.model';
|
||||
import { CustomError } from '@msfa-models/error/custom-error';
|
||||
import { EmployeeService } from '@msfa-services/api/employee.service';
|
||||
import { AdministrationService } from '../../administration.service';
|
||||
import { CommaSeparatedEmailValidator } from '@msfa-utils/validators/email.validator';
|
||||
import { RequiredValidator } from '@msfa-utils/validators/required.validator';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
@@ -21,7 +21,7 @@ export class EmployeeInviteComponent {
|
||||
lastInvites$: Observable<EmployeeInviteResponse> = this._lastInvites$.asObservable();
|
||||
submitIsLoading$ = new BehaviorSubject<boolean>(false);
|
||||
|
||||
constructor(private employeeService: EmployeeService) {}
|
||||
constructor(private administrationService: AdministrationService) {}
|
||||
|
||||
get emailsControl(): AbstractControl {
|
||||
return this.formGroup.get('emails');
|
||||
@@ -93,7 +93,7 @@ export class EmployeeInviteComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
const post = this.employeeService.postEmployeeInvitation(this.emailsControlValueAsArray).subscribe({
|
||||
const post = this.administrationService.postEmployeeInvitation$(this.emailsControlValueAsArray).subscribe({
|
||||
next: data => {
|
||||
this.submitIsLoading$.next(false);
|
||||
this._lastInvites$.next(data);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { UiIconType } from '@ui/icon/icon-type.enum';
|
||||
import { EmployeeCompactResponse } from '@msfa-models/api/employee.response.model';
|
||||
import { Employee, EmployeesData } from '@msfa-models/employee.model';
|
||||
import { Sort } from '@msfa-models/sort.model';
|
||||
import { EmployeeService } from '@msfa-services/api/employee.service';
|
||||
import { AdministrationService } from '../../administration.service';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { UiLinkButtonType } from '@ui/link-button/link-button-type.enum';
|
||||
|
||||
@@ -16,16 +16,17 @@ import { UiLinkButtonType } from '@ui/link-button/link-button-type.enum';
|
||||
export class EmployeesComponent implements OnDestroy {
|
||||
UiLinkButtonType = UiLinkButtonType;
|
||||
private _searchValue$ = new BehaviorSubject<string>('');
|
||||
onlyEmployeesWithoutAuthorization$: Observable<boolean> = this.employeeService.onlyEmployeesWithoutAuthorization$;
|
||||
employeesData$: Observable<EmployeesData> = this.employeeService.employeesData$;
|
||||
employeesLoading$: Observable<boolean> = this.employeeService.employeesLoading$;
|
||||
sort$: Observable<Sort<keyof EmployeeCompactResponse>> = this.employeeService.sort$;
|
||||
onlyEmployeesWithoutAuthorization$: Observable<boolean> = this.administrationService
|
||||
.onlyEmployeesWithoutAuthorization$;
|
||||
employeesData$: Observable<EmployeesData> = this.administrationService.employeesData$;
|
||||
employeesLoading$: Observable<boolean> = this.administrationService.employeesLoading$;
|
||||
sort$: Observable<Sort<keyof EmployeeCompactResponse>> = this.administrationService.sort$;
|
||||
iconType = UiIconType;
|
||||
|
||||
constructor(private employeeService: EmployeeService) {}
|
||||
constructor(private administrationService: AdministrationService) {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.employeeService.resetParams();
|
||||
this.administrationService.resetParams();
|
||||
}
|
||||
|
||||
get searchValue(): string {
|
||||
@@ -33,7 +34,7 @@ export class EmployeesComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
setSearchString(): void {
|
||||
this.employeeService.setSearchString(this.searchValue);
|
||||
this.administrationService.setSearchString(this.searchValue);
|
||||
}
|
||||
|
||||
setSearchValue($event: CustomEvent<{ target: { value: string } }>): void {
|
||||
@@ -41,18 +42,18 @@ export class EmployeesComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
handleEmployeesSort(key: keyof EmployeeCompactResponse): void {
|
||||
this.employeeService.setSort(key);
|
||||
this.administrationService.setSort(key);
|
||||
}
|
||||
|
||||
setNewPage(page: number): void {
|
||||
this.employeeService.setPage(page);
|
||||
this.administrationService.setPage(page);
|
||||
}
|
||||
|
||||
setOnlyEmployeesWithoutAuthorization(checked: boolean): void {
|
||||
this.employeeService.setOnlyEmployeesWithoutAuthorization(checked);
|
||||
this.administrationService.setOnlyEmployeesWithoutAuthorization(checked);
|
||||
}
|
||||
|
||||
setEmployeeToDelete(employee: Employee): void {
|
||||
this.employeeService.setEmployeeToDelete(employee);
|
||||
this.administrationService.setEmployeeToDelete(employee);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { environment } from '@msfa-environment';
|
||||
import { EmployeeParams, Params } from '@msfa-models/api/params.model';
|
||||
import { EmployeeResponse, EmployeesDataResponse } from '@msfa-models/api/employee.response.model';
|
||||
import { catchError, map, mapTo, take } from 'rxjs/operators';
|
||||
import {
|
||||
Employee,
|
||||
EmployeeCompact,
|
||||
mapResponseToEmployee,
|
||||
mapResponseToEmployeeCompact,
|
||||
} from '@msfa-models/employee.model';
|
||||
import { CustomError } from '@msfa-models/error/custom-error';
|
||||
import { Observable } from 'rxjs';
|
||||
import { PaginationMeta } from '@msfa-models/pagination-meta.model';
|
||||
import { EmployeeInviteResponse } from '@msfa-models/api/employee-invite.response.model';
|
||||
import { EmployeeEditRequest } from '@msfa-models/api/employee-edit.request.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class EmployeeApiService {
|
||||
private _apiBaseUrl = `${environment.api.url}/users`;
|
||||
constructor(private httpClient: HttpClient) {}
|
||||
|
||||
fetchEmployees$(employeeParams: EmployeeParams): Observable<{ data: EmployeeCompact[]; meta: PaginationMeta }> {
|
||||
const { sort, order, limit, page, search, onlyEmployeesWithoutAuthorization } = employeeParams;
|
||||
const params: Params = {
|
||||
sort,
|
||||
order,
|
||||
limit: limit.toString(),
|
||||
page: page.toString(),
|
||||
};
|
||||
if (search) {
|
||||
params.search = search;
|
||||
}
|
||||
|
||||
if (onlyEmployeesWithoutAuthorization) {
|
||||
params.onlyEmployeesWithoutAuthorization = onlyEmployeesWithoutAuthorization.toString();
|
||||
}
|
||||
|
||||
return this.httpClient
|
||||
.get<EmployeesDataResponse>(this._apiBaseUrl, { params })
|
||||
.pipe(
|
||||
map(({ data, meta }) => {
|
||||
return { data: data.map(employee => mapResponseToEmployeeCompact(employee)), meta };
|
||||
}),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte hämta personal.\n\n${error.message}`,
|
||||
name: `GET ${this._apiBaseUrl}`,
|
||||
method: 'EmployeeApiService._fetchEmployees$',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
fetchEmployee$(ciamUserId: string): Observable<Employee> {
|
||||
const apiUrl = `${this._apiBaseUrl}/${ciamUserId}`;
|
||||
return this.httpClient.get<{ data: EmployeeResponse }>(apiUrl).pipe(
|
||||
map(({ data }) => mapResponseToEmployee(data)),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte hämta personal.\n\n${error.message}`,
|
||||
name: `GET ${this._apiBaseUrl}/{ciamUserId}`,
|
||||
data: { ciamUserId },
|
||||
method: 'EmployeeApiService._fetchEmployee$',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
deleteEmployee(employee: Employee): Observable<Employee> {
|
||||
return this.httpClient.delete<void>(`${this._apiBaseUrl}/${employee.id}`).pipe(
|
||||
map(() => employee),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte ta bort personal.\n\n${error.message}`,
|
||||
name: `DELETE ${this._apiBaseUrl}/{ciamUserId}`,
|
||||
method: 'EmployeeApiService.deleteEmployee',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
postEmployeeInvitation(emails: string[]): Observable<EmployeeInviteResponse | null> {
|
||||
const apiUrl = `${this._apiBaseUrl}/invite`;
|
||||
return this.httpClient
|
||||
.patch<{ data: EmployeeInviteResponse }>(apiUrl, { emails })
|
||||
.pipe(
|
||||
take(1),
|
||||
map(({ data }) => data),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte bjuda in personal.\n\n${error.message}`,
|
||||
name: `PATCH ${apiUrl}`,
|
||||
data: { emails },
|
||||
method: 'EmployeeApiService.postEmployeeInvitation',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
updateEmployee$(ciamUserId: string, data: EmployeeEditRequest): Observable<boolean> {
|
||||
return this.httpClient.put<boolean>(`${this._apiBaseUrl}/${ciamUserId}`, data).pipe(
|
||||
mapTo(true),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte redigera personal.\n\n${error.message}`,
|
||||
name: `PATCH ${this._apiBaseUrl}/{ciamUserId}`,
|
||||
data: { ciamUserId },
|
||||
method: 'EmployeeApiService.updateEmployee$',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive';
|
||||
import { SortOrder } from '@msfa-enums/sort-order.enum';
|
||||
import { environment } from '@msfa-environment';
|
||||
import { EmployeeEditRequest } from '@msfa-models/api/employee-edit.request.model';
|
||||
import { EmployeeInviteResponse } from '@msfa-models/api/employee-invite.response.model';
|
||||
import {
|
||||
EmployeeCompactResponse,
|
||||
EmployeeResponse,
|
||||
EmployeesDataResponse,
|
||||
} from '@msfa-models/api/employee.response.model';
|
||||
import { EmployeeParams, Params } from '@msfa-models/api/params.model';
|
||||
import {
|
||||
Employee,
|
||||
EmployeesData,
|
||||
mapResponseToEmployee,
|
||||
mapResponseToEmployeeCompact,
|
||||
} from '@msfa-models/employee.model';
|
||||
import { CustomError } from '@msfa-models/error/custom-error';
|
||||
import { Sort } from '@msfa-models/sort.model';
|
||||
import { ErrorService } from '@msfa-services/error.service';
|
||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||
import { catchError, distinctUntilChanged, filter, map, switchMap, take, tap } from 'rxjs/operators';
|
||||
|
||||
const DEFAULT_PARAMS: EmployeeParams = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
sort: 'name',
|
||||
order: SortOrder.ASC,
|
||||
search: '',
|
||||
onlyEmployeesWithoutAuthorization: false,
|
||||
};
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class EmployeeService extends UnsubscribeDirective {
|
||||
private _apiBaseUrl = `${environment.api.url}/users`;
|
||||
private _currentEmployeeId$ = new BehaviorSubject<string>(null);
|
||||
private _params$ = new BehaviorSubject<EmployeeParams>(DEFAULT_PARAMS);
|
||||
public sort$: Observable<Sort<keyof EmployeeCompactResponse>> = this._params$.pipe(
|
||||
map(({ sort, order }) => ({ key: sort, order }))
|
||||
);
|
||||
public onlyEmployeesWithoutAuthorization$: Observable<boolean> = this._params$.pipe(
|
||||
map(({ onlyEmployeesWithoutAuthorization }) => onlyEmployeesWithoutAuthorization)
|
||||
);
|
||||
private _employee$ = new BehaviorSubject<Employee>(null);
|
||||
public employee$: Observable<Employee> = this._employee$.asObservable();
|
||||
private _lastUpdatedEmployeeId$ = new BehaviorSubject<string>(null);
|
||||
public lastUpdatedEmployeeId$: Observable<string> = this._lastUpdatedEmployeeId$.asObservable();
|
||||
private _lastDeletedEmployee$ = new BehaviorSubject<Employee>(null);
|
||||
public lastDeletedEmployee$: Observable<Employee> = this._lastDeletedEmployee$.asObservable();
|
||||
private _employeeToDelete$ = new BehaviorSubject<Employee>(null);
|
||||
public employeeToDelete$: Observable<Employee> = this._employeeToDelete$.asObservable();
|
||||
private _employeesLoading$ = new BehaviorSubject<boolean>(false);
|
||||
public employeesLoading$: Observable<boolean> = this._employeesLoading$.asObservable();
|
||||
|
||||
constructor(private httpClient: HttpClient, private errorService: ErrorService) {
|
||||
super();
|
||||
super.unsubscribeOnDestroy(
|
||||
combineLatest([this._currentEmployeeId$, this._lastUpdatedEmployeeId$])
|
||||
.pipe(
|
||||
distinctUntilChanged(
|
||||
([prevEmployeeId], [currEmployeeId, currLastUpdatedEmployeeId]) =>
|
||||
!currLastUpdatedEmployeeId && prevEmployeeId === currEmployeeId
|
||||
),
|
||||
filter(([currentEmployeeId]) => !!currentEmployeeId),
|
||||
switchMap(([currentEmployeeId]) =>
|
||||
this._fetchEmployee$(currentEmployeeId).pipe(filter(employee => !!employee))
|
||||
)
|
||||
)
|
||||
.subscribe(employee => {
|
||||
this._employee$.next(employee);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public employeesData$: Observable<EmployeesData> = combineLatest([this._params$, this._lastDeletedEmployee$]).pipe(
|
||||
switchMap(([params]) => this._fetchEmployees$(params))
|
||||
);
|
||||
|
||||
public resetParams(): void {
|
||||
this._params$.next(DEFAULT_PARAMS);
|
||||
}
|
||||
|
||||
public setCurrentEmployeeId(currentEmployeeId: string): void {
|
||||
if (this._currentEmployeeId$.getValue() !== currentEmployeeId) {
|
||||
this._employee$.next(null);
|
||||
this._currentEmployeeId$.next(currentEmployeeId);
|
||||
}
|
||||
}
|
||||
|
||||
public resetLastUpdatedEmployeeId(): void {
|
||||
this._lastUpdatedEmployeeId$.next(null);
|
||||
}
|
||||
|
||||
private _fetchEmployees$(employeeParams: EmployeeParams): Observable<EmployeesData> {
|
||||
const { sort, order, limit, page, search, onlyEmployeesWithoutAuthorization } = employeeParams;
|
||||
const params: Params = {
|
||||
sort,
|
||||
order,
|
||||
limit: limit.toString(),
|
||||
page: page.toString(),
|
||||
};
|
||||
|
||||
if (search) {
|
||||
params.search = search;
|
||||
}
|
||||
|
||||
if (onlyEmployeesWithoutAuthorization) {
|
||||
params.onlyEmployeesWithoutAuthorization = onlyEmployeesWithoutAuthorization.toString();
|
||||
}
|
||||
this._employeesLoading$.next(true);
|
||||
|
||||
return this.httpClient
|
||||
.get<EmployeesDataResponse>(this._apiBaseUrl, { params })
|
||||
.pipe(
|
||||
map(({ data, meta }) => {
|
||||
this._employeesLoading$.next(false);
|
||||
return { data: data.map(employee => mapResponseToEmployeeCompact(employee)), meta };
|
||||
}),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte hämta personal.\n\n${error.message}`,
|
||||
name: `GET ${this._apiBaseUrl}`,
|
||||
method: 'EmployeeService._fetchEmployees$',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private _fetchEmployee$(ciamUserId: string): Observable<Employee> {
|
||||
const apiUrl = `${this._apiBaseUrl}/${ciamUserId}`;
|
||||
return this.httpClient.get<{ data: EmployeeResponse }>(apiUrl).pipe(
|
||||
map(({ data }) => mapResponseToEmployee(data)),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte hämta personal.\n\n${error.message}`,
|
||||
name: `GET ${this._apiBaseUrl}/{ciamUserId}`,
|
||||
data: { ciamUserId },
|
||||
method: 'EmployeeService._fetchEmployee$',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public setSearchString(value: string): void {
|
||||
this._params$.next({
|
||||
...this._params$.getValue(),
|
||||
search: value,
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
|
||||
public setOnlyEmployeesWithoutAuthorization(value: boolean): void {
|
||||
this._params$.next({
|
||||
...this._params$.getValue(),
|
||||
onlyEmployeesWithoutAuthorization: value,
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
|
||||
public setEmployeeToDelete(employee: Employee): void {
|
||||
this._employeeToDelete$.next(employee);
|
||||
}
|
||||
|
||||
public deleteEmployee(employee: Employee): Observable<Employee> {
|
||||
return this.httpClient.delete<void>(`${this._apiBaseUrl}/${employee.id}`).pipe(
|
||||
tap(() => {
|
||||
this._lastDeletedEmployee$.next(employee);
|
||||
}),
|
||||
map(() => employee),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte ta bort personal.\n\n${error.message}`,
|
||||
name: `DELETE ${this._apiBaseUrl}/{ciamUserId}`,
|
||||
method: 'EmployeeService.deleteEmployee',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public setSort(sort: keyof EmployeeCompactResponse): void {
|
||||
const params = this._params$.getValue();
|
||||
const order = params.sort === sort && params.order === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
||||
|
||||
this._params$.next({ ...params, sort, order });
|
||||
}
|
||||
|
||||
public setPage(page: number): void {
|
||||
this._params$.next({ ...this._params$.getValue(), page });
|
||||
}
|
||||
|
||||
public postEmployeeInvitation(emails: string[]): Observable<EmployeeInviteResponse | null> {
|
||||
const apiUrl = `${this._apiBaseUrl}/invite`;
|
||||
return this.httpClient
|
||||
.patch<{ data: EmployeeInviteResponse }>(apiUrl, { emails })
|
||||
.pipe(
|
||||
take(1),
|
||||
map(({ data }) => data),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte bjuda in personal.\n\n${error.message}`,
|
||||
name: `PATCH ${apiUrl}`,
|
||||
data: { emails },
|
||||
method: 'EmployeeService.postEmployeeInvitation',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public updateEmployee$(ciamUserId: string, data: EmployeeEditRequest): Observable<boolean> {
|
||||
return this.httpClient.put<boolean>(`${this._apiBaseUrl}/${ciamUserId}`, data).pipe(
|
||||
take(1),
|
||||
tap(() => {
|
||||
this._employee$.next(null);
|
||||
this._lastUpdatedEmployeeId$.next(ciamUserId);
|
||||
}),
|
||||
map(() => true),
|
||||
catchError((error: Error) => {
|
||||
throw new CustomError({
|
||||
error,
|
||||
message: `Kunde inte redigera personal.\n\n${error.message}`,
|
||||
name: `PATCH ${this._apiBaseUrl}/{ciamUserId}`,
|
||||
data: { ciamUserId },
|
||||
method: 'EmployeeService.updateEmployee$',
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user