common-ui/src/lib/sorting/sorting.service.ts

54 lines
1.9 KiB
TypeScript

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { SortingOption } from './models/sorting-option.model';
import { SortingOrder, SortingOrders } from './models/sorting-order.type';
import { KeysOf, shareDistinctLast } from '../utils';
import { Id, IListable } from '../listing';
import { orderBy } from 'lodash-es';
@Injectable()
export class SortingService<T extends IListable<PrimaryKey>, PrimaryKey extends Id = T['id']> {
private readonly _sortingOption$ = new BehaviorSubject<SortingOption<T>>({
column: 'searchKey',
order: SortingOrders.asc,
});
readonly sortingOption$ = this._sortingOption$.asObservable().pipe(shareDistinctLast());
get sortingOption(): SortingOption<T> | undefined {
return this._sortingOption$.getValue();
}
static sort<T>(values: T[], order?: SortingOrder, column?: KeysOf<T>): T[] {
if (!values || values.length <= 1 || !order) {
return values;
}
if (!column) {
/** sort 1D array */
const result = [...values].sort();
return order === SortingOrders.asc ? result : result.reverse();
}
return orderBy<T>(
values,
[(entity: T) => (typeof entity[column] === 'string' ? (entity[column] as unknown as string).toLowerCase() : entity[column])],
[order],
);
}
setSortingOption(value: SortingOption<T>): void {
this._sortingOption$.next(value);
}
defaultSort(values: T[]): T[] {
return SortingService.sort(values, this.sortingOption?.order, this.sortingOption?.column);
}
toggleSort(column: KeysOf<T>): void {
const sameColumn = this.sortingOption?.column === column;
const order = sameColumn ? SortingOrders.inverseOf(this.sortingOption?.order) : SortingOrders.asc;
this._sortingOption$.next({ column, order });
}
}