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

View File

@ -300,12 +300,14 @@ export default class TbImageMap {
onMarkerIconReady(iconInfo);
}
createMarker(position, dsIndex, settings, onClickListener, markerArgs) {
createMarker(position, dsIndex, settings, onClickListener, markerArgs, onDragendListener) {
var pos = this.posFunction(position.x, position.y);
var x = pos.x * this.width;
var y = pos.y * this.height;
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.offsetX = settings.markerOffsetX;
marker.offsetY = settings.markerOffsetY;
@ -327,10 +329,30 @@ export default class TbImageMap {
if (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);
return marker;
}
static calculateNewPosition(positon, imageSize) {
let newPosition = positon / imageSize;
if (newPosition < 0) {
newPosition = 0;
} else if (newPosition > 1) {
newPosition = 1;
}
return newPosition;
}
updateMarkers() {
this.markers.forEach((marker) => {
this.updateMarkerLocation(marker);
@ -439,6 +461,10 @@ export default class TbImageMap {
return this.tooltips;
}
getCenter() {
return this.map.getCenter();
}
}
class Position {

View File

@ -21,10 +21,12 @@ import TbImageMap from './image-map';
import TbTencentMap from './tencent-map';
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 {
constructor(mapProvider, drawRoutes, ctx, useDynamicLocations, $element) {
constructor(mapProvider, drawRoutes, ctx, useDynamicLocations, $element, isEdit) {
var tbMap = this;
this.ctx = ctx;
this.mapProvider = mapProvider;
@ -33,6 +35,7 @@ export default class TbMapWidgetV2 {
}
this.utils = ctx.$scope.$injector.get('utils');
this.drawRoutes = drawRoutes;
this.isEdit = isEdit ? isEdit : false;
this.markers = [];
this.polygons = [];
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() {
var tbMap = this;
@ -411,7 +520,10 @@ export default class TbMapWidgetV2 {
function (event) {
tbMap.callbacks.onLocationClick(location);
locationRowClick(event, location);
}, [location.dsIndex]);
}, [location.dsIndex],
function (event) {
markerDragend(event, location)
});
tbMap.markers.push(location.marker);
changed = true;
} else {
@ -424,6 +536,22 @@ export default class TbMapWidgetV2 {
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) {
var descriptors = tbMap.ctx.actionsApi.getActionDescriptors('markerClick');
if (descriptors.length) {
@ -567,6 +695,7 @@ export default class TbMapWidgetV2 {
location.settings.tooltipPattern = tbMap.utils.createLabelFromDatasource(currentDatasource, location.settings.tooltipPattern);
location.settings.tooltipReplaceInfo = processPattern(location.settings.tooltipPattern, datasources, currentDatasourceIndex);
}
location.settings.drraggable = tbMap.isEdit;
tbMap.locations.push(location);
updateLocation(location, data, dataMap);
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.minZoomLevel = minZoomLevel;
this.tooltips = [];
this.isMarketCluster = markerClusteringSetting.isMarketCluster;
this.isMarketCluster = markerClusteringSetting && markerClusteringSetting.isMarketCluster;
if (!mapProvider) {
mapProvider = {
@ -150,8 +150,10 @@ export default class TbOpenStreetMap {
onMarkerIconReady(iconInfo);
}
createMarker(location, dsIndex, settings, onClickListener, markerArgs) {
var marker = L.marker(location, {});
createMarker(location, dsIndex, settings, onClickListener, markerArgs, onDragendListener) {
var marker = L.marker(location, {
draggable: settings.drraggable
});
var opMap = this;
this.createMarkerIcon(marker, settings, (iconInfo) => {
marker.setIcon(iconInfo.icon);
@ -171,6 +173,10 @@ export default class TbOpenStreetMap {
marker.on('click', onClickListener);
}
if (onDragendListener) {
marker.on('dragend', onDragendListener);
}
return marker;
}
@ -326,4 +332,8 @@ export default class TbOpenStreetMap {
return this.tooltips;
}
getCenter() {
return this.map.getCenter();
}
}

View File

@ -28,7 +28,7 @@ export default class TbTencentMap {
this.tooltips = [];
this.defaultMapType = tmDefaultMapType;
this.defaultCenterPosition =defaultCenterPosition;
this.isMarketCluster = markerClusteringSetting.isMarketCluster;
this.isMarketCluster = markerClusteringSetting && markerClusteringSetting.isMarketCluster;
function clearGlobalId() {
if (tmGlobals.loadingTmId && tmGlobals.loadingTmId === tbMap.mapId) {
@ -239,7 +239,7 @@ export default class TbTencentMap {
/* eslint-enable 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({
position: location
});
@ -260,7 +260,8 @@ export default class TbTencentMap {
visible: true,
position: location,
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);
}
if (onDragendListener) {
qq.maps.event.addListener(marker, 'dragend', onDragendListener);
}
return marker;
}
@ -487,4 +492,8 @@ export default class TbTencentMap {
return this.tooltips;
}
getCenter() {
return this.map.getCenter();
}
}