thingsboard-aplcache
Changes
ui/src/app/common/utils.service.js 35(+34 -1)
ui/src/app/locale/locale.constant.js 1(+1 -0)
ui/src/app/widget/lib/google-map.js 123(+70 -53)
ui/src/app/widget/lib/image-map.js 141(+76 -65)
ui/src/app/widget/lib/map-widget.js 71(+40 -31)
ui/src/app/widget/lib/map-widget2.js 74(+40 -34)
ui/src/app/widget/lib/openstreet-map.js 120(+67 -53)
Details
diff --git a/application/src/main/data/json/system/widget_bundles/cards.json b/application/src/main/data/json/system/widget_bundles/cards.json
index 0fc0085..ddb90db 100644
--- a/application/src/main/data/json/system/widget_bundles/cards.json
+++ b/application/src/main/data/json/system/widget_bundles/cards.json
@@ -112,9 +112,9 @@
"templateHtml": "<tb-timeseries-table-widget \n table-id=\"tableId\"\n ctx=\"ctx\">\n</tb-timeseries-table-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.tableId = \"table-\"+id;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.$broadcast('timeseries-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.onDestroy = function() {\n}",
- "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"TimeseriesTableSettings\",\n \"properties\": {\n \"showTimestamp\": {\n \"title\": \"Display timestamp column\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTimestamp\"\n ]\n}",
+ "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"TimeseriesTableSettings\",\n \"properties\": {\n \"showTimestamp\": {\n \"title\": \"Display timestamp column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n }, \n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTimestamp\",\n \"displayPagination\",\n \"defaultPageSize\"\n ]\n}",
"dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, rowData, filter)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}",
- "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', amount = percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":false,\"showLegend\":false}"
+ "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', amount = percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true,\"displayPagination\":true,\"defaultPageSize\":10},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":false,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{}}"
}
}
]
diff --git a/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java b/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java
index 35d1773..9f7c08f 100644
--- a/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java
+++ b/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java
@@ -47,8 +47,8 @@ public class WebSocketConfiguration implements WebSocketConfigurer {
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
- container.setMaxTextMessageBufferSize(8192);
- container.setMaxBinaryMessageBufferSize(8192);
+ container.setMaxTextMessageBufferSize(32768);
+ container.setMaxBinaryMessageBufferSize(32768);
return container;
}
diff --git a/ui/src/app/api/telemetry-websocket.service.js b/ui/src/app/api/telemetry-websocket.service.js
index f84d66d..b0e8ea9 100644
--- a/ui/src/app/api/telemetry-websocket.service.js
+++ b/ui/src/app/api/telemetry-websocket.service.js
@@ -23,6 +23,8 @@ export default angular.module('thingsboard.api.telemetryWebsocket', [thingsboard
const RECONNECT_INTERVAL = 2000;
const WS_IDLE_TIMEOUT = 90000;
+const MAX_PUBLISH_COMMANDS = 10;
+
/*@ngInject*/
function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, types, userService) {
@@ -75,19 +77,40 @@ function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, ty
return service;
function publishCommands () {
- if (isOpened && (cmdsWrapper.tsSubCmds.length > 0 ||
- cmdsWrapper.historyCmds.length > 0 ||
- cmdsWrapper.attrSubCmds.length > 0)) {
- dataStream.send(angular.copy(cmdsWrapper)).then(function () {
+ while(isOpened && hasCommands()) {
+ dataStream.send(preparePublishCommands()).then(function () {
checkToClose();
});
- cmdsWrapper.tsSubCmds = [];
- cmdsWrapper.historyCmds = [];
- cmdsWrapper.attrSubCmds = [];
}
tryOpenSocket();
}
+ function hasCommands() {
+ return cmdsWrapper.tsSubCmds.length > 0 ||
+ cmdsWrapper.historyCmds.length > 0 ||
+ cmdsWrapper.attrSubCmds.length > 0;
+ }
+
+ function preparePublishCommands() {
+ var preparedWrapper = {};
+ var leftCount = MAX_PUBLISH_COMMANDS;
+ preparedWrapper.tsSubCmds = popCmds(cmdsWrapper.tsSubCmds, leftCount);
+ leftCount -= preparedWrapper.tsSubCmds.length;
+ preparedWrapper.historyCmds = popCmds(cmdsWrapper.historyCmds, leftCount);
+ leftCount -= preparedWrapper.historyCmds.length;
+ preparedWrapper.attrSubCmds = popCmds(cmdsWrapper.attrSubCmds, leftCount);
+ return preparedWrapper;
+ }
+
+ function popCmds(cmds, leftCount) {
+ var toPublish = Math.min(cmds.length, leftCount);
+ if (toPublish > 0) {
+ return cmds.splice(0, toPublish);
+ } else {
+ return [];
+ }
+ }
+
function onError (/*message*/) {
isOpening = false;
}
ui/src/app/common/utils.service.js 35(+34 -1)
diff --git a/ui/src/app/common/utils.service.js b/ui/src/app/common/utils.service.js
index 9d99781..085a28b 100644
--- a/ui/src/app/common/utils.service.js
+++ b/ui/src/app/common/utils.service.js
@@ -134,6 +134,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
defaultAlarmDataKeys.push(dataKey);
}
+ var imageAspectMap = {};
+
var service = {
getDefaultDatasource: getDefaultDatasource,
generateObjectFromJsonSchema: generateObjectFromJsonSchema,
@@ -159,7 +161,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
insertVariable: insertVariable,
customTranslation: customTranslation,
objToBase64: objToBase64,
- base64toObj: base64toObj
+ base64toObj: base64toObj,
+ loadImageAspect: loadImageAspect
}
return service;
@@ -543,4 +546,34 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
return obj;
}
+ function loadImageAspect(imageUrl) {
+ var deferred = $q.defer();
+ if (imageUrl && imageUrl.length) {
+ var urlHashCode = hashCode(imageUrl);
+ var aspect = imageAspectMap[urlHashCode];
+ if (angular.isUndefined(aspect)) {
+ var testImage = document.createElement('img'); // eslint-disable-line
+ testImage.style.visibility = 'hidden';
+ testImage.onload = function() {
+ aspect = testImage.width / testImage.height;
+ document.body.removeChild(testImage); //eslint-disable-line
+ imageAspectMap[urlHashCode] = aspect;
+ deferred.resolve(aspect);
+ };
+ testImage.onerror = function() {
+ aspect = 0;
+ imageAspectMap[urlHashCode] = aspect;
+ deferred.resolve(aspect);
+ };
+ document.body.appendChild(testImage); //eslint-disable-line
+ testImage.src = imageUrl;
+ } else {
+ deferred.resolve(aspect);
+ }
+ } else {
+ deferred.resolve(0);
+ }
+ return deferred.promise;
+ }
+
}
diff --git a/ui/src/app/entity/attribute/attribute-table.scss b/ui/src/app/entity/attribute/attribute-table.scss
index cdf9ffd..3f40cdf 100644
--- a/ui/src/app/entity/attribute/attribute-table.scss
+++ b/ui/src/app/entity/attribute/attribute-table.scss
@@ -47,7 +47,7 @@ md-toolbar.md-table-toolbar.alternate {
.widgets-carousel {
position: relative;
margin: 0px;
-
+ height: calc(100% - 100px);
min-height: 150px !important;
tb-dashboard {
ui/src/app/locale/locale.constant.js 1(+1 -0)
diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js
index ab672de..7769b3d 100644
--- a/ui/src/app/locale/locale.constant.js
+++ b/ui/src/app/locale/locale.constant.js
@@ -1213,6 +1213,7 @@ export default angular.module('thingsboard.locale', [])
"remove-widget-title": "Are you sure you want to remove the widget '{{widgetTitle}}'?",
"remove-widget-text": "After the confirmation the widget and all related data will become unrecoverable.",
"timeseries": "Time series",
+ "search-data": "Search data",
"latest-values": "Latest values",
"rpc": "Control widget",
"alarm": "Alarm widget",
diff --git a/ui/src/app/widget/lib/alarms-table-widget.tpl.html b/ui/src/app/widget/lib/alarms-table-widget.tpl.html
index 860128d..34c7c1b 100644
--- a/ui/src/app/widget/lib/alarms-table-widget.tpl.html
+++ b/ui/src/app/widget/lib/alarms-table-widget.tpl.html
@@ -77,7 +77,7 @@
</td>
<td md-cell ng-if="vm.displayDetails" class="tb-action-cell">
<md-button class="md-icon-button" aria-label="{{ 'alarm.details' | translate }}"
- ng-click="vm.openAlarmDetails($event, alarm)">
+ ng-click="vm.openAlarmDetails($event, alarm)" ng-disabled="$root.loading">
<md-icon aria-label="{{ 'alarm.details' | translate }}" class="material-icons">more_horiz</md-icon>
<md-tooltip md-direction="top">
{{ 'alarm.details' | translate }}
@@ -90,7 +90,7 @@
width: vm.actionCellDescriptors.length*36+'px'}">
<md-button class="md-icon-button" ng-repeat="actionDescriptor in vm.actionCellDescriptors"
aria-label="{{ actionDescriptor.displayName }}"
- ng-click="vm.onActionButtonClick($event, alarm, actionDescriptor)">
+ ng-click="vm.onActionButtonClick($event, alarm, actionDescriptor)" ng-disabled="$root.loading">
<md-icon aria-label="{{ actionDescriptor.displayName }}" class="material-icons">{{actionDescriptor.icon}}</md-icon>
<md-tooltip md-direction="top">
{{ actionDescriptor.displayName }}
diff --git a/ui/src/app/widget/lib/CanvasDigitalGauge.js b/ui/src/app/widget/lib/CanvasDigitalGauge.js
index bd3ff98..200430c 100644
--- a/ui/src/app/widget/lib/CanvasDigitalGauge.js
+++ b/ui/src/app/widget/lib/CanvasDigitalGauge.js
@@ -455,7 +455,7 @@ function barDimensions(context, options, x, y, w, h) {
if (options.hideMinMax && options.label === '') {
bd.labelY = bd.barBottom;
bd.barLeft = bd.origBaseX + options.fontMinMaxSize/3 * bd.fontSizeFactor;
- bd.barRight = bd.bd.origBaseX + w + /*bd.width*/ - options.fontMinMaxSize/3 * bd.fontSizeFactor;
+ bd.barRight = bd.origBaseX + w + /*bd.width*/ - options.fontMinMaxSize/3 * bd.fontSizeFactor;
} else {
context.font = canvasGauges.drawings.font(options, 'MinMax', bd.fontSizeFactor);
var minTextWidth = context.measureText(options.minValue+'').width;
diff --git a/ui/src/app/widget/lib/entities-table-widget.tpl.html b/ui/src/app/widget/lib/entities-table-widget.tpl.html
index 2587da1..7ef8c54 100644
--- a/ui/src/app/widget/lib/entities-table-widget.tpl.html
+++ b/ui/src/app/widget/lib/entities-table-widget.tpl.html
@@ -63,7 +63,7 @@
width: vm.actionCellDescriptors.length*36+'px'}">
<md-button class="md-icon-button" ng-repeat="actionDescriptor in vm.actionCellDescriptors"
aria-label="{{ actionDescriptor.displayName }}"
- ng-click="vm.onActionButtonClick($event, entity, actionDescriptor)">
+ ng-click="vm.onActionButtonClick($event, entity, actionDescriptor)" ng-disabled="$root.loading">
<md-icon aria-label="{{ actionDescriptor.displayName }}" class="material-icons">{{actionDescriptor.icon}}</md-icon>
<md-tooltip md-direction="top">
{{ actionDescriptor.displayName }}
ui/src/app/widget/lib/google-map.js 123(+70 -53)
diff --git a/ui/src/app/widget/lib/google-map.js b/ui/src/app/widget/lib/google-map.js
index e2b4dc6..af11ac3 100644
--- a/ui/src/app/widget/lib/google-map.js
+++ b/ui/src/app/widget/lib/google-map.js
@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
var gmGlobals = {
loadingGmId: null,
gmApiKeys: {}
}
export default class TbGoogleMap {
- constructor($containerElement, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, gmApiKey, gmDefaultMapType) {
+ constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, gmApiKey, gmDefaultMapType) {
var tbMap = this;
+ this.utils = utils;
this.defaultZoomLevel = defaultZoomLevel;
this.dontFitMapBounds = dontFitMapBounds;
this.minZoomLevel = minZoomLevel;
@@ -151,80 +151,97 @@ export default class TbGoogleMap {
/* eslint-disable no-undef */
updateMarkerColor(marker, color) {
- var pinColor = color.substr(1);
- var pinImage = new google.maps.MarkerImage("https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor,
- new google.maps.Size(21, 34),
- new google.maps.Point(0,0),
- new google.maps.Point(10, 34));
- marker.setIcon(pinImage);
+ this.createDefaultMarkerIcon(marker, color, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
+ });
}
/* eslint-enable no-undef */
/* eslint-disable no-undef */
- updateMarkerImage(marker, settings, image, maxSize) {
- var testImage = document.createElement('img'); // eslint-disable-line
- testImage.style.visibility = 'hidden';
- testImage.onload = function() {
- var width;
- var height;
- var aspect = testImage.width / testImage.height;
- document.body.removeChild(testImage); //eslint-disable-line
- if (aspect > 1) {
- width = maxSize;
- height = maxSize / aspect;
- } else {
- width = maxSize * aspect;
- height = maxSize;
- }
- var pinImage = {
- url: image,
- scaledSize : new google.maps.Size(width, height)
- }
- marker.setIcon(pinImage);
+ updateMarkerIcon(marker, settings) {
+ this.createMarkerIcon(marker, settings, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
if (settings.showLabel) {
- marker.set('labelAnchor', new google.maps.Point(100, height + 20));
+ marker.set('labelAnchor', new google.maps.Point(100, iconInfo.size[1] + 20));
}
+ });
+ }
+ /* eslint-disable no-undef */
+
+ /* eslint-disable no-undef */
+ createMarkerIcon(marker, settings, onMarkerIconReady) {
+ var currentImage = settings.currentImage;
+ var gMap = this;
+ if (currentImage && currentImage.url) {
+ this.utils.loadImageAspect(currentImage.url).then(
+ (aspect) => {
+ if (aspect) {
+ var width;
+ var height;
+ if (aspect > 1) {
+ width = currentImage.size;
+ height = currentImage.size / aspect;
+ } else {
+ width = currentImage.size * aspect;
+ height = currentImage.size;
+ }
+ var icon = {
+ url: currentImage.url,
+ scaledSize : new google.maps.Size(width, height)
+ };
+ var iconInfo = {
+ size: [width, height],
+ icon: icon
+ };
+ onMarkerIconReady(iconInfo);
+ } else {
+ gMap.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady);
+ }
+ }
+ );
+ } else {
+ this.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady);
}
- document.body.appendChild(testImage); //eslint-disable-line
- testImage.src = image;
}
/* eslint-enable no-undef */
/* eslint-disable no-undef */
- createMarker(location, settings, onClickListener, markerArgs) {
- var height = 34;
- var pinColor = settings.color.substr(1);
- var pinImage = new google.maps.MarkerImage("https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor,
- new google.maps.Size(21, 34),
- new google.maps.Point(0,0),
- new google.maps.Point(10, 34));
- var pinShadow = new google.maps.MarkerImage("https://chart.apis.google.com/chart?chst=d_map_pin_shadow",
+ createDefaultMarkerIcon(marker, color, onMarkerIconReady) {
+ var pinColor = color.substr(1);
+ var icon = new google.maps.MarkerImage("https://chart.apis.google.com/chart?chst=d_map_pin_letter_withshadow&chld=%E2%80%A2|" + pinColor,
new google.maps.Size(40, 37),
- new google.maps.Point(0, 0),
- new google.maps.Point(12, 35));
+ new google.maps.Point(0,0),
+ new google.maps.Point(10, 37));
+ var iconInfo = {
+ size: [40, 37],
+ icon: icon
+ };
+ onMarkerIconReady(iconInfo);
+ }
+ /* eslint-enable no-undef */
+
+ /* eslint-disable no-undef */
+ createMarker(location, settings, onClickListener, markerArgs) {
var marker;
if (settings.showLabel) {
marker = new MarkerWithLabel({
position: location,
- map: this.map,
- icon: pinImage,
- shadow: pinShadow,
labelContent: '<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
- labelClass: "tb-labels",
- labelAnchor: new google.maps.Point(100, height + 20)
+ labelClass: "tb-labels"
});
} else {
marker = new google.maps.Marker({
position: location,
- map: this.map,
- icon: pinImage,
- shadow: pinShadow
});
}
-
- if (settings.useMarkerImage) {
- this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34);
- }
+ var gMap = this;
+ this.createMarkerIcon(marker, settings, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
+ if (settings.showLabel) {
+ marker.set('labelAnchor', new google.maps.Point(100, iconInfo.size[1] + 20));
+ }
+ marker.setMap(gMap.map);
+ });
if (settings.displayTooltip) {
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
ui/src/app/widget/lib/image-map.js 141(+76 -65)
diff --git a/ui/src/app/widget/lib/image-map.js b/ui/src/app/widget/lib/image-map.js
index e9d9976..c130539 100644
--- a/ui/src/app/widget/lib/image-map.js
+++ b/ui/src/app/widget/lib/image-map.js
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
import 'leaflet/dist/leaflet.css';
import * as L from 'leaflet';
@@ -21,9 +20,10 @@ const maxZoom = 4;
export default class TbImageMap {
- constructor(ctx, $containerElement, initCallback, imageUrl, posFunction, imageEntityAlias, imageUrlAttribute) {
+ constructor(ctx, $containerElement, utils, initCallback, imageUrl, posFunction, imageEntityAlias, imageUrlAttribute) {
this.ctx = ctx;
+ this.utils = utils;
this.tooltips = [];
this.$containerElement = $containerElement;
@@ -117,18 +117,15 @@ export default class TbImageMap {
}
this.imageUrl = imageUrl;
var imageMap = this;
- var testImage = document.createElement('img'); // eslint-disable-line
- testImage.style.visibility = 'hidden';
- testImage.onload = function() {
- imageMap.aspect = testImage.width / testImage.height;
- document.body.removeChild(testImage); //eslint-disable-line
- imageMap.onresize(updateImage);
- if (initCallback) {
- setTimeout(initCallback, 0); //eslint-disable-line
+ this.utils.loadImageAspect(imageUrl).then(
+ (aspect) => {
+ imageMap.aspect = aspect;
+ imageMap.onresize(updateImage);
+ if (initCallback) {
+ setTimeout(initCallback, 0); //eslint-disable-line
+ }
}
- }
- document.body.appendChild(testImage); //eslint-disable-line
- testImage.src = imageUrl;
+ );
}
onresize(updateImage) {
@@ -229,83 +226,97 @@ export default class TbImageMap {
}
updateMarkerColor(marker, color) {
- var pinColor = color.substr(1);
- var icon = L.icon({
- iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor,
- iconSize: [21, 34],
- iconAnchor: [10, 34],
- popupAnchor: [0, -34],
- shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
- shadowSize: [40, 37],
- shadowAnchor: [12, 35]
+ this.createDefaultMarkerIcon(marker, color, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
});
- marker.setIcon(icon);
- }
-
- updateMarkerImage(marker, settings, image, maxSize) {
- var testImage = document.createElement('img'); // eslint-disable-line
- testImage.style.visibility = 'hidden';
- testImage.onload = function() {
- var width;
- var height;
- var aspect = testImage.width / testImage.height;
- document.body.removeChild(testImage); //eslint-disable-line
- if (aspect > 1) {
- width = maxSize;
- height = maxSize / aspect;
- } else {
- width = maxSize * aspect;
- height = maxSize;
- }
- var icon = L.icon({
- iconUrl: image,
- iconSize: [width, height],
- iconAnchor: [marker.offsetX * width, marker.offsetY * height],
- popupAnchor: [0, -height]
- });
- marker.setIcon(icon);
+ }
+
+ updateMarkerIcon(marker, settings) {
+ this.createMarkerIcon(marker, settings, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
if (settings.showLabel) {
marker.unbindTooltip();
- marker.tooltipOffset = [0, -height * marker.offsetY + 10];
+ marker.tooltipOffset = [0, -iconInfo.size[1] * marker.offsetY + 10];
marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
{ className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
}
+ });
+ }
+
+ createMarkerIcon(marker, settings, onMarkerIconReady) {
+ var currentImage = settings.currentImage;
+ var opMap = this;
+ if (currentImage && currentImage.url) {
+ this.utils.loadImageAspect(currentImage.url).then(
+ (aspect) => {
+ if (aspect) {
+ var width;
+ var height;
+ if (aspect > 1) {
+ width = currentImage.size;
+ height = currentImage.size / aspect;
+ } else {
+ width = currentImage.size * aspect;
+ height = currentImage.size;
+ }
+ var icon = L.icon({
+ iconUrl: currentImage.url,
+ iconSize: [width, height],
+ iconAnchor: [marker.offsetX * width, marker.offsetY * height],
+ popupAnchor: [0, -height]
+ });
+ var iconInfo = {
+ size: [width, height],
+ icon: icon
+ };
+ onMarkerIconReady(iconInfo);
+ } else {
+ opMap.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady);
+ }
+ }
+ );
+ } else {
+ this.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady);
}
- document.body.appendChild(testImage); //eslint-disable-line
- testImage.src = image;
}
- createMarker(position, settings, onClickListener, markerArgs) {
- var height = 34;
- var pinColor = settings.color.substr(1);
+ createDefaultMarkerIcon(marker, color, onMarkerIconReady) {
+ var pinColor = color.substr(1);
var icon = L.icon({
iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor,
iconSize: [21, 34],
- iconAnchor: [21 * settings.markerOffsetX, 34 * settings.markerOffsetY],
+ iconAnchor: [21 * marker.offsetX, 34 * marker.offsetY],
popupAnchor: [0, -34],
shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
shadowSize: [40, 37],
shadowAnchor: [12, 35]
});
+ var iconInfo = {
+ size: [21, 34],
+ icon: icon
+ };
+ onMarkerIconReady(iconInfo);
+ }
+ createMarker(position, settings, onClickListener, markerArgs) {
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, {icon: icon}).addTo(this.map);
+ var marker = L.marker(location, {});//.addTo(this.map);
marker.position = position;
marker.offsetX = settings.markerOffsetX;
marker.offsetY = settings.markerOffsetY;
-
- if (settings.showLabel) {
- marker.tooltipOffset = [0, -height * marker.offsetY + 10];
- marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
- { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
- }
-
- if (settings.useMarkerImage) {
- this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34);
- }
+ var opMap = this;
+ this.createMarkerIcon(marker, settings, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
+ if (settings.showLabel) {
+ marker.tooltipOffset = [0, -iconInfo.size[1] * marker.offsetY + 10];
+ marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
+ { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
+ }
+ marker.addTo(opMap.map);
+ });
if (settings.displayTooltip) {
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
ui/src/app/widget/lib/map-widget.js 71(+40 -31)
diff --git a/ui/src/app/widget/lib/map-widget.js b/ui/src/app/widget/lib/map-widget.js
index f742514..ef86381 100644
--- a/ui/src/app/widget/lib/map-widget.js
+++ b/ui/src/app/widget/lib/map-widget.js
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
import tinycolor from 'tinycolor2';
import TbGoogleMap from './google-map';
@@ -75,7 +74,7 @@ export default class TbMapWidget {
if (!$element) {
$element = ctx.$container;
}
-
+ this.utils = ctx.$scope.$injector.get('utils');
this.drawRoutes = drawRoutes;
this.markers = [];
if (this.drawRoutes) {
@@ -110,9 +109,9 @@ export default class TbMapWidget {
};
if (mapProvider === 'google-map') {
- this.map = new TbGoogleMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType);
+ this.map = new TbGoogleMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType);
} else if (mapProvider === 'openstreet-map') {
- this.map = new TbOpenStreetMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel);
+ this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel);
}
}
@@ -274,9 +273,13 @@ export default class TbMapWidget {
if (!this.locationsSettings[i].useMarkerImageFunction &&
angular.isDefined(configuredLocationsSettings[i].markerImage) &&
configuredLocationsSettings[i].markerImage.length > 0) {
- this.locationsSettings[i].markerImage = configuredLocationsSettings[i].markerImage;
this.locationsSettings[i].useMarkerImage = true;
- this.locationsSettings[i].markerImageSize = configuredLocationsSettings[i].markerImageSize || 34;
+ var url = this.ctx.settings.markerImage;
+ var size = this.ctx.settings.markerImageSize || 34;
+ this.locationSettings.currentImage = {
+ url: url,
+ size: size
+ };
}
if (this.drawRoutes) {
@@ -380,17 +383,41 @@ export default class TbMapWidget {
}
}
- function updateLocationMarkerImage(location, dataMap) {
+ function updateLocationMarkerIcon(location, dataMap) {
var image = calculateLocationMarkerImage(location, dataMap);
- if (image != null && (!location.settings.calculatedImage || !angular.equals(location.settings.calculatedImage, image))) {
- tbMap.map.updateMarkerImage(location.marker, location.settings, image.url, image.size);
- location.settings.calculatedImage = image;
+ if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) {
+ location.settings.currentImage = image;
+ tbMap.map.updateMarkerIcon(location.marker, location.settings);
}
}
function updateLocationStyle(location, dataMap) {
updateLocationColor(location, dataMap);
- updateLocationMarkerImage(location, dataMap);
+ updateLocationMarkerIcon(location, dataMap);
+ }
+
+ function createOrUpdateLocationMarker(location, markerLocation, dataMap) {
+ var changed = false;
+ if (!location.marker) {
+ var image = calculateLocationMarkerImage(location, dataMap);
+ if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) {
+ location.settings.currentImage = image;
+ }
+ location.marker = tbMap.map.createMarker(markerLocation, location.settings,
+ function() {
+ tbMap.callbacks.onLocationClick(location);
+ }
+ );
+ tbMap.markers.push(location.marker);
+ changed = true;
+ } else {
+ var prevPosition = tbMap.map.getMarkerPosition(location.marker);
+ if (!prevPosition.equals(markerLocation)) {
+ tbMap.map.setMarkerPosition(location.marker, markerLocation);
+ changed = true;
+ }
+ }
+ return changed;
}
function updateLocation(location, data, dataMap) {
@@ -413,15 +440,7 @@ export default class TbMapWidget {
}
if (latLngs.length > 0) {
var markerLocation = latLngs[latLngs.length-1];
- if (!location.marker) {
- location.marker = tbMap.map.createMarker(markerLocation, location.settings,
- function() {
- tbMap.callbacks.onLocationClick(location);
- }
- );
- } else {
- tbMap.map.setMarkerPosition(location.marker, markerLocation);
- }
+ createOrUpdateLocationMarker(location, markerLocation, dataMap);
}
if (!location.polyline) {
location.polyline = tbMap.map.createPolyline(latLngs, location.settings);
@@ -439,18 +458,8 @@ export default class TbMapWidget {
lat = latData[latData.length-1][1];
lng = lngData[lngData.length-1][1];
latLng = tbMap.map.createLatLng(lat, lng);
- if (!location.marker) {
- location.marker = tbMap.map.createMarker(latLng, location.settings, function() {
- tbMap.callbacks.onLocationClick(location);
- });
- tbMap.markers.push(location.marker);
+ if (createOrUpdateLocationMarker(location, latLng, dataMap)) {
locationChanged = true;
- } else {
- var prevPosition = tbMap.map.getMarkerPosition(location.marker);
- if (!prevPosition.equals(latLng)) {
- tbMap.map.setMarkerPosition(location.marker, latLng);
- locationChanged = true;
- }
}
}
updateLocationStyle(location, dataMap);
ui/src/app/widget/lib/map-widget2.js 74(+40 -34)
diff --git a/ui/src/app/widget/lib/map-widget2.js b/ui/src/app/widget/lib/map-widget2.js
index 44abb2b..6b589aa 100644
--- a/ui/src/app/widget/lib/map-widget2.js
+++ b/ui/src/app/widget/lib/map-widget2.js
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
import tinycolor from 'tinycolor2';
import TbGoogleMap from './google-map';
@@ -75,11 +74,11 @@ export default class TbMapWidgetV2 {
});
if (mapProvider === 'google-map') {
- this.map = new TbGoogleMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType);
+ this.map = new TbGoogleMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType);
} else if (mapProvider === 'openstreet-map') {
- this.map = new TbOpenStreetMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.mapProvider);
+ this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.mapProvider);
} else if (mapProvider === 'image-map') {
- this.map = new TbImageMap(this.ctx, $element, initCallback,
+ this.map = new TbImageMap(this.ctx, $element, this.utils, initCallback,
settings.mapImageUrl,
settings.posFunction,
settings.imageEntityAlias,
@@ -159,9 +158,13 @@ export default class TbMapWidgetV2 {
if (!this.locationSettings.useMarkerImageFunction &&
angular.isDefined(this.ctx.settings.markerImage) &&
this.ctx.settings.markerImage.length > 0) {
- this.locationSettings.markerImage = this.ctx.settings.markerImage;
this.locationSettings.useMarkerImage = true;
- this.locationSettings.markerImageSize = this.ctx.settings.markerImageSize || 34;
+ var url = this.ctx.settings.markerImage;
+ var size = this.ctx.settings.markerImageSize || 34;
+ this.locationSettings.currentImage = {
+ url: url,
+ size: size
+ };
}
if (this.drawRoutes) {
@@ -235,10 +238,10 @@ export default class TbMapWidgetV2 {
}
}
- function updateLocationMarkerImage(location, image) {
- if (image && (!location.settings.calculatedImage || !angular.equals(location.settings.calculatedImage, image))) {
- tbMap.map.updateMarkerImage(location.marker, location.settings, image.url, image.size);
- location.settings.calculatedImage = image;
+ function updateLocationMarkerIcon(location, image) {
+ if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) {
+ location.settings.currentImage = image;
+ tbMap.map.updateMarkerIcon(location.marker, location.settings);
}
}
@@ -247,7 +250,31 @@ export default class TbMapWidgetV2 {
var color = calculateLocationColor(location, dataMap);
var image = calculateLocationMarkerImage(location, dataMap);
updateLocationColor(location, color, image);
- updateLocationMarkerImage(location, image);
+ updateLocationMarkerIcon(location, image);
+ }
+
+ function createOrUpdateLocationMarker(location, markerLocation, dataMap) {
+ var changed = false;
+ if (!location.marker) {
+ var image = calculateLocationMarkerImage(location, dataMap);
+ if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) {
+ location.settings.currentImage = image;
+ }
+ location.marker = tbMap.map.createMarker(markerLocation, location.settings,
+ function (event) {
+ tbMap.callbacks.onLocationClick(location);
+ locationRowClick(event, location);
+ }, [location.dsIndex]);
+ tbMap.markers.push(location.marker);
+ changed = true;
+ } else {
+ var prevPosition = tbMap.map.getMarkerPosition(location.marker);
+ if (!prevPosition.equals(markerLocation)) {
+ tbMap.map.setMarkerPosition(location.marker, markerLocation);
+ changed = true;
+ }
+ }
+ return changed;
}
function locationRowClick($event, location) {
@@ -284,16 +311,7 @@ export default class TbMapWidgetV2 {
}
if (latLngs.length > 0) {
var markerLocation = latLngs[latLngs.length - 1];
- if (!location.marker) {
- location.marker = tbMap.map.createMarker(markerLocation, location.settings,
- function (event) {
- tbMap.callbacks.onLocationClick(location);
- locationRowClick(event, location);
- }, [location.dsIndex]
- );
- } else {
- tbMap.map.setMarkerPosition(location.marker, markerLocation);
- }
+ createOrUpdateLocationMarker(location, markerLocation, dataMap);
}
if (!location.polyline) {
location.polyline = tbMap.map.createPolyline(latLngs, location.settings);
@@ -312,20 +330,8 @@ export default class TbMapWidgetV2 {
lng = lngData[lngData.length - 1][1];
if (angular.isDefined(lat) && lat != null && angular.isDefined(lng) && lng != null) {
latLng = tbMap.map.createLatLng(lat, lng);
- if (!location.marker) {
- location.marker = tbMap.map.createMarker(latLng, location.settings,
- function (event) {
- tbMap.callbacks.onLocationClick(location);
- locationRowClick(event, location);
- }, [location.dsIndex]);
- tbMap.markers.push(location.marker);
+ if (createOrUpdateLocationMarker(location, latLng, dataMap)) {
locationChanged = true;
- } else {
- var prevPosition = tbMap.map.getMarkerPosition(location.marker);
- if (!prevPosition.equals(latLng)) {
- tbMap.map.setMarkerPosition(location.marker, latLng);
- locationChanged = true;
- }
}
}
}
ui/src/app/widget/lib/openstreet-map.js 120(+67 -53)
diff --git a/ui/src/app/widget/lib/openstreet-map.js b/ui/src/app/widget/lib/openstreet-map.js
index 1d1d3f7..8aafe69 100644
--- a/ui/src/app/widget/lib/openstreet-map.js
+++ b/ui/src/app/widget/lib/openstreet-map.js
@@ -13,15 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
import 'leaflet/dist/leaflet.css';
import * as L from 'leaflet';
import 'leaflet-providers';
export default class TbOpenStreetMap {
- constructor($containerElement, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, mapProvider) {
+ constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, mapProvider) {
+ this.utils = utils;
this.defaultZoomLevel = defaultZoomLevel;
this.dontFitMapBounds = dontFitMapBounds;
this.minZoomLevel = minZoomLevel;
@@ -54,55 +54,62 @@ export default class TbOpenStreetMap {
}
updateMarkerColor(marker, color) {
- var pinColor = color.substr(1);
- var icon = L.icon({
- iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor,
- iconSize: [21, 34],
- iconAnchor: [10, 34],
- popupAnchor: [0, -34],
- shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
- shadowSize: [40, 37],
- shadowAnchor: [12, 35]
+ this.createDefaultMarkerIcon(marker, color, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
});
- marker.setIcon(icon);
- }
-
- updateMarkerImage(marker, settings, image, maxSize) {
- var testImage = document.createElement('img'); // eslint-disable-line
- testImage.style.visibility = 'hidden';
- testImage.onload = function() {
- var width;
- var height;
- var aspect = testImage.width / testImage.height;
- document.body.removeChild(testImage); //eslint-disable-line
- if (aspect > 1) {
- width = maxSize;
- height = maxSize / aspect;
- } else {
- width = maxSize * aspect;
- height = maxSize;
- }
- var icon = L.icon({
- iconUrl: image,
- iconSize: [width, height],
- iconAnchor: [width/2, height],
- popupAnchor: [0, -height]
- });
- marker.setIcon(icon);
+ }
+
+ updateMarkerIcon(marker, settings) {
+ this.createMarkerIcon(marker, settings, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
if (settings.showLabel) {
marker.unbindTooltip();
- marker.tooltipOffset = [0, -height + 10];
+ marker.tooltipOffset = [0, -iconInfo.size[1] + 10];
marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
{ className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
}
+ });
+ }
+
+ createMarkerIcon(marker, settings, onMarkerIconReady) {
+ var currentImage = settings.currentImage;
+ var opMap = this;
+ if (currentImage && currentImage.url) {
+ this.utils.loadImageAspect(currentImage.url).then(
+ (aspect) => {
+ if (aspect) {
+ var width;
+ var height;
+ if (aspect > 1) {
+ width = currentImage.size;
+ height = currentImage.size / aspect;
+ } else {
+ width = currentImage.size * aspect;
+ height = currentImage.size;
+ }
+ var icon = L.icon({
+ iconUrl: currentImage.url,
+ iconSize: [width, height],
+ iconAnchor: [width/2, height],
+ popupAnchor: [0, -height]
+ });
+ var iconInfo = {
+ size: [width, height],
+ icon: icon
+ };
+ onMarkerIconReady(iconInfo);
+ } else {
+ opMap.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady);
+ }
+ }
+ );
+ } else {
+ this.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady);
}
- document.body.appendChild(testImage); //eslint-disable-line
- testImage.src = image;
}
- createMarker(location, settings, onClickListener, markerArgs) {
- var height = 34;
- var pinColor = settings.color.substr(1);
+ createDefaultMarkerIcon(marker, color, onMarkerIconReady) {
+ var pinColor = color.substr(1);
var icon = L.icon({
iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor,
iconSize: [21, 34],
@@ -112,18 +119,25 @@ export default class TbOpenStreetMap {
shadowSize: [40, 37],
shadowAnchor: [12, 35]
});
+ var iconInfo = {
+ size: [21, 34],
+ icon: icon
+ };
+ onMarkerIconReady(iconInfo);
+ }
- var marker = L.marker(location, {icon: icon}).addTo(this.map);
-
- if (settings.showLabel) {
- marker.tooltipOffset = [0, -height + 10];
- marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
- { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
- }
-
- if (settings.useMarkerImage) {
- this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34);
- }
+ createMarker(location, settings, onClickListener, markerArgs) {
+ var marker = L.marker(location, {});
+ var opMap = this;
+ this.createMarkerIcon(marker, settings, (iconInfo) => {
+ marker.setIcon(iconInfo.icon);
+ if (settings.showLabel) {
+ marker.tooltipOffset = [0, -iconInfo.size[1] + 10];
+ marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
+ { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
+ }
+ marker.addTo(opMap.map);
+ });
if (settings.displayTooltip) {
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
diff --git a/ui/src/app/widget/lib/timeseries-table-widget.js b/ui/src/app/widget/lib/timeseries-table-widget.js
index 0c23e02..28ac811 100644
--- a/ui/src/app/widget/lib/timeseries-table-widget.js
+++ b/ui/src/app/widget/lib/timeseries-table-widget.js
@@ -47,9 +47,37 @@ function TimeseriesTableWidget() {
/*@ngInject*/
function TimeseriesTableWidgetController($element, $scope, $filter) {
var vm = this;
+ let dateFormatFilter = 'yyyy-MM-dd HH:mm:ss';
vm.sources = [];
vm.sourceIndex = 0;
+ vm.defaultPageSize = 10;
+ vm.defaultSortOrder = '-0';
+ vm.query = {
+ "search": null
+ };
+
+ vm.enterFilterMode = enterFilterMode;
+ vm.exitFilterMode = exitFilterMode;
+
+ function enterFilterMode () {
+ vm.query.search = '';
+ vm.ctx.hideTitlePanel = true;
+ }
+
+ function exitFilterMode () {
+ vm.query.search = null;
+ vm.ctx.hideTitlePanel = false;
+ }
+
+ vm.searchAction = {
+ name: 'action.search',
+ show: true,
+ onAction: function() {
+ vm.enterFilterMode();
+ },
+ icon: 'search'
+ };
$scope.$watch('vm.ctx', function() {
if (vm.ctx) {
@@ -62,6 +90,7 @@ function TimeseriesTableWidgetController($element, $scope, $filter) {
});
function initialize() {
+ vm.ctx.widgetActions = [ vm.searchAction ];
vm.showTimestamp = vm.settings.showTimestamp !== false;
var origColor = vm.widgetConfig.color || 'rgba(0, 0, 0, 0.87)';
var defaultColor = tinycolor(origColor);
@@ -108,6 +137,8 @@ function TimeseriesTableWidgetController($element, $scope, $filter) {
cssParser.createStyleElement(namespace, cssString);
$element.addClass(namespace);
+ vm.displayPagination = angular.isDefined(vm.settings.displayPagination) ? vm.settings.displayPagination : true;
+
function hashCode(str) {
var hash = 0;
var i, char;
@@ -163,7 +194,7 @@ function TimeseriesTableWidgetController($element, $scope, $filter) {
vm.cellContent = function(source, index, row, value) {
if (index === 0) {
- return $filter('date')(value, 'yyyy-MM-dd HH:mm:ss');
+ return $filter('date')(value, dateFormatFilter);
} else {
var strContent = '';
if (angular.isDefined(value)) {
@@ -211,7 +242,7 @@ function TimeseriesTableWidgetController($element, $scope, $filter) {
source.data = [];
source.rawData = [];
source.query = {
- limit: 5,
+ limit: vm.settings.defaultPageSize || 10,
page: 1,
order: '-0'
}
@@ -287,7 +318,30 @@ function TimeseriesTableWidgetController($element, $scope, $filter) {
}
function reorder(source) {
+ let searchRegExp = new RegExp(vm.query.search);
+
source.data = $filter('orderBy')(source.data, source.query.order);
+ if (vm.query.search !== null) {
+ source.data = source.data.filter(function(item){
+ for (let i = 0; i < item.length; i++) {
+ if (vm.showTimestamp) {
+ if (i === 0) {
+ if (searchRegExp.test($filter('date')(item[i], dateFormatFilter))) {
+ return true;
+ }
+ } else {
+ if (searchRegExp.test(item[i])) {
+ return true;
+ }
+ }
+ } else {
+ if (searchRegExp.test(item[i])) {
+ return true;
+ }
+ }
+ }
+ });
+ }
}
function convertData(data) {
diff --git a/ui/src/app/widget/lib/timeseries-table-widget.scss b/ui/src/app/widget/lib/timeseries-table-widget.scss
index 99a0653..da3ee81 100644
--- a/ui/src/app/widget/lib/timeseries-table-widget.scss
+++ b/ui/src/app/widget/lib/timeseries-table-widget.scss
@@ -26,4 +26,8 @@ tb-timeseries-table-widget {
.md-table-pagination>* {
height: 46px;
}
+
+ .tb-data-table md-toolbar {
+ z-index: 10;
+ }
}
diff --git a/ui/src/app/widget/lib/timeseries-table-widget.tpl.html b/ui/src/app/widget/lib/timeseries-table-widget.tpl.html
index 2b6d72c..2e7286c 100644
--- a/ui/src/app/widget/lib/timeseries-table-widget.tpl.html
+++ b/ui/src/app/widget/lib/timeseries-table-widget.tpl.html
@@ -15,29 +15,71 @@
limitations under the License.
-->
+<div class="tb-absolute-fill tb-entities-table tb-data-table timeseriesWidget" layout="column">
+ <div flex class="tb-absolute-fill" layout="column">
+ <md-toolbar class="md-table-toolbar md-default" ng-show="vm.query.search !== null">
+ <div class="md-toolbar-tools">
+ <md-button class="md-icon-button" aria-label="{{ 'action.search' | translate }}">
+ <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">search</md-icon>
+ <md-tooltip md-direction="{{vm.ctx.dashboard.isWidgetExpanded ? 'bottom' : 'top'}}">
+ {{'entity.search' | translate}}
+ </md-tooltip>
+ </md-button>
+ <md-input-container flex>
+ <label> </label>
+ <input ng-model="vm.query.search" placeholder="{{'widget.search-data' | translate}}" md-autofocus/>
+ </md-input-container>
+ <md-button class="md-icon-button" aria-label="Close" ng-click="vm.exitFilterMode()">
+ <md-icon aria-label="Close" class="material-icons">close</md-icon>
+ <md-tooltip md-direction="{{vm.ctx.dashboard.isWidgetExpanded ? 'bottom' : 'top'}}">
+ {{ 'action.close' | translate }}
+ </md-tooltip>
+ </md-button>
+ </div>
+ </md-toolbar>
-<md-tabs md-selected="vm.sourceIndex" ng-class="{'tb-headless': vm.sources.length === 1}"
- id="tabs" md-border-bottom flex class="tb-absolute-fill">
- <md-tab ng-repeat="source in vm.sources" label="{{ source.datasource.name }}">
- <md-table-container>
- <table md-table>
- <thead md-head md-order="source.query.order" md-on-reorder="vm.onReorder(source)">
- <tr md-row>
- <th ng-show="vm.showTimestamp" md-column md-order-by="0"><span>Timestamp</span></th>
- <th md-column md-order-by="{{ h.index }}" ng-repeat="h in source.ts.header"><span>{{ h.dataKey.label }}</span></th>
- </tr>
- </thead>
- <tbody md-body>
- <tr md-row ng-repeat="row in source.ts.data">
- <td ng-show="$index > 0 || ($index === 0 && vm.showTimestamp)" md-cell ng-repeat="d in row track by $index" ng-style="vm.cellStyle(source, $index, d)" ng-bind-html="vm.cellContent(source, $index, row, d)">
- </td>
- </tr>
- </tbody>
- </table>
- </md-table-container>
- <md-table-pagination md-limit="source.query.limit" md-limit-options="[5, 10, 15]"
- md-page="source.query.page" md-total="{{source.ts.count}}"
- md-on-paginate="vm.onPaginate(source)" md-page-select>
- </md-table-pagination>
- </md-tab>
-</md-tabs>
\ No newline at end of file
+ <md-tabs flex md-selected="vm.sourceIndex" ng-class="{'tb-headless': vm.sources.length === 1}"
+ id="tabs" md-border-bottom flex>
+ <md-tab ng-repeat="source in vm.sources" label="{{ source.datasource.name }}">
+ <md-table-container>
+ <table md-table>
+ <thead md-head md-order="source.query.order" md-on-reorder="vm.onReorder(source)">
+ <tr md-row>
+ <th ng-show="vm.showTimestamp"
+ md-column md-order-by="0"
+ >
+ <span>Timestamp</span>
+ </th>
+ <th md-column
+ md-order-by="{{ h.index }}"
+ ng-repeat="h in source.ts.header"
+ >
+ <span>{{ h.dataKey.label }}</span>
+ </th>
+ </tr>
+ </thead>
+
+ <tbody md-body>
+ <tr md-row ng-repeat="row in source.ts.data track by $index">
+ <td ng-show="$index > 0 || ($index === 0 && vm.showTimestamp)"
+ md-cell
+ ng-repeat="d in row track by $index"
+ ng-style="vm.cellStyle(source, $index, d)"
+ ng-bind-html="vm.cellContent(source, $index, row, d)"
+ ></td>
+ </tr>
+ </tbody>
+ </table>
+ </md-table-container>
+ <md-table-pagination ng-if="vm.displayPagination"
+ md-limit="source.query.limit"
+ md-limit-options="vm.limitOptions"
+ md-page="source.query.page"
+ md-total="{{source.data.length}}"
+ md-on-paginate="vm.onPaginate(source)"
+ md-page-select>
+ </md-table-pagination>
+ </md-tab>
+ </md-tabs>
+ </div>
+</div>
\ No newline at end of file