Merge branch 'master' into develop/3.2

This commit is contained in:
Igor Kulikov 2020-08-21 17:24:07 +03:00
commit 3ffda44816
24 changed files with 298 additions and 363 deletions

View File

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.controller;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
@ -59,7 +60,11 @@ public class AdminController extends BaseController {
public AdminSettings getAdminSettings(@PathVariable("key") String key) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key));
AdminSettings adminSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key));
if (adminSettings.getKey().equals("mail")) {
((ObjectNode) adminSettings.getJsonValue()).put("password", "");
}
return adminSettings;
} catch (Exception e) {
throw handleException(e);
}
@ -74,6 +79,7 @@ public class AdminController extends BaseController {
adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings));
if (adminSettings.getKey().equals("mail")) {
mailService.updateMailConfiguration();
((ObjectNode) adminSettings.getJsonValue()).put("password", "");
}
return adminSettings;
} catch (Exception e) {

View File

@ -391,8 +391,12 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
}
private Set<EntityId> getPropagationEntityIds(Alarm alarm) {
List<EntityRelation> relations = relationService.findByTo(alarm.getTenantId(), alarm.getId(), RelationTypeGroup.ALARM);
return relations.stream().map(EntityRelation::getFrom).collect(Collectors.toSet());
if (alarm.isPropagate()) {
List<EntityRelation> relations = relationService.findByTo(alarm.getTenantId(), alarm.getId(), RelationTypeGroup.ALARM);
return relations.stream().map(EntityRelation::getFrom).collect(Collectors.toSet());
} else {
return Collections.singleton(alarm.getOriginator());
}
}
private void createAlarmRelation(TenantId tenantId, EntityId entityId, EntityId alarmId) {

View File

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.dao.settings;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -51,6 +52,13 @@ public class AdminSettingsServiceImpl implements AdminSettingsService {
public AdminSettings saveAdminSettings(TenantId tenantId, AdminSettings adminSettings) {
log.trace("Executing saveAdminSettings [{}]", adminSettings);
adminSettingsValidator.validate(adminSettings, data -> tenantId);
if (adminSettings.getKey().equals("mail") && "".equals(adminSettings.getJsonValue().get("password").asText())) {
AdminSettings mailSettings = findAdminSettingsByKey(tenantId, "mail");
if (mailSettings != null) {
((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText());
}
}
return adminSettingsDao.save(tenantId, adminSettings);
}

View File

@ -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",

View File

@ -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;

View File

@ -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;

View File

@ -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}`;

View File

@ -30,6 +30,7 @@ import 'leaflet.markercluster/dist/leaflet.markercluster';
import {
defaultSettings,
FormattedData,
MapProviders,
MapSettings,
MarkerSettings,
PolygonSettings,
@ -74,6 +75,8 @@ export default abstract class LeafletMap {
drawRoutes: boolean;
showPolygon: boolean;
updatePending = false;
addMarkers: L.Marker[] = [];
addPolygons: L.Polygon[] = [];
protected constructor(public ctx: WidgetContext,
public $container: HTMLElement,
@ -133,6 +136,7 @@ export default abstract class LeafletMap {
shadowSize: [41, 41]
});
const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map);
this.addMarkers.push(newMarker);
const datasourcesList = document.createElement('div');
const customLatLng = this.convertToCustomFormat(mousePositionOnMap);
const header = document.createElement('p');
@ -147,10 +151,14 @@ export default abstract class LeafletMap {
const updatedEnttity = { ...ds, ...customLatLng };
this.saveMarkerLocation(updatedEnttity).subscribe(() => {
this.map.removeLayer(newMarker);
const markerIndex = this.addMarkers.indexOf(newMarker);
if (markerIndex > -1) {
this.addMarkers.splice(markerIndex, 1);
}
this.deleteMarker(ds.entityName);
this.createMarker(ds.entityName, updatedEnttity, this.datasources, this.options);
});
}
};
datasourcesList.append(dsItem);
});
datasourcesList.append(document.createElement('br'));
@ -158,14 +166,18 @@ export default abstract class LeafletMap {
deleteBtn.appendChild(document.createTextNode('Discard changes'));
deleteBtn.onclick = () => {
this.map.removeLayer(newMarker);
}
const markerIndex = this.addMarkers.indexOf(newMarker);
if (markerIndex > -1) {
this.addMarkers.splice(markerIndex, 1);
}
};
datasourcesList.append(deleteBtn);
const popup = L.popup();
popup.setContent(datasourcesList);
newMarker.bindPopup(popup).openPopup();
}
addMarker.setPosition('topright')
}
addMarker.setPosition('topright');
};
L.Control.AddMarker = L.Control.extend({
onAdd() {
const img = L.DomUtil.create('img') as any;
@ -177,7 +189,7 @@ export default abstract class LeafletMap {
img.draggable = true;
const draggableImg = new L.Draggable(img);
draggableImg.enable();
draggableImg.on('dragend', dragListener)
draggableImg.on('dragend', dragListener);
return img;
},
onRemove() {
@ -186,7 +198,7 @@ export default abstract class LeafletMap {
} as any);
L.control.addMarker = (opts) => {
return new L.Control.AddMarker(opts);
}
};
addMarker = L.control.addMarker({ position: 'topright' }).addTo(this.map);
}
}
@ -196,14 +208,16 @@ export default abstract class LeafletMap {
let mousePositionOnMap: L.LatLng[];
let addPolygon: L.Control;
this.map.on('mousemove', (e: L.LeafletMouseEvent) => {
const polygonOffset = this.options.provider === MapProviders.image ? 10 : 0.01;
const latlng1 = e.latlng;
const latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + 10);
const latlng3 = L.latLng(e.latlng.lat-10, e.latlng.lng);
mousePositionOnMap = [latlng1,latlng2, latlng3 ];
const latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + polygonOffset);
const latlng3 = L.latLng(e.latlng.lat - polygonOffset, e.latlng.lng);
mousePositionOnMap = [latlng1, latlng2, latlng3];
});
const dragListener = (e: L.DragEndEvent) => {
if (e.type === 'dragend' && mousePositionOnMap) {
const newPolygon = L.polygon(mousePositionOnMap).addTo(this.map);
this.addPolygons.push(newPolygon);
const datasourcesList = document.createElement('div');
const customLatLng = {[this.options.polygonKeyName]: this.convertToPolygonFormat(mousePositionOnMap)};
const header = document.createElement('p');
@ -218,9 +232,13 @@ export default abstract class LeafletMap {
const updatedEnttity = { ...ds, ...customLatLng };
this.savePolygonLocation(updatedEnttity).subscribe(() => {
this.map.removeLayer(newPolygon);
const polygonIndex = this.addPolygons.indexOf(newPolygon);
if (polygonIndex > -1) {
this.addPolygons.splice(polygonIndex, 1);
}
this.deletePolygon(ds.entityName);
});
}
};
datasourcesList.append(dsItem);
});
datasourcesList.append(document.createElement('br'));
@ -228,14 +246,18 @@ export default abstract class LeafletMap {
deleteBtn.appendChild(document.createTextNode('Discard changes'));
deleteBtn.onclick = () => {
this.map.removeLayer(newPolygon);
}
const polygonIndex = this.addPolygons.indexOf(newPolygon);
if (polygonIndex > -1) {
this.addPolygons.splice(polygonIndex, 1);
}
};
datasourcesList.append(deleteBtn);
const popup = L.popup();
popup.setContent(datasourcesList);
newPolygon.bindPopup(popup).openPopup();
}
addPolygon.setPosition('topright')
}
addPolygon.setPosition('topright');
};
L.Control.AddPolygon = L.Control.extend({
onAdd() {
const img = L.DomUtil.create('img') as any;
@ -247,7 +269,7 @@ export default abstract class LeafletMap {
img.draggable = true;
const draggableImg = new L.Draggable(img);
draggableImg.enable();
draggableImg.on('dragend', dragListener)
draggableImg.on('dragend', dragListener);
return img;
},
onRemove() {
@ -256,7 +278,7 @@ export default abstract class LeafletMap {
} as any);
L.control.addPolygon = (opts) => {
return new L.Control.AddPolygon(opts);
}
};
addPolygon = L.control.addPolygon({ position: 'topright' }).addTo(this.map);
}
}
@ -280,10 +302,11 @@ export default abstract class LeafletMap {
public setMap(map: L.Map) {
this.map = map;
if (this.options.useDefaultCenterPosition) {
this.map.panTo(this.options.defaultCenterPosition);
this.bounds = map.getBounds();
this.map.panTo(this.options.defaultCenterPosition);
this.bounds = map.getBounds();
} else {
this.bounds = new L.LatLngBounds(null, null);
}
else this.bounds = new L.LatLngBounds(null, null);
if (this.options.draggableMarker) {
this.addMarkerControl();
}
@ -299,11 +322,11 @@ export default abstract class LeafletMap {
}
}
public saveMarkerLocation(_e: FormattedData, lat?: number, lng?: number): Observable<any> {
public saveMarkerLocation(datasource: FormattedData, lat?: number, lng?: number): Observable<any> {
return of(null);
}
public savePolygonLocation(_e: FormattedData, coordinates?: Array<[number, number]>): Observable<any> {
public savePolygonLocation(datasource: FormattedData, coordinates?: Array<[number, number]>): Observable<any> {
return of(null);
}
@ -364,7 +387,9 @@ export default abstract class LeafletMap {
}
convertPosition(expression: object): L.LatLng {
if (!expression) return null;
if (!expression) {
return null;
}
const lat = expression[this.options.latKeyName];
const lng = expression[this.options.lngKeyName];
if (!isDefinedAndNotNull(lat) || isString(lat) || isNaN(lat) || !isDefinedAndNotNull(lng) || isString(lng) || isNaN(lng)) {
@ -382,35 +407,35 @@ export default abstract class LeafletMap {
} else {
return null;
}
}).filter(el => !!el)
}).filter(el => !!el);
}
convertToCustomFormat(position: L.LatLng): object {
return {
[this.options.latKeyName]: position.lat % 90,
[this.options.lngKeyName]: position.lng % 180
}
};
}
convertToPolygonFormat(points: Array<any>): Array<any> {
if (points.length) {
return points.map(point=> {
if (point.length) {
return this.convertToPolygonFormat(point);
} else {
return [point.lat, point.lng];
}
})
} else {
return []
convertToPolygonFormat(points: Array<any>): Array<any> {
if (points.length) {
return points.map(point => {
if (point.length) {
return this.convertToPolygonFormat(point);
} else {
return [point.lat, point.lng];
}
});
} else {
return [];
}
}
}
convertPolygonToCustomFormat(expression: any[][]): object {
return {
[this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
convertPolygonToCustomFormat(expression: any[][]): object {
return {
[this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
};
}
}
updateData(drawRoutes: boolean, showPolygon: boolean) {
this.drawRoutes = drawRoutes;
@ -509,7 +534,7 @@ export default abstract class LeafletMap {
this.markersCluster.addLayers(createdMarkers.map(marker => marker.leafletMarker));
}
if (updatedMarkers.length) {
this.markersCluster.refreshClusters(updatedMarkers.map(marker => marker.leafletMarker))
this.markersCluster.refreshClusters(updatedMarkers.map(marker => marker.leafletMarker));
}
if (deletedMarkers.length) {
this.markersCluster.removeLayers(deletedMarkers.map(marker => marker.leafletMarker));
@ -518,7 +543,9 @@ export default abstract class LeafletMap {
}
dragMarker = (e, data = {} as FormattedData) => {
if (e.type !== 'dragend') return;
if (e.type !== 'dragend') {
return;
}
this.saveMarkerLocation({ ...data, ...this.convertToCustomFormat(e.target._latlng) }).subscribe();
}
@ -527,7 +554,7 @@ export default abstract class LeafletMap {
const newMarker = new Marker(this, this.convertPosition(data), settings, data, dataSources, this.dragMarker);
if (callback) {
newMarker.leafletMarker.on('click', () => {
callback(data, true)
callback(data, true);
});
}
if (this.bounds && updateBounds && !(this.options as MarkerSettings).useClusterMarkers) {
@ -565,11 +592,10 @@ export default abstract class LeafletMap {
}
deletePolygon(key: string) {
let polygon = this.polygons.get(key)?.leafletPoly;
const polygon = this.polygons.get(key)?.leafletPoly;
if (polygon) {
this.map.removeLayer(polygon);
this.polygons.delete(key);
polygon = null;
}
return polygon;
}
@ -684,7 +710,9 @@ export default abstract class LeafletMap {
}
dragPolygonVertex = (e?, data = {} as FormattedData) => {
if (e === undefined || (e.type !== 'editable:vertex:dragend' && e.type !== 'editable:vertex:deleted')) return;
if (e === undefined || (e.type !== 'editable:vertex:dragend' && e.type !== 'editable:vertex:deleted')) {
return;
}
this.savePolygonLocation({ ...data, ...this.convertPolygonToCustomFormat(e.layer._latlngs) }).subscribe();
}

View File

@ -62,7 +62,7 @@ export type MapSettings = {
useCustomProvider: boolean,
customProviderTileUrl: string;
mapPageSize: number;
}
};
export enum MapProviders {
google = 'google-map',
@ -103,7 +103,7 @@ export type MarkerSettings = {
markerImageFunction?: MarkerImageFunction;
markerOffsetX: number;
markerOffsetY: number;
}
};
export interface FormattedData {
$datasource: Datasource;
@ -112,19 +112,19 @@ export interface FormattedData {
entityType: EntityType;
dsIndex: number;
deviceType: string;
[key: string]: any
[key: string]: any;
}
export interface ReplaceInfo {
variable: string;
valDec?: number;
dataKeyName: string
dataKeyName: string;
}
export type PolygonSettings = {
showPolygon: boolean;
polygonKeyName: string;
polKeyName: string;// deprecated
polKeyName: string; // deprecated
polygonStrokeOpacity: number;
polygonOpacity: number;
polygonStrokeWeight: number;
@ -141,7 +141,7 @@ export type PolygonSettings = {
polygonTooltipFunction: GenericFunction;
polygonColorFunction?: GenericFunction;
editablePolygon: boolean;
}
};
export type PolylineSettings = {
usePolylineDecorator: any;
@ -166,7 +166,7 @@ export type PolylineSettings = {
colorFunction: GenericFunction;
strokeOpacityFunction: GenericFunction;
strokeWeightFunction: GenericFunction;
}
};
export interface HistorySelectSettings {
buttonColor: string;
@ -244,4 +244,5 @@ export const hereProviders = [
'HERE.normalDay',
'HERE.normalNight',
'HERE.hybridDay',
'HERE.terrainDay']
'HERE.terrainDay'
];

View File

@ -18,15 +18,15 @@ import { JsonSettingsSchema } from '@shared/models/widget.models';
import { MapProviders } from './map-models';
export interface MapWidgetInterface {
resize(),
update(),
onInit(),
resize();
update();
onInit();
onDestroy();
}
export interface MapWidgetStaticInterface {
settingsSchema(mapProvider?: MapProviders, drawRoutes?: boolean): JsonSettingsSchema;
getProvidersSchema(mapProvider?: MapProviders, ignoreImageMap?: boolean): JsonSettingsSchema
getProvidersSchema(mapProvider?: MapProviders, ignoreImageMap?: boolean): JsonSettingsSchema;
dataKeySettingsSchema(): object;
actionSources(): object;
}

View File

@ -33,7 +33,7 @@ import {
import { MapWidgetInterface, MapWidgetStaticInterface } from './map-widget.interface';
import { addCondition, addGroupInfo, addToSchema, initSchema, mergeSchemes } from '@core/schema-utils';
import { WidgetContext } from '@app/modules/home/models/widget-component.models';
import { getDefCenterPosition, parseData, parseFunction, parseWithTranslation } from './maps-utils';
import { getDefCenterPosition, parseFunction, parseWithTranslation } from './maps-utils';
import { Datasource, DatasourceData, JsonSettingsSchema, WidgetActionDescriptor } from '@shared/models/widget.models';
import { EntityId } from '@shared/models/id/entity-id';
import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/telemetry/telemetry.models';
@ -102,8 +102,9 @@ export class MapWidgetController implements MapWidgetInterface {
public static getProvidersSchema(mapProvider: MapProviders, ignoreImageMap = false) {
const providerSchema = _.cloneDeep(mapProviderSchema);
if (mapProvider)
providerSchema.schema.properties.provider.default = mapProvider;
if (mapProvider) {
providerSchema.schema.properties.provider.default = mapProvider;
}
if (ignoreImageMap) {
providerSchema.form[0].items = providerSchema.form[0]?.items.filter(item => item.value !== 'image-map');
}
@ -129,7 +130,7 @@ export class MapWidgetController implements MapWidgetInterface {
} else {
const clusteringSchema = mergeSchemes([markerClusteringSettingsSchema,
addCondition(markerClusteringSettingsSchemaLeaflet,
`model.useClusterMarkers === true && model.provider !== "image-map"`)])
`model.useClusterMarkers === true && model.provider !== "image-map"`)]);
addToSchema(schema, clusteringSchema);
addGroupInfo(schema, 'Markers Clustering Settings');
}
@ -154,10 +155,11 @@ export class MapWidgetController implements MapWidgetInterface {
}
translate = (key: string, defaultTranslation?: string): string => {
if (key)
return (this.ctx.$injector.get(UtilsService).customTranslation(key, defaultTranslation || key)
|| this.ctx.$injector.get(TranslateService).instant(key));
else return '';
if (key) {
return (this.ctx.$injector.get(UtilsService).customTranslation(key, defaultTranslation || key)
|| this.ctx.$injector.get(TranslateService).instant(key));
}
return '';
}
getDescriptors(name: string): { [name: string]: ($event: Event, datasource: Datasource) => void } {
@ -211,10 +213,10 @@ export class MapWidgetController implements MapWidgetInterface {
}
if (value) {
if (key.type === DataKeyType.attribute) {
attributes.push(value)
attributes.push(value);
}
if (key.type === DataKeyType.timeseries) {
timeseries.push(value)
timeseries.push(value);
}
}
});
@ -253,7 +255,7 @@ export class MapWidgetController implements MapWidgetInterface {
const coordinatesProperties = this.settings.polygonKeyName;
e.$datasource.dataKeys.forEach(key => {
let value;
if (coordinatesProperties == key.name) {
if (coordinatesProperties === key.name) {
value = {
key: key.name,
value: isDefined(coordinates) ? coordinates : e[key.name]
@ -261,10 +263,10 @@ export class MapWidgetController implements MapWidgetInterface {
}
if (value) {
if (key.type === DataKeyType.attribute) {
attributes.push(value)
attributes.push(value);
}
if (key.type === DataKeyType.timeseries) {
timeseries.push(value)
timeseries.push(value);
}
}
});
@ -294,9 +296,11 @@ export class MapWidgetController implements MapWidgetInterface {
const functionParams = ['data', 'dsData', 'dsIndex'];
this.provider = settings.provider || this.mapProvider;
if (this.provider === MapProviders.here && !settings.mapProviderHere) {
if (settings.mapProvider && hereProviders.includes(settings.mapProvider))
settings.mapProviderHere = settings.mapProvider
else settings.mapProviderHere = hereProviders[0];
if (settings.mapProvider && hereProviders.includes(settings.mapProvider)) {
settings.mapProviderHere = settings.mapProvider;
} else {
settings.mapProviderHere = hereProviders[0];
}
}
const customOptions = {
provider: this.provider,
@ -317,14 +321,14 @@ export class MapWidgetController implements MapWidgetInterface {
url: settings.markerImage,
size: settings.markerImageSize || 34
} : null
}
};
if (isEditMap && !settings.hasOwnProperty('draggableMarker')) {
settings.draggableMarker = true;
}
if (isEditMap && !settings.hasOwnProperty('editablePolygon')) {
settings.editablePolygon = true;
}
return { ...defaultSettings, ...settings, ...customOptions, }
return { ...defaultSettings, ...settings, ...customOptions, };
}
update() {

View File

@ -31,9 +31,9 @@ import {
} from '@core/utils';
export function createTooltip(target: L.Layer,
settings: MarkerSettings | PolylineSettings | PolygonSettings,
datasource: Datasource,
content?: string | HTMLElement
settings: MarkerSettings | PolylineSettings | PolygonSettings,
datasource: Datasource,
content?: string | HTMLElement
): L.Popup {
const popup = L.popup();
popup.setContent(content);
@ -87,7 +87,7 @@ export function interpolateOnLineSegment(
}
export function findAngle(startPoint: FormattedData, endPoint: FormattedData, latKeyName: string, lngKeyName: string): number {
if(isUndefined(startPoint) || isUndefined(endPoint)){
if (isUndefined(startPoint) || isUndefined(endPoint)) {
return 0;
}
let angle = -Math.atan2(endPoint[latKeyName] - startPoint[latKeyName], endPoint[lngKeyName] - startPoint[lngKeyName]);
@ -97,11 +97,13 @@ export function findAngle(startPoint: FormattedData, endPoint: FormattedData, la
export function getDefCenterPosition(position) {
if (typeof (position) === 'string')
return position.split(',');
if (typeof (position) === 'object')
return position;
return [0, 0];
if (typeof (position) === 'string') {
return position.split(',');
}
if (typeof (position) === 'object') {
return position;
}
return [0, 0];
}
@ -123,7 +125,7 @@ function imageLoader(imageUrl: string): Observable<HTMLImageElement> {
document.body.removeChild(image);
observer.complete();
};
document.body.appendChild(image)
document.body.appendChild(image);
image.src = imageUrl;
});
}
@ -135,11 +137,11 @@ export function aspectCache(imageUrl: string): Observable<number> {
if (aspect) {
return of(aspect);
}
else return imageLoader(imageUrl).pipe(map(image => {
return imageLoader(imageUrl).pipe(map(image => {
aspect = image.width / image.height;
imageAspectMap[hash] = aspect;
return aspect;
}))
}));
}
}
@ -221,7 +223,7 @@ function parseTemplate(template: string, data: { $datasource?: Datasource, [key:
// res = compiled(data);
res = template;
} catch (ex) {
console.log(ex, template)
console.log(ex, template);
}
return res;
}
@ -263,7 +265,7 @@ export function processPattern(template: string, data: { $datasource?: Datasourc
match = reg.exec(template);
}
} catch (ex) {
console.log(ex, template)
console.log(ex, template);
}
return replaceInfo;
}
@ -271,7 +273,7 @@ export function processPattern(template: string, data: { $datasource?: Datasourc
export function fillPattern(markerLabelText: string, replaceInfoLabelMarker: Array<ReplaceInfo>, data: FormattedData) {
let text = createLabelFromDatasource(data.$datasource, markerLabelText);
if (replaceInfoLabelMarker) {
for(const variableInfo of replaceInfoLabelMarker) {
for (const variableInfo of replaceInfoLabelMarker) {
let txtVal = '';
if (variableInfo.dataKeyName && isDefinedAndNotNull(data[variableInfo.dataKeyName])) {
const varData = data[variableInfo.dataKeyName];
@ -334,7 +336,7 @@ export const parseWithTranslation = {
setTranslate(translateFn: TranslateFunc) {
this.translateFn = translateFn;
}
}
};
export function parseData(input: DatasourceData[]): FormattedData[] {
return _(input).groupBy(el => el?.datasource?.entityName)
@ -361,7 +363,7 @@ export function parseData(input: DatasourceData[]): FormattedData[] {
export function parseArray(input: DatasourceData[]): FormattedData[][] {
return _(input).groupBy(el => el?.datasource?.entityName)
.values().value().map((entityArray, dsIndex) =>
.values().value().map((entityArray) =>
entityArray[0].data.map((el, i) => {
const obj: FormattedData = {
entityName: entityArray[0]?.datasource?.entityName,

View File

@ -81,7 +81,7 @@ export class Marker {
}
updateMarkerTooltip(data: FormattedData) {
if(!this.map.markerTooltipText || this.settings.useTooltipFunction) {
if (!this.map.markerTooltipText || this.settings.useTooltipFunction) {
const pattern = this.settings.useTooltipFunction ?
safeExecute(this.settings.tooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : this.settings.tooltipPattern;
this.map.markerTooltipText = parseWithTranslation.prepareProcessPattern(pattern, true);
@ -103,7 +103,7 @@ export class Marker {
updateMarkerLabel(settings: MarkerSettings) {
this.leafletMarker.unbindTooltip();
if (settings.showLabel) {
if(!this.map.markerLabelText || settings.useLabelFunction) {
if (!this.map.markerLabelText || settings.useLabelFunction) {
const pattern = settings.useLabelFunction ?
safeExecute(settings.labelFunction, [this.data, this.dataSources, this.data.dsIndex]) : settings.label;
this.map.markerLabelText = parseWithTranslation.prepareProcessPattern(pattern, true);

View File

@ -55,7 +55,7 @@ export class Polygon {
this.leafletPoly.on('click', (event: LeafletMouseEvent) => {
for (const action in this.settings.polygonClick) {
if (typeof (this.settings.polygonClick[action]) === 'function') {
this.settings.polygonClick[action](event.originalEvent, polyData.datasource);
this.settings.polygonClick[action](event.originalEvent, polyData.$datasource);
}
}
});
@ -70,18 +70,19 @@ export class Polygon {
}
updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) {
this.data = data;
this.dataSources = dataSources;
if (settings.editablePolygon) {
this.leafletPoly.disableEdit();
}
this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]);
this.data = data;
this.dataSources = dataSources;
if (settings.editablePolygon) {
this.leafletPoly.disableEdit();
}
this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]);
if (settings.editablePolygon) {
this.leafletPoly.enableEdit(this.map);
}
if (settings.showPolygonTooltip)
this.updateTooltip(this.data);
this.updatePolygonColor(settings);
if (settings.showPolygonTooltip) {
this.updateTooltip(this.data);
}
this.updatePolygonColor(settings);
}
removePolygon() {

View File

@ -57,7 +57,7 @@ export class Polyline {
})
}
]
}
};
}
updatePolyline(locations: L.LatLng[], data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) {
@ -65,8 +65,9 @@ export class Polyline {
this.dataSources = dataSources;
this.leafletPoly.setLatLngs(locations);
this.leafletPoly.setStyle(this.getPolyStyle(settings));
if (this.polylineDecorator)
if (this.polylineDecorator) {
this.polylineDecorator.setPaths(this.leafletPoly);
}
}
getPolyStyle(settings: PolylineSettings): L.PolylineOptions {
@ -78,7 +79,7 @@ export class Polyline {
[this.data, this.dataSources, this.data.dsIndex], settings.strokeOpacity),
weight: functionValueCalculator(settings.useStrokeWeightFunction, settings.strokeWeightFunction,
[this.data, this.dataSources, this.data.dsIndex], settings.strokeWeight)
}
};
}
removePolyline() {

View File

@ -49,7 +49,7 @@ export class GoogleMap extends LeafletMap {
private loadGoogle(callback, apiKey = 'AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q') {
if (gmGlobals[apiKey]) {
callback()
callback();
} else {
this.resource.loadResource(`https://maps.googleapis.com/maps/api/js?key=${apiKey}`).subscribe(
() => {

View File

@ -26,7 +26,7 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { WidgetSubscriptionOptions } from '@core/api/widget-api.models';
import { isDefinedAndNotNull, isEmptyStr } from '@core/utils';
const maxZoom = 4;// ?
const maxZoom = 4; // ?
export class ImageMap extends LeafletMap {
@ -162,52 +162,64 @@ export class ImageMap extends LeafletMap {
}
onResize(updateImage?: boolean) {
let width = this.$container.clientWidth;
if (width > 0 && this.aspect) {
let height = width / this.aspect;
const imageMapHeight = this.$container.clientHeight;
if (imageMapHeight > 0 && height > imageMapHeight) {
height = imageMapHeight;
width = height * this.aspect;
}
width *= maxZoom;
const prevWidth = this.width;
const prevHeight = this.height;
if (this.width !== width || updateImage) {
this.width = width;
this.height = width / this.aspect;
if (!this.map) {
this.initMap(updateImage);
} else {
const lastCenterPos = this.latLngToPoint(this.map.getCenter());
lastCenterPos.x /= prevWidth;
lastCenterPos.y /= prevHeight;
this.updateBounds(updateImage, lastCenterPos);
this.map.invalidateSize(true);
this.updateMarkers(this.markersData);
this.updatePolygons(this.polygonsData);
}
}
let width = this.$container.clientWidth;
if (width > 0 && this.aspect) {
let height = width / this.aspect;
const imageMapHeight = this.$container.clientHeight;
if (imageMapHeight > 0 && height > imageMapHeight) {
height = imageMapHeight;
width = height * this.aspect;
}
width *= maxZoom;
const prevWidth = this.width;
const prevHeight = this.height;
if (this.width !== width || updateImage) {
this.width = width;
this.height = width / this.aspect;
if (!this.map) {
this.initMap(updateImage);
} else {
const lastCenterPos = this.latLngToPoint(this.map.getCenter());
lastCenterPos.x /= prevWidth;
lastCenterPos.y /= prevHeight;
this.updateBounds(updateImage, lastCenterPos);
this.map.invalidateSize(true);
this.updateMarkers(this.markersData);
if (this.options.draggableMarker && this.addMarkers.length) {
this.addMarkers.forEach((marker) => {
const prevPoint = this.convertToCustomFormat(marker.getLatLng(), prevWidth, prevHeight);
marker.setLatLng(this.convertPosition(prevPoint));
});
}
this.updatePolygons(this.polygonsData);
if (this.options.showPolygon && this.options.editablePolygon && this.addPolygons.length) {
this.addPolygons.forEach((polygon) => {
const prevPolygonPoint = this.convertToPolygonFormat(polygon.getLatLngs(), prevWidth, prevHeight);
polygon.setLatLngs(this.convertPositionPolygon(prevPolygonPoint));
});
}
}
}
}
}
fitBounds(bounds: LatLngBounds, padding?: LatLngTuple) { }
initMap(updateImage?: boolean) {
if (!this.map && this.aspect > 0) {
const center = this.pointToLatLng(this.width / 2, this.height / 2);
this.map = L.map(this.$container, {
minZoom: 1,
maxZoom,
scrollWheelZoom: !this.options.disableScrollZooming,
center,
zoom: 1,
crs: L.CRS.Simple,
attributionControl: false,
editable: !!this.options.editablePolygon
});
this.updateBounds(updateImage);
}
if (!this.map && this.aspect > 0) {
const center = this.pointToLatLng(this.width / 2, this.height / 2);
this.map = L.map(this.$container, {
minZoom: 1,
maxZoom,
scrollWheelZoom: !this.options.disableScrollZooming,
center,
zoom: 1,
crs: L.CRS.Simple,
attributionControl: false,
editable: !!this.options.editablePolygon
});
this.updateBounds(updateImage);
}
}
convertPosition(expression): L.LatLng {
@ -227,13 +239,14 @@ export class ImageMap extends LeafletMap {
if (!Array.isArray(el[0]) && !Array.isArray(el[1]) && el.length === 2) {
return this.pointToLatLng(
el[0] * this.width,
el[1] * this.height)
el[1] * this.height
);
} else if (Array.isArray(el) && el.length) {
return this.convertPositionPolygon(el as LatLngTuple[] | LatLngTuple[][]);
} else {
return null;
}
}).filter(el => !!el)
}).filter(el => !!el);
}
pointToLatLng(x, y): L.LatLng {
@ -244,32 +257,32 @@ export class ImageMap extends LeafletMap {
return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1);
}
convertToCustomFormat(position: L.LatLng): object {
const point = this.latLngToPoint(position);
return {
[this.options.xPosKeyName]: calculateNewPointCoordinate(point.x, this.width),
[this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, this.height)
}
convertToCustomFormat(position: L.LatLng, width = this.width, height = this.height): object {
const point = this.latLngToPoint(position);
return {
[this.options.xPosKeyName]: calculateNewPointCoordinate(point.x, width),
[this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, height)
};
}
convertToPolygonFormat(points: Array<any>): Array<any> {
convertToPolygonFormat(points: Array<any>, width = this.width, height = this.height): Array<any> {
if (points.length) {
return points.map(point=> {
return points.map(point => {
if (point.length) {
return this.convertToPolygonFormat(point);
return this.convertToPolygonFormat(point, width, height);
} else {
const pos = this.latLngToPoint(point);
return [calculateNewPointCoordinate(pos.x, this.width), calculateNewPointCoordinate(pos.y, this.height)];
return [calculateNewPointCoordinate(pos.x, width), calculateNewPointCoordinate(pos.y, height)];
}
})
});
} else {
return []
return [];
}
}
convertPolygonToCustomFormat(expression: any[][]): object {
return {
[this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
}
};
}
}

View File

@ -29,16 +29,16 @@ import LeafletMap from '@home/components/widget/lib/maps/leaflet-map';
import { JsonSettingsSchema } from '@shared/models/widget.models';
interface IProvider {
MapClass: Type<LeafletMap>,
schema: JsonSettingsSchema,
name: string
MapClass: Type<LeafletMap>;
schema: JsonSettingsSchema;
name: string;
}
export const providerSets: { [key: string]: IProvider } = {
'openstreet-map': {
MapClass: OpenStreetMap,
schema: openstreetMapSettingsSchema,
name: 'openstreet-map',
name: 'openstreet-map'
},
'tencent-map': {
MapClass: TencentMap,

View File

@ -26,10 +26,11 @@ export class OpenStreetMap extends LeafletMap {
editable: !!options.editablePolygon
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
let tileLayer;
if (options.useCustomProvider)
tileLayer = L.tileLayer(options.customProviderTileUrl);
else
tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik');
if (options.useCustomProvider) {
tileLayer = L.tileLayer(options.customProviderTileUrl);
} else {
tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik');
}
tileLayer.addTo(map);
super.initSettings(options);
super.setMap(map);

View File

@ -1068,31 +1068,31 @@ export const tripAnimationSchema = {
key: 'labelFunction',
type: 'javascript'
}, 'showTooltip', {
key: 'tooltipColor',
type: 'color'
}, {
key: 'tooltipFontColor',
type: 'color'
}, 'tooltipOpacity', {
key: 'tooltipPattern',
type: 'textarea'
}, 'useTooltipFunction', {
key: 'tooltipFunction',
type: 'javascript'
}, 'autocloseTooltip', {
key: 'markerImage',
type: 'image'
}, 'markerImageSize', 'rotationAngle', 'useMarkerImageFunction',
{
key: 'markerImageFunction',
type: 'javascript'
}, {
key: 'markerImages',
items: [
{
key: 'markerImages[]',
type: 'image'
}
]
}]
}
key: 'tooltipColor',
type: 'color'
}, {
key: 'tooltipFontColor',
type: 'color'
}, 'tooltipOpacity', {
key: 'tooltipPattern',
type: 'textarea'
}, 'useTooltipFunction', {
key: 'tooltipFunction',
type: 'javascript'
}, 'autocloseTooltip', {
key: 'markerImage',
type: 'image'
}, 'markerImageSize', 'rotationAngle', 'useMarkerImageFunction',
{
key: 'markerImageFunction',
type: 'javascript'
}, {
key: 'markerImages',
items: [
{
key: 'markerImages[]',
type: 'image'
}
]
}]
};

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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==