Create new input widgets for edit location enity to map (#2138)

This commit is contained in:
Vladyslav 2019-11-08 14:19:15 +02:00 committed by Igor Kulikov
parent 46c7862258
commit ac8e67eff0
8 changed files with 307 additions and 13 deletions

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2019 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.
*/
.tb-add-entity-panel {
min-width: 150px;
max-height: 200px;
overflow: hidden;
overflow-y: auto;
background: #fff;
border-radius: 4px;
box-shadow:
0 7px 8px -4px rgba(0, 0, 0, .2),
0 13px 19px 2px rgba(0, 0, 0, .14),
0 5px 24px 4px rgba(0, 0, 0, .12);
}

View File

@ -0,0 +1,22 @@
<!--
Copyright © 2016-2019 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.
-->
<md-list ng-cloak>
<md-list-item ng-repeat="entity in vm.entities" ng-click="vm.selectEntity(entity)">
<span>{{ entity.entityLabel || entity.name }}</span>
</md-list-item>
</md-list>

View File

@ -29,7 +29,7 @@ export default class TbGoogleMap {
this.tooltips = []; this.tooltips = [];
this.defaultMapType = gmDefaultMapType; this.defaultMapType = gmDefaultMapType;
this.defaultCenterPosition = defaultCenterPosition; this.defaultCenterPosition = defaultCenterPosition;
this.isMarketCluster = markerClusteringSetting.isMarketCluster; this.isMarketCluster = markerClusteringSetting && markerClusteringSetting.isMarketCluster;
function clearGlobalId() { function clearGlobalId() {
if (gmGlobals.loadingGmId && gmGlobals.loadingGmId === tbMap.mapId) { if (gmGlobals.loadingGmId && gmGlobals.loadingGmId === tbMap.mapId) {
@ -234,17 +234,19 @@ export default class TbGoogleMap {
/* eslint-enable no-undef */ /* eslint-enable no-undef */
/* eslint-disable no-undef */ /* eslint-disable no-undef */
createMarker(location, dsIndex, settings, onClickListener, markerArgs) { createMarker(location, dsIndex, settings, onClickListener, markerArgs, onDragendListener) {
var marker; var marker;
if (settings.showLabel) { if (settings.showLabel) {
marker = new MarkerWithLabel({ marker = new MarkerWithLabel({
position: location, position: location,
labelContent: '<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>', labelContent: '<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
labelClass: "tb-labels" labelClass: "tb-labels",
draggable: settings.drraggable,
}); });
} else { } else {
marker = new google.maps.Marker({ marker = new google.maps.Marker({
position: location, position: location,
draggable: settings.drraggable,
}); });
} }
var gMap = this; var gMap = this;
@ -268,6 +270,10 @@ export default class TbGoogleMap {
marker.addListener('click', onClickListener); marker.addListener('click', onClickListener);
} }
if (onDragendListener) {
marker.addListener('dragend', onDragendListener);
}
return marker; return marker;
} }
@ -476,4 +482,8 @@ export default class TbGoogleMap {
return this.tooltips; return this.tooltips;
} }
getCenter() {
return this.map.getCenter().toJSON();
}
} }

View File

@ -300,12 +300,14 @@ export default class TbImageMap {
onMarkerIconReady(iconInfo); onMarkerIconReady(iconInfo);
} }
createMarker(position, dsIndex, settings, onClickListener, markerArgs) { createMarker(position, dsIndex, settings, onClickListener, markerArgs, onDragendListener) {
var pos = this.posFunction(position.x, position.y); var pos = this.posFunction(position.x, position.y);
var x = pos.x * this.width; var x = pos.x * this.width;
var y = pos.y * this.height; var y = pos.y * this.height;
var location = this.pointToLatLng(x, y); var location = this.pointToLatLng(x, y);
var marker = L.marker(location, {});//.addTo(this.map); var marker = L.marker(location, {
draggable: settings.drraggable
});//.addTo(this.map);
marker.position = position; marker.position = position;
marker.offsetX = settings.markerOffsetX; marker.offsetX = settings.markerOffsetX;
marker.offsetY = settings.markerOffsetY; marker.offsetY = settings.markerOffsetY;
@ -327,10 +329,30 @@ export default class TbImageMap {
if (onClickListener) { if (onClickListener) {
marker.on('click', onClickListener); marker.on('click', onClickListener);
} }
if (onDragendListener) {
marker.on('dragend', ($event) => {
let newMarkerPosition = this.latLngToPoint(marker.getLatLng());
marker.position.x = this.constructor.calculateNewPosition(newMarkerPosition.x, this.width);
marker.position.y = this.constructor.calculateNewPosition(newMarkerPosition.y, this.height);
this.setMarkerPosition(marker, marker.position);
onDragendListener($event);
});
}
this.markers.push(marker); this.markers.push(marker);
return marker; return marker;
} }
static calculateNewPosition(positon, imageSize) {
let newPosition = positon / imageSize;
if (newPosition < 0) {
newPosition = 0;
} else if (newPosition > 1) {
newPosition = 1;
}
return newPosition;
}
updateMarkers() { updateMarkers() {
this.markers.forEach((marker) => { this.markers.forEach((marker) => {
this.updateMarkerLocation(marker); this.updateMarkerLocation(marker);
@ -439,6 +461,10 @@ export default class TbImageMap {
return this.tooltips; return this.tooltips;
} }
getCenter() {
return this.map.getCenter();
}
} }
class Position { class Position {

View File

@ -21,10 +21,12 @@ import TbImageMap from './image-map';
import TbTencentMap from './tencent-map'; import TbTencentMap from './tencent-map';
import {processPattern, arraysEqual, toLabelValueMap, fillPattern, fillPatternWithActions} from './widget-utils'; import {processPattern, arraysEqual, toLabelValueMap, fillPattern, fillPatternWithActions} from './widget-utils';
import addEntityPanelTemplate from './add-entity-panel.tpl.html';
import './add-entity-panel.scss';
export default class TbMapWidgetV2 { export default class TbMapWidgetV2 {
constructor(mapProvider, drawRoutes, ctx, useDynamicLocations, $element) { constructor(mapProvider, drawRoutes, ctx, useDynamicLocations, $element, isEdit) {
var tbMap = this; var tbMap = this;
this.ctx = ctx; this.ctx = ctx;
this.mapProvider = mapProvider; this.mapProvider = mapProvider;
@ -33,6 +35,7 @@ export default class TbMapWidgetV2 {
} }
this.utils = ctx.$scope.$injector.get('utils'); this.utils = ctx.$scope.$injector.get('utils');
this.drawRoutes = drawRoutes; this.drawRoutes = drawRoutes;
this.isEdit = isEdit ? isEdit : false;
this.markers = []; this.markers = [];
this.polygons = []; this.polygons = [];
if (this.drawRoutes) { if (this.drawRoutes) {
@ -292,6 +295,112 @@ export default class TbMapWidgetV2 {
} }
} }
selectEntity($event) {
var tbMap = this;
function setDefaultPosition(entity) {
let position = tbMap.map.getCenter();
if (tbMap.mapProvider === "image-map") {
position = tbMap.map.latLngToPoint(position);
position.lat = position.x / tbMap.map.width;
position.lng = position.y / tbMap.map.height;
}
tbMap.saveMarkerLocation(
entity,
locationsWithoutMarker[entitiesWithoutPosition.indexOf(entity)],
position
);
}
const element = angular.element($event.target);
const $mdPanel = this.ctx.$scope.$injector.get('$mdPanel');
const $document = this.ctx.$scope.$injector.get('$document');
let position = $mdPanel.newPanelPosition()
.relativeTo(element)
.addPanelPosition($mdPanel.xPosition.ALIGN_END, $mdPanel.yPosition.BELOW);
let locationsWithoutMarker = this.locations.filter((location) => !location.marker);
let entitiesWithoutPosition = [];
for (let i = 0; i < locationsWithoutMarker.length; i++) {
entitiesWithoutPosition.push(this.subscription.datasources[locationsWithoutMarker[i].dsIndex]);
}
if(entitiesWithoutPosition.length === 1){
setDefaultPosition(entitiesWithoutPosition[0]);
} else {
let config = {
attachTo: angular.element($document[0].body),
controller: addEntityPanelController,
controllerAs: 'vm',
templateUrl: addEntityPanelTemplate,
panelClass: 'tb-add-entity-panel',
position: position,
fullscreen: false,
locals: {
'entities': entitiesWithoutPosition,
'onClose': setDefaultPosition
},
openFrom: $event,
clickOutsideToClose: true,
escapeToClose: true,
focusOnOpen: false
};
$mdPanel.open(config);
}
}
saveMarkerLocation(datasource, location, coordinate) {
var tbMap = this;
const types = tbMap.ctx.$scope.$injector.get('types');
const $q = tbMap.ctx.$scope.$injector.get('$q');
const attributeService = tbMap.ctx.$scope.$injector.get('attributeService');
let attributesLocation = [];
let timeseriesLocation = [];
let promises = [];
let dataKeys = datasource.dataKeys;
for (let i = 0; i < dataKeys.length; i++) {
if (dataKeys[i].name === location.settings.latKeyName || dataKeys[i].name === location.settings.lngKeyName) {
let newLocation = {
key: dataKeys[i].name,
value: dataKeys[i].name === location.settings.latKeyName ? coordinate.lat : coordinate.lng
};
if (dataKeys[i].type === types.dataKeyType.attribute) {
attributesLocation.push(newLocation);
} else if (dataKeys[i].type === types.dataKeyType.timeseries) {
timeseriesLocation.push(newLocation);
}
}
}
if (attributesLocation.length > 0) {
promises.push(attributeService.saveEntityAttributes(
datasource.entityType,
datasource.entityId,
types.attributesScope.server.value,
attributesLocation,
{
ignoreLoading: true
}
))
}
if (timeseriesLocation.length > 0) {
promises.push(attributeService.saveEntityTimeseries(
datasource.entityType,
datasource.entityId,
"scope",
timeseriesLocation,
{
ignoreLoading: true
}
))
}
return $q.all([promises]);
}
update() { update() {
var tbMap = this; var tbMap = this;
@ -411,7 +520,10 @@ export default class TbMapWidgetV2 {
function (event) { function (event) {
tbMap.callbacks.onLocationClick(location); tbMap.callbacks.onLocationClick(location);
locationRowClick(event, location); locationRowClick(event, location);
}, [location.dsIndex]); }, [location.dsIndex],
function (event) {
markerDragend(event, location)
});
tbMap.markers.push(location.marker); tbMap.markers.push(location.marker);
changed = true; changed = true;
} else { } else {
@ -424,6 +536,22 @@ export default class TbMapWidgetV2 {
return changed; return changed;
} }
function markerDragend($event, location) {
if (location.settings.drraggable) {
let position = tbMap.map.getMarkerPosition(location.marker);
if (tbMap.mapProvider === "image-map") {
position.lat = position.x;
position.lng = position.y;
delete position.x;
delete position.y;
} else if (tbMap.mapProvider === "google-map") {
position = position.toJSON();
}
tbMap.saveMarkerLocation(tbMap.subscription.datasources[location.dsIndex], location, position);
}
}
function locationRowClick($event, location) { function locationRowClick($event, location) {
var descriptors = tbMap.ctx.actionsApi.getActionDescriptors('markerClick'); var descriptors = tbMap.ctx.actionsApi.getActionDescriptors('markerClick');
if (descriptors.length) { if (descriptors.length) {
@ -567,6 +695,7 @@ export default class TbMapWidgetV2 {
location.settings.tooltipPattern = tbMap.utils.createLabelFromDatasource(currentDatasource, location.settings.tooltipPattern); location.settings.tooltipPattern = tbMap.utils.createLabelFromDatasource(currentDatasource, location.settings.tooltipPattern);
location.settings.tooltipReplaceInfo = processPattern(location.settings.tooltipPattern, datasources, currentDatasourceIndex); location.settings.tooltipReplaceInfo = processPattern(location.settings.tooltipPattern, datasources, currentDatasourceIndex);
} }
location.settings.drraggable = tbMap.isEdit;
tbMap.locations.push(location); tbMap.locations.push(location);
updateLocation(location, data, dataMap); updateLocation(location, data, dataMap);
if (!tbMap.locationSettings.useDefaultCenterPosition) { if (!tbMap.locationSettings.useDefaultCenterPosition) {
@ -1626,3 +1755,16 @@ const imageMapSettingsSchema =
} }
] ]
}; };
/*@ngInject*/
function addEntityPanelController(mdPanelRef, entities) {
var vm = this;
vm.entities = entities;
vm.selectEntity = selectEntity;
function selectEntity(entity) {
mdPanelRef.close().then(() => {
this.onClose(entity);
});
}
}

View File

@ -29,7 +29,7 @@ export default class TbOpenStreetMap {
this.dontFitMapBounds = dontFitMapBounds; this.dontFitMapBounds = dontFitMapBounds;
this.minZoomLevel = minZoomLevel; this.minZoomLevel = minZoomLevel;
this.tooltips = []; this.tooltips = [];
this.isMarketCluster = markerClusteringSetting.isMarketCluster; this.isMarketCluster = markerClusteringSetting && markerClusteringSetting.isMarketCluster;
if (!mapProvider) { if (!mapProvider) {
mapProvider = { mapProvider = {
@ -150,8 +150,10 @@ export default class TbOpenStreetMap {
onMarkerIconReady(iconInfo); onMarkerIconReady(iconInfo);
} }
createMarker(location, dsIndex, settings, onClickListener, markerArgs) { createMarker(location, dsIndex, settings, onClickListener, markerArgs, onDragendListener) {
var marker = L.marker(location, {}); var marker = L.marker(location, {
draggable: settings.drraggable
});
var opMap = this; var opMap = this;
this.createMarkerIcon(marker, settings, (iconInfo) => { this.createMarkerIcon(marker, settings, (iconInfo) => {
marker.setIcon(iconInfo.icon); marker.setIcon(iconInfo.icon);
@ -171,6 +173,10 @@ export default class TbOpenStreetMap {
marker.on('click', onClickListener); marker.on('click', onClickListener);
} }
if (onDragendListener) {
marker.on('dragend', onDragendListener);
}
return marker; return marker;
} }
@ -326,4 +332,8 @@ export default class TbOpenStreetMap {
return this.tooltips; return this.tooltips;
} }
getCenter() {
return this.map.getCenter();
}
} }

View File

@ -28,7 +28,7 @@ export default class TbTencentMap {
this.tooltips = []; this.tooltips = [];
this.defaultMapType = tmDefaultMapType; this.defaultMapType = tmDefaultMapType;
this.defaultCenterPosition =defaultCenterPosition; this.defaultCenterPosition =defaultCenterPosition;
this.isMarketCluster = markerClusteringSetting.isMarketCluster; this.isMarketCluster = markerClusteringSetting && markerClusteringSetting.isMarketCluster;
function clearGlobalId() { function clearGlobalId() {
if (tmGlobals.loadingTmId && tmGlobals.loadingTmId === tbMap.mapId) { if (tmGlobals.loadingTmId && tmGlobals.loadingTmId === tbMap.mapId) {
@ -239,7 +239,7 @@ export default class TbTencentMap {
/* eslint-enable no-undef */ /* eslint-enable no-undef */
/* eslint-disable no-undef */ /* eslint-disable no-undef */
createMarker(location, dsIndex, settings, onClickListener, markerArgs) { createMarker(location, dsIndex, settings, onClickListener, markerArgs, onDragendListener) {
var marker = new qq.maps.Marker({ var marker = new qq.maps.Marker({
position: location position: location
}); });
@ -260,7 +260,8 @@ export default class TbTencentMap {
visible: true, visible: true,
position: location, position: location,
map: tMap.map, map: tMap.map,
zIndex: 1000 zIndex: 1000,
draggable: settings.drraggable
}); });
} }
}); });
@ -273,6 +274,10 @@ export default class TbTencentMap {
qq.maps.event.addListener(marker, 'click', onClickListener); qq.maps.event.addListener(marker, 'click', onClickListener);
} }
if (onDragendListener) {
qq.maps.event.addListener(marker, 'dragend', onDragendListener);
}
return marker; return marker;
} }
@ -487,4 +492,8 @@ export default class TbTencentMap {
return this.tooltips; return this.tooltips;
} }
getCenter() {
return this.map.getCenter();
}
} }