|
|
|
@ -1,27 +1,40 @@
|
|
|
|
|
import { Injectable } from '@angular/core';
|
|
|
|
|
import { HttpRequest } from '@angular/common/http';
|
|
|
|
|
import { InternalStore } from '../utils/internal-store-utils';
|
|
|
|
|
import { getPathName } from '../utils/http-utils';
|
|
|
|
|
import { debounceTime, tap } from 'rxjs/operators';
|
|
|
|
|
|
|
|
|
|
export interface HttpWaitState {
|
|
|
|
|
requests: Set<HttpRequest<any>>;
|
|
|
|
|
filteredRequests: Array<HttpRequestInfo>;
|
|
|
|
|
delay: number;
|
|
|
|
|
}
|
|
|
|
|
export interface HttpRequestInfo {
|
|
|
|
|
method: string;
|
|
|
|
|
endpoint: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Injectable({
|
|
|
|
|
providedIn: 'root',
|
|
|
|
|
})
|
|
|
|
|
export class HttpWaitService {
|
|
|
|
|
protected store = new InternalStore<HttpWaitState>({ requests: new Set() });
|
|
|
|
|
protected store = new InternalStore<HttpWaitState>({
|
|
|
|
|
requests: new Set(),
|
|
|
|
|
filteredRequests: [],
|
|
|
|
|
delay: 0,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
getLoading() {
|
|
|
|
|
return !!this.store.state.requests.size;
|
|
|
|
|
return !!this.applyFilter(this.store.state.requests).length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getLoading$() {
|
|
|
|
|
return this.store.sliceState(({ requests }) => !!requests.size);
|
|
|
|
|
return this.store
|
|
|
|
|
.sliceState(({ requests }) => !!this.applyFilter(requests).length)
|
|
|
|
|
.pipe(this.debounceWhenLoading());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateLoading$() {
|
|
|
|
|
return this.store.sliceUpdate(({ requests }) => !!requests.size);
|
|
|
|
|
return this.store.sliceUpdate(({ requests }) => !!this.applyFilter(requests).length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clearLoading() {
|
|
|
|
@ -29,16 +42,55 @@ export class HttpWaitService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addRequest(request: HttpRequest<any>) {
|
|
|
|
|
const requests = this.store.state.requests;
|
|
|
|
|
let { requests } = this.store.state;
|
|
|
|
|
requests = new Set(requests.values());
|
|
|
|
|
requests.add(request);
|
|
|
|
|
this.store.patch({ requests });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deleteRequest(request: HttpRequest<any>) {
|
|
|
|
|
const requests = this.store.state.requests;
|
|
|
|
|
const { requests } = this.store.state;
|
|
|
|
|
requests.delete(request);
|
|
|
|
|
this.store.patch({ requests });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Add filter function
|
|
|
|
|
addFilter(request: HttpRequestInfo) {
|
|
|
|
|
const filteredRequests = [
|
|
|
|
|
...this.store.state.filteredRequests.filter(f => !this.isSameRequest(f, request)),
|
|
|
|
|
request,
|
|
|
|
|
];
|
|
|
|
|
this.store.patch({ filteredRequests });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
removeFilter(request: HttpRequestInfo) {
|
|
|
|
|
const filteredRequests = this.store.state.filteredRequests.filter(
|
|
|
|
|
f => !this.isSameRequest(f, request),
|
|
|
|
|
);
|
|
|
|
|
this.store.patch({ filteredRequests });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setDelay(delay: number) {
|
|
|
|
|
this.store.patch({ delay });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private applyFilter(requests: Set<HttpRequest<any>>) {
|
|
|
|
|
const { filteredRequests } = this.store.state;
|
|
|
|
|
return Array.from(requests).filter(
|
|
|
|
|
({ method, url }) =>
|
|
|
|
|
!filteredRequests.find(filteredRequest =>
|
|
|
|
|
this.isSameRequest(filteredRequest, { method, endpoint: getPathName(url) }),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private isSameRequest(filteredRequest: HttpRequestInfo, request: HttpRequestInfo) {
|
|
|
|
|
const { method, endpoint } = filteredRequest;
|
|
|
|
|
return endpoint === request.endpoint && method === request.method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private debounceWhenLoading() {
|
|
|
|
|
return this.store.state.delay && !!this.applyFilter(this.store.state.requests).length
|
|
|
|
|
? debounceTime(this.store.state.delay)
|
|
|
|
|
: tap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|