Browse Source

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

pull/2163/head
Vladyslav 7 years ago
committed by Igor Kulikov
parent
commit
ac8e67eff0
  1. 48
      application/src/main/data/json/system/widget_bundles/input_widgets.json
  2. 27
      ui/src/app/widget/lib/add-entity-panel.scss
  3. 22
      ui/src/app/widget/lib/add-entity-panel.tpl.html
  4. 16
      ui/src/app/widget/lib/google-map.js
  5. 30
      ui/src/app/widget/lib/image-map.js
  6. 146
      ui/src/app/widget/lib/map-widget2.js
  7. 16
      ui/src/app/widget/lib/openstreet-map.js
  8. 15
      ui/src/app/widget/lib/tencent-map.js

48
application/src/main/data/json/system/widget_bundles/input_widgets.json

File diff suppressed because one or more lines are too long

27
ui/src/app/widget/lib/add-entity-panel.scss

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

22
ui/src/app/widget/lib/add-entity-panel.tpl.html

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

16
ui/src/app/widget/lib/google-map.js

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

30
ui/src/app/widget/lib/image-map.js

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

146
ui/src/app/widget/lib/map-widget2.js

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

16
ui/src/app/widget/lib/openstreet-map.js

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

15
ui/src/app/widget/lib/tencent-map.js

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

Loading…
Cancel
Save