Commit 86a991162f31ea9ae66f726235d673398271a2f4

Authored by Vladyslav_Prykhodko
1 parent 8e3c3990

Improvment encode-state params for dashboard

... ... @@ -35,13 +35,11 @@
35 35 "@ngrx/effects": "^10.0.0",
36 36 "@ngrx/store": "^10.0.0",
37 37 "@ngrx/store-devtools": "^10.0.0",
38   - "ngx-sharebuttons": "^8.0.1",
39 38 "@ngx-translate/core": "^13.0.0",
40 39 "@ngx-translate/http-loader": "^6.0.0",
41 40 "ace-builds": "^1.4.12",
42 41 "angular-gridster2": "^10.1.3",
43 42 "angular2-hotkeys": "^2.2.0",
44   - "base64-js": "^1.3.1",
45 43 "canvas-gauges": "^2.1.7",
46 44 "compass-sass-mixins": "^0.12.7",
47 45 "core-js": "^3.6.5",
... ... @@ -70,6 +68,7 @@
70 68 "ngx-daterangepicker-material": "^3.0.4",
71 69 "ngx-flowchart": "git://github.com/thingsboard/ngx-flowchart.git#master",
72 70 "ngx-hm-carousel": "^2.0.0-rc.1",
  71 + "ngx-sharebuttons": "^8.0.1",
73 72 "ngx-translate-messageformat-compiler": "^4.8.0",
74 73 "objectpath": "^2.0.0",
75 74 "prettier": "^2.0.5",
... ...
... ... @@ -26,7 +26,6 @@ import {
26 26 import { DOCUMENT } from '@angular/common';
27 27 import { forkJoin, Observable, ReplaySubject, throwError } from 'rxjs';
28 28 import { HttpClient } from '@angular/common/http';
29   -import { objToBase64 } from '@core/utils';
30 29
31 30 declare const SystemJS;
32 31
... ...
... ... @@ -17,7 +17,6 @@
17 17 import _ from 'lodash';
18 18 import { Observable, Subject } from 'rxjs';
19 19 import { finalize, share } from 'rxjs/operators';
20   -import base64js from 'base64-js';
21 20 import { Datasource } from '@app/shared/models/widget.models';
22 21
23 22 const varsRegex = /\${([^}]*)}/g;
... ... @@ -123,7 +122,8 @@ export function isEmpty(obj: any): boolean {
123 122 }
124 123
125 124 export function formatValue(value: any, dec?: number, units?: string, showZeroDecimals?: boolean): string | undefined {
126   - if (isDefinedAndNotNull(value) && isNumeric(value) && (isDefinedAndNotNull(dec) || isDefinedAndNotNull(units) || Number(value).toString() === value)) {
  125 + if (isDefinedAndNotNull(value) && isNumeric(value) &&
  126 + (isDefinedAndNotNull(dec) || isDefinedAndNotNull(units) || Number(value).toString() === value)) {
127 127 let formatted: string | number = Number(value);
128 128 if (isDefinedAndNotNull(dec)) {
129 129 formatted = formatted.toFixed(dec);
... ... @@ -164,28 +164,21 @@ export function deleteNullProperties(obj: any) {
164 164
165 165 export function objToBase64(obj: any): string {
166 166 const json = JSON.stringify(obj);
167   - const encoded = utf8Encode(json);
168   - return base64js.fromByteArray(encoded);
  167 + return btoa(encodeURIComponent(json).replace(/%([0-9A-F]{2})/g,
  168 + function toSolidBytes(match, p1) {
  169 + return String.fromCharCode(Number('0x' + p1));
  170 + }));
169 171 }
170 172
171   -export function base64toObj(b64Encoded: string): any {
172   - const encoded: Uint8Array | number[] = base64js.toByteArray(b64Encoded);
173   - const json = utf8Decode(encoded);
174   - return JSON.parse(json);
175   -}
176   -
177   -function utf8Encode(str: string): Uint8Array | number[] {
178   - let result: Uint8Array | number[];
179   - if (isUndefined(Uint8Array)) {
180   - result = utf8ToBytes(str);
181   - } else {
182   - result = new Uint8Array(utf8ToBytes(str));
183   - }
184   - return result;
  173 +export function objToBase64URI(obj: any): string {
  174 + return encodeURIComponent(objToBase64(obj));
185 175 }
186 176
187   -function utf8Decode(bytes: Uint8Array | number[]): string {
188   - return utf8Slice(bytes, 0, bytes.length);
  177 +export function base64toObj(b64Encoded: string): any {
  178 + const json = decodeURIComponent(atob(b64Encoded).split('').map((c) => {
  179 + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
  180 + }).join(''));
  181 + return JSON.parse(json);
189 182 }
190 183
191 184 const scrollRegex = /(auto|scroll)/;
... ... @@ -275,129 +268,6 @@ function easeInOut(
275 268 );
276 269 }
277 270
278   -function utf8Slice(buf: Uint8Array | number[], start: number, end: number): string {
279   - let res = '';
280   - let tmp = '';
281   - end = Math.min(buf.length, end || Infinity);
282   - start = start || 0;
283   -
284   - for (let i = start; i < end; i++) {
285   - if (buf[i] <= 0x7F) {
286   - res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]);
287   - tmp = '';
288   - } else {
289   - tmp += '%' + buf[i].toString(16);
290   - }
291   - }
292   - return res + decodeUtf8Char(tmp);
293   -}
294   -
295   -function decodeUtf8Char(str: string): string {
296   - try {
297   - return decodeURIComponent(str);
298   - } catch (err) {
299   - return String.fromCharCode(0xFFFD); // UTF 8 invalid char
300   - }
301   -}
302   -
303   -function utf8ToBytes(input: string, units?: number): number[] {
304   - units = units || Infinity;
305   - let codePoint: number;
306   - const length = input.length;
307   - let leadSurrogate: number = null;
308   - const bytes: number[] = [];
309   - let i = 0;
310   -
311   - for (; i < length; i++) {
312   - codePoint = input.charCodeAt(i);
313   -
314   - // is surrogate component
315   - if (codePoint > 0xD7FF && codePoint < 0xE000) {
316   - // last char was a lead
317   - if (leadSurrogate) {
318   - // 2 leads in a row
319   - if (codePoint < 0xDC00) {
320   - units -= 3;
321   - if (units > -1) { bytes.push(0xEF, 0xBF, 0xBD); }
322   - leadSurrogate = codePoint;
323   - continue;
324   - } else {
325   - // valid surrogate pair
326   - // tslint:disable-next-line:no-bitwise
327   - codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000;
328   - leadSurrogate = null;
329   - }
330   - } else {
331   - // no lead yet
332   -
333   - if (codePoint > 0xDBFF) {
334   - // unexpected trail
335   - units -= 3;
336   - if (units > -1) { bytes.push(0xEF, 0xBF, 0xBD); }
337   - continue;
338   - } else if (i + 1 === length) {
339   - // unpaired lead
340   - units -= 3;
341   - if (units > -1) { bytes.push(0xEF, 0xBF, 0xBD); }
342   - continue;
343   - } else {
344   - // valid lead
345   - leadSurrogate = codePoint;
346   - continue;
347   - }
348   - }
349   - } else if (leadSurrogate) {
350   - // valid bmp char, but last char was a lead
351   - units -= 3;
352   - if (units > -1) { bytes.push(0xEF, 0xBF, 0xBD); }
353   - leadSurrogate = null;
354   - }
355   -
356   - // encode utf8
357   - if (codePoint < 0x80) {
358   - units -= 1;
359   - if (units < 0) { break; }
360   - bytes.push(codePoint);
361   - } else if (codePoint < 0x800) {
362   - units -= 2;
363   - if (units < 0) { break; }
364   - bytes.push(
365   - // tslint:disable-next-line:no-bitwise
366   - codePoint >> 0x6 | 0xC0,
367   - // tslint:disable-next-line:no-bitwise
368   - codePoint & 0x3F | 0x80
369   - );
370   - } else if (codePoint < 0x10000) {
371   - units -= 3;
372   - if (units < 0) { break; }
373   - bytes.push(
374   - // tslint:disable-next-line:no-bitwise
375   - codePoint >> 0xC | 0xE0,
376   - // tslint:disable-next-line:no-bitwise
377   - codePoint >> 0x6 & 0x3F | 0x80,
378   - // tslint:disable-next-line:no-bitwise
379   - codePoint & 0x3F | 0x80
380   - );
381   - } else if (codePoint < 0x200000) {
382   - units -= 4;
383   - if (units < 0) { break; }
384   - bytes.push(
385   - // tslint:disable-next-line:no-bitwise
386   - codePoint >> 0x12 | 0xF0,
387   - // tslint:disable-next-line:no-bitwise
388   - codePoint >> 0xC & 0x3F | 0x80,
389   - // tslint:disable-next-line:no-bitwise
390   - codePoint >> 0x6 & 0x3F | 0x80,
391   - // tslint:disable-next-line:no-bitwise
392   - codePoint & 0x3F | 0x80
393   - );
394   - } else {
395   - throw new Error('Invalid code point');
396   - }
397   - }
398   - return bytes;
399   -}
400   -
401 271 export function deepClone<T>(target: T, ignoreFields?: string[]): T {
402 272 if (target === null) {
403 273 return target;
... ...
... ... @@ -24,7 +24,7 @@ import { Router } from '@angular/router';
24 24 import { DialogComponent } from '@app/shared/components/dialog.component';
25 25 import { UtilsService } from '@core/services/utils.service';
26 26 import { Dashboard, DashboardLayoutId } from '@app/shared/models/dashboard.models';
27   -import { objToBase64 } from '@core/utils';
  27 +import { objToBase64URI } from '@core/utils';
28 28 import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
29 29 import { EntityId } from '@app/shared/models/id/entity-id';
30 30 import { Widget } from '@app/shared/models/widget.models';
... ... @@ -205,7 +205,7 @@ export class AddWidgetToDashboardDialogComponent extends
205 205 id: targetState,
206 206 params: {}
207 207 };
208   - const state = objToBase64([ stateObject ]);
  208 + const state = objToBase64URI([ stateObject ]);
209 209 url = `/dashboards/${theDashboard.id.id}?state=${state}`;
210 210 } else {
211 211 url = `/dashboards/${theDashboard.id.id}`;
... ...
... ... @@ -35,7 +35,6 @@ import {
35 35 } from '@angular/core';
36 36 import { DashboardWidget } from '@home/models/dashboard-component.models';
37 37 import {
38   - Datasource,
39 38 defaultLegendConfig,
40 39 LegendConfig,
41 40 LegendData,
... ... @@ -55,7 +54,7 @@ import { AppState } from '@core/core.state';
55 54 import { WidgetService } from '@core/http/widget.service';
56 55 import { UtilsService } from '@core/services/utils.service';
57 56 import { forkJoin, Observable, of, ReplaySubject, Subscription, throwError } from 'rxjs';
58   -import { deepClone, isDefined, objToBase64 } from '@core/utils';
  57 +import { deepClone, isDefined, objToBase64URI } from '@core/utils';
59 58 import {
60 59 IDynamicWidgetComponent,
61 60 WidgetContext,
... ... @@ -68,7 +67,8 @@ import {
68 67 StateObject,
69 68 StateParams,
70 69 SubscriptionEntityInfo,
71   - SubscriptionInfo, SubscriptionMessage,
  70 + SubscriptionInfo,
  71 + SubscriptionMessage,
72 72 WidgetSubscriptionContext,
73 73 WidgetSubscriptionOptions
74 74 } from '@core/api/widget-api.models';
... ... @@ -80,11 +80,9 @@ import { catchError, switchMap } from 'rxjs/operators';
80 80 import { ActionNotificationShow } from '@core/notification/notification.actions';
81 81 import { TimeService } from '@core/services/time.service';
82 82 import { DeviceService } from '@app/core/http/device.service';
83   -import { AlarmService } from '@app/core/http/alarm.service';
84 83 import { ExceptionData } from '@shared/models/error.models';
85 84 import { WidgetComponentService } from './widget-component.service';
86 85 import { Timewindow } from '@shared/models/time/time.models';
87   -import { AlarmSearchStatus } from '@shared/models/alarm.models';
88 86 import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
89 87 import { DashboardService } from '@core/http/dashboard.service';
90 88 import { WidgetSubscription } from '@core/api/widget-subscription';
... ... @@ -688,7 +686,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
688 686
689 687 private destroyDynamicWidgetComponent() {
690 688 if (this.widgetContext.$containerParent && this.widgetResize$) {
691   - this.widgetResize$.disconnect()
  689 + this.widgetResize$.disconnect();
692 690 }
693 691 if (this.dynamicWidgetComponentRef) {
694 692 this.dynamicWidgetComponentRef.destroy();
... ... @@ -1023,7 +1021,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
1023 1021 if (targetDashboardStateId) {
1024 1022 stateObject.id = targetDashboardStateId;
1025 1023 }
1026   - const state = objToBase64([ stateObject ]);
  1024 + const state = objToBase64URI([ stateObject ]);
1027 1025 const isSinglePage = this.route.snapshot.data.singlePageMode;
1028 1026 let url;
1029 1027 if (isSinglePage) {
... ...
... ... @@ -23,7 +23,7 @@ import { StateControllerComponent } from './state-controller.component';
23 23 import { StatesControllerService } from '@home/pages/dashboard/states/states-controller.service';
24 24 import { EntityId } from '@app/shared/models/id/entity-id';
25 25 import { UtilsService } from '@core/services/utils.service';
26   -import { base64toObj, objToBase64 } from '@app/core/utils';
  26 +import { base64toObj, objToBase64URI } from '@app/core/utils';
27 27 import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
28 28 import { EntityService } from '@core/http/entity.service';
29 29
... ... @@ -237,7 +237,7 @@ export class DefaultStateControllerComponent extends StateControllerComponent im
237 237
238 238 private updateLocation() {
239 239 if (this.stateObject[0].id) {
240   - const newState = objToBase64(this.stateObject);
  240 + const newState = objToBase64URI(this.stateObject);
241 241 this.updateStateParam(newState);
242 242 }
243 243 }
... ...
... ... @@ -23,7 +23,7 @@ import { StateControllerComponent } from './state-controller.component';
23 23 import { StatesControllerService } from '@home/pages/dashboard/states/states-controller.service';
24 24 import { EntityId } from '@app/shared/models/id/entity-id';
25 25 import { UtilsService } from '@core/services/utils.service';
26   -import { base64toObj, insertVariable, isEmpty, objToBase64 } from '@app/core/utils';
  26 +import { base64toObj, insertVariable, isEmpty, objToBase64URI } from '@app/core/utils';
27 27 import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
28 28 import { EntityService } from '@core/http/entity.service';
29 29 import { EntityType } from '@shared/models/entity-type.models';
... ... @@ -281,7 +281,7 @@ export class EntityStateControllerComponent extends StateControllerComponent imp
281 281 if (this.isDefaultState()) {
282 282 newState = null;
283 283 } else {
284   - newState = objToBase64(this.stateObject);
  284 + newState = objToBase64URI(this.stateObject);
285 285 }
286 286 this.updateStateParam(newState);
287 287 }
... ...
... ... @@ -2138,7 +2138,7 @@ base64-arraybuffer@0.1.5:
2138 2138 resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
2139 2139 integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
2140 2140
2141   -base64-js@^1.0.2, base64-js@^1.3.1:
  2141 +base64-js@^1.0.2:
2142 2142 version "1.3.1"
2143 2143 resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
2144 2144 integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
... ...