igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
129 lines (109 loc) • 4.01 kB
text/typescript
import type { KeyOfOrString } from '../core/types';
import { IBaseEventArgs } from '../core/utils';
import { GridType } from '../grids/common/grid.interface';
export enum SortingDirection {
None = 0,
Asc = 1,
Desc = 2
}
export interface ISortingExpression<T = any> extends IBaseEventArgs {
fieldName: KeyOfOrString<T> & string;
dir: SortingDirection;
ignoreCase?: boolean;
strategy?: ISortingStrategy;
}
export interface ISortingStrategy {
sort: (
data: any[],
fieldName: string,
dir: SortingDirection,
ignoreCase: boolean,
valueResolver: (obj: any, key: string, isDate?: boolean) => any,
isDate?: boolean,
isTime?: boolean,
grid?: GridType
) => any[];
}
export class DefaultSortingStrategy implements ISortingStrategy {
protected static _instance: DefaultSortingStrategy = null;
protected constructor() { }
public static instance(): DefaultSortingStrategy {
return this._instance || (this._instance = new this());
}
public sort(
data: any[],
fieldName: string,
dir: SortingDirection,
ignoreCase: boolean,
valueResolver: (obj: any, key: string, isDate?: boolean) => any,
isDate?: boolean,
isTime?: boolean
) {
const key = fieldName;
const reverse = (dir === SortingDirection.Desc ? -1 : 1);
const cmpFunc = (obj1: any, obj2: any) => this.compareObjects(obj1, obj2, key, reverse, ignoreCase, valueResolver, isDate, isTime);
return this.arraySort(data, cmpFunc);
}
public compareValues(a: any, b: any): number {
const an = (a === null || a === undefined);
const bn = (b === null || b === undefined);
if (an) {
if (bn) {
return 0;
}
return -1;
} else if (bn) {
return 1;
}
return a > b ? 1 : a < b ? -1 : 0;
}
protected compareObjects(
obj1: any,
obj2: any,
key: string,
reverse: number,
ignoreCase: boolean,
valueResolver: (obj: any, key: string, isDate?: boolean, isTime?: boolean) => any,
isDate: boolean,
isTime: boolean
) {
let a = valueResolver.call(this, obj1, key, isDate, isTime);
let b = valueResolver.call(this, obj2, key, isDate, isTime);
if (ignoreCase) {
a = a && a.toLowerCase ? a.toLowerCase() : a;
b = b && b.toLowerCase ? b.toLowerCase() : b;
}
return reverse * this.compareValues(a, b);
}
protected arraySort(data: any[], compareFn?: (arg0: any, arg1: any) => number): any[] {
return data.sort(compareFn);
}
}
export class GroupMemberCountSortingStrategy implements ISortingStrategy {
protected static _instance: GroupMemberCountSortingStrategy = null;
protected constructor() { }
public static instance(): GroupMemberCountSortingStrategy {
return this._instance || (this._instance = new this());
}
public sort(data: any[], fieldName: string, dir: SortingDirection) {
const groupedArray = this.groupBy(data, fieldName);
const reverse = (dir === SortingDirection.Desc ? -1 : 1);
const cmpFunc = (a, b) => {
return this.compareObjects(a, b, groupedArray, fieldName, reverse);
};
return data
.sort((a, b) => a[fieldName].localeCompare(b[fieldName]))
.sort(cmpFunc);
}
public groupBy(data, key) {
return data.reduce((acc, curr) => {
(acc[curr[key]] = acc[curr[key]] || []).push(curr);
return acc;
}, {})
}
protected compareObjects(obj1: any, obj2: any, data: any[], fieldName: string, reverse: number) {
const firstItemValuesLength = data[obj1[fieldName]].length;
const secondItemValuesLength = data[obj2[fieldName]].length;
return reverse * (firstItemValuesLength - secondItemValuesLength);
}
}