remove some constructor dependencies
This commit is contained in:
parent
10de0152c7
commit
c39a69df3e
@ -1,10 +1,12 @@
|
||||
import { Directive, HostListener, Injector, OnInit } from '@angular/core';
|
||||
import { Directive, HostListener, inject, OnInit } from '@angular/core';
|
||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import { UntypedFormGroup } from '@angular/forms';
|
||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { AutoUnsubscribe, hasFormChanged, IqserEventTarget } from '../utils';
|
||||
import { ConfirmOptions } from '.';
|
||||
import { ConfirmationDialogService } from './confirmation-dialog.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { LoadingService } from '../loading';
|
||||
import { Toaster } from '../services';
|
||||
|
||||
const TARGET_NODE = 'mat-dialog-container';
|
||||
|
||||
@ -27,14 +29,13 @@ export interface SaveOptions {
|
||||
export abstract class BaseDialogComponent extends AutoUnsubscribe implements OnInit {
|
||||
form!: UntypedFormGroup;
|
||||
initialFormValue!: Record<string, string>;
|
||||
private readonly _confirmationDialogService: ConfirmationDialogService = this._injector.get(ConfirmationDialogService);
|
||||
private readonly _dialog: MatDialog = this._injector.get(MatDialog);
|
||||
protected readonly _formBuilder = inject(UntypedFormBuilder);
|
||||
protected readonly _loadingService = inject(LoadingService);
|
||||
protected readonly _toaster = inject(Toaster);
|
||||
readonly #confirmationDialogService = inject(ConfirmationDialogService);
|
||||
readonly #dialog = inject(MatDialog);
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
protected readonly _dialogRef: MatDialogRef<BaseDialogComponent>,
|
||||
private readonly _isInEditMode?: boolean,
|
||||
) {
|
||||
constructor(protected readonly _dialogRef: MatDialogRef<BaseDialogComponent>, private readonly _isInEditMode?: boolean) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -85,13 +86,13 @@ export abstract class BaseDialogComponent extends AutoUnsubscribe implements OnI
|
||||
|
||||
@HostListener('window:keydown.Escape', ['$event'])
|
||||
onEscape(): void {
|
||||
if (this._dialog.openDialogs.length === 1) {
|
||||
if (this.#dialog.openDialogs.length === 1) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected _openConfirmDialog() {
|
||||
const dialogRef = this._confirmationDialogService.openDialog({ disableConfirm: !this.valid });
|
||||
const dialogRef = this.#confirmationDialogService.openDialog({ disableConfirm: !this.valid });
|
||||
return firstValueFrom(dialogRef.afterClosed());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
export * from './models';
|
||||
export * from './utils';
|
||||
export * from './services';
|
||||
|
||||
export * from './scroll-button/scroll-button.component';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Directive, Injector, OnDestroy, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { Directive, inject, OnDestroy, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { FilterService } from '../filtering';
|
||||
@ -8,20 +8,17 @@ import { SearchService } from '../search';
|
||||
import { EntitiesService, ListingService } from './services';
|
||||
import { IListable, TableColumnConfig } from './models';
|
||||
|
||||
export const DefaultListingServicesTmp = [FilterService, SearchService, SortingService, ListingService] as const;
|
||||
export const DefaultListingServices = [...DefaultListingServicesTmp, EntitiesService] as const;
|
||||
|
||||
@Directive()
|
||||
export abstract class ListingComponent<T extends IListable> extends AutoUnsubscribe implements OnDestroy {
|
||||
readonly filterService = this._injector.get(FilterService);
|
||||
readonly searchService = this._injector.get<SearchService<T>>(SearchService);
|
||||
readonly sortingService = this._injector.get<SortingService<T>>(SortingService);
|
||||
readonly entitiesService = this._injector.get<EntitiesService<T>>(EntitiesService);
|
||||
readonly listingService = this._injector.get<ListingService<T>>(ListingService);
|
||||
readonly filterService = inject(FilterService);
|
||||
readonly searchService = inject<SearchService<T>>(SearchService);
|
||||
readonly sortingService = inject<SortingService<T>>(SortingService);
|
||||
readonly entitiesService = inject<EntitiesService<T>>(EntitiesService);
|
||||
readonly listingService = inject<ListingService<T>>(ListingService);
|
||||
|
||||
readonly noMatch$ = this._noMatch$;
|
||||
readonly noContent$ = this._noContent$;
|
||||
readonly sortedDisplayedEntities$ = this._sortedDisplayedEntities$;
|
||||
readonly noMatch$ = this.#noMatch$;
|
||||
readonly noContent$ = this.#noContent$;
|
||||
readonly sortedDisplayedEntities$ = this.#sortedDisplayedEntities$;
|
||||
|
||||
abstract readonly tableColumnConfigs: readonly TableColumnConfig<T>[];
|
||||
abstract readonly tableHeaderLabel: string;
|
||||
@ -29,15 +26,11 @@ export abstract class ListingComponent<T extends IListable> extends AutoUnsubscr
|
||||
@ViewChild('tableItemTemplate') readonly tableItemTemplate?: TemplateRef<unknown>;
|
||||
@ViewChild('workflowItemTemplate') readonly workflowItemTemplate?: TemplateRef<unknown>;
|
||||
|
||||
protected constructor(protected readonly _injector: Injector) {
|
||||
super();
|
||||
}
|
||||
|
||||
get allEntities(): T[] {
|
||||
return this.entitiesService.all;
|
||||
}
|
||||
|
||||
private get _sortedDisplayedEntities$(): Observable<T[]> {
|
||||
get #sortedDisplayedEntities$(): Observable<T[]> {
|
||||
const sort = (entities: T[]) => this.sortingService.defaultSort(entities);
|
||||
const sortedEntities$ = this.listingService.displayed$.pipe(map(sort));
|
||||
return this.sortingService.sortingOption$.pipe(
|
||||
@ -46,15 +39,15 @@ export abstract class ListingComponent<T extends IListable> extends AutoUnsubscr
|
||||
);
|
||||
}
|
||||
|
||||
private get _noMatch$(): Observable<boolean> {
|
||||
get #noMatch$(): Observable<boolean> {
|
||||
return combineLatest([this.entitiesService.allLength$, this.listingService.displayedLength$]).pipe(
|
||||
map(([hasEntities, hasDisplayedEntities]) => !!hasEntities && !hasDisplayedEntities),
|
||||
shareDistinctLast(),
|
||||
);
|
||||
}
|
||||
|
||||
private get _noContent$(): Observable<boolean> {
|
||||
return combineLatest([this._noMatch$, this.entitiesService.noData$]).pipe(
|
||||
get #noContent$(): Observable<boolean> {
|
||||
return combineLatest([this.#noMatch$, this.entitiesService.noData$]).pipe(
|
||||
map(([noMatch, noData]) => noMatch || noData),
|
||||
shareDistinctLast(),
|
||||
);
|
||||
|
||||
@ -1,46 +1,38 @@
|
||||
import { Inject, Injectable, InjectionToken, Injector, Optional } from '@angular/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||
import { filter, map, startWith, tap } from 'rxjs/operators';
|
||||
import { IListable } from '../models';
|
||||
import { GenericService, QueryParam } from '../../services';
|
||||
import { getLength, List, mapEach, shareDistinctLast, shareLast } from '../../utils';
|
||||
|
||||
/**
|
||||
* This should be removed when refactoring is done
|
||||
*/
|
||||
const ENTITY_PATH = new InjectionToken<string>('This is here for compatibility while refactoring things.');
|
||||
const ENTITY_CLASS = new InjectionToken<string>('This is here for compatibility while refactoring things.');
|
||||
|
||||
@Injectable()
|
||||
/**
|
||||
* E for Entity
|
||||
* I for Interface
|
||||
* E for Entity,
|
||||
* I for Interface.
|
||||
* By default, if no interface is provided, I = E
|
||||
*/
|
||||
export class EntitiesService<E extends IListable, I = E> extends GenericService<I> {
|
||||
export class EntitiesService<I, E extends I & IListable = I & IListable> extends GenericService<I> {
|
||||
readonly noData$: Observable<boolean>;
|
||||
readonly all$: Observable<E[]>;
|
||||
readonly allLength$: Observable<number>;
|
||||
protected readonly _defaultModelPath: string = '';
|
||||
protected readonly _entityClass?: new (entityInterface: I, ...args: unknown[]) => E;
|
||||
protected readonly _entityChanged$ = new Subject<E>();
|
||||
protected readonly _entityDeleted$ = new Subject<E>();
|
||||
private readonly _all$ = new BehaviorSubject<E[]>([]);
|
||||
readonly #all$ = new BehaviorSubject<E[]>([]);
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
@Optional() @Inject(ENTITY_CLASS) private readonly _entityClass: new (entityInterface: I, ...args: unknown[]) => E,
|
||||
@Optional() @Inject(ENTITY_PATH) protected readonly _defaultModelPath = '',
|
||||
) {
|
||||
super(_injector, _defaultModelPath);
|
||||
this.all$ = this._all$.asObservable().pipe(shareDistinctLast());
|
||||
this.allLength$ = this._all$.pipe(getLength, shareDistinctLast());
|
||||
this.noData$ = this._noData$;
|
||||
constructor() {
|
||||
super();
|
||||
this.all$ = this.#all$.asObservable().pipe(shareDistinctLast());
|
||||
this.allLength$ = this.#all$.pipe(getLength, shareDistinctLast());
|
||||
this.noData$ = this.#noData$;
|
||||
}
|
||||
|
||||
get all(): E[] {
|
||||
return Object.values(this._all$.getValue());
|
||||
return Object.values(this.#all$.getValue());
|
||||
}
|
||||
|
||||
private get _noData$(): Observable<boolean> {
|
||||
get #noData$(): Observable<boolean> {
|
||||
return this.allLength$.pipe(
|
||||
map(length => length === 0),
|
||||
shareDistinctLast(),
|
||||
@ -50,7 +42,7 @@ export class EntitiesService<E extends IListable, I = E> extends GenericService<
|
||||
loadAll(...args: unknown[]): Observable<E[]>;
|
||||
loadAll(modelPath = this._defaultModelPath, queryParams?: List<QueryParam>): Observable<E[]> {
|
||||
return this.getAll(modelPath, queryParams).pipe(
|
||||
mapEach(entity => new this._entityClass(entity)),
|
||||
mapEach(entity => (this._entityClass ? new this._entityClass(entity) : (entity as E))),
|
||||
tap((entities: E[]) => this.setEntities(entities)),
|
||||
);
|
||||
}
|
||||
@ -83,7 +75,7 @@ export class EntitiesService<E extends IListable, I = E> extends GenericService<
|
||||
return entity;
|
||||
});
|
||||
|
||||
this._all$.next(newEntities);
|
||||
this.#all$.next(newEntities);
|
||||
|
||||
// Emit observables only after entities have been updated
|
||||
|
||||
@ -99,7 +91,7 @@ export class EntitiesService<E extends IListable, I = E> extends GenericService<
|
||||
remove(id: string) {
|
||||
const entity = this.all.find(item => item.id === id);
|
||||
if (entity) {
|
||||
this._all$.next(this.all.filter(item => item.id !== id));
|
||||
this.#all$.next(this.all.filter(item => item.id !== id));
|
||||
this._entityDeleted$.next(entity);
|
||||
}
|
||||
}
|
||||
|
||||
70
src/lib/listing/utils.ts
Normal file
70
src/lib/listing/utils.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { FilterService } from '../filtering';
|
||||
import { SearchService } from '../search';
|
||||
import { SortingService } from '../sorting';
|
||||
import { EntitiesService, ListingService } from './services';
|
||||
import { forwardRef, Provider, Type } from '@angular/core';
|
||||
import { ListingComponent } from './listing-component.directive';
|
||||
|
||||
export const DefaultListingServices: readonly Provider[] = [FilterService, SearchService, SortingService, ListingService] as const;
|
||||
|
||||
export interface IListingServiceFactoryOptions<T> {
|
||||
readonly entitiesService?: Type<EntitiesService<T>>;
|
||||
readonly component: Type<unknown>;
|
||||
}
|
||||
|
||||
function getEntitiesService<T>(service?: Type<EntitiesService<T>>): Provider {
|
||||
if (service) {
|
||||
return {
|
||||
provide: EntitiesService,
|
||||
useExisting: service,
|
||||
};
|
||||
}
|
||||
|
||||
return EntitiesService;
|
||||
}
|
||||
|
||||
function getOptions<T>(options?: IListingServiceFactoryOptions<T> | Type<unknown>) {
|
||||
if (typeof options === 'function') {
|
||||
return {
|
||||
component: options,
|
||||
};
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function getComponent<T>(component: Type<unknown>) {
|
||||
return {
|
||||
provide: ListingComponent,
|
||||
useExisting: forwardRef(() => component),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This is equivalent to
|
||||
* @example <code>[FilterService, SearchService, SortingService, ListingService, EntitiesService]</code>
|
||||
*/
|
||||
export function listingProvidersFactory(): Provider[];
|
||||
/**
|
||||
* This is equivalent to
|
||||
* @example <code>[{provide: ListingComponent, useExisting: forwardRef(() => component)}, EntitiesService, FilterService, SearchService, SortingService, ListingService]</code>
|
||||
*/
|
||||
export function listingProvidersFactory(component: Type<unknown>): Provider[];
|
||||
/**
|
||||
* This is equivalent to
|
||||
* @example <code>[{provide: EntitiesService, useExisting: entitiesService}, {provide: ListingComponent, useExisting: forwardRef(() => component)}, FilterService, SearchService, SortingService, ListingService]</code>
|
||||
*/
|
||||
export function listingProvidersFactory<T>(options: IListingServiceFactoryOptions<T>): Provider[];
|
||||
export function listingProvidersFactory<T>(args?: IListingServiceFactoryOptions<T> | Type<unknown>): Provider[] {
|
||||
const options = getOptions(args);
|
||||
const services = [...DefaultListingServices];
|
||||
|
||||
const entitiesService = getEntitiesService(options?.entitiesService);
|
||||
services.push(entitiesService);
|
||||
|
||||
if (options?.component) {
|
||||
services.push(getComponent(options.component));
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||
import { filter, startWith } from 'rxjs/operators';
|
||||
import { Entity } from '../listing';
|
||||
@ -6,11 +6,11 @@ import { RequiredParam, shareLast, Validate } from '../utils';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export abstract class EntitiesMapService<E extends Entity<I>, I> {
|
||||
protected readonly _map = new Map<string, BehaviorSubject<E[]>>();
|
||||
private readonly _entityChanged$ = new Subject<E>();
|
||||
private readonly _entityDeleted$ = new Subject<E>();
|
||||
protected abstract readonly _primaryKey: string;
|
||||
|
||||
protected constructor(@Inject('ENTITY_PRIMARY_KEY') protected readonly _primaryKey: string) {}
|
||||
protected readonly _map = new Map<string, BehaviorSubject<E[]>>();
|
||||
readonly #entityChanged$ = new Subject<E>();
|
||||
readonly #entityDeleted$ = new Subject<E>();
|
||||
|
||||
get empty(): boolean {
|
||||
return this._map.size === 0;
|
||||
@ -45,7 +45,7 @@ export abstract class EntitiesMapService<E extends Entity<I>, I> {
|
||||
set(key: string, entities: E[]): void {
|
||||
if (!this._map.has(key)) {
|
||||
this._map.set(key, new BehaviorSubject<E[]>(entities));
|
||||
return entities.forEach(entity => this._entityChanged$.next(entity));
|
||||
return entities.forEach(entity => this.#entityChanged$.next(entity));
|
||||
}
|
||||
|
||||
const changedEntities: E[] = [];
|
||||
@ -68,11 +68,11 @@ export abstract class EntitiesMapService<E extends Entity<I>, I> {
|
||||
// Emit observables only after entities have been updated
|
||||
|
||||
for (const entity of changedEntities) {
|
||||
this._entityChanged$.next(entity);
|
||||
this.#entityChanged$.next(entity);
|
||||
}
|
||||
|
||||
for (const entity of deletedEntities) {
|
||||
this._entityDeleted$.next(entity);
|
||||
this.#entityDeleted$.next(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ export abstract class EntitiesMapService<E extends Entity<I>, I> {
|
||||
|
||||
@Validate()
|
||||
watch$(@RequiredParam() key: string, @RequiredParam() entityId: string): Observable<E> {
|
||||
return this._entityChanged$.pipe(
|
||||
return this.#entityChanged$.pipe(
|
||||
filter(entity => entity.id === entityId),
|
||||
startWith(this.get(key, entityId) as E),
|
||||
shareLast(),
|
||||
@ -105,7 +105,7 @@ export abstract class EntitiesMapService<E extends Entity<I>, I> {
|
||||
}
|
||||
|
||||
watchDeleted$(entityId: string): Observable<E> {
|
||||
return this._entityDeleted$.pipe(filter(entity => entity.id === entityId));
|
||||
return this.#entityDeleted$.pipe(filter(entity => entity.id === entityId));
|
||||
}
|
||||
|
||||
private _pluckPrimaryKey(entity: E): string {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { HttpClient, HttpEvent, HttpParams } from '@angular/common/http';
|
||||
import { Injector } from '@angular/core';
|
||||
import { inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { CustomHttpUrlEncodingCodec, HeadersConfiguration, List, RequiredParam, Validate } from '../utils';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
@ -18,31 +18,31 @@ export interface QueryParam {
|
||||
}
|
||||
|
||||
/**
|
||||
* I for interface
|
||||
* I for interface,
|
||||
* R for response
|
||||
*/
|
||||
export abstract class GenericService<I> {
|
||||
protected readonly _http = this._injector.get(HttpClient);
|
||||
protected readonly _http = inject(HttpClient);
|
||||
protected readonly _lastCheckedForChanges = new Map<string, string>([[ROOT_CHANGES_KEY, '0']]);
|
||||
|
||||
protected constructor(protected readonly _injector: Injector, protected readonly _defaultModelPath: string) {}
|
||||
protected abstract readonly _defaultModelPath: string;
|
||||
|
||||
get<T = I[]>(): Observable<T>;
|
||||
// eslint-disable-next-line @typescript-eslint/unified-signatures
|
||||
get<T extends I[]>(): Observable<T>;
|
||||
get<T = I>(id: string, ...args: unknown[]): Observable<T>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
|
||||
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> {
|
||||
return this._http
|
||||
.get<R>(`/${encodeURI(modelPath)}`, {
|
||||
headers: HeadersConfiguration.getHeaders({ contentType: false }),
|
||||
observe: 'body',
|
||||
params: this._queryParams(queryParams),
|
||||
})
|
||||
.pipe(tap(() => this._updateLastChanged()));
|
||||
const request$ = this._http.get<R>(`/${encodeURI(modelPath)}`, {
|
||||
headers: HeadersConfiguration.getHeaders({ contentType: false }),
|
||||
observe: 'body',
|
||||
params: this._queryParams(queryParams),
|
||||
});
|
||||
return request$.pipe(tap(() => this._updateLastChanged()));
|
||||
}
|
||||
|
||||
getFor<R = I[]>(entityId: string, queryParams?: List<QueryParam>): Observable<R> {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable, Injector } from '@angular/core';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { tap } from 'rxjs/operators';
|
||||
@ -6,19 +6,16 @@ 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 abstract readonly _primaryKey: string;
|
||||
protected abstract readonly _entityClass: new (entityInterface: I, ...args: unknown[]) => E;
|
||||
protected abstract readonly _defaultModelPath: string;
|
||||
|
||||
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,
|
||||
) {}
|
||||
readonly #http = inject(HttpClient);
|
||||
readonly #map = new Map<string, BehaviorSubject<E>>();
|
||||
|
||||
@Validate()
|
||||
getFor(@RequiredParam() ids: string[]): Observable<E[]> {
|
||||
const request = this._http.post<I[]>(`/${encodeURI(this._defaultModelPath)}`, ids, {
|
||||
const request = this.#http.post<I[]>(`/${encodeURI(this._defaultModelPath)}`, ids, {
|
||||
headers: HeadersConfiguration.getHeaders(),
|
||||
observe: 'body',
|
||||
});
|
||||
@ -34,8 +31,8 @@ export abstract class StatsService<E, I = E> {
|
||||
}
|
||||
|
||||
set(stats: E): void {
|
||||
if (!this._map.has(this._pluckPrimaryKey(stats))) {
|
||||
this._map.set(this._pluckPrimaryKey(stats), new BehaviorSubject<E>(stats));
|
||||
if (!this.#map.has(this._pluckPrimaryKey(stats))) {
|
||||
this.#map.set(this._pluckPrimaryKey(stats), new BehaviorSubject<E>(stats));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -57,6 +54,6 @@ export abstract class StatsService<E, I = E> {
|
||||
|
||||
private _getBehaviourSubject(key: string): BehaviorSubject<E> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return this._map.get(key)!;
|
||||
return this.#map.get(key)!;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ import { ITrackable } from '../listing/models/trackable';
|
||||
import { UntypedFormGroup } from '@angular/forms';
|
||||
import { forOwn, has, isEqual, isPlainObject, transform } from 'lodash-es';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
export function capitalize(value: string | String): string {
|
||||
if (!value) {
|
||||
@ -165,3 +167,11 @@ String.prototype.capitalize = function _capitalize(this: string): string {
|
||||
Array.prototype.filterTruthy = function <T>(this: T[], predicate: (value: T) => boolean = () => true): T[] {
|
||||
return this.filter(value => !!value && predicate(value));
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this in field initialization or in constructor of a service / component
|
||||
* @param param
|
||||
*/
|
||||
export function getParam(param: string): string | null {
|
||||
return inject(ActivatedRoute).snapshot.paramMap.get(param);
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
"lib": ["es2021", "dom"],
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["**/*.ts"],
|
||||
"include": ["src/**/*.ts"],
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user