mp-common
Version:
This is XPO MarketPlace common libary
109 lines (94 loc) • 3.54 kB
text/typescript
import { Pipe } from "@angular/core";
import { PaginationService } from "./pagination.service";
import { PaginationInstance } from './pagination-instance';
const LARGE_NUMBER = Number.MAX_SAFE_INTEGER;
interface PipeState {
collection: any[];
size: number;
start: number;
end: number;
slice: any[];
}
({
name: 'paginate',
pure: false
})
export class PaginatePipe {
private state: { [ id: string ]: PipeState } = {};
constructor(private service: PaginationService) {
}
public transform(collection: any[], args: any): any {
if (args instanceof Array) {
args = args[ 0 ];
}
if (!(collection instanceof Array)) {
let _id = args.id || this.service.defaultId;
if (this.state[ _id ]) {
return this.state[ _id ].slice;
} else {
return collection;
}
}
let serverSideMode = args.totalItems && args.totalItems !== collection.length;
let instance = this.createInstance(collection, args);
let id = instance.id;
let start, end;
let perPage = instance.itemsPerPage;
this.service.register(instance);
if (!serverSideMode && collection instanceof Array) {
perPage = +perPage || LARGE_NUMBER;
start = (instance.currentPage - 1) * perPage;
end = start + perPage;
let isIdentical = this.stateIsIdentical(id, collection, start, end);
if (isIdentical) {
return this.state[ id ].slice;
} else {
let slice = collection.slice(start, end);
this.saveState(id, collection, slice, start, end);
this.service.change.emit(id);
return slice;
}
}
this.saveState(id, collection, collection, start, end);
return collection;
}
private createInstance(collection: any[], args: any): PaginationInstance {
let config = args;
this.checkConfig(config);
return {
id: config.id || this.service.defaultId(),
itemsPerPage: config.itemsPerPage || 0,
currentPage: config.currentPage || 1,
totalItems: config.totalItems || collection.length
};
}
private checkConfig(config: any): void {
const required = [ 'itemsPerPage', 'currentPage' ];
const missing = required.filter(prop => !(prop in config));
if (0 < missing.length) {
throw new Error(`PaginatePipe: Argument is missing the following required properties: ${missing.join(', ')}`);
}
}
private saveState(id: string, collection: any[], slice: any[], start: number, end: number) {
this.state[ id ] = {
collection,
size: collection.length,
slice,
start,
end
};
}
private stateIsIdentical(id: string, collection: any[], start: number, end: number): boolean {
let state = this.state[ id ];
if (!state) {
return false;
}
let isMetaDataIdentical = state.size === collection.length &&
state.start === start &&
state.end === end;
if (!isMetaDataIdentical) {
return false;
}
return state.slice.every((element, index) => element === collection[ start + index ]);
}
}