2019-08-09 19:13:18 +03:00
|
|
|
///
|
2021-01-11 13:42:16 +02:00
|
|
|
/// Copyright © 2016-2021 The Thingsboard Authors
|
2019-08-09 19:13:18 +03:00
|
|
|
///
|
|
|
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
/// you may not use this file except in compliance with the License.
|
|
|
|
|
/// You may obtain a copy of the License at
|
|
|
|
|
///
|
|
|
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
///
|
|
|
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
/// See the License for the specific language governing permissions and
|
|
|
|
|
/// limitations under the License.
|
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
import { Direction, SortOrder } from '@shared/models/page/sort-order';
|
2019-08-23 15:06:42 +03:00
|
|
|
import { emptyPageData, PageData } from '@shared/models/page/page-data';
|
2020-01-29 17:20:28 +02:00
|
|
|
import { getDescendantProp, isObject } from '@core/utils';
|
2020-02-04 15:14:17 +02:00
|
|
|
import { SortDirection } from '@angular/material/sort';
|
2019-08-23 15:06:42 +03:00
|
|
|
|
2020-04-08 19:31:08 +03:00
|
|
|
export const MAX_SAFE_PAGE_SIZE = 2147483647;
|
|
|
|
|
|
2020-04-14 11:34:22 +03:00
|
|
|
export type PageLinkSearchFunction<T> = (entity: T, textSearch: string, searchProperty?: string) => boolean;
|
2019-08-23 15:06:42 +03:00
|
|
|
|
2020-04-14 11:34:22 +03:00
|
|
|
export function defaultPageLinkSearchFunction(searchProperty?: string): PageLinkSearchFunction<any> {
|
|
|
|
|
return (entity, textSearch) => defaultPageLinkSearch(entity, textSearch, searchProperty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const defaultPageLinkSearch: PageLinkSearchFunction<any> =
|
|
|
|
|
(entity: any, textSearch: string, searchProperty?: string) => {
|
2019-08-23 15:06:42 +03:00
|
|
|
if (textSearch === null || !textSearch.length) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
const expected = ('' + textSearch).toLowerCase();
|
2020-04-14 11:34:22 +03:00
|
|
|
if (searchProperty && searchProperty.length) {
|
|
|
|
|
if (Object.prototype.hasOwnProperty.call(entity, searchProperty)) {
|
|
|
|
|
const val = entity[searchProperty];
|
|
|
|
|
if (val !== null) {
|
|
|
|
|
if (val !== Object(val)) {
|
|
|
|
|
const actual = ('' + val).toLowerCase();
|
|
|
|
|
if (actual.indexOf(expected) !== -1) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-01-29 17:20:28 +02:00
|
|
|
}
|
2020-04-14 11:34:22 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (const key of Object.keys(entity)) {
|
|
|
|
|
const val = entity[key];
|
|
|
|
|
if (val !== null) {
|
|
|
|
|
if (val !== Object(val)) {
|
|
|
|
|
const actual = ('' + val).toLowerCase();
|
|
|
|
|
if (actual.indexOf(expected) !== -1) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} else if (isObject(val)) {
|
|
|
|
|
if (defaultPageLinkSearch(val, textSearch)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-01-29 17:20:28 +02:00
|
|
|
}
|
2019-08-23 15:06:42 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
2019-08-09 19:13:18 +03:00
|
|
|
|
2020-06-26 11:00:00 +03:00
|
|
|
export function sortItems(item1: any, item2: any, property: string, asc: boolean): number {
|
|
|
|
|
const item1Value = getDescendantProp(item1, property);
|
|
|
|
|
const item2Value = getDescendantProp(item2, property);
|
|
|
|
|
let result = 0;
|
|
|
|
|
if (item1Value !== item2Value) {
|
2020-06-26 17:02:41 +03:00
|
|
|
const item1Type = typeof item1Value;
|
|
|
|
|
const item2Type = typeof item2Value;
|
|
|
|
|
if (item1Type === 'number' && item2Type === 'number') {
|
2020-06-26 11:00:00 +03:00
|
|
|
result = item1Value - item2Value;
|
2020-06-26 17:02:41 +03:00
|
|
|
} else if (item1Type === 'string' && item2Type === 'string') {
|
2020-06-26 11:00:00 +03:00
|
|
|
result = item1Value.localeCompare(item2Value);
|
2020-06-26 17:02:41 +03:00
|
|
|
} else if ((item1Type === 'boolean' && item2Type === 'boolean') || (item1Type !== item2Type)) {
|
2020-06-26 11:00:00 +03:00
|
|
|
if (item1Value && !item2Value) {
|
|
|
|
|
result = 1;
|
|
|
|
|
} else if (!item1Value && item2Value) {
|
|
|
|
|
result = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return asc ? result : result * -1;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-09 19:13:18 +03:00
|
|
|
export class PageLink {
|
|
|
|
|
|
|
|
|
|
textSearch: string;
|
|
|
|
|
pageSize: number;
|
|
|
|
|
page: number;
|
|
|
|
|
sortOrder: SortOrder;
|
|
|
|
|
|
|
|
|
|
constructor(pageSize: number, page: number = 0, textSearch: string = null, sortOrder: SortOrder = null) {
|
|
|
|
|
this.textSearch = textSearch;
|
|
|
|
|
this.pageSize = pageSize;
|
|
|
|
|
this.page = page;
|
|
|
|
|
this.sortOrder = sortOrder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public nextPageLink(): PageLink {
|
|
|
|
|
return new PageLink(this.pageSize, this.page + 1, this.textSearch, this.sortOrder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public toQuery(): string {
|
|
|
|
|
let query = `?pageSize=${this.pageSize}&page=${this.page}`;
|
|
|
|
|
if (this.textSearch && this.textSearch.length) {
|
2021-02-25 17:31:24 +02:00
|
|
|
const textSearch = encodeURIComponent(this.textSearch);
|
|
|
|
|
query += `&textSearch=${textSearch}`;
|
2019-08-09 19:13:18 +03:00
|
|
|
}
|
|
|
|
|
if (this.sortOrder) {
|
|
|
|
|
query += `&sortProperty=${this.sortOrder.property}&sortOrder=${this.sortOrder.direction}`;
|
|
|
|
|
}
|
|
|
|
|
return query;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sort(item1: any, item2: any): number {
|
|
|
|
|
if (this.sortOrder) {
|
2020-06-26 11:00:00 +03:00
|
|
|
const sortProperty = this.sortOrder.property;
|
|
|
|
|
const asc = this.sortOrder.direction === Direction.ASC;
|
|
|
|
|
return sortItems(item1, item2, sortProperty, asc);
|
2019-08-09 19:13:18 +03:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-23 15:06:42 +03:00
|
|
|
public filterData<T>(data: Array<T>,
|
2020-04-14 11:34:22 +03:00
|
|
|
searchFunction: PageLinkSearchFunction<T> = defaultPageLinkSearchFunction()): PageData<T> {
|
2019-08-23 15:06:42 +03:00
|
|
|
const pageData = emptyPageData<T>();
|
|
|
|
|
pageData.data = [...data];
|
|
|
|
|
if (this.textSearch && this.textSearch.length) {
|
|
|
|
|
pageData.data = pageData.data.filter((entity) => searchFunction(entity, this.textSearch));
|
|
|
|
|
}
|
|
|
|
|
pageData.totalElements = pageData.data.length;
|
2020-01-22 20:05:30 +02:00
|
|
|
pageData.totalPages = this.pageSize === Number.POSITIVE_INFINITY ? 1 : Math.ceil(pageData.totalElements / this.pageSize);
|
2019-08-23 15:06:42 +03:00
|
|
|
if (this.sortOrder) {
|
2020-06-26 11:00:00 +03:00
|
|
|
const sortProperty = this.sortOrder.property;
|
|
|
|
|
const asc = this.sortOrder.direction === Direction.ASC;
|
|
|
|
|
pageData.data = pageData.data.sort((a, b) => sortItems(a, b, sortProperty, asc));
|
2019-08-23 15:06:42 +03:00
|
|
|
}
|
2020-01-22 20:05:30 +02:00
|
|
|
if (this.pageSize !== Number.POSITIVE_INFINITY) {
|
|
|
|
|
const startIndex = this.pageSize * this.page;
|
|
|
|
|
pageData.data = pageData.data.slice(startIndex, startIndex + this.pageSize);
|
|
|
|
|
pageData.hasNext = pageData.totalElements > startIndex + pageData.data.length;
|
|
|
|
|
}
|
2019-08-23 15:06:42 +03:00
|
|
|
return pageData;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 15:14:17 +02:00
|
|
|
public sortDirection(): SortDirection {
|
|
|
|
|
if (this.sortOrder) {
|
|
|
|
|
return (this.sortOrder.direction + '').toLowerCase() as SortDirection;
|
|
|
|
|
} else {
|
|
|
|
|
return '' as SortDirection;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-09 19:13:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class TimePageLink extends PageLink {
|
|
|
|
|
|
|
|
|
|
startTime: number;
|
|
|
|
|
endTime: number;
|
|
|
|
|
|
|
|
|
|
constructor(pageSize: number, page: number = 0, textSearch: string = null, sortOrder: SortOrder = null,
|
|
|
|
|
startTime: number = null, endTime: number = null) {
|
|
|
|
|
super(pageSize, page, textSearch, sortOrder);
|
|
|
|
|
this.startTime = startTime;
|
|
|
|
|
this.endTime = endTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public nextPageLink(): TimePageLink {
|
|
|
|
|
return new TimePageLink(this.pageSize, this.page + 1, this.textSearch, this.sortOrder, this.startTime, this.endTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public toQuery(): string {
|
|
|
|
|
let query = super.toQuery();
|
|
|
|
|
if (this.startTime) {
|
|
|
|
|
query += `&startTime=${this.startTime}`;
|
|
|
|
|
}
|
|
|
|
|
if (this.endTime) {
|
|
|
|
|
query += `&endTime=${this.endTime}`;
|
|
|
|
|
}
|
|
|
|
|
return query;
|
|
|
|
|
}
|
|
|
|
|
}
|