add search service and better typings
This commit is contained in:
parent
3f9915434d
commit
be233975d6
@ -4,6 +4,7 @@ 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/pipes/humanize.pipe';
|
||||
export * from './lib/utils/types/utility-types';
|
||||
export * from './lib/utils/types/tooltip-positions.type';
|
||||
export * from './lib/utils/decorators/required.decorator';
|
||||
export * from './lib/buttons/circle-button/circle-button.type';
|
||||
@ -17,3 +18,4 @@ export * from './lib/sorting/sort-by.pipe';
|
||||
export * from './lib/sorting/sorting.service';
|
||||
export * from './lib/sorting/models/sorting-option.model';
|
||||
export * from './lib/sorting/models/sorting-order.type';
|
||||
export * from './lib/search/search.service';
|
||||
|
||||
@ -38,7 +38,7 @@ export function handleCheckedValue(filter: NestedFilter) {
|
||||
}
|
||||
}
|
||||
|
||||
export function checkFilter(entity: any, filters: NestedFilter[], validate: Function, validateArgs = [], matchAll: boolean = false) {
|
||||
export function checkFilter(entity: any, filters: NestedFilter[], validate: Function, validateArgs: any = [], matchAll: boolean = false) {
|
||||
const hasChecked = filters.find(f => f.checked);
|
||||
|
||||
if (!hasChecked) return true;
|
||||
|
||||
49
src/lib/search/search.service.ts
Normal file
49
src/lib/search/search.service.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { KeysOf } from '../utils/types/utility-types';
|
||||
|
||||
const controlsConfig = {
|
||||
query: ['']
|
||||
} as const;
|
||||
|
||||
type FormControls = { [key in KeysOf<typeof controlsConfig>]: string };
|
||||
|
||||
@Injectable()
|
||||
export class SearchService<T extends object> {
|
||||
readonly searchForm = this._formBuilder.group(controlsConfig);
|
||||
readonly valueChanges$ = this.searchForm.valueChanges.pipe(
|
||||
startWith(''),
|
||||
map((values: FormControls) => values.query)
|
||||
);
|
||||
private _searchKey!: KeysOf<T>;
|
||||
|
||||
constructor(private readonly _formBuilder: FormBuilder) {}
|
||||
|
||||
get searchValue(): string {
|
||||
return this.searchForm.get('query')?.value;
|
||||
}
|
||||
|
||||
set searchValue(value: string) {
|
||||
this.searchForm.patchValue({ query: value });
|
||||
}
|
||||
|
||||
searchIn(entities: T[]) {
|
||||
if (!this._searchKey) return entities;
|
||||
|
||||
const searchValue = this.searchValue.toLowerCase();
|
||||
return entities.filter(entity => this._searchField(entity).includes(searchValue));
|
||||
}
|
||||
|
||||
setSearchKey(value: KeysOf<T>): void {
|
||||
this._searchKey = value;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.searchForm.reset({ query: '' }, { emitEvent: true });
|
||||
}
|
||||
|
||||
private _searchField(entity: T): string {
|
||||
return ((<unknown>entity[this._searchKey]) as string).toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import { SortingOrder } from './sorting-order.type';
|
||||
import { KeysOf } from '../../utils/types/utility-types';
|
||||
|
||||
export interface SortingOption {
|
||||
export interface SortingOption<T extends object> {
|
||||
readonly order: SortingOrder;
|
||||
readonly column: string;
|
||||
readonly column: KeysOf<T>;
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { SortingService } from './sorting.service';
|
||||
import { SortingOrder } from './models/sorting-order.type';
|
||||
import { KeysOf } from '../utils/types/utility-types';
|
||||
|
||||
@Pipe({ name: 'sortBy' })
|
||||
export class SortByPipe implements PipeTransform {
|
||||
constructor(private readonly _sortingService: SortingService) {}
|
||||
export class SortByPipe<T extends object> implements PipeTransform {
|
||||
constructor(private readonly _sortingService: SortingService<T>) {}
|
||||
|
||||
transform<T>(value: T[], order: SortingOrder, column: string): T[] {
|
||||
transform(value: T[], order: SortingOrder, column: KeysOf<T>): T[] {
|
||||
return this._sortingService.sort(value, order, column);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,23 +3,24 @@ import { orderBy } from 'lodash';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { SortingOption } from './models/sorting-option.model';
|
||||
import { SortingOrder, SortingOrders } from './models/sorting-order.type';
|
||||
import { KeysOf } from '../utils/types/utility-types';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SortingService {
|
||||
private readonly _sortingOption$ = new BehaviorSubject<SortingOption | undefined>(undefined);
|
||||
export class SortingService<T extends object> {
|
||||
private readonly _sortingOption$ = new BehaviorSubject<SortingOption<T> | undefined>(undefined);
|
||||
readonly sortingOption$ = this._sortingOption$.asObservable();
|
||||
|
||||
get sortingOption(): SortingOption | undefined {
|
||||
get sortingOption(): SortingOption<T> | undefined {
|
||||
return this._sortingOption$.getValue();
|
||||
}
|
||||
|
||||
setSortingOption(value: SortingOption): void {
|
||||
setSortingOption(value: SortingOption<T>): void {
|
||||
this._sortingOption$.next(value);
|
||||
}
|
||||
|
||||
sort<T>(values: T[], order?: SortingOrder, column?: string): T[] {
|
||||
sort(values: T[], order?: SortingOrder, column?: KeysOf<T>): T[] {
|
||||
if (!values || values.length <= 1 || !order) return values;
|
||||
|
||||
if (!column) {
|
||||
@ -31,11 +32,11 @@ export class SortingService {
|
||||
return orderBy(values, [column], [order]);
|
||||
}
|
||||
|
||||
defaultSort<T>(values: T[]): T[] {
|
||||
defaultSort(values: T[]): T[] {
|
||||
return this.sort(values, this.sortingOption?.order, this.sortingOption?.column);
|
||||
}
|
||||
|
||||
toggleSort(column: string): void {
|
||||
toggleSort(column: KeysOf<T>): void {
|
||||
const sameColumn = this.sortingOption?.column === column;
|
||||
const order = sameColumn ? SortingOrders.inverseOf(this.sortingOption?.order) : SortingOrders.asc;
|
||||
|
||||
|
||||
@ -1,5 +1,25 @@
|
||||
export type KeysOf<T> = keyof T;
|
||||
/**
|
||||
* KeysOf
|
||||
* @desc Get union type of keys in object type `T`
|
||||
* @example
|
||||
* type Object = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
|
||||
*
|
||||
* // Expect: "name | setName | someKeys | someFn"
|
||||
* type Keys = KeysOf<Object>;
|
||||
*/
|
||||
export type KeysOf<T extends object> = {
|
||||
[K in keyof T]: K;
|
||||
}[keyof T];
|
||||
|
||||
/**
|
||||
* ValuesOf
|
||||
* @desc Get union type of values in object type `T`
|
||||
* @example
|
||||
* const Object = {bar: "some bar", foo: "some foo"};
|
||||
*
|
||||
* // Expect: "some bar | some foo"
|
||||
* type Values = ValuesOf<Object>;
|
||||
*/
|
||||
export type ValuesOf<T extends object> = T[KeysOf<T>];
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user