UNPKG

mp-common

Version:

This is XPO MarketPlace common libary

109 lines (94 loc) 3.54 kB
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[]; } @Pipe({ 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 ]); } }