Commit 8808d66c9d19a5d3f073019c1f7cc07780c1274b
Merge branch 'master' of https://github.com/ArtemHalushko/thingsboard into trip-select
Showing
60 changed files
with
987 additions
and
744 deletions
Too many changes to show.
To preserve performance only 60 of 724 files are displayed.
@@ -153,12 +153,8 @@ | @@ -153,12 +153,8 @@ | ||
153 | <artifactId>jjwt</artifactId> | 153 | <artifactId>jjwt</artifactId> |
154 | </dependency> | 154 | </dependency> |
155 | <dependency> | 155 | <dependency> |
156 | - <groupId>org.apache.velocity</groupId> | ||
157 | - <artifactId>velocity</artifactId> | ||
158 | - </dependency> | ||
159 | - <dependency> | ||
160 | - <groupId>org.apache.velocity</groupId> | ||
161 | - <artifactId>velocity-tools</artifactId> | 156 | + <groupId>org.freemarker</groupId> |
157 | + <artifactId>freemarker</artifactId> | ||
162 | </dependency> | 158 | </dependency> |
163 | <dependency> | 159 | <dependency> |
164 | <groupId>commons-io</groupId> | 160 | <groupId>commons-io</groupId> |
@@ -130,7 +130,7 @@ | @@ -130,7 +130,7 @@ | ||
130 | "controllerScript": " self.onInit = function() {\n var $scope = self.ctx.$scope;\n $scope.self = self;\n }\n \n \n self.actionSources = function () {\n return {\n 'tooltipAction': {\n name: 'widget-action.tooltip-tag-action',\n multiple: false\n }\n }\n };\n \n self.getSettingsSchema = function() {\n return TbTripAnimationWidget.getSettingsSchema();\n}\n", | 130 | "controllerScript": " self.onInit = function() {\n var $scope = self.ctx.$scope;\n $scope.self = self;\n }\n \n \n self.actionSources = function () {\n return {\n 'tooltipAction': {\n name: 'widget-action.tooltip-tag-action',\n multiple: false\n }\n }\n };\n \n self.getSettingsSchema = function() {\n return TbTripAnimationWidget.getSettingsSchema();\n}\n", |
131 | "settingsSchema": "", | 131 | "settingsSchema": "", |
132 | "dataKeySettingsSchema": "{}", | 132 | "dataKeySettingsSchema": "{}", |
133 | - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var gpsData = [\\n37.771210000, -122.510960000,\\n 37.771990000, -122.497070000,\\n 37.772730000, -122.480740000,\\n 37.773360000, -122.466870000,\\n 37.774270000, -122.458520000,\\n 37.771980000, -122.454110000,\\n 37.768250000, -122.453380000,\\n 37.765920000, -122.456810000,\\n 37.765930000, -122.467680000,\\n 37.765500000, -122.477180000,\\n 37.765300000, -122.481660000,\\n 37.764780000, -122.493350000,\\n 37.764120000, -122.508360000,\\n 37.766410000, -122.510260000,\\n 37.770010000, -122.510830000,\\n 37.770980000, -122.510930000\\n];\\n let value = gpsData.indexOf(prevValue); \\nreturn gpsData[(value == -1 ? 0 : value + 2)];\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var gpsData = [\\n37.771210000, -122.510960000,\\n 37.771990000, -122.497070000,\\n 37.772730000, -122.480740000,\\n 37.773360000, -122.466870000,\\n 37.774270000, -122.458520000,\\n 37.771980000, -122.454110000,\\n 37.768250000, -122.453380000,\\n 37.765920000, -122.456810000,\\n 37.765930000, -122.467680000,\\n 37.765500000, -122.477180000,\\n 37.765300000, -122.481660000,\\n 37.764780000, -122.493350000,\\n 37.764120000, -122.508360000,\\n 37.766410000, -122.510260000,\\n 37.770010000, -122.510830000,\\n 37.770980000, -122.510930000\\n];\\n let value = gpsData.indexOf(prevValue); \\nreturn gpsData[(value == -1 ? 1 : value + 2)];\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}]}],\"timewindow\":{\"history\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":500}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"mapProvider\":\"OpenStreetMap.Mapnik\",\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"showTooltip\":true,\"tooltipColor\":\"#fff\",\"tooltipFontColor\":\"#000\",\"tooltipOpacity\":1,\"tooltipPattern\":\"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>End Time:</b> ${maxTime}<br/><b>Start Time:</b> ${minTime}\",\"strokeWeight\":2,\"strokeOpacity\":1,\"pointSize\":10,\"markerImageSize\":34,\"rotationAngle\":180,\"provider\":\"openstreet-map\",\"normalizationStep\":1000,\"polKeyName\":\"coordinates\",\"decoratorSymbol\":\"arrowHead\",\"decoratorSymbolSize\":10,\"decoratorCustomColor\":\"#000\",\"decoratorOffset\":\"20px\",\"endDecoratorOffset\":\"20px\",\"decoratorRepeat\":\"20px\",\"polygonTooltipPattern\":\"<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${ts:7}\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"pointTooltipOnRightPanel\":true,\"autocloseTooltip\":true},\"title\":\"Trip Animation\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":false,\"showLegend\":false,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false},\"displayTimewindow\":true}" | 133 | + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var gpsData = [\\n37.771210000, -122.510960000,\\n 37.771990000, -122.497070000,\\n 37.772730000, -122.480740000,\\n 37.773360000, -122.466870000,\\n 37.774270000, -122.458520000,\\n 37.771980000, -122.454110000,\\n 37.768250000, -122.453380000,\\n 37.765920000, -122.456810000,\\n 37.765930000, -122.467680000,\\n 37.765500000, -122.477180000,\\n 37.765300000, -122.481660000,\\n 37.764780000, -122.493350000,\\n 37.764120000, -122.508360000,\\n 37.766410000, -122.510260000,\\n 37.770010000, -122.510830000,\\n 37.770980000, -122.510930000\\n];\\n let value = gpsData.indexOf(prevValue); \\nreturn gpsData[(value == -1 ? 0 : (value + 2) % gpsData.length)];\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var gpsData = [\\n37.771210000, -122.510960000,\\n 37.771990000, -122.497070000,\\n 37.772730000, -122.480740000,\\n 37.773360000, -122.466870000,\\n 37.774270000, -122.458520000,\\n 37.771980000, -122.454110000,\\n 37.768250000, -122.453380000,\\n 37.765920000, -122.456810000,\\n 37.765930000, -122.467680000,\\n 37.765500000, -122.477180000,\\n 37.765300000, -122.481660000,\\n 37.764780000, -122.493350000,\\n 37.764120000, -122.508360000,\\n 37.766410000, -122.510260000,\\n 37.770010000, -122.510830000,\\n 37.770980000, -122.510930000\\n];\\n let value = gpsData.indexOf(prevValue); \\nreturn gpsData[(value == -1 ? 1 : (value + 2) % gpsData.length)];\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}]}],\"timewindow\":{\"history\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":500}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"mapProvider\":\"OpenStreetMap.Mapnik\",\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"showTooltip\":true,\"tooltipColor\":\"#fff\",\"tooltipFontColor\":\"#000\",\"tooltipOpacity\":1,\"tooltipPattern\":\"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>End Time:</b> ${maxTime}<br/><b>Start Time:</b> ${minTime}\",\"strokeWeight\":2,\"strokeOpacity\":1,\"pointSize\":10,\"markerImageSize\":34,\"rotationAngle\":180,\"provider\":\"openstreet-map\",\"normalizationStep\":1000,\"polKeyName\":\"coordinates\",\"decoratorSymbol\":\"arrowHead\",\"decoratorSymbolSize\":10,\"decoratorCustomColor\":\"#000\",\"decoratorOffset\":\"20px\",\"endDecoratorOffset\":\"20px\",\"decoratorRepeat\":\"20px\",\"polygonTooltipPattern\":\"<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${ts:7}\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"pointTooltipOnRightPanel\":true,\"autocloseTooltip\":true},\"title\":\"Trip Animation\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":false,\"showLegend\":false,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false},\"displayTimewindow\":true}" |
134 | } | 134 | } |
135 | }, | 135 | }, |
136 | { | 136 | { |
@@ -150,4 +150,4 @@ | @@ -150,4 +150,4 @@ | ||
150 | } | 150 | } |
151 | } | 151 | } |
152 | ] | 152 | ] |
153 | -} | ||
153 | +} |
@@ -56,6 +56,7 @@ import org.thingsboard.server.dao.audit.AuditLogService; | @@ -56,6 +56,7 @@ import org.thingsboard.server.dao.audit.AuditLogService; | ||
56 | import org.thingsboard.server.dao.cassandra.CassandraCluster; | 56 | import org.thingsboard.server.dao.cassandra.CassandraCluster; |
57 | import org.thingsboard.server.dao.customer.CustomerService; | 57 | import org.thingsboard.server.dao.customer.CustomerService; |
58 | import org.thingsboard.server.dao.dashboard.DashboardService; | 58 | import org.thingsboard.server.dao.dashboard.DashboardService; |
59 | +import org.thingsboard.server.dao.device.ClaimDevicesService; | ||
59 | import org.thingsboard.server.dao.device.DeviceService; | 60 | import org.thingsboard.server.dao.device.DeviceService; |
60 | import org.thingsboard.server.dao.entityview.EntityViewService; | 61 | import org.thingsboard.server.dao.entityview.EntityViewService; |
61 | import org.thingsboard.server.dao.event.EventService; | 62 | import org.thingsboard.server.dao.event.EventService; |
@@ -218,6 +219,10 @@ public class ActorSystemContext { | @@ -218,6 +219,10 @@ public class ActorSystemContext { | ||
218 | @Getter | 219 | @Getter |
219 | private MailService mailService; | 220 | private MailService mailService; |
220 | 221 | ||
222 | + @Autowired | ||
223 | + @Getter | ||
224 | + private ClaimDevicesService claimDevicesService; | ||
225 | + | ||
221 | //TODO: separate context for TbCore and TbRuleEngine | 226 | //TODO: separate context for TbCore and TbRuleEngine |
222 | @Autowired(required = false) | 227 | @Autowired(required = false) |
223 | @Getter | 228 | @Getter |
@@ -39,6 +39,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; | @@ -39,6 +39,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; | ||
39 | import org.thingsboard.server.common.msg.queue.TbCallback; | 39 | import org.thingsboard.server.common.msg.queue.TbCallback; |
40 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | 40 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
41 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; | 41 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; |
42 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
42 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; | 43 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; |
43 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheEntry; | 44 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheEntry; |
44 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; | 45 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; |
@@ -232,9 +233,17 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -232,9 +233,17 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
232 | if (msg.hasSubscriptionInfo()) { | 233 | if (msg.hasSubscriptionInfo()) { |
233 | handleSessionActivity(context, msg.getSessionInfo(), msg.getSubscriptionInfo()); | 234 | handleSessionActivity(context, msg.getSessionInfo(), msg.getSubscriptionInfo()); |
234 | } | 235 | } |
236 | + if (msg.hasClaimDevice()) { | ||
237 | + handleClaimDeviceMsg(context, msg.getSessionInfo(), msg.getClaimDevice()); | ||
238 | + } | ||
235 | callback.onSuccess(); | 239 | callback.onSuccess(); |
236 | } | 240 | } |
237 | 241 | ||
242 | + private void handleClaimDeviceMsg(ActorContext context, SessionInfoProto sessionInfo, TransportProtos.ClaimDeviceMsg msg) { | ||
243 | + DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); | ||
244 | + systemContext.getClaimDevicesService().registerClaimingInfo(tenantId, deviceId, msg.getSecretKey(), msg.getDurationMs()); | ||
245 | + } | ||
246 | + | ||
238 | private void reportSessionOpen() { | 247 | private void reportSessionOpen() { |
239 | systemContext.getDeviceStateService().onDeviceConnect(deviceId); | 248 | systemContext.getDeviceStateService().onDeviceConnect(deviceId); |
240 | } | 249 | } |
@@ -15,28 +15,11 @@ | @@ -15,28 +15,11 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.config; | 16 | package org.thingsboard.server.config; |
17 | 17 | ||
18 | -import lombok.extern.slf4j.Slf4j; | ||
19 | -import org.apache.commons.collections.ExtendedProperties; | ||
20 | -import org.apache.commons.logging.Log; | ||
21 | -import org.apache.commons.logging.LogFactory; | ||
22 | -import org.apache.velocity.app.VelocityEngine; | ||
23 | -import org.apache.velocity.exception.ResourceNotFoundException; | ||
24 | -import org.apache.velocity.runtime.RuntimeConstants; | ||
25 | -import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; | ||
26 | import org.springframework.context.MessageSource; | 18 | import org.springframework.context.MessageSource; |
27 | import org.springframework.context.annotation.Bean; | 19 | import org.springframework.context.annotation.Bean; |
28 | import org.springframework.context.annotation.Configuration; | 20 | import org.springframework.context.annotation.Configuration; |
29 | import org.springframework.context.annotation.Primary; | 21 | import org.springframework.context.annotation.Primary; |
30 | import org.springframework.context.support.ResourceBundleMessageSource; | 22 | import org.springframework.context.support.ResourceBundleMessageSource; |
31 | -import org.springframework.core.io.DefaultResourceLoader; | ||
32 | -import org.springframework.core.io.Resource; | ||
33 | -import org.springframework.core.io.ResourceLoader; | ||
34 | -import org.springframework.util.StringUtils; | ||
35 | - | ||
36 | -import java.io.File; | ||
37 | -import java.io.IOException; | ||
38 | -import java.io.InputStream; | ||
39 | -import java.util.Arrays; | ||
40 | 23 | ||
41 | @Configuration | 24 | @Configuration |
42 | public class ThingsboardMessageConfiguration { | 25 | public class ThingsboardMessageConfiguration { |
@@ -49,114 +32,4 @@ public class ThingsboardMessageConfiguration { | @@ -49,114 +32,4 @@ public class ThingsboardMessageConfiguration { | ||
49 | messageSource.setDefaultEncoding("UTF-8"); | 32 | messageSource.setDefaultEncoding("UTF-8"); |
50 | return messageSource; | 33 | return messageSource; |
51 | } | 34 | } |
52 | - | ||
53 | - private static final String DEFAULT_RESOURCE_LOADER_PATH = "classpath:/templates/"; | ||
54 | - | ||
55 | - private ResourceLoader resourceLoader = new DefaultResourceLoader(); | ||
56 | - | ||
57 | - @Bean | ||
58 | - public VelocityEngine velocityEngine() { | ||
59 | - VelocityEngine velocityEngine = new VelocityEngine(); | ||
60 | - try { | ||
61 | - Resource resource = resourceLoader.getResource(DEFAULT_RESOURCE_LOADER_PATH); | ||
62 | - File file = resource.getFile(); | ||
63 | - velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "file"); | ||
64 | - velocityEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true"); | ||
65 | - velocityEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath()); | ||
66 | - } catch (IOException e) { | ||
67 | - initSpringResourceLoader(velocityEngine, DEFAULT_RESOURCE_LOADER_PATH); | ||
68 | - } | ||
69 | - velocityEngine.init(); | ||
70 | - return velocityEngine; | ||
71 | - } | ||
72 | - | ||
73 | - private void initSpringResourceLoader(VelocityEngine velocityEngine, String resourceLoaderPath) { | ||
74 | - velocityEngine.setProperty( | ||
75 | - RuntimeConstants.RESOURCE_LOADER, SpringResourceLoader.NAME); | ||
76 | - velocityEngine.setProperty( | ||
77 | - SpringResourceLoader.SPRING_RESOURCE_LOADER_CLASS, SpringResourceLoader.class.getName()); | ||
78 | - velocityEngine.setProperty( | ||
79 | - SpringResourceLoader.SPRING_RESOURCE_LOADER_CACHE, "true"); | ||
80 | - velocityEngine.setApplicationAttribute( | ||
81 | - SpringResourceLoader.SPRING_RESOURCE_LOADER, resourceLoader); | ||
82 | - velocityEngine.setApplicationAttribute( | ||
83 | - SpringResourceLoader.SPRING_RESOURCE_LOADER_PATH, resourceLoaderPath); | ||
84 | - } | ||
85 | - | ||
86 | - @Slf4j | ||
87 | - public static class SpringResourceLoader extends org.apache.velocity.runtime.resource.loader.ResourceLoader { | ||
88 | - | ||
89 | - public static final String NAME = "spring"; | ||
90 | - | ||
91 | - public static final String SPRING_RESOURCE_LOADER_CLASS = "spring.resource.loader.class"; | ||
92 | - | ||
93 | - public static final String SPRING_RESOURCE_LOADER_CACHE = "spring.resource.loader.cache"; | ||
94 | - | ||
95 | - public static final String SPRING_RESOURCE_LOADER = "spring.resource.loader"; | ||
96 | - | ||
97 | - public static final String SPRING_RESOURCE_LOADER_PATH = "spring.resource.loader.path"; | ||
98 | - | ||
99 | - private org.springframework.core.io.ResourceLoader resourceLoader; | ||
100 | - | ||
101 | - private String[] resourceLoaderPaths; | ||
102 | - | ||
103 | - | ||
104 | - @Override | ||
105 | - public void init(ExtendedProperties configuration) { | ||
106 | - this.resourceLoader = (org.springframework.core.io.ResourceLoader) | ||
107 | - this.rsvc.getApplicationAttribute(SPRING_RESOURCE_LOADER); | ||
108 | - String resourceLoaderPath = (String) this.rsvc.getApplicationAttribute(SPRING_RESOURCE_LOADER_PATH); | ||
109 | - if (this.resourceLoader == null) { | ||
110 | - throw new IllegalArgumentException( | ||
111 | - "'resourceLoader' application attribute must be present for SpringResourceLoader"); | ||
112 | - } | ||
113 | - if (resourceLoaderPath == null) { | ||
114 | - throw new IllegalArgumentException( | ||
115 | - "'resourceLoaderPath' application attribute must be present for SpringResourceLoader"); | ||
116 | - } | ||
117 | - this.resourceLoaderPaths = StringUtils.commaDelimitedListToStringArray(resourceLoaderPath); | ||
118 | - for (int i = 0; i < this.resourceLoaderPaths.length; i++) { | ||
119 | - String path = this.resourceLoaderPaths[i]; | ||
120 | - if (!path.endsWith("/")) { | ||
121 | - this.resourceLoaderPaths[i] = path + "/"; | ||
122 | - } | ||
123 | - } | ||
124 | - if (log.isInfoEnabled()) { | ||
125 | - log.info("SpringResourceLoader for Velocity: using resource loader [" + this.resourceLoader + | ||
126 | - "] and resource loader paths " + Arrays.asList(this.resourceLoaderPaths)); | ||
127 | - } | ||
128 | - } | ||
129 | - | ||
130 | - @Override | ||
131 | - public InputStream getResourceStream(String source) throws ResourceNotFoundException { | ||
132 | - if (log.isDebugEnabled()) { | ||
133 | - log.debug("Looking for Velocity resource with name [" + source + "]"); | ||
134 | - } | ||
135 | - for (String resourceLoaderPath : this.resourceLoaderPaths) { | ||
136 | - org.springframework.core.io.Resource resource = | ||
137 | - this.resourceLoader.getResource(resourceLoaderPath + source); | ||
138 | - try { | ||
139 | - return resource.getInputStream(); | ||
140 | - } | ||
141 | - catch (IOException ex) { | ||
142 | - if (log.isDebugEnabled()) { | ||
143 | - log.debug("Could not find Velocity resource: " + resource); | ||
144 | - } | ||
145 | - } | ||
146 | - } | ||
147 | - throw new ResourceNotFoundException( | ||
148 | - "Could not find resource [" + source + "] in Spring resource loader path"); | ||
149 | - } | ||
150 | - | ||
151 | - @Override | ||
152 | - public boolean isSourceModified(org.apache.velocity.runtime.resource.Resource resource) { | ||
153 | - return false; | ||
154 | - } | ||
155 | - | ||
156 | - @Override | ||
157 | - public long getLastModified(org.apache.velocity.runtime.resource.Resource resource) { | ||
158 | - return 0; | ||
159 | - } | ||
160 | - | ||
161 | - } | ||
162 | } | 35 | } |
@@ -135,7 +135,7 @@ public class UserController extends BaseController { | @@ -135,7 +135,7 @@ public class UserController extends BaseController { | ||
135 | HttpServletRequest request) throws ThingsboardException { | 135 | HttpServletRequest request) throws ThingsboardException { |
136 | try { | 136 | try { |
137 | 137 | ||
138 | - if (getCurrentUser().getAuthority() == Authority.TENANT_ADMIN) { | 138 | + if (Authority.TENANT_ADMIN.equals(getCurrentUser().getAuthority())) { |
139 | user.setTenantId(getCurrentUser().getTenantId()); | 139 | user.setTenantId(getCurrentUser().getTenantId()); |
140 | } | 140 | } |
141 | 141 |
@@ -60,7 +60,7 @@ public class WidgetTypeController extends BaseController { | @@ -60,7 +60,7 @@ public class WidgetTypeController extends BaseController { | ||
60 | @ResponseBody | 60 | @ResponseBody |
61 | public WidgetType saveWidgetType(@RequestBody WidgetType widgetType) throws ThingsboardException { | 61 | public WidgetType saveWidgetType(@RequestBody WidgetType widgetType) throws ThingsboardException { |
62 | try { | 62 | try { |
63 | - if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) { | 63 | + if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { |
64 | widgetType.setTenantId(TenantId.SYS_TENANT_ID); | 64 | widgetType.setTenantId(TenantId.SYS_TENANT_ID); |
65 | } else { | 65 | } else { |
66 | widgetType.setTenantId(getCurrentUser().getTenantId()); | 66 | widgetType.setTenantId(getCurrentUser().getTenantId()); |
@@ -61,7 +61,7 @@ public class WidgetsBundleController extends BaseController { | @@ -61,7 +61,7 @@ public class WidgetsBundleController extends BaseController { | ||
61 | @ResponseBody | 61 | @ResponseBody |
62 | public WidgetsBundle saveWidgetsBundle(@RequestBody WidgetsBundle widgetsBundle) throws ThingsboardException { | 62 | public WidgetsBundle saveWidgetsBundle(@RequestBody WidgetsBundle widgetsBundle) throws ThingsboardException { |
63 | try { | 63 | try { |
64 | - if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) { | 64 | + if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { |
65 | widgetsBundle.setTenantId(TenantId.SYS_TENANT_ID); | 65 | widgetsBundle.setTenantId(TenantId.SYS_TENANT_ID); |
66 | } else { | 66 | } else { |
67 | widgetsBundle.setTenantId(getCurrentUser().getTenantId()); | 67 | widgetsBundle.setTenantId(getCurrentUser().getTenantId()); |
@@ -103,7 +103,7 @@ public class WidgetsBundleController extends BaseController { | @@ -103,7 +103,7 @@ public class WidgetsBundleController extends BaseController { | ||
103 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { | 103 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { |
104 | try { | 104 | try { |
105 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | 105 | PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
106 | - if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) { | 106 | + if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { |
107 | return checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByPageLink(getTenantId(), pageLink)); | 107 | return checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByPageLink(getTenantId(), pageLink)); |
108 | } else { | 108 | } else { |
109 | TenantId tenantId = getCurrentUser().getTenantId(); | 109 | TenantId tenantId = getCurrentUser().getTenantId(); |
@@ -119,7 +119,7 @@ public class WidgetsBundleController extends BaseController { | @@ -119,7 +119,7 @@ public class WidgetsBundleController extends BaseController { | ||
119 | @ResponseBody | 119 | @ResponseBody |
120 | public List<WidgetsBundle> getWidgetsBundles() throws ThingsboardException { | 120 | public List<WidgetsBundle> getWidgetsBundles() throws ThingsboardException { |
121 | try { | 121 | try { |
122 | - if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) { | 122 | + if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { |
123 | return checkNotNull(widgetsBundleService.findSystemWidgetsBundles(getTenantId())); | 123 | return checkNotNull(widgetsBundleService.findSystemWidgetsBundles(getTenantId())); |
124 | } else { | 124 | } else { |
125 | TenantId tenantId = getCurrentUser().getTenantId(); | 125 | TenantId tenantId = getCurrentUser().getTenantId(); |
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
@@ -131,6 +131,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -131,6 +131,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
131 | node.put("username", ""); | 131 | node.put("username", ""); |
132 | node.put("password", ""); | 132 | node.put("password", ""); |
133 | node.put("tlsVersion", "TLSv1.2");//NOSONAR, key used to identify password field (not password value itself) | 133 | node.put("tlsVersion", "TLSv1.2");//NOSONAR, key used to identify password field (not password value itself) |
134 | + node.put("enableProxy", false); | ||
134 | mailSettings.setJsonValue(node); | 135 | mailSettings.setJsonValue(node); |
135 | adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, mailSettings); | 136 | adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, mailSettings); |
136 | } | 137 | } |
@@ -16,18 +16,17 @@ | @@ -16,18 +16,17 @@ | ||
16 | package org.thingsboard.server.service.mail; | 16 | package org.thingsboard.server.service.mail; |
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import freemarker.template.Configuration; | ||
20 | +import freemarker.template.Template; | ||
19 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
20 | import org.apache.commons.lang3.StringUtils; | 22 | import org.apache.commons.lang3.StringUtils; |
21 | -import org.apache.velocity.VelocityContext; | ||
22 | -import org.apache.velocity.app.VelocityEngine; | ||
23 | -import org.apache.velocity.exception.VelocityException; | ||
24 | import org.springframework.beans.factory.annotation.Autowired; | 23 | import org.springframework.beans.factory.annotation.Autowired; |
25 | -import org.springframework.beans.factory.annotation.Qualifier; | ||
26 | import org.springframework.context.MessageSource; | 24 | import org.springframework.context.MessageSource; |
27 | import org.springframework.core.NestedRuntimeException; | 25 | import org.springframework.core.NestedRuntimeException; |
28 | import org.springframework.mail.javamail.JavaMailSenderImpl; | 26 | import org.springframework.mail.javamail.JavaMailSenderImpl; |
29 | import org.springframework.mail.javamail.MimeMessageHelper; | 27 | import org.springframework.mail.javamail.MimeMessageHelper; |
30 | import org.springframework.stereotype.Service; | 28 | import org.springframework.stereotype.Service; |
29 | +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; | ||
31 | import org.thingsboard.rule.engine.api.MailService; | 30 | import org.thingsboard.rule.engine.api.MailService; |
32 | import org.thingsboard.server.common.data.AdminSettings; | 31 | import org.thingsboard.server.common.data.AdminSettings; |
33 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 32 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
@@ -40,8 +39,6 @@ import org.thingsboard.server.dao.settings.AdminSettingsService; | @@ -40,8 +39,6 @@ import org.thingsboard.server.dao.settings.AdminSettingsService; | ||
40 | import javax.annotation.PostConstruct; | 39 | import javax.annotation.PostConstruct; |
41 | import javax.mail.MessagingException; | 40 | import javax.mail.MessagingException; |
42 | import javax.mail.internet.MimeMessage; | 41 | import javax.mail.internet.MimeMessage; |
43 | -import java.io.StringWriter; | ||
44 | -import java.io.Writer; | ||
45 | import java.util.HashMap; | 42 | import java.util.HashMap; |
46 | import java.util.Locale; | 43 | import java.util.Locale; |
47 | import java.util.Map; | 44 | import java.util.Map; |
@@ -58,8 +55,7 @@ public class DefaultMailService implements MailService { | @@ -58,8 +55,7 @@ public class DefaultMailService implements MailService { | ||
58 | private MessageSource messages; | 55 | private MessageSource messages; |
59 | 56 | ||
60 | @Autowired | 57 | @Autowired |
61 | - @Qualifier("velocityEngine") | ||
62 | - private VelocityEngine engine; | 58 | + private Configuration freemarkerConfig; |
63 | 59 | ||
64 | private JavaMailSenderImpl mailSender; | 60 | private JavaMailSenderImpl mailSender; |
65 | 61 | ||
@@ -118,6 +114,21 @@ public class DefaultMailService implements MailService { | @@ -118,6 +114,21 @@ public class DefaultMailService implements MailService { | ||
118 | javaMailProperties.put(MAIL_PROP + protocol + ".ssl.protocols", tlsVersion); | 114 | javaMailProperties.put(MAIL_PROP + protocol + ".ssl.protocols", tlsVersion); |
119 | } | 115 | } |
120 | } | 116 | } |
117 | + | ||
118 | + boolean enableProxy = jsonConfig.has("enableProxy") && jsonConfig.get("enableProxy").asBoolean(); | ||
119 | + | ||
120 | + if (enableProxy) { | ||
121 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.host", jsonConfig.get("proxyHost").asText()); | ||
122 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.port", jsonConfig.get("proxyPort").asText()); | ||
123 | + String proxyUser = jsonConfig.get("proxyUser").asText(); | ||
124 | + if (StringUtils.isNoneEmpty(proxyUser)) { | ||
125 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.user", proxyUser); | ||
126 | + } | ||
127 | + String proxyPassword = jsonConfig.get("proxyPassword").asText(); | ||
128 | + if (StringUtils.isNoneEmpty(proxyPassword)) { | ||
129 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.password", proxyPassword); | ||
130 | + } | ||
131 | + } | ||
121 | return javaMailProperties; | 132 | return javaMailProperties; |
122 | } | 133 | } |
123 | 134 | ||
@@ -140,11 +151,10 @@ public class DefaultMailService implements MailService { | @@ -140,11 +151,10 @@ public class DefaultMailService implements MailService { | ||
140 | String mailFrom = jsonConfig.get("mailFrom").asText(); | 151 | String mailFrom = jsonConfig.get("mailFrom").asText(); |
141 | String subject = messages.getMessage("test.message.subject", null, Locale.US); | 152 | String subject = messages.getMessage("test.message.subject", null, Locale.US); |
142 | 153 | ||
143 | - Map<String, Object> model = new HashMap<String, Object>(); | 154 | + Map<String, Object> model = new HashMap<>(); |
144 | model.put(TARGET_EMAIL, email); | 155 | model.put(TARGET_EMAIL, email); |
145 | 156 | ||
146 | - String message = mergeTemplateIntoString(this.engine, | ||
147 | - "test.vm", UTF_8, model); | 157 | + String message = mergeTemplateIntoString("test.ftl", model); |
148 | 158 | ||
149 | sendMail(testMailSender, mailFrom, email, subject, message); | 159 | sendMail(testMailSender, mailFrom, email, subject, message); |
150 | } | 160 | } |
@@ -154,12 +164,11 @@ public class DefaultMailService implements MailService { | @@ -154,12 +164,11 @@ public class DefaultMailService implements MailService { | ||
154 | 164 | ||
155 | String subject = messages.getMessage("activation.subject", null, Locale.US); | 165 | String subject = messages.getMessage("activation.subject", null, Locale.US); |
156 | 166 | ||
157 | - Map<String, Object> model = new HashMap<String, Object>(); | 167 | + Map<String, Object> model = new HashMap<>(); |
158 | model.put("activationLink", activationLink); | 168 | model.put("activationLink", activationLink); |
159 | model.put(TARGET_EMAIL, email); | 169 | model.put(TARGET_EMAIL, email); |
160 | 170 | ||
161 | - String message = mergeTemplateIntoString(this.engine, | ||
162 | - "activation.vm", UTF_8, model); | 171 | + String message = mergeTemplateIntoString("activation.ftl", model); |
163 | 172 | ||
164 | sendMail(mailSender, mailFrom, email, subject, message); | 173 | sendMail(mailSender, mailFrom, email, subject, message); |
165 | } | 174 | } |
@@ -169,12 +178,11 @@ public class DefaultMailService implements MailService { | @@ -169,12 +178,11 @@ public class DefaultMailService implements MailService { | ||
169 | 178 | ||
170 | String subject = messages.getMessage("account.activated.subject", null, Locale.US); | 179 | String subject = messages.getMessage("account.activated.subject", null, Locale.US); |
171 | 180 | ||
172 | - Map<String, Object> model = new HashMap<String, Object>(); | 181 | + Map<String, Object> model = new HashMap<>(); |
173 | model.put("loginLink", loginLink); | 182 | model.put("loginLink", loginLink); |
174 | model.put(TARGET_EMAIL, email); | 183 | model.put(TARGET_EMAIL, email); |
175 | 184 | ||
176 | - String message = mergeTemplateIntoString(this.engine, | ||
177 | - "account.activated.vm", UTF_8, model); | 185 | + String message = mergeTemplateIntoString("account.activated.ftl", model); |
178 | 186 | ||
179 | sendMail(mailSender, mailFrom, email, subject, message); | 187 | sendMail(mailSender, mailFrom, email, subject, message); |
180 | } | 188 | } |
@@ -184,12 +192,11 @@ public class DefaultMailService implements MailService { | @@ -184,12 +192,11 @@ public class DefaultMailService implements MailService { | ||
184 | 192 | ||
185 | String subject = messages.getMessage("reset.password.subject", null, Locale.US); | 193 | String subject = messages.getMessage("reset.password.subject", null, Locale.US); |
186 | 194 | ||
187 | - Map<String, Object> model = new HashMap<String, Object>(); | 195 | + Map<String, Object> model = new HashMap<>(); |
188 | model.put("passwordResetLink", passwordResetLink); | 196 | model.put("passwordResetLink", passwordResetLink); |
189 | model.put(TARGET_EMAIL, email); | 197 | model.put(TARGET_EMAIL, email); |
190 | 198 | ||
191 | - String message = mergeTemplateIntoString(this.engine, | ||
192 | - "reset.password.vm", UTF_8, model); | 199 | + String message = mergeTemplateIntoString("reset.password.ftl", model); |
193 | 200 | ||
194 | sendMail(mailSender, mailFrom, email, subject, message); | 201 | sendMail(mailSender, mailFrom, email, subject, message); |
195 | } | 202 | } |
@@ -199,12 +206,11 @@ public class DefaultMailService implements MailService { | @@ -199,12 +206,11 @@ public class DefaultMailService implements MailService { | ||
199 | 206 | ||
200 | String subject = messages.getMessage("password.was.reset.subject", null, Locale.US); | 207 | String subject = messages.getMessage("password.was.reset.subject", null, Locale.US); |
201 | 208 | ||
202 | - Map<String, Object> model = new HashMap<String, Object>(); | 209 | + Map<String, Object> model = new HashMap<>(); |
203 | model.put("loginLink", loginLink); | 210 | model.put("loginLink", loginLink); |
204 | model.put(TARGET_EMAIL, email); | 211 | model.put(TARGET_EMAIL, email); |
205 | 212 | ||
206 | - String message = mergeTemplateIntoString(this.engine, | ||
207 | - "password.was.reset.vm", UTF_8, model); | 213 | + String message = mergeTemplateIntoString("password.was.reset.ftl", model); |
208 | 214 | ||
209 | sendMail(mailSender, mailFrom, email, subject, message); | 215 | sendMail(mailSender, mailFrom, email, subject, message); |
210 | } | 216 | } |
@@ -230,13 +236,12 @@ public class DefaultMailService implements MailService { | @@ -230,13 +236,12 @@ public class DefaultMailService implements MailService { | ||
230 | public void sendAccountLockoutEmail(String lockoutEmail, String email, Integer maxFailedLoginAttempts) throws ThingsboardException { | 236 | public void sendAccountLockoutEmail(String lockoutEmail, String email, Integer maxFailedLoginAttempts) throws ThingsboardException { |
231 | String subject = messages.getMessage("account.lockout.subject", null, Locale.US); | 237 | String subject = messages.getMessage("account.lockout.subject", null, Locale.US); |
232 | 238 | ||
233 | - Map<String, Object> model = new HashMap<String, Object>(); | 239 | + Map<String, Object> model = new HashMap<>(); |
234 | model.put("lockoutAccount", lockoutEmail); | 240 | model.put("lockoutAccount", lockoutEmail); |
235 | model.put("maxFailedLoginAttempts", maxFailedLoginAttempts); | 241 | model.put("maxFailedLoginAttempts", maxFailedLoginAttempts); |
236 | model.put(TARGET_EMAIL, email); | 242 | model.put(TARGET_EMAIL, email); |
237 | 243 | ||
238 | - String message = mergeTemplateIntoString(this.engine, | ||
239 | - "account.lockout.vm", UTF_8, model); | 244 | + String message = mergeTemplateIntoString("account.lockout.ftl", model); |
240 | 245 | ||
241 | sendMail(mailSender, mailFrom, email, subject, message); | 246 | sendMail(mailSender, mailFrom, email, subject, message); |
242 | } | 247 | } |
@@ -257,20 +262,14 @@ public class DefaultMailService implements MailService { | @@ -257,20 +262,14 @@ public class DefaultMailService implements MailService { | ||
257 | } | 262 | } |
258 | } | 263 | } |
259 | 264 | ||
260 | - private static String mergeTemplateIntoString(VelocityEngine velocityEngine, String templateLocation, | ||
261 | - String encoding, Map<String, Object> model) throws VelocityException { | ||
262 | - | ||
263 | - StringWriter result = new StringWriter(); | ||
264 | - mergeTemplate(velocityEngine, templateLocation, encoding, model, result); | ||
265 | - return result.toString(); | ||
266 | - } | ||
267 | - | ||
268 | - private static void mergeTemplate( | ||
269 | - VelocityEngine velocityEngine, String templateLocation, String encoding, | ||
270 | - Map<String, Object> model, Writer writer) throws VelocityException { | ||
271 | - | ||
272 | - VelocityContext velocityContext = new VelocityContext(model); | ||
273 | - velocityEngine.mergeTemplate(templateLocation, encoding, velocityContext, writer); | 265 | + private String mergeTemplateIntoString(String templateLocation, |
266 | + Map<String, Object> model) throws ThingsboardException { | ||
267 | + try { | ||
268 | + Template template = freemarkerConfig.getTemplate(templateLocation); | ||
269 | + return FreeMarkerTemplateUtils.processTemplateIntoString(template, model); | ||
270 | + } catch (Exception e) { | ||
271 | + throw handleException(e); | ||
272 | + } | ||
274 | } | 273 | } |
275 | 274 | ||
276 | protected ThingsboardException handleException(Exception exception) { | 275 | protected ThingsboardException handleException(Exception exception) { |
@@ -46,6 +46,9 @@ import java.util.concurrent.atomic.AtomicInteger; | @@ -46,6 +46,9 @@ import java.util.concurrent.atomic.AtomicInteger; | ||
46 | @Service | 46 | @Service |
47 | public class RemoteJsInvokeService extends AbstractJsInvokeService { | 47 | public class RemoteJsInvokeService extends AbstractJsInvokeService { |
48 | 48 | ||
49 | + @Value("${queue.js.max_eval_requests_timeout}") | ||
50 | + private long maxEvalRequestsTimeout; | ||
51 | + | ||
49 | @Value("${queue.js.max_requests_timeout}") | 52 | @Value("${queue.js.max_requests_timeout}") |
50 | private long maxRequestsTimeout; | 53 | private long maxRequestsTimeout; |
51 | 54 | ||
@@ -59,22 +62,22 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | @@ -59,22 +62,22 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | ||
59 | @Value("${js.remote.stats.enabled:false}") | 62 | @Value("${js.remote.stats.enabled:false}") |
60 | private boolean statsEnabled; | 63 | private boolean statsEnabled; |
61 | 64 | ||
62 | - private final AtomicInteger kafkaPushedMsgs = new AtomicInteger(0); | ||
63 | - private final AtomicInteger kafkaInvokeMsgs = new AtomicInteger(0); | ||
64 | - private final AtomicInteger kafkaEvalMsgs = new AtomicInteger(0); | ||
65 | - private final AtomicInteger kafkaFailedMsgs = new AtomicInteger(0); | ||
66 | - private final AtomicInteger kafkaTimeoutMsgs = new AtomicInteger(0); | 65 | + private final AtomicInteger queuePushedMsgs = new AtomicInteger(0); |
66 | + private final AtomicInteger queueInvokeMsgs = new AtomicInteger(0); | ||
67 | + private final AtomicInteger queueEvalMsgs = new AtomicInteger(0); | ||
68 | + private final AtomicInteger queueFailedMsgs = new AtomicInteger(0); | ||
69 | + private final AtomicInteger queueTimeoutMsgs = new AtomicInteger(0); | ||
67 | 70 | ||
68 | @Scheduled(fixedDelayString = "${js.remote.stats.print_interval_ms}") | 71 | @Scheduled(fixedDelayString = "${js.remote.stats.print_interval_ms}") |
69 | public void printStats() { | 72 | public void printStats() { |
70 | if (statsEnabled) { | 73 | if (statsEnabled) { |
71 | - int pushedMsgs = kafkaPushedMsgs.getAndSet(0); | ||
72 | - int invokeMsgs = kafkaInvokeMsgs.getAndSet(0); | ||
73 | - int evalMsgs = kafkaEvalMsgs.getAndSet(0); | ||
74 | - int failed = kafkaFailedMsgs.getAndSet(0); | ||
75 | - int timedOut = kafkaTimeoutMsgs.getAndSet(0); | 74 | + int pushedMsgs = queuePushedMsgs.getAndSet(0); |
75 | + int invokeMsgs = queueInvokeMsgs.getAndSet(0); | ||
76 | + int evalMsgs = queueEvalMsgs.getAndSet(0); | ||
77 | + int failed = queueFailedMsgs.getAndSet(0); | ||
78 | + int timedOut = queueTimeoutMsgs.getAndSet(0); | ||
76 | if (pushedMsgs > 0 || invokeMsgs > 0 || evalMsgs > 0 || failed > 0 || timedOut > 0) { | 79 | if (pushedMsgs > 0 || invokeMsgs > 0 || evalMsgs > 0 || failed > 0 || timedOut > 0) { |
77 | - log.info("Kafka JS Invoke Stats: pushed [{}] received [{}] invoke [{}] eval [{}] failed [{}] timedOut [{}]", | 80 | + log.info("Queue JS Invoke Stats: pushed [{}] received [{}] invoke [{}] eval [{}] failed [{}] timedOut [{}]", |
78 | pushedMsgs, invokeMsgs + evalMsgs, invokeMsgs, evalMsgs, failed, timedOut); | 81 | pushedMsgs, invokeMsgs + evalMsgs, invokeMsgs, evalMsgs, failed, timedOut); |
79 | } | 82 | } |
80 | } | 83 | } |
@@ -113,22 +116,22 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | @@ -113,22 +116,22 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | ||
113 | 116 | ||
114 | log.trace("Post compile request for scriptId [{}]", scriptId); | 117 | log.trace("Post compile request for scriptId [{}]", scriptId); |
115 | ListenableFuture<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> future = requestTemplate.send(new TbProtoJsQueueMsg<>(UUID.randomUUID(), jsRequestWrapper)); | 118 | ListenableFuture<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> future = requestTemplate.send(new TbProtoJsQueueMsg<>(UUID.randomUUID(), jsRequestWrapper)); |
116 | - if (maxRequestsTimeout > 0) { | ||
117 | - future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService); | 119 | + if (maxEvalRequestsTimeout > 0) { |
120 | + future = Futures.withTimeout(future, maxEvalRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService); | ||
118 | } | 121 | } |
119 | - kafkaPushedMsgs.incrementAndGet(); | 122 | + queuePushedMsgs.incrementAndGet(); |
120 | Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() { | 123 | Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() { |
121 | @Override | 124 | @Override |
122 | public void onSuccess(@Nullable TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse> result) { | 125 | public void onSuccess(@Nullable TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse> result) { |
123 | - kafkaEvalMsgs.incrementAndGet(); | 126 | + queueEvalMsgs.incrementAndGet(); |
124 | } | 127 | } |
125 | 128 | ||
126 | @Override | 129 | @Override |
127 | public void onFailure(Throwable t) { | 130 | public void onFailure(Throwable t) { |
128 | if (t instanceof TimeoutException || (t.getCause() != null && t.getCause() instanceof TimeoutException)) { | 131 | if (t instanceof TimeoutException || (t.getCause() != null && t.getCause() instanceof TimeoutException)) { |
129 | - kafkaTimeoutMsgs.incrementAndGet(); | 132 | + queueTimeoutMsgs.incrementAndGet(); |
130 | } | 133 | } |
131 | - kafkaFailedMsgs.incrementAndGet(); | 134 | + queueFailedMsgs.incrementAndGet(); |
132 | } | 135 | } |
133 | }, MoreExecutors.directExecutor()); | 136 | }, MoreExecutors.directExecutor()); |
134 | return Futures.transform(future, response -> { | 137 | return Futures.transform(future, response -> { |
@@ -170,20 +173,20 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | @@ -170,20 +173,20 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | ||
170 | if (maxRequestsTimeout > 0) { | 173 | if (maxRequestsTimeout > 0) { |
171 | future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService); | 174 | future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService); |
172 | } | 175 | } |
173 | - kafkaPushedMsgs.incrementAndGet(); | 176 | + queuePushedMsgs.incrementAndGet(); |
174 | Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() { | 177 | Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() { |
175 | @Override | 178 | @Override |
176 | public void onSuccess(@Nullable TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse> result) { | 179 | public void onSuccess(@Nullable TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse> result) { |
177 | - kafkaInvokeMsgs.incrementAndGet(); | 180 | + queueInvokeMsgs.incrementAndGet(); |
178 | } | 181 | } |
179 | 182 | ||
180 | @Override | 183 | @Override |
181 | public void onFailure(Throwable t) { | 184 | public void onFailure(Throwable t) { |
182 | onScriptExecutionError(scriptId); | 185 | onScriptExecutionError(scriptId); |
183 | if (t instanceof TimeoutException || (t.getCause() != null && t.getCause() instanceof TimeoutException)) { | 186 | if (t instanceof TimeoutException || (t.getCause() != null && t.getCause() instanceof TimeoutException)) { |
184 | - kafkaTimeoutMsgs.incrementAndGet(); | 187 | + queueTimeoutMsgs.incrementAndGet(); |
185 | } | 188 | } |
186 | - kafkaFailedMsgs.incrementAndGet(); | 189 | + queueFailedMsgs.incrementAndGet(); |
187 | } | 190 | } |
188 | }, MoreExecutors.directExecutor()); | 191 | }, MoreExecutors.directExecutor()); |
189 | return Futures.transform(future, response -> { | 192 | return Futures.transform(future, response -> { |
@@ -105,7 +105,7 @@ public class CustomerUserPermissions extends AbstractPermissions { | @@ -105,7 +105,7 @@ public class CustomerUserPermissions extends AbstractPermissions { | ||
105 | 105 | ||
106 | @Override | 106 | @Override |
107 | public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { | 107 | public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { |
108 | - if (userEntity.getAuthority() != Authority.CUSTOMER_USER) { | 108 | + if (!Authority.CUSTOMER_USER.equals(userEntity.getAuthority())) { |
109 | return false; | 109 | return false; |
110 | } | 110 | } |
111 | if (!user.getId().equals(userId)) { | 111 | if (!user.getId().equals(userId)) { |
@@ -57,7 +57,7 @@ public class SysAdminPermissions extends AbstractPermissions { | @@ -57,7 +57,7 @@ public class SysAdminPermissions extends AbstractPermissions { | ||
57 | 57 | ||
58 | @Override | 58 | @Override |
59 | public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { | 59 | public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { |
60 | - if (userEntity.getAuthority() == Authority.CUSTOMER_USER) { | 60 | + if (Authority.CUSTOMER_USER.equals(userEntity.getAuthority())) { |
61 | return false; | 61 | return false; |
62 | } | 62 | } |
63 | return true; | 63 | return true; |
@@ -76,7 +76,7 @@ public class TenantAdminPermissions extends AbstractPermissions { | @@ -76,7 +76,7 @@ public class TenantAdminPermissions extends AbstractPermissions { | ||
76 | 76 | ||
77 | @Override | 77 | @Override |
78 | public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { | 78 | public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) { |
79 | - if (userEntity.getAuthority() == Authority.SYS_ADMIN) { | 79 | + if (Authority.SYS_ADMIN.equals(userEntity.getAuthority())) { |
80 | return false; | 80 | return false; |
81 | } | 81 | } |
82 | if (!user.getTenantId().equals(userEntity.getTenantId())) { | 82 | if (!user.getTenantId().equals(userEntity.getTenantId())) { |
@@ -224,7 +224,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer | @@ -224,7 +224,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer | ||
224 | return null; | 224 | return null; |
225 | } | 225 | } |
226 | }, | 226 | }, |
227 | - s -> (StringUtils.isEmpty(s.getScope()) || scope.equals(s.getScope().name())), | 227 | + s -> (TbAttributeSubscriptionScope.ANY_SCOPE.equals(s.getScope()) || scope.equals(s.getScope().name())), |
228 | s -> { | 228 | s -> { |
229 | List<TsKvEntry> subscriptionUpdate = null; | 229 | List<TsKvEntry> subscriptionUpdate = null; |
230 | for (AttributeKvEntry kv : attributes) { | 230 | for (AttributeKvEntry kv : attributes) { |
@@ -17,6 +17,6 @@ package org.thingsboard.server.service.subscription; | @@ -17,6 +17,6 @@ package org.thingsboard.server.service.subscription; | ||
17 | 17 | ||
18 | public enum TbAttributeSubscriptionScope { | 18 | public enum TbAttributeSubscriptionScope { |
19 | 19 | ||
20 | - CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE | 20 | + ANY_SCOPE, CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE |
21 | 21 | ||
22 | } | 22 | } |
@@ -345,7 +345,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -345,7 +345,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
345 | keys.forEach(key -> subState.put(key, 0L)); | 345 | keys.forEach(key -> subState.put(key, 0L)); |
346 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); | 346 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); |
347 | 347 | ||
348 | - TbAttributeSubscriptionScope scope = StringUtils.isEmpty(cmd.getScope()) ? TbAttributeSubscriptionScope.SERVER_SCOPE : TbAttributeSubscriptionScope.valueOf(cmd.getScope()); | 348 | + TbAttributeSubscriptionScope scope = StringUtils.isEmpty(cmd.getScope()) ? TbAttributeSubscriptionScope.ANY_SCOPE : TbAttributeSubscriptionScope.valueOf(cmd.getScope()); |
349 | 349 | ||
350 | TbAttributeSubscription sub = TbAttributeSubscription.builder() | 350 | TbAttributeSubscription sub = TbAttributeSubscription.builder() |
351 | .serviceId(serviceId) | 351 | .serviceId(serviceId) |
@@ -442,7 +442,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -442,7 +442,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
442 | Map<String, Long> subState = new HashMap<>(attributesData.size()); | 442 | Map<String, Long> subState = new HashMap<>(attributesData.size()); |
443 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); | 443 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); |
444 | 444 | ||
445 | - TbAttributeSubscriptionScope scope = StringUtils.isEmpty(cmd.getScope()) ? TbAttributeSubscriptionScope.SERVER_SCOPE : TbAttributeSubscriptionScope.valueOf(cmd.getScope()); | 445 | + TbAttributeSubscriptionScope scope = StringUtils.isEmpty(cmd.getScope()) ? TbAttributeSubscriptionScope.ANY_SCOPE : TbAttributeSubscriptionScope.valueOf(cmd.getScope()); |
446 | 446 | ||
447 | TbAttributeSubscription sub = TbAttributeSubscription.builder() | 447 | TbAttributeSubscription sub = TbAttributeSubscription.builder() |
448 | .serviceId(serviceId) | 448 | .serviceId(serviceId) |
application/src/main/resources/templates/account.activated.ftl
renamed from
application/src/main/resources/templates/account.activated.vm
1 | -#* | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - *# | 1 | +<#-- |
2 | + | ||
3 | + Copyright © 2016-2020 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
16 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | 18 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
17 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 19 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
18 | <head> | 20 | <head> |
@@ -96,7 +98,7 @@ background-color: #f6f6f6; | @@ -96,7 +98,7 @@ background-color: #f6f6f6; | ||
96 | </tr> | 98 | </tr> |
97 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 99 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
98 | <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> | 100 | <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> |
99 | - <a href="$loginLink" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Login</a> | 101 | + <a href="${loginLink}" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Login</a> |
100 | </td> | 102 | </td> |
101 | </tr> | 103 | </tr> |
102 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 104 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
@@ -109,7 +111,7 @@ background-color: #f6f6f6; | @@ -109,7 +111,7 @@ background-color: #f6f6f6; | ||
109 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> | 111 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> |
110 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 112 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
111 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 113 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
112 | - <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:$targetEmail" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">$targetEmail</a> by Thingsboard.</td> | 114 | + <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:${targetEmail}" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">${targetEmail}</a> by Thingsboard.</td> |
113 | </tr> | 115 | </tr> |
114 | </table> | 116 | </table> |
115 | </div> | 117 | </div> |
application/src/main/resources/templates/account.lockout.ftl
renamed from
application/src/main/resources/templates/test.vm
1 | -#* | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - *# | 1 | +<#-- |
2 | + | ||
3 | + Copyright © 2016-2020 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
16 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | 18 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
17 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 19 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
18 | <head> | 20 | <head> |
19 | <meta name="viewport" content="width=device-width" /> | 21 | <meta name="viewport" content="width=device-width" /> |
20 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | 22 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
21 | -<title>Thingsboard - Test Message</title> | 23 | +<title>Thingsboard - Account Lockout</title> |
22 | 24 | ||
23 | 25 | ||
24 | <style type="text/css"> | 26 | <style type="text/css"> |
@@ -81,12 +83,12 @@ background-color: #f6f6f6; | @@ -81,12 +83,12 @@ background-color: #f6f6f6; | ||
81 | <meta itemprop="name" content="Confirm Email" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" /><table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 83 | <meta itemprop="name" content="Confirm Email" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" /><table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
82 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 84 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
83 | <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #348eda; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> | 85 | <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #348eda; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> |
84 | - <h2>Test message from Thingsboard</h2> | 86 | + <h2>Thingsboard user account has been locked out</h2> |
85 | </td> | 87 | </td> |
86 | </tr> | 88 | </tr> |
87 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 89 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
88 | <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> | 90 | <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> |
89 | - This email is indicating that your outgoing mail settings were set up correctly. | 91 | + Thingsboard user account ${lockoutAccount} has been lockout due to failed credentials were provided more than ${maxFailedLoginAttempts} times. |
90 | </td> | 92 | </td> |
91 | </tr> | 93 | </tr> |
92 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 94 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
@@ -99,7 +101,7 @@ background-color: #f6f6f6; | @@ -99,7 +101,7 @@ background-color: #f6f6f6; | ||
99 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> | 101 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> |
100 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 102 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
101 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 103 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
102 | - <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:$targetEmail" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">$targetEmail</a> by Thingsboard.</td> | 104 | + <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:${targetEmail}" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">${targetEmail}</a> by Thingsboard.</td> |
103 | </tr> | 105 | </tr> |
104 | </table> | 106 | </table> |
105 | </div> | 107 | </div> |
application/src/main/resources/templates/activation.ftl
renamed from
application/src/main/resources/templates/activation.vm
1 | -#* | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - *# | 1 | +<#-- |
2 | + | ||
3 | + Copyright © 2016-2020 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
16 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | 18 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
17 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 19 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
18 | <head> | 20 | <head> |
@@ -96,7 +98,7 @@ background-color: #f6f6f6; | @@ -96,7 +98,7 @@ background-color: #f6f6f6; | ||
96 | </tr> | 98 | </tr> |
97 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 99 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
98 | <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> | 100 | <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> |
99 | - <a href="$activationLink" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Activate your account</a> | 101 | + <a href="${activationLink}" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Activate your account</a> |
100 | </td> | 102 | </td> |
101 | </tr> | 103 | </tr> |
102 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 104 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
@@ -109,7 +111,7 @@ background-color: #f6f6f6; | @@ -109,7 +111,7 @@ background-color: #f6f6f6; | ||
109 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> | 111 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> |
110 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 112 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
111 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 113 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
112 | - <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:$targetEmail" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">$targetEmail</a> by Thingsboard.</td> | 114 | + <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:${targetEmail}" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">${targetEmail}</a> by Thingsboard.</td> |
113 | </tr> | 115 | </tr> |
114 | </table> | 116 | </table> |
115 | </div> | 117 | </div> |
application/src/main/resources/templates/password.was.reset.ftl
renamed from
application/src/main/resources/templates/password.was.reset.vm
1 | -#* | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - *# | 1 | +<#-- |
2 | + | ||
3 | + Copyright © 2016-2020 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
16 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | 18 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
17 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 19 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
18 | <head> | 20 | <head> |
@@ -96,7 +98,7 @@ background-color: #f6f6f6; | @@ -96,7 +98,7 @@ background-color: #f6f6f6; | ||
96 | </tr> | 98 | </tr> |
97 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 99 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
98 | <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> | 100 | <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> |
99 | - <a href="$loginLink" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Login</a> | 101 | + <a href="${loginLink}" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Login</a> |
100 | </td> | 102 | </td> |
101 | </tr> | 103 | </tr> |
102 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 104 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
@@ -109,7 +111,7 @@ background-color: #f6f6f6; | @@ -109,7 +111,7 @@ background-color: #f6f6f6; | ||
109 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> | 111 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> |
110 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 112 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
111 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 113 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
112 | - <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:$targetEmail" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">$targetEmail</a> by Thingsboard.</td> | 114 | + <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:${targetEmail}" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">${targetEmail}</a> by Thingsboard.</td> |
113 | </tr> | 115 | </tr> |
114 | </table> | 116 | </table> |
115 | </div> | 117 | </div> |
application/src/main/resources/templates/reset.password.ftl
renamed from
application/src/main/resources/templates/reset.password.vm
1 | -#* | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - *# | 1 | +<#-- |
2 | + | ||
3 | + Copyright © 2016-2020 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
16 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | 18 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
17 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 19 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
18 | <head> | 20 | <head> |
@@ -96,7 +98,7 @@ background-color: #f6f6f6; | @@ -96,7 +98,7 @@ background-color: #f6f6f6; | ||
96 | </tr> | 98 | </tr> |
97 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 99 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
98 | <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> | 100 | <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> |
99 | - <a href="$passwordResetLink" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Reset password</a> | 101 | + <a href="${passwordResetLink}" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Reset password</a> |
100 | </td> | 102 | </td> |
101 | </tr> | 103 | </tr> |
102 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 104 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
@@ -109,7 +111,7 @@ background-color: #f6f6f6; | @@ -109,7 +111,7 @@ background-color: #f6f6f6; | ||
109 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> | 111 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> |
110 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 112 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
111 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 113 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
112 | - <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:$targetEmail" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">$targetEmail</a> by Thingsboard.</td> | 114 | + <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:${targetEmail}" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">${targetEmail}</a> by Thingsboard.</td> |
113 | </tr> | 115 | </tr> |
114 | </table> | 116 | </table> |
115 | </div> | 117 | </div> |
application/src/main/resources/templates/test.ftl
renamed from
application/src/main/resources/templates/account.lockout.vm
1 | -#* | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - *# | 1 | +<#-- |
2 | + | ||
3 | + Copyright © 2016-2020 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
16 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | 18 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
17 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 19 | <html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
18 | <head> | 20 | <head> |
19 | <meta name="viewport" content="width=device-width" /> | 21 | <meta name="viewport" content="width=device-width" /> |
20 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | 22 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
21 | -<title>Thingsboard - Account Lockout</title> | 23 | +<title>Thingsboard - Test Message</title> |
22 | 24 | ||
23 | 25 | ||
24 | <style type="text/css"> | 26 | <style type="text/css"> |
@@ -81,12 +83,12 @@ background-color: #f6f6f6; | @@ -81,12 +83,12 @@ background-color: #f6f6f6; | ||
81 | <meta itemprop="name" content="Confirm Email" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" /><table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 83 | <meta itemprop="name" content="Confirm Email" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" /><table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
82 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 84 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
83 | <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #348eda; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> | 85 | <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #348eda; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> |
84 | - <h2>Thingsboard user account has been locked out</h2> | 86 | + <h2>Test message from Thingsboard</h2> |
85 | </td> | 87 | </td> |
86 | </tr> | 88 | </tr> |
87 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 89 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
88 | <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> | 90 | <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> |
89 | - Thingsboard user account $lockoutAccount has been lockout due to failed credentials were provided more than $maxFailedLoginAttempts times. | 91 | + This email is indicating that your outgoing mail settings were set up correctly. |
90 | </td> | 92 | </td> |
91 | </tr> | 93 | </tr> |
92 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 94 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
@@ -99,7 +101,7 @@ background-color: #f6f6f6; | @@ -99,7 +101,7 @@ background-color: #f6f6f6; | ||
99 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> | 101 | <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"> |
100 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 102 | <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
101 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> | 103 | <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> |
102 | - <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:$targetEmail" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">$targetEmail</a> by Thingsboard.</td> | 104 | + <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">This email was sent to <a href="mailto:${targetEmail}" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">${targetEmail}</a> by Thingsboard.</td> |
103 | </tr> | 105 | </tr> |
104 | </table> | 106 | </table> |
105 | </div> | 107 | </div> |
@@ -668,6 +668,8 @@ queue: | @@ -668,6 +668,8 @@ queue: | ||
668 | # JS Eval max pending requests | 668 | # JS Eval max pending requests |
669 | max_pending_requests: "${REMOTE_JS_MAX_PENDING_REQUESTS:10000}" | 669 | max_pending_requests: "${REMOTE_JS_MAX_PENDING_REQUESTS:10000}" |
670 | # JS Eval max request timeout | 670 | # JS Eval max request timeout |
671 | + max_eval_requests_timeout: "${REMOTE_JS_MAX_EVAL_REQUEST_TIMEOUT:60000}" | ||
672 | + # JS max request timeout | ||
671 | max_requests_timeout: "${REMOTE_JS_MAX_REQUEST_TIMEOUT:10000}" | 673 | max_requests_timeout: "${REMOTE_JS_MAX_REQUEST_TIMEOUT:10000}" |
672 | # JS response poll interval | 674 | # JS response poll interval |
673 | response_poll_interval: "${REMOTE_JS_RESPONSE_POLL_INTERVAL_MS:25}" | 675 | response_poll_interval: "${REMOTE_JS_RESPONSE_POLL_INTERVAL_MS:25}" |
common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/guava/GuavaMultiPageResultSet.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.cassandra.guava; | ||
17 | + | ||
18 | +import com.datastax.oss.driver.api.core.cql.AsyncResultSet; | ||
19 | +import com.datastax.oss.driver.api.core.cql.ColumnDefinitions; | ||
20 | +import com.datastax.oss.driver.api.core.cql.ExecutionInfo; | ||
21 | +import com.datastax.oss.driver.api.core.cql.ResultSet; | ||
22 | +import com.datastax.oss.driver.api.core.cql.Row; | ||
23 | +import com.datastax.oss.driver.api.core.cql.Statement; | ||
24 | +import com.datastax.oss.driver.internal.core.util.CountingIterator; | ||
25 | +import com.datastax.oss.driver.internal.core.util.concurrent.BlockingOperation; | ||
26 | +import edu.umd.cs.findbugs.annotations.NonNull; | ||
27 | + | ||
28 | +import java.nio.ByteBuffer; | ||
29 | +import java.util.ArrayList; | ||
30 | +import java.util.Iterator; | ||
31 | +import java.util.List; | ||
32 | + | ||
33 | +public class GuavaMultiPageResultSet implements ResultSet { | ||
34 | + | ||
35 | + private final RowIterator iterator; | ||
36 | + private final List<ExecutionInfo> executionInfos = new ArrayList<>(); | ||
37 | + private ColumnDefinitions columnDefinitions; | ||
38 | + | ||
39 | + public GuavaMultiPageResultSet(@NonNull GuavaSession session, @NonNull Statement statement, @NonNull AsyncResultSet firstPage) { | ||
40 | + assert firstPage.hasMorePages(); | ||
41 | + this.iterator = new RowIterator(session, statement, firstPage); | ||
42 | + this.executionInfos.add(firstPage.getExecutionInfo()); | ||
43 | + this.columnDefinitions = firstPage.getColumnDefinitions(); | ||
44 | + } | ||
45 | + | ||
46 | + @NonNull | ||
47 | + @Override | ||
48 | + public ColumnDefinitions getColumnDefinitions() { | ||
49 | + return columnDefinitions; | ||
50 | + } | ||
51 | + | ||
52 | + @NonNull | ||
53 | + @Override | ||
54 | + public List<ExecutionInfo> getExecutionInfos() { | ||
55 | + return executionInfos; | ||
56 | + } | ||
57 | + | ||
58 | + @Override | ||
59 | + public boolean isFullyFetched() { | ||
60 | + return iterator.isFullyFetched(); | ||
61 | + } | ||
62 | + | ||
63 | + @Override | ||
64 | + public int getAvailableWithoutFetching() { | ||
65 | + return iterator.remaining(); | ||
66 | + } | ||
67 | + | ||
68 | + @NonNull | ||
69 | + @Override | ||
70 | + public Iterator<Row> iterator() { | ||
71 | + return iterator; | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public boolean wasApplied() { | ||
76 | + return iterator.wasApplied(); | ||
77 | + } | ||
78 | + | ||
79 | + private class RowIterator extends CountingIterator<Row> { | ||
80 | + private GuavaSession session; | ||
81 | + private Statement statement; | ||
82 | + private AsyncResultSet currentPage; | ||
83 | + private Iterator<Row> currentRows; | ||
84 | + | ||
85 | + private RowIterator(GuavaSession session, Statement statement, AsyncResultSet firstPage) { | ||
86 | + super(firstPage.remaining()); | ||
87 | + this.session = session; | ||
88 | + this.statement = statement; | ||
89 | + this.currentPage = firstPage; | ||
90 | + this.currentRows = firstPage.currentPage().iterator(); | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + protected Row computeNext() { | ||
95 | + maybeMoveToNextPage(); | ||
96 | + return currentRows.hasNext() ? currentRows.next() : endOfData(); | ||
97 | + } | ||
98 | + | ||
99 | + private void maybeMoveToNextPage() { | ||
100 | + if (!currentRows.hasNext() && currentPage.hasMorePages()) { | ||
101 | + BlockingOperation.checkNotDriverThread(); | ||
102 | + ByteBuffer nextPagingState = currentPage.getExecutionInfo().getPagingState(); | ||
103 | + this.statement = this.statement.setPagingState(nextPagingState); | ||
104 | + AsyncResultSet nextPage = GuavaSession.getSafe(this.session.executeAsync(this.statement)); | ||
105 | + currentPage = nextPage; | ||
106 | + remaining += nextPage.remaining(); | ||
107 | + currentRows = nextPage.currentPage().iterator(); | ||
108 | + executionInfos.add(nextPage.getExecutionInfo()); | ||
109 | + // The definitions can change from page to page if this result set was built from a bound | ||
110 | + // 'SELECT *', and the schema was altered. | ||
111 | + columnDefinitions = nextPage.getColumnDefinitions(); | ||
112 | + } | ||
113 | + } | ||
114 | + | ||
115 | + private boolean isFullyFetched() { | ||
116 | + return !currentPage.hasMorePages(); | ||
117 | + } | ||
118 | + | ||
119 | + private boolean wasApplied() { | ||
120 | + return currentPage.wasApplied(); | ||
121 | + } | ||
122 | + } | ||
123 | +} |
@@ -17,13 +17,18 @@ package org.thingsboard.server.dao.cassandra.guava; | @@ -17,13 +17,18 @@ package org.thingsboard.server.dao.cassandra.guava; | ||
17 | 17 | ||
18 | import com.datastax.oss.driver.api.core.cql.AsyncResultSet; | 18 | import com.datastax.oss.driver.api.core.cql.AsyncResultSet; |
19 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; | 19 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; |
20 | +import com.datastax.oss.driver.api.core.cql.ResultSet; | ||
20 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; | 21 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; |
21 | import com.datastax.oss.driver.api.core.cql.Statement; | 22 | import com.datastax.oss.driver.api.core.cql.Statement; |
22 | import com.datastax.oss.driver.api.core.cql.SyncCqlSession; | 23 | import com.datastax.oss.driver.api.core.cql.SyncCqlSession; |
23 | import com.datastax.oss.driver.api.core.session.Session; | 24 | import com.datastax.oss.driver.api.core.session.Session; |
24 | import com.datastax.oss.driver.api.core.type.reflect.GenericType; | 25 | import com.datastax.oss.driver.api.core.type.reflect.GenericType; |
25 | import com.datastax.oss.driver.internal.core.cql.DefaultPrepareRequest; | 26 | import com.datastax.oss.driver.internal.core.cql.DefaultPrepareRequest; |
27 | +import com.datastax.oss.driver.internal.core.cql.SinglePageResultSet; | ||
26 | import com.google.common.util.concurrent.ListenableFuture; | 28 | import com.google.common.util.concurrent.ListenableFuture; |
29 | +import edu.umd.cs.findbugs.annotations.NonNull; | ||
30 | + | ||
31 | +import java.util.concurrent.ExecutionException; | ||
27 | 32 | ||
28 | public interface GuavaSession extends Session, SyncCqlSession { | 33 | public interface GuavaSession extends Session, SyncCqlSession { |
29 | 34 | ||
@@ -33,6 +38,16 @@ public interface GuavaSession extends Session, SyncCqlSession { | @@ -33,6 +38,16 @@ public interface GuavaSession extends Session, SyncCqlSession { | ||
33 | GenericType<ListenableFuture<PreparedStatement>> ASYNC_PREPARED = | 38 | GenericType<ListenableFuture<PreparedStatement>> ASYNC_PREPARED = |
34 | new GenericType<ListenableFuture<PreparedStatement>>() {}; | 39 | new GenericType<ListenableFuture<PreparedStatement>>() {}; |
35 | 40 | ||
41 | + @NonNull | ||
42 | + default ResultSet execute(@NonNull Statement<?> statement) { | ||
43 | + AsyncResultSet firstPage = getSafe(this.executeAsync(statement)); | ||
44 | + if (firstPage.hasMorePages()) { | ||
45 | + return new GuavaMultiPageResultSet(this, statement, firstPage); | ||
46 | + } else { | ||
47 | + return new SinglePageResultSet(firstPage); | ||
48 | + } | ||
49 | + } | ||
50 | + | ||
36 | default ListenableFuture<AsyncResultSet> executeAsync(Statement<?> statement) { | 51 | default ListenableFuture<AsyncResultSet> executeAsync(Statement<?> statement) { |
37 | return this.execute(statement, ASYNC); | 52 | return this.execute(statement, ASYNC); |
38 | } | 53 | } |
@@ -48,4 +63,12 @@ public interface GuavaSession extends Session, SyncCqlSession { | @@ -48,4 +63,12 @@ public interface GuavaSession extends Session, SyncCqlSession { | ||
48 | default ListenableFuture<PreparedStatement> prepareAsync(String statement) { | 63 | default ListenableFuture<PreparedStatement> prepareAsync(String statement) { |
49 | return this.prepareAsync(SimpleStatement.newInstance(statement)); | 64 | return this.prepareAsync(SimpleStatement.newInstance(statement)); |
50 | } | 65 | } |
66 | + | ||
67 | + static AsyncResultSet getSafe(ListenableFuture<AsyncResultSet> future) { | ||
68 | + try { | ||
69 | + return future.get(); | ||
70 | + } catch (InterruptedException | ExecutionException e) { | ||
71 | + throw new IllegalStateException(e); | ||
72 | + } | ||
73 | + } | ||
51 | } | 74 | } |
@@ -19,10 +19,10 @@ version: '2.2' | @@ -19,10 +19,10 @@ version: '2.2' | ||
19 | services: | 19 | services: |
20 | tb-js-executor: | 20 | tb-js-executor: |
21 | env_file: | 21 | env_file: |
22 | - - queue-pubsub.env.env | 22 | + - queue-pubsub.env |
23 | tb-core1: | 23 | tb-core1: |
24 | env_file: | 24 | env_file: |
25 | - - queue-pubsub.env.env | 25 | + - queue-pubsub.env |
26 | depends_on: | 26 | depends_on: |
27 | - zookeeper | 27 | - zookeeper |
28 | - redis | 28 | - redis |
1 | TB_QUEUE_TYPE=service-bus | 1 | TB_QUEUE_TYPE=service-bus |
2 | TB_QUEUE_SERVICE_BUS_NAMESPACE_NAME=YOUR_NAMESPACE_NAME | 2 | TB_QUEUE_SERVICE_BUS_NAMESPACE_NAME=YOUR_NAMESPACE_NAME |
3 | TB_QUEUE_SERVICE_BUS_SAS_KEY_NAME=YOUR_SAS_KEY_NAME | 3 | TB_QUEUE_SERVICE_BUS_SAS_KEY_NAME=YOUR_SAS_KEY_NAME |
4 | -TB_QUEUE_SERVICE_BUS_SAS_KEY=YOUR_SAS_KEY | ||
4 | +TB_QUEUE_SERVICE_BUS_SAS_KEY=YOUR_SAS_KEY |
@@ -13,9 +13,9 @@ | @@ -13,9 +13,9 @@ | ||
13 | } | 13 | } |
14 | }, | 14 | }, |
15 | "@azure/amqp-common": { | 15 | "@azure/amqp-common": { |
16 | - "version": "1.0.0-preview.13", | ||
17 | - "resolved": "https://registry.npmjs.org/@azure/amqp-common/-/amqp-common-1.0.0-preview.13.tgz", | ||
18 | - "integrity": "sha512-v19NGXFm8Hzr2bj/DSWYc2anaDcoAeFQXJGuBT8QO7eS13vaELQNGaynOGipEcI313A1778R/FFCk4o+dylIiw==", | 16 | + "version": "1.0.0-preview.15", |
17 | + "resolved": "https://registry.npmjs.org/@azure/amqp-common/-/amqp-common-1.0.0-preview.15.tgz", | ||
18 | + "integrity": "sha512-EoxNsVR7yLioNKRz5JBwQAE9pEdPVGCmmQbPKkZHP72vE5NhaLnOwHOCrk/311cuhJ8aQ60eiLUtF9J2XrEZyA==", | ||
19 | "requires": { | 19 | "requires": { |
20 | "@types/async-lock": "^1.1.0", | 20 | "@types/async-lock": "^1.1.0", |
21 | "@types/is-buffer": "^2.0.0", | 21 | "@types/is-buffer": "^2.0.0", |
@@ -53,9 +53,9 @@ | @@ -53,9 +53,9 @@ | ||
53 | } | 53 | } |
54 | }, | 54 | }, |
55 | "@azure/core-http": { | 55 | "@azure/core-http": { |
56 | - "version": "1.1.1", | ||
57 | - "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.1.1.tgz", | ||
58 | - "integrity": "sha512-yBxH5CtYaCj0f1CKoi3OjQw5C5Go8TbgNA6Q2rX7XsDpN2eeKu0n3kRvzZnKW+brtO1u3YnBBuBLF2KcGoZv6g==", | 56 | + "version": "1.1.2", |
57 | + "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.1.2.tgz", | ||
58 | + "integrity": "sha512-xeZpTs6caBIrRipqZs70jgrA+mAFxII5XrBzbOCELPs18n4QWfchB20F94ITAk3GuFVDaSBsOhVL3GP1J+ncGg==", | ||
59 | "requires": { | 59 | "requires": { |
60 | "@azure/abort-controller": "^1.0.0", | 60 | "@azure/abort-controller": "^1.0.0", |
61 | "@azure/core-auth": "^1.1.2", | 61 | "@azure/core-auth": "^1.1.2", |
@@ -116,11 +116,11 @@ | @@ -116,11 +116,11 @@ | ||
116 | } | 116 | } |
117 | }, | 117 | }, |
118 | "@azure/service-bus": { | 118 | "@azure/service-bus": { |
119 | - "version": "1.1.6", | ||
120 | - "resolved": "https://registry.npmjs.org/@azure/service-bus/-/service-bus-1.1.6.tgz", | ||
121 | - "integrity": "sha512-eCJXcJZGWdlVwLEqMcoIqtUrh/NtyFcDDfq/y8gdCOy3Dzuv8JkPTxjdjcxDthwG9mc5Qter3dGOTwh0U8gwiw==", | 119 | + "version": "1.1.7", |
120 | + "resolved": "https://registry.npmjs.org/@azure/service-bus/-/service-bus-1.1.7.tgz", | ||
121 | + "integrity": "sha512-wns3egBrP6UyT9CIPkM66KsOVJwit7VJT0P/t8PPPfUaO6yx3bEeZyVDq6WMiibnbIkgHtW85xXml4WDb+nPMw==", | ||
122 | "requires": { | 122 | "requires": { |
123 | - "@azure/amqp-common": "1.0.0-preview.13", | 123 | + "@azure/amqp-common": "1.0.0-preview.15", |
124 | "@azure/core-http": "^1.0.0", | 124 | "@azure/core-http": "^1.0.0", |
125 | "@opentelemetry/types": "^0.2.0", | 125 | "@opentelemetry/types": "^0.2.0", |
126 | "@types/is-buffer": "^2.0.0", | 126 | "@types/is-buffer": "^2.0.0", |
@@ -130,7 +130,7 @@ | @@ -130,7 +130,7 @@ | ||
130 | "is-buffer": "^2.0.3", | 130 | "is-buffer": "^2.0.3", |
131 | "long": "^4.0.0", | 131 | "long": "^4.0.0", |
132 | "process": "^0.11.10", | 132 | "process": "^0.11.10", |
133 | - "rhea": "^1.0.18", | 133 | + "rhea": "^1.0.21", |
134 | "rhea-promise": "^0.1.15", | 134 | "rhea-promise": "^0.1.15", |
135 | "tslib": "^1.10.0" | 135 | "tslib": "^1.10.0" |
136 | }, | 136 | }, |
@@ -151,18 +151,18 @@ | @@ -151,18 +151,18 @@ | ||
151 | } | 151 | } |
152 | }, | 152 | }, |
153 | "@babel/parser": { | 153 | "@babel/parser": { |
154 | - "version": "7.8.4", | ||
155 | - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", | ||
156 | - "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", | 154 | + "version": "7.9.6", |
155 | + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz", | ||
156 | + "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==", | ||
157 | "dev": true | 157 | "dev": true |
158 | }, | 158 | }, |
159 | "@babel/runtime": { | 159 | "@babel/runtime": { |
160 | - "version": "7.8.4", | ||
161 | - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", | ||
162 | - "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", | 160 | + "version": "7.9.6", |
161 | + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.6.tgz", | ||
162 | + "integrity": "sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==", | ||
163 | "dev": true, | 163 | "dev": true, |
164 | "requires": { | 164 | "requires": { |
165 | - "regenerator-runtime": "^0.13.2" | 165 | + "regenerator-runtime": "^0.13.4" |
166 | } | 166 | } |
167 | }, | 167 | }, |
168 | "@google-cloud/paginator": { | 168 | "@google-cloud/paginator": { |
@@ -190,9 +190,9 @@ | @@ -190,9 +190,9 @@ | ||
190 | "integrity": "sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ==" | 190 | "integrity": "sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ==" |
191 | }, | 191 | }, |
192 | "@google-cloud/pubsub": { | 192 | "@google-cloud/pubsub": { |
193 | - "version": "1.7.2", | ||
194 | - "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-1.7.2.tgz", | ||
195 | - "integrity": "sha512-/TziioDSV4FS4wKF1sIaQ+1gvE+um83oHz1nRsZ3L87uWSoOciBjJAcocgPjqrpnW441+Nuw4w0QdSUV1Lka/g==", | 193 | + "version": "1.7.3", |
194 | + "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-1.7.3.tgz", | ||
195 | + "integrity": "sha512-v+KdeaOS17WtHnsDf2bPGxKDT9HIRPYo3n+WsAEmvAzDHnh8q65mFcuYoQxuy2iRhmN/1ql2a0UU2tAAL7XZ8Q==", | ||
196 | "requires": { | 196 | "requires": { |
197 | "@google-cloud/paginator": "^2.0.0", | 197 | "@google-cloud/paginator": "^2.0.0", |
198 | "@google-cloud/precise-date": "^1.0.0", | 198 | "@google-cloud/precise-date": "^1.0.0", |
@@ -372,9 +372,9 @@ | @@ -372,9 +372,9 @@ | ||
372 | "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" | 372 | "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" |
373 | }, | 373 | }, |
374 | "@types/node": { | 374 | "@types/node": { |
375 | - "version": "13.13.4", | ||
376 | - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.4.tgz", | ||
377 | - "integrity": "sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA==" | 375 | + "version": "14.0.1", |
376 | + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.1.tgz", | ||
377 | + "integrity": "sha512-FAYBGwC+W6F9+huFIDtn43cpy7+SzG+atzRiTfdp3inUKL2hXnd4rG8hylJLIh4+hqrQy1P17kvJByE/z825hA==" | ||
378 | }, | 378 | }, |
379 | "@types/node-fetch": { | 379 | "@types/node-fetch": { |
380 | "version": "2.5.7", | 380 | "version": "2.5.7", |
@@ -449,9 +449,9 @@ | @@ -449,9 +449,9 @@ | ||
449 | } | 449 | } |
450 | }, | 450 | }, |
451 | "amqplib": { | 451 | "amqplib": { |
452 | - "version": "0.5.5", | ||
453 | - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.5.tgz", | ||
454 | - "integrity": "sha512-sWx1hbfHbyKMw6bXOK2k6+lHL8TESWxjAx5hG8fBtT7wcxoXNIsFxZMnFyBjxt3yL14vn7WqBDe5U6BGOadtLg==", | 452 | + "version": "0.5.6", |
453 | + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.6.tgz", | ||
454 | + "integrity": "sha512-J4TR0WAMPBHN+tgTuhNsSObfM9eTVTZm/FNw0LyaGfbiLsBxqSameDNYpChUFXW4bnTKHDXy0ab+nuLhumnRrQ==", | ||
455 | "requires": { | 455 | "requires": { |
456 | "bitsyntax": "~0.1.0", | 456 | "bitsyntax": "~0.1.0", |
457 | "bluebird": "^3.5.2", | 457 | "bluebird": "^3.5.2", |
@@ -610,9 +610,9 @@ | @@ -610,9 +610,9 @@ | ||
610 | "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" | 610 | "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" |
611 | }, | 611 | }, |
612 | "async-lock": { | 612 | "async-lock": { |
613 | - "version": "1.2.2", | ||
614 | - "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.2.2.tgz", | ||
615 | - "integrity": "sha512-uczz62z2fMWOFbyo6rG4NlV2SdxugJT6sZA2QcfB1XaSjEiOh8CuOb/TttyMnYQCda6nkWecJe465tGQDPJiKw==" | 613 | + "version": "1.2.4", |
614 | + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.2.4.tgz", | ||
615 | + "integrity": "sha512-UBQJC2pbeyGutIfYmErGc9RaJYnpZ1FHaxuKwb0ahvGiiCkPUf3p67Io+YLPmmv3RHY+mF6JEtNW8FlHsraAaA==" | ||
616 | }, | 616 | }, |
617 | "asynckit": { | 617 | "asynckit": { |
618 | "version": "0.4.0", | 618 | "version": "0.4.0", |
@@ -626,9 +626,9 @@ | @@ -626,9 +626,9 @@ | ||
626 | "dev": true | 626 | "dev": true |
627 | }, | 627 | }, |
628 | "aws-sdk": { | 628 | "aws-sdk": { |
629 | - "version": "2.669.0", | ||
630 | - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.669.0.tgz", | ||
631 | - "integrity": "sha512-kuVcSRpDzvkgmeSmMX6Q32eTOb8UeihhUdavMrvUOP6fzSU19cNWS9HAIkYOi/jrEDK85cCZxXjxqE3JGZIGcw==", | 629 | + "version": "2.677.0", |
630 | + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.677.0.tgz", | ||
631 | + "integrity": "sha512-vzQWRh1sgM0HRNmbLXgxnFPySLQrtSNgs9dNQsksGiYrJtf1wYjJSh4UHhekeyMuorQqef3m4AY0vFWsWyZSMg==", | ||
632 | "requires": { | 632 | "requires": { |
633 | "buffer": "4.9.1", | 633 | "buffer": "4.9.1", |
634 | "events": "1.1.1", | 634 | "events": "1.1.1", |
@@ -1136,11 +1136,11 @@ | @@ -1136,11 +1136,11 @@ | ||
1136 | "dev": true | 1136 | "dev": true |
1137 | }, | 1137 | }, |
1138 | "config": { | 1138 | "config": { |
1139 | - "version": "3.2.5", | ||
1140 | - "resolved": "https://registry.npmjs.org/config/-/config-3.2.5.tgz", | ||
1141 | - "integrity": "sha512-8itpjyR01lAJanhAlPncBngYRZez/LoRLW8wnGi+6SEcsUyA1wvHvbpIrAJYDJT+W9BScnj4mYoUgbtp9I+0+Q==", | 1139 | + "version": "3.3.1", |
1140 | + "resolved": "https://registry.npmjs.org/config/-/config-3.3.1.tgz", | ||
1141 | + "integrity": "sha512-+2/KaaaAzdwUBE3jgZON11L1ggLLhpf2FsGrfqYFHZW22ySGv/HqYIXrBwKKvn+XZh1UBUjHwAcrfsSkSygT+Q==", | ||
1142 | "requires": { | 1142 | "requires": { |
1143 | - "json5": "^1.0.1" | 1143 | + "json5": "^2.1.1" |
1144 | } | 1144 | } |
1145 | }, | 1145 | }, |
1146 | "configstore": { | 1146 | "configstore": { |
@@ -1680,16 +1680,17 @@ | @@ -1680,16 +1680,17 @@ | ||
1680 | "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" | 1680 | "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" |
1681 | }, | 1681 | }, |
1682 | "fast-glob": { | 1682 | "fast-glob": { |
1683 | - "version": "3.1.1", | ||
1684 | - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", | ||
1685 | - "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", | 1683 | + "version": "3.2.2", |
1684 | + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", | ||
1685 | + "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", | ||
1686 | "dev": true, | 1686 | "dev": true, |
1687 | "requires": { | 1687 | "requires": { |
1688 | "@nodelib/fs.stat": "^2.0.2", | 1688 | "@nodelib/fs.stat": "^2.0.2", |
1689 | "@nodelib/fs.walk": "^1.2.3", | 1689 | "@nodelib/fs.walk": "^1.2.3", |
1690 | "glob-parent": "^5.1.0", | 1690 | "glob-parent": "^5.1.0", |
1691 | "merge2": "^1.3.0", | 1691 | "merge2": "^1.3.0", |
1692 | - "micromatch": "^4.0.2" | 1692 | + "micromatch": "^4.0.2", |
1693 | + "picomatch": "^2.2.1" | ||
1693 | }, | 1694 | }, |
1694 | "dependencies": { | 1695 | "dependencies": { |
1695 | "braces": { | 1696 | "braces": { |
@@ -1711,9 +1712,9 @@ | @@ -1711,9 +1712,9 @@ | ||
1711 | } | 1712 | } |
1712 | }, | 1713 | }, |
1713 | "glob-parent": { | 1714 | "glob-parent": { |
1714 | - "version": "5.1.0", | ||
1715 | - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", | ||
1716 | - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", | 1715 | + "version": "5.1.1", |
1716 | + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", | ||
1717 | + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", | ||
1717 | "dev": true, | 1718 | "dev": true, |
1718 | "requires": { | 1719 | "requires": { |
1719 | "is-glob": "^4.0.1" | 1720 | "is-glob": "^4.0.1" |
@@ -1768,12 +1769,12 @@ | @@ -1768,12 +1769,12 @@ | ||
1768 | "integrity": "sha512-5rQdinSsycpzvAoHga2EDn+LRX1d5xLFsuNG0Kg61JrAT/tASXcLL0nf/33v+sAxlQcfYmWbTURa1mmAf55jGw==" | 1769 | "integrity": "sha512-5rQdinSsycpzvAoHga2EDn+LRX1d5xLFsuNG0Kg61JrAT/tASXcLL0nf/33v+sAxlQcfYmWbTURa1mmAf55jGw==" |
1769 | }, | 1770 | }, |
1770 | "fastq": { | 1771 | "fastq": { |
1771 | - "version": "1.6.0", | ||
1772 | - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", | ||
1773 | - "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", | 1772 | + "version": "1.8.0", |
1773 | + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", | ||
1774 | + "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", | ||
1774 | "dev": true, | 1775 | "dev": true, |
1775 | "requires": { | 1776 | "requires": { |
1776 | - "reusify": "^1.0.0" | 1777 | + "reusify": "^1.0.4" |
1777 | } | 1778 | } |
1778 | }, | 1779 | }, |
1779 | "fecha": { | 1780 | "fecha": { |
@@ -3038,11 +3039,18 @@ | @@ -3038,11 +3039,18 @@ | ||
3038 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" | 3039 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" |
3039 | }, | 3040 | }, |
3040 | "json5": { | 3041 | "json5": { |
3041 | - "version": "1.0.1", | ||
3042 | - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", | ||
3043 | - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", | 3042 | + "version": "2.1.3", |
3043 | + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", | ||
3044 | + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", | ||
3044 | "requires": { | 3045 | "requires": { |
3045 | - "minimist": "^1.2.0" | 3046 | + "minimist": "^1.2.5" |
3047 | + }, | ||
3048 | + "dependencies": { | ||
3049 | + "minimist": { | ||
3050 | + "version": "1.2.5", | ||
3051 | + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", | ||
3052 | + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" | ||
3053 | + } | ||
3046 | } | 3054 | } |
3047 | }, | 3055 | }, |
3048 | "jsonfile": { | 3056 | "jsonfile": { |
@@ -3269,7 +3277,8 @@ | @@ -3269,7 +3277,8 @@ | ||
3269 | "minimist": { | 3277 | "minimist": { |
3270 | "version": "1.2.0", | 3278 | "version": "1.2.0", |
3271 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", | 3279 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", |
3272 | - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" | 3280 | + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", |
3281 | + "dev": true | ||
3273 | }, | 3282 | }, |
3274 | "mixin-deep": { | 3283 | "mixin-deep": { |
3275 | "version": "1.3.2", | 3284 | "version": "1.3.2", |
@@ -3293,18 +3302,18 @@ | @@ -3293,18 +3302,18 @@ | ||
3293 | } | 3302 | } |
3294 | }, | 3303 | }, |
3295 | "mkdirp": { | 3304 | "mkdirp": { |
3296 | - "version": "0.5.1", | ||
3297 | - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", | ||
3298 | - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", | 3305 | + "version": "0.5.5", |
3306 | + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", | ||
3307 | + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", | ||
3299 | "dev": true, | 3308 | "dev": true, |
3300 | "requires": { | 3309 | "requires": { |
3301 | - "minimist": "0.0.8" | 3310 | + "minimist": "^1.2.5" |
3302 | }, | 3311 | }, |
3303 | "dependencies": { | 3312 | "dependencies": { |
3304 | "minimist": { | 3313 | "minimist": { |
3305 | - "version": "0.0.8", | ||
3306 | - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", | ||
3307 | - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", | 3314 | + "version": "1.2.5", |
3315 | + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", | ||
3316 | + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", | ||
3308 | "dev": true | 3317 | "dev": true |
3309 | } | 3318 | } |
3310 | } | 3319 | } |
@@ -3629,9 +3638,9 @@ | @@ -3629,9 +3638,9 @@ | ||
3629 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" | 3638 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" |
3630 | }, | 3639 | }, |
3631 | "picomatch": { | 3640 | "picomatch": { |
3632 | - "version": "2.2.1", | ||
3633 | - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", | ||
3634 | - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", | 3641 | + "version": "2.2.2", |
3642 | + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", | ||
3643 | + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", | ||
3635 | "dev": true | 3644 | "dev": true |
3636 | }, | 3645 | }, |
3637 | "pify": { | 3646 | "pify": { |
@@ -3641,23 +3650,23 @@ | @@ -3641,23 +3650,23 @@ | ||
3641 | "dev": true | 3650 | "dev": true |
3642 | }, | 3651 | }, |
3643 | "pkg": { | 3652 | "pkg": { |
3644 | - "version": "4.4.3", | ||
3645 | - "resolved": "https://registry.npmjs.org/pkg/-/pkg-4.4.3.tgz", | ||
3646 | - "integrity": "sha512-1M0KNVLxNUzr0CGMhccPxx02G05GL3h9czbQGLswRB2gOvHeKAbld+1S5SGDNLOoFt+IYNNxqHtBhZA6Rer7QQ==", | 3653 | + "version": "4.4.8", |
3654 | + "resolved": "https://registry.npmjs.org/pkg/-/pkg-4.4.8.tgz", | ||
3655 | + "integrity": "sha512-Fqqv0iaX48U3CFZxd6Dq6JKe7BrAWbgRAqMJkz/m8W3H5cqJ6suvsUWe5AJPRlN/AhbBYXBJ0XG9QlYPTXcVFA==", | ||
3647 | "dev": true, | 3656 | "dev": true, |
3648 | "requires": { | 3657 | "requires": { |
3649 | - "@babel/parser": "^7.7.5", | ||
3650 | - "@babel/runtime": "^7.7.5", | 3658 | + "@babel/parser": "^7.9.4", |
3659 | + "@babel/runtime": "^7.9.2", | ||
3651 | "chalk": "^3.0.0", | 3660 | "chalk": "^3.0.0", |
3652 | - "escodegen": "^1.13.0", | 3661 | + "escodegen": "^1.14.1", |
3653 | "fs-extra": "^8.1.0", | 3662 | "fs-extra": "^8.1.0", |
3654 | "globby": "^11.0.0", | 3663 | "globby": "^11.0.0", |
3655 | "into-stream": "^5.1.1", | 3664 | "into-stream": "^5.1.1", |
3656 | - "minimist": "^1.2.0", | 3665 | + "minimist": "^1.2.5", |
3657 | "multistream": "^2.1.1", | 3666 | "multistream": "^2.1.1", |
3658 | - "pkg-fetch": "^2.6.4", | 3667 | + "pkg-fetch": "^2.6.7", |
3659 | "progress": "^2.0.3", | 3668 | "progress": "^2.0.3", |
3660 | - "resolve": "^1.15.0", | 3669 | + "resolve": "^1.15.1", |
3661 | "stream-meter": "^1.0.4" | 3670 | "stream-meter": "^1.0.4" |
3662 | }, | 3671 | }, |
3663 | "dependencies": { | 3672 | "dependencies": { |
@@ -3713,6 +3722,12 @@ | @@ -3713,6 +3722,12 @@ | ||
3713 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", | 3722 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", |
3714 | "dev": true | 3723 | "dev": true |
3715 | }, | 3724 | }, |
3725 | + "minimist": { | ||
3726 | + "version": "1.2.5", | ||
3727 | + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", | ||
3728 | + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", | ||
3729 | + "dev": true | ||
3730 | + }, | ||
3716 | "supports-color": { | 3731 | "supports-color": { |
3717 | "version": "7.1.0", | 3732 | "version": "7.1.0", |
3718 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", | 3733 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", |
@@ -3725,17 +3740,17 @@ | @@ -3725,17 +3740,17 @@ | ||
3725 | } | 3740 | } |
3726 | }, | 3741 | }, |
3727 | "pkg-fetch": { | 3742 | "pkg-fetch": { |
3728 | - "version": "2.6.4", | ||
3729 | - "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-2.6.4.tgz", | ||
3730 | - "integrity": "sha512-4j4jiuo6RRIuD9e9xUE6OQYnIkQCArZjkHXNYsSJjxhJeiHE16MA+rENMblvGLbeWsTY3BPfcYVCGFXzpfJetA==", | 3743 | + "version": "2.6.8", |
3744 | + "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-2.6.8.tgz", | ||
3745 | + "integrity": "sha512-CFG7jOeVD38lltLGA7xCJxYsD//GKLjl1P9tc/n9By2a4WEHQjfkBMrYdMS8WOHVP+r9L20fsZNbaKcubDAiQg==", | ||
3731 | "dev": true, | 3746 | "dev": true, |
3732 | "requires": { | 3747 | "requires": { |
3733 | - "@babel/runtime": "^7.7.5", | 3748 | + "@babel/runtime": "^7.9.2", |
3734 | "byline": "^5.0.0", | 3749 | "byline": "^5.0.0", |
3735 | "chalk": "^3.0.0", | 3750 | "chalk": "^3.0.0", |
3736 | "expand-template": "^2.0.3", | 3751 | "expand-template": "^2.0.3", |
3737 | "fs-extra": "^8.1.0", | 3752 | "fs-extra": "^8.1.0", |
3738 | - "minimist": "^1.2.0", | 3753 | + "minimist": "^1.2.5", |
3739 | "progress": "^2.0.3", | 3754 | "progress": "^2.0.3", |
3740 | "request": "^2.88.0", | 3755 | "request": "^2.88.0", |
3741 | "request-progress": "^3.0.0", | 3756 | "request-progress": "^3.0.0", |
@@ -3795,6 +3810,12 @@ | @@ -3795,6 +3810,12 @@ | ||
3795 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", | 3810 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", |
3796 | "dev": true | 3811 | "dev": true |
3797 | }, | 3812 | }, |
3813 | + "minimist": { | ||
3814 | + "version": "1.2.5", | ||
3815 | + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", | ||
3816 | + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", | ||
3817 | + "dev": true | ||
3818 | + }, | ||
3798 | "supports-color": { | 3819 | "supports-color": { |
3799 | "version": "7.1.0", | 3820 | "version": "7.1.0", |
3800 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", | 3821 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", |
@@ -3858,6 +3879,13 @@ | @@ -3858,6 +3879,13 @@ | ||
3858 | "@types/long": "^4.0.1", | 3879 | "@types/long": "^4.0.1", |
3859 | "@types/node": "^13.7.0", | 3880 | "@types/node": "^13.7.0", |
3860 | "long": "^4.0.0" | 3881 | "long": "^4.0.0" |
3882 | + }, | ||
3883 | + "dependencies": { | ||
3884 | + "@types/node": { | ||
3885 | + "version": "13.13.6", | ||
3886 | + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.6.tgz", | ||
3887 | + "integrity": "sha512-zqRj8ugfROCjXCNbmPBe2mmQ0fJWP9lQaN519hwunOgpHgVykme4G6FW95++dyNFDvJUk4rtExkVkL0eciu5NA==" | ||
3888 | + } | ||
3861 | } | 3889 | } |
3862 | }, | 3890 | }, |
3863 | "pseudomap": { | 3891 | "pseudomap": { |
@@ -3963,9 +3991,9 @@ | @@ -3963,9 +3991,9 @@ | ||
3963 | } | 3991 | } |
3964 | }, | 3992 | }, |
3965 | "regenerator-runtime": { | 3993 | "regenerator-runtime": { |
3966 | - "version": "0.13.3", | ||
3967 | - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", | ||
3968 | - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", | 3994 | + "version": "0.13.5", |
3995 | + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", | ||
3996 | + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", | ||
3969 | "dev": true | 3997 | "dev": true |
3970 | }, | 3998 | }, |
3971 | "regex-not": { | 3999 | "regex-not": { |
@@ -4057,9 +4085,9 @@ | @@ -4057,9 +4085,9 @@ | ||
4057 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" | 4085 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" |
4058 | }, | 4086 | }, |
4059 | "resolve": { | 4087 | "resolve": { |
4060 | - "version": "1.15.1", | ||
4061 | - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", | ||
4062 | - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", | 4088 | + "version": "1.17.0", |
4089 | + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", | ||
4090 | + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", | ||
4063 | "dev": true, | 4091 | "dev": true, |
4064 | "requires": { | 4092 | "requires": { |
4065 | "path-parse": "^1.0.6" | 4093 | "path-parse": "^1.0.6" |
@@ -4103,9 +4131,9 @@ | @@ -4103,9 +4131,9 @@ | ||
4103 | "dev": true | 4131 | "dev": true |
4104 | }, | 4132 | }, |
4105 | "rhea": { | 4133 | "rhea": { |
4106 | - "version": "1.0.20", | ||
4107 | - "resolved": "https://registry.npmjs.org/rhea/-/rhea-1.0.20.tgz", | ||
4108 | - "integrity": "sha512-qj4LSEykJ0SEYESQLg9Vee6VXH5xHN1pYj7ozPeUk+l+S1OaGKx1FugAu+g+3pPwK46WXV1PJD9XiRx8+tS4cw==", | 4134 | + "version": "1.0.21", |
4135 | + "resolved": "https://registry.npmjs.org/rhea/-/rhea-1.0.21.tgz", | ||
4136 | + "integrity": "sha512-9ddxyJR0nlWmynukzZTWN+bSYWu7KLHVMkIH/7PpFG5RHfV5t7zXIfZ6rqJSJe9wBAgnNr2Xz41KM2nPujWiFQ==", | ||
4109 | "requires": { | 4137 | "requires": { |
4110 | "debug": "0.8.0 - 3.5.0" | 4138 | "debug": "0.8.0 - 3.5.0" |
4111 | } | 4139 | } |
@@ -4670,9 +4698,9 @@ | @@ -4670,9 +4698,9 @@ | ||
4670 | "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" | 4698 | "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" |
4671 | }, | 4699 | }, |
4672 | "tslib": { | 4700 | "tslib": { |
4673 | - "version": "1.11.1", | ||
4674 | - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", | ||
4675 | - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" | 4701 | + "version": "1.13.0", |
4702 | + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", | ||
4703 | + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" | ||
4676 | }, | 4704 | }, |
4677 | "tunnel": { | 4705 | "tunnel": { |
4678 | "version": "0.0.6", | 4706 | "version": "0.0.6", |
@@ -12,14 +12,14 @@ | @@ -12,14 +12,14 @@ | ||
12 | "start-prod": "NODE_ENV=production nodemon server.js" | 12 | "start-prod": "NODE_ENV=production nodemon server.js" |
13 | }, | 13 | }, |
14 | "dependencies": { | 14 | "dependencies": { |
15 | - "config": "^3.2.2", | 15 | + "@azure/service-bus": "^1.1.7", |
16 | + "@google-cloud/pubsub": "^1.7.3", | ||
17 | + "amqplib": "^0.5.6", | ||
18 | + "aws-sdk": "^2.677.0", | ||
19 | + "azure-sb": "^0.11.1", | ||
20 | + "config": "^3.3.1", | ||
16 | "js-yaml": "^3.12.0", | 21 | "js-yaml": "^3.12.0", |
17 | "kafkajs": "^1.12.0", | 22 | "kafkajs": "^1.12.0", |
18 | - "@google-cloud/pubsub": "^1.7.1", | ||
19 | - "aws-sdk": "^2.663.0", | ||
20 | - "amqplib": "^0.5.5", | ||
21 | - "@azure/service-bus": "^1.1.6", | ||
22 | - "azure-sb": "^0.11.1", | ||
23 | "long": "^4.0.0", | 23 | "long": "^4.0.0", |
24 | "uuid-parse": "^1.0.0", | 24 | "uuid-parse": "^1.0.0", |
25 | "uuid-random": "^1.3.0", | 25 | "uuid-random": "^1.3.0", |
@@ -40,7 +40,7 @@ | @@ -40,7 +40,7 @@ | ||
40 | "devDependencies": { | 40 | "devDependencies": { |
41 | "fs-extra": "^6.0.1", | 41 | "fs-extra": "^6.0.1", |
42 | "nodemon": "^1.17.5", | 42 | "nodemon": "^1.17.5", |
43 | - "pkg": "^4.4.0" | 43 | + "pkg": "^4.4.8" |
44 | }, | 44 | }, |
45 | "pkg": { | 45 | "pkg": { |
46 | "assets": [ | 46 | "assets": [ |
@@ -100,7 +100,7 @@ function AwsSqsProducer() { | @@ -100,7 +100,7 @@ function AwsSqsProducer() { | ||
100 | const params = { | 100 | const params = { |
101 | MaxNumberOfMessages: 10, | 101 | MaxNumberOfMessages: 10, |
102 | QueueUrl: requestQueueURL, | 102 | QueueUrl: requestQueueURL, |
103 | - WaitTimeSeconds: poolInterval / 1000 | 103 | + WaitTimeSeconds: pollInterval / 1000 |
104 | }; | 104 | }; |
105 | while (!stopped) { | 105 | while (!stopped) { |
106 | let pollStartTs = new Date().getTime(); | 106 | let pollStartTs = new Date().getTime(); |
@@ -68,9 +68,8 @@ function RabbitMqProducer() { | @@ -68,9 +68,8 @@ function RabbitMqProducer() { | ||
68 | (async () => { | 68 | (async () => { |
69 | try { | 69 | try { |
70 | logger.info('Starting ThingsBoard JavaScript Executor Microservice...'); | 70 | logger.info('Starting ThingsBoard JavaScript Executor Microservice...'); |
71 | - const url = `amqp://${host}:${port}${vhost}`; | 71 | + const url = `amqp://${username}:${password}@${host}:${port}${vhost}`; |
72 | 72 | ||
73 | - amqp.credentials.amqplain(username, password); | ||
74 | connection = await new Promise((resolve, reject) => { | 73 | connection = await new Promise((resolve, reject) => { |
75 | amqp.connect(url, function (err, connection) { | 74 | amqp.connect(url, function (err, connection) { |
76 | if (err) { | 75 | if (err) { |
@@ -61,15 +61,14 @@ | @@ -61,15 +61,14 @@ | ||
61 | <akka.version>2.6.3</akka.version> | 61 | <akka.version>2.6.3</akka.version> |
62 | <californium.version>1.0.2</californium.version> | 62 | <californium.version>1.0.2</californium.version> |
63 | <gson.version>2.6.2</gson.version> | 63 | <gson.version>2.6.2</gson.version> |
64 | - <velocity.version>1.7</velocity.version> | ||
65 | - <velocity-tools.version>2.0</velocity-tools.version> | 64 | + <freemarker.version>2.3.30</freemarker.version> |
66 | <mail.version>1.6.2</mail.version> | 65 | <mail.version>1.6.2</mail.version> |
67 | <curator.version>4.2.0</curator.version> | 66 | <curator.version>4.2.0</curator.version> |
68 | <zookeeper.version>3.5.5</zookeeper.version> | 67 | <zookeeper.version>3.5.5</zookeeper.version> |
69 | <protobuf.version>3.11.4</protobuf.version> | 68 | <protobuf.version>3.11.4</protobuf.version> |
70 | <grpc.version>1.22.1</grpc.version> | 69 | <grpc.version>1.22.1</grpc.version> |
71 | <lombok.version>1.16.18</lombok.version> | 70 | <lombok.version>1.16.18</lombok.version> |
72 | - <paho.client.version>1.1.0</paho.client.version> | 71 | + <paho.client.version>1.2.4</paho.client.version> |
73 | <netty.version>4.1.49.Final</netty.version> | 72 | <netty.version>4.1.49.Final</netty.version> |
74 | <os-maven-plugin.version>1.5.0</os-maven-plugin.version> | 73 | <os-maven-plugin.version>1.5.0</os-maven-plugin.version> |
75 | <rabbitmq.version>4.8.0</rabbitmq.version> | 74 | <rabbitmq.version>4.8.0</rabbitmq.version> |
@@ -565,28 +564,9 @@ | @@ -565,28 +564,9 @@ | ||
565 | <version>${jjwt.version}</version> | 564 | <version>${jjwt.version}</version> |
566 | </dependency> | 565 | </dependency> |
567 | <dependency> | 566 | <dependency> |
568 | - <groupId>org.apache.velocity</groupId> | ||
569 | - <artifactId>velocity</artifactId> | ||
570 | - <version>${velocity.version}</version> | ||
571 | - </dependency> | ||
572 | - <dependency> | ||
573 | - <groupId>org.apache.velocity</groupId> | ||
574 | - <artifactId>velocity-tools</artifactId> | ||
575 | - <version>${velocity-tools.version}</version> | ||
576 | - <exclusions> | ||
577 | - <exclusion> | ||
578 | - <groupId>javax.servlet</groupId> | ||
579 | - <artifactId>servlet-api</artifactId> | ||
580 | - </exclusion> | ||
581 | - <exclusion> | ||
582 | - <groupId>dom4j</groupId> | ||
583 | - <artifactId>dom4j</artifactId> | ||
584 | - </exclusion> | ||
585 | - <exclusion> | ||
586 | - <groupId>antlr</groupId> | ||
587 | - <artifactId>antlr</artifactId> | ||
588 | - </exclusion> | ||
589 | - </exclusions> | 567 | + <groupId>org.freemarker</groupId> |
568 | + <artifactId>freemarker</artifactId> | ||
569 | + <version>${freemarker.version}</version> | ||
590 | </dependency> | 570 | </dependency> |
591 | <dependency> | 571 | <dependency> |
592 | <groupId>org.yaml</groupId> | 572 | <groupId>org.yaml</groupId> |
@@ -975,11 +955,6 @@ | @@ -975,11 +955,6 @@ | ||
975 | <version>${commons-collections.version}</version> | 955 | <version>${commons-collections.version}</version> |
976 | </dependency> | 956 | </dependency> |
977 | <dependency> | 957 | <dependency> |
978 | - <groupId>org.yaml</groupId> | ||
979 | - <artifactId>snakeyaml</artifactId> | ||
980 | - <version>${snakeyaml.version}</version> | ||
981 | - </dependency> | ||
982 | - <dependency> | ||
983 | <groupId>org.apache.struts</groupId> | 958 | <groupId>org.apache.struts</groupId> |
984 | <artifactId>struts-core</artifactId> | 959 | <artifactId>struts-core</artifactId> |
985 | <version>${struts.version}</version> | 960 | <version>${struts.version}</version> |
@@ -147,6 +147,16 @@ public class TbSendEmailNode implements TbNode { | @@ -147,6 +147,16 @@ public class TbSendEmailNode implements TbNode { | ||
147 | if (this.config.isEnableTls() && StringUtils.isNoneEmpty(this.config.getTlsVersion())) { | 147 | if (this.config.isEnableTls() && StringUtils.isNoneEmpty(this.config.getTlsVersion())) { |
148 | javaMailProperties.put(MAIL_PROP + protocol + ".ssl.protocols", this.config.getTlsVersion()); | 148 | javaMailProperties.put(MAIL_PROP + protocol + ".ssl.protocols", this.config.getTlsVersion()); |
149 | } | 149 | } |
150 | + if (this.config.isEnableProxy()) { | ||
151 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.host", config.getProxyHost()); | ||
152 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.port", config.getProxyPort()); | ||
153 | + if (StringUtils.isNoneEmpty(config.getProxyUser())) { | ||
154 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.user", config.getProxyUser()); | ||
155 | + } | ||
156 | + if (StringUtils.isNoneEmpty(config.getProxyPassword())) { | ||
157 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.password", config.getProxyPassword()); | ||
158 | + } | ||
159 | + } | ||
150 | return javaMailProperties; | 160 | return javaMailProperties; |
151 | } | 161 | } |
152 | } | 162 | } |
@@ -30,6 +30,11 @@ public class TbSendEmailNodeConfiguration implements NodeConfiguration { | @@ -30,6 +30,11 @@ public class TbSendEmailNodeConfiguration implements NodeConfiguration { | ||
30 | private int timeout; | 30 | private int timeout; |
31 | private boolean enableTls; | 31 | private boolean enableTls; |
32 | private String tlsVersion; | 32 | private String tlsVersion; |
33 | + private boolean enableProxy; | ||
34 | + private String proxyHost; | ||
35 | + private String proxyPort; | ||
36 | + private String proxyUser; | ||
37 | + private String proxyPassword; | ||
33 | 38 | ||
34 | @Override | 39 | @Override |
35 | public TbSendEmailNodeConfiguration defaultConfiguration() { | 40 | public TbSendEmailNodeConfiguration defaultConfiguration() { |
@@ -41,6 +46,7 @@ public class TbSendEmailNodeConfiguration implements NodeConfiguration { | @@ -41,6 +46,7 @@ public class TbSendEmailNodeConfiguration implements NodeConfiguration { | ||
41 | configuration.setTimeout(10000); | 46 | configuration.setTimeout(10000); |
42 | configuration.setEnableTls(false); | 47 | configuration.setEnableTls(false); |
43 | configuration.setTlsVersion("TLSv1.2"); | 48 | configuration.setTlsVersion("TLSv1.2"); |
49 | + configuration.setEnableProxy(false); | ||
44 | return configuration; | 50 | return configuration; |
45 | } | 51 | } |
46 | } | 52 | } |
@@ -48,7 +48,7 @@ public class TbSynchronizationBeginNode implements TbNode { | @@ -48,7 +48,7 @@ public class TbSynchronizationBeginNode implements TbNode { | ||
48 | 48 | ||
49 | @Override | 49 | @Override |
50 | public void onMsg(TbContext ctx, TbMsg msg) { | 50 | public void onMsg(TbContext ctx, TbMsg msg) { |
51 | - log.warn("Synchronization Start/End nodes are deprecated since TB 2.5. Use queue with submit strategy SEQUENTIAL_WITHIN_ORIGINATOR instead."); | 51 | + log.warn("Synchronization Start/End nodes are deprecated since TB 2.5. Use queue with submit strategy SEQUENTIAL_BY_ORIGINATOR instead."); |
52 | ctx.tellSuccess(msg); | 52 | ctx.tellSuccess(msg); |
53 | } | 53 | } |
54 | 54 |
@@ -49,7 +49,7 @@ public class TbSynchronizationEndNode implements TbNode { | @@ -49,7 +49,7 @@ public class TbSynchronizationEndNode implements TbNode { | ||
49 | 49 | ||
50 | @Override | 50 | @Override |
51 | public void onMsg(TbContext ctx, TbMsg msg) { | 51 | public void onMsg(TbContext ctx, TbMsg msg) { |
52 | - log.warn("Synchronization Start/End nodes are deprecated since TB 2.5. Use queue with submit strategy SEQUENTIAL_WITHIN_ORIGINATOR instead."); | 52 | + log.warn("Synchronization Start/End nodes are deprecated since TB 2.5. Use queue with submit strategy SEQUENTIAL_BY_ORIGINATOR instead."); |
53 | ctx.tellSuccess(msg); | 53 | ctx.tellSuccess(msg); |
54 | } | 54 | } |
55 | 55 |
@@ -155,19 +155,19 @@ queue: | @@ -155,19 +155,19 @@ queue: | ||
155 | pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" | 155 | pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" |
156 | stats: | 156 | stats: |
157 | enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" | 157 | enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" |
158 | - print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:10000}" | 158 | + print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:60000}" |
159 | queues: | 159 | queues: |
160 | - - name: "Main" | 160 | + - name: "${TB_QUEUE_RE_MAIN_QUEUE_NAME:Main}" |
161 | topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" | 161 | topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" |
162 | poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" | 162 | poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" |
163 | partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" | 163 | partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" |
164 | pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:60000}" | 164 | pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:60000}" |
165 | submit-strategy: | 165 | submit-strategy: |
166 | - type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_WITHIN_ORIGINATOR, SEQUENTIAL_WITHIN_TENANT, SEQUENTIAL | 166 | + type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
167 | # For BATCH only | 167 | # For BATCH only |
168 | batch-size: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_BATCH_SIZE:1000}" # Maximum number of messages in batch | 168 | batch-size: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_BATCH_SIZE:1000}" # Maximum number of messages in batch |
169 | processing-strategy: | 169 | processing-strategy: |
170 | - type: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | 170 | + type: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_TYPE:SKIP_ALL_FAILURES}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT |
171 | # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | 171 | # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT |
172 | retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | 172 | retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited |
173 | failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 173 | failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
@@ -175,10 +175,10 @@ queue: | @@ -175,10 +175,10 @@ queue: | ||
175 | - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" | 175 | - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" |
176 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" | 176 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" |
177 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" | 177 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" |
178 | - partitions: "${TB_QUEUE_RE_HP_PARTITIONS:3}" | 178 | + partitions: "${TB_QUEUE_RE_HP_PARTITIONS:10}" |
179 | pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:60000}" | 179 | pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:60000}" |
180 | submit-strategy: | 180 | submit-strategy: |
181 | - type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_WITHIN_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_WITHIN_ORIGINATOR, SEQUENTIAL_WITHIN_TENANT, SEQUENTIAL | 181 | + type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
182 | # For BATCH only | 182 | # For BATCH only |
183 | batch-size: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch | 183 | batch-size: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch |
184 | processing-strategy: | 184 | processing-strategy: |
@@ -187,6 +187,21 @@ queue: | @@ -187,6 +187,21 @@ queue: | ||
187 | retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited | 187 | retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited |
188 | failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 188 | failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
189 | pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | 189 | pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; |
190 | + - name: "${TB_QUEUE_RE_SQ_QUEUE_NAME:SequentialByOriginator}" | ||
191 | + topic: "${TB_QUEUE_RE_SQ_TOPIC:tb_rule_engine.sq}" | ||
192 | + poll-interval: "${TB_QUEUE_RE_SQ_POLL_INTERVAL_MS:25}" | ||
193 | + partitions: "${TB_QUEUE_RE_SQ_PARTITIONS:10}" | ||
194 | + pack-processing-timeout: "${TB_QUEUE_RE_SQ_PACK_PROCESSING_TIMEOUT_MS:60000}" | ||
195 | + submit-strategy: | ||
196 | + type: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_BY_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | ||
197 | + # For BATCH only | ||
198 | + batch-size: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch | ||
199 | + processing-strategy: | ||
200 | + type: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
201 | + # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
202 | + retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | ||
203 | + failure-percentage: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | ||
204 | + pause-between-retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | ||
190 | transport: | 205 | transport: |
191 | # For high priority notifications that require minimum latency and processing time | 206 | # For high priority notifications that require minimum latency and processing time |
192 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" | 207 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" |
@@ -156,19 +156,19 @@ queue: | @@ -156,19 +156,19 @@ queue: | ||
156 | pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" | 156 | pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" |
157 | stats: | 157 | stats: |
158 | enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" | 158 | enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" |
159 | - print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:10000}" | 159 | + print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:60000}" |
160 | queues: | 160 | queues: |
161 | - - name: "Main" | 161 | + - name: "${TB_QUEUE_RE_MAIN_QUEUE_NAME:Main}" |
162 | topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" | 162 | topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" |
163 | poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" | 163 | poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" |
164 | partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" | 164 | partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" |
165 | pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:60000}" | 165 | pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:60000}" |
166 | submit-strategy: | 166 | submit-strategy: |
167 | - type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_WITHIN_ORIGINATOR, SEQUENTIAL_WITHIN_TENANT, SEQUENTIAL | 167 | + type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
168 | # For BATCH only | 168 | # For BATCH only |
169 | batch-size: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_BATCH_SIZE:1000}" # Maximum number of messages in batch | 169 | batch-size: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_BATCH_SIZE:1000}" # Maximum number of messages in batch |
170 | processing-strategy: | 170 | processing-strategy: |
171 | - type: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | 171 | + type: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_TYPE:SKIP_ALL_FAILURES}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT |
172 | # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | 172 | # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT |
173 | retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | 173 | retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited |
174 | failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 174 | failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
@@ -176,10 +176,10 @@ queue: | @@ -176,10 +176,10 @@ queue: | ||
176 | - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" | 176 | - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" |
177 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" | 177 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" |
178 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" | 178 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" |
179 | - partitions: "${TB_QUEUE_RE_HP_PARTITIONS:3}" | 179 | + partitions: "${TB_QUEUE_RE_HP_PARTITIONS:10}" |
180 | pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:60000}" | 180 | pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:60000}" |
181 | submit-strategy: | 181 | submit-strategy: |
182 | - type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_WITHIN_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_WITHIN_ORIGINATOR, SEQUENTIAL_WITHIN_TENANT, SEQUENTIAL | 182 | + type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
183 | # For BATCH only | 183 | # For BATCH only |
184 | batch-size: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch | 184 | batch-size: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch |
185 | processing-strategy: | 185 | processing-strategy: |
@@ -188,6 +188,21 @@ queue: | @@ -188,6 +188,21 @@ queue: | ||
188 | retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited | 188 | retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited |
189 | failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 189 | failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
190 | pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | 190 | pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; |
191 | + - name: "${TB_QUEUE_RE_SQ_QUEUE_NAME:SequentialByOriginator}" | ||
192 | + topic: "${TB_QUEUE_RE_SQ_TOPIC:tb_rule_engine.sq}" | ||
193 | + poll-interval: "${TB_QUEUE_RE_SQ_POLL_INTERVAL_MS:25}" | ||
194 | + partitions: "${TB_QUEUE_RE_SQ_PARTITIONS:10}" | ||
195 | + pack-processing-timeout: "${TB_QUEUE_RE_SQ_PACK_PROCESSING_TIMEOUT_MS:60000}" | ||
196 | + submit-strategy: | ||
197 | + type: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_BY_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | ||
198 | + # For BATCH only | ||
199 | + batch-size: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch | ||
200 | + processing-strategy: | ||
201 | + type: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
202 | + # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
203 | + retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | ||
204 | + failure-percentage: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | ||
205 | + pause-between-retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | ||
191 | transport: | 206 | transport: |
192 | # For high priority notifications that require minimum latency and processing time | 207 | # For high priority notifications that require minimum latency and processing time |
193 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" | 208 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" |
@@ -176,19 +176,19 @@ queue: | @@ -176,19 +176,19 @@ queue: | ||
176 | pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" | 176 | pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" |
177 | stats: | 177 | stats: |
178 | enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" | 178 | enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" |
179 | - print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:10000}" | 179 | + print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:60000}" |
180 | queues: | 180 | queues: |
181 | - - name: "Main" | 181 | + - name: "${TB_QUEUE_RE_MAIN_QUEUE_NAME:Main}" |
182 | topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" | 182 | topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" |
183 | poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" | 183 | poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" |
184 | partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" | 184 | partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" |
185 | pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:60000}" | 185 | pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:60000}" |
186 | submit-strategy: | 186 | submit-strategy: |
187 | - type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_WITHIN_ORIGINATOR, SEQUENTIAL_WITHIN_TENANT, SEQUENTIAL | 187 | + type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
188 | # For BATCH only | 188 | # For BATCH only |
189 | batch-size: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_BATCH_SIZE:1000}" # Maximum number of messages in batch | 189 | batch-size: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_BATCH_SIZE:1000}" # Maximum number of messages in batch |
190 | processing-strategy: | 190 | processing-strategy: |
191 | - type: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | 191 | + type: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_TYPE:SKIP_ALL_FAILURES}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT |
192 | # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | 192 | # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT |
193 | retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | 193 | retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited |
194 | failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 194 | failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
@@ -196,10 +196,10 @@ queue: | @@ -196,10 +196,10 @@ queue: | ||
196 | - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" | 196 | - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" |
197 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" | 197 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" |
198 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" | 198 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" |
199 | - partitions: "${TB_QUEUE_RE_HP_PARTITIONS:3}" | 199 | + partitions: "${TB_QUEUE_RE_HP_PARTITIONS:10}" |
200 | pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:60000}" | 200 | pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:60000}" |
201 | submit-strategy: | 201 | submit-strategy: |
202 | - type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_WITHIN_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_WITHIN_ORIGINATOR, SEQUENTIAL_WITHIN_TENANT, SEQUENTIAL | 202 | + type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
203 | # For BATCH only | 203 | # For BATCH only |
204 | batch-size: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch | 204 | batch-size: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch |
205 | processing-strategy: | 205 | processing-strategy: |
@@ -208,6 +208,21 @@ queue: | @@ -208,6 +208,21 @@ queue: | ||
208 | retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited | 208 | retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited |
209 | failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 209 | failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
210 | pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | 210 | pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; |
211 | + - name: "${TB_QUEUE_RE_SQ_QUEUE_NAME:SequentialByOriginator}" | ||
212 | + topic: "${TB_QUEUE_RE_SQ_TOPIC:tb_rule_engine.sq}" | ||
213 | + poll-interval: "${TB_QUEUE_RE_SQ_POLL_INTERVAL_MS:25}" | ||
214 | + partitions: "${TB_QUEUE_RE_SQ_PARTITIONS:10}" | ||
215 | + pack-processing-timeout: "${TB_QUEUE_RE_SQ_PACK_PROCESSING_TIMEOUT_MS:60000}" | ||
216 | + submit-strategy: | ||
217 | + type: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_BY_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | ||
218 | + # For BATCH only | ||
219 | + batch-size: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_BATCH_SIZE:100}" # Maximum number of messages in batch | ||
220 | + processing-strategy: | ||
221 | + type: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
222 | + # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT | ||
223 | + retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | ||
224 | + failure-percentage: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | ||
225 | + pause-between-retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | ||
211 | transport: | 226 | transport: |
212 | # For high priority notifications that require minimum latency and processing time | 227 | # For high priority notifications that require minimum latency and processing time |
213 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" | 228 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" |
@@ -7969,14 +7969,6 @@ | @@ -7969,14 +7969,6 @@ | ||
7969 | "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.6.0.tgz", | 7969 | "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.6.0.tgz", |
7970 | "integrity": "sha512-CPkhyqWUKZKFJ6K8umN5/D2wrJ2+/8UIpXppY7QDnUZW5bZL5+SEI2J7GBpwh4LIupOKqbNSQXgqmrEJopHVNQ==" | 7970 | "integrity": "sha512-CPkhyqWUKZKFJ6K8umN5/D2wrJ2+/8UIpXppY7QDnUZW5bZL5+SEI2J7GBpwh4LIupOKqbNSQXgqmrEJopHVNQ==" |
7971 | }, | 7971 | }, |
7972 | - "leaflet-geometryutil": { | ||
7973 | - "version": "0.9.3", | ||
7974 | - "resolved": "https://registry.npmjs.org/leaflet-geometryutil/-/leaflet-geometryutil-0.9.3.tgz", | ||
7975 | - "integrity": "sha512-Wi6YvfNx/Xu9q35AEfXpsUXmIFLen/MO+C2qimxHRnjyeyOxBhdcZa6kSiReaOX0cGK7yQInqrzz0dkIqZ8Dpg==", | ||
7976 | - "requires": { | ||
7977 | - "leaflet": ">=0.7.0" | ||
7978 | - } | ||
7979 | - }, | ||
7980 | "leaflet-polylinedecorator": { | 7972 | "leaflet-polylinedecorator": { |
7981 | "version": "1.6.0", | 7973 | "version": "1.6.0", |
7982 | "resolved": "https://registry.npmjs.org/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz", | 7974 | "resolved": "https://registry.npmjs.org/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz", |
@@ -58,7 +58,6 @@ | @@ -58,7 +58,6 @@ | ||
58 | "jstree-bootstrap-theme": "^1.0.1", | 58 | "jstree-bootstrap-theme": "^1.0.1", |
59 | "jszip": "^3.4.0", | 59 | "jszip": "^3.4.0", |
60 | "leaflet": "^1.6.0", | 60 | "leaflet": "^1.6.0", |
61 | - "leaflet-geometryutil": "^0.9.3", | ||
62 | "leaflet-polylinedecorator": "^1.6.0", | 61 | "leaflet-polylinedecorator": "^1.6.0", |
63 | "leaflet-providers": "^1.9.1", | 62 | "leaflet-providers": "^1.9.1", |
64 | "leaflet.gridlayer.googlemutant": "0.8.0", | 63 | "leaflet.gridlayer.googlemutant": "0.8.0", |
@@ -496,7 +496,7 @@ export function padValue(val: any, dec: number): string { | @@ -496,7 +496,7 @@ export function padValue(val: any, dec: number): string { | ||
496 | val = Math.abs(val); | 496 | val = Math.abs(val); |
497 | 497 | ||
498 | if (dec > 0) { | 498 | if (dec > 0) { |
499 | - strVal = val.toFixed(dec).toString() | 499 | + strVal = val.toFixed(dec); |
500 | } else { | 500 | } else { |
501 | strVal = Math.round(val).toString(); | 501 | strVal = Math.round(val).toString(); |
502 | } | 502 | } |
@@ -18,7 +18,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; | @@ -18,7 +18,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; | ||
18 | import { | 18 | import { |
19 | Component, | 19 | Component, |
20 | ComponentFactory, | 20 | ComponentFactory, |
21 | - ComponentRef, | 21 | + ComponentRef, HostBinding, |
22 | Inject, | 22 | Inject, |
23 | Injector, | 23 | Injector, |
24 | OnDestroy, | 24 | OnDestroy, |
@@ -46,6 +46,8 @@ export interface CustomDialogContainerData { | @@ -46,6 +46,8 @@ export interface CustomDialogContainerData { | ||
46 | }) | 46 | }) |
47 | export class CustomDialogContainerComponent extends DialogComponent<CustomDialogContainerComponent> implements OnDestroy { | 47 | export class CustomDialogContainerComponent extends DialogComponent<CustomDialogContainerComponent> implements OnDestroy { |
48 | 48 | ||
49 | + @HostBinding('style.height') height = '0px'; | ||
50 | + | ||
49 | private readonly customComponentRef: ComponentRef<CustomDialogComponent>; | 51 | private readonly customComponentRef: ComponentRef<CustomDialogComponent>; |
50 | 52 | ||
51 | constructor(protected store: Store<AppState>, | 53 | constructor(protected store: Store<AppState>, |
@@ -20,12 +20,12 @@ import 'leaflet-providers'; | @@ -20,12 +20,12 @@ import 'leaflet-providers'; | ||
20 | import 'leaflet.markercluster/dist/leaflet.markercluster'; | 20 | import 'leaflet.markercluster/dist/leaflet.markercluster'; |
21 | 21 | ||
22 | import { | 22 | import { |
23 | - FormattedData, | ||
24 | - MapSettings, | ||
25 | - MarkerSettings, | ||
26 | - PolygonSettings, | ||
27 | - PolylineSettings, | ||
28 | - UnitedMapSettings | 23 | + FormattedData, |
24 | + MapSettings, | ||
25 | + MarkerSettings, | ||
26 | + PolygonSettings, | ||
27 | + PolylineSettings, | ||
28 | + UnitedMapSettings | ||
29 | } from './map-models'; | 29 | } from './map-models'; |
30 | import { Marker } from './markers'; | 30 | import { Marker } from './markers'; |
31 | import { BehaviorSubject, Observable } from 'rxjs'; | 31 | import { BehaviorSubject, Observable } from 'rxjs'; |
@@ -345,12 +345,12 @@ export default abstract class LeafletMap { | @@ -345,12 +345,12 @@ export default abstract class LeafletMap { | ||
345 | 345 | ||
346 | // Polyline | 346 | // Polyline |
347 | 347 | ||
348 | - updatePolylines(polyData: FormattedData[][]) { | ||
349 | - polyData.forEach((data: FormattedData[]) => { | ||
350 | - if (data.length) { | ||
351 | - const dataSource = polyData.map(arr => arr[0]); | ||
352 | - if (this.polylines.get(data[0].entityName)) { | ||
353 | - this.updatePolyline(data[0].entityName, data, dataSource, this.options); | 348 | + updatePolylines(polyData: FormattedData[][], data?: FormattedData) { |
349 | + polyData.forEach((dataSource) => { | ||
350 | + if (dataSource.length) { | ||
351 | + data = data || dataSource[0]; | ||
352 | + if (this.polylines.get(data.$datasource.entityName)) { | ||
353 | + this.updatePolyline(data, dataSource, this.options); | ||
354 | } | 354 | } |
355 | else { | 355 | else { |
356 | this.createPolyline(data, dataSource, this.options); | 356 | this.createPolyline(data, dataSource, this.options); |
@@ -359,28 +359,27 @@ export default abstract class LeafletMap { | @@ -359,28 +359,27 @@ export default abstract class LeafletMap { | ||
359 | }) | 359 | }) |
360 | } | 360 | } |
361 | 361 | ||
362 | - createPolyline(data: FormattedData[], dataSources: FormattedData[], settings: PolylineSettings) { | ||
363 | - if (data.length) | ||
364 | - this.ready$.subscribe(() => { | ||
365 | - const poly = new Polyline(this.map, | ||
366 | - data.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); | ||
367 | - const bounds = poly.leafletPoly.getBounds(); | ||
368 | - this.fitBounds(bounds); | ||
369 | - this.polylines.set(data[0].entityName, poly); | ||
370 | - }); | 362 | + createPolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { |
363 | + this.ready$.subscribe(() => { | ||
364 | + const poly = new Polyline(this.map, | ||
365 | + dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); | ||
366 | + const bounds = poly.leafletPoly.getBounds(); | ||
367 | + this.fitBounds(bounds); | ||
368 | + this.polylines.set(data.$datasource.entityName, poly); | ||
369 | + }); | ||
371 | } | 370 | } |
372 | 371 | ||
373 | - updatePolyline(key: string, data: FormattedData[], dataSources: FormattedData[], settings: PolylineSettings) { | 372 | + updatePolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { |
374 | this.ready$.subscribe(() => { | 373 | this.ready$.subscribe(() => { |
375 | - const poly = this.polylines.get(key); | 374 | + const poly = this.polylines.get(data.entityName); |
376 | const oldBounds = poly.leafletPoly.getBounds(); | 375 | const oldBounds = poly.leafletPoly.getBounds(); |
377 | - poly.updatePolyline(settings, data.map(el => this.convertPosition(el)), dataSources); | 376 | + poly.updatePolyline(settings, data.map(el => this.convertPosition(el)).filter(el => !!el), dataSources); |
378 | const newBounds = poly.leafletPoly.getBounds(); | 377 | const newBounds = poly.leafletPoly.getBounds(); |
379 | if (oldBounds.toBBoxString() !== newBounds.toBBoxString()) { | 378 | if (oldBounds.toBBoxString() !== newBounds.toBBoxString()) { |
380 | this.fitBounds(newBounds); | 379 | this.fitBounds(newBounds); |
381 | } | 380 | } |
382 | }); | 381 | }); |
383 | - } | 382 | + }Я |
384 | 383 | ||
385 | // Polygon | 384 | // Polygon |
386 | 385 |
@@ -14,22 +14,28 @@ | @@ -14,22 +14,28 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import { MapProviders, UnitedMapSettings, providerSets, hereProviders, defaultSettings } from './map-models'; | 17 | +import { defaultSettings, hereProviders, MapProviders, providerSets, UnitedMapSettings } from './map-models'; |
18 | import LeafletMap from './leaflet-map'; | 18 | import LeafletMap from './leaflet-map'; |
19 | import { | 19 | import { |
20 | - commonMapSettingsSchema, | ||
21 | - routeMapSettingsSchema, | ||
22 | - markerClusteringSettingsSchema, | ||
23 | - markerClusteringSettingsSchemaLeaflet, | ||
24 | - mapProviderSchema, | ||
25 | - mapPolygonSchema | 20 | + commonMapSettingsSchema, |
21 | + mapPolygonSchema, | ||
22 | + mapProviderSchema, | ||
23 | + markerClusteringSettingsSchema, | ||
24 | + markerClusteringSettingsSchemaLeaflet, | ||
25 | + routeMapSettingsSchema | ||
26 | } from './schemes'; | 26 | } from './schemes'; |
27 | -import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface'; | ||
28 | -import { initSchema, addToSchema, mergeSchemes, addCondition, addGroupInfo } from '@core/schema-utils'; | 27 | +import { MapWidgetInterface, MapWidgetStaticInterface } from './map-widget.interface'; |
28 | +import { addCondition, addGroupInfo, addToSchema, initSchema, mergeSchemes } from '@core/schema-utils'; | ||
29 | import { of, Subject } from 'rxjs'; | 29 | import { of, Subject } from 'rxjs'; |
30 | import { WidgetContext } from '@app/modules/home/models/widget-component.models'; | 30 | import { WidgetContext } from '@app/modules/home/models/widget-component.models'; |
31 | import { getDefCenterPosition, parseArray, parseData, parseFunction, parseWithTranslation } from './maps-utils'; | 31 | import { getDefCenterPosition, parseArray, parseData, parseFunction, parseWithTranslation } from './maps-utils'; |
32 | -import { JsonSettingsSchema, WidgetActionDescriptor, DatasourceType, widgetType, Datasource } from '@shared/models/widget.models'; | 32 | +import { |
33 | + Datasource, | ||
34 | + DatasourceType, | ||
35 | + JsonSettingsSchema, | ||
36 | + WidgetActionDescriptor, | ||
37 | + widgetType | ||
38 | +} from '@shared/models/widget.models'; | ||
33 | import { EntityId } from '@shared/models/id/entity-id'; | 39 | import { EntityId } from '@shared/models/id/entity-id'; |
34 | import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/telemetry/telemetry.models'; | 40 | import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/telemetry/telemetry.models'; |
35 | import { AttributeService } from '@core/http/attribute.service'; | 41 | import { AttributeService } from '@core/http/attribute.service'; |
@@ -39,7 +45,13 @@ import { UtilsService } from '@core/services/utils.service'; | @@ -39,7 +45,13 @@ import { UtilsService } from '@core/services/utils.service'; | ||
39 | // @dynamic | 45 | // @dynamic |
40 | export class MapWidgetController implements MapWidgetInterface { | 46 | export class MapWidgetController implements MapWidgetInterface { |
41 | 47 | ||
42 | - constructor(public mapProvider: MapProviders, private drawRoutes: boolean, public ctx: WidgetContext, $element: HTMLElement, isEdit?) { | 48 | + constructor( |
49 | + public mapProvider: MapProviders, | ||
50 | + private drawRoutes: boolean, | ||
51 | + public ctx: WidgetContext, | ||
52 | + $element: HTMLElement, | ||
53 | + isEdit?: boolean | ||
54 | + ) { | ||
43 | if (this.map) { | 55 | if (this.map) { |
44 | this.map.map.remove(); | 56 | this.map.map.remove(); |
45 | delete this.map; | 57 | delete this.map; |
@@ -20,7 +20,7 @@ import { Datasource } from '@app/shared/models/widget.models'; | @@ -20,7 +20,7 @@ import { Datasource } from '@app/shared/models/widget.models'; | ||
20 | import _ from 'lodash'; | 20 | import _ from 'lodash'; |
21 | import { Observable, Observer, of } from 'rxjs'; | 21 | import { Observable, Observer, of } from 'rxjs'; |
22 | import { map } from 'rxjs/operators'; | 22 | import { map } from 'rxjs/operators'; |
23 | -import { createLabelFromDatasource, hashCode, padValue } from '@core/utils'; | 23 | +import { createLabelFromDatasource, hashCode, isNumber, isUndefined, padValue } from '@core/utils'; |
24 | 24 | ||
25 | export function createTooltip(target: L.Layer, | 25 | export function createTooltip(target: L.Layer, |
26 | settings: MarkerSettings | PolylineSettings | PolygonSettings, | 26 | settings: MarkerSettings | PolylineSettings | PolygonSettings, |
@@ -43,8 +43,9 @@ export function createTooltip(target: L.Layer, | @@ -43,8 +43,9 @@ export function createTooltip(target: L.Layer, | ||
43 | const actions = document.getElementsByClassName('tb-custom-action'); | 43 | const actions = document.getElementsByClassName('tb-custom-action'); |
44 | Array.from(actions).forEach( | 44 | Array.from(actions).forEach( |
45 | (element: HTMLElement) => { | 45 | (element: HTMLElement) => { |
46 | - if (element && settings.tooltipAction[element.id]) { | ||
47 | - element.addEventListener('click', ($event) => settings.tooltipAction[element.id]($event, datasource)); | 46 | + const actionName = element.getAttribute('data-action-name'); |
47 | + if (element && settings.tooltipAction[actionName]) { | ||
48 | + element.addEventListener('click', ($event) => settings.tooltipAction[actionName]($event, datasource)); | ||
48 | } | 49 | } |
49 | }); | 50 | }); |
50 | }); | 51 | }); |
@@ -55,10 +56,26 @@ export function getRatio(firsMoment: number, secondMoment: number, intermediateM | @@ -55,10 +56,26 @@ export function getRatio(firsMoment: number, secondMoment: number, intermediateM | ||
55 | return (intermediateMoment - firsMoment) / (secondMoment - firsMoment); | 56 | return (intermediateMoment - firsMoment) / (secondMoment - firsMoment); |
56 | } | 57 | } |
57 | 58 | ||
58 | -export function findAngle(startPoint, endPoint) { | ||
59 | - let angle = -Math.atan2(endPoint.latitude - startPoint.latitude, endPoint.longitude - startPoint.longitude); | ||
60 | - angle = angle * 180 / Math.PI; | ||
61 | - return parseInt(angle.toFixed(2), 10); | 59 | +export function interpolateOnLineSegment( |
60 | + pointA: FormattedData, | ||
61 | + oointB: FormattedData, | ||
62 | + latKeyName: string, | ||
63 | + lngKeyName: string, | ||
64 | + ratio: number | ||
65 | +): { [key: string]: number } { | ||
66 | + return { | ||
67 | + [latKeyName]: (pointA[latKeyName] + (oointB[latKeyName] - pointA[latKeyName]) * ratio), | ||
68 | + [lngKeyName]: (pointA[lngKeyName] + (oointB[lngKeyName] - pointA[lngKeyName]) * ratio) | ||
69 | + }; | ||
70 | +} | ||
71 | + | ||
72 | +export function findAngle(startPoint: FormattedData, endPoint: FormattedData, latKeyName: string, lngKeyName: string): number { | ||
73 | + if(isUndefined(startPoint) || isUndefined(endPoint)){ | ||
74 | + return 0; | ||
75 | + } | ||
76 | + let angle = -Math.atan2(endPoint[latKeyName] - startPoint[latKeyName], endPoint[lngKeyName] - startPoint[lngKeyName]); | ||
77 | + angle = angle * 180 / Math.PI; | ||
78 | + return parseInt(angle.toFixed(2), 10); | ||
62 | } | 79 | } |
63 | 80 | ||
64 | 81 | ||
@@ -111,38 +128,81 @@ export function aspectCache(imageUrl: string): Observable<number> { | @@ -111,38 +128,81 @@ export function aspectCache(imageUrl: string): Observable<number> { | ||
111 | 128 | ||
112 | export type TranslateFunc = (key: string, defaultTranslation?: string) => string; | 129 | export type TranslateFunc = (key: string, defaultTranslation?: string) => string; |
113 | 130 | ||
131 | +const varsRegex = /\${([^}]*)}/g; | ||
132 | +const linkActionRegex = /<link-act name=['"]([^['"]*)['"]>([^<]*)<\/link-act>/g; | ||
133 | +const buttonActionRegex = /<button-act name=['"]([^['"]*)['"]>([^<]*)<\/button-act>/g; | ||
134 | + | ||
135 | +function createLinkElement(actionName: string, actionText: string): string { | ||
136 | + return `<a href="#" class="tb-custom-action" data-action-name=${actionName}>${actionText}</a>`; | ||
137 | +} | ||
138 | + | ||
139 | +function createButtonElement(actionName: string, actionText: string) { | ||
140 | + return `<button mat-button class="tb-custom-action" data-action-name=${actionName}>${actionText}</button>`; | ||
141 | +} | ||
142 | + | ||
114 | function parseTemplate(template: string, data: { $datasource?: Datasource, [key: string]: any }, | 143 | function parseTemplate(template: string, data: { $datasource?: Datasource, [key: string]: any }, |
115 | - translateFn?: TranslateFunc) { | 144 | + translateFn?: TranslateFunc) { |
116 | let res = ''; | 145 | let res = ''; |
117 | try { | 146 | try { |
118 | - if (template.match(/<link-act/g)) { | ||
119 | - template = template.replace(/<link-act/g, '<a href="#"').replace(/link-act>/g, 'a>') | ||
120 | - .replace(/name=(['"])(.*?)(['"])/g, `class='tb-custom-action' id='$2'`); | ||
121 | - } | ||
122 | if (translateFn) { | 147 | if (translateFn) { |
123 | template = translateFn(template); | 148 | template = translateFn(template); |
124 | } | 149 | } |
125 | template = createLabelFromDatasource(data.$datasource, template); | 150 | template = createLabelFromDatasource(data.$datasource, template); |
126 | - const formatted = template.match(/\${([^}]*):\d*}/g); | ||
127 | - if (formatted) | ||
128 | - formatted.forEach(value => { | ||
129 | - const [variable, digits] = value.replace('${', '').replace('}', '').split(':'); | ||
130 | - data[variable] = padValue(data[variable], +digits); | ||
131 | - if (data[variable] === 'NaN') data[variable] = ''; | ||
132 | - template = template.replace(value, '${' + variable + '}'); | ||
133 | - }); | ||
134 | - const variables = template.match(/\${.*?}/g); | ||
135 | - if (variables) { | ||
136 | - variables.forEach(variable => { | ||
137 | - variable = variable.replace('${', '').replace('}', ''); | ||
138 | - if (!data[variable]) | ||
139 | - data[variable] = ''; | ||
140 | - }) | 151 | + |
152 | + let match = varsRegex.exec(template); | ||
153 | + while (match !== null) { | ||
154 | + const variable = match[0]; | ||
155 | + let label = match[1]; | ||
156 | + let valDec = 2; | ||
157 | + const splitValues = label.split(':'); | ||
158 | + if (splitValues.length > 1) { | ||
159 | + label = splitValues[0]; | ||
160 | + valDec = parseFloat(splitValues[1]); | ||
161 | + } | ||
162 | + | ||
163 | + if (label.startsWith('#')) { | ||
164 | + const keyIndexStr = label.substring(1); | ||
165 | + const n = Math.floor(Number(keyIndexStr)); | ||
166 | + if (String(n) === keyIndexStr && n >= 0) { | ||
167 | + label = data.$datasource.dataKeys[n].label; | ||
168 | + } | ||
169 | + } | ||
170 | + | ||
171 | + const value = data[label] || ''; | ||
172 | + let textValue: string; | ||
173 | + if (isNumber(value)) { | ||
174 | + textValue = padValue(value, valDec); | ||
175 | + } else { | ||
176 | + textValue = value; | ||
177 | + } | ||
178 | + template = template.split(variable).join(textValue); | ||
179 | + match = varsRegex.exec(template); | ||
141 | } | 180 | } |
181 | + | ||
182 | + let actionTags: string; | ||
183 | + let actionText: string; | ||
184 | + let actionName: string; | ||
185 | + let action: string; | ||
186 | + | ||
187 | + match = linkActionRegex.exec(template); | ||
188 | + while (match !== null) { | ||
189 | + [actionTags, actionName, actionText] = match; | ||
190 | + action = createLinkElement(actionName, actionText); | ||
191 | + template = template.split(actionTags).join(action); | ||
192 | + match = linkActionRegex.exec(template); | ||
193 | + } | ||
194 | + | ||
195 | + match = buttonActionRegex.exec(template); | ||
196 | + while (match !== null) { | ||
197 | + [actionTags, actionName, actionText] = match; | ||
198 | + action = createButtonElement(actionName, actionText); | ||
199 | + template = template.split(actionTags).join(action); | ||
200 | + match = buttonActionRegex.exec(template); | ||
201 | + } | ||
202 | + | ||
142 | const compiled = _.template(template); | 203 | const compiled = _.template(template); |
143 | res = compiled(data); | 204 | res = compiled(data); |
144 | - } | ||
145 | - catch (ex) { | 205 | + } catch (ex) { |
146 | console.log(ex, template) | 206 | console.log(ex, template) |
147 | } | 207 | } |
148 | return res; | 208 | return res; |
@@ -14,18 +14,18 @@ | @@ -14,18 +14,18 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import L, { LatLngExpression, LatLngTuple, LeafletMouseEvent } from 'leaflet'; | 17 | +import L, { LatLngExpression, LeafletMouseEvent } from 'leaflet'; |
18 | import { createTooltip, parseWithTranslation, safeExecute } from './maps-utils'; | 18 | import { createTooltip, parseWithTranslation, safeExecute } from './maps-utils'; |
19 | import { FormattedData, PolygonSettings } from './map-models'; | 19 | import { FormattedData, PolygonSettings } from './map-models'; |
20 | 20 | ||
21 | export class Polygon { | 21 | export class Polygon { |
22 | 22 | ||
23 | leafletPoly: L.Polygon; | 23 | leafletPoly: L.Polygon; |
24 | - tooltip; | ||
25 | - data; | ||
26 | - dataSources; | 24 | + tooltip: L.Popup; |
25 | + data: FormattedData; | ||
26 | + dataSources: FormattedData[]; | ||
27 | 27 | ||
28 | - constructor(public map, polyData: FormattedData, dataSources, private settings: PolygonSettings) { | 28 | + constructor(public map, polyData: FormattedData, dataSources: FormattedData[], private settings: PolygonSettings) { |
29 | this.dataSources = dataSources; | 29 | this.dataSources = dataSources; |
30 | this.data = polyData; | 30 | this.data = polyData; |
31 | const polygonColor = this.getPolygonColor(settings); | 31 | const polygonColor = this.getPolygonColor(settings); |
@@ -61,7 +61,7 @@ export class Polygon { | @@ -61,7 +61,7 @@ export class Polygon { | ||
61 | this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, data, true)); | 61 | this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, data, true)); |
62 | } | 62 | } |
63 | 63 | ||
64 | - updatePolygon(data:{[coordinates:string]: LatLngTuple[]}, dataSources: FormattedData[], settings: PolygonSettings) { | 64 | + updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) { |
65 | this.data = data; | 65 | this.data = data; |
66 | this.dataSources = dataSources; | 66 | this.dataSources = dataSources; |
67 | this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]); | 67 | this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]); |
@@ -17,82 +17,83 @@ | @@ -17,82 +17,83 @@ | ||
17 | import L, { PolylineDecoratorOptions } from 'leaflet'; | 17 | import L, { PolylineDecoratorOptions } from 'leaflet'; |
18 | import 'leaflet-polylinedecorator'; | 18 | import 'leaflet-polylinedecorator'; |
19 | 19 | ||
20 | -import { PolylineSettings } from './map-models'; | 20 | +import { FormattedData, PolylineSettings } from './map-models'; |
21 | import { safeExecute } from '@home/components/widget/lib/maps/maps-utils'; | 21 | import { safeExecute } from '@home/components/widget/lib/maps/maps-utils'; |
22 | 22 | ||
23 | export class Polyline { | 23 | export class Polyline { |
24 | 24 | ||
25 | - leafletPoly: L.Polyline; | ||
26 | - polylineDecorator: L.PolylineDecorator; | ||
27 | - dataSources; | ||
28 | - data; | 25 | + leafletPoly: L.Polyline; |
26 | + polylineDecorator: L.PolylineDecorator; | ||
27 | + dataSources: FormattedData[]; | ||
28 | + data: FormattedData; | ||
29 | 29 | ||
30 | - constructor(private map: L.Map, locations, data, dataSources, settings: PolylineSettings) { | ||
31 | - this.dataSources = dataSources; | ||
32 | - this.data = data; | 30 | + constructor(private map: L.Map, locations: L.LatLng[], data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { |
31 | + this.dataSources = dataSources; | ||
32 | + this.data = data; | ||
33 | 33 | ||
34 | - this.leafletPoly = L.polyline(locations, | ||
35 | - this.getPolyStyle(settings) | ||
36 | - ).addTo(this.map); | 34 | + this.leafletPoly = L.polyline(locations, |
35 | + this.getPolyStyle(settings) | ||
36 | + ).addTo(this.map); | ||
37 | 37 | ||
38 | - if (settings.usePolylineDecorator) { | ||
39 | - this.polylineDecorator = L.polylineDecorator(this.leafletPoly, this.getDecoratorSettings(settings)).addTo(this.map); | ||
40 | - } | 38 | + if (settings.usePolylineDecorator) { |
39 | + this.polylineDecorator = L.polylineDecorator(this.leafletPoly, this.getDecoratorSettings(settings)).addTo(this.map); | ||
41 | } | 40 | } |
41 | + } | ||
42 | 42 | ||
43 | - getDecoratorSettings(settings: PolylineSettings): PolylineDecoratorOptions { | ||
44 | - return { | ||
45 | - patterns: [ | ||
46 | - { | ||
47 | - offset: settings.decoratorOffset, | ||
48 | - endOffset: settings.endDecoratorOffset, | ||
49 | - repeat: settings.decoratorRepeat, | ||
50 | - symbol: L.Symbol[settings.decoratorSymbol]({ | ||
51 | - pixelSize: settings.decoratorSymbolSize, | ||
52 | - polygon: false, | ||
53 | - pathOptions: { | ||
54 | - color: settings.useDecoratorCustomColor ? settings.decoratorCustomColor : this.getPolyStyle(settings).color, | ||
55 | - stroke: true | ||
56 | - } | ||
57 | - }) | ||
58 | - } | ||
59 | - ], | ||
60 | - interactive: false, | ||
61 | - } as PolylineDecoratorOptions | 43 | + getDecoratorSettings(settings: PolylineSettings): PolylineDecoratorOptions { |
44 | + return { | ||
45 | + patterns: [ | ||
46 | + { | ||
47 | + offset: settings.decoratorOffset, | ||
48 | + endOffset: settings.endDecoratorOffset, | ||
49 | + repeat: settings.decoratorRepeat, | ||
50 | + symbol: L.Symbol[settings.decoratorSymbol]({ | ||
51 | + pixelSize: settings.decoratorSymbolSize, | ||
52 | + polygon: false, | ||
53 | + pathOptions: { | ||
54 | + color: settings.useDecoratorCustomColor ? settings.decoratorCustomColor : this.getPolyStyle(settings).color, | ||
55 | + stroke: true | ||
56 | + } | ||
57 | + }) | ||
58 | + } | ||
59 | + ] | ||
62 | } | 60 | } |
61 | + } | ||
63 | 62 | ||
64 | - updatePolyline(settings, data, dataSources) { | ||
65 | - this.data = data; | ||
66 | - this.dataSources = dataSources; | ||
67 | - this.leafletPoly.setStyle(this.getPolyStyle(settings)); | ||
68 | - // this.setPolylineLatLngs(data); | ||
69 | - if (this.polylineDecorator) | ||
70 | - this.polylineDecorator.setPaths(this.leafletPoly); | ||
71 | - } | 63 | + updatePolyline(locations: L.LatLng[], data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { |
64 | + this.data = data; | ||
65 | + this.dataSources = dataSources; | ||
66 | + this.leafletPoly.setLatLngs(locations); | ||
67 | + this.leafletPoly.setStyle(this.getPolyStyle(settings)); | ||
68 | + // this.setPolylineLatLngs(data); | ||
69 | + if (this.polylineDecorator) | ||
70 | + this.polylineDecorator.setPaths(this.leafletPoly); | ||
71 | + } | ||
72 | 72 | ||
73 | - getPolyStyle(settings: PolylineSettings): L.PolylineOptions { | ||
74 | - return { | ||
75 | - color: settings.useColorFunction ? | ||
76 | - safeExecute(settings.colorFunction, | ||
77 | - [this.data, this.dataSources, this.dataSources[0]?.dsIndex]) : settings.color, | ||
78 | - opacity: settings.useStrokeOpacityFunction ? | ||
79 | - safeExecute(settings.strokeOpacityFunction, | ||
80 | - [this.data, this.dataSources, this.dataSources[0]?.dsIndex]) : settings.strokeOpacity, | ||
81 | - weight: settings.useStrokeWeightFunction ? | ||
82 | - safeExecute(settings.strokeWeightFunction, | ||
83 | - [this.data, this.dataSources, this.dataSources[0]?.dsIndex]) : settings.strokeWeight, | ||
84 | - } | 73 | + getPolyStyle(settings: PolylineSettings): L.PolylineOptions { |
74 | + return { | ||
75 | + interactive: false, | ||
76 | + color: settings.useColorFunction ? | ||
77 | + safeExecute(settings.colorFunction, | ||
78 | + [this.data, this.dataSources, this.data.dsIndex]) : settings.color, | ||
79 | + opacity: settings.useStrokeOpacityFunction ? | ||
80 | + safeExecute(settings.strokeOpacityFunction, | ||
81 | + [this.data, this.dataSources, this.data.dsIndex]) : settings.strokeOpacity, | ||
82 | + weight: settings.useStrokeWeightFunction ? | ||
83 | + safeExecute(settings.strokeWeightFunction, | ||
84 | + [this.data, this.dataSources, this.data.dsIndex]) : settings.strokeWeight, | ||
85 | } | 85 | } |
86 | + } | ||
86 | 87 | ||
87 | - removePolyline() { | ||
88 | - this.map.removeLayer(this.leafletPoly); | ||
89 | - } | 88 | + removePolyline() { |
89 | + this.map.removeLayer(this.leafletPoly); | ||
90 | + } | ||
90 | 91 | ||
91 | - getPolylineLatLngs() { | ||
92 | - return this.leafletPoly.getLatLngs(); | ||
93 | - } | 92 | + getPolylineLatLngs() { |
93 | + return this.leafletPoly.getLatLngs(); | ||
94 | + } | ||
94 | 95 | ||
95 | - setPolylineLatLngs(latLngs) { | ||
96 | - this.leafletPoly.setLatLngs(latLngs); | ||
97 | - } | 96 | + setPolylineLatLngs(latLngs) { |
97 | + this.leafletPoly.setLatLngs(latLngs); | ||
98 | + } | ||
98 | } | 99 | } |
@@ -841,52 +841,57 @@ export const pathSchema = | @@ -841,52 +841,57 @@ export const pathSchema = | ||
841 | }; | 841 | }; |
842 | 842 | ||
843 | export const pointSchema = | 843 | export const pointSchema = |
844 | -{ | 844 | + { |
845 | schema: { | 845 | schema: { |
846 | - title: 'Trip Animation Path Configuration', | ||
847 | - type: 'object', | ||
848 | - properties: { | ||
849 | - showPoints: { | ||
850 | - title: 'Show points', | ||
851 | - type: 'boolean', | ||
852 | - default: false | ||
853 | - }, | ||
854 | - pointColor: { | ||
855 | - title: 'Point color', | ||
856 | - type: 'string' | ||
857 | - }, | ||
858 | - pointSize: { | ||
859 | - title: 'Point size (px)', | ||
860 | - type: 'number', | ||
861 | - default: 10 | ||
862 | - }, | ||
863 | - usePointAsAnchor: { | ||
864 | - title: 'Use point as anchor', | ||
865 | - type: 'boolean', | ||
866 | - default: false | ||
867 | - }, | ||
868 | - pointAsAnchorFunction: { | ||
869 | - title: 'Point as anchor function: f(data, dsData, dsIndex)', | ||
870 | - type: 'string' | ||
871 | - }, | ||
872 | - pointTooltipOnRightPanel: { | ||
873 | - title: 'Independant point tooltip', | ||
874 | - type: 'boolean', | ||
875 | - default: true | ||
876 | - }, | 846 | + title: 'Trip Animation Path Configuration', |
847 | + type: 'object', | ||
848 | + properties: { | ||
849 | + showPoints: { | ||
850 | + title: 'Show points', | ||
851 | + type: 'boolean', | ||
852 | + default: false | ||
877 | }, | 853 | }, |
878 | - required: [] | 854 | + pointColor: { |
855 | + title: 'Point color', | ||
856 | + type: 'string' | ||
857 | + }, | ||
858 | + pointSize: { | ||
859 | + title: 'Point size (px)', | ||
860 | + type: 'number', | ||
861 | + default: 10 | ||
862 | + }, | ||
863 | + usePointAsAnchor: { | ||
864 | + title: 'Use point as anchor', | ||
865 | + type: 'boolean', | ||
866 | + default: false | ||
867 | + }, | ||
868 | + pointAsAnchorFunction: { | ||
869 | + title: 'Point as anchor function: f(data, dsData, dsIndex)', | ||
870 | + type: 'string' | ||
871 | + }, | ||
872 | + pointTooltipOnRightPanel: { | ||
873 | + title: 'Independant point tooltip', | ||
874 | + type: 'boolean', | ||
875 | + default: true | ||
876 | + }, | ||
877 | + }, | ||
878 | + required: [] | ||
879 | }, | 879 | }, |
880 | form: [ | 880 | form: [ |
881 | - 'showPoints', { | ||
882 | - key: 'pointColor', | ||
883 | - type: 'color' | ||
884 | - }, 'pointSize', 'usePointAsAnchor', { | ||
885 | - key: 'pointAsAnchorFunction', | ||
886 | - type: 'javascript' | ||
887 | - }, 'pointTooltipOnRightPanel', | 881 | + 'showPoints', |
882 | + { | ||
883 | + key: 'pointColor', | ||
884 | + type: 'color' | ||
885 | + }, | ||
886 | + 'pointSize', | ||
887 | + 'usePointAsAnchor', | ||
888 | + { | ||
889 | + key: 'pointAsAnchorFunction', | ||
890 | + type: 'javascript' | ||
891 | + }, | ||
892 | + 'pointTooltipOnRightPanel', | ||
888 | ] | 893 | ] |
889 | -}; | 894 | + }; |
890 | 895 | ||
891 | export const mapProviderSchema = | 896 | export const mapProviderSchema = |
892 | { | 897 | { |
@@ -32,6 +32,12 @@ | @@ -32,6 +32,12 @@ | ||
32 | [ngStyle]="{'background-color': settings.tooltipColor, 'opacity': settings.tooltipOpacity, 'color': settings.tooltipFontColor}"> | 32 | [ngStyle]="{'background-color': settings.tooltipColor, 'opacity': settings.tooltipOpacity, 'color': settings.tooltipFontColor}"> |
33 | </div> | 33 | </div> |
34 | </div> | 34 | </div> |
35 | - <tb-history-selector *ngIf="historicalData" [settings]="settings" [intervals]="intervals" [anchors]="anchors" [useAnchors]="useAnchors" | ||
36 | - (timeUpdated)="timeUpdated($event)"></tb-history-selector> | ||
37 | -</div> | ||
35 | + <tb-history-selector *ngIf="historicalData" | ||
36 | + [settings]="settings" | ||
37 | + [minTime]="minTime" | ||
38 | + [maxTime]="maxTime" | ||
39 | + [step]="normalizationStep" | ||
40 | + [anchors]="anchors" | ||
41 | + [useAnchors]="useAnchors" | ||
42 | + (timeUpdated)="timeUpdated($event)"></tb-history-selector> | ||
43 | +</div> |
@@ -14,21 +14,28 @@ | @@ -14,21 +14,28 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import L from 'leaflet'; | ||
18 | import _ from 'lodash'; | 17 | import _ from 'lodash'; |
19 | import tinycolor from 'tinycolor2'; | 18 | import tinycolor from 'tinycolor2'; |
20 | -import { interpolateOnPointSegment } from 'leaflet-geometryutil'; | ||
21 | 19 | ||
22 | import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, SecurityContext, ViewChild } from '@angular/core'; | 20 | import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, SecurityContext, ViewChild } from '@angular/core'; |
23 | import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2'; | 21 | import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2'; |
24 | -import { MapProviders, FormattedData } from '../lib/maps/map-models'; | ||
25 | -import { initSchema, addToSchema, addGroupInfo, addCondition } from '@app/core/schema-utils'; | ||
26 | -import { tripAnimationSchema, mapPolygonSchema, pathSchema, pointSchema } from '../lib/maps/schemes'; | 22 | +import { FormattedData, MapProviders } from '../lib/maps/map-models'; |
23 | +import { addCondition, addGroupInfo, addToSchema, initSchema } from '@app/core/schema-utils'; | ||
24 | +import { mapPolygonSchema, pathSchema, pointSchema, tripAnimationSchema } from '../lib/maps/schemes'; | ||
27 | import { DomSanitizer } from '@angular/platform-browser'; | 25 | import { DomSanitizer } from '@angular/platform-browser'; |
28 | import { WidgetContext } from '@app/modules/home/models/widget-component.models'; | 26 | import { WidgetContext } from '@app/modules/home/models/widget-component.models'; |
29 | -import { findAngle, getRatio, parseArray, parseWithTranslation, safeExecute } from '../lib/maps/maps-utils'; | 27 | +import { |
28 | + findAngle, | ||
29 | + getRatio, | ||
30 | + interpolateOnLineSegment, | ||
31 | + parseArray, | ||
32 | + parseFunction, | ||
33 | + parseWithTranslation, | ||
34 | + safeExecute | ||
35 | +} from '../lib/maps/maps-utils'; | ||
30 | import { JsonSettingsSchema, WidgetConfig } from '@shared/models/widget.models'; | 36 | import { JsonSettingsSchema, WidgetConfig } from '@shared/models/widget.models'; |
31 | import moment from 'moment'; | 37 | import moment from 'moment'; |
38 | +import { isUndefined } from '@core/utils'; | ||
32 | 39 | ||
33 | 40 | ||
34 | @Component({ | 41 | @Component({ |
@@ -46,20 +53,22 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | @@ -46,20 +53,22 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | ||
46 | @ViewChild('map') mapContainer; | 53 | @ViewChild('map') mapContainer; |
47 | 54 | ||
48 | mapWidget: MapWidgetController; | 55 | mapWidget: MapWidgetController; |
49 | - historicalData; | 56 | + historicalData: FormattedData[][]; |
57 | + normalizationStep: number; | ||
58 | + interpolatedTimeData = []; | ||
50 | intervals = []; | 59 | intervals = []; |
51 | - normalizationStep = 1000; | ||
52 | - interpolatedData = []; | ||
53 | widgetConfig: WidgetConfig; | 60 | widgetConfig: WidgetConfig; |
54 | settings; | 61 | settings; |
55 | mainTooltip = ''; | 62 | mainTooltip = ''; |
56 | visibleTooltip = false; | 63 | visibleTooltip = false; |
57 | - activeTrip; | 64 | + activeTrip: FormattedData; |
58 | label; | 65 | label; |
59 | - minTime; | ||
60 | - maxTime; | ||
61 | - anchors = []; | ||
62 | - useAnchors = false; | 66 | + minTime: number; |
67 | + minTimeFormat: string; | ||
68 | + maxTime: number; | ||
69 | + maxTimeFormat: string; | ||
70 | + anchors: number[] = []; | ||
71 | + useAnchors: boolean; | ||
63 | 72 | ||
64 | static getSettingsSchema(): JsonSettingsSchema { | 73 | static getSettingsSchema(): JsonSettingsSchema { |
65 | const schema = initSchema(); | 74 | const schema = initSchema(); |
@@ -86,7 +95,8 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | @@ -86,7 +95,8 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | ||
86 | rotationAngle: 0 | 95 | rotationAngle: 0 |
87 | } | 96 | } |
88 | this.settings = { ...settings, ...this.ctx.settings }; | 97 | this.settings = { ...settings, ...this.ctx.settings }; |
89 | - this.useAnchors = this.settings.usePointAsAnchor && this.settings.showPoints; | 98 | + this.useAnchors = this.settings.showPoints && this.settings.usePointAsAnchor; |
99 | + this.settings.pointAsAnchorFunction = parseFunction(this.settings.pointAsAnchorFunction, ['data', 'dsData', 'dsIndex']); | ||
90 | this.settings.fitMapBounds = true; | 100 | this.settings.fitMapBounds = true; |
91 | this.normalizationStep = this.settings.normalizationStep; | 101 | this.normalizationStep = this.settings.normalizationStep; |
92 | const subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]]; | 102 | const subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]]; |
@@ -95,7 +105,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | @@ -95,7 +105,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | ||
95 | if (this.historicalData.length) { | 105 | if (this.historicalData.length) { |
96 | this.activeTrip = this.historicalData[0][0]; | 106 | this.activeTrip = this.historicalData[0][0]; |
97 | this.calculateIntervals(); | 107 | this.calculateIntervals(); |
98 | - this.timeUpdated(this.intervals[0]); | 108 | + this.timeUpdated(this.minTime); |
99 | } | 109 | } |
100 | this.mapWidget.map.map?.invalidateSize(); | 110 | this.mapWidget.map.map?.invalidateSize(); |
101 | this.cd.detectChanges(); | 111 | this.cd.detectChanges(); |
@@ -108,30 +118,40 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | @@ -108,30 +118,40 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | ||
108 | } | 118 | } |
109 | 119 | ||
110 | timeUpdated(time: number) { | 120 | timeUpdated(time: number) { |
111 | - this.minTime = moment(this.intervals[this.intervals.length - 1]).format('YYYY-MM-DD HH:mm:ss'); | ||
112 | - this.maxTime = moment(this.intervals[0]).format('YYYY-MM-DD HH:mm:ss'); | ||
113 | - const currentPosition = this.interpolatedData | 121 | + const currentPosition = this.interpolatedTimeData |
114 | .map(dataSource => dataSource[time]) | 122 | .map(dataSource => dataSource[time]) |
115 | .filter(ds => ds) | 123 | .filter(ds => ds) |
116 | .map(ds => { | 124 | .map(ds => { |
117 | - ds.minTime = this.minTime; | ||
118 | - ds.maxTime = this.maxTime; | 125 | + ds.minTime = this.minTimeFormat; |
126 | + ds.maxTime = this.maxTimeFormat; | ||
119 | return ds; | 127 | return ds; |
120 | }); | 128 | }); |
129 | + if (isUndefined(currentPosition[0])) { | ||
130 | + const timePoints = Object.keys(this.interpolatedTimeData[0]).map(item => parseInt(item, 10)); | ||
131 | + for (let i = 1; i < timePoints.length; i++) { | ||
132 | + if (timePoints[i - 1] < time && timePoints[i] > time) { | ||
133 | + const beforePosition = this.interpolatedTimeData[0][timePoints[i - 1]]; | ||
134 | + const afterPosition = this.interpolatedTimeData[0][timePoints[i]]; | ||
135 | + const ratio = getRatio(timePoints[i - 1], timePoints[i], time); | ||
136 | + currentPosition[0] = { | ||
137 | + ...beforePosition, | ||
138 | + time, | ||
139 | + ...interpolateOnLineSegment(beforePosition, afterPosition, this.settings.latKeyName, this.settings.lngKeyName, ratio) | ||
140 | + } | ||
141 | + break; | ||
142 | + } | ||
143 | + } | ||
144 | + } | ||
121 | this.activeTrip = currentPosition[0]; | 145 | this.activeTrip = currentPosition[0]; |
122 | this.calcLabel(); | 146 | this.calcLabel(); |
123 | this.calcTooltip(); | 147 | this.calcTooltip(); |
124 | if (this.mapWidget) { | 148 | if (this.mapWidget) { |
125 | - this.mapWidget.map.updatePolylines(this.interpolatedData.map(ds => _.values(ds))); | 149 | + this.mapWidget.map.updatePolylines(this.interpolatedTimeData.map(ds => _.values(ds)), this.activeTrip); |
126 | if (this.settings.showPolygon) { | 150 | if (this.settings.showPolygon) { |
127 | - this.mapWidget.map.updatePolygons(this.interpolatedData); | 151 | + this.mapWidget.map.updatePolygons(this.interpolatedTimeData); |
128 | } | 152 | } |
129 | if (this.settings.showPoints) { | 153 | if (this.settings.showPoints) { |
130 | - this.mapWidget.map.updatePoints(this.historicalData[0], this.calcTooltip); | ||
131 | - this.anchors = this.historicalData[0] | ||
132 | - .filter(data => | ||
133 | - this.settings.usePointAsAnchor || | ||
134 | - safeExecute(this.settings.pointAsAnchorFunction, [this.historicalData, data, data.dsIndex])).map(data => data.time); | 154 | + this.mapWidget.map.updatePoints(_.values(_.union(this.interpolatedTimeData)[0]), this.calcTooltip); |
135 | } | 155 | } |
136 | this.mapWidget.map.updateMarkers(currentPosition, this.calcTooltip); | 156 | this.mapWidget.map.updateMarkers(currentPosition, this.calcTooltip); |
137 | } | 157 | } |
@@ -142,22 +162,31 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | @@ -142,22 +162,31 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | ||
142 | 162 | ||
143 | calculateIntervals() { | 163 | calculateIntervals() { |
144 | this.historicalData.forEach((dataSource, index) => { | 164 | this.historicalData.forEach((dataSource, index) => { |
145 | - this.intervals = []; | ||
146 | - for (let time = dataSource[0]?.time; time < dataSource[dataSource.length - 1]?.time; time += this.normalizationStep) { | ||
147 | - this.intervals.push(time); | ||
148 | - } | ||
149 | - this.intervals.push(dataSource[dataSource.length - 1]?.time); | ||
150 | - this.interpolatedData[index] = this.interpolateArray(dataSource, this.intervals); | 165 | + this.minTime = dataSource[0]?.time || Infinity; |
166 | + this.minTimeFormat = this.minTime !== Infinity ? moment(this.minTime).format('YYYY-MM-DD HH:mm:ss') : ''; | ||
167 | + this.maxTime = dataSource[dataSource.length - 1]?.time || -Infinity; | ||
168 | + this.maxTimeFormat = this.maxTime !== -Infinity ? moment(this.maxTime).format('YYYY-MM-DD HH:mm:ss') : ''; | ||
169 | + this.interpolatedTimeData[index] = this.interpolateArray(dataSource); | ||
151 | }); | 170 | }); |
171 | + if (this.useAnchors) { | ||
172 | + const anchorDate = Object.entries(_.union(this.interpolatedTimeData)[0]); | ||
173 | + this.anchors = anchorDate | ||
174 | + .filter((data: [string, FormattedData]) => safeExecute(this.settings.pointAsAnchorFunction, [data[1], anchorDate, data[1].dsIndex])) | ||
175 | + .map(data => parseInt(data[0], 10)); | ||
176 | + } | ||
152 | } | 177 | } |
153 | 178 | ||
154 | calcTooltip = (point?: FormattedData, setTooltip = true) => { | 179 | calcTooltip = (point?: FormattedData, setTooltip = true) => { |
155 | if (!point) { | 180 | if (!point) { |
156 | point = this.activeTrip; | 181 | point = this.activeTrip; |
157 | } | 182 | } |
158 | - const data = { ...point, maxTime: this.maxTime, minTime: this.minTime } | 183 | + const data = { |
184 | + ...this.activeTrip, | ||
185 | + maxTime: this.maxTimeFormat, | ||
186 | + minTime: this.minTimeFormat | ||
187 | + } | ||
159 | const tooltipPattern: string = this.settings.useTooltipFunction ? | 188 | const tooltipPattern: string = this.settings.useTooltipFunction ? |
160 | - safeExecute(this.settings.tooolTipFunction, [data, this.historicalData, 0]) : this.settings.tooltipPattern; | 189 | + safeExecute(this.settings.tooolTipFunction, [data, this.historicalData, point.dsIndex]) : this.settings.tooltipPattern; |
161 | const tooltipText = parseWithTranslation.parseTemplate(tooltipPattern, data, true); | 190 | const tooltipText = parseWithTranslation.parseTemplate(tooltipPattern, data, true); |
162 | if (setTooltip) { | 191 | if (setTooltip) { |
163 | this.mainTooltip = this.sanitizer.sanitize( | 192 | this.mainTooltip = this.sanitizer.sanitize( |
@@ -168,34 +197,34 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | @@ -168,34 +197,34 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { | ||
168 | } | 197 | } |
169 | 198 | ||
170 | calcLabel() { | 199 | calcLabel() { |
171 | - const data = { ...this.activeTrip, maxTime: this.maxTime, minTime: this.minTime } | 200 | + const data = { |
201 | + ...this.activeTrip, | ||
202 | + maxTime: this.maxTimeFormat, | ||
203 | + minTime: this.minTimeFormat | ||
204 | + } | ||
172 | const labelText: string = this.settings.useLabelFunction ? | 205 | const labelText: string = this.settings.useLabelFunction ? |
173 | - safeExecute(this.settings.labelFunction, [data, this.historicalData, 0]) : this.settings.label; | 206 | + safeExecute(this.settings.labelFunction, [data, this.historicalData, data.dsIndex]) : this.settings.label; |
174 | this.label = (parseWithTranslation.parseTemplate(labelText, data, true)); | 207 | this.label = (parseWithTranslation.parseTemplate(labelText, data, true)); |
175 | } | 208 | } |
176 | 209 | ||
177 | - interpolateArray(originData, interpolatedIntervals) { | 210 | + interpolateArray(originData: FormattedData[]) { |
178 | const result = {}; | 211 | const result = {}; |
179 | - for (let i = 1, j = 0; i < originData.length && j < interpolatedIntervals.length;) { | ||
180 | - const currentTime = interpolatedIntervals[j]; | ||
181 | - while (originData[i].time < currentTime) i++; | ||
182 | - const before = originData[i - 1]; | ||
183 | - const after = originData[i]; | ||
184 | - const interpolation = interpolateOnPointSegment( | ||
185 | - new L.Point(before.latitude, before.longitude), | ||
186 | - new L.Point(after.latitude, after.longitude), | ||
187 | - getRatio(before.time, after.time, currentTime)); | ||
188 | - result[currentTime] = ({ | ||
189 | - ...originData[i], | ||
190 | - rotationAngle: findAngle(before, after) + this.settings.rotationAngle, | ||
191 | - latitude: interpolation.x, | ||
192 | - longitude: interpolation.y | ||
193 | - }); | ||
194 | - j++; | 212 | + const latKeyName = this.settings.latKeyName; |
213 | + const lngKeyName = this.settings.lngKeyName; | ||
214 | + for (const data of originData) { | ||
215 | + const currentTime = data.time; | ||
216 | + const normalizeTime = this.minTime + Math.ceil((currentTime - this.minTime) / this.normalizationStep) * this.normalizationStep; | ||
217 | + result[normalizeTime] = { | ||
218 | + ...data, | ||
219 | + rotationAngle: this.settings.rotationAngle | ||
220 | + }; | ||
221 | + } | ||
222 | + const timeStamp = Object.keys(result); | ||
223 | + for (let i = 0; i < timeStamp.length - 1; i++) { | ||
224 | + result[timeStamp[i]].rotationAngle += findAngle(result[timeStamp[i]], result[timeStamp[i + 1]], latKeyName, lngKeyName) | ||
195 | } | 225 | } |
196 | return result; | 226 | return result; |
197 | } | 227 | } |
198 | } | 228 | } |
199 | 229 | ||
200 | export let TbTripAnimationWidget = TripAnimationComponent; | 230 | export let TbTripAnimationWidget = TripAnimationComponent; |
201 | - |
@@ -19,7 +19,7 @@ | @@ -19,7 +19,7 @@ | ||
19 | tb-fullscreen | 19 | tb-fullscreen |
20 | [fullscreen]="fullscreen" (fullscreenChanged)="onFullscreen()" fxLayout="column"> | 20 | [fullscreen]="fullscreen" (fullscreenChanged)="onFullscreen()" fxLayout="column"> |
21 | <div fxLayout="row" fxLayoutAlign="start center" style="height: 40px;" class="tb-json-content-toolbar"> | 21 | <div fxLayout="row" fxLayoutAlign="start center" style="height: 40px;" class="tb-json-content-toolbar"> |
22 | - <label class="tb-title no-padding">{{ label }}</label> | 22 | + <label class="tb-title no-padding" [ngClass]="{'tb-error': !contentValid}">{{ label }}</label> |
23 | <span fxFlex></span> | 23 | <span fxFlex></span> |
24 | <button type="button" | 24 | <button type="button" |
25 | mat-button *ngIf="!readonly && !disabled" class="tidy" (click)="beautifyJSON()"> | 25 | mat-button *ngIf="!readonly && !disabled" class="tidy" (click)="beautifyJSON()"> |
@@ -92,6 +92,15 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid | @@ -92,6 +92,15 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid | ||
92 | this.validateContentValue = coerceBooleanProperty(value); | 92 | this.validateContentValue = coerceBooleanProperty(value); |
93 | } | 93 | } |
94 | 94 | ||
95 | + private validateOnChangeValue: boolean; | ||
96 | + get validateOnChange(): boolean { | ||
97 | + return this.validateOnChangeValue; | ||
98 | + } | ||
99 | + @Input() | ||
100 | + set validateOnChange(value: boolean) { | ||
101 | + this.validateOnChangeValue = coerceBooleanProperty(value); | ||
102 | + } | ||
103 | + | ||
95 | fullscreen = false; | 104 | fullscreen = false; |
96 | 105 | ||
97 | contentBody: string; | 106 | contentBody: string; |
@@ -256,7 +265,7 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid | @@ -256,7 +265,7 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid | ||
256 | const editorValue = this.jsonEditor.getValue(); | 265 | const editorValue = this.jsonEditor.getValue(); |
257 | if (this.contentBody !== editorValue) { | 266 | if (this.contentBody !== editorValue) { |
258 | this.contentBody = editorValue; | 267 | this.contentBody = editorValue; |
259 | - this.contentValid = true; | 268 | + this.contentValid = !this.validateOnChange || this.doValidate(); |
260 | this.propagateChange(this.contentBody); | 269 | this.propagateChange(this.contentBody); |
261 | } | 270 | } |
262 | } | 271 | } |
@@ -117,6 +117,11 @@ export class KeyValMapComponent extends PageComponent implements ControlValueAcc | @@ -117,6 +117,11 @@ export class KeyValMapComponent extends PageComponent implements ControlValueAcc | ||
117 | this.valueChangeSubscription = this.kvListFormGroup.valueChanges.subscribe(() => { | 117 | this.valueChangeSubscription = this.kvListFormGroup.valueChanges.subscribe(() => { |
118 | this.updateModel(); | 118 | this.updateModel(); |
119 | }); | 119 | }); |
120 | + if (this.disabled) { | ||
121 | + this.kvListFormGroup.disable({emitEvent: false}); | ||
122 | + } else { | ||
123 | + this.kvListFormGroup.enable({emitEvent: false}); | ||
124 | + } | ||
120 | } | 125 | } |
121 | 126 | ||
122 | public removeKeyVal(index: number) { | 127 | public removeKeyVal(index: number) { |
@@ -27,8 +27,8 @@ | @@ -27,8 +27,8 @@ | ||
27 | <mat-slider [(ngModel)]="index" [min]="minTimeIndex" [max]="maxTimeIndex" (change)="changeIndex()"> | 27 | <mat-slider [(ngModel)]="index" [min]="minTimeIndex" [max]="maxTimeIndex" (change)="changeIndex()"> |
28 | </mat-slider> | 28 | </mat-slider> |
29 | <div class="panel-timer"> | 29 | <div class="panel-timer"> |
30 | - <span *ngIf="this.intervals[this.index]">{{ this.intervals[this.index] | date:'medium'}}</span> | ||
31 | - <span *ngIf="!this.intervals[this.index]">{{ "widget.no-data-found" | translate}}</span> | 30 | + <span *ngIf="this.currentTime">{{ this.currentTime | date:'medium'}}</span> |
31 | + <span *ngIf="!this.currentTime">{{ "widget.no-data-found" | translate}}</span> | ||
32 | </div> | 32 | </div> |
33 | </div> | 33 | </div> |
34 | <button mat-icon-button class="mat-icon-button" aria-label="Next" (click)="moveNext()"> | 34 | <button mat-icon-button class="mat-icon-button" aria-label="Next" (click)="moveNext()"> |
@@ -47,8 +47,9 @@ | @@ -47,8 +47,9 @@ | ||
47 | pause_circle_outline | 47 | pause_circle_outline |
48 | </mat-icon> | 48 | </mat-icon> |
49 | </button> | 49 | </button> |
50 | - <mat-select matInput [(ngModel)]="speed" (selectionChange)="reeneble()" class="speed-select" | 50 | + <mat-select [(ngModel)]="speed" (selectionChange)="reeneble()" class="speed-select" |
51 | aria-label="Speed selector"> | 51 | aria-label="Speed selector"> |
52 | <mat-option [value]="speedValue" *ngFor="let speedValue of speeds">{{speedValue}} </mat-option> | 52 | <mat-option [value]="speedValue" *ngFor="let speedValue of speeds">{{speedValue}} </mat-option> |
53 | </mat-select> | 53 | </mat-select> |
54 | - </div> | ||
54 | + </div> | ||
55 | +</div> |
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import { Component, OnInit, OnChanges, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core'; | 17 | +import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; |
18 | import { interval } from 'rxjs'; | 18 | import { interval } from 'rxjs'; |
19 | import { filter } from 'rxjs/operators'; | 19 | import { filter } from 'rxjs/operators'; |
20 | import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/maps/map-models'; | 20 | import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/maps/map-models'; |
@@ -27,13 +27,14 @@ import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/m | @@ -27,13 +27,14 @@ import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/m | ||
27 | export class HistorySelectorComponent implements OnInit, OnChanges { | 27 | export class HistorySelectorComponent implements OnInit, OnChanges { |
28 | 28 | ||
29 | @Input() settings: HistorySelectSettings | 29 | @Input() settings: HistorySelectSettings |
30 | - @Input() intervals = []; | 30 | + @Input() minTime: number; |
31 | + @Input() maxTime: number; | ||
32 | + @Input() step = 1000; | ||
31 | @Input() anchors = []; | 33 | @Input() anchors = []; |
32 | @Input() useAnchors = false; | 34 | @Input() useAnchors = false; |
33 | 35 | ||
34 | @Output() timeUpdated: EventEmitter<number> = new EventEmitter(); | 36 | @Output() timeUpdated: EventEmitter<number> = new EventEmitter(); |
35 | 37 | ||
36 | - animationTime; | ||
37 | minTimeIndex = 0; | 38 | minTimeIndex = 0; |
38 | maxTimeIndex = 0; | 39 | maxTimeIndex = 0; |
39 | speed = 1; | 40 | speed = 1; |
@@ -41,6 +42,7 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | @@ -41,6 +42,7 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | ||
41 | playing = false; | 42 | playing = false; |
42 | interval; | 43 | interval; |
43 | speeds = [1, 5, 10, 25]; | 44 | speeds = [1, 5, 10, 25]; |
45 | + currentTime = null; | ||
44 | 46 | ||
45 | 47 | ||
46 | constructor(private cd: ChangeDetectorRef) { } | 48 | constructor(private cd: ChangeDetectorRef) { } |
@@ -49,7 +51,8 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | @@ -49,7 +51,8 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | ||
49 | } | 51 | } |
50 | 52 | ||
51 | ngOnChanges() { | 53 | ngOnChanges() { |
52 | - this.maxTimeIndex = this.intervals?.length - 1; | 54 | + this.maxTimeIndex = Math.ceil((this.maxTime - this.minTime) / this.step); |
55 | + this.currentTime = this.minTime === Infinity ? null : this.minTime; | ||
53 | } | 56 | } |
54 | 57 | ||
55 | play() { | 58 | play() { |
@@ -59,17 +62,18 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | @@ -59,17 +62,18 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | ||
59 | .pipe( | 62 | .pipe( |
60 | filter(() => this.playing)).subscribe(() => { | 63 | filter(() => this.playing)).subscribe(() => { |
61 | this.index++; | 64 | this.index++; |
62 | - if (this.index < this.maxTimeIndex) { | 65 | + this.currentTime = this.minTime + this.index * this.step; |
66 | + if (this.index <= this.maxTimeIndex) { | ||
63 | this.cd.detectChanges(); | 67 | this.cd.detectChanges(); |
64 | - this.timeUpdated.emit(this.intervals[this.index]); | 68 | + this.timeUpdated.emit(this.currentTime); |
65 | } | 69 | } |
66 | else { | 70 | else { |
67 | this.interval.complete(); | 71 | this.interval.complete(); |
68 | } | 72 | } |
69 | }, err => { | 73 | }, err => { |
70 | - console.log(err); | 74 | + console.error(err); |
71 | }, () => { | 75 | }, () => { |
72 | - this.index = this.minTimeIndex; | 76 | + this.currentTime = this.index = this.minTimeIndex; |
73 | this.playing = false; | 77 | this.playing = false; |
74 | this.interval = null; | 78 | this.interval = null; |
75 | this.cd.detectChanges(); | 79 | this.cd.detectChanges(); |
@@ -87,18 +91,19 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | @@ -87,18 +91,19 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | ||
87 | 91 | ||
88 | pause() { | 92 | pause() { |
89 | this.playing = false; | 93 | this.playing = false; |
94 | + this.currentTime = this.minTime + this.index * this.step; | ||
90 | this.cd.detectChanges(); | 95 | this.cd.detectChanges(); |
91 | - this.timeUpdated.emit(this.intervals[this.index]); | 96 | + this.timeUpdated.emit(this.currentTime); |
92 | } | 97 | } |
93 | 98 | ||
94 | moveNext() { | 99 | moveNext() { |
95 | if (this.index < this.maxTimeIndex) { | 100 | if (this.index < this.maxTimeIndex) { |
96 | if (this.useAnchors) { | 101 | if (this.useAnchors) { |
97 | - const anchorIndex = this.findIndex(this.intervals[this.index], this.anchors)+1; | ||
98 | - this.index = this.findIndex(this.anchors[anchorIndex], this.intervals); | ||
99 | - } | ||
100 | - else | 102 | + const anchorIndex = this.findIndex(this.currentTime, this.anchors) + 1; |
103 | + this.index = Math.floor((this.anchors[anchorIndex] - this.minTime) / this.step); | ||
104 | + } else { | ||
101 | this.index++; | 105 | this.index++; |
106 | + } | ||
102 | } | 107 | } |
103 | this.pause(); | 108 | this.pause(); |
104 | } | 109 | } |
@@ -106,15 +111,23 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | @@ -106,15 +111,23 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | ||
106 | movePrev() { | 111 | movePrev() { |
107 | if (this.index > this.minTimeIndex) { | 112 | if (this.index > this.minTimeIndex) { |
108 | if (this.useAnchors) { | 113 | if (this.useAnchors) { |
109 | - const anchorIndex = this.findIndex(this.intervals[this.index], this.anchors) - 1; | ||
110 | - this.index = this.findIndex(this.anchors[anchorIndex], this.intervals); | ||
111 | - } | ||
112 | - else | 114 | + const anchorIndex = this.findIndex(this.currentTime, this.anchors) - 1; |
115 | + this.index = Math.floor((this.anchors[anchorIndex] - this.minTime) / this.step); | ||
116 | + } else { | ||
113 | this.index--; | 117 | this.index--; |
118 | + } | ||
114 | } | 119 | } |
115 | this.pause(); | 120 | this.pause(); |
116 | } | 121 | } |
117 | 122 | ||
123 | + findIndex(value: number, array: number[]): number { | ||
124 | + let i = 0; | ||
125 | + while (array[i] < value) { | ||
126 | + i++; | ||
127 | + } | ||
128 | + return i; | ||
129 | + } | ||
130 | + | ||
118 | moveStart() { | 131 | moveStart() { |
119 | this.index = this.minTimeIndex; | 132 | this.index = this.minTimeIndex; |
120 | this.pause(); | 133 | this.pause(); |
@@ -125,15 +138,8 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | @@ -125,15 +138,8 @@ export class HistorySelectorComponent implements OnInit, OnChanges { | ||
125 | this.pause(); | 138 | this.pause(); |
126 | } | 139 | } |
127 | 140 | ||
128 | - findIndex(value, array: any[]) { | ||
129 | - let i = 0; | ||
130 | - while (array[i] < value) { | ||
131 | - i++; | ||
132 | - }; | ||
133 | - return i; | ||
134 | - } | ||
135 | - | ||
136 | changeIndex() { | 141 | changeIndex() { |
137 | - this.timeUpdated.emit(this.intervals[this.index]); | 142 | + this.currentTime = this.minTime + this.index * this.step; |
143 | + this.timeUpdated.emit(this.currentTime); | ||
138 | } | 144 | } |
139 | } | 145 | } |
@@ -90,6 +90,14 @@ | @@ -90,6 +90,14 @@ | ||
90 | "timeout-invalid": "That doesn't look like a valid timeout.", | 90 | "timeout-invalid": "That doesn't look like a valid timeout.", |
91 | "enable-tls": "Enable TLS", | 91 | "enable-tls": "Enable TLS", |
92 | "tls-version": "TLS version", | 92 | "tls-version": "TLS version", |
93 | + "enable-proxy": "Enable proxy", | ||
94 | + "proxy-host": "Proxy host", | ||
95 | + "proxy-host-required": "Proxy host is required.", | ||
96 | + "proxy-port": "Proxy port", | ||
97 | + "proxy-port-required": "You must supply a proxy port.", | ||
98 | + "proxy-port-invalid": "That doesn't look like a valid proxy port.", | ||
99 | + "proxy-user": "Proxy user", | ||
100 | + "proxy-password": "Proxy password", | ||
93 | "send-test-mail": "Send test mail", | 101 | "send-test-mail": "Send test mail", |
94 | "security-settings": "Security settings", | 102 | "security-settings": "Security settings", |
95 | "password-policy": "Password policy", | 103 | "password-policy": "Password policy", |