fix(avrop): Fixed issue with filtering and paginating. (TV-714)

Squashed commit of the following:

commit 74e3471f042b67308db3a7639cd475c7ae10402b
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Fri Oct 1 09:23:48 2021 +0200

    readded page-check for pagination

commit 99e7e1c2f7a6435a795892242cdb4356e15b3987
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Fri Oct 1 09:09:46 2021 +0200

    Changed params handling inside avrop
This commit is contained in:
Erik Tiekstra
2021-10-01 15:28:53 +02:00
parent 002e26c088
commit 93556d4885
7 changed files with 121 additions and 81 deletions

View File

@@ -1,4 +1,4 @@
<div class="avrop-filters" *ngIf="filtersAreLoading$ | async; else loadingRef"> <div class="avrop-filters" *ngIf="(filtersAreLoading$ | async) === false; else loadingRef">
<div class="avrop-filters__filter-wrapper" *ngIf="availableTjanster$ | async as availableTjanster"> <div class="avrop-filters__filter-wrapper" *ngIf="availableTjanster$ | async as availableTjanster">
<msfa-multiselect <msfa-multiselect
[multiselectTitle]="'Tjänster'" [multiselectTitle]="'Tjänster'"

View File

@@ -24,7 +24,7 @@ export class AvropFiltersComponent {
this.availableKommuner$, this.availableKommuner$,
this.availableTjanster$, this.availableTjanster$,
this.availableUtforandeVerksamheter$, this.availableUtforandeVerksamheter$,
]).pipe(map(([kommuner, tjanster, uv]) => !!(kommuner && tjanster && uv))); ]).pipe(map(([kommuner, tjanster, uv]) => !(kommuner && tjanster && uv)));
constructor(private avropService: AvropService) {} constructor(private avropService: AvropService) {}

View File

@@ -1,5 +1,5 @@
<digi-ng-skeleton-base *ngIf="avropLoading" [afCount]="3" afText="Laddar nya deltagare"></digi-ng-skeleton-base> <div class="avrop-list">
<div *ngIf="availableAvrop?.length" class="avrop-list"> <msfa-loader *ngIf="avropLoading" type="absolute"></msfa-loader>
<ul class="avrop-list__list"> <ul class="avrop-list__list">
<li *ngFor="let avrop of avropRows"> <li *ngFor="let avrop of avropRows">
<msfa-avrop-row <msfa-avrop-row

View File

@@ -1,6 +1,9 @@
@import 'mixins/list'; @import 'mixins/list';
.avrop-list { .avrop-list {
position: relative;
z-index: 0;
&__list { &__list {
@include msfa__reset-list; @include msfa__reset-list;
display: flex; display: flex;

View File

@@ -1,13 +1,14 @@
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base'; import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { LoaderModule } from '@msfa-shared/components/loader/loader.module';
import { AvropRowModule } from '../avrop-row/avrop-row.module'; import { AvropRowModule } from '../avrop-row/avrop-row.module';
import { AvropListComponent } from './avrop-list.component'; import { AvropListComponent } from './avrop-list.component';
@NgModule({ @NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [AvropListComponent], declarations: [AvropListComponent],
imports: [CommonModule, AvropRowModule, DigiNgSkeletonBaseModule], imports: [CommonModule, AvropRowModule, LoaderModule, DigiNgSkeletonBaseModule],
exports: [AvropListComponent], exports: [AvropListComponent],
}) })
export class AvropListModule {} export class AvropListModule {}

View File

@@ -1,5 +1,6 @@
import { SortOrder } from '@msfa-enums/sort-order.enum'; import { SortOrder } from '@msfa-enums/sort-order.enum';
import { DeltagareCompact } from '@msfa-models/deltagare.model'; import { DeltagareCompact } from '@msfa-models/deltagare.model';
import { MultiselectFilterOption } from '@msfa-shared/components/multiselect/multiselect-filter-option';
import { EmployeeCompactResponse } from './employee.response.model'; import { EmployeeCompactResponse } from './employee.response.model';
export interface Params { export interface Params {
@@ -9,16 +10,29 @@ export interface Params {
export interface PaginationParams { export interface PaginationParams {
page: number; page: number;
limit: number; limit: number;
}
export interface SortParams {
sort: string;
order: SortOrder; order: SortOrder;
}
export interface FilterParams {
search?: string; search?: string;
} }
export interface DeltagareParams extends PaginationParams { export interface DeltagareParams extends PaginationParams, SortParams {
sort: keyof DeltagareCompact; sort: keyof DeltagareCompact;
onlyMyDeltagare: boolean; onlyMyDeltagare: boolean;
} }
export interface EmployeeParams extends PaginationParams { export interface EmployeeParams extends PaginationParams, SortParams, FilterParams {
sort: keyof EmployeeCompactResponse; sort: keyof EmployeeCompactResponse;
onlyEmployeesWithoutAuthorization: boolean; onlyEmployeesWithoutAuthorization: boolean;
} }
export interface AvropParams extends PaginationParams {
filteredTjanster: MultiselectFilterOption[];
filteredUtforandeVerksamheter: MultiselectFilterOption[];
filteredKommuner: MultiselectFilterOption[];
}

View File

@@ -1,11 +1,11 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Params } from '@msfa-models/api/params.model'; import { AvropParams, Params } from '@msfa-models/api/params.model';
import { AvropCompact, AvropCompactData } from '@msfa-models/avrop.model'; import { AvropCompact, AvropCompactData } from '@msfa-models/avrop.model';
import { Handledare } from '@msfa-models/handledare.model'; import { Handledare } from '@msfa-models/handledare.model';
import { AvropApiService } from '@msfa-services/api/avrop-api.service'; import { AvropApiService } from '@msfa-services/api/avrop-api.service';
import { MultiselectFilterOption } from '@msfa-shared/components/multiselect/multiselect-filter-option'; import { MultiselectFilterOption } from '@msfa-shared/components/multiselect/multiselect-filter-option';
import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs'; import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
import { filter, map, switchMap, tap } from 'rxjs/operators'; import { distinctUntilChanged, filter, map, shareReplay, switchMap, tap } from 'rxjs/operators';
type Step = 1 | 2 | 3 | 4; type Step = 1 | 2 | 3 | 4;
@@ -13,11 +13,13 @@ type Step = 1 | 2 | 3 | 4;
providedIn: 'root', providedIn: 'root',
}) })
export class AvropService { export class AvropService {
private _limit$ = new BehaviorSubject<number>(5); private _params$ = new BehaviorSubject<AvropParams>({
private _page$ = new BehaviorSubject<number>(1); page: 1,
private _filteredTjanster$ = new BehaviorSubject<MultiselectFilterOption[]>(null); limit: 5,
private _filteredUtforandeVerksamheter$ = new BehaviorSubject<MultiselectFilterOption[]>(null); filteredTjanster: null,
private _filteredKommuner$ = new BehaviorSubject<MultiselectFilterOption[]>(null); filteredUtforandeVerksamheter: null,
filteredKommuner: null,
});
private _selectedAvrop$ = new BehaviorSubject<AvropCompact[]>([]); private _selectedAvrop$ = new BehaviorSubject<AvropCompact[]>([]);
private _avropIsLocked$ = new BehaviorSubject<boolean>(null); private _avropIsLocked$ = new BehaviorSubject<boolean>(null);
private _selectedHandledareId$ = new BehaviorSubject<string>(null); private _selectedHandledareId$ = new BehaviorSubject<string>(null);
@@ -26,12 +28,23 @@ export class AvropService {
private _error$ = new BehaviorSubject<string>(null); private _error$ = new BehaviorSubject<string>(null);
private _avropLoading$ = new BehaviorSubject<boolean>(false); private _avropLoading$ = new BehaviorSubject<boolean>(false);
public avropLoading$: Observable<boolean> = this._avropLoading$.asObservable(); public avropLoading$: Observable<boolean> = this._avropLoading$.asObservable();
public handledareIsConfirmed$: Observable<boolean> = this._handledareIsConfirmed$.asObservable();
public avropIsSubmitted$: Observable<boolean> = this._avropIsSubmitted$.asObservable();
public error$: Observable<string> = this._error$.asObservable();
public showUnauthorizedError$: Observable<boolean> = this.avropApiService.showUnauthorizedError$;
public filteredTjanster$: Observable<MultiselectFilterOption[]> = this._filteredTjanster$.asObservable(); public filteredTjanster$: Observable<MultiselectFilterOption[]> = this._params$.pipe(
public filteredUtforandeVerksamheter$: Observable< map(({ filteredTjanster }) => filteredTjanster),
MultiselectFilterOption[] distinctUntilChanged()
> = this._filteredUtforandeVerksamheter$.asObservable(); );
public filteredKommuner$: Observable<MultiselectFilterOption[]> = this._filteredKommuner$.asObservable(); public filteredUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = this._params$.pipe(
map(({ filteredUtforandeVerksamheter }) => filteredUtforandeVerksamheter),
distinctUntilChanged((prevFilter, currFilter) => JSON.stringify(prevFilter) === JSON.stringify(currFilter))
);
public filteredKommuner$: Observable<MultiselectFilterOption[]> = this._params$.pipe(
map(({ filteredKommuner }) => filteredKommuner),
distinctUntilChanged()
);
public selectedAvrop$: Observable<AvropCompact[]> = this._selectedAvrop$.asObservable(); public selectedAvrop$: Observable<AvropCompact[]> = this._selectedAvrop$.asObservable();
public avropIsLocked$: Observable<boolean> = this._avropIsLocked$.asObservable(); public avropIsLocked$: Observable<boolean> = this._avropIsLocked$.asObservable();
public selectedHandledare$: Observable<Handledare | null> = this._selectedHandledareId$.pipe( public selectedHandledare$: Observable<Handledare | null> = this._selectedHandledareId$.pipe(
@@ -43,21 +56,10 @@ export class AvropService {
: of(null as null) : of(null as null)
) )
); );
public handledareIsConfirmed$: Observable<boolean> = this._handledareIsConfirmed$.asObservable(); public avropData$: Observable<AvropCompactData> = combineLatest([this._avropIsSubmitted$, this._params$]).pipe(
public avropIsSubmitted$: Observable<boolean> = this._avropIsSubmitted$.asObservable();
public error$: Observable<string> = this._error$.asObservable();
public showUnauthorizedError$: Observable<boolean> = this.avropApiService.showUnauthorizedError$;
public avropData$: Observable<AvropCompactData> = combineLatest([
this._filteredTjanster$,
this._filteredUtforandeVerksamheter$,
this._filteredKommuner$,
this._page$,
this._limit$,
this._avropIsSubmitted$,
]).pipe(
switchMap(() => { switchMap(() => {
this._avropLoading$.next(true); this._avropLoading$.next(true);
return this.avropApiService.fetchAvrop$(this.filtersForAvrop).pipe( return this.avropApiService.fetchAvrop$(this._filtersForAvrop).pipe(
tap(() => { tap(() => {
this._avropLoading$.next(false); this._avropLoading$.next(false);
}) })
@@ -65,22 +67,35 @@ export class AvropService {
}) })
); );
public availableTjanster$: Observable<MultiselectFilterOption[]> = combineLatest([ public availableTjanster$: Observable<MultiselectFilterOption[]> = this._params$.pipe(
this._filteredUtforandeVerksamheter$, distinctUntilChanged(
this._filteredKommuner$, (prevParams, currParams) =>
]).pipe(switchMap(() => this.avropApiService.fetchAvailableTjanster$(this.filtersForTjanster))); prevParams.filteredKommuner === currParams.filteredKommuner &&
prevParams.filteredUtforandeVerksamheter === currParams.filteredUtforandeVerksamheter
public availableUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = combineLatest([ ),
this._filteredTjanster$, switchMap(() => this.avropApiService.fetchAvailableTjanster$(this._filtersForTjanster)),
this._filteredKommuner$, shareReplay(1)
]).pipe(
switchMap(() => this.avropApiService.fetchAvailableUtforandeVerksamheter$(this.filtersForUtforandeVerksamheter))
); );
public availableKommuner$: Observable<MultiselectFilterOption[]> = combineLatest([ public availableUtforandeVerksamheter$: Observable<MultiselectFilterOption[]> = this._params$.pipe(
this._filteredTjanster$, distinctUntilChanged(
this._filteredUtforandeVerksamheter$, (prevParams, currParams) =>
]).pipe(switchMap(() => this.avropApiService.fetchAvailableKommuner$(this.filtersForKommuner))); prevParams.filteredKommuner === currParams.filteredKommuner &&
prevParams.filteredTjanster === currParams.filteredTjanster
),
switchMap(() => this.avropApiService.fetchAvailableUtforandeVerksamheter$(this._filtersForUtforandeVerksamheter)),
shareReplay(1)
);
public availableKommuner$: Observable<MultiselectFilterOption[]> = this._params$.pipe(
distinctUntilChanged(
(prevParams, currParams) =>
prevParams.filteredUtforandeVerksamheter === currParams.filteredUtforandeVerksamheter &&
prevParams.filteredTjanster === currParams.filteredTjanster
),
switchMap(() => this.avropApiService.fetchAvailableKommuner$(this._filtersForKommuner)),
shareReplay(1)
);
private _lockedAvrop$: Observable<AvropCompact[]> = combineLatest([this.selectedAvrop$, this.avropIsLocked$]).pipe( private _lockedAvrop$: Observable<AvropCompact[]> = combineLatest([this.selectedAvrop$, this.avropIsLocked$]).pipe(
map(([selectedAvrop, isLocked]) => (isLocked ? selectedAvrop : null)) map(([selectedAvrop, isLocked]) => (isLocked ? selectedAvrop : null))
@@ -97,14 +112,18 @@ export class AvropService {
this._avropIsSubmitted$, this._avropIsSubmitted$,
]).pipe( ]).pipe(
map(([confirmedHandledare, avropIsLocked, avropIsSubmitted]) => map(([confirmedHandledare, avropIsLocked, avropIsSubmitted]) =>
AvropService.calculateStep(confirmedHandledare, avropIsLocked, avropIsSubmitted) AvropService._getCalculatedStep(confirmedHandledare, avropIsLocked, avropIsSubmitted)
), ),
tap(() => { tap(() => {
window.scrollTo(0, 0); window.scrollTo(0, 0);
}) })
); );
private static calculateStep(confirmedHandledare: boolean, avropIsLocked: boolean, avropIsSubmitted: boolean): Step { private static _getCalculatedStep(
confirmedHandledare: boolean,
avropIsLocked: boolean,
avropIsSubmitted: boolean
): Step {
if (avropIsLocked) { if (avropIsLocked) {
if (confirmedHandledare) { if (confirmedHandledare) {
if (avropIsSubmitted) { if (avropIsSubmitted) {
@@ -118,56 +137,56 @@ export class AvropService {
return 1; return 1;
} }
private get tjanstKoder(): { tjanstKoder: string[] } | null { private get _tjanstKoder(): { tjanstKoder: string[] } | null {
return this._filteredTjanster$.value?.length const params = this._params$.getValue();
? { tjanstKoder: this._filteredTjanster$.value.map(tjanst => tjanst.id) } return params.filteredTjanster?.length ? { tjanstKoder: params.filteredTjanster.map(tjanst => tjanst.id) } : null;
: null;
} }
private get kommunKoder(): { kommunKoder: string[] } | null { private get _kommunKoder(): { kommunKoder: string[] } | null {
return this._filteredKommuner$.value?.length const params = this._params$.getValue();
? { kommunKoder: this._filteredKommuner$.value.map(kommun => kommun.id) } return params.filteredKommuner?.length ? { kommunKoder: params.filteredKommuner.map(kommun => kommun.id) } : null;
: null;
} }
private get utforandeverksamhetIds(): { utforandeverksamhetIds: string[] } | null { private get _utforandeverksamhetIds(): { utforandeverksamhetIds: string[] } | null {
return this._filteredUtforandeVerksamheter$.value?.length const params = this._params$.getValue();
return params.filteredUtforandeVerksamheter?.length
? { ? {
utforandeverksamhetIds: this._filteredUtforandeVerksamheter$.value.map( utforandeverksamhetIds: params.filteredUtforandeVerksamheter.map(
utforandeVerksamhet => utforandeVerksamhet.id utforandeVerksamhet => utforandeVerksamhet.id
), ),
} }
: null; : null;
} }
private get filtersForAvrop(): Params { private get _filtersForAvrop(): Params {
const { page, limit } = this._params$.getValue();
return { return {
...this.tjanstKoder, ...this._tjanstKoder,
...this.kommunKoder, ...this._kommunKoder,
...this.utforandeverksamhetIds, ...this._utforandeverksamhetIds,
page: this._page$.value.toString(), page: page.toString(),
limit: this._limit$.value.toString(), limit: limit.toString(),
}; };
} }
private get filtersForTjanster(): Params { private get _filtersForTjanster(): Params {
return { return {
...this.kommunKoder, ...this._kommunKoder,
...this.utforandeverksamhetIds, ...this._utforandeverksamhetIds,
}; };
} }
private get filtersForUtforandeVerksamheter(): Params { private get _filtersForUtforandeVerksamheter(): Params {
return { return {
...this.tjanstKoder, ...this._tjanstKoder,
...this.kommunKoder, ...this._kommunKoder,
}; };
} }
private get filtersForKommuner(): Params { private get _filtersForKommuner(): Params {
return { return {
...this.tjanstKoder, ...this._tjanstKoder,
...this.utforandeverksamhetIds, ...this._utforandeverksamhetIds,
}; };
} }
@@ -232,15 +251,15 @@ export class AvropService {
} }
public setSelectedTjanster(selectedFilterOptions: MultiselectFilterOption[]): void { public setSelectedTjanster(selectedFilterOptions: MultiselectFilterOption[]): void {
this._filteredTjanster$.next(selectedFilterOptions); this._params$.next({ ...this._params$.getValue(), filteredTjanster: selectedFilterOptions, page: 1 });
} }
public setSelectedUtforandeVerksamheter(selectedFilterOptions: MultiselectFilterOption[]): void { public setSelectedUtforandeVerksamheter(selectedFilterOptions: MultiselectFilterOption[]): void {
this._filteredUtforandeVerksamheter$.next(selectedFilterOptions); this._params$.next({ ...this._params$.getValue(), filteredUtforandeVerksamheter: selectedFilterOptions, page: 1 });
} }
public setSelectedKommuner(selectedFilterOptions: MultiselectFilterOption[]): void { public setSelectedKommuner(selectedFilterOptions: MultiselectFilterOption[]): void {
this._filteredKommuner$.next(selectedFilterOptions); this._params$.next({ ...this._params$.getValue(), filteredKommuner: selectedFilterOptions, page: 1 });
} }
public goToStep1(): void { public goToStep1(): void {
@@ -252,22 +271,25 @@ export class AvropService {
} }
public removeKommun(kommunToRemove: MultiselectFilterOption): void { public removeKommun(kommunToRemove: MultiselectFilterOption): void {
this.setSelectedKommuner(this._filteredKommuner$.value.filter(selectedKommun => selectedKommun !== kommunToRemove)); const params = this._params$.getValue();
this.setSelectedKommuner(params.filteredKommuner.filter(selectedKommun => selectedKommun !== kommunToRemove));
} }
public removeUtforandeVerksamhet(utforandeVerksamhetToRemove: MultiselectFilterOption): void { public removeUtforandeVerksamhet(utforandeVerksamhetToRemove: MultiselectFilterOption): void {
const params = this._params$.getValue();
this.setSelectedUtforandeVerksamheter( this.setSelectedUtforandeVerksamheter(
this._filteredUtforandeVerksamheter$.value.filter( params.filteredUtforandeVerksamheter.filter(
selectedUtforandeVerksamhet => selectedUtforandeVerksamhet !== utforandeVerksamhetToRemove selectedUtforandeVerksamhet => selectedUtforandeVerksamhet !== utforandeVerksamhetToRemove
) )
); );
} }
public removeTjanst(tjanstToRemove: MultiselectFilterOption): void { public removeTjanst(tjanstToRemove: MultiselectFilterOption): void {
this.setSelectedTjanster(this._filteredTjanster$.value.filter(selectedTjanst => selectedTjanst !== tjanstToRemove)); const params = this._params$.getValue();
this.setSelectedTjanster(params.filteredTjanster.filter(selectedTjanst => selectedTjanst !== tjanstToRemove));
} }
public setPage(page: number): void { public setPage(page: number): void {
this._page$.next(page); this._params$.next({ ...this._params$.getValue(), page });
} }
} }