add sorting and utility types
This commit is contained in:
parent
4004c4c8f9
commit
bb7b3af13e
@ -24,7 +24,8 @@
|
||||
"prefix": "iqser",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
]
|
||||
],
|
||||
"no-param-reassign": "error"
|
||||
},
|
||||
"plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"]
|
||||
},
|
||||
|
||||
@ -11,3 +11,6 @@ export * from './lib/filtering/filter-utils';
|
||||
export * from './lib/filtering/models/filter-group.model';
|
||||
export * from './lib/filtering/models/nested-filter.model';
|
||||
export * from './lib/filtering/models/filter.model';
|
||||
export * from './lib/sorting/sorting.service';
|
||||
export * from './lib/sorting/models/sorting-option.model';
|
||||
export * from './lib/sorting/models/sorting-order.type';
|
||||
|
||||
@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, On
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { CircleButtonType, CircleButtonTypes } from './circle-button.type';
|
||||
import { Required } from '../../utils/decorators/required.decorator';
|
||||
import { TooltipPositionsType, TooltipPositionsTypes } from '../../utils/types/tooltip-positions.type';
|
||||
import { IqserTooltipPosition, IqserTooltipPositions } from '../../utils/types/tooltip-positions.type';
|
||||
|
||||
@Component({
|
||||
selector: 'iqser-circle-button',
|
||||
@ -17,7 +17,7 @@ export class CircleButtonComponent implements OnInit {
|
||||
@Input() tooltip?: string;
|
||||
@Input() tooltipClass?: string;
|
||||
@Input() showDot = false;
|
||||
@Input() tooltipPosition: TooltipPositionsType = TooltipPositionsTypes.above;
|
||||
@Input() tooltipPosition: IqserTooltipPosition = IqserTooltipPositions.above;
|
||||
@Input() disabled = false;
|
||||
@Input() type: CircleButtonType = CircleButtonTypes.default;
|
||||
@Input() removeTooltip = false;
|
||||
|
||||
6
src/lib/sorting/models/sorting-option.model.ts
Normal file
6
src/lib/sorting/models/sorting-option.model.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { SortingOrder } from './sorting-order.type';
|
||||
|
||||
export interface SortingOption {
|
||||
readonly order: SortingOrder;
|
||||
readonly column: string;
|
||||
}
|
||||
14
src/lib/sorting/models/sorting-order.type.ts
Normal file
14
src/lib/sorting/models/sorting-order.type.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { NonFunctionKeys } from '../../utils/types/utility-types';
|
||||
|
||||
function inverseOf(order?: SortingOrder) {
|
||||
if (order === undefined) return SortingOrders.asc;
|
||||
return order === SortingOrders.asc ? SortingOrders.desc : SortingOrders.asc;
|
||||
}
|
||||
|
||||
export const SortingOrders = {
|
||||
asc: 'asc',
|
||||
desc: 'desc',
|
||||
inverseOf: inverseOf
|
||||
} as const;
|
||||
|
||||
export type SortingOrder = NonFunctionKeys<typeof SortingOrders>;
|
||||
42
src/lib/sorting/sorting.service.ts
Normal file
42
src/lib/sorting/sorting.service.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { orderBy } from 'lodash';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { SortingOption } from './models/sorting-option.model';
|
||||
import { SortingOrder, SortingOrders } from './models/sorting-order.type';
|
||||
|
||||
@Injectable()
|
||||
export class SortingService {
|
||||
private readonly _sortingOption$ = new BehaviorSubject<SortingOption | undefined>(undefined);
|
||||
readonly sortingOption$ = this._sortingOption$.asObservable();
|
||||
|
||||
get sortingOption(): SortingOption | undefined {
|
||||
return this._sortingOption$.getValue();
|
||||
}
|
||||
|
||||
setSortingOption(value: SortingOption): void {
|
||||
this._sortingOption$.next(value);
|
||||
}
|
||||
|
||||
sort<T>(values: T[], order?: SortingOrder, column?: string): 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(values, [column], [order]);
|
||||
}
|
||||
|
||||
defaultSort<T>(values: T[]): T[] {
|
||||
return this.sort(values, this.sortingOption?.order, this.sortingOption?.column);
|
||||
}
|
||||
|
||||
toggleSort(column: string): void {
|
||||
const sameColumn = this.sortingOption?.column === column;
|
||||
const order = sameColumn ? SortingOrders.inverseOf(this.sortingOption?.order) : SortingOrders.asc;
|
||||
|
||||
this._sortingOption$.next({ column, order });
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
export function Required(message?: string) {
|
||||
export function Required(message?: string): PropertyDecorator {
|
||||
return function (target: Object, propertyKey: PropertyKey) {
|
||||
Object.defineProperty(target, propertyKey, {
|
||||
get() {
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
export const TooltipPositionsTypes = {
|
||||
import { KeysOf } from './utility-types';
|
||||
|
||||
export const IqserTooltipPositions = {
|
||||
below: 'below',
|
||||
above: 'above',
|
||||
before: 'before',
|
||||
after: 'after'
|
||||
} as const;
|
||||
|
||||
export type TooltipPositionsType = keyof typeof TooltipPositionsTypes;
|
||||
export type IqserTooltipPosition = KeysOf<typeof IqserTooltipPositions>;
|
||||
|
||||
38
src/lib/utils/types/utility-types.ts
Normal file
38
src/lib/utils/types/utility-types.ts
Normal file
@ -0,0 +1,38 @@
|
||||
export type KeysOf<T> = keyof T;
|
||||
|
||||
export type ValuesOf<T extends object> = T[KeysOf<T>];
|
||||
|
||||
/**
|
||||
* NonUndefined
|
||||
* @desc Exclude undefined from set `A`
|
||||
* @example
|
||||
* // Expect: "string | null"
|
||||
* SymmetricDifference<string | null | undefined>;
|
||||
*/
|
||||
export type NonUndefined<T> = T extends undefined ? never : T;
|
||||
|
||||
/**
|
||||
* FunctionKeys
|
||||
* @desc Get union type of keys that are functions in object type `T`
|
||||
* @example
|
||||
* type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
|
||||
*
|
||||
* // Expect: "setName | someFn"
|
||||
* type Keys = FunctionKeys<MixedProps>;
|
||||
*/
|
||||
export type FunctionKeys<T extends object> = {
|
||||
[K in keyof T]-?: NonUndefined<T[K]> extends Function ? K : never;
|
||||
}[keyof T];
|
||||
|
||||
/**
|
||||
* NonFunctionKeys
|
||||
* @desc Get union type of keys that are non-functions in object type `T`
|
||||
* @example
|
||||
* type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
|
||||
*
|
||||
* // Expect: "name | someKey"
|
||||
* type Keys = NonFunctionKeys<MixedProps>;
|
||||
*/
|
||||
export type NonFunctionKeys<T extends object> = {
|
||||
[K in keyof T]-?: NonUndefined<T[K]> extends Function ? never : K;
|
||||
}[keyof T];
|
||||
Loading…
x
Reference in New Issue
Block a user