angular-t9n
Version:
A translation tool for Angular i18n
95 lines (83 loc) • 3.04 kB
text/typescript
import { Hal, HalLink, LinkBuilder } from '../hal';
import { QueryParams } from '../requests';
import { Filterables } from './filterables';
import { Sortables } from './sortables';
const PAGE_PLACEHOLDER = 'PAGE_PLACEHOLDER';
export class PaginationResponse<TEntry, TResponse> implements Hal {
entriesPerPage: number;
currentPage: number;
totalEntries: number;
totalPages: number;
_links?: { [key: string]: HalLink };
_embedded?: { [key: string]: unknown };
constructor(params: {
query: QueryParams;
entries: TEntry[];
responseMapper: (entry: TEntry) => TResponse;
urlFactory: (query: QueryParams) => string;
sortables?: Sortables<TEntry>;
filterables?: Filterables<TEntry>;
}) {
let entries = params.entries.slice();
const { entriesPerPage, page, sort, ...query } = params.query;
entries = this._sort(entries, sort, params.sortables);
entries = this._filter(entries, query, params.filterables);
this.entriesPerPage = +entriesPerPage || 10;
this.currentPage = +page || 0;
this.totalEntries = entries.length;
this.totalPages = Math.ceil(entries.length / this.entriesPerPage);
const lastPage = this.totalPages - 1;
this._links = new LinkBuilder()
.self(params.urlFactory(params.query))
.hrefWhen(this.currentPage > 0, 'first', () =>
params.urlFactory({ ...params.query, page: '0' }),
)
.hrefWhen(this.currentPage > 0, 'previous', () =>
params.urlFactory({ ...params.query, page: `${this.currentPage - 1}` }),
)
.templatedHref(
'page',
params
.urlFactory({ ...params.query, page: PAGE_PLACEHOLDER })
.replace(PAGE_PLACEHOLDER, '{page}'),
)
.hrefWhen(this.currentPage < lastPage, 'next', () =>
params.urlFactory({ ...params.query, page: `${this.currentPage + 1}` }),
)
.hrefWhen(this.currentPage < lastPage, 'last', () =>
params.urlFactory({ ...params.query, page: `${lastPage}` }),
)
.build();
const start = this.currentPage * this.entriesPerPage;
this._embedded = {
entries: entries.slice(start, start + this.entriesPerPage).map(params.responseMapper),
};
}
private _sort(entries: TEntry[], sort: string | undefined, sortables?: Sortables<TEntry>) {
if (!sort || !sortables) {
return entries;
}
const direction = sort[0] !== '!' ? 'asc' : 'desc';
if (direction === 'desc') {
sort = sort.substring(1);
}
if (!(sort in sortables)) {
return entries;
}
const sorting = sortables[sort];
entries = entries.slice().sort(sorting);
return direction === 'asc' ? entries : entries.reverse();
}
private _filter(
entries: TEntry[],
query: { [key: string]: string },
filterables?: Filterables<TEntry>,
) {
if (!filterables) {
return entries;
}
return Object.keys(filterables)
.filter((k) => query[k])
.reduce((current, next) => current.filter(filterables[next](query[next])), entries);
}
}