Stats generic service

This commit is contained in:
Adina Țeudan 2021-12-17 10:52:16 +02:00
parent 0610684e8f
commit f4ffa08f86
3 changed files with 64 additions and 1 deletions

View File

@ -9,7 +9,7 @@ import { IqserEventTarget } from '../utils';
* However, some components (e.g. redaction-select, color picker) don't set focus on the input after choosing a value.
* Also, other components (e.g. dropdown select) trigger a different action on enter, instead of submit.
*
* Make sure to remove property type="submit" from the save button and the (submit)="save()" property from the form
* Make sure to remove the (submit)="save()" property from the form and to set type="button" on the save button
* (otherwise the save request will be triggered twice).
* */
export abstract class BaseDialogComponent {

View File

@ -3,3 +3,4 @@ export * from './toaster.service';
export * from './error-message.service';
export * from './generic.service';
export * from './composite-route.guard';
export * from './stats.service';

View File

@ -0,0 +1,62 @@
import { Inject, Injectable, Injector } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { tap } from 'rxjs/operators';
import { HeadersConfiguration, mapEach, RequiredParam, Validate } from '../utils';
@Injectable()
export abstract class StatsService<E, I = E> {
private readonly _http = this._injector.get(HttpClient);
private readonly _map = new Map<string, BehaviorSubject<E>>();
protected constructor(
protected readonly _injector: Injector,
@Inject('ENTITY_PRIMARY_KEY') protected readonly _primaryKey: string,
@Inject('ENTITY_CLASS') private readonly _entityClass: new (entityInterface: I, ...args: unknown[]) => E,
@Inject('ENTITY_PATH') protected readonly _defaultModelPath: string,
) {}
@Validate()
getFor(@RequiredParam() ids: string[]): Observable<E[]> {
const request = this._http.post<I[]>(`/${encodeURI(this._defaultModelPath)}`, ids, {
headers: HeadersConfiguration.getHeaders(),
observe: 'body',
});
return request.pipe(
mapEach(entity => new this._entityClass(entity)),
tap(entities => entities.forEach(entity => this.set(entity))),
);
}
get(key: string): E {
return this._getBehaviourSubject(key).value;
}
set(stats: E): void {
if (!this._map.has(this._pluckPrimaryKey(stats))) {
this._map.set(this._pluckPrimaryKey(stats), new BehaviorSubject<E>(stats));
return;
}
const old = this.get(this._pluckPrimaryKey(stats));
if (JSON.stringify(old) !== JSON.stringify(stats)) {
this._getBehaviourSubject(this._pluckPrimaryKey(stats)).next(stats);
}
}
watch$(key: string): Observable<E> {
return this._getBehaviourSubject(key).asObservable();
}
private _pluckPrimaryKey(stats: E): string {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return stats[this._primaryKey] as string;
}
private _getBehaviourSubject(key: string): BehaviorSubject<E> {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this._map.get(key)!;
}
}