add sorting and utility types

This commit is contained in:
Dan Percic 2021-08-05 21:25:40 +03:00
parent 4004c4c8f9
commit bb7b3af13e
9 changed files with 112 additions and 6 deletions

View File

@ -24,7 +24,8 @@
"prefix": "iqser",
"style": "kebab-case"
}
]
],
"no-param-reassign": "error"
},
"plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"]
},

View File

@ -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';

View File

@ -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;

View File

@ -0,0 +1,6 @@
import { SortingOrder } from './sorting-order.type';
export interface SortingOption {
readonly order: SortingOrder;
readonly column: string;
}

View 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>;

View 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 });
}
}

View File

@ -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() {

View File

@ -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>;

View 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];