Merge pull request #3353 from vvlladd28/feature/encode-state-params
Improvment encode-state params for dashboard
This commit is contained in:
commit
e3dcc96913
@ -35,13 +35,11 @@
|
||||
"@ngrx/effects": "^10.0.0",
|
||||
"@ngrx/store": "^10.0.0",
|
||||
"@ngrx/store-devtools": "^10.0.0",
|
||||
"ngx-sharebuttons": "^8.0.1",
|
||||
"@ngx-translate/core": "^13.0.0",
|
||||
"@ngx-translate/http-loader": "^6.0.0",
|
||||
"ace-builds": "^1.4.12",
|
||||
"angular-gridster2": "^10.1.3",
|
||||
"angular2-hotkeys": "^2.2.0",
|
||||
"base64-js": "^1.3.1",
|
||||
"canvas-gauges": "^2.1.7",
|
||||
"compass-sass-mixins": "^0.12.7",
|
||||
"core-js": "^3.6.5",
|
||||
@ -70,6 +68,7 @@
|
||||
"ngx-daterangepicker-material": "^3.0.4",
|
||||
"ngx-flowchart": "git://github.com/thingsboard/ngx-flowchart.git#master",
|
||||
"ngx-hm-carousel": "^2.0.0-rc.1",
|
||||
"ngx-sharebuttons": "^8.0.1",
|
||||
"ngx-translate-messageformat-compiler": "^4.8.0",
|
||||
"objectpath": "^2.0.0",
|
||||
"prettier": "^2.0.5",
|
||||
|
||||
@ -26,7 +26,6 @@ import {
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { forkJoin, Observable, ReplaySubject, throwError } from 'rxjs';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { objToBase64 } from '@core/utils';
|
||||
|
||||
declare const SystemJS;
|
||||
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
import _ from 'lodash';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { finalize, share } from 'rxjs/operators';
|
||||
import base64js from 'base64-js';
|
||||
import { Datasource } from '@app/shared/models/widget.models';
|
||||
|
||||
const varsRegex = /\${([^}]*)}/g;
|
||||
@ -123,7 +122,8 @@ export function isEmpty(obj: any): boolean {
|
||||
}
|
||||
|
||||
export function formatValue(value: any, dec?: number, units?: string, showZeroDecimals?: boolean): string | undefined {
|
||||
if (isDefinedAndNotNull(value) && isNumeric(value) && (isDefinedAndNotNull(dec) || isDefinedAndNotNull(units) || Number(value).toString() === value)) {
|
||||
if (isDefinedAndNotNull(value) && isNumeric(value) &&
|
||||
(isDefinedAndNotNull(dec) || isDefinedAndNotNull(units) || Number(value).toString() === value)) {
|
||||
let formatted: string | number = Number(value);
|
||||
if (isDefinedAndNotNull(dec)) {
|
||||
formatted = formatted.toFixed(dec);
|
||||
@ -164,30 +164,23 @@ export function deleteNullProperties(obj: any) {
|
||||
|
||||
export function objToBase64(obj: any): string {
|
||||
const json = JSON.stringify(obj);
|
||||
const encoded = utf8Encode(json);
|
||||
return base64js.fromByteArray(encoded);
|
||||
return btoa(encodeURIComponent(json).replace(/%([0-9A-F]{2})/g,
|
||||
function toSolidBytes(match, p1) {
|
||||
return String.fromCharCode(Number('0x' + p1));
|
||||
}));
|
||||
}
|
||||
|
||||
export function objToBase64URI(obj: any): string {
|
||||
return encodeURIComponent(objToBase64(obj));
|
||||
}
|
||||
|
||||
export function base64toObj(b64Encoded: string): any {
|
||||
const encoded: Uint8Array | number[] = base64js.toByteArray(b64Encoded);
|
||||
const json = utf8Decode(encoded);
|
||||
const json = decodeURIComponent(atob(b64Encoded).split('').map((c) => {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
}).join(''));
|
||||
return JSON.parse(json);
|
||||
}
|
||||
|
||||
function utf8Encode(str: string): Uint8Array | number[] {
|
||||
let result: Uint8Array | number[];
|
||||
if (isUndefined(Uint8Array)) {
|
||||
result = utf8ToBytes(str);
|
||||
} else {
|
||||
result = new Uint8Array(utf8ToBytes(str));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function utf8Decode(bytes: Uint8Array | number[]): string {
|
||||
return utf8Slice(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
const scrollRegex = /(auto|scroll)/;
|
||||
|
||||
function parentNodes(node: Node, nodes: Node[]): Node[] {
|
||||
@ -275,129 +268,6 @@ function easeInOut(
|
||||
);
|
||||
}
|
||||
|
||||
function utf8Slice(buf: Uint8Array | number[], start: number, end: number): string {
|
||||
let res = '';
|
||||
let tmp = '';
|
||||
end = Math.min(buf.length, end || Infinity);
|
||||
start = start || 0;
|
||||
|
||||
for (let i = start; i < end; i++) {
|
||||
if (buf[i] <= 0x7F) {
|
||||
res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]);
|
||||
tmp = '';
|
||||
} else {
|
||||
tmp += '%' + buf[i].toString(16);
|
||||
}
|
||||
}
|
||||
return res + decodeUtf8Char(tmp);
|
||||
}
|
||||
|
||||
function decodeUtf8Char(str: string): string {
|
||||
try {
|
||||
return decodeURIComponent(str);
|
||||
} catch (err) {
|
||||
return String.fromCharCode(0xFFFD); // UTF 8 invalid char
|
||||
}
|
||||
}
|
||||
|
||||
function utf8ToBytes(input: string, units?: number): number[] {
|
||||
units = units || Infinity;
|
||||
let codePoint: number;
|
||||
const length = input.length;
|
||||
let leadSurrogate: number = null;
|
||||
const bytes: number[] = [];
|
||||
let i = 0;
|
||||
|
||||
for (; i < length; i++) {
|
||||
codePoint = input.charCodeAt(i);
|
||||
|
||||
// is surrogate component
|
||||
if (codePoint > 0xD7FF && codePoint < 0xE000) {
|
||||
// last char was a lead
|
||||
if (leadSurrogate) {
|
||||
// 2 leads in a row
|
||||
if (codePoint < 0xDC00) {
|
||||
units -= 3;
|
||||
if (units > -1) { bytes.push(0xEF, 0xBF, 0xBD); }
|
||||
leadSurrogate = codePoint;
|
||||
continue;
|
||||
} else {
|
||||
// valid surrogate pair
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000;
|
||||
leadSurrogate = null;
|
||||
}
|
||||
} else {
|
||||
// no lead yet
|
||||
|
||||
if (codePoint > 0xDBFF) {
|
||||
// unexpected trail
|
||||
units -= 3;
|
||||
if (units > -1) { bytes.push(0xEF, 0xBF, 0xBD); }
|
||||
continue;
|
||||
} else if (i + 1 === length) {
|
||||
// unpaired lead
|
||||
units -= 3;
|
||||
if (units > -1) { bytes.push(0xEF, 0xBF, 0xBD); }
|
||||
continue;
|
||||
} else {
|
||||
// valid lead
|
||||
leadSurrogate = codePoint;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (leadSurrogate) {
|
||||
// valid bmp char, but last char was a lead
|
||||
units -= 3;
|
||||
if (units > -1) { bytes.push(0xEF, 0xBF, 0xBD); }
|
||||
leadSurrogate = null;
|
||||
}
|
||||
|
||||
// encode utf8
|
||||
if (codePoint < 0x80) {
|
||||
units -= 1;
|
||||
if (units < 0) { break; }
|
||||
bytes.push(codePoint);
|
||||
} else if (codePoint < 0x800) {
|
||||
units -= 2;
|
||||
if (units < 0) { break; }
|
||||
bytes.push(
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint >> 0x6 | 0xC0,
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint & 0x3F | 0x80
|
||||
);
|
||||
} else if (codePoint < 0x10000) {
|
||||
units -= 3;
|
||||
if (units < 0) { break; }
|
||||
bytes.push(
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint >> 0xC | 0xE0,
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint >> 0x6 & 0x3F | 0x80,
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint & 0x3F | 0x80
|
||||
);
|
||||
} else if (codePoint < 0x200000) {
|
||||
units -= 4;
|
||||
if (units < 0) { break; }
|
||||
bytes.push(
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint >> 0x12 | 0xF0,
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint >> 0xC & 0x3F | 0x80,
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint >> 0x6 & 0x3F | 0x80,
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
codePoint & 0x3F | 0x80
|
||||
);
|
||||
} else {
|
||||
throw new Error('Invalid code point');
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export function deepClone<T>(target: T, ignoreFields?: string[]): T {
|
||||
if (target === null) {
|
||||
return target;
|
||||
|
||||
@ -24,7 +24,7 @@ import { Router } from '@angular/router';
|
||||
import { DialogComponent } from '@app/shared/components/dialog.component';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { Dashboard, DashboardLayoutId } from '@app/shared/models/dashboard.models';
|
||||
import { objToBase64 } from '@core/utils';
|
||||
import { objToBase64URI } from '@core/utils';
|
||||
import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
|
||||
import { EntityId } from '@app/shared/models/id/entity-id';
|
||||
import { Widget } from '@app/shared/models/widget.models';
|
||||
@ -205,7 +205,7 @@ export class AddWidgetToDashboardDialogComponent extends
|
||||
id: targetState,
|
||||
params: {}
|
||||
};
|
||||
const state = objToBase64([ stateObject ]);
|
||||
const state = objToBase64URI([ stateObject ]);
|
||||
url = `/dashboards/${theDashboard.id.id}?state=${state}`;
|
||||
} else {
|
||||
url = `/dashboards/${theDashboard.id.id}`;
|
||||
|
||||
@ -35,7 +35,6 @@ import {
|
||||
} from '@angular/core';
|
||||
import { DashboardWidget } from '@home/models/dashboard-component.models';
|
||||
import {
|
||||
Datasource,
|
||||
defaultLegendConfig,
|
||||
LegendConfig,
|
||||
LegendData,
|
||||
@ -55,7 +54,7 @@ import { AppState } from '@core/core.state';
|
||||
import { WidgetService } from '@core/http/widget.service';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { forkJoin, Observable, of, ReplaySubject, Subscription, throwError } from 'rxjs';
|
||||
import { deepClone, isDefined, objToBase64 } from '@core/utils';
|
||||
import { deepClone, isDefined, objToBase64URI } from '@core/utils';
|
||||
import {
|
||||
IDynamicWidgetComponent,
|
||||
WidgetContext,
|
||||
@ -68,7 +67,8 @@ import {
|
||||
StateObject,
|
||||
StateParams,
|
||||
SubscriptionEntityInfo,
|
||||
SubscriptionInfo, SubscriptionMessage,
|
||||
SubscriptionInfo,
|
||||
SubscriptionMessage,
|
||||
WidgetSubscriptionContext,
|
||||
WidgetSubscriptionOptions
|
||||
} from '@core/api/widget-api.models';
|
||||
@ -80,11 +80,9 @@ import { catchError, switchMap } from 'rxjs/operators';
|
||||
import { ActionNotificationShow } from '@core/notification/notification.actions';
|
||||
import { TimeService } from '@core/services/time.service';
|
||||
import { DeviceService } from '@app/core/http/device.service';
|
||||
import { AlarmService } from '@app/core/http/alarm.service';
|
||||
import { ExceptionData } from '@shared/models/error.models';
|
||||
import { WidgetComponentService } from './widget-component.service';
|
||||
import { Timewindow } from '@shared/models/time/time.models';
|
||||
import { AlarmSearchStatus } from '@shared/models/alarm.models';
|
||||
import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
|
||||
import { DashboardService } from '@core/http/dashboard.service';
|
||||
import { WidgetSubscription } from '@core/api/widget-subscription';
|
||||
@ -688,7 +686,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
||||
|
||||
private destroyDynamicWidgetComponent() {
|
||||
if (this.widgetContext.$containerParent && this.widgetResize$) {
|
||||
this.widgetResize$.disconnect()
|
||||
this.widgetResize$.disconnect();
|
||||
}
|
||||
if (this.dynamicWidgetComponentRef) {
|
||||
this.dynamicWidgetComponentRef.destroy();
|
||||
@ -1023,7 +1021,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
||||
if (targetDashboardStateId) {
|
||||
stateObject.id = targetDashboardStateId;
|
||||
}
|
||||
const state = objToBase64([ stateObject ]);
|
||||
const state = objToBase64URI([ stateObject ]);
|
||||
const isSinglePage = this.route.snapshot.data.singlePageMode;
|
||||
let url;
|
||||
if (isSinglePage) {
|
||||
|
||||
@ -23,7 +23,7 @@ import { StateControllerComponent } from './state-controller.component';
|
||||
import { StatesControllerService } from '@home/pages/dashboard/states/states-controller.service';
|
||||
import { EntityId } from '@app/shared/models/id/entity-id';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { base64toObj, objToBase64 } from '@app/core/utils';
|
||||
import { base64toObj, objToBase64URI } from '@app/core/utils';
|
||||
import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
|
||||
import { EntityService } from '@core/http/entity.service';
|
||||
|
||||
@ -237,7 +237,7 @@ export class DefaultStateControllerComponent extends StateControllerComponent im
|
||||
|
||||
private updateLocation() {
|
||||
if (this.stateObject[0].id) {
|
||||
const newState = objToBase64(this.stateObject);
|
||||
const newState = objToBase64URI(this.stateObject);
|
||||
this.updateStateParam(newState);
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ import { StateControllerComponent } from './state-controller.component';
|
||||
import { StatesControllerService } from '@home/pages/dashboard/states/states-controller.service';
|
||||
import { EntityId } from '@app/shared/models/id/entity-id';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { base64toObj, insertVariable, isEmpty, objToBase64 } from '@app/core/utils';
|
||||
import { base64toObj, insertVariable, isEmpty, objToBase64URI } from '@app/core/utils';
|
||||
import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
|
||||
import { EntityService } from '@core/http/entity.service';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
@ -281,7 +281,7 @@ export class EntityStateControllerComponent extends StateControllerComponent imp
|
||||
if (this.isDefaultState()) {
|
||||
newState = null;
|
||||
} else {
|
||||
newState = objToBase64(this.stateObject);
|
||||
newState = objToBase64URI(this.stateObject);
|
||||
}
|
||||
this.updateStateParam(newState);
|
||||
}
|
||||
|
||||
@ -2138,7 +2138,7 @@ base64-arraybuffer@0.1.5:
|
||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
|
||||
integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
|
||||
|
||||
base64-js@^1.0.2, base64-js@^1.3.1:
|
||||
base64-js@^1.0.2:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user