add listing component

This commit is contained in:
Dan Percic 2021-08-10 16:58:25 +03:00
parent 6b0cbc09f2
commit c552ed2e21
4 changed files with 82 additions and 4 deletions

View File

@ -1,8 +1,8 @@
export * from './lib/common-ui.module';
export * from './lib/base/auto-unsubscribe.component';
export * from './lib/buttons/icon-button/icon-button.type';
export * from './lib/buttons/icon-button/icon-button.component';
export * from './lib/utils/functions';
export * from './lib/utils/auto-unsubscribe.directive';
export * from './lib/utils/pipes/humanize.pipe';
export * from './lib/utils/types/utility-types';
export * from './lib/utils/types/tooltip-positions.type';
@ -21,5 +21,6 @@ export * from './lib/sorting/models/sorting-option.model';
export * from './lib/sorting/models/sorting-order.type';
export * from './lib/search/search.service';
export * from './lib/tables/entities.service';
export * from './lib/tables/listing-component.directive';
export * from './lib/tables/models/table-column-config.model';
export * from './lib/tables/table-column-name/table-column-name.component';

View File

@ -57,10 +57,10 @@ export class FilterService {
}
getFilterModels$(filterGroupSlug: string): Observable<NestedFilter[] | undefined> {
return this.getFilterGroup$(filterGroupSlug).pipe(map(f => f?.filters));
return this.getGroup$(filterGroupSlug).pipe(map(f => f?.filters));
}
getFilterGroup$(slug: string): Observable<FilterGroup | undefined> {
getGroup$(slug: string): Observable<FilterGroup | undefined> {
return this.filterGroups$.pipe(map(all => all.find(f => f.slug === slug)));
}

View File

@ -0,0 +1,77 @@
import { Directive, Injector, OnDestroy, Provider } from '@angular/core';
import { combineLatest, Observable } from 'rxjs';
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
import { FilterService } from '../filtering/filter.service';
import { SortingService } from '../sorting/sorting.service';
import { SortingOrders } from '../sorting/models/sorting-order.type';
import { Bind } from '../utils/decorators/bind.decorator';
import { AutoUnsubscribe } from '../utils/auto-unsubscribe.directive';
import { SearchService } from '../search/search.service';
import { KeysOf } from '../utils/types/utility-types';
import { TableColumnConfig } from './models/table-column-config.model';
import { EntitiesService } from './entities.service';
export const DefaultListingServices = new Set<Provider>().add(FilterService).add(SearchService).add(EntitiesService).add(SortingService);
@Directive()
export abstract class ListingComponent<T extends object> 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 noMatch$ = this._noMatch$;
readonly sortedDisplayedEntities$ = this._sortedDisplayedEntities$;
abstract readonly tableColumnConfigs: TableColumnConfig<T>[];
/**
* Key used in the *trackBy* function with **ngFor* or **cdkVirtualFor*
* and in the default sorting and as the search field
* @protected
*/
protected abstract readonly _primaryKey: KeysOf<T>;
protected constructor(protected readonly _injector: Injector) {
super();
setTimeout(() => this.setInitialConfig());
}
get allEntities(): T[] {
return this.entitiesService.all;
}
private get _sortedDisplayedEntities$(): Observable<readonly T[]> {
const sort = (entities: T[]) => this.sortingService.defaultSort(entities);
const sortedEntities = () => this.entitiesService.displayed$.pipe(map(sort));
return this.sortingService.sortingOption$.pipe(switchMap(sortedEntities));
}
private get _noMatch$(): Observable<boolean> {
return combineLatest([this.entitiesService.allLength$, this.entitiesService.displayedLength$]).pipe(
map(([hasEntities, hasDisplayedEntities]) => !!hasEntities && !hasDisplayedEntities),
distinctUntilChanged()
);
}
setInitialConfig() {
this.sortingService.setSortingOption({
column: this._primaryKey,
order: SortingOrders.asc
});
this.searchService.setSearchKey(this._primaryKey);
}
toggleEntitySelected(event: MouseEvent, entity: T) {
event.stopPropagation();
return this.entitiesService.select(entity);
}
isSelected(entity: T): boolean {
return this.entitiesService.isSelected(entity);
}
@Bind()
trackByPrimaryKey(index: number, item: T) {
return item[this._primaryKey];
}
}

View File

@ -5,7 +5,7 @@ import { Subscription } from "rxjs";
* Inherit this class when you need to subscribe to observables in your components
*/
@Directive()
export abstract class AutoUnsubscribeComponent implements OnDestroy {
export abstract class AutoUnsubscribe implements OnDestroy {
private readonly _subscriptions = new Subscription();
/**