Newer
Older
import { Resource } from '@ngxp/rest';
import { isEmpty } from 'lodash-es';
import { BehaviorSubject, Observable, first, map, tap, withLatestFrom } from 'rxjs';
import { EMPTY_STRING, isNotEmpty } from '../tech.util';
import { LinkRelationName, ListItemResource, SearchResourceServiceConfig } from './resource.model';
import { ResourceRepository } from './resource.repository';
import {
ListResource,
StateResource,
createEmptyStateResource,
createStateResource,
} from './resource.util';
/**
* B = Type of baseresource
* T = Type of listresource
* I = Type of items in listresource
*/
export class ResourceSearchService<
B extends Resource,
T extends ListResource,
I extends ListItemResource,
> {
readonly listResource: BehaviorSubject<StateResource<T>> = new BehaviorSubject(
createEmptyStateResource(),
);
readonly searchBy: BehaviorSubject<string> = new BehaviorSubject<string>(EMPTY_STRING);
readonly selectedResource: BehaviorSubject<I> = new BehaviorSubject<I>(null);
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
constructor(
private config: SearchResourceServiceConfig<B>,
private repository: ResourceRepository,
) {}
public getResultList(): Observable<StateResource<T>> {
return this.selectListResource().pipe(
withLatestFrom(this.selectSearchBy(), this.config.baseResource),
tap(([listResource, searchBy, baseResource]) => {
this.handleChanges(listResource, searchBy, baseResource);
}),
map(([listResource]) => listResource),
);
}
private selectListResource(): Observable<StateResource<T>> {
return this.listResource.asObservable();
}
private selectSearchBy(): Observable<string> {
return this.searchBy.asObservable();
}
handleChanges(listResource: StateResource<T>, searchBy: string, baseResource: B): void {
if (listResource.loading) this.doSearch(searchBy, baseResource);
}
doSearch(searchBy: string, baseResource: B): void {
if (isNotEmpty(searchBy)) {
this.dispatchSearch(baseResource, this.config.searchLinkRel, searchBy);
}
if (isEmpty(searchBy)) {
this.dispatchClearSearchList();
}
}
dispatchSearch(baseResource: B, linkRel: LinkRelationName, searchBy: string): void {
this.repository
.search<T>(baseResource, linkRel, searchBy)
.pipe(first())
.subscribe((result: T) => this.dispatchSearchSuccess(result));
}
private dispatchSearchSuccess(result: T): void {
this.listResource.next(createStateResource(result));
}
public clearResultList(): void {
this.dispatchClearSearchList();
}
private dispatchClearSearchList(): void {
this.listResource.next(createEmptyStateResource());
}
public search(searchBy: string): void {
this.dispatchInitSearch(searchBy);
}
private dispatchInitSearch(searchBy: string): void {
this.searchBy.next(searchBy);
this.listResource.next({ ...this.listResource.value, loading: true });
}
public getSelectedResult(): Observable<I> {
return this.selectedResource.asObservable();
}
public selectResult(selected: I): void {
this.selectedResource.next(selected);

OZGCloud
committed
public clearSelectedResult(): void {
this.selectedResource.next(null);
}