common-ui/src/lib/services/generic.service.ts
2024-06-19 13:05:12 +03:00

132 lines
5.2 KiB
TypeScript

import { HttpClient, HttpEvent, HttpParams } from '@angular/common/http';
import { inject } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { HeadersConfiguration } from '../utils/headers-configuration';
import { List } from '../utils/types/iqser-types';
export const ROOT_CHANGES_KEY = 'root';
export const LAST_CHECKED_OFFSET = 30000;
export interface QueryParam {
readonly key: string;
readonly value: string | number | boolean;
}
/**
* I for interface,
* R for response
*/
export abstract class GenericService<I> {
protected readonly _http = inject(HttpClient);
protected readonly _lastCheckedForChanges = new Map<string, string>([
[ROOT_CHANGES_KEY, new Date(Date.now() - LAST_CHECKED_OFFSET).toISOString()],
]);
protected abstract readonly _defaultModelPath: string;
protected readonly _serviceName: string = 'redaction-gateway-v1';
get<T = I[]>(): Observable<T>;
get<T extends I[]>(): Observable<T>;
get<T = I>(id: string, ...args: unknown[]): Observable<T>;
get<T extends I>(id: string, ...args: unknown[]): Observable<T>;
get<T>(id?: string, ...args: unknown[]): Observable<T> {
return id ? this._getOne<T>([id]) : this.getAll<T>();
}
getAll<R extends I[]>(modelPath?: string, queryParams?: List<QueryParam>): Observable<R>;
getAll<R = I[]>(modelPath?: string, queryParams?: List<QueryParam>): Observable<R>;
getAll<R = I[]>(modelPath = this._defaultModelPath, queryParams?: List<QueryParam>): Observable<R> {
this._updateLastChanged();
return this._http.get<R>(`/${this._serviceName}/${encodeURI(modelPath)}`, {
headers: HeadersConfiguration.getHeaders({ contentType: false }),
observe: 'body',
params: this._queryParams(queryParams),
});
}
getFor<R = I[]>(entityId: string, queryParams?: List<QueryParam>): Observable<R> {
this._updateLastChanged(entityId);
return this.getAll<R>(`${this._defaultModelPath}/${entityId}`, queryParams);
}
delete(body: unknown, modelPath = this._defaultModelPath, queryParams?: List<QueryParam>): Observable<unknown> {
let path = `/${this._serviceName}/${encodeURI(modelPath)}`;
if (typeof body === 'string') {
path += `/${encodeURIComponent(body)}`;
}
return this._http.delete(path, {
body: body,
params: this._queryParams(queryParams),
headers: HeadersConfiguration.getHeaders({ contentType: false }),
observe: 'body',
});
}
upload<R = I>(data?: Blob, modelPath = this._defaultModelPath): Observable<HttpEvent<R>> {
const formParams = new FormData();
if (data !== undefined) {
formParams.append('file', data);
}
const headers = HeadersConfiguration.getHeaders({ contentType: false });
return this._http.post<R>(`/${this._serviceName}/${encodeURI(modelPath)}`, formParams, {
headers,
observe: 'events',
reportProgress: true,
});
}
hasChanges$(key = ROOT_CHANGES_KEY): Observable<boolean> {
const modelPath = key === ROOT_CHANGES_KEY ? '' : `${key}/`;
const body = { value: this._lastCheckedForChanges.get(key) };
return this._post<{ value: boolean }>(body, `${this._defaultModelPath}/${modelPath}changes`).pipe(
map((res: { value: boolean }) => res.value),
);
}
protected _post<R = I>(body: unknown, modelPath = this._defaultModelPath, queryParams?: List<QueryParam>): Observable<R> {
return this._http.post<R>(`/${this._serviceName}/${encodeURI(modelPath)}`, body, {
params: this._queryParams(queryParams),
headers: HeadersConfiguration.getHeaders(),
observe: 'body',
});
}
protected _put<R = I>(body: unknown, modelPath = this._defaultModelPath, queryParams?: List<QueryParam>): Observable<R> {
return this._http.put<R>(`/${this._serviceName}/${encodeURI(modelPath)}`, body, {
params: this._queryParams(queryParams),
headers: HeadersConfiguration.getHeaders(),
observe: 'body',
});
}
protected _getOne<R = I>(path: List, modelPath = this._defaultModelPath, queryParams?: List<QueryParam>): Observable<R> {
const entityPath = path.map(item => encodeURIComponent(item)).join('/');
return this._http.get<R>(`/${this._serviceName}/${encodeURI(modelPath)}/${entityPath}`.replace(/\/+$/, ''), {
headers: HeadersConfiguration.getHeaders({ contentType: false }),
params: this._queryParams(queryParams),
observe: 'body',
});
}
protected _queryParams(queryParams?: List<QueryParam>): HttpParams {
let queryParameters = new HttpParams();
queryParams?.forEach(param => {
if (param?.value !== undefined && param?.value !== null) {
queryParameters = queryParameters.append(param.key, param.value);
}
});
return queryParameters;
}
protected _updateLastChanged(key = ROOT_CHANGES_KEY): void {
this._lastCheckedForChanges.set(key, new Date(Date.now() - LAST_CHECKED_OFFSET).toISOString());
}
}