TB-70: Keep dashboard state as base64 url parameter.
This commit is contained in:
parent
81ccdf7bfa
commit
87c2574acd
@ -45,6 +45,7 @@
|
|||||||
"angular-ui-ace": "^0.2.3",
|
"angular-ui-ace": "^0.2.3",
|
||||||
"angular-ui-router": "^0.3.1",
|
"angular-ui-router": "^0.3.1",
|
||||||
"angular-websocket": "^2.0.1",
|
"angular-websocket": "^2.0.1",
|
||||||
|
"base64-js": "^1.2.1",
|
||||||
"brace": "^0.8.0",
|
"brace": "^0.8.0",
|
||||||
"canvas-gauges": "^2.0.9",
|
"canvas-gauges": "^2.0.9",
|
||||||
"clipboard": "^1.5.15",
|
"clipboard": "^1.5.15",
|
||||||
|
|||||||
138
ui/src/app/common/utf8-support.js
Normal file
138
ui/src/app/common/utf8-support.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2016-2017 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function utf8Encode(str) {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
if (angular.isUndefined(Uint8Array)) { // eslint-disable-line no-undef
|
||||||
|
result = utf8ToBytes(str);
|
||||||
|
} else {
|
||||||
|
result = new Uint8Array(utf8ToBytes(str)); // eslint-disable-line no-undef
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function utf8Decode(bytes) {
|
||||||
|
return utf8Slice(bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function utf8Slice (buf, start, end) {
|
||||||
|
var res = ''
|
||||||
|
var tmp = ''
|
||||||
|
end = Math.min(buf.length, end || Infinity)
|
||||||
|
start = start || 0;
|
||||||
|
|
||||||
|
for (var 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) {
|
||||||
|
try {
|
||||||
|
return decodeURIComponent(str)
|
||||||
|
} catch (err) {
|
||||||
|
return String.fromCharCode(0xFFFD) // UTF 8 invalid char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function utf8ToBytes (string, units) {
|
||||||
|
units = units || Infinity
|
||||||
|
var codePoint
|
||||||
|
var length = string.length
|
||||||
|
var leadSurrogate = null
|
||||||
|
var bytes = []
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
for (; i < length; i++) {
|
||||||
|
codePoint = string.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) {
|
||||||
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
||||||
|
leadSurrogate = codePoint
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
// valid surrogate pair
|
||||||
|
codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
|
||||||
|
leadSurrogate = null
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no lead yet
|
||||||
|
|
||||||
|
if (codePoint > 0xDBFF) {
|
||||||
|
// unexpected trail
|
||||||
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
||||||
|
continue
|
||||||
|
} else if (i + 1 === length) {
|
||||||
|
// unpaired lead
|
||||||
|
if ((units -= 3) > -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
|
||||||
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
||||||
|
leadSurrogate = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode utf8
|
||||||
|
if (codePoint < 0x80) {
|
||||||
|
if ((units -= 1) < 0) break
|
||||||
|
bytes.push(codePoint)
|
||||||
|
} else if (codePoint < 0x800) {
|
||||||
|
if ((units -= 2) < 0) break
|
||||||
|
bytes.push(
|
||||||
|
codePoint >> 0x6 | 0xC0,
|
||||||
|
codePoint & 0x3F | 0x80
|
||||||
|
)
|
||||||
|
} else if (codePoint < 0x10000) {
|
||||||
|
if ((units -= 3) < 0) break
|
||||||
|
bytes.push(
|
||||||
|
codePoint >> 0xC | 0xE0,
|
||||||
|
codePoint >> 0x6 & 0x3F | 0x80,
|
||||||
|
codePoint & 0x3F | 0x80
|
||||||
|
)
|
||||||
|
} else if (codePoint < 0x200000) {
|
||||||
|
if ((units -= 4) < 0) break
|
||||||
|
bytes.push(
|
||||||
|
codePoint >> 0x12 | 0xF0,
|
||||||
|
codePoint >> 0xC & 0x3F | 0x80,
|
||||||
|
codePoint >> 0x6 & 0x3F | 0x80,
|
||||||
|
codePoint & 0x3F | 0x80
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid code point')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes
|
||||||
|
}
|
||||||
@ -20,9 +20,12 @@ import materialIconsCodepoints from 'raw-loader!material-design-icons/iconfont/c
|
|||||||
|
|
||||||
/* eslint-enable import/no-unresolved, import/default */
|
/* eslint-enable import/no-unresolved, import/default */
|
||||||
|
|
||||||
import tinycolor from "tinycolor2";
|
import tinycolor from 'tinycolor2';
|
||||||
import jsonSchemaDefaults from "json-schema-defaults";
|
import jsonSchemaDefaults from 'json-schema-defaults';
|
||||||
import thingsboardTypes from "./types.constant";
|
import base64js from 'base64-js';
|
||||||
|
import {utf8Encode, utf8Decode} from './utf8-support';
|
||||||
|
|
||||||
|
import thingsboardTypes from './types.constant';
|
||||||
|
|
||||||
export default angular.module('thingsboard.utils', [thingsboardTypes])
|
export default angular.module('thingsboard.utils', [thingsboardTypes])
|
||||||
.factory('utils', Utils)
|
.factory('utils', Utils)
|
||||||
@ -153,7 +156,9 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
|
|||||||
createKey: createKey,
|
createKey: createKey,
|
||||||
createLabelFromDatasource: createLabelFromDatasource,
|
createLabelFromDatasource: createLabelFromDatasource,
|
||||||
insertVariable: insertVariable,
|
insertVariable: insertVariable,
|
||||||
customTranslation: customTranslation
|
customTranslation: customTranslation,
|
||||||
|
objToBase64: objToBase64,
|
||||||
|
base64toObj: base64toObj
|
||||||
}
|
}
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
@ -486,4 +491,18 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function objToBase64(obj) {
|
||||||
|
var json = angular.toJson(obj);
|
||||||
|
var encoded = utf8Encode(json);
|
||||||
|
var b64Encoded = base64js.fromByteArray(encoded);
|
||||||
|
return b64Encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
function base64toObj(b64Encoded) {
|
||||||
|
var encoded = base64js.toByteArray(b64Encoded);
|
||||||
|
var json = utf8Decode(encoded);
|
||||||
|
var obj = angular.fromJson(json);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -473,7 +473,7 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele
|
|||||||
}
|
}
|
||||||
var stateParams = {
|
var stateParams = {
|
||||||
dashboardId: targetDashboardId,
|
dashboardId: targetDashboardId,
|
||||||
state: angular.toJson([ stateObject ])
|
state: utils.objToBase64([ stateObject ])
|
||||||
}
|
}
|
||||||
$state.go('home.dashboards.dashboard', stateParams);
|
$state.go('home.dashboards.dashboard', stateParams);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -121,11 +121,11 @@ export default function DefaultStateController($scope, $location, $state, $state
|
|||||||
return utils.customTranslation(state.name, id);
|
return utils.customTranslation(state.name, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseState(stateJson) {
|
function parseState(stateBase64) {
|
||||||
var result;
|
var result;
|
||||||
if (stateJson) {
|
if (stateBase64) {
|
||||||
try {
|
try {
|
||||||
result = angular.fromJson(stateJson);
|
result = utils.base64toObj(stateBase64);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
result = [ { id: null, params: {} } ];
|
result = [ { id: null, params: {} } ];
|
||||||
}
|
}
|
||||||
@ -205,7 +205,7 @@ export default function DefaultStateController($scope, $location, $state, $state
|
|||||||
|
|
||||||
function updateLocation() {
|
function updateLocation() {
|
||||||
if (vm.stateObject[0].id) {
|
if (vm.stateObject[0].id) {
|
||||||
$location.search({state : angular.toJson(vm.stateObject)});
|
$location.search({state : utils.objToBase64(vm.stateObject)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -168,11 +168,11 @@ export default function EntityStateController($scope, $location, $state, $stateP
|
|||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseState(stateJson) {
|
function parseState(stateBase64) {
|
||||||
var result;
|
var result;
|
||||||
if (stateJson) {
|
if (stateBase64) {
|
||||||
try {
|
try {
|
||||||
result = angular.fromJson(stateJson);
|
result = utils.base64toObj(stateBase64);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
result = [ { id: null, params: {} } ];
|
result = [ { id: null, params: {} } ];
|
||||||
}
|
}
|
||||||
@ -278,7 +278,7 @@ export default function EntityStateController($scope, $location, $state, $stateP
|
|||||||
|
|
||||||
function updateLocation() {
|
function updateLocation() {
|
||||||
if (vm.stateObject[vm.stateObject.length-1].id) {
|
if (vm.stateObject[vm.stateObject.length-1].id) {
|
||||||
$location.search({state : angular.toJson(vm.stateObject)});
|
$location.search({state : utils.objToBase64(vm.stateObject)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import selectTargetLayoutTemplate from '../../dashboard/layouts/select-target-la
|
|||||||
|
|
||||||
/*@ngInject*/
|
/*@ngInject*/
|
||||||
export default function AddWidgetToDashboardDialogController($scope, $mdDialog, $state, $q, $document, dashboardUtils,
|
export default function AddWidgetToDashboardDialogController($scope, $mdDialog, $state, $q, $document, dashboardUtils,
|
||||||
types, itembuffer, dashboardService, entityId, entityType, entityName, widget) {
|
utils, types, itembuffer, dashboardService, entityId, entityType, entityName, widget) {
|
||||||
|
|
||||||
var vm = this;
|
var vm = this;
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ export default function AddWidgetToDashboardDialogController($scope, $mdDialog,
|
|||||||
var stateIds = Object.keys(dashboard.configuration.states);
|
var stateIds = Object.keys(dashboard.configuration.states);
|
||||||
var stateIndex = stateIds.indexOf(targetState);
|
var stateIndex = stateIds.indexOf(targetState);
|
||||||
if (stateIndex > 0) {
|
if (stateIndex > 0) {
|
||||||
stateParams.state = angular.toJson([ {id: targetState, params: {}} ]);
|
stateParams.state = utils.objToBase64([ {id: targetState, params: {}} ]);
|
||||||
}
|
}
|
||||||
$state.go('home.dashboards.dashboard', stateParams);
|
$state.go('home.dashboards.dashboard', stateParams);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user