2019-09-05 21:15:40 +03:00
|
|
|
///
|
2021-01-11 13:42:16 +02:00
|
|
|
/// Copyright © 2016-2021 The Thingsboard Authors
|
2019-09-05 21:15:40 +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.
|
|
|
|
|
///
|
|
|
|
|
|
2019-12-23 14:36:44 +02:00
|
|
|
// tslint:disable-next-line:no-reference
|
|
|
|
|
/// <reference path="../../../../src/typings/rawloader.typings.d.ts" />
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
import { Inject, Injectable, NgZone } from '@angular/core';
|
2019-09-05 21:15:40 +03:00
|
|
|
import { WINDOW } from '@core/services/window.service';
|
|
|
|
|
import { ExceptionData } from '@app/shared/models/error.models';
|
2020-05-05 12:19:21 +03:00
|
|
|
import {
|
2020-11-27 18:21:12 +02:00
|
|
|
baseUrl,
|
2020-05-05 12:19:21 +03:00
|
|
|
createLabelFromDatasource,
|
|
|
|
|
deepClone,
|
|
|
|
|
deleteNullProperties,
|
|
|
|
|
guid,
|
|
|
|
|
isDefined,
|
2021-03-02 12:04:45 +02:00
|
|
|
isDefinedAndNotNull,
|
|
|
|
|
isString,
|
2020-05-05 12:19:21 +03:00
|
|
|
isUndefined
|
|
|
|
|
} from '@core/utils';
|
2019-09-05 21:15:40 +03:00
|
|
|
import { WindowMessage } from '@shared/models/window-message.model';
|
|
|
|
|
import { TranslateService } from '@ngx-translate/core';
|
2020-11-27 17:35:19 +02:00
|
|
|
import { customTranslationsPrefix, i18nPrefix } from '@app/shared/models/constants';
|
2019-10-10 13:00:29 +03:00
|
|
|
import { DataKey, Datasource, DatasourceType, KeyInfo } from '@shared/models/widget.models';
|
2019-09-10 15:12:10 +03:00
|
|
|
import { EntityType } from '@shared/models/entity-type.models';
|
|
|
|
|
import { DataKeyType } from '@app/shared/models/telemetry/telemetry.models';
|
|
|
|
|
import { alarmFields } from '@shared/models/alarm.models';
|
|
|
|
|
import { materialColors } from '@app/shared/models/material.models';
|
2019-09-19 20:10:52 +03:00
|
|
|
import { WidgetInfo } from '@home/models/widget-component.models';
|
2019-10-10 13:00:29 +03:00
|
|
|
import jsonSchemaDefaults from 'json-schema-defaults';
|
2019-12-12 19:55:17 +02:00
|
|
|
import materialIconsCodepoints from '!raw-loader!material-design-icons/iconfont/codepoints';
|
2019-10-24 19:52:19 +03:00
|
|
|
import { Observable, of, ReplaySubject } from 'rxjs';
|
2019-09-05 21:15:40 +03:00
|
|
|
|
2020-11-27 17:35:19 +02:00
|
|
|
const i18nRegExp = new RegExp(`{${i18nPrefix}:[^{}]+}`, 'g');
|
|
|
|
|
|
2020-05-04 11:40:54 +03:00
|
|
|
const predefinedFunctions: { [func: string]: string } = {
|
2019-10-10 13:00:29 +03:00
|
|
|
Sin: 'return Math.round(1000*Math.sin(time/5000));',
|
|
|
|
|
Cos: 'return Math.round(1000*Math.cos(time/5000));',
|
|
|
|
|
Random: 'var value = prevValue + Math.random() * 100 - 50;\n' +
|
|
|
|
|
'var multiplier = Math.pow(10, 2 || 0);\n' +
|
|
|
|
|
'var value = Math.round(value * multiplier) / multiplier;\n' +
|
|
|
|
|
'if (value < -1000) {\n' +
|
|
|
|
|
' value = -1000;\n' +
|
|
|
|
|
'} else if (value > 1000) {\n' +
|
|
|
|
|
' value = 1000;\n' +
|
|
|
|
|
'}\n' +
|
|
|
|
|
'return value;'
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const predefinedFunctionsList: Array<string> = [];
|
|
|
|
|
for (const func of Object.keys(predefinedFunctions)) {
|
|
|
|
|
predefinedFunctionsList.push(func);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
const defaultAlarmFields: Array<string> = [
|
|
|
|
|
alarmFields.createdTime.keyName,
|
|
|
|
|
alarmFields.originator.keyName,
|
|
|
|
|
alarmFields.type.keyName,
|
|
|
|
|
alarmFields.severity.keyName,
|
|
|
|
|
alarmFields.status.keyName
|
|
|
|
|
];
|
|
|
|
|
|
2020-05-04 11:40:54 +03:00
|
|
|
const commonMaterialIcons: Array<string> = ['more_horiz', 'more_vert', 'open_in_new',
|
2019-10-24 19:52:19 +03:00
|
|
|
'visibility', 'play_arrow', 'arrow_back', 'arrow_downward',
|
|
|
|
|
'arrow_forward', 'arrow_upwards', 'close', 'refresh', 'menu', 'show_chart', 'multiline_chart', 'pie_chart', 'insert_chart', 'people',
|
|
|
|
|
'person', 'domain', 'devices_other', 'now_widgets', 'dashboards', 'map', 'pin_drop', 'my_location', 'extension', 'search',
|
|
|
|
|
'settings', 'notifications', 'notifications_active', 'info', 'info_outline', 'warning', 'list', 'file_download', 'import_export',
|
2020-05-04 11:40:54 +03:00
|
|
|
'share', 'add', 'edit', 'done'];
|
2019-10-24 19:52:19 +03:00
|
|
|
|
2019-12-23 14:36:44 +02:00
|
|
|
// @dynamic
|
2019-09-05 21:15:40 +03:00
|
|
|
@Injectable({
|
|
|
|
|
providedIn: 'root'
|
|
|
|
|
})
|
|
|
|
|
export class UtilsService {
|
|
|
|
|
|
|
|
|
|
iframeMode = false;
|
|
|
|
|
widgetEditMode = false;
|
2019-09-19 20:10:52 +03:00
|
|
|
editWidgetInfo: WidgetInfo = null;
|
2019-09-05 21:15:40 +03:00
|
|
|
|
2019-10-10 13:00:29 +03:00
|
|
|
defaultDataKey: DataKey = {
|
|
|
|
|
name: 'f(x)',
|
|
|
|
|
type: DataKeyType.function,
|
|
|
|
|
label: 'Sin',
|
|
|
|
|
color: this.getMaterialColor(0),
|
|
|
|
|
funcBody: this.getPredefinedFunctionBody('Sin'),
|
|
|
|
|
settings: {},
|
|
|
|
|
_hash: Math.random()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
defaultDatasource: Datasource = {
|
|
|
|
|
type: DatasourceType.function,
|
|
|
|
|
name: DatasourceType.function,
|
|
|
|
|
dataKeys: [deepClone(this.defaultDataKey)]
|
|
|
|
|
};
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
defaultAlarmDataKeys: Array<DataKey> = [];
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
materialIcons: Array<string> = [];
|
|
|
|
|
|
2019-09-05 21:15:40 +03:00
|
|
|
constructor(@Inject(WINDOW) private window: Window,
|
2020-11-27 17:35:19 +02:00
|
|
|
private zone: NgZone,
|
|
|
|
|
private translate: TranslateService) {
|
2019-09-05 21:15:40 +03:00
|
|
|
let frame: Element = null;
|
|
|
|
|
try {
|
|
|
|
|
frame = window.frameElement;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// ie11 fix
|
|
|
|
|
}
|
|
|
|
|
if (frame) {
|
|
|
|
|
this.iframeMode = true;
|
|
|
|
|
const dataWidgetAttr = frame.getAttribute('data-widget');
|
|
|
|
|
if (dataWidgetAttr && dataWidgetAttr.length) {
|
|
|
|
|
this.editWidgetInfo = JSON.parse(dataWidgetAttr);
|
|
|
|
|
this.widgetEditMode = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-10 13:00:29 +03:00
|
|
|
public getPredefinedFunctionsList(): Array<string> {
|
|
|
|
|
return predefinedFunctionsList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getPredefinedFunctionBody(func: string): string {
|
|
|
|
|
return predefinedFunctions[func];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getDefaultDatasource(dataKeySchema: any): Datasource {
|
|
|
|
|
const datasource = deepClone(this.defaultDatasource);
|
|
|
|
|
if (isDefined(dataKeySchema)) {
|
|
|
|
|
datasource.dataKeys[0].settings = this.generateObjectFromJsonSchema(dataKeySchema);
|
|
|
|
|
}
|
|
|
|
|
return datasource;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
private initDefaultAlarmDataKeys() {
|
|
|
|
|
for (let i = 0; i < defaultAlarmFields.length; i++) {
|
|
|
|
|
const name = defaultAlarmFields[i];
|
|
|
|
|
const dataKey: DataKey = {
|
|
|
|
|
name,
|
|
|
|
|
type: DataKeyType.alarm,
|
|
|
|
|
label: this.translate.instant(alarmFields[name].name),
|
|
|
|
|
color: this.getMaterialColor(i),
|
|
|
|
|
settings: {},
|
|
|
|
|
_hash: Math.random()
|
|
|
|
|
};
|
|
|
|
|
this.defaultAlarmDataKeys.push(dataKey);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getDefaultAlarmDataKeys(): Array<DataKey> {
|
|
|
|
|
if (!this.defaultAlarmDataKeys.length) {
|
|
|
|
|
this.initDefaultAlarmDataKeys();
|
|
|
|
|
}
|
|
|
|
|
return deepClone(this.defaultAlarmDataKeys);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-10 13:00:29 +03:00
|
|
|
public generateObjectFromJsonSchema(schema: any): any {
|
|
|
|
|
const obj = jsonSchemaDefaults(schema);
|
|
|
|
|
deleteNullProperties(obj);
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-05 21:15:40 +03:00
|
|
|
public processWidgetException(exception: any): ExceptionData {
|
2019-09-23 20:35:31 +03:00
|
|
|
const data = this.parseException(exception, -6);
|
2019-09-05 21:15:40 +03:00
|
|
|
if (this.widgetEditMode) {
|
|
|
|
|
const message: WindowMessage = {
|
|
|
|
|
type: 'widgetException',
|
|
|
|
|
data
|
|
|
|
|
};
|
2019-09-19 20:10:52 +03:00
|
|
|
this.window.parent.postMessage(JSON.stringify(message), '*');
|
2019-09-05 21:15:40 +03:00
|
|
|
}
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public parseException(exception: any, lineOffset?: number): ExceptionData {
|
|
|
|
|
const data: ExceptionData = {};
|
|
|
|
|
if (exception) {
|
|
|
|
|
if (typeof exception === 'string') {
|
|
|
|
|
data.message = exception;
|
|
|
|
|
} else if (exception instanceof String) {
|
|
|
|
|
data.message = exception.toString();
|
|
|
|
|
} else {
|
|
|
|
|
if (exception.name) {
|
|
|
|
|
data.name = exception.name;
|
|
|
|
|
} else {
|
|
|
|
|
data.name = 'UnknownError';
|
|
|
|
|
}
|
|
|
|
|
if (exception.message) {
|
|
|
|
|
data.message = exception.message;
|
|
|
|
|
}
|
|
|
|
|
if (exception.lineNumber) {
|
|
|
|
|
data.lineNumber = exception.lineNumber;
|
|
|
|
|
if (exception.columnNumber) {
|
|
|
|
|
data.columnNumber = exception.columnNumber;
|
|
|
|
|
}
|
|
|
|
|
} else if (exception.stack) {
|
|
|
|
|
const lineInfoRegexp = /(.*<anonymous>):(\d*)(:)?(\d*)?/g;
|
|
|
|
|
const lineInfoGroups = lineInfoRegexp.exec(exception.stack);
|
|
|
|
|
if (lineInfoGroups != null && lineInfoGroups.length >= 3) {
|
|
|
|
|
if (isUndefined(lineOffset)) {
|
|
|
|
|
lineOffset = -2;
|
|
|
|
|
}
|
|
|
|
|
data.lineNumber = Number(lineInfoGroups[2]) + lineOffset;
|
|
|
|
|
if (lineInfoGroups.length >= 5) {
|
|
|
|
|
data.columnNumber = Number(lineInfoGroups[4]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public customTranslation(translationValue: string, defaultValue: string): string {
|
2020-11-27 17:35:19 +02:00
|
|
|
if (translationValue && isString(translationValue)) {
|
|
|
|
|
if (translationValue.includes(`{${i18nPrefix}`)) {
|
|
|
|
|
const matches = translationValue.match(i18nRegExp);
|
|
|
|
|
let result = translationValue;
|
|
|
|
|
for (const match of matches) {
|
|
|
|
|
const translationId = match.substring(6, match.length - 1);
|
|
|
|
|
result = result.replace(match, this.doTranslate(translationId, match));
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
} else {
|
|
|
|
|
return this.doTranslate(translationValue, defaultValue, customTranslationsPrefix);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return translationValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private doTranslate(translationValue: string, defaultValue: string, prefix?: string): string {
|
2020-05-05 12:19:21 +03:00
|
|
|
let result: string;
|
2020-11-27 17:35:19 +02:00
|
|
|
let translationId;
|
|
|
|
|
if (prefix) {
|
|
|
|
|
translationId = prefix + translationValue;
|
|
|
|
|
} else {
|
|
|
|
|
translationId = translationValue;
|
|
|
|
|
}
|
2019-09-05 21:15:40 +03:00
|
|
|
const translation = this.translate.instant(translationId);
|
|
|
|
|
if (translation !== translationId) {
|
|
|
|
|
result = translation + '';
|
|
|
|
|
} else {
|
|
|
|
|
result = defaultValue;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-10 15:12:10 +03:00
|
|
|
public guid(): string {
|
2019-10-31 10:06:57 +02:00
|
|
|
return guid();
|
2019-09-10 15:12:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public validateDatasources(datasources: Array<Datasource>): Array<Datasource> {
|
|
|
|
|
datasources.forEach((datasource) => {
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
if (datasource.type === 'device') {
|
|
|
|
|
datasource.type = DatasourceType.entity;
|
|
|
|
|
datasource.entityType = EntityType.DEVICE;
|
|
|
|
|
if (datasource.deviceId) {
|
|
|
|
|
datasource.entityId = datasource.deviceId;
|
|
|
|
|
} else if (datasource.deviceAliasId) {
|
|
|
|
|
datasource.entityAliasId = datasource.deviceAliasId;
|
|
|
|
|
}
|
|
|
|
|
if (datasource.deviceName) {
|
|
|
|
|
datasource.entityName = datasource.deviceName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (datasource.type === DatasourceType.entity && datasource.entityId) {
|
|
|
|
|
datasource.name = datasource.entityName;
|
|
|
|
|
}
|
2020-06-30 19:37:50 +03:00
|
|
|
if (!datasource.dataKeys) {
|
|
|
|
|
datasource.dataKeys = [];
|
|
|
|
|
}
|
2019-09-10 15:12:10 +03:00
|
|
|
});
|
|
|
|
|
return datasources;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
public getMaterialIcons(): Observable<Array<string>> {
|
|
|
|
|
if (this.materialIcons.length) {
|
|
|
|
|
return of(this.materialIcons);
|
|
|
|
|
} else {
|
|
|
|
|
const materialIconsSubject = new ReplaySubject<Array<string>>();
|
|
|
|
|
this.zone.runOutsideAngular(() => {
|
|
|
|
|
const codepointsArray = materialIconsCodepoints
|
|
|
|
|
.split('\n')
|
|
|
|
|
.filter((codepoint) => codepoint && codepoint.length);
|
|
|
|
|
codepointsArray.forEach((codepoint) => {
|
2020-05-04 11:40:54 +03:00
|
|
|
const values = codepoint.split(' ');
|
|
|
|
|
if (values && values.length === 2) {
|
|
|
|
|
this.materialIcons.push(values[0]);
|
|
|
|
|
}
|
2019-10-24 19:52:19 +03:00
|
|
|
});
|
|
|
|
|
materialIconsSubject.next(this.materialIcons);
|
|
|
|
|
});
|
|
|
|
|
return materialIconsSubject.asObservable();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getCommonMaterialIcons(): Array<string> {
|
|
|
|
|
return commonMaterialIcons;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-10 13:00:29 +03:00
|
|
|
public getMaterialColor(index: number) {
|
2019-09-10 15:12:10 +03:00
|
|
|
const colorIndex = index % materialColors.length;
|
|
|
|
|
return materialColors[colorIndex].value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public createKey(keyInfo: KeyInfo, type: DataKeyType, index: number = -1): DataKey {
|
|
|
|
|
let label;
|
|
|
|
|
if (type === DataKeyType.alarm && !keyInfo.label) {
|
|
|
|
|
const alarmField = alarmFields[keyInfo.name];
|
|
|
|
|
if (alarmField) {
|
|
|
|
|
label = this.translate.instant(alarmField.name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!label) {
|
|
|
|
|
label = keyInfo.label || keyInfo.name;
|
|
|
|
|
}
|
|
|
|
|
const dataKey: DataKey = {
|
|
|
|
|
name: keyInfo.name,
|
|
|
|
|
type,
|
|
|
|
|
label,
|
|
|
|
|
funcBody: keyInfo.funcBody,
|
|
|
|
|
settings: {},
|
|
|
|
|
_hash: Math.random()
|
|
|
|
|
};
|
|
|
|
|
if (keyInfo.units) {
|
|
|
|
|
dataKey.units = keyInfo.units;
|
|
|
|
|
}
|
|
|
|
|
if (isDefined(keyInfo.decimals)) {
|
|
|
|
|
dataKey.decimals = keyInfo.decimals;
|
|
|
|
|
}
|
|
|
|
|
if (keyInfo.color) {
|
|
|
|
|
dataKey.color = keyInfo.color;
|
|
|
|
|
} else if (index > -1) {
|
|
|
|
|
dataKey.color = this.getMaterialColor(index);
|
|
|
|
|
}
|
|
|
|
|
if (keyInfo.postFuncBody && keyInfo.postFuncBody.length) {
|
|
|
|
|
dataKey.usePostProcessing = true;
|
|
|
|
|
dataKey.postFuncBody = keyInfo.postFuncBody;
|
|
|
|
|
}
|
|
|
|
|
return dataKey;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-24 18:07:47 +03:00
|
|
|
/* public createAdditionalDataKey(dataKey: DataKey, datasource: Datasource, timeUnit: string,
|
2020-05-04 11:40:54 +03:00
|
|
|
datasources: Datasource[], additionalKeysNumber: number): DataKey {
|
2020-02-24 17:16:02 +02:00
|
|
|
const additionalDataKey = deepClone(dataKey);
|
|
|
|
|
if (dataKey.settings.comparisonSettings.comparisonValuesLabel) {
|
2020-05-04 11:40:54 +03:00
|
|
|
additionalDataKey.label = createLabelFromDatasource(datasource, dataKey.settings.comparisonSettings.comparisonValuesLabel);
|
2020-02-24 17:16:02 +02:00
|
|
|
} else {
|
2020-05-04 11:40:54 +03:00
|
|
|
additionalDataKey.label = dataKey.label + ' ' + this.translate.instant('legend.comparison-time-ago.' + timeUnit);
|
2020-02-24 17:16:02 +02:00
|
|
|
}
|
|
|
|
|
additionalDataKey.pattern = additionalDataKey.label;
|
|
|
|
|
if (dataKey.settings.comparisonSettings.color) {
|
|
|
|
|
additionalDataKey.color = dataKey.settings.comparisonSettings.color;
|
|
|
|
|
} else {
|
|
|
|
|
const index = datasources.map((_datasource) => datasource.dataKeys.length)
|
|
|
|
|
.reduce((previousValue, currentValue) => previousValue + currentValue, 0);
|
|
|
|
|
additionalDataKey.color = this.getMaterialColor(index + additionalKeysNumber);
|
|
|
|
|
}
|
|
|
|
|
additionalDataKey._hash = Math.random();
|
|
|
|
|
return additionalDataKey;
|
2020-06-24 18:07:47 +03:00
|
|
|
}*/
|
2020-02-24 17:16:02 +02:00
|
|
|
|
2020-05-05 13:53:20 +03:00
|
|
|
public createLabelFromDatasource(datasource: Datasource, pattern: string): string {
|
|
|
|
|
return createLabelFromDatasource(datasource, pattern);
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-10 15:12:10 +03:00
|
|
|
public generateColors(datasources: Array<Datasource>) {
|
|
|
|
|
let index = 0;
|
|
|
|
|
datasources.forEach((datasource) => {
|
|
|
|
|
datasource.dataKeys.forEach((dataKey) => {
|
|
|
|
|
if (!dataKey.color) {
|
|
|
|
|
dataKey.color = this.getMaterialColor(index);
|
|
|
|
|
}
|
|
|
|
|
index++;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 19:58:42 +03:00
|
|
|
public currentPerfTime(): number {
|
|
|
|
|
return this.window.performance && this.window.performance.now ?
|
|
|
|
|
this.window.performance.now() : Date.now();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 12:22:14 +02:00
|
|
|
public getQueryParam(name: string): string {
|
|
|
|
|
const url = this.window.location.href;
|
|
|
|
|
name = name.replace(/[\[\]]/g, '\\$&');
|
|
|
|
|
const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
|
|
|
|
|
const results = regex.exec(url);
|
|
|
|
|
if (!results) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
if (!results[2]) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
return decodeURIComponent(results[2].replace(/\+/g, ' '));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 18:03:18 +03:00
|
|
|
public removeQueryParams(keys: Array<string>) {
|
|
|
|
|
let params = this.window.location.search;
|
|
|
|
|
for (const key of keys) {
|
|
|
|
|
params = this.updateUrlQueryString(params, key, null);
|
|
|
|
|
}
|
|
|
|
|
const baseUrlPart = [baseUrl(), this.window.location.pathname].join('');
|
|
|
|
|
this.window.history.replaceState({}, '', baseUrlPart + params);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 12:22:14 +02:00
|
|
|
public updateQueryParam(name: string, value: string | null) {
|
2020-11-27 18:21:12 +02:00
|
|
|
const baseUrlPart = [baseUrl(), this.window.location.pathname].join('');
|
2019-11-15 12:22:14 +02:00
|
|
|
const urlQueryString = this.window.location.search;
|
2021-05-11 18:03:18 +03:00
|
|
|
const params = this.updateUrlQueryString(urlQueryString, name, value);
|
|
|
|
|
this.window.history.replaceState({}, '', baseUrlPart + params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private updateUrlQueryString(urlQueryString: string, name: string, value: string | null): string {
|
2019-11-15 12:22:14 +02:00
|
|
|
let newParam = '';
|
|
|
|
|
let params = '';
|
|
|
|
|
if (value !== null) {
|
|
|
|
|
newParam = name + '=' + value;
|
|
|
|
|
}
|
|
|
|
|
if (urlQueryString) {
|
|
|
|
|
const keyRegex = new RegExp('([\?&])' + name + '[^&]*');
|
|
|
|
|
if (urlQueryString.match(keyRegex) !== null) {
|
|
|
|
|
if (newParam) {
|
|
|
|
|
newParam = '$1' + newParam;
|
|
|
|
|
}
|
|
|
|
|
params = urlQueryString.replace(keyRegex, newParam);
|
2021-05-11 18:03:18 +03:00
|
|
|
if (params.startsWith('&')) {
|
|
|
|
|
params = '?' + params.substring(1);
|
|
|
|
|
}
|
2019-11-15 12:22:14 +02:00
|
|
|
} else if (newParam) {
|
|
|
|
|
params = urlQueryString + '&' + newParam;
|
|
|
|
|
}
|
|
|
|
|
} else if (newParam) {
|
2020-05-04 11:40:54 +03:00
|
|
|
params = '?' + newParam;
|
2019-11-15 12:22:14 +02:00
|
|
|
}
|
2021-05-11 18:03:18 +03:00
|
|
|
return params;
|
2020-11-27 18:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public baseUrl(): string {
|
|
|
|
|
return baseUrl();
|
2019-11-15 12:22:14 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-10 13:04:56 +02:00
|
|
|
public deepClone<T>(target: T, ignoreFields?: string[]): T {
|
|
|
|
|
return deepClone(target, ignoreFields);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public isUndefined(value: any): boolean {
|
|
|
|
|
return isUndefined(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public isDefined(value: any): boolean {
|
|
|
|
|
return isDefined(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public defaultValue(value: any, defaultValue: any): any {
|
|
|
|
|
if (isDefinedAndNotNull(value)) {
|
|
|
|
|
return value;
|
|
|
|
|
} else {
|
|
|
|
|
return defaultValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-05 21:15:40 +03:00
|
|
|
}
|