TB-70: Map widget actions.
This commit is contained in:
parent
f7f9b8948c
commit
ecac20dc50
File diff suppressed because one or more lines are too long
@ -1220,7 +1220,9 @@ export default angular.module('thingsboard.locale', [])
|
||||
"custom": {
|
||||
"widget-action": {
|
||||
"action-cell-button": "Action cell button",
|
||||
"row-click": "On row click"
|
||||
"row-click": "On row click",
|
||||
"marker-click": "On marker click",
|
||||
"tooltip-tag-action": "Tooltip tag action"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ export default class TbGoogleMap {
|
||||
/* eslint-enable no-undef */
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
createMarker(location, settings, onClickListener) {
|
||||
createMarker(location, settings, onClickListener, markerArgs) {
|
||||
var height = 34;
|
||||
var pinColor = settings.color.substr(1);
|
||||
var pinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor,
|
||||
@ -224,7 +224,7 @@ export default class TbGoogleMap {
|
||||
}
|
||||
|
||||
if (settings.displayTooltip) {
|
||||
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo);
|
||||
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, markerArgs);
|
||||
}
|
||||
|
||||
if (onClickListener) {
|
||||
@ -241,7 +241,7 @@ export default class TbGoogleMap {
|
||||
/* eslint-enable no-undef */
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
createTooltip(marker, pattern, replaceInfo) {
|
||||
createTooltip(marker, pattern, replaceInfo, markerArgs) {
|
||||
var popup = new google.maps.InfoWindow({
|
||||
content: ''
|
||||
});
|
||||
@ -249,6 +249,7 @@ export default class TbGoogleMap {
|
||||
popup.open(this.map, marker);
|
||||
});
|
||||
this.tooltips.push( {
|
||||
markerArgs: markerArgs,
|
||||
popup: popup,
|
||||
pattern: pattern,
|
||||
replaceInfo: replaceInfo
|
||||
|
||||
@ -19,7 +19,7 @@ import tinycolor from 'tinycolor2';
|
||||
import TbGoogleMap from './google-map';
|
||||
import TbOpenStreetMap from './openstreet-map';
|
||||
|
||||
import {processPattern, arraysEqual, toLabelValueMap, fillPattern} from './widget-utils';
|
||||
import {processPattern, arraysEqual, toLabelValueMap, fillPattern, fillPatternWithActions} from './widget-utils';
|
||||
|
||||
export default class TbMapWidgetV2 {
|
||||
constructor(mapProvider, drawRoutes, ctx, useDynamicLocations, $element) {
|
||||
@ -63,6 +63,15 @@ export default class TbMapWidgetV2 {
|
||||
tbMap.resize();
|
||||
};
|
||||
|
||||
this.ctx.$scope.onTooltipAction = function(event, actionName, dsIndex) {
|
||||
tbMap.onTooltipAction(event, actionName, dsIndex);
|
||||
};
|
||||
this.tooltipActionsMap = {};
|
||||
var descriptors = this.ctx.actionsApi.getActionDescriptors('tooltipAction');
|
||||
descriptors.forEach(function (descriptor) {
|
||||
tbMap.tooltipActionsMap[descriptor.name] = descriptor;
|
||||
});
|
||||
|
||||
if (mapProvider === 'google-map') {
|
||||
this.map = new TbGoogleMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType);
|
||||
} else if (mapProvider === 'openstreet-map') {
|
||||
@ -145,6 +154,18 @@ export default class TbMapWidgetV2 {
|
||||
}
|
||||
}
|
||||
|
||||
onTooltipAction(event, actionName, dsIndex) {
|
||||
var descriptor = this.tooltipActionsMap[actionName];
|
||||
if (descriptor) {
|
||||
var datasource = this.subscription.datasources[dsIndex];
|
||||
var entityId = {};
|
||||
entityId.id = datasource.entityId;
|
||||
entityId.entityType = datasource.entityType;
|
||||
var entityName = datasource.entityName;
|
||||
this.ctx.actionsApi.handleWidgetAction(event, descriptor, entityId, entityName);
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
|
||||
var tbMap = this;
|
||||
@ -159,10 +180,11 @@ export default class TbMapWidgetV2 {
|
||||
|
||||
function calculateLocationColor(location, dataMap) {
|
||||
if (location.settings.useColorFunction && location.settings.colorFunction) {
|
||||
var color = '#FE7569';
|
||||
var color;
|
||||
try {
|
||||
color = location.settings.colorFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex);
|
||||
} catch (e) {
|
||||
} catch (e) {/**/}
|
||||
if (!color) {
|
||||
color = '#FE7569';
|
||||
}
|
||||
return tinycolor(color).toHexString();
|
||||
@ -212,6 +234,18 @@ export default class TbMapWidgetV2 {
|
||||
updateLocationMarkerImage(location, image);
|
||||
}
|
||||
|
||||
function locationRowClick($event, location) {
|
||||
var descriptors = tbMap.ctx.actionsApi.getActionDescriptors('markerClick');
|
||||
if (descriptors.length) {
|
||||
var datasource = tbMap.subscription.datasources[location.dsIndex];
|
||||
var entityId = {};
|
||||
entityId.id = datasource.entityId;
|
||||
entityId.entityType = datasource.entityType;
|
||||
var entityName = datasource.entityName;
|
||||
tbMap.ctx.actionsApi.handleWidgetAction($event, descriptors[0], entityId, entityName);
|
||||
}
|
||||
}
|
||||
|
||||
function updateLocation(location, data, dataMap) {
|
||||
var locationChanged = false;
|
||||
if (location.latIndex > -1 && location.lngIndex > -1) {
|
||||
@ -234,9 +268,10 @@ export default class TbMapWidgetV2 {
|
||||
var markerLocation = latLngs[latLngs.length - 1];
|
||||
if (!location.marker) {
|
||||
location.marker = tbMap.map.createMarker(markerLocation, location.settings,
|
||||
function () {
|
||||
function (event) {
|
||||
tbMap.callbacks.onLocationClick(location);
|
||||
}
|
||||
locationRowClick(event, location);
|
||||
}, [location.dsIndex]
|
||||
);
|
||||
} else {
|
||||
tbMap.map.setMarkerPosition(location.marker, markerLocation);
|
||||
@ -259,9 +294,11 @@ export default class TbMapWidgetV2 {
|
||||
lng = lngData[lngData.length - 1][1];
|
||||
latLng = tbMap.map.createLatLng(lat, lng);
|
||||
if (!location.marker) {
|
||||
location.marker = tbMap.map.createMarker(latLng, location.settings, function () {
|
||||
location.marker = tbMap.map.createMarker(latLng, location.settings,
|
||||
function (event) {
|
||||
tbMap.callbacks.onLocationClick(location);
|
||||
});
|
||||
locationRowClick(event, location);
|
||||
}, [location.dsIndex]);
|
||||
tbMap.markers.push(location.marker);
|
||||
locationChanged = true;
|
||||
} else {
|
||||
@ -368,6 +405,7 @@ export default class TbMapWidgetV2 {
|
||||
for (var t=0; t < tooltips.length; t++) {
|
||||
var tooltip = tooltips[t];
|
||||
var text = fillPattern(tooltip.pattern, tooltip.replaceInfo, this.subscription.data);
|
||||
text = fillPatternWithActions(text, 'onTooltipAction', tooltip.markerArgs);
|
||||
tooltip.popup.setContent(text);
|
||||
}
|
||||
}
|
||||
@ -414,6 +452,19 @@ export default class TbMapWidgetV2 {
|
||||
return {};
|
||||
}
|
||||
|
||||
static actionSources() {
|
||||
return {
|
||||
'markerClick': {
|
||||
name: 'widget-action.marker-click',
|
||||
multiple: false
|
||||
},
|
||||
'tooltipAction': {
|
||||
name: 'widget-action.tooltip-tag-action',
|
||||
multiple: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const googleMapSettingsSchema =
|
||||
@ -509,12 +560,12 @@ const commonMapSettingsSchema =
|
||||
"default":true
|
||||
},
|
||||
"label":{
|
||||
"title":"Label",
|
||||
"title":"Label (pattern examples: '${entityName}', '${entityName}: (Text ${keyName} units.)' )",
|
||||
"type":"string",
|
||||
"default":"${entityName}"
|
||||
},
|
||||
"tooltipPattern":{
|
||||
"title":"Pattern ( for ex. 'Text ${keyName} units.' or '${#<key index>} units' )",
|
||||
"title":"Tooltip (for ex. 'Text ${keyName} units.' or <link-act name='my-action'>Link text</link-act>')",
|
||||
"type":"string",
|
||||
"default":"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}"
|
||||
},
|
||||
@ -567,7 +618,10 @@ const commonMapSettingsSchema =
|
||||
"lngKeyName",
|
||||
"showLabel",
|
||||
"label",
|
||||
"tooltipPattern",
|
||||
{
|
||||
"key": "tooltipPattern",
|
||||
"type": "textarea"
|
||||
},
|
||||
{
|
||||
"key":"color",
|
||||
"type":"color"
|
||||
|
||||
@ -92,7 +92,7 @@ export default class TbOpenStreetMap {
|
||||
testImage.src = image;
|
||||
}
|
||||
|
||||
createMarker(location, settings, onClickListener) {
|
||||
createMarker(location, settings, onClickListener, markerArgs) {
|
||||
var height = 34;
|
||||
var pinColor = settings.color.substr(1);
|
||||
var icon = L.icon({
|
||||
@ -118,7 +118,7 @@ export default class TbOpenStreetMap {
|
||||
}
|
||||
|
||||
if (settings.displayTooltip) {
|
||||
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo);
|
||||
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, markerArgs);
|
||||
}
|
||||
|
||||
if (onClickListener) {
|
||||
@ -132,11 +132,12 @@ export default class TbOpenStreetMap {
|
||||
this.map.removeLayer(marker);
|
||||
}
|
||||
|
||||
createTooltip(marker, pattern, replaceInfo) {
|
||||
createTooltip(marker, pattern, replaceInfo, markerArgs) {
|
||||
var popup = L.popup();
|
||||
popup.setContent('');
|
||||
marker.bindPopup(popup, {autoClose: false, closeOnClick: false});
|
||||
this.tooltips.push( {
|
||||
markerArgs: markerArgs,
|
||||
popup: popup,
|
||||
pattern: pattern,
|
||||
replaceInfo: replaceInfo
|
||||
|
||||
@ -16,6 +16,9 @@
|
||||
|
||||
const varsRegex = /\$\{([^\}]*)\}/g;
|
||||
|
||||
const linkActionRegex = /\<link-act name=['"]([^['"]*)['"]\>([^\<]*)\<\/link-act\>/g;
|
||||
const buttonActionRegex = /\<button-act name=['"]([^['"]*)['"]\>([^\<]*)\<\/button-act\>/g;
|
||||
|
||||
export function processPattern(pattern, datasources, dsIndex) {
|
||||
var match = varsRegex.exec(pattern);
|
||||
var replaceInfo = {};
|
||||
@ -90,6 +93,49 @@ export function fillPattern(pattern, replaceInfo, data) {
|
||||
return text;
|
||||
}
|
||||
|
||||
function createLink(actionName, actionText, actionCallbackName, additionalArgs) {
|
||||
var args = 'event,\''+actionName+'\'';
|
||||
if (additionalArgs && additionalArgs.length) {
|
||||
args += ','+additionalArgs.join();
|
||||
}
|
||||
return '<a href="#" onclick="angular.element(this).scope().'+actionCallbackName+'('+args+'); return false;">'+actionText+'</a>';
|
||||
}
|
||||
|
||||
function createButton(actionName, actionText, actionCallbackName, additionalArgs) {
|
||||
var args = 'event,\''+actionName+'\'';
|
||||
if (additionalArgs && additionalArgs.length) {
|
||||
args += ','+additionalArgs.join();
|
||||
}
|
||||
return '<button onclick="angular.element(this).scope().'+actionCallbackName+'('+args+'); return false;">'+actionText+'</button>';
|
||||
}
|
||||
|
||||
export function fillPatternWithActions(pattern, actionCallbackName, additionalArgs) {
|
||||
var text = angular.copy(pattern);
|
||||
var match = linkActionRegex.exec(pattern);
|
||||
var actionTags;
|
||||
var actionName;
|
||||
var actionText;
|
||||
var actionHtml;
|
||||
while (match !== null) {
|
||||
actionTags = match[0];
|
||||
actionName = match[1];
|
||||
actionText = match[2];
|
||||
actionHtml = createLink(actionName, actionText, actionCallbackName, additionalArgs);
|
||||
text = text.split(actionTags).join(actionHtml);
|
||||
match = linkActionRegex.exec(pattern);
|
||||
}
|
||||
match = buttonActionRegex.exec(pattern);
|
||||
while (match !== null) {
|
||||
actionTags = match[0];
|
||||
actionName = match[1];
|
||||
actionText = match[2];
|
||||
actionHtml = createButton(actionName, actionText, actionCallbackName, additionalArgs);
|
||||
text = text.split(actionTags).join(actionHtml);
|
||||
match = buttonActionRegex.exec(pattern);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
export function toLabelValueMap(data, datasources) {
|
||||
var dataMap = {};
|
||||
var dsDataMap = [];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user