|
实体视图别名在仪表板中必须是唯一的。",
+ "configure-alias": "配置 '{{alias}}' 别名",
+ "no-entity-views-matching": "没有实体视图匹配 '{{entity}}' 被找到。",
+ "alias": "别名",
+ "alias-required": "视图实体别名必填。",
+ "remove-alias": "移除视图实体别名",
+ "add-alias": "添加视图实体别名",
+ "name-starts-with": "实体视图名称前缀",
+ "entity-view-list": "实体视图列表",
+ "use-entity-view-name-filter": "使用过滤器",
+ "entity-view-list-empty": "未选择任何实体视图。",
+ "entity-view-name-filter-required": "实体视图名称过滤器必填。",
+ "entity-view-name-filter-no-entity-view-matched": "没有实体视图名称前缀 '{{entityView}}' 被找到。",
+ "add": "添加视图实体",
+ "assign-to-customer": "分配给客户",
+ "assign-entity-view-to-customer": "将实体视图分配给客户",
+ "assign-entity-view-to-customer-text": "请选择要分配给客户的实体视图",
+ "no-entity-views-text": "找不到实体视图",
+ "assign-to-customer-text": "请选择客户以分配实体视图",
+ "entity-view-details": "实体视图详细信息",
+ "add-entity-view-text": "添加新的实体视图",
+ "delete": "删除实体视图",
+ "assign-entity-views": "分配实体视图",
+ "assign-entity-views-text": "分配 { count, plural, 1 {1 实体视图} other {# 实体视图} } 给客户",
+ "delete-entity-views": "移除实体视图",
+ "unassign-from-customer": "取消分配客户",
+ "unassign-entity-views": "取消分配实体视图",
+ "unassign-entity-views-action-title": "从客户处取消分配 { count, plural, 1 {1 实体视图} other {# 实体视图} }",
+ "assign-new-entity-view": "分配新的实体视图",
+ "delete-entity-view-title": "您确定要删除实体视图 '{{entityViewName}}'吗?",
+ "delete-entity-view-text": "请注意,在确认后实体视图和所有相关数据将变得不可恢复。",
+ "delete-entity-views-title": "你确定要删除 { count, plural, 1 {1 实体视图} other {# 实体视图} }吗?",
+ "delete-entity-views-action-title": "删除 { count, plural, 1 {1 实体视图} other {# 实体视图} }",
+ "delete-entity-views-text": "请注意,在确认后将删除所有选定的实体视图,并且所有相关数据将变为不可恢复。",
+ "unassign-entity-view-title": "您确定要取消分配实体视图 '{{entityViewName}}'吗?",
+ "unassign-entity-view-text": "确认后,实体视图将被取消分配,客户将无法访问。",
+ "unassign-entity-view": "取消分配实体视图",
+ "unassign-entity-views-title": "你确定要取消分配 { count, plural, 1 {1 实体视图} other {# 实体视图} }吗?",
+ "unassign-entity-views-text": "确认后,所有选定的实体视图都将被取消分配,客户将无法访问。",
+ "entity-view-type": "实体视图类型",
+ "entity-view-type-required": "实体视图类型必填。",
+ "select-entity-view-type": "选择实体视图类型",
+ "enter-entity-view-type": "输入实体视图类型",
+ "any-entity-view": "任何实体视图",
+ "no-entity-view-types-matching": "没有找到匹配 '{{entitySubtype}}' 的实体视图类型。",
+ "entity-view-type-list-empty": "未选择任何实体视图类型。",
+ "entity-view-types": "实体视图类型",
+ "name": "名称",
+ "name-required": "名称必填。",
+ "description": "描述",
+ "events": "事件",
+ "details": "详情",
+ "copyId": "复制实体视图ID",
+ "assignedToCustomer": "分配给客户",
+ "unable-entity-view-device-alias-title": "无法删除实体视图别名",
+ "unable-entity-view-device-alias-text": "设备别名 '{{entityViewAlias}}' 无法删除,因为它由以下小部件使用: {{widgetsList}}",
+ "select-entity-view": "选择实体视图",
+ "make-public": "将实体视图公开",
+ "make-private": "将实体视图设为私有",
+ "start-date": "开始日期",
+ "start-ts": "开始时间",
+ "end-date": "结束日期",
+ "end-ts": "结束时间",
+ "date-limits": "日期范围",
+ "client-attributes": "客户属性",
+ "shared-attributes": "共享属性",
+ "server-attributes": "服务器属性",
+ "timeseries": "时间序列",
+ "client-attributes-placeholder": "客户属性",
+ "shared-attributes-placeholder": "共享属性",
+ "server-attributes-placeholder": "服务器属性",
+ "timeseries-placeholder": "时间序列",
+ "target-entity": "目标实体",
+ "attributes-propagation": "属性传播",
+ "attributes-propagation-hint": "每次保存或更新此实体视图时,实体视图将自动从目标实体复制指定的属性。出于性能原因,目标实体属性不会在每次属性更改时传播到实体视图。通过在规则链中配置“copy to view”规则节点,并将“Post attributes”和“Attributes Updated”消息链接到新的规则节点,可以启用自动传播。",
+ "timeseries-data": "时间序列数据",
+ "timeseries-data-hint": "配置实体视图可访问目标实体的时间序列数据键。此时间序列数据是只读的。",
+ "make-public-entity-view-title": "您确定要将实体视图 '{{entityViewName}}' 设为公开吗?",
+ "make-public-entity-view-text": "确认后,设备及其所有数据将被设为公开并可被其他人访问。",
+ "make-private-entity-view-title": "您确定要将实体视图 '{{entityViewName}}' 设为私有吗?",
+ "make-private-entity-view-text": "确认后,设备及其所有数据将被设为私有,不被其他人访问。"
+ },
"event": {
"event-type": "事件类型",
"type-error": "错误",
@@ -1442,7 +1538,7 @@
"Dec": "12月",
"January": "一月",
"February": "二月",
- "March": "游行",
+ "March": "三月",
"April": "四月",
"June": "六月",
"July": "七月",
@@ -1472,7 +1568,7 @@
"6 months": "6个月",
"Custom interval": "自定义间隔",
"Interval": "间隔",
- "Step size": "一步的大小",
+ "Step size": "步长",
"Ok": "Ok"
}
}
@@ -1509,4 +1605,4 @@
"uk_UA": "乌克兰"
}
}
-}
\ No newline at end of file
+}
diff --git a/ui/src/app/widget/lib/google-map.js b/ui/src/app/widget/lib/google-map.js
index a21f7a0876..6acbc3e988 100644
--- a/ui/src/app/widget/lib/google-map.js
+++ b/ui/src/app/widget/lib/google-map.js
@@ -19,7 +19,7 @@ var gmGlobals = {
}
export default class TbGoogleMap {
- constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, gmApiKey, gmDefaultMapType) {
+ constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, gmApiKey, gmDefaultMapType) {
var tbMap = this;
this.utils = utils;
@@ -44,7 +44,7 @@ export default class TbGoogleMap {
function initGoogleMap() {
tbMap.map = new google.maps.Map($containerElement[0], { // eslint-disable-line no-undef
- scrollwheel: true,
+ scrollwheel: !disableScrollZooming,
mapTypeId: getGoogleMapTypeId(tbMap.defaultMapType),
zoom: tbMap.defaultZoomLevel || 8
});
diff --git a/ui/src/app/widget/lib/image-map.js b/ui/src/app/widget/lib/image-map.js
index 1c50bae14b..17f0b13af3 100644
--- a/ui/src/app/widget/lib/image-map.js
+++ b/ui/src/app/widget/lib/image-map.js
@@ -20,7 +20,7 @@ const maxZoom = 4;
export default class TbImageMap {
- constructor(ctx, $containerElement, utils, initCallback, imageUrl, posFunction, imageEntityAlias, imageUrlAttribute) {
+ constructor(ctx, $containerElement, utils, initCallback, imageUrl, disableScrollZooming, posFunction, imageEntityAlias, imageUrlAttribute) {
this.ctx = ctx;
this.utils = utils;
@@ -34,6 +34,7 @@ export default class TbImageMap {
this.height = 0;
this.markers = [];
this.initCallback = initCallback;
+ this.disableScrollZooming = disableScrollZooming;
if (angular.isDefined(posFunction) && posFunction.length > 0) {
try {
@@ -165,6 +166,7 @@ export default class TbImageMap {
this.map = L.map(this.$containerElement[0], {
minZoom: 1,
maxZoom: maxZoom,
+ scrollWheelZoom: !this.disableScrollZooming,
center: center,
zoom: 1,
crs: L.CRS.Simple,
diff --git a/ui/src/app/widget/lib/map-widget2.js b/ui/src/app/widget/lib/map-widget2.js
index f330bd61bf..fac3de7aa2 100644
--- a/ui/src/app/widget/lib/map-widget2.js
+++ b/ui/src/app/widget/lib/map-widget2.js
@@ -78,18 +78,29 @@ export default class TbMapWidgetV2 {
tbMap.tooltipActionsMap[descriptor.name] = descriptor;
});
+ let openStreetMapProvider = {};
if (mapProvider === 'google-map') {
- this.map = new TbGoogleMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType);
+ this.map = new TbGoogleMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType);
} else if (mapProvider === 'openstreet-map') {
- this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.mapProvider);
+ if (settings.useCustomProvider && settings.customProviderTileUrl) {
+ openStreetMapProvider.name = settings.customProviderTileUrl;
+ openStreetMapProvider.isCustom = true;
+ } else {
+ openStreetMapProvider.name = settings.mapProvider;
+ }
+ this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, openStreetMapProvider);
+ } else if (mapProvider === 'here') {
+ openStreetMapProvider.name = settings.mapProvider;
+ this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, openStreetMapProvider, settings.credentials);
} else if (mapProvider === 'image-map') {
this.map = new TbImageMap(this.ctx, $element, this.utils, initCallback,
settings.mapImageUrl,
+ settings.disableScrollZooming,
settings.posFunction,
settings.imageEntityAlias,
settings.imageUrlAttribute);
} else if (mapProvider === 'tencent-map') {
- this.map = new TbTencentMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.tmApiKey, settings.tmDefaultMapType);
+ this.map = new TbTencentMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, settings.tmApiKey, settings.tmDefaultMapType);
}
@@ -663,6 +674,8 @@ export default class TbMapWidgetV2 {
return imageMapSettingsSchema;
} else if (mapProvider === 'tencent-map') {
schema = angular.copy(tencentMapSettingsSchema);
+ } else if (mapProvider === 'here') {
+ schema = angular.copy(hereMapSettingsSchema);
}
angular.merge(schema.schema.properties, commonMapSettingsSchema.schema.properties);
schema.schema.required = schema.schema.required.concat(commonMapSettingsSchema.schema.required);
@@ -790,6 +803,62 @@ const tencentMapSettingsSchema =
]
};
+const hereMapSettingsSchema =
+ {
+ "schema": {
+ "title": "HERE Map Configuration",
+ "type": "object",
+ "properties": {
+ "mapProvider": {
+ "title": "Map layer",
+ "type": "string",
+ "default": "HERE.normalDay"
+ },
+ "credentials":{
+ "type": "object",
+ "properties": {
+ "app_id": {
+ "title": "HERE app id",
+ "type": "string"
+ },
+ "app_code": {
+ "title": "HERE app code",
+ "type": "string"
+ }
+ },
+ "required": ["app_id", "app_code"]
+ }
+ },
+ "required": []
+ },
+ "form": [
+ {
+ "key": "mapProvider",
+ "type": "rc-select",
+ "multiple": false,
+ "items": [
+ {
+ "value": "HERE.normalDay",
+ "label": "HERE.normalDay (Default)"
+ },
+ {
+ "value": "HERE.normalNight",
+ "label": "HERE.normalNight"
+ },
+ {
+ "value": "HERE.hybridDay",
+ "label": "HERE.hybridDay"
+ },
+ {
+ "value": "HERE.terrainDay",
+ "label": "HERE.terrainDay"
+ }
+ ]
+ },
+ "credentials"
+ ]
+ };
+
const openstreetMapSettingsSchema =
{
"schema": {
@@ -800,7 +869,17 @@ const openstreetMapSettingsSchema =
"title": "Map provider",
"type": "string",
"default": "OpenStreetMap.Mapnik"
- }
+ },
+ "useCustomProvider": {
+ "title": "Use custom provider",
+ "type": "boolean",
+ "default": false
+ },
+ "customProviderTileUrl": {
+ "title": "Custom provider tile URL",
+ "type": "string",
+ "default": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
+ }
},
"required": []
},
@@ -839,7 +918,9 @@ const openstreetMapSettingsSchema =
"label": "CartoDB.DarkMatter"
}
]
- }
+ },
+ "useCustomProvider",
+ "customProviderTileUrl"
]
};
@@ -858,6 +939,11 @@ const commonMapSettingsSchema =
"type": "boolean",
"default": true
},
+ "disableScrollZooming": {
+ "title": "Disable scroll zooming",
+ "type": "boolean",
+ "default": false
+ },
"latKeyName": {
"title": "Latitude key name",
"type": "string",
@@ -998,6 +1084,7 @@ const commonMapSettingsSchema =
"form": [
"defaultZoomLevel",
"fitMapBounds",
+ "disableScrollZooming",
"latKeyName",
"lngKeyName",
"showLabel",
@@ -1109,6 +1196,11 @@ const imageMapSettingsSchema =
"type": "string",
"default": ""
},
+ "disableScrollZooming": {
+ "title": "Disable scroll zooming",
+ "type": "boolean",
+ "default": false
+ },
"xPosKeyName": {
"title": "X position key name",
"type": "string",
@@ -1226,6 +1318,7 @@ const imageMapSettingsSchema =
},
"imageEntityAlias",
"imageUrlAttribute",
+ "disableScrollZooming",
"xPosKeyName",
"yPosKeyName",
"showLabel",
diff --git a/ui/src/app/widget/lib/openstreet-map.js b/ui/src/app/widget/lib/openstreet-map.js
index 33f9ae09e2..c7d253ea3f 100644
--- a/ui/src/app/widget/lib/openstreet-map.js
+++ b/ui/src/app/widget/lib/openstreet-map.js
@@ -19,7 +19,7 @@ import 'leaflet-providers';
export default class TbOpenStreetMap {
- constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, mapProvider) {
+ constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, mapProvider, credentials) {
this.utils = utils;
this.defaultZoomLevel = defaultZoomLevel;
@@ -28,13 +28,23 @@ export default class TbOpenStreetMap {
this.tooltips = [];
if (!mapProvider) {
- mapProvider = "OpenStreetMap.Mapnik";
+ mapProvider = {
+ name: "OpenStreetMap.Mapnik"
+ };
+ }
+
+ if (mapProvider.name.startsWith("HERE.")) {
+ credentials.app_id = credentials.app_id || "AhM6TzD9ThyK78CT3ptx";
+ credentials.app_code = credentials.app_code || "p6NPiITB3Vv0GMUFnkLOOg";
}
this.map = L.map($containerElement[0]).setView([0, 0], this.defaultZoomLevel || 8);
- var tileLayer = L.tileLayer.provider(mapProvider);
+ if (disableScrollZooming) {
+ this.map.scrollWheelZoom.disable();
+ }
+ var tileLayer = mapProvider.isCustom ? L.tileLayer(mapProvider.name) : L.tileLayer.provider(mapProvider.name, credentials);
tileLayer.addTo(this.map);
if (initCallback) {
diff --git a/ui/src/app/widget/lib/tencent-map.js b/ui/src/app/widget/lib/tencent-map.js
index 9638667317..6c3f5b1921 100644
--- a/ui/src/app/widget/lib/tencent-map.js
+++ b/ui/src/app/widget/lib/tencent-map.js
@@ -19,7 +19,7 @@ var tmGlobals = {
}
export default class TbTencentMap {
- constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, tmApiKey, tmDefaultMapType) {
+ constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, tmApiKey, tmDefaultMapType) {
var tbMap = this;
this.utils = utils;
this.defaultZoomLevel = defaultZoomLevel;
@@ -42,7 +42,7 @@ export default class TbTencentMap {
function initTencentMap() {
tbMap.map = new qq.maps.Map($containerElement[0], { // eslint-disable-line no-undef
- scrollwheel: true,
+ scrollwheel: !disableScrollZooming,
mapTypeId: getTencentMapTypeId(tbMap.defaultMapType),
zoom: tbMap.defaultZoomLevel || 8
});
diff --git a/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.js b/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.js
index 5d7cc78943..2188353141 100644
--- a/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.js
+++ b/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.js
@@ -286,7 +286,7 @@ function tripAnimationController($document, $scope, $log, $http, $timeout, $filt
}
}
vm.dontFitMapBounds = vm.ctx.settings.fitMapBounds === false;
- vm.map = new TbOpenStreetMap(vm.ctx.$element, vm.utils, initCallback, vm.defaultZoomLevel, vm.dontFitMapBounds, null, vm.staticSettings.mapProvider);
+ vm.map = new TbOpenStreetMap(vm.ctx.$element, vm.utils, initCallback, vm.defaultZoomLevel, vm.dontFitMapBounds, vm.staticSettings.disableScrollZooming, null, vm.staticSettings.mapProvider);
vm.map.bounds = vm.map.createBounds();
vm.map.invalidateSize(true);
vm.map.bounds = vm.map.createBounds();
@@ -307,7 +307,8 @@ function tripAnimationController($document, $scope, $log, $http, $timeout, $filt
staticSettings.disabledButtonColor = tinycolor(vm.widgetConfig.color).setAlpha(0.3).toRgbString();
staticSettings.polygonColor = tinycolor(vm.ctx.settings.polygonColor).toHexString();
staticSettings.polygonStrokeColor = tinycolor(vm.ctx.settings.polygonStrokeColor).toHexString();
- staticSettings.mapProvider = vm.ctx.settings.mapProvider || "OpenStreetMap.Mapnik";
+ staticSettings.mapProvider = vm.ctx.settings.mapProvider ? {name: vm.ctx.settings.mapProvider} : {name: "OpenStreetMap.Mapnik"};
+ staticSettings.disableScrollZooming = vm.ctx.settings.disableScrollZooming || false;
staticSettings.latKeyName = vm.ctx.settings.latKeyName || "latitude";
staticSettings.lngKeyName = vm.ctx.settings.lngKeyName || "longitude";
staticSettings.polKeyName = vm.ctx.settings.polKeyName || "coordinates";
@@ -362,6 +363,12 @@ function tripAnimationController($document, $scope, $log, $http, $timeout, $filt
iconSize: [30, 30],
iconAnchor: [15, 15]
});
+
+ if (vm.ctx.settings.useCustomProvider && vm.ctx.settings.customProviderTileUrl) {
+ staticSettings.mapProvider.name = vm.ctx.settings.customProviderTileUrl;
+ staticSettings.mapProvider.isCustom = true;
+ }
+
if (angular.isDefined(vm.ctx.settings.markerImage)) {
staticSettings.icon = L.icon({
iconUrl: vm.ctx.settings.markerImage,
|