Showing
129 changed files
with
1020 additions
and
741 deletions
... | ... | @@ -126,10 +126,6 @@ |
126 | 126 | <artifactId>jjwt</artifactId> |
127 | 127 | </dependency> |
128 | 128 | <dependency> |
129 | - <groupId>joda-time</groupId> | |
130 | - <artifactId>joda-time</artifactId> | |
131 | - </dependency> | |
132 | - <dependency> | |
133 | 129 | <groupId>org.apache.velocity</groupId> |
134 | 130 | <artifactId>velocity</artifactId> |
135 | 131 | </dependency> | ... | ... |
... | ... | @@ -112,9 +112,9 @@ |
112 | 112 | "templateHtml": "<tb-timeseries-table-widget \n table-id=\"tableId\"\n ctx=\"ctx\">\n</tb-timeseries-table-widget>", |
113 | 113 | "templateCss": "", |
114 | 114 | "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.tableId = \"table-\"+id;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.$broadcast('timeseries-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.onDestroy = function() {\n}", |
115 | - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"TimeseriesTableSettings\",\n \"properties\": {\n \"showTimestamp\": {\n \"title\": \"Display timestamp column\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTimestamp\"\n ]\n}", | |
115 | + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"TimeseriesTableSettings\",\n \"properties\": {\n \"showTimestamp\": {\n \"title\": \"Display timestamp column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n }, \n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTimestamp\",\n \"displayPagination\",\n \"defaultPageSize\"\n ]\n}", | |
116 | 116 | "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, rowData, filter)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", |
117 | - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', amount = percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":false,\"showLegend\":false}" | |
117 | + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', amount = percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true,\"displayPagination\":true,\"defaultPageSize\":10},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":false,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{}}" | |
118 | 118 | } |
119 | 119 | } |
120 | 120 | ] | ... | ... |
... | ... | @@ -62,6 +62,7 @@ public final class PluginProcessingContext implements PluginContext { |
62 | 62 | private static final Executor executor = Executors.newSingleThreadExecutor(); |
63 | 63 | public static final String CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION = "Customer user is not allowed to perform this operation!"; |
64 | 64 | public static final String SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION = "System administrator is not allowed to perform this operation!"; |
65 | + public static final String DEVICE_WITH_REQUESTED_ID_NOT_FOUND = "Device with requested id wasn't found!"; | |
65 | 66 | |
66 | 67 | private final SharedPluginProcessingContext pluginCtx; |
67 | 68 | private final Optional<PluginApiCallSecurityContext> securityCtx; |
... | ... | @@ -309,7 +310,7 @@ public final class PluginProcessingContext implements PluginContext { |
309 | 310 | ListenableFuture<Device> deviceFuture = pluginCtx.deviceService.findDeviceByIdAsync(new DeviceId(entityId.getId())); |
310 | 311 | Futures.addCallback(deviceFuture, getCallback(callback, device -> { |
311 | 312 | if (device == null) { |
312 | - return ValidationResult.entityNotFound("Device with requested id wasn't found!"); | |
313 | + return ValidationResult.entityNotFound(DEVICE_WITH_REQUESTED_ID_NOT_FOUND); | |
313 | 314 | } else { |
314 | 315 | if (!device.getTenantId().equals(ctx.getTenantId())) { |
315 | 316 | return ValidationResult.accessDenied("Device doesn't belong to the current Tenant!"); | ... | ... |
... | ... | @@ -47,8 +47,8 @@ public class WebSocketConfiguration implements WebSocketConfigurer { |
47 | 47 | @Bean |
48 | 48 | public ServletServerContainerFactoryBean createWebSocketContainer() { |
49 | 49 | ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); |
50 | - container.setMaxTextMessageBufferSize(8192); | |
51 | - container.setMaxBinaryMessageBufferSize(8192); | |
50 | + container.setMaxTextMessageBufferSize(32768); | |
51 | + container.setMaxBinaryMessageBufferSize(32768); | |
52 | 52 | return container; |
53 | 53 | } |
54 | 54 | ... | ... |
... | ... | @@ -82,7 +82,7 @@ public class CustomerController extends BaseController { |
82 | 82 | |
83 | 83 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
84 | 84 | @RequestMapping(value = "/customer", method = RequestMethod.POST) |
85 | - @ResponseBody | |
85 | + @ResponseBody | |
86 | 86 | public Customer saveCustomer(@RequestBody Customer customer) throws ThingsboardException { |
87 | 87 | try { |
88 | 88 | customer.setTenantId(getCurrentUser().getTenantId()); |
... | ... | @@ -107,7 +107,7 @@ public class CustomerController extends BaseController { |
107 | 107 | } |
108 | 108 | |
109 | 109 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
110 | - @RequestMapping(value = "/customers", params = { "limit" }, method = RequestMethod.GET) | |
110 | + @RequestMapping(value = "/customers", params = {"limit"}, method = RequestMethod.GET) | |
111 | 111 | @ResponseBody |
112 | 112 | public TextPageData<Customer> getCustomers(@RequestParam int limit, |
113 | 113 | @RequestParam(required = false) String textSearch, |
... | ... | @@ -122,4 +122,16 @@ public class CustomerController extends BaseController { |
122 | 122 | } |
123 | 123 | } |
124 | 124 | |
125 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | |
126 | + @RequestMapping(value = "/tenant/customers", params = {"customerTitle"}, method = RequestMethod.GET) | |
127 | + @ResponseBody | |
128 | + public Customer getTenantCustomer( | |
129 | + @RequestParam String customerTitle) throws ThingsboardException { | |
130 | + try { | |
131 | + TenantId tenantId = getCurrentUser().getTenantId(); | |
132 | + return checkNotNull(customerService.findCustomerByTenantIdAndTitle(tenantId, customerTitle)); | |
133 | + } catch (Exception e) { | |
134 | + throw handleException(e); | |
135 | + } | |
136 | + } | |
125 | 137 | } | ... | ... |
... | ... | @@ -77,7 +77,6 @@ public class PluginWebSocketHandler extends TextWebSocketHandler implements Plug |
77 | 77 | log.warn("[{}] Failed to find session", session.getId()); |
78 | 78 | session.close(CloseStatus.SERVER_ERROR.withReason("Session not found!")); |
79 | 79 | } |
80 | - session.sendMessage(message); | |
81 | 80 | } catch (IOException e) { |
82 | 81 | log.warn("IO error", e); |
83 | 82 | } | ... | ... |
... | ... | @@ -96,7 +96,7 @@ public class DefaultMailService implements MailService { |
96 | 96 | javaMailProperties.put(MAIL_PROP + protocol + ".port", jsonConfig.get("smtpPort").asText()); |
97 | 97 | javaMailProperties.put(MAIL_PROP + protocol + ".timeout", jsonConfig.get("timeout").asText()); |
98 | 98 | javaMailProperties.put(MAIL_PROP + protocol + ".auth", String.valueOf(StringUtils.isNotEmpty(jsonConfig.get("username").asText()))); |
99 | - javaMailProperties.put(MAIL_PROP + protocol + ".starttls.enable", jsonConfig.get("enableTls")); | |
99 | + javaMailProperties.put(MAIL_PROP + protocol + ".starttls.enable", jsonConfig.has("enableTls") ? jsonConfig.get("enableTls").asText() : "false"); | |
100 | 100 | return javaMailProperties; |
101 | 101 | } |
102 | 102 | ... | ... |
... | ... | @@ -20,7 +20,6 @@ import io.jsonwebtoken.Jws; |
20 | 20 | import io.jsonwebtoken.Jwts; |
21 | 21 | import io.jsonwebtoken.SignatureAlgorithm; |
22 | 22 | import org.apache.commons.lang3.StringUtils; |
23 | -import org.joda.time.DateTime; | |
24 | 23 | import org.springframework.beans.factory.annotation.Autowired; |
25 | 24 | import org.springframework.stereotype.Component; |
26 | 25 | import org.thingsboard.server.common.data.id.CustomerId; |
... | ... | @@ -31,7 +30,9 @@ import org.thingsboard.server.config.JwtSettings; |
31 | 30 | import org.thingsboard.server.service.security.model.SecurityUser; |
32 | 31 | import org.thingsboard.server.service.security.model.UserPrincipal; |
33 | 32 | |
34 | -import java.util.Arrays; | |
33 | +import java.time.ZonedDateTime; | |
34 | +import java.util.Collections; | |
35 | +import java.util.Date; | |
35 | 36 | import java.util.List; |
36 | 37 | import java.util.UUID; |
37 | 38 | import java.util.stream.Collectors; |
... | ... | @@ -81,13 +82,13 @@ public class JwtTokenFactory { |
81 | 82 | claims.put(CUSTOMER_ID, securityUser.getCustomerId().getId().toString()); |
82 | 83 | } |
83 | 84 | |
84 | - DateTime currentTime = new DateTime(); | |
85 | + ZonedDateTime currentTime = ZonedDateTime.now(); | |
85 | 86 | |
86 | 87 | String token = Jwts.builder() |
87 | 88 | .setClaims(claims) |
88 | 89 | .setIssuer(settings.getTokenIssuer()) |
89 | - .setIssuedAt(currentTime.toDate()) | |
90 | - .setExpiration(currentTime.plusSeconds(settings.getTokenExpirationTime()).toDate()) | |
90 | + .setIssuedAt(Date.from(currentTime.toInstant())) | |
91 | + .setExpiration(Date.from(currentTime.plusSeconds(settings.getTokenExpirationTime()).toInstant())) | |
91 | 92 | .signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey()) |
92 | 93 | .compact(); |
93 | 94 | |
... | ... | @@ -129,11 +130,11 @@ public class JwtTokenFactory { |
129 | 130 | throw new IllegalArgumentException("Cannot create JWT Token without username/email"); |
130 | 131 | } |
131 | 132 | |
132 | - DateTime currentTime = new DateTime(); | |
133 | + ZonedDateTime currentTime = ZonedDateTime.now(); | |
133 | 134 | |
134 | 135 | UserPrincipal principal = securityUser.getUserPrincipal(); |
135 | 136 | Claims claims = Jwts.claims().setSubject(principal.getValue()); |
136 | - claims.put(SCOPES, Arrays.asList(Authority.REFRESH_TOKEN.name())); | |
137 | + claims.put(SCOPES, Collections.singletonList(Authority.REFRESH_TOKEN.name())); | |
137 | 138 | claims.put(USER_ID, securityUser.getId().getId().toString()); |
138 | 139 | claims.put(IS_PUBLIC, principal.getType() == UserPrincipal.Type.PUBLIC_ID); |
139 | 140 | |
... | ... | @@ -141,8 +142,8 @@ public class JwtTokenFactory { |
141 | 142 | .setClaims(claims) |
142 | 143 | .setIssuer(settings.getTokenIssuer()) |
143 | 144 | .setId(UUID.randomUUID().toString()) |
144 | - .setIssuedAt(currentTime.toDate()) | |
145 | - .setExpiration(currentTime.plusSeconds(settings.getRefreshTokenExpTime()).toDate()) | |
145 | + .setIssuedAt(Date.from(currentTime.toInstant())) | |
146 | + .setExpiration(Date.from(currentTime.plusSeconds(settings.getRefreshTokenExpTime()).toInstant())) | |
146 | 147 | .signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey()) |
147 | 148 | .compact(); |
148 | 149 | ... | ... |
... | ... | @@ -106,6 +106,11 @@ public abstract class AbstractControllerTest { |
106 | 106 | protected static final String CUSTOMER_USER_EMAIL = "testcustomer@thingsboard.org"; |
107 | 107 | private static final String CUSTOMER_USER_PASSWORD = "customer"; |
108 | 108 | |
109 | + /** See {@link org.springframework.test.web.servlet.DefaultMvcResult#getAsyncResult(long)} | |
110 | + * and {@link org.springframework.mock.web.MockAsyncContext#getTimeout()} | |
111 | + */ | |
112 | + private static final long DEFAULT_TIMEOUT = -1L; | |
113 | + | |
109 | 114 | protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), |
110 | 115 | MediaType.APPLICATION_JSON.getSubtype(), |
111 | 116 | Charset.forName("utf8")); |
... | ... | @@ -336,7 +341,7 @@ public abstract class AbstractControllerTest { |
336 | 341 | } |
337 | 342 | |
338 | 343 | protected <T> T doPost(String urlTemplate, T content, Class<T> responseClass, ResultMatcher resultMatcher, String... params) throws Exception { |
339 | - return readResponse(doPost(urlTemplate, params).andExpect(resultMatcher), responseClass); | |
344 | + return readResponse(doPost(urlTemplate, content, params).andExpect(resultMatcher), responseClass); | |
340 | 345 | } |
341 | 346 | |
342 | 347 | protected <T> T doPost(String urlTemplate, T content, Class<T> responseClass, String... params) throws Exception { |
... | ... | @@ -344,7 +349,11 @@ public abstract class AbstractControllerTest { |
344 | 349 | } |
345 | 350 | |
346 | 351 | protected <T> T doPostAsync(String urlTemplate, T content, Class<T> responseClass, ResultMatcher resultMatcher, String... params) throws Exception { |
347 | - return readResponse(doPostAsync(urlTemplate, content, params).andExpect(resultMatcher), responseClass); | |
352 | + return readResponse(doPostAsync(urlTemplate, content, DEFAULT_TIMEOUT, params).andExpect(resultMatcher), responseClass); | |
353 | + } | |
354 | + | |
355 | + protected <T> T doPostAsync(String urlTemplate, T content, Class<T> responseClass, ResultMatcher resultMatcher, Long timeout, String... params) throws Exception { | |
356 | + return readResponse(doPostAsync(urlTemplate, content, timeout, params).andExpect(resultMatcher), responseClass); | |
348 | 357 | } |
349 | 358 | |
350 | 359 | protected <T> T doDelete(String urlTemplate, Class<T> responseClass, String... params) throws Exception { |
... | ... | @@ -366,12 +375,13 @@ public abstract class AbstractControllerTest { |
366 | 375 | return mockMvc.perform(postRequest); |
367 | 376 | } |
368 | 377 | |
369 | - protected <T> ResultActions doPostAsync(String urlTemplate, T content, String... params) throws Exception { | |
378 | + protected <T> ResultActions doPostAsync(String urlTemplate, T content, Long timeout, String... params) throws Exception { | |
370 | 379 | MockHttpServletRequestBuilder postRequest = post(urlTemplate); |
371 | 380 | setJwtToken(postRequest); |
372 | 381 | String json = json(content); |
373 | 382 | postRequest.contentType(contentType).content(json); |
374 | 383 | MvcResult result = mockMvc.perform(postRequest).andReturn(); |
384 | + result.getAsyncResult(timeout); | |
375 | 385 | return mockMvc.perform(asyncDispatch(result)); |
376 | 386 | } |
377 | 387 | |
... | ... | @@ -384,8 +394,8 @@ public abstract class AbstractControllerTest { |
384 | 394 | |
385 | 395 | protected void populateParams(MockHttpServletRequestBuilder request, String... params) { |
386 | 396 | if (params != null && params.length > 0) { |
387 | - Assert.assertEquals(params.length % 2, 0); | |
388 | - MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<String, String>(); | |
397 | + Assert.assertEquals(0, params.length % 2); | |
398 | + MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); | |
389 | 399 | for (int i = 0; i < params.length; i += 2) { |
390 | 400 | paramsMap.add(params[i], params[i + 1]); |
391 | 401 | } | ... | ... |
... | ... | @@ -15,21 +15,23 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.mqtt.rpc; |
17 | 17 | |
18 | +import java.util.Arrays; | |
19 | + | |
20 | +import com.datastax.driver.core.utils.UUIDs; | |
21 | +import com.fasterxml.jackson.core.type.TypeReference; | |
18 | 22 | import lombok.extern.slf4j.Slf4j; |
19 | 23 | import org.apache.commons.lang3.StringUtils; |
20 | 24 | import org.eclipse.paho.client.mqttv3.*; |
21 | 25 | import org.junit.*; |
22 | -import org.springframework.http.HttpStatus; | |
23 | -import org.springframework.web.client.HttpClientErrorException; | |
26 | +import org.thingsboard.server.actors.plugin.PluginProcessingContext; | |
24 | 27 | import org.thingsboard.server.common.data.Device; |
25 | 28 | import org.thingsboard.server.common.data.Tenant; |
26 | 29 | import org.thingsboard.server.common.data.User; |
30 | +import org.thingsboard.server.common.data.page.TextPageData; | |
31 | +import org.thingsboard.server.common.data.plugin.PluginMetaData; | |
27 | 32 | import org.thingsboard.server.common.data.security.Authority; |
28 | 33 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
29 | 34 | import org.thingsboard.server.controller.AbstractControllerTest; |
30 | -import org.thingsboard.server.dao.service.DaoNoSqlTest; | |
31 | - | |
32 | -import java.util.UUID; | |
33 | 35 | |
34 | 36 | import static org.junit.Assert.assertEquals; |
35 | 37 | import static org.junit.Assert.assertNotNull; |
... | ... | @@ -42,15 +44,19 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. |
42 | 44 | public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractControllerTest { |
43 | 45 | |
44 | 46 | private static final String MQTT_URL = "tcp://localhost:1883"; |
45 | - private static final String FAIL_MSG_IF_HTTP_CLIENT_ERROR_NOT_ENCOUNTERED = "HttpClientErrorException expected, but not encountered"; | |
47 | + private static final Long TIME_TO_HANDLE_REQUEST = 500L; | |
46 | 48 | |
47 | 49 | private Tenant savedTenant; |
48 | 50 | private User tenantAdmin; |
51 | + private Long asyncContextTimeoutToUseRpcPlugin; | |
52 | + | |
49 | 53 | |
50 | 54 | @Before |
51 | 55 | public void beforeTest() throws Exception { |
52 | 56 | loginSysAdmin(); |
53 | 57 | |
58 | + asyncContextTimeoutToUseRpcPlugin = getAsyncContextTimeoutToUseRpcPlugin(); | |
59 | + | |
54 | 60 | Tenant tenant = new Tenant(); |
55 | 61 | tenant.setTitle("My tenant"); |
56 | 62 | savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
... | ... | @@ -70,8 +76,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC |
70 | 76 | public void afterTest() throws Exception { |
71 | 77 | loginSysAdmin(); |
72 | 78 | if (savedTenant != null) { |
73 | - doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | |
74 | - .andExpect(status().isOk()); | |
79 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()).andExpect(status().isOk()); | |
75 | 80 | } |
76 | 81 | } |
77 | 82 | |
... | ... | @@ -102,7 +107,6 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC |
102 | 107 | } |
103 | 108 | |
104 | 109 | @Test |
105 | - @Ignore // TODO: figure out the right error code for this case. Ignored due to failure: expected 408 but was: 200 | |
106 | 110 | public void testServerMqttOneWayRpcDeviceOffline() throws Exception { |
107 | 111 | Device device = new Device(); |
108 | 112 | device.setName("Test One-Way Server-Side RPC Device Offline"); |
... | ... | @@ -115,29 +119,19 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC |
115 | 119 | |
116 | 120 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; |
117 | 121 | String deviceId = savedDevice.getId().getId().toString(); |
118 | - try { | |
119 | - doPost("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(408)); | |
120 | - Assert.fail(FAIL_MSG_IF_HTTP_CLIENT_ERROR_NOT_ENCOUNTERED); | |
121 | - } catch (HttpClientErrorException e) { | |
122 | - log.error(e.getMessage(), e); | |
123 | - Assert.assertEquals(HttpStatus.REQUEST_TIMEOUT, e.getStatusCode()); | |
124 | - Assert.assertEquals("408 null", e.getMessage()); | |
125 | - } | |
122 | + | |
123 | + doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isRequestTimeout(), | |
124 | + asyncContextTimeoutToUseRpcPlugin); | |
126 | 125 | } |
127 | 126 | |
128 | 127 | @Test |
129 | - @Ignore // TODO: figure out the right error code for this case. Ignored due to failure: expected 400 (404?) but was: 401 | |
130 | 128 | public void testServerMqttOneWayRpcDeviceDoesNotExist() throws Exception { |
131 | 129 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; |
132 | - String nonExistentDeviceId = UUID.randomUUID().toString(); | |
133 | - try { | |
134 | - doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, status().is(400)); | |
135 | - Assert.fail(FAIL_MSG_IF_HTTP_CLIENT_ERROR_NOT_ENCOUNTERED); | |
136 | - } catch (HttpClientErrorException e) { | |
137 | - log.error(e.getMessage(), e); | |
138 | - Assert.assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode()); | |
139 | - Assert.assertEquals("400 null", e.getMessage()); | |
140 | - } | |
130 | + String nonExistentDeviceId = UUIDs.timeBased().toString(); | |
131 | + | |
132 | + String result = doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
133 | + status().isNotFound()); | |
134 | + Assert.assertEquals(PluginProcessingContext.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); | |
141 | 135 | } |
142 | 136 | |
143 | 137 | @Test |
... | ... | @@ -168,7 +162,6 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC |
168 | 162 | } |
169 | 163 | |
170 | 164 | @Test |
171 | - @Ignore // TODO: figure out the right error code for this case. Ignored due to failure: expected 408 but was: 200 | |
172 | 165 | public void testServerMqttTwoWayRpcDeviceOffline() throws Exception { |
173 | 166 | Device device = new Device(); |
174 | 167 | device.setName("Test Two-Way Server-Side RPC Device Offline"); |
... | ... | @@ -181,29 +174,19 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC |
181 | 174 | |
182 | 175 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; |
183 | 176 | String deviceId = savedDevice.getId().getId().toString(); |
184 | - try { | |
185 | - doPost("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(408)); | |
186 | - Assert.fail(FAIL_MSG_IF_HTTP_CLIENT_ERROR_NOT_ENCOUNTERED); | |
187 | - } catch (HttpClientErrorException e) { | |
188 | - log.error(e.getMessage(), e); | |
189 | - Assert.assertEquals(HttpStatus.REQUEST_TIMEOUT, e.getStatusCode()); | |
190 | - Assert.assertEquals("408 null", e.getMessage()); | |
191 | - } | |
177 | + | |
178 | + doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isRequestTimeout(), | |
179 | + asyncContextTimeoutToUseRpcPlugin); | |
192 | 180 | } |
193 | 181 | |
194 | 182 | @Test |
195 | - @Ignore // TODO: figure out the right error code for this case. Ignored due to failure: expected 400 (404?) but was: 401 | |
196 | 183 | public void testServerMqttTwoWayRpcDeviceDoesNotExist() throws Exception { |
197 | 184 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; |
198 | - String nonExistentDeviceId = UUID.randomUUID().toString(); | |
199 | - try { | |
200 | - doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, status().is(400)); | |
201 | - Assert.fail(FAIL_MSG_IF_HTTP_CLIENT_ERROR_NOT_ENCOUNTERED); | |
202 | - } catch (HttpClientErrorException e) { | |
203 | - log.error(e.getMessage(), e); | |
204 | - Assert.assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode()); | |
205 | - Assert.assertEquals("400 null", e.getMessage()); | |
206 | - } | |
185 | + String nonExistentDeviceId = UUIDs.timeBased().toString(); | |
186 | + | |
187 | + String result = doPostAsync("/api/plugins/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class, | |
188 | + status().isNotFound()); | |
189 | + Assert.assertEquals(PluginProcessingContext.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); | |
207 | 190 | } |
208 | 191 | |
209 | 192 | private Device getSavedDevice(Device device) throws Exception { |
... | ... | @@ -214,6 +197,13 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC |
214 | 197 | return doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
215 | 198 | } |
216 | 199 | |
200 | + private Long getAsyncContextTimeoutToUseRpcPlugin() throws Exception { | |
201 | + TextPageData<PluginMetaData> plugins = doGetTyped("/api/plugin/system?limit=1&textSearch=system rpc plugin", | |
202 | + new TypeReference<TextPageData<PluginMetaData>>(){}); | |
203 | + Long systemRpcPluginTimeout = plugins.getData().iterator().next().getConfiguration().get("defaultTimeout").asLong(); | |
204 | + return systemRpcPluginTimeout + TIME_TO_HANDLE_REQUEST; | |
205 | + } | |
206 | + | |
217 | 207 | private static class TestMqttCallback implements MqttCallback { |
218 | 208 | |
219 | 209 | private final MqttAsyncClient client; |
... | ... | @@ -228,10 +218,10 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC |
228 | 218 | |
229 | 219 | @Override |
230 | 220 | public void messageArrived(String requestTopic, MqttMessage mqttMessage) throws Exception { |
231 | - log.info("Message Arrived: " + mqttMessage.getPayload().toString()); | |
221 | + log.info("Message Arrived: " + Arrays.toString(mqttMessage.getPayload())); | |
232 | 222 | MqttMessage message = new MqttMessage(); |
233 | 223 | String responseTopic = requestTopic.replace("request", "response"); |
234 | - message.setPayload("{\"value1\":\"A\", \"value2\":\"B\"}".getBytes()); | |
224 | + message.setPayload("{\"value1\":\"A\", \"value2\":\"B\"}".getBytes("UTF-8")); | |
235 | 225 | client.publish(responseTopic, message); |
236 | 226 | } |
237 | 227 | ... | ... |
... | ... | @@ -22,20 +22,24 @@ import org.thingsboard.server.common.data.id.TenantId; |
22 | 22 | import org.thingsboard.server.common.data.page.TextPageData; |
23 | 23 | import org.thingsboard.server.common.data.page.TextPageLink; |
24 | 24 | |
25 | +import java.util.Optional; | |
26 | + | |
25 | 27 | public interface CustomerService { |
26 | 28 | |
27 | 29 | Customer findCustomerById(CustomerId customerId); |
28 | 30 | |
31 | + Optional<Customer> findCustomerByTenantIdAndTitle(TenantId tenantId, String title); | |
32 | + | |
29 | 33 | ListenableFuture<Customer> findCustomerByIdAsync(CustomerId customerId); |
30 | 34 | |
31 | 35 | Customer saveCustomer(Customer customer); |
32 | - | |
36 | + | |
33 | 37 | void deleteCustomer(CustomerId customerId); |
34 | 38 | |
35 | 39 | Customer findOrCreatePublicCustomer(TenantId tenantId); |
36 | 40 | |
37 | 41 | TextPageData<Customer> findCustomersByTenantId(TenantId tenantId, TextPageLink pageLink); |
38 | - | |
42 | + | |
39 | 43 | void deleteCustomersByTenantId(TenantId tenantId); |
40 | 44 | |
41 | 45 | } | ... | ... |
... | ... | @@ -52,6 +52,7 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom |
52 | 52 | |
53 | 53 | private static final String PUBLIC_CUSTOMER_TITLE = "Public"; |
54 | 54 | public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; |
55 | + public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; | |
55 | 56 | |
56 | 57 | @Autowired |
57 | 58 | private CustomerDao customerDao; |
... | ... | @@ -79,6 +80,13 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom |
79 | 80 | } |
80 | 81 | |
81 | 82 | @Override |
83 | + public Optional<Customer> findCustomerByTenantIdAndTitle(TenantId tenantId, String title) { | |
84 | + log.trace("Executing findCustomerByTenantIdAndTitle [{}] [{}]", tenantId, title); | |
85 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
86 | + return customerDao.findCustomersByTenantIdAndTitle(tenantId.getId(), title); | |
87 | + } | |
88 | + | |
89 | + @Override | |
82 | 90 | public ListenableFuture<Customer> findCustomerByIdAsync(CustomerId customerId) { |
83 | 91 | log.trace("Executing findCustomerByIdAsync [{}]", customerId); |
84 | 92 | validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); | ... | ... |
... | ... | @@ -33,8 +33,7 @@ |
33 | 33 | <spring.version>4.3.4.RELEASE</spring.version> |
34 | 34 | <spring-security.version>4.2.0.RELEASE</spring-security.version> |
35 | 35 | <jjwt.version>0.7.0</jjwt.version> |
36 | - <joda-time.version>2.4</joda-time.version> | |
37 | - <json-path.version>2.2.0</json-path.version> | |
36 | + <json-path.version>2.2.0</json-path.version> | |
38 | 37 | <junit.version>4.12</junit.version> |
39 | 38 | <slf4j.version>1.7.7</slf4j.version> |
40 | 39 | <logback.version>1.2.3</logback.version> |
... | ... | @@ -484,11 +483,6 @@ |
484 | 483 | <version>${jjwt.version}</version> |
485 | 484 | </dependency> |
486 | 485 | <dependency> |
487 | - <groupId>joda-time</groupId> | |
488 | - <artifactId>joda-time</artifactId> | |
489 | - <version>${joda-time.version}</version> | |
490 | - </dependency> | |
491 | - <dependency> | |
492 | 486 | <groupId>org.apache.velocity</groupId> |
493 | 487 | <artifactId>velocity</artifactId> |
494 | 488 | <version>${velocity.version}</version> | ... | ... |
... | ... | @@ -29,13 +29,12 @@ import org.springframework.web.client.RestTemplate; |
29 | 29 | import org.thingsboard.server.common.data.Customer; |
30 | 30 | import org.thingsboard.server.common.data.Device; |
31 | 31 | import org.thingsboard.server.common.data.alarm.Alarm; |
32 | -import org.thingsboard.server.common.data.alarm.AlarmSeverity; | |
33 | -import org.thingsboard.server.common.data.alarm.AlarmStatus; | |
34 | 32 | import org.thingsboard.server.common.data.asset.Asset; |
35 | 33 | import org.thingsboard.server.common.data.id.AssetId; |
36 | 34 | import org.thingsboard.server.common.data.id.CustomerId; |
37 | 35 | import org.thingsboard.server.common.data.id.DeviceId; |
38 | 36 | import org.thingsboard.server.common.data.id.EntityId; |
37 | +import org.thingsboard.server.common.data.relation.EntityRelation; | |
39 | 38 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
40 | 39 | |
41 | 40 | import java.io.IOException; |
... | ... | @@ -78,6 +77,36 @@ public class RestClient implements ClientHttpRequestInterceptor { |
78 | 77 | } |
79 | 78 | } |
80 | 79 | |
80 | + public Optional<Customer> findCustomer(String title) { | |
81 | + Map<String, String> params = new HashMap<String, String>(); | |
82 | + params.put("customerTitle", title); | |
83 | + try { | |
84 | + ResponseEntity<Customer> customerEntity = restTemplate.getForEntity(baseURL + "/api/tenant/customers?customerTitle={customerTitle}", Customer.class, params); | |
85 | + return Optional.of(customerEntity.getBody()); | |
86 | + } catch (HttpClientErrorException exception) { | |
87 | + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { | |
88 | + return Optional.empty(); | |
89 | + } else { | |
90 | + throw exception; | |
91 | + } | |
92 | + } | |
93 | + } | |
94 | + | |
95 | + public Optional<Asset> findAsset(String name) { | |
96 | + Map<String, String> params = new HashMap<String, String>(); | |
97 | + params.put("assetName", name); | |
98 | + try { | |
99 | + ResponseEntity<Asset> assetEntity = restTemplate.getForEntity(baseURL + "/api/tenant/assets?assetName={assetName}", Asset.class, params); | |
100 | + return Optional.of(assetEntity.getBody()); | |
101 | + } catch (HttpClientErrorException exception) { | |
102 | + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { | |
103 | + return Optional.empty(); | |
104 | + } else { | |
105 | + throw exception; | |
106 | + } | |
107 | + } | |
108 | + } | |
109 | + | |
81 | 110 | public Customer createCustomer(String title) { |
82 | 111 | Customer customer = new Customer(); |
83 | 112 | customer.setTitle(title); |
... | ... | @@ -112,6 +141,14 @@ public class RestClient implements ClientHttpRequestInterceptor { |
112 | 141 | customerId.toString(), assetId.toString()).getBody(); |
113 | 142 | } |
114 | 143 | |
144 | + public EntityRelation makeRelation(String relationType, EntityId idFrom, EntityId idTo) { | |
145 | + EntityRelation relation = new EntityRelation(); | |
146 | + relation.setFrom(idFrom); | |
147 | + relation.setTo(idTo); | |
148 | + relation.setType(relationType); | |
149 | + return restTemplate.postForEntity(baseURL + "/api/relation", relation, EntityRelation.class).getBody(); | |
150 | + } | |
151 | + | |
115 | 152 | public DeviceCredentials getCredentials(DeviceId id) { |
116 | 153 | return restTemplate.getForEntity(baseURL + "/api/device/" + id.getId().toString() + "/credentials", DeviceCredentials.class).getBody(); |
117 | 154 | } | ... | ... |
... | ... | @@ -74,13 +74,13 @@ echo "Generating SSL Key Pair..." |
74 | 74 | |
75 | 75 | keytool -genkeypair -v \ |
76 | 76 | -alias $CLIENT_KEY_ALIAS \ |
77 | - -dname "CN=$DOMAIN_SUFFIX, OU=$ORGANIZATIONAL_UNIT, O=$ORGANIZATION, L=$CITY, ST=$STATE_OR_PROVINCE, C=$TWO_LETTER_COUNTRY_CODE" \ | |
78 | 77 | -keystore $CLIENT_FILE_PREFIX.jks \ |
79 | 78 | -keypass $CLIENT_KEY_PASSWORD \ |
80 | 79 | -storepass $CLIENT_KEYSTORE_PASSWORD \ |
81 | 80 | -keyalg RSA \ |
82 | 81 | -keysize 2048 \ |
83 | - -validity 9999 | |
82 | + -validity 9999 \ | |
83 | + -dname "CN=$DOMAIN_SUFFIX, OU=$ORGANIZATIONAL_UNIT, O=$ORGANIZATION, L=$CITY, ST=$STATE_OR_PROVINCE, C=$TWO_LETTER_COUNTRY_CODE" | |
84 | 84 | |
85 | 85 | echo "Converting keystore to pkcs12" |
86 | 86 | keytool -importkeystore \ | ... | ... |
... | ... | @@ -22,11 +22,11 @@ |
22 | 22 | <span translate class="md-headline">admin.general-settings</span> |
23 | 23 | </md-card-title-text> |
24 | 24 | </md-card-title> |
25 | - <md-progress-linear md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
26 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
25 | + <md-progress-linear md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
26 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
27 | 27 | <md-card-content> |
28 | 28 | <form name="vm.settingsForm" ng-submit="vm.save()" tb-confirm-on-exit confirm-form="vm.settingsForm"> |
29 | - <fieldset ng-disabled="loading"> | |
29 | + <fieldset ng-disabled="$root.loading"> | |
30 | 30 | <md-input-container class="md-block"> |
31 | 31 | <label translate>admin.base-url</label> |
32 | 32 | <input required name="baseUrl" ng-model="vm.settings.jsonValue.baseUrl"> |
... | ... | @@ -35,7 +35,7 @@ |
35 | 35 | </div> |
36 | 36 | </md-input-container> |
37 | 37 | <div layout="row" layout-align="end center" width="100%" layout-wrap> |
38 | - <md-button ng-disabled="loading || vm.settingsForm.$invalid || !vm.settingsForm.$dirty" type="submit" class="md-raised md-primary">{{'action.save' | translate}}</md-button> | |
38 | + <md-button ng-disabled="$root.loading || vm.settingsForm.$invalid || !vm.settingsForm.$dirty" type="submit" class="md-raised md-primary">{{'action.save' | translate}}</md-button> | |
39 | 39 | </div> |
40 | 40 | </fieldset> |
41 | 41 | </form> | ... | ... |
... | ... | @@ -24,11 +24,11 @@ |
24 | 24 | <div id="help-container"></div> |
25 | 25 | </md-card-title-text> |
26 | 26 | </md-card-title> |
27 | - <md-progress-linear md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
28 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
27 | + <md-progress-linear md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
28 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
29 | 29 | <md-card-content> |
30 | 30 | <form name="vm.settingsForm" ng-submit="vm.save()" tb-confirm-on-exit confirm-form="vm.settingsForm"> |
31 | - <fieldset ng-disabled="loading"> | |
31 | + <fieldset ng-disabled="$root.loading"> | |
32 | 32 | <md-input-container class="md-block"> |
33 | 33 | <label translate>admin.mail-from</label> |
34 | 34 | <input required name="mailFrom" ng-model="vm.settings.jsonValue.mailFrom"> |
... | ... | @@ -38,7 +38,7 @@ |
38 | 38 | </md-input-container> |
39 | 39 | <md-input-container class="md-block"> |
40 | 40 | <label translate>admin.smtp-protocol</label> |
41 | - <md-select ng-disabled="loading" ng-model="vm.settings.jsonValue.smtpProtocol"> | |
41 | + <md-select ng-disabled="$root.loading" ng-model="vm.settings.jsonValue.smtpProtocol"> | |
42 | 42 | <md-option ng-repeat="smtpProtocol in vm.smtpProtocols" value="{{smtpProtocol}}"> |
43 | 43 | {{smtpProtocol.toUpperCase()}} |
44 | 44 | </md-option> |
... | ... | @@ -78,7 +78,7 @@ |
78 | 78 | <div translate ng-message="md-maxlength">admin.timeout-invalid</div> |
79 | 79 | </div> |
80 | 80 | </md-input-container> |
81 | - <md-checkbox ng-disabled="loading" ng-true-value="'true'" ng-false-value="'false'" | |
81 | + <md-checkbox ng-disabled="$root.loading" ng-true-value="'true'" ng-false-value="'false'" | |
82 | 82 | aria-label="{{ 'admin.enable-tls' | translate }}" ng-model="vm.settings.jsonValue.enableTls">{{ 'admin.enable-tls' | translate }}</md-checkbox> |
83 | 83 | <md-input-container class="md-block"> |
84 | 84 | <label translate>common.username</label> |
... | ... | @@ -89,8 +89,8 @@ |
89 | 89 | <input name="password" placeholder="{{ 'common.enter-password' | translate }}" type="password" ng-model="vm.settings.jsonValue.password"> |
90 | 90 | </md-input-container> |
91 | 91 | <div layout="row" layout-align="end center" width="100%" layout-wrap> |
92 | - <md-button ng-disabled="loading || vm.settingsForm.$invalid" ng-click="vm.sendTestMail()" class="md-raised">{{'admin.send-test-mail' | translate}}</md-button> | |
93 | - <md-button ng-disabled="loading || vm.settingsForm.$invalid || !vm.settingsForm.$dirty" type="submit" class="md-raised md-primary">{{'action.save' | translate}}</md-button> | |
92 | + <md-button ng-disabled="$root.loading || vm.settingsForm.$invalid" ng-click="vm.sendTestMail()" class="md-raised">{{'admin.send-test-mail' | translate}}</md-button> | |
93 | + <md-button ng-disabled="$root.loading || vm.settingsForm.$invalid || !vm.settingsForm.$dirty" type="submit" class="md-raised md-primary">{{'action.save' | translate}}</md-button> | |
94 | 94 | </div> |
95 | 95 | </fieldset> |
96 | 96 | </form> | ... | ... |
... | ... | @@ -87,7 +87,7 @@ |
87 | 87 | <md-button ng-if="vm.allowAcknowledgment && (vm.alarm.status==vm.types.alarmStatus.activeUnack || |
88 | 88 | vm.alarm.status==vm.types.alarmStatus.clearedUnack)" |
89 | 89 | class="md-raised md-primary" |
90 | - ng-disabled="loading" | |
90 | + ng-disabled="$root.loading" | |
91 | 91 | ng-click="vm.acknowledge()" |
92 | 92 | style="margin-right:20px;">{{ 'alarm.acknowledge' | |
93 | 93 | translate }} |
... | ... | @@ -95,12 +95,12 @@ |
95 | 95 | <md-button ng-if="vm.allowClear && (vm.alarm.status==vm.types.alarmStatus.activeAck || |
96 | 96 | vm.alarm.status==vm.types.alarmStatus.activeUnack)" |
97 | 97 | class="md-raised md-primary" |
98 | - ng-disabled="loading" | |
98 | + ng-disabled="$root.loading" | |
99 | 99 | ng-click="vm.clear()">{{ 'alarm.clear' | |
100 | 100 | translate }} |
101 | 101 | </md-button> |
102 | 102 | <span flex></span> |
103 | - <md-button ng-disabled="loading" ng-click="vm.close()" style="margin-right:20px;">{{ 'action.close' | | |
103 | + <md-button ng-disabled="$root.loading" ng-click="vm.close()" style="margin-right:20px;">{{ 'action.close' | | |
104 | 104 | translate }} |
105 | 105 | </md-button> |
106 | 106 | </md-dialog-actions> | ... | ... |
... | ... | @@ -19,7 +19,7 @@ |
19 | 19 | <section layout="row"> |
20 | 20 | <md-input-container class="md-block" style="width: 200px;"> |
21 | 21 | <label translate>alarm.alarm-status</label> |
22 | - <md-select ng-model="alarmSearchStatus" ng-disabled="loading()"> | |
22 | + <md-select ng-model="alarmSearchStatus" ng-disabled="$root.loading"> | |
23 | 23 | <md-option ng-repeat="searchStatus in types.alarmSearchStatus" ng-value="searchStatus"> |
24 | 24 | {{ ('alarm.search-status.' + searchStatus) | translate }} |
25 | 25 | </md-option> |
... | ... | @@ -31,8 +31,8 @@ |
31 | 31 | <md-list flex layout="column" class="tb-alarm-table"> |
32 | 32 | <md-list class="tb-row tb-header" layout="row" tb-alarm-header> |
33 | 33 | </md-list> |
34 | - <md-progress-linear style="max-height: 0px;" md-mode="indeterminate" ng-disabled="!loading()" | |
35 | - ng-show="loading()"></md-progress-linear> | |
34 | + <md-progress-linear style="max-height: 0px;" md-mode="indeterminate" ng-disabled="!$root.loading" | |
35 | + ng-show="$root.loading"></md-progress-linear> | |
36 | 36 | <md-divider></md-divider> |
37 | 37 | <span translate layout-align="center center" |
38 | 38 | style="margin-top: 25px;" | ... | ... |
... | ... | @@ -265,10 +265,10 @@ function AssetService($http, $q, customerService, userService) { |
265 | 265 | return deferred.promise; |
266 | 266 | } |
267 | 267 | |
268 | - function getAssetTypes() { | |
268 | + function getAssetTypes(config) { | |
269 | 269 | var deferred = $q.defer(); |
270 | 270 | var url = '/api/asset/types'; |
271 | - $http.get(url).then(function success(response) { | |
271 | + $http.get(url, config).then(function success(response) { | |
272 | 272 | deferred.resolve(response.data); |
273 | 273 | }, function fail() { |
274 | 274 | deferred.reject(); | ... | ... |
... | ... | @@ -35,7 +35,7 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService) |
35 | 35 | |
36 | 36 | return service; |
37 | 37 | |
38 | - function getEntityKeys(entityType, entityId, query, type) { | |
38 | + function getEntityKeys(entityType, entityId, query, type, config) { | |
39 | 39 | var deferred = $q.defer(); |
40 | 40 | var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/keys/'; |
41 | 41 | if (type === types.dataKeyType.timeseries) { |
... | ... | @@ -43,7 +43,7 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService) |
43 | 43 | } else if (type === types.dataKeyType.attribute) { |
44 | 44 | url += 'attributes'; |
45 | 45 | } |
46 | - $http.get(url, null).then(function success(response) { | |
46 | + $http.get(url, config).then(function success(response) { | |
47 | 47 | var result = []; |
48 | 48 | if (response.data) { |
49 | 49 | if (query) { | ... | ... |
... | ... | @@ -32,7 +32,7 @@ function CustomerService($http, $q, types) { |
32 | 32 | |
33 | 33 | return service; |
34 | 34 | |
35 | - function getCustomers(pageLink) { | |
35 | + function getCustomers(pageLink, config) { | |
36 | 36 | var deferred = $q.defer(); |
37 | 37 | var url = '/api/customers?limit=' + pageLink.limit; |
38 | 38 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -44,7 +44,7 @@ function CustomerService($http, $q, types) { |
44 | 44 | if (angular.isDefined(pageLink.textOffset)) { |
45 | 45 | url += '&textOffset=' + pageLink.textOffset; |
46 | 46 | } |
47 | - $http.get(url, null).then(function success(response) { | |
47 | + $http.get(url, config).then(function success(response) { | |
48 | 48 | deferred.resolve(response.data); |
49 | 49 | }, function fail() { |
50 | 50 | deferred.reject(); |
... | ... | @@ -52,10 +52,10 @@ function CustomerService($http, $q, types) { |
52 | 52 | return deferred.promise; |
53 | 53 | } |
54 | 54 | |
55 | - function getCustomer(customerId) { | |
55 | + function getCustomer(customerId, config) { | |
56 | 56 | var deferred = $q.defer(); |
57 | 57 | var url = '/api/customer/' + customerId; |
58 | - $http.get(url, null).then(function success(response) { | |
58 | + $http.get(url, config).then(function success(response) { | |
59 | 59 | deferred.resolve(response.data); |
60 | 60 | }, function fail(response) { |
61 | 61 | deferred.reject(response.data); | ... | ... |
... | ... | @@ -43,7 +43,7 @@ function DashboardService($rootScope, $http, $q, $location, customerService) { |
43 | 43 | |
44 | 44 | return service; |
45 | 45 | |
46 | - function getTenantDashboardsByTenantId(tenantId, pageLink) { | |
46 | + function getTenantDashboardsByTenantId(tenantId, pageLink, config) { | |
47 | 47 | var deferred = $q.defer(); |
48 | 48 | var url = '/api/tenant/' + tenantId + '/dashboards?limit=' + pageLink.limit; |
49 | 49 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -55,7 +55,7 @@ function DashboardService($rootScope, $http, $q, $location, customerService) { |
55 | 55 | if (angular.isDefined(pageLink.textOffset)) { |
56 | 56 | url += '&textOffset=' + pageLink.textOffset; |
57 | 57 | } |
58 | - $http.get(url, null).then(function success(response) { | |
58 | + $http.get(url, config).then(function success(response) { | |
59 | 59 | deferred.resolve(response.data); |
60 | 60 | }, function fail() { |
61 | 61 | deferred.reject(); |
... | ... | @@ -63,7 +63,7 @@ function DashboardService($rootScope, $http, $q, $location, customerService) { |
63 | 63 | return deferred.promise; |
64 | 64 | } |
65 | 65 | |
66 | - function getTenantDashboards(pageLink, applyCustomersInfo) { | |
66 | + function getTenantDashboards(pageLink, applyCustomersInfo, config) { | |
67 | 67 | var deferred = $q.defer(); |
68 | 68 | var url = '/api/tenant/dashboards?limit=' + pageLink.limit; |
69 | 69 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -75,7 +75,7 @@ function DashboardService($rootScope, $http, $q, $location, customerService) { |
75 | 75 | if (angular.isDefined(pageLink.textOffset)) { |
76 | 76 | url += '&textOffset=' + pageLink.textOffset; |
77 | 77 | } |
78 | - $http.get(url, null).then(function success(response) { | |
78 | + $http.get(url, config).then(function success(response) { | |
79 | 79 | if (applyCustomersInfo) { |
80 | 80 | customerService.applyAssignedCustomersInfo(response.data.data).then( |
81 | 81 | function success(data) { |
... | ... | @@ -95,7 +95,7 @@ function DashboardService($rootScope, $http, $q, $location, customerService) { |
95 | 95 | return deferred.promise; |
96 | 96 | } |
97 | 97 | |
98 | - function getCustomerDashboards(customerId, pageLink, applyCustomersInfo) { | |
98 | + function getCustomerDashboards(customerId, pageLink, applyCustomersInfo, config) { | |
99 | 99 | var deferred = $q.defer(); |
100 | 100 | var url = '/api/customer/' + customerId + '/dashboards?limit=' + pageLink.limit; |
101 | 101 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -107,7 +107,7 @@ function DashboardService($rootScope, $http, $q, $location, customerService) { |
107 | 107 | if (angular.isDefined(pageLink.textOffset)) { |
108 | 108 | url += '&textOffset=' + pageLink.textOffset; |
109 | 109 | } |
110 | - $http.get(url, null).then(function success(response) { | |
110 | + $http.get(url, config).then(function success(response) { | |
111 | 111 | if (applyCustomersInfo) { |
112 | 112 | customerService.applyAssignedCustomerInfo(response.data.data, customerId).then( |
113 | 113 | function success(data) { |
... | ... | @@ -158,10 +158,10 @@ function DashboardService($rootScope, $http, $q, $location, customerService) { |
158 | 158 | return deferred.promise; |
159 | 159 | } |
160 | 160 | |
161 | - function getDashboardInfo(dashboardId) { | |
161 | + function getDashboardInfo(dashboardId, config) { | |
162 | 162 | var deferred = $q.defer(); |
163 | 163 | var url = '/api/dashboard/info/' + dashboardId; |
164 | - $http.get(url, null).then(function success(response) { | |
164 | + $http.get(url, config).then(function success(response) { | |
165 | 165 | deferred.resolve(response.data); |
166 | 166 | }, function fail() { |
167 | 167 | deferred.reject(); | ... | ... |
... | ... | @@ -293,10 +293,10 @@ function DeviceService($http, $q, attributeService, customerService, types) { |
293 | 293 | return deferred.promise; |
294 | 294 | } |
295 | 295 | |
296 | - function getDeviceTypes() { | |
296 | + function getDeviceTypes(config) { | |
297 | 297 | var deferred = $q.defer(); |
298 | 298 | var url = '/api/device/types'; |
299 | - $http.get(url).then(function success(response) { | |
299 | + $http.get(url, config).then(function success(response) { | |
300 | 300 | deferred.resolve(response.data); |
301 | 301 | }, function fail() { |
302 | 302 | deferred.reject(); | ... | ... |
... | ... | @@ -175,10 +175,10 @@ function EntityRelationService($http, $q) { |
175 | 175 | return deferred.promise; |
176 | 176 | } |
177 | 177 | |
178 | - function findInfoByQuery(query) { | |
178 | + function findInfoByQuery(query, config) { | |
179 | 179 | var deferred = $q.defer(); |
180 | 180 | var url = '/api/relations/info'; |
181 | - $http.post(url, query).then(function success(response) { | |
181 | + $http.post(url, query, config).then(function success(response) { | |
182 | 182 | deferred.resolve(response.data); |
183 | 183 | }, function fail() { |
184 | 184 | deferred.reject(); | ... | ... |
... | ... | @@ -56,22 +56,22 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
56 | 56 | promise = assetService.getAsset(entityId, true, config); |
57 | 57 | break; |
58 | 58 | case types.entityType.tenant: |
59 | - promise = tenantService.getTenant(entityId); | |
59 | + promise = tenantService.getTenant(entityId, config); | |
60 | 60 | break; |
61 | 61 | case types.entityType.customer: |
62 | - promise = customerService.getCustomer(entityId); | |
62 | + promise = customerService.getCustomer(entityId, config); | |
63 | 63 | break; |
64 | 64 | case types.entityType.rule: |
65 | - promise = ruleService.getRule(entityId); | |
65 | + promise = ruleService.getRule(entityId, config); | |
66 | 66 | break; |
67 | 67 | case types.entityType.plugin: |
68 | - promise = pluginService.getPlugin(entityId); | |
68 | + promise = pluginService.getPlugin(entityId, config); | |
69 | 69 | break; |
70 | 70 | case types.entityType.dashboard: |
71 | - promise = dashboardService.getDashboardInfo(entityId); | |
71 | + promise = dashboardService.getDashboardInfo(entityId, config); | |
72 | 72 | break; |
73 | 73 | case types.entityType.user: |
74 | - promise = userService.getUser(entityId); | |
74 | + promise = userService.getUser(entityId, true, config); | |
75 | 75 | break; |
76 | 76 | case types.entityType.alarm: |
77 | 77 | $log.error('Get Alarm Entity is not implemented!'); |
... | ... | @@ -136,22 +136,28 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
136 | 136 | promise = assetService.getAssets(entityIds, config); |
137 | 137 | break; |
138 | 138 | case types.entityType.tenant: |
139 | - promise = getEntitiesByIdsPromise(tenantService.getTenant, entityIds); | |
139 | + promise = getEntitiesByIdsPromise( | |
140 | + (id) => tenantService.getTenant(id, config), entityIds); | |
140 | 141 | break; |
141 | 142 | case types.entityType.customer: |
142 | - promise = getEntitiesByIdsPromise(customerService.getCustomer, entityIds); | |
143 | + promise = getEntitiesByIdsPromise( | |
144 | + (id) => customerService.getCustomer(id, config), entityIds); | |
143 | 145 | break; |
144 | 146 | case types.entityType.rule: |
145 | - promise = getEntitiesByIdsPromise(ruleService.getRule, entityIds); | |
147 | + promise = getEntitiesByIdsPromise( | |
148 | + (id) => ruleService.getRule(id, config), entityIds); | |
146 | 149 | break; |
147 | 150 | case types.entityType.plugin: |
148 | - promise = getEntitiesByIdsPromise(pluginService.getPlugin, entityIds); | |
151 | + promise = getEntitiesByIdsPromise( | |
152 | + (id) => pluginService.getPlugin(id, config), entityIds); | |
149 | 153 | break; |
150 | 154 | case types.entityType.dashboard: |
151 | - promise = getEntitiesByIdsPromise(dashboardService.getDashboardInfo, entityIds); | |
155 | + promise = getEntitiesByIdsPromise( | |
156 | + (id) => dashboardService.getDashboardInfo(id, config), entityIds); | |
152 | 157 | break; |
153 | 158 | case types.entityType.user: |
154 | - promise = getEntitiesByIdsPromise(userService.getUser, entityIds); | |
159 | + promise = getEntitiesByIdsPromise( | |
160 | + (id) => userService.getUser(id, true, config), entityIds); | |
155 | 161 | break; |
156 | 162 | case types.entityType.alarm: |
157 | 163 | $log.error('Get Alarm Entity is not implemented!'); |
... | ... | @@ -178,11 +184,11 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
178 | 184 | return deferred.promise; |
179 | 185 | } |
180 | 186 | |
181 | - function getSingleTenantByPageLinkPromise(pageLink) { | |
187 | + function getSingleTenantByPageLinkPromise(pageLink, config) { | |
182 | 188 | var user = userService.getCurrentUser(); |
183 | 189 | var tenantId = user.tenantId; |
184 | 190 | var deferred = $q.defer(); |
185 | - tenantService.getTenant(tenantId).then( | |
191 | + tenantService.getTenant(tenantId, config).then( | |
186 | 192 | function success(tenant) { |
187 | 193 | var tenantName = tenant.name; |
188 | 194 | var result = { |
... | ... | @@ -202,11 +208,11 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
202 | 208 | return deferred.promise; |
203 | 209 | } |
204 | 210 | |
205 | - function getSingleCustomerByPageLinkPromise(pageLink) { | |
211 | + function getSingleCustomerByPageLinkPromise(pageLink, config) { | |
206 | 212 | var user = userService.getCurrentUser(); |
207 | 213 | var customerId = user.customerId; |
208 | 214 | var deferred = $q.defer(); |
209 | - customerService.getCustomer(customerId).then( | |
215 | + customerService.getCustomer(customerId, config).then( | |
210 | 216 | function success(customer) { |
211 | 217 | var customerName = customer.name; |
212 | 218 | var result = { |
... | ... | @@ -247,29 +253,29 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
247 | 253 | break; |
248 | 254 | case types.entityType.tenant: |
249 | 255 | if (user.authority === 'TENANT_ADMIN') { |
250 | - promise = getSingleTenantByPageLinkPromise(pageLink); | |
256 | + promise = getSingleTenantByPageLinkPromise(pageLink, config); | |
251 | 257 | } else { |
252 | - promise = tenantService.getTenants(pageLink); | |
258 | + promise = tenantService.getTenants(pageLink, config); | |
253 | 259 | } |
254 | 260 | break; |
255 | 261 | case types.entityType.customer: |
256 | 262 | if (user.authority === 'CUSTOMER_USER') { |
257 | - promise = getSingleCustomerByPageLinkPromise(pageLink); | |
263 | + promise = getSingleCustomerByPageLinkPromise(pageLink, config); | |
258 | 264 | } else { |
259 | - promise = customerService.getCustomers(pageLink); | |
265 | + promise = customerService.getCustomers(pageLink, config); | |
260 | 266 | } |
261 | 267 | break; |
262 | 268 | case types.entityType.rule: |
263 | - promise = ruleService.getAllRules(pageLink); | |
269 | + promise = ruleService.getAllRules(pageLink, config); | |
264 | 270 | break; |
265 | 271 | case types.entityType.plugin: |
266 | - promise = pluginService.getAllPlugins(pageLink); | |
272 | + promise = pluginService.getAllPlugins(pageLink, config); | |
267 | 273 | break; |
268 | 274 | case types.entityType.dashboard: |
269 | 275 | if (user.authority === 'CUSTOMER_USER') { |
270 | - promise = dashboardService.getCustomerDashboards(customerId, pageLink, false); | |
276 | + promise = dashboardService.getCustomerDashboards(customerId, pageLink, false, config); | |
271 | 277 | } else { |
272 | - promise = dashboardService.getTenantDashboards(pageLink, false); | |
278 | + promise = dashboardService.getTenantDashboards(pageLink, false, config); | |
273 | 279 | } |
274 | 280 | break; |
275 | 281 | case types.entityType.user: |
... | ... | @@ -426,7 +432,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
426 | 432 | var stateEntityId = getStateEntityId(filter, stateParams); |
427 | 433 | switch (filter.type) { |
428 | 434 | case types.aliasFilterType.singleEntity.value: |
429 | - getEntity(filter.singleEntity.entityType, filter.singleEntity.id).then( | |
435 | + getEntity(filter.singleEntity.entityType, filter.singleEntity.id, {ignoreLoading: true}).then( | |
430 | 436 | function success(entity) { |
431 | 437 | result.entities = entitiesToEntitiesInfo([entity]); |
432 | 438 | deferred.resolve(result); |
... | ... | @@ -437,7 +443,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
437 | 443 | ); |
438 | 444 | break; |
439 | 445 | case types.aliasFilterType.entityList.value: |
440 | - getEntities(filter.entityType, filter.entityList).then( | |
446 | + getEntities(filter.entityType, filter.entityList, {ignoreLoading: true}).then( | |
441 | 447 | function success(entities) { |
442 | 448 | if (entities && entities.length || !failOnEmpty) { |
443 | 449 | result.entities = entitiesToEntitiesInfo(entities); |
... | ... | @@ -452,7 +458,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
452 | 458 | ); |
453 | 459 | break; |
454 | 460 | case types.aliasFilterType.entityName.value: |
455 | - getEntitiesByNameFilter(filter.entityType, filter.entityNameFilter, maxItems).then( | |
461 | + getEntitiesByNameFilter(filter.entityType, filter.entityNameFilter, maxItems, {ignoreLoading: true}).then( | |
456 | 462 | function success(entities) { |
457 | 463 | if (entities && entities.length || !failOnEmpty) { |
458 | 464 | result.entities = entitiesToEntitiesInfo(entities); |
... | ... | @@ -469,7 +475,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
469 | 475 | case types.aliasFilterType.stateEntity.value: |
470 | 476 | result.stateEntity = true; |
471 | 477 | if (stateEntityId) { |
472 | - getEntity(stateEntityId.entityType, stateEntityId.id).then( | |
478 | + getEntity(stateEntityId.entityType, stateEntityId.id, {ignoreLoading: true}).then( | |
473 | 479 | function success(entity) { |
474 | 480 | result.entities = entitiesToEntitiesInfo([entity]); |
475 | 481 | deferred.resolve(result); |
... | ... | @@ -483,7 +489,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
483 | 489 | } |
484 | 490 | break; |
485 | 491 | case types.aliasFilterType.assetType.value: |
486 | - getEntitiesByNameFilter(types.entityType.asset, filter.assetNameFilter, maxItems, null, filter.assetType).then( | |
492 | + getEntitiesByNameFilter(types.entityType.asset, filter.assetNameFilter, maxItems, {ignoreLoading: true}, filter.assetType).then( | |
487 | 493 | function success(entities) { |
488 | 494 | if (entities && entities.length || !failOnEmpty) { |
489 | 495 | result.entities = entitiesToEntitiesInfo(entities); |
... | ... | @@ -498,7 +504,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
498 | 504 | ); |
499 | 505 | break; |
500 | 506 | case types.aliasFilterType.deviceType.value: |
501 | - getEntitiesByNameFilter(types.entityType.device, filter.deviceNameFilter, maxItems, null, filter.deviceType).then( | |
507 | + getEntitiesByNameFilter(types.entityType.device, filter.deviceNameFilter, maxItems, {ignoreLoading: true}, filter.deviceType).then( | |
502 | 508 | function success(entities) { |
503 | 509 | if (entities && entities.length || !failOnEmpty) { |
504 | 510 | result.entities = entitiesToEntitiesInfo(entities); |
... | ... | @@ -533,7 +539,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
533 | 539 | filters: filter.filters |
534 | 540 | }; |
535 | 541 | searchQuery.parameters.maxLevel = filter.maxLevel && filter.maxLevel > 0 ? filter.maxLevel : -1; |
536 | - entityRelationService.findInfoByQuery(searchQuery).then( | |
542 | + entityRelationService.findInfoByQuery(searchQuery, {ignoreLoading: true}).then( | |
537 | 543 | function success(allRelations) { |
538 | 544 | if (allRelations && allRelations.length || !failOnEmpty) { |
539 | 545 | if (angular.isDefined(maxItems) && maxItems > 0 && allRelations) { |
... | ... | @@ -577,10 +583,10 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
577 | 583 | var findByQueryPromise; |
578 | 584 | if (filter.type == types.aliasFilterType.assetSearchQuery.value) { |
579 | 585 | searchQuery.assetTypes = filter.assetTypes; |
580 | - findByQueryPromise = assetService.findByQuery(searchQuery, false); | |
586 | + findByQueryPromise = assetService.findByQuery(searchQuery, false, {ignoreLoading: true}); | |
581 | 587 | } else if (filter.type == types.aliasFilterType.deviceSearchQuery.value) { |
582 | 588 | searchQuery.deviceTypes = filter.deviceTypes; |
583 | - findByQueryPromise = deviceService.findByQuery(searchQuery, false); | |
589 | + findByQueryPromise = deviceService.findByQuery(searchQuery, false, {ignoreLoading: true}); | |
584 | 590 | } |
585 | 591 | findByQueryPromise.then( |
586 | 592 | function success(entities) { |
... | ... | @@ -762,7 +768,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
762 | 768 | return deferred.promise; |
763 | 769 | } |
764 | 770 | |
765 | - function getEntityKeys(entityType, entityId, query, type) { | |
771 | + function getEntityKeys(entityType, entityId, query, type, config) { | |
766 | 772 | var deferred = $q.defer(); |
767 | 773 | var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/keys/'; |
768 | 774 | if (type === types.dataKeyType.timeseries) { |
... | ... | @@ -770,7 +776,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device |
770 | 776 | } else if (type === types.dataKeyType.attribute) { |
771 | 777 | url += 'attributes'; |
772 | 778 | } |
773 | - $http.get(url, null).then(function success(response) { | |
779 | + $http.get(url, config).then(function success(response) { | |
774 | 780 | var result = []; |
775 | 781 | if (response.data) { |
776 | 782 | if (query) { | ... | ... |
... | ... | @@ -50,11 +50,11 @@ function PluginService($http, $q, $rootScope, $filter, componentDescriptorServic |
50 | 50 | tenantPlugins = undefined; |
51 | 51 | } |
52 | 52 | |
53 | - function loadPluginsCache() { | |
53 | + function loadPluginsCache(config) { | |
54 | 54 | var deferred = $q.defer(); |
55 | 55 | if (!allPlugins) { |
56 | 56 | var url = '/api/plugins'; |
57 | - $http.get(url, null).then(function success(response) { | |
57 | + $http.get(url, config).then(function success(response) { | |
58 | 58 | componentDescriptorService.getComponentDescriptorsByType(types.componentType.plugin).then( |
59 | 59 | function success(pluginComponents) { |
60 | 60 | allPlugins = response.data; |
... | ... | @@ -93,9 +93,9 @@ function PluginService($http, $q, $rootScope, $filter, componentDescriptorServic |
93 | 93 | return deferred.promise; |
94 | 94 | } |
95 | 95 | |
96 | - function getSystemPlugins(pageLink) { | |
96 | + function getSystemPlugins(pageLink, config) { | |
97 | 97 | var deferred = $q.defer(); |
98 | - loadPluginsCache().then( | |
98 | + loadPluginsCache(config).then( | |
99 | 99 | function success() { |
100 | 100 | utils.filterSearchTextEntities(systemPlugins, 'name', pageLink, deferred); |
101 | 101 | }, |
... | ... | @@ -106,9 +106,9 @@ function PluginService($http, $q, $rootScope, $filter, componentDescriptorServic |
106 | 106 | return deferred.promise; |
107 | 107 | } |
108 | 108 | |
109 | - function getTenantPlugins(pageLink) { | |
109 | + function getTenantPlugins(pageLink, config) { | |
110 | 110 | var deferred = $q.defer(); |
111 | - loadPluginsCache().then( | |
111 | + loadPluginsCache(config).then( | |
112 | 112 | function success() { |
113 | 113 | utils.filterSearchTextEntities(tenantPlugins, 'name', pageLink, deferred); |
114 | 114 | }, |
... | ... | @@ -119,9 +119,9 @@ function PluginService($http, $q, $rootScope, $filter, componentDescriptorServic |
119 | 119 | return deferred.promise; |
120 | 120 | } |
121 | 121 | |
122 | - function getAllActionPlugins(pageLink) { | |
122 | + function getAllActionPlugins(pageLink, config) { | |
123 | 123 | var deferred = $q.defer(); |
124 | - loadPluginsCache().then( | |
124 | + loadPluginsCache(config).then( | |
125 | 125 | function success() { |
126 | 126 | utils.filterSearchTextEntities(allActionPlugins, 'name', pageLink, deferred); |
127 | 127 | }, |
... | ... | @@ -132,9 +132,9 @@ function PluginService($http, $q, $rootScope, $filter, componentDescriptorServic |
132 | 132 | return deferred.promise; |
133 | 133 | } |
134 | 134 | |
135 | - function getAllPlugins(pageLink) { | |
135 | + function getAllPlugins(pageLink, config) { | |
136 | 136 | var deferred = $q.defer(); |
137 | - loadPluginsCache().then( | |
137 | + loadPluginsCache(config).then( | |
138 | 138 | function success() { |
139 | 139 | utils.filterSearchTextEntities(allPlugins, 'name', pageLink, deferred); |
140 | 140 | }, |
... | ... | @@ -156,10 +156,10 @@ function PluginService($http, $q, $rootScope, $filter, componentDescriptorServic |
156 | 156 | return deferred.promise; |
157 | 157 | } |
158 | 158 | |
159 | - function getPlugin(pluginId) { | |
159 | + function getPlugin(pluginId, config) { | |
160 | 160 | var deferred = $q.defer(); |
161 | 161 | var url = '/api/plugin/' + pluginId; |
162 | - $http.get(url, null).then(function success(response) { | |
162 | + $http.get(url, config).then(function success(response) { | |
163 | 163 | deferred.resolve(response.data); |
164 | 164 | }, function fail(response) { |
165 | 165 | deferred.reject(response.data); | ... | ... |
... | ... | @@ -47,11 +47,11 @@ function RuleService($http, $q, $rootScope, $filter, types, utils) { |
47 | 47 | tenantRules = undefined; |
48 | 48 | } |
49 | 49 | |
50 | - function loadRulesCache() { | |
50 | + function loadRulesCache(config) { | |
51 | 51 | var deferred = $q.defer(); |
52 | 52 | if (!allRules) { |
53 | 53 | var url = '/api/rules'; |
54 | - $http.get(url, null).then(function success(response) { | |
54 | + $http.get(url, config).then(function success(response) { | |
55 | 55 | allRules = response.data; |
56 | 56 | systemRules = []; |
57 | 57 | tenantRules = []; |
... | ... | @@ -100,9 +100,9 @@ function RuleService($http, $q, $rootScope, $filter, types, utils) { |
100 | 100 | return deferred.promise; |
101 | 101 | } |
102 | 102 | |
103 | - function getAllRules(pageLink) { | |
103 | + function getAllRules(pageLink, config) { | |
104 | 104 | var deferred = $q.defer(); |
105 | - loadRulesCache().then( | |
105 | + loadRulesCache(config).then( | |
106 | 106 | function success() { |
107 | 107 | utils.filterSearchTextEntities(allRules, 'name', pageLink, deferred); |
108 | 108 | }, |
... | ... | @@ -124,10 +124,10 @@ function RuleService($http, $q, $rootScope, $filter, types, utils) { |
124 | 124 | return deferred.promise; |
125 | 125 | } |
126 | 126 | |
127 | - function getRule(ruleId) { | |
127 | + function getRule(ruleId, config) { | |
128 | 128 | var deferred = $q.defer(); |
129 | 129 | var url = '/api/rule/' + ruleId; |
130 | - $http.get(url, null).then(function success(response) { | |
130 | + $http.get(url, config).then(function success(response) { | |
131 | 131 | deferred.resolve(response.data); |
132 | 132 | }, function fail(response) { |
133 | 133 | deferred.reject(response.data); | ... | ... |
... | ... | @@ -23,6 +23,8 @@ export default angular.module('thingsboard.api.telemetryWebsocket', [thingsboard |
23 | 23 | const RECONNECT_INTERVAL = 2000; |
24 | 24 | const WS_IDLE_TIMEOUT = 90000; |
25 | 25 | |
26 | +const MAX_PUBLISH_COMMANDS = 10; | |
27 | + | |
26 | 28 | /*@ngInject*/ |
27 | 29 | function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, types, userService) { |
28 | 30 | |
... | ... | @@ -75,19 +77,40 @@ function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, ty |
75 | 77 | return service; |
76 | 78 | |
77 | 79 | function publishCommands () { |
78 | - if (isOpened && (cmdsWrapper.tsSubCmds.length > 0 || | |
79 | - cmdsWrapper.historyCmds.length > 0 || | |
80 | - cmdsWrapper.attrSubCmds.length > 0)) { | |
81 | - dataStream.send(angular.copy(cmdsWrapper)).then(function () { | |
80 | + while(isOpened && hasCommands()) { | |
81 | + dataStream.send(preparePublishCommands()).then(function () { | |
82 | 82 | checkToClose(); |
83 | 83 | }); |
84 | - cmdsWrapper.tsSubCmds = []; | |
85 | - cmdsWrapper.historyCmds = []; | |
86 | - cmdsWrapper.attrSubCmds = []; | |
87 | 84 | } |
88 | 85 | tryOpenSocket(); |
89 | 86 | } |
90 | 87 | |
88 | + function hasCommands() { | |
89 | + return cmdsWrapper.tsSubCmds.length > 0 || | |
90 | + cmdsWrapper.historyCmds.length > 0 || | |
91 | + cmdsWrapper.attrSubCmds.length > 0; | |
92 | + } | |
93 | + | |
94 | + function preparePublishCommands() { | |
95 | + var preparedWrapper = {}; | |
96 | + var leftCount = MAX_PUBLISH_COMMANDS; | |
97 | + preparedWrapper.tsSubCmds = popCmds(cmdsWrapper.tsSubCmds, leftCount); | |
98 | + leftCount -= preparedWrapper.tsSubCmds.length; | |
99 | + preparedWrapper.historyCmds = popCmds(cmdsWrapper.historyCmds, leftCount); | |
100 | + leftCount -= preparedWrapper.historyCmds.length; | |
101 | + preparedWrapper.attrSubCmds = popCmds(cmdsWrapper.attrSubCmds, leftCount); | |
102 | + return preparedWrapper; | |
103 | + } | |
104 | + | |
105 | + function popCmds(cmds, leftCount) { | |
106 | + var toPublish = Math.min(cmds.length, leftCount); | |
107 | + if (toPublish > 0) { | |
108 | + return cmds.splice(0, toPublish); | |
109 | + } else { | |
110 | + return []; | |
111 | + } | |
112 | + } | |
113 | + | |
91 | 114 | function onError (/*message*/) { |
92 | 115 | isOpening = false; |
93 | 116 | } | ... | ... |
... | ... | @@ -29,7 +29,7 @@ function TenantService($http, $q) { |
29 | 29 | |
30 | 30 | return service; |
31 | 31 | |
32 | - function getTenants (pageLink) { | |
32 | + function getTenants (pageLink, config) { | |
33 | 33 | var deferred = $q.defer(); |
34 | 34 | var url = '/api/tenants?limit=' + pageLink.limit; |
35 | 35 | if (angular.isDefined(pageLink.textSearch)) { |
... | ... | @@ -41,7 +41,7 @@ function TenantService($http, $q) { |
41 | 41 | if (angular.isDefined(pageLink.textOffset)) { |
42 | 42 | url += '&textOffset=' + pageLink.textOffset; |
43 | 43 | } |
44 | - $http.get(url, null).then(function success(response) { | |
44 | + $http.get(url, config).then(function success(response) { | |
45 | 45 | deferred.resolve(response.data); |
46 | 46 | }, function fail() { |
47 | 47 | deferred.reject(); |
... | ... | @@ -49,10 +49,10 @@ function TenantService($http, $q) { |
49 | 49 | return deferred.promise; |
50 | 50 | } |
51 | 51 | |
52 | - function getTenant (tenantId) { | |
52 | + function getTenant (tenantId, config) { | |
53 | 53 | var deferred = $q.defer(); |
54 | 54 | var url = '/api/tenant/' + tenantId; |
55 | - $http.get(url, null).then(function success(response) { | |
55 | + $http.get(url, config).then(function success(response) { | |
56 | 56 | deferred.resolve(response.data); |
57 | 57 | }, function fail(response) { |
58 | 58 | deferred.reject(response.data); | ... | ... |
... | ... | @@ -421,10 +421,14 @@ function UserService($http, $q, $rootScope, adminService, dashboardService, logi |
421 | 421 | return deferred.promise; |
422 | 422 | } |
423 | 423 | |
424 | - function getUser(userId, ignoreErrors) { | |
424 | + function getUser(userId, ignoreErrors, config) { | |
425 | 425 | var deferred = $q.defer(); |
426 | 426 | var url = '/api/user/' + userId; |
427 | - $http.get(url, { ignoreErrors: ignoreErrors }).then(function success(response) { | |
427 | + if (!config) { | |
428 | + config = {}; | |
429 | + } | |
430 | + config = Object.assign(config, { ignoreErrors: ignoreErrors }); | |
431 | + $http.get(url, config).then(function success(response) { | |
428 | 432 | deferred.resolve(response.data); |
429 | 433 | }, function fail() { |
430 | 434 | deferred.reject(); | ... | ... |
... | ... | @@ -298,11 +298,11 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr |
298 | 298 | tenantWidgetsBundles = undefined; |
299 | 299 | } |
300 | 300 | |
301 | - function loadWidgetsBundleCache() { | |
301 | + function loadWidgetsBundleCache(config) { | |
302 | 302 | var deferred = $q.defer(); |
303 | 303 | if (!allWidgetsBundles) { |
304 | 304 | var url = '/api/widgetsBundles'; |
305 | - $http.get(url, null).then(function success(response) { | |
305 | + $http.get(url, config).then(function success(response) { | |
306 | 306 | allWidgetsBundles = response.data; |
307 | 307 | systemWidgetsBundles = []; |
308 | 308 | tenantWidgetsBundles = []; |
... | ... | @@ -326,9 +326,9 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr |
326 | 326 | } |
327 | 327 | |
328 | 328 | |
329 | - function getSystemWidgetsBundles() { | |
329 | + function getSystemWidgetsBundles(config) { | |
330 | 330 | var deferred = $q.defer(); |
331 | - loadWidgetsBundleCache().then( | |
331 | + loadWidgetsBundleCache(config).then( | |
332 | 332 | function success() { |
333 | 333 | deferred.resolve(systemWidgetsBundles); |
334 | 334 | }, |
... | ... | @@ -339,9 +339,9 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr |
339 | 339 | return deferred.promise; |
340 | 340 | } |
341 | 341 | |
342 | - function getTenantWidgetsBundles() { | |
342 | + function getTenantWidgetsBundles(config) { | |
343 | 343 | var deferred = $q.defer(); |
344 | - loadWidgetsBundleCache().then( | |
344 | + loadWidgetsBundleCache(config).then( | |
345 | 345 | function success() { |
346 | 346 | deferred.resolve(tenantWidgetsBundles); |
347 | 347 | }, |
... | ... | @@ -352,9 +352,9 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr |
352 | 352 | return deferred.promise; |
353 | 353 | } |
354 | 354 | |
355 | - function getAllWidgetsBundles() { | |
355 | + function getAllWidgetsBundles(config) { | |
356 | 356 | var deferred = $q.defer(); |
357 | - loadWidgetsBundleCache().then( | |
357 | + loadWidgetsBundleCache(config).then( | |
358 | 358 | function success() { |
359 | 359 | deferred.resolve(allWidgetsBundles); |
360 | 360 | }, | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-asset asset="vm.item" is-edit="true" the-form="theForm"></tb-asset> |
... | ... | @@ -36,10 +36,10 @@ |
36 | 36 | </md-dialog-content> |
37 | 37 | <md-dialog-actions layout="row"> |
38 | 38 | <span flex></span> |
39 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
40 | 40 | {{ 'action.add' | translate }} |
41 | 41 | </md-button> |
42 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
42 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
43 | 43 | </md-dialog-actions> |
44 | 44 | </form> |
45 | 45 | </md-dialog> | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <fieldset> |
... | ... | @@ -65,11 +65,11 @@ |
65 | 65 | </md-dialog-content> |
66 | 66 | <md-dialog-actions layout="row"> |
67 | 67 | <span flex></span> |
68 | - <md-button ng-disabled="loading || vm.assets.selectedCount == 0" type="submit" | |
68 | + <md-button ng-disabled="$root.loading || vm.assets.selectedCount == 0" type="submit" | |
69 | 69 | class="md-raised md-primary"> |
70 | 70 | {{ 'action.assign' | translate }} |
71 | 71 | </md-button> |
72 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
72 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
73 | 73 | translate }} |
74 | 74 | </md-button> |
75 | 75 | </md-dialog-actions> | ... | ... |
... | ... | @@ -48,7 +48,7 @@ |
48 | 48 | ng-show="!isEdit && isPublic && (assetScope === 'customer' || assetScope === 'tenant')"> |
49 | 49 | {{ 'asset.asset-public' | translate }} |
50 | 50 | </div> |
51 | - <fieldset ng-disabled="loading || !isEdit"> | |
51 | + <fieldset ng-disabled="$root.loading || !isEdit"> | |
52 | 52 | <md-input-container class="md-block"> |
53 | 53 | <label translate>asset.name</label> |
54 | 54 | <input required name="name" ng-model="asset.name"> |
... | ... | @@ -57,7 +57,7 @@ |
57 | 57 | </div> |
58 | 58 | </md-input-container> |
59 | 59 | <tb-entity-subtype-autocomplete |
60 | - ng-disabled="loading || !isEdit" | |
60 | + ng-disabled="$root.loading || !isEdit" | |
61 | 61 | tb-required="true" |
62 | 62 | the-form="theForm" |
63 | 63 | ng-model="asset.type" | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <fieldset> |
... | ... | @@ -65,10 +65,10 @@ |
65 | 65 | </md-dialog-content> |
66 | 66 | <md-dialog-actions layout="row"> |
67 | 67 | <span flex></span> |
68 | - <md-button ng-disabled="loading || vm.customers.selection==null" type="submit" class="md-raised md-primary"> | |
68 | + <md-button ng-disabled="$root.loading || vm.customers.selection==null" type="submit" class="md-raised md-primary"> | |
69 | 69 | {{ 'action.assign' | translate }} |
70 | 70 | </md-button> |
71 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
71 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
72 | 72 | translate }} |
73 | 73 | </md-button> |
74 | 74 | </md-dialog-actions> | ... | ... |
... | ... | @@ -134,6 +134,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t |
134 | 134 | defaultAlarmDataKeys.push(dataKey); |
135 | 135 | } |
136 | 136 | |
137 | + var imageAspectMap = {}; | |
138 | + | |
137 | 139 | var service = { |
138 | 140 | getDefaultDatasource: getDefaultDatasource, |
139 | 141 | generateObjectFromJsonSchema: generateObjectFromJsonSchema, |
... | ... | @@ -159,7 +161,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t |
159 | 161 | insertVariable: insertVariable, |
160 | 162 | customTranslation: customTranslation, |
161 | 163 | objToBase64: objToBase64, |
162 | - base64toObj: base64toObj | |
164 | + base64toObj: base64toObj, | |
165 | + loadImageAspect: loadImageAspect | |
163 | 166 | } |
164 | 167 | |
165 | 168 | return service; |
... | ... | @@ -543,4 +546,34 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t |
543 | 546 | return obj; |
544 | 547 | } |
545 | 548 | |
549 | + function loadImageAspect(imageUrl) { | |
550 | + var deferred = $q.defer(); | |
551 | + if (imageUrl && imageUrl.length) { | |
552 | + var urlHashCode = hashCode(imageUrl); | |
553 | + var aspect = imageAspectMap[urlHashCode]; | |
554 | + if (angular.isUndefined(aspect)) { | |
555 | + var testImage = document.createElement('img'); // eslint-disable-line | |
556 | + testImage.style.visibility = 'hidden'; | |
557 | + testImage.onload = function() { | |
558 | + aspect = testImage.width / testImage.height; | |
559 | + document.body.removeChild(testImage); //eslint-disable-line | |
560 | + imageAspectMap[urlHashCode] = aspect; | |
561 | + deferred.resolve(aspect); | |
562 | + }; | |
563 | + testImage.onerror = function() { | |
564 | + aspect = 0; | |
565 | + imageAspectMap[urlHashCode] = aspect; | |
566 | + deferred.resolve(aspect); | |
567 | + }; | |
568 | + document.body.appendChild(testImage); //eslint-disable-line | |
569 | + testImage.src = imageUrl; | |
570 | + } else { | |
571 | + deferred.resolve(aspect); | |
572 | + } | |
573 | + } else { | |
574 | + deferred.resolve(0); | |
575 | + } | |
576 | + return deferred.promise; | |
577 | + } | |
578 | + | |
546 | 579 | } | ... | ... |
... | ... | @@ -27,11 +27,11 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content tb-filter"> |
34 | - <fieldset ng-disabled="loading || vm.isReadOnly"> | |
34 | + <fieldset ng-disabled="$root.loading || vm.isReadOnly"> | |
35 | 35 | <section flex layout="row"> |
36 | 36 | <md-input-container flex class="md-block"> |
37 | 37 | <label translate>rule.component-name</label> |
... | ... | @@ -42,7 +42,7 @@ |
42 | 42 | </md-input-container> |
43 | 43 | <md-input-container flex class="md-block"> |
44 | 44 | <label translate>rule.component-type</label> |
45 | - <md-select required name="componentType" ng-model="vm.componentInfo.component.clazz" ng-disabled="loading || vm.isReadOnly"> | |
45 | + <md-select required name="componentType" ng-model="vm.componentInfo.component.clazz" ng-disabled="$root.loading || vm.isReadOnly"> | |
46 | 46 | <md-option ng-repeat="componentDescriptor in vm.componentDescriptors" ng-value="componentDescriptor.clazz"> |
47 | 47 | {{componentDescriptor.name}} |
48 | 48 | </md-option> |
... | ... | @@ -57,7 +57,7 @@ |
57 | 57 | <tb-json-form schema="vm.componentDescriptor.configurationDescriptor.schema" |
58 | 58 | form="vm.componentDescriptor.configurationDescriptor.form" |
59 | 59 | model="vm.componentInfo.component.configuration" |
60 | - readonly="loading || vm.isReadOnly" | |
60 | + readonly="$root.loading || vm.isReadOnly" | |
61 | 61 | form-control="theForm"> |
62 | 62 | </tb-json-form> |
63 | 63 | </md-card-content> |
... | ... | @@ -67,11 +67,11 @@ |
67 | 67 | </md-dialog-content> |
68 | 68 | <md-dialog-actions layout="row"> |
69 | 69 | <span flex></span> |
70 | - <md-button ng-if="!vm.isReadOnly" ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
70 | + <md-button ng-if="!vm.isReadOnly" ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
71 | 71 | class="md-raised md-primary"> |
72 | 72 | {{ (vm.isAdd ? 'action.add' : 'action.save') | translate }} |
73 | 73 | </md-button> |
74 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
74 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
75 | 75 | translate }} |
76 | 76 | </md-button> |
77 | 77 | </md-dialog-actions> | ... | ... |
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | {{ componentTypeName }} |
25 | 25 | </span> |
26 | 26 | <span ng-if="readOnly" style="min-width: 40px; min-height: 40px; margin: 0 6px;"></br></span> |
27 | - <md-button ng-disabled="loading" class="md-icon-button md-primary" | |
27 | + <md-button ng-disabled="$root.loading" class="md-icon-button md-primary" | |
28 | 28 | style="min-width: 40px;" |
29 | 29 | ng-click="openComponent($event)" |
30 | 30 | aria-label="{{ (readOnly ? 'action.view' : 'action.edit') | translate }}"> |
... | ... | @@ -43,7 +43,7 @@ |
43 | 43 | edit |
44 | 44 | </md-icon> |
45 | 45 | </md-button> |
46 | - <md-button ng-if="!readOnly" ng-disabled="loading" class="md-icon-button md-primary" | |
46 | + <md-button ng-if="!readOnly" ng-disabled="$root.loading" class="md-icon-button md-primary" | |
47 | 47 | style="min-width: 40px;" |
48 | 48 | ng-click="onRemoveComponent({event: $event})" |
49 | 49 | aria-label="{{ 'action.remove' | translate }}"> | ... | ... |
... | ... | @@ -48,19 +48,19 @@ function DashboardAutocomplete($compile, $templateCache, $q, dashboardService, u |
48 | 48 | var promise; |
49 | 49 | if (scope.dashboardsScope === 'customer' || userService.getAuthority() === 'CUSTOMER_USER') { |
50 | 50 | if (scope.customerId) { |
51 | - promise = dashboardService.getCustomerDashboards(scope.customerId, pageLink, false); | |
51 | + promise = dashboardService.getCustomerDashboards(scope.customerId, pageLink, false, {ignoreLoading: true}); | |
52 | 52 | } else { |
53 | 53 | promise = $q.when({data: []}); |
54 | 54 | } |
55 | 55 | } else { |
56 | 56 | if (userService.getAuthority() === 'SYS_ADMIN') { |
57 | 57 | if (scope.tenantId) { |
58 | - promise = dashboardService.getTenantDashboardsByTenantId(scope.tenantId, pageLink); | |
58 | + promise = dashboardService.getTenantDashboardsByTenantId(scope.tenantId, pageLink, {ignoreLoading: true}); | |
59 | 59 | } else { |
60 | 60 | promise = $q.when({data: []}); |
61 | 61 | } |
62 | 62 | } else { |
63 | - promise = dashboardService.getTenantDashboards(pageLink, false); | |
63 | + promise = dashboardService.getTenantDashboards(pageLink, false, {ignoreLoading: true}); | |
64 | 64 | } |
65 | 65 | } |
66 | 66 | ... | ... |
... | ... | @@ -48,12 +48,12 @@ function DashboardSelect($compile, $templateCache, $q, $mdMedia, $mdPanel, $docu |
48 | 48 | var promise; |
49 | 49 | if (scope.dashboardsScope === 'customer' || userService.getAuthority() === 'CUSTOMER_USER') { |
50 | 50 | if (scope.customerId && scope.customerId != types.id.nullUid) { |
51 | - promise = dashboardService.getCustomerDashboards(scope.customerId, pageLink, false); | |
51 | + promise = dashboardService.getCustomerDashboards(scope.customerId, pageLink, false, {ignoreLoading: true}); | |
52 | 52 | } else { |
53 | 53 | promise = $q.when({data: []}); |
54 | 54 | } |
55 | 55 | } else { |
56 | - promise = dashboardService.getTenantDashboards(pageLink, false); | |
56 | + promise = dashboardService.getTenantDashboards(pageLink, false, {ignoreLoading: true}); | |
57 | 57 | } |
58 | 58 | |
59 | 59 | promise.then(function success(result) { | ... | ... |
... | ... | @@ -43,7 +43,7 @@ function DatakeyConfigDialogController($scope, $mdDialog, $q, entityService, dat |
43 | 43 | function success(aliasInfo) { |
44 | 44 | var entity = aliasInfo.currentEntity; |
45 | 45 | if (entity) { |
46 | - entityService.getEntityKeys(entity.entityType, entity.id, query, type).then( | |
46 | + entityService.getEntityKeys(entity.entityType, entity.id, query, type, {ignoreLoading: true}).then( | |
47 | 47 | function success(keys) { |
48 | 48 | deferred.resolve(keys); |
49 | 49 | }, | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <tb-datakey-config ng-model="vm.dataKey" |
33 | 33 | fetch-entity-keys="vm.fetchEntityKeys(entityAliasId, query, type)" |
... | ... | @@ -37,10 +37,10 @@ |
37 | 37 | </md-dialog-content> |
38 | 38 | <md-dialog-actions layout="row"> |
39 | 39 | <span flex></span> |
40 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
40 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
41 | 41 | {{ 'action.save' | translate }} |
42 | 42 | </md-button> |
43 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
43 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
44 | 44 | </md-dialog-actions> |
45 | 45 | </form> |
46 | 46 | </md-dialog> | ... | ... |
... | ... | @@ -35,7 +35,7 @@ |
35 | 35 | </div> |
36 | 36 | <section ng-if="!isReadOnly" layout="row" layout-wrap |
37 | 37 | class="tb-header-buttons md-fab"> |
38 | - <md-button ng-show="isEdit" ng-disabled="loading || theForm.$invalid || !theForm.$dirty" | |
38 | + <md-button ng-show="isEdit" ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" | |
39 | 39 | class="tb-btn-header md-accent md-hue-2 md-fab md-fab-bottom-right" |
40 | 40 | aria-label="{{ 'action.apply' | translate }}" |
41 | 41 | ng-click="detailsApply()"> |
... | ... | @@ -44,7 +44,7 @@ |
44 | 44 | </md-tooltip> |
45 | 45 | <ng-md-icon icon="done"></ng-md-icon> |
46 | 46 | </md-button> |
47 | - <md-button ng-disabled="loading || (isAlwaysEdit && !theForm.$dirty)" class="tb-btn-header md-accent md-hue-2 md-fab md-fab-bottom-right" | |
47 | + <md-button ng-disabled="$root.loading || (isAlwaysEdit && !theForm.$dirty)" class="tb-btn-header md-accent md-hue-2 md-fab md-fab-bottom-right" | |
48 | 48 | aria-label="{{ 'details.edit-mode' | translate }}" |
49 | 49 | ng-click="toggleDetailsEditMode()"> |
50 | 50 | <md-tooltip md-direction="top"> | ... | ... |
... | ... | @@ -45,7 +45,7 @@ |
45 | 45 | <tb-grid-card-content flex grid-ctl="vm" parent-ctl="vm.parentCtl" item-controller="vm.itemCardController" item-template="vm.itemCardTemplate" item="rowItem[n]"></tb-grid-card-content> |
46 | 46 | </md-card-content> |
47 | 47 | <md-card-actions layout="row" layout-align="end end"> |
48 | - <md-button ng-if="action.isEnabled(rowItem[n])" ng-disabled="loading" class="md-icon-button md-primary" ng-repeat="action in vm.actionsList" | |
48 | + <md-button ng-if="action.isEnabled(rowItem[n])" ng-disabled="$root.loading" class="md-icon-button md-primary" ng-repeat="action in vm.actionsList" | |
49 | 49 | ng-click="action.onAction($event, rowItem[n])" aria-label="{{ action.name() }}"> |
50 | 50 | <md-tooltip md-direction="top"> |
51 | 51 | {{ action.details( rowItem[n] ) }} |
... | ... | @@ -81,28 +81,28 @@ |
81 | 81 | </section> |
82 | 82 | |
83 | 83 | <section layout="row" layout-wrap class="tb-footer-buttons md-fab " layout-align="start end"> |
84 | - <md-button ng-disabled="loading" ng-show="vm.items.selectedCount > 0" class="tb-btn-footer md-accent md-hue-2 md-fab" ng-repeat="groupAction in vm.groupActionsList" | |
84 | + <md-button ng-disabled="$root.loading" ng-show="vm.items.selectedCount > 0" class="tb-btn-footer md-accent md-hue-2 md-fab" ng-repeat="groupAction in vm.groupActionsList" | |
85 | 85 | ng-click="groupAction.onAction($event, vm.items)" aria-label="{{ groupAction.name() }}"> |
86 | 86 | <md-tooltip md-direction="top"> |
87 | 87 | {{ groupAction.details(vm.items.selectedCount) }} |
88 | 88 | </md-tooltip> |
89 | 89 | <ng-md-icon icon="{{groupAction.icon}}"></ng-md-icon> |
90 | 90 | </md-button> |
91 | - <md-button ng-disabled="loading" ng-show="vm.topIndex > 0" class="tb-btn-footer md-primary md-hue-1 md-fab" ng-click="vm.moveToTop()" aria-label="{{'grid.scroll-to-top' | translate}}" > | |
91 | + <md-button ng-disabled="$root.loading" ng-show="vm.topIndex > 0" class="tb-btn-footer md-primary md-hue-1 md-fab" ng-click="vm.moveToTop()" aria-label="{{'grid.scroll-to-top' | translate}}" > | |
92 | 92 | <md-tooltip md-direction="top"> |
93 | 93 | {{'grid.scroll-to-top' | translate}} |
94 | 94 | </md-tooltip> |
95 | 95 | <ng-md-icon icon="arrow_drop_up"></ng-md-icon> |
96 | 96 | </md-button> |
97 | - <md-button ng-disabled="loading" ng-if="vm.addItemAction.name() && vm.addItemActions.length == 0" class="tb-btn-footer md-accent md-hue-2 md-fab" ng-click="vm.addItemAction.onAction($event)" aria-label="{{ vm.addItemAction.name() }}" > | |
97 | + <md-button ng-disabled="$root.loading" ng-if="vm.addItemAction.name() && vm.addItemActions.length == 0" class="tb-btn-footer md-accent md-hue-2 md-fab" ng-click="vm.addItemAction.onAction($event)" aria-label="{{ vm.addItemAction.name() }}" > | |
98 | 98 | <md-tooltip md-direction="top"> |
99 | 99 | {{ vm.addItemAction.details() }} |
100 | 100 | </md-tooltip> |
101 | 101 | <ng-md-icon icon="{{ vm.addItemAction.icon }}"></ng-md-icon> |
102 | 102 | </md-button> |
103 | - <md-fab-speed-dial ng-disabled="loading" ng-if="vm.addItemAction.name() && vm.addItemActions.length > 0" md-open="vm.addItemActionsOpen" class="md-scale" md-direction="up" ng-if="vm.addItemAction.name()"> | |
103 | + <md-fab-speed-dial ng-disabled="$root.loading" ng-if="vm.addItemAction.name() && vm.addItemActions.length > 0" md-open="vm.addItemActionsOpen" class="md-scale" md-direction="up" ng-if="vm.addItemAction.name()"> | |
104 | 104 | <md-fab-trigger> |
105 | - <md-button ng-disabled="loading" class="tb-btn-footer md-accent md-hue-2 md-fab" aria-label="{{ vm.addItemAction.name() }}" > | |
105 | + <md-button ng-disabled="$root.loading" class="tb-btn-footer md-accent md-hue-2 md-fab" aria-label="{{ vm.addItemAction.name() }}" > | |
106 | 106 | <md-tooltip md-direction="top"> |
107 | 107 | {{ vm.addItemAction.details() }} |
108 | 108 | </md-tooltip> |
... | ... | @@ -110,7 +110,7 @@ |
110 | 110 | </md-button> |
111 | 111 | </md-fab-trigger> |
112 | 112 | <md-fab-actions> |
113 | - <md-button ng-disabled="loading" class="md-accent md-hue-2 md-fab" ng-repeat="addItemAction in vm.addItemActions" | |
113 | + <md-button ng-disabled="$root.loading" class="md-accent md-hue-2 md-fab" ng-repeat="addItemAction in vm.addItemActions" | |
114 | 114 | ng-click="addItemAction.onAction($event)" aria-label="{{ addItemAction.name() }}" > |
115 | 115 | <md-tooltip md-direction="top"> |
116 | 116 | {{ addItemAction.details() }} | ... | ... |
... | ... | @@ -16,7 +16,7 @@ |
16 | 16 | |
17 | 17 | --> |
18 | 18 | <form name="theForm" ng-submit="vm.update()"> |
19 | - <fieldset ng-disabled="loading"> | |
19 | + <fieldset ng-disabled="$root.loading"> | |
20 | 20 | <md-content style="height: 100%" flex layout="column"> |
21 | 21 | <section layout="column"> |
22 | 22 | <md-content class="md-padding" layout="column"> | ... | ... |
... | ... | @@ -32,15 +32,15 @@ |
32 | 32 | </md-button> |
33 | 33 | </div> |
34 | 34 | </md-toolbar> |
35 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
36 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
35 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
36 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
37 | 37 | <div class="tb-absolute-fill tb-icons-load" ng-show="vm.loadingIcons" layout="column" layout-align="center center"> |
38 | 38 | <md-progress-circular md-mode="indeterminate" ng-disabled="!vm.loadingIcons" class="md-accent" md-diameter="40"></md-progress-circular> |
39 | 39 | </div> |
40 | 40 | <md-dialog-content> |
41 | 41 | <div class="md-dialog-content"> |
42 | 42 | <md-content class="md-padding" layout="column"> |
43 | - <fieldset ng-disabled="loading"> | |
43 | + <fieldset ng-disabled="$root.loading"> | |
44 | 44 | <md-button ng-class="{'md-primary md-raised': icon == vm.selectedIcon}" class="tb-select-icon-button md-icon-button" |
45 | 45 | ng-repeat="icon in vm.icons" ng-click="vm.selectIcon($event, icon)" tb-on-finish-render="iconsLoadFinished"> |
46 | 46 | <md-icon class="material-icons">{{icon}}</md-icon> |
... | ... | @@ -54,7 +54,7 @@ |
54 | 54 | </md-dialog-content> |
55 | 55 | <md-dialog-actions layout="row"> |
56 | 56 | <span flex></span> |
57 | - <md-button ng-disabled="loading" ng-click="vm.cancel()"> | |
57 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()"> | |
58 | 58 | {{ 'action.cancel' | translate }} |
59 | 59 | </md-button> |
60 | 60 | </md-dialog-actions> | ... | ... |
... | ... | @@ -56,7 +56,7 @@ function PluginSelect($compile, $templateCache, $q, pluginService, types) { |
56 | 56 | |
57 | 57 | var deferred = $q.defer(); |
58 | 58 | |
59 | - scope.pluginFetchFunction(pageLink).then(function success(result) { | |
59 | + scope.pluginFetchFunction(pageLink, {ignoreLoading: true}).then(function success(result) { | |
60 | 60 | deferred.resolve(result.data); |
61 | 61 | }, function fail() { |
62 | 62 | deferred.reject(); |
... | ... | @@ -89,7 +89,7 @@ function PluginSelect($compile, $templateCache, $q, pluginService, types) { |
89 | 89 | |
90 | 90 | if (scope.selectFirstPlugin) { |
91 | 91 | var pageLink = {limit: 1, textSearch: ''}; |
92 | - scope.pluginFetchFunction(pageLink).then(function success(result) { | |
92 | + scope.pluginFetchFunction(pageLink, {ignoreLoading: true}).then(function success(result) { | |
93 | 93 | var plugins = result.data; |
94 | 94 | if (plugins.length > 0) { |
95 | 95 | scope.plugin = plugins[0]; | ... | ... |
... | ... | @@ -16,7 +16,7 @@ |
16 | 16 | |
17 | 17 | --> |
18 | 18 | <form name="theForm" ng-submit="vm.update()"> |
19 | - <fieldset ng-disabled="loading"> | |
19 | + <fieldset ng-disabled="$root.loading"> | |
20 | 20 | <md-content style="height: 100%" flex layout="column"> |
21 | 21 | <section layout="column"> |
22 | 22 | <md-tabs ng-class="{'tb-headless': vm.historyOnly}" md-dynamic-height md-selected="vm.timewindow.selectedTab" md-border-bottom> |
... | ... | @@ -81,10 +81,10 @@ |
81 | 81 | <span flex></span> |
82 | 82 | <section layout="row" layout-alignment="start center"> |
83 | 83 | <span flex></span> |
84 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
84 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
85 | 85 | {{ 'action.update' | translate }} |
86 | 86 | </md-button> |
87 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;"> | |
87 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;"> | |
88 | 88 | {{ 'action.cancel' | translate }} |
89 | 89 | </md-button> |
90 | 90 | </section> | ... | ... |
... | ... | @@ -26,12 +26,12 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <md-content class="md-padding" layout="column"> |
34 | - <fieldset ng-disabled="loading" layout="column"> | |
34 | + <fieldset ng-disabled="$root.loading" layout="column"> | |
35 | 35 | <md-input-container class="md-block"> |
36 | 36 | <label translate>widget-config.action-source</label> |
37 | 37 | <md-select name="actionSource" required aria-label="{{ 'widget-config.action-source' | translate }}" ng-model="vm.action.actionSourceId"> |
... | ... | @@ -120,7 +120,7 @@ |
120 | 120 | </div> |
121 | 121 | <tb-js-func ng-if="vm.action.type == vm.types.widgetActionTypes.custom.value" |
122 | 122 | ng-model="vm.action.customFunction" |
123 | - function-args="{{ ['$event', 'widgetContext', 'entityId'] }}" | |
123 | + function-args="{{ ['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams'] }}" | |
124 | 124 | validation-args="{{ [] }}"> |
125 | 125 | </tb-js-func> |
126 | 126 | </fieldset> |
... | ... | @@ -129,11 +129,11 @@ |
129 | 129 | </md-dialog-content> |
130 | 130 | <md-dialog-actions layout="row"> |
131 | 131 | <span flex></span> |
132 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
132 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
133 | 133 | class="md-raised md-primary"> |
134 | 134 | {{ (vm.isAdd ? 'action.add' : 'action.save') | translate }} |
135 | 135 | </md-button> |
136 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;"> | |
136 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;"> | |
137 | 137 | {{ 'action.cancel' | translate }} |
138 | 138 | </md-button> |
139 | 139 | </md-dialog-actions> | ... | ... |
... | ... | @@ -104,7 +104,7 @@ |
104 | 104 | generate-data-key="generateDataKey(chip,type)" |
105 | 105 | fetch-entity-keys="fetchEntityKeys({entityAliasId: entityAliasId, query: query, type: type})" |
106 | 106 | on-create-entity-alias="onCreateEntityAlias({event: event, alias: alias})"></tb-datasource> |
107 | - <md-button ng-disabled="loading" class="md-icon-button md-primary" | |
107 | + <md-button ng-disabled="$root.loading" class="md-icon-button md-primary" | |
108 | 108 | style="min-width: 40px;" |
109 | 109 | ng-click="removeDatasource($event, datasource)" |
110 | 110 | aria-label="{{ 'action.remove' | translate }}"> |
... | ... | @@ -121,7 +121,7 @@ |
121 | 121 | </div> |
122 | 122 | </div> |
123 | 123 | <div flex layout="row" layout-align="start center"> |
124 | - <md-button ng-show="typeParameters.maxDatasources == -1 || datasources.length < typeParameters.maxDatasources" ng-disabled="loading" class="md-primary md-raised" | |
124 | + <md-button ng-show="typeParameters.maxDatasources == -1 || datasources.length < typeParameters.maxDatasources" ng-disabled="$root.loading" class="md-primary md-raised" | |
125 | 125 | ng-click="addDatasource($event)" aria-label="{{ 'action.add' | translate }}"> |
126 | 126 | <md-tooltip md-direction="top"> |
127 | 127 | {{ 'widget-config.add-datasource' | translate }} | ... | ... |
... | ... | @@ -444,7 +444,7 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele |
444 | 444 | } |
445 | 445 | } |
446 | 446 | |
447 | - function handleWidgetAction($event, descriptor, entityId, entityName) { | |
447 | + function handleWidgetAction($event, descriptor, entityId, entityName, additionalParams) { | |
448 | 448 | var type = descriptor.type; |
449 | 449 | var targetEntityParamName = descriptor.stateEntityParamName; |
450 | 450 | var targetEntityId; |
... | ... | @@ -485,8 +485,11 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele |
485 | 485 | var customFunction = descriptor.customFunction; |
486 | 486 | if (angular.isDefined(customFunction) && customFunction.length > 0) { |
487 | 487 | try { |
488 | - var customActionFunction = new Function('$event', 'widgetContext', 'entityId', 'entityName', customFunction); | |
489 | - customActionFunction($event, widgetContext, entityId, entityName); | |
488 | + if (!additionalParams) { | |
489 | + additionalParams = {}; | |
490 | + } | |
491 | + var customActionFunction = new Function('$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', customFunction); | |
492 | + customActionFunction($event, widgetContext, entityId, entityName, additionalParams); | |
490 | 493 | } catch (e) { |
491 | 494 | // |
492 | 495 | } | ... | ... |
... | ... | @@ -48,7 +48,7 @@ function WidgetsBundleSelect($compile, $templateCache, widgetService, types) { |
48 | 48 | } |
49 | 49 | } |
50 | 50 | |
51 | - widgetsBundleFetchFunction().then( | |
51 | + widgetsBundleFetchFunction({ignoreLoading: true}).then( | |
52 | 52 | function success(widgetsBundles) { |
53 | 53 | scope.widgetsBundles = widgetsBundles; |
54 | 54 | if (scope.selectFirstBundle) { | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-customer customer="vm.item" is-edit="true" the-form="theForm"></tb-customer> |
... | ... | @@ -36,10 +36,10 @@ |
36 | 36 | </md-dialog-content> |
37 | 37 | <md-dialog-actions layout="row"> |
38 | 38 | <span flex></span> |
39 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
40 | 40 | {{ 'action.add' | translate }} |
41 | 41 | </md-button> |
42 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
42 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
43 | 43 | </md-dialog-actions> |
44 | 44 | </form> |
45 | 45 | </md-dialog> | ... | ... |
... | ... | @@ -32,7 +32,7 @@ |
32 | 32 | </div> |
33 | 33 | |
34 | 34 | <md-content class="md-padding" layout="column"> |
35 | - <fieldset ng-show="!isPublic" ng-disabled="loading || !isEdit"> | |
35 | + <fieldset ng-show="!isPublic" ng-disabled="$root.loading || !isEdit"> | |
36 | 36 | <md-input-container class="md-block"> |
37 | 37 | <label translate>customer.title</label> |
38 | 38 | <input required name="title" ng-model="customer.title"> | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-dashboard-details dashboard="vm.item" is-edit="true" the-form="theForm"></tb-dashboard-details> |
... | ... | @@ -36,10 +36,10 @@ |
36 | 36 | </md-dialog-content> |
37 | 37 | <md-dialog-actions layout="row"> |
38 | 38 | <span flex></span> |
39 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
40 | 40 | {{ 'action.add' | translate }} |
41 | 41 | </md-button> |
42 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
42 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
43 | 43 | </md-dialog-actions> |
44 | 44 | </form> |
45 | 45 | </md-dialog> |
\ No newline at end of file | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <fieldset> |
... | ... | @@ -65,11 +65,11 @@ |
65 | 65 | </md-dialog-content> |
66 | 66 | <md-dialog-actions layout="row"> |
67 | 67 | <span flex></span> |
68 | - <md-button ng-disabled="loading || vm.dashboards.selectedCount == 0" type="submit" | |
68 | + <md-button ng-disabled="$root.loading || vm.dashboards.selectedCount == 0" type="submit" | |
69 | 69 | class="md-raised md-primary"> |
70 | 70 | {{ 'action.assign' | translate }} |
71 | 71 | </md-button> |
72 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
72 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
73 | 73 | translate }} |
74 | 74 | </md-button> |
75 | 75 | </md-dialog-actions> | ... | ... |
... | ... | @@ -110,7 +110,7 @@ export default function AddWidgetController($scope, widgetService, entityService |
110 | 110 | function success(aliasInfo) { |
111 | 111 | var entity = aliasInfo.currentEntity; |
112 | 112 | if (entity) { |
113 | - entityService.getEntityKeys(entity.entityType, entity.id, query, type).then( | |
113 | + entityService.getEntityKeys(entity.entityType, entity.id, query, type, {ignoreLoading: true}).then( | |
114 | 114 | function success(keys) { |
115 | 115 | deferred.resolve(keys); |
116 | 116 | }, | ... | ... |
... | ... | @@ -27,11 +27,11 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content" style="padding-top: 0px;"> |
34 | - <fieldset ng-disabled="loading" style="position: relative; height: 600px;"> | |
34 | + <fieldset ng-disabled="$root.loading" style="position: relative; height: 600px;"> | |
35 | 35 | <tb-widget-config widget-type="vm.widget.type" |
36 | 36 | type-parameters="vm.widgetInfo.typeParameters" |
37 | 37 | action-sources="vm.widgetInfo.actionSources" |
... | ... | @@ -50,11 +50,11 @@ |
50 | 50 | </md-dialog-content> |
51 | 51 | <md-dialog-actions layout="row"> |
52 | 52 | <span flex></span> |
53 | - <md-button ng-disabled="loading || theForm.$invalid" type="submit" | |
53 | + <md-button ng-disabled="$root.loading || theForm.$invalid" type="submit" | |
54 | 54 | class="md-raised md-primary"> |
55 | 55 | {{ 'action.add' | translate }} |
56 | 56 | </md-button> |
57 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
57 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
58 | 58 | translate }} |
59 | 59 | </md-button> |
60 | 60 | </md-dialog-actions> | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <fieldset> |
... | ... | @@ -65,10 +65,10 @@ |
65 | 65 | </md-dialog-content> |
66 | 66 | <md-dialog-actions layout="row"> |
67 | 67 | <span flex></span> |
68 | - <md-button ng-disabled="loading || vm.customers.selection==null" type="submit" class="md-raised md-primary"> | |
68 | + <md-button ng-disabled="$root.loading || vm.customers.selection==null" type="submit" class="md-raised md-primary"> | |
69 | 69 | {{ 'action.assign' | translate }} |
70 | 70 | </md-button> |
71 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
71 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
72 | 72 | translate }} |
73 | 73 | </md-button> |
74 | 74 | </md-dialog-actions> | ... | ... |
... | ... | @@ -59,7 +59,7 @@ |
59 | 59 | </md-button> |
60 | 60 | </div> |
61 | 61 | </div> |
62 | - <fieldset ng-disabled="loading || !isEdit"> | |
62 | + <fieldset ng-disabled="$root.loading || !isEdit"> | |
63 | 63 | <md-input-container class="md-block"> |
64 | 64 | <label translate>dashboard.title</label> |
65 | 65 | <input required name="title" ng-model="dashboard.title"> | ... | ... |
... | ... | @@ -26,11 +26,11 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading"> | |
33 | + <fieldset ng-disabled="$root.loading"> | |
34 | 34 | <div ng-show="vm.settings"> |
35 | 35 | <md-input-container class="md-block"> |
36 | 36 | <label translate>dashboard.state-controller</label> |
... | ... | @@ -194,10 +194,10 @@ |
194 | 194 | </md-dialog-content> |
195 | 195 | <md-dialog-actions layout="row"> |
196 | 196 | <span flex></span> |
197 | - <md-button ng-disabled="loading || !theForm.$dirty || !theForm.$valid" type="submit" class="md-raised md-primary"> | |
197 | + <md-button ng-disabled="$root.loading || !theForm.$dirty || !theForm.$valid" type="submit" class="md-raised md-primary"> | |
198 | 198 | {{ 'action.save' | translate }} |
199 | 199 | </md-button> |
200 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
200 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
201 | 201 | </md-dialog-actions> |
202 | 202 | </form> |
203 | 203 | </md-dialog> | ... | ... |
... | ... | @@ -110,7 +110,7 @@ |
110 | 110 | </section> |
111 | 111 | <section class="tb-dashboard-container tb-absolute-fill" |
112 | 112 | ng-class="{ 'is-fullscreen': forceFullscreen, 'tb-dashboard-toolbar-opened': vm.toolbarOpened, 'tb-dashboard-toolbar-closed': !vm.toolbarOpened }"> |
113 | - <section ng-show="!loading && vm.dashboardConfigurationError()" layout-align="center center" | |
113 | + <section ng-show="!$root.loading && vm.dashboardConfigurationError()" layout-align="center center" | |
114 | 114 | ng-style="{'color': vm.dashboard.configuration.settings.titleColor}" |
115 | 115 | ng-class="{'tb-padded' : !vm.widgetEditMode}" |
116 | 116 | style="text-transform: uppercase; display: flex; z-index: 1;" |
... | ... | @@ -277,10 +277,10 @@ |
277 | 277 | </div> |
278 | 278 | </tb-details-sidenav> |
279 | 279 | <section layout="row" layout-wrap class="tb-footer-buttons md-fab" layout-align="start end"> |
280 | - <md-fab-speed-dial ng-disabled="loading" ng-show="!vm.isAddingWidget && vm.isEdit && !vm.widgetEditMode" | |
280 | + <md-fab-speed-dial ng-disabled="$root.loading" ng-show="!vm.isAddingWidget && vm.isEdit && !vm.widgetEditMode" | |
281 | 281 | md-open="vm.addItemActionsOpen" class="md-scale" md-direction="up"> |
282 | 282 | <md-fab-trigger> |
283 | - <md-button ng-disabled="loading" | |
283 | + <md-button ng-disabled="$root.loading" | |
284 | 284 | class="tb-btn-footer md-accent md-hue-2 md-fab" |
285 | 285 | aria-label="{{ 'dashboard.add-widget' | translate }}"> |
286 | 286 | <md-tooltip md-direction="top"> |
... | ... | @@ -290,7 +290,7 @@ |
290 | 290 | </md-button> |
291 | 291 | </md-fab-trigger> |
292 | 292 | <md-fab-actions> |
293 | - <md-button ng-disabled="loading" | |
293 | + <md-button ng-disabled="$root.loading" | |
294 | 294 | class="tmd-accent md-hue-2 md-fab" ng-click="vm.addWidget($event)" |
295 | 295 | aria-label="{{ 'action.create' | translate }}"> |
296 | 296 | <md-tooltip md-direction="top"> |
... | ... | @@ -298,7 +298,7 @@ |
298 | 298 | </md-tooltip> |
299 | 299 | <ng-md-icon icon="insert_drive_file"></ng-md-icon> |
300 | 300 | </md-button> |
301 | - <md-button ng-disabled="loading" | |
301 | + <md-button ng-disabled="$root.loading" | |
302 | 302 | class="tmd-accent md-hue-2 md-fab" ng-click="vm.importWidget($event)" |
303 | 303 | aria-label="{{ 'action.import' | translate }}"> |
304 | 304 | <md-tooltip md-direction="top"> |
... | ... | @@ -308,7 +308,7 @@ |
308 | 308 | </md-button> |
309 | 309 | </md-fab-actions> |
310 | 310 | </md-fab-speed-dial> |
311 | - <md-button ng-if="(vm.isTenantAdmin() || vm.isSystemAdmin()) && !forceFullscreen" ng-show="vm.isEdit && !vm.isAddingWidget && !loading" ng-disabled="loading" | |
311 | + <md-button ng-if="(vm.isTenantAdmin() || vm.isSystemAdmin()) && !forceFullscreen" ng-show="vm.isEdit && !vm.isAddingWidget && !$root.loading" ng-disabled="$root.loading" | |
312 | 312 | class="tb-btn-footer md-accent md-hue-2 md-fab" |
313 | 313 | aria-label="{{ 'action.apply' | translate }}" |
314 | 314 | ng-click="vm.saveDashboard()"> |
... | ... | @@ -317,8 +317,8 @@ |
317 | 317 | </md-tooltip> |
318 | 318 | <ng-md-icon icon="done"></ng-md-icon> |
319 | 319 | </md-button> |
320 | - <md-button ng-show="!vm.isAddingWidget && !loading" | |
321 | - ng-if="(vm.isTenantAdmin() || vm.isSystemAdmin()) && !forceFullscreen" ng-disabled="loading" | |
320 | + <md-button ng-show="!vm.isAddingWidget && !$root.loading" | |
321 | + ng-if="(vm.isTenantAdmin() || vm.isSystemAdmin()) && !forceFullscreen" ng-disabled="$root.loading" | |
322 | 322 | class="tb-btn-footer md-accent md-hue-2 md-fab" |
323 | 323 | aria-label="{{ 'action.edit-mode' | translate }}" |
324 | 324 | ng-click="vm.toggleDashboardEditMode()"> | ... | ... |
... | ... | @@ -75,7 +75,7 @@ export default function EditWidgetDirective($compile, $templateCache, types, wid |
75 | 75 | function success(aliasInfo) { |
76 | 76 | var entity = aliasInfo.currentEntity; |
77 | 77 | if (entity) { |
78 | - entityService.getEntityKeys(entity.entityType, entity.id, query, type).then( | |
78 | + entityService.getEntityKeys(entity.entityType, entity.id, query, type, {ignoreLoading: true}).then( | |
79 | 79 | function success(keys) { |
80 | 80 | deferred.resolve(keys); |
81 | 81 | }, | ... | ... |
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | 'background-attachment': 'scroll', |
23 | 23 | 'background-size': vm.layoutCtx.gridSettings.backgroundSizeMode || '100%', |
24 | 24 | 'background-position': '0% 0%'}"> |
25 | - <section ng-show="!loading && vm.noData()" layout-align="center center" | |
25 | + <section ng-show="!$root.loading && vm.noData()" layout-align="center center" | |
26 | 26 | ng-style="{'color': vm.layoutCtx.gridSettings.color}" |
27 | 27 | style="text-transform: uppercase; display: flex; z-index: 1; pointer-events: none;" |
28 | 28 | class="md-headline tb-absolute-fill"> | ... | ... |
... | ... | @@ -26,11 +26,11 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading"> | |
33 | + <fieldset ng-disabled="$root.loading"> | |
34 | 34 | <div layout="row" layout-align="start center"> |
35 | 35 | <md-checkbox ng-disabled="true" flex aria-label="{{ 'layout.main' | translate }}" |
36 | 36 | ng-model="vm.displayLayouts.main">{{ 'layout.main' | translate }} |
... | ... | @@ -56,10 +56,10 @@ |
56 | 56 | </md-dialog-content> |
57 | 57 | <md-dialog-actions layout="row"> |
58 | 58 | <span flex></span> |
59 | - <md-button ng-disabled="loading || !theForm.$dirty || !theForm.$valid" type="submit" class="md-raised md-primary"> | |
59 | + <md-button ng-disabled="$root.loading || !theForm.$dirty || !theForm.$valid" type="submit" class="md-raised md-primary"> | |
60 | 60 | {{ 'action.save' | translate }} |
61 | 61 | </md-button> |
62 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
62 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
63 | 63 | </md-dialog-actions> |
64 | 64 | </form> |
65 | 65 | </md-dialog> | ... | ... |
... | ... | @@ -26,11 +26,11 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading"> | |
33 | + <fieldset ng-disabled="$root.loading"> | |
34 | 34 | <div layout="row" layout-align="start center"> |
35 | 35 | <md-button flex class="tb-layout-button md-raised md-primary" layout="column" |
36 | 36 | ng-click="vm.selectLayout($event, 'main')"> | ... | ... |
... | ... | @@ -26,12 +26,12 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <md-content class="md-padding" layout="column"> |
34 | - <fieldset ng-disabled="loading"> | |
34 | + <fieldset ng-disabled="$root.loading"> | |
35 | 35 | <md-input-container class="md-block"> |
36 | 36 | <label translate>dashboard.state-name</label> |
37 | 37 | <input name="name" required ng-model="vm.state.name"> |
... | ... | @@ -57,11 +57,11 @@ |
57 | 57 | </md-dialog-content> |
58 | 58 | <md-dialog-actions layout="row"> |
59 | 59 | <span flex></span> |
60 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
60 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
61 | 61 | class="md-raised md-primary"> |
62 | 62 | {{ (vm.isAdd ? 'action.add' : 'action.save') | translate }} |
63 | 63 | </md-button> |
64 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;"> | |
64 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;"> | |
65 | 65 | {{ 'action.cancel' | translate }} |
66 | 66 | </md-button> |
67 | 67 | </md-dialog-actions> | ... | ... |
... | ... | @@ -26,11 +26,11 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading"> | |
33 | + <fieldset ng-disabled="$root.loading"> | |
34 | 34 | <div class="manage-dashboard-states" layout="column"> |
35 | 35 | <md-toolbar class="md-table-toolbar md-default" ng-show="vm.query.search === null"> |
36 | 36 | <div class="md-toolbar-tools"> |
... | ... | @@ -118,10 +118,10 @@ |
118 | 118 | </md-dialog-content> |
119 | 119 | <md-dialog-actions layout="row"> |
120 | 120 | <span flex></span> |
121 | - <md-button ng-disabled="loading || !theForm.$dirty || !theForm.$valid" type="submit" class="md-raised md-primary"> | |
121 | + <md-button ng-disabled="$root.loading || !theForm.$dirty || !theForm.$valid" type="submit" class="md-raised md-primary"> | |
122 | 122 | {{ 'action.save' | translate }} |
123 | 123 | </md-button> |
124 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
124 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
125 | 125 | </md-dialog-actions> |
126 | 126 | </form> |
127 | 127 | </md-dialog> | ... | ... |
... | ... | @@ -26,11 +26,11 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading"> | |
33 | + <fieldset ng-disabled="$root.loading"> | |
34 | 34 | <md-select required aria-label="{{ 'dashboard.state' | translate }}" ng-model="vm.stateId"> |
35 | 35 | <md-option ng-repeat="(stateId, state) in vm.states" ng-value="stateId"> |
36 | 36 | {{state.name}} |
... | ... | @@ -41,10 +41,10 @@ |
41 | 41 | </md-dialog-content> |
42 | 42 | <md-dialog-actions layout="row"> |
43 | 43 | <span flex></span> |
44 | - <md-button ng-disabled="loading || !theForm.$dirty || !theForm.$valid" type="submit" class="md-raised md-primary"> | |
44 | + <md-button ng-disabled="$root.loading || !theForm.$dirty || !theForm.$valid" type="submit" class="md-raised md-primary"> | |
45 | 45 | {{ 'action.save' | translate }} |
46 | 46 | </md-button> |
47 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
47 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
48 | 48 | </md-dialog-actions> |
49 | 49 | </form> |
50 | 50 | </md-dialog> | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-device device="vm.item" is-edit="true" the-form="theForm"></tb-device> |
... | ... | @@ -36,10 +36,10 @@ |
36 | 36 | </md-dialog-content> |
37 | 37 | <md-dialog-actions layout="row"> |
38 | 38 | <span flex></span> |
39 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
40 | 40 | {{ 'action.add' | translate }} |
41 | 41 | </md-button> |
42 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
42 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
43 | 43 | </md-dialog-actions> |
44 | 44 | </form> |
45 | 45 | </md-dialog> |
\ No newline at end of file | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <fieldset> |
... | ... | @@ -65,11 +65,11 @@ |
65 | 65 | </md-dialog-content> |
66 | 66 | <md-dialog-actions layout="row"> |
67 | 67 | <span flex></span> |
68 | - <md-button ng-disabled="loading || vm.devices.selectedCount == 0" type="submit" | |
68 | + <md-button ng-disabled="$root.loading || vm.devices.selectedCount == 0" type="submit" | |
69 | 69 | class="md-raised md-primary"> |
70 | 70 | {{ 'action.assign' | translate }} |
71 | 71 | </md-button> |
72 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
72 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
73 | 73 | translate }} |
74 | 74 | </md-button> |
75 | 75 | </md-dialog-actions> | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <fieldset> |
... | ... | @@ -65,10 +65,10 @@ |
65 | 65 | </md-dialog-content> |
66 | 66 | <md-dialog-actions layout="row"> |
67 | 67 | <span flex></span> |
68 | - <md-button ng-disabled="loading || vm.customers.selection==null" type="submit" class="md-raised md-primary"> | |
68 | + <md-button ng-disabled="$root.loading || vm.customers.selection==null" type="submit" class="md-raised md-primary"> | |
69 | 69 | {{ 'action.assign' | translate }} |
70 | 70 | </md-button> |
71 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
71 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
72 | 72 | translate }} |
73 | 73 | </md-button> |
74 | 74 | </md-dialog-actions> | ... | ... |
... | ... | @@ -26,14 +26,14 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading || vm.isReadOnly"> | |
33 | + <fieldset ng-disabled="$root.loading || vm.isReadOnly"> | |
34 | 34 | <md-input-container class="md-block"> |
35 | 35 | <label translate>device.credentials-type</label> |
36 | - <md-select ng-disabled="loading || vm.isReadOnly" ng-model="vm.deviceCredentials.credentialsType" | |
36 | + <md-select ng-disabled="$root.loading || vm.isReadOnly" ng-model="vm.deviceCredentials.credentialsType" | |
37 | 37 | ng-change="vm.clear()"> |
38 | 38 | <md-option ng-repeat="credentialsType in vm.credentialsTypes" value="{{credentialsType.value}}"> |
39 | 39 | {{credentialsType.name}} |
... | ... | @@ -62,10 +62,10 @@ |
62 | 62 | </md-dialog-content> |
63 | 63 | <md-dialog-actions layout="row"> |
64 | 64 | <span flex></span> |
65 | - <md-button ng-if="!vm.isReadOnly" ng-disabled="loading || theForm.$invalid || !theForm.$dirty || !vm.valid()" type="submit" class="md-raised md-primary"> | |
65 | + <md-button ng-if="!vm.isReadOnly" ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty || !vm.valid()" type="submit" class="md-raised md-primary"> | |
66 | 66 | {{ 'action.save' | translate }} |
67 | 67 | </md-button> |
68 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ (vm.isReadOnly ? 'action.close' : 'action.cancel') | translate }}</md-button> | |
68 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ (vm.isReadOnly ? 'action.close' : 'action.cancel') | translate }}</md-button> | |
69 | 69 | </md-dialog-actions> |
70 | 70 | </form> |
71 | 71 | </md-dialog> |
\ No newline at end of file | ... | ... |
... | ... | @@ -58,7 +58,7 @@ |
58 | 58 | ng-show="!isEdit && isPublic && (deviceScope === 'customer' || deviceScope === 'tenant')"> |
59 | 59 | {{ 'device.device-public' | translate }} |
60 | 60 | </div> |
61 | - <fieldset ng-disabled="loading || !isEdit"> | |
61 | + <fieldset ng-disabled="$root.loading || !isEdit"> | |
62 | 62 | <md-input-container class="md-block"> |
63 | 63 | <label translate>device.name</label> |
64 | 64 | <input required name="name" ng-model="device.name"> |
... | ... | @@ -67,14 +67,14 @@ |
67 | 67 | </div> |
68 | 68 | </md-input-container> |
69 | 69 | <tb-entity-subtype-autocomplete |
70 | - ng-disabled="loading || !isEdit" | |
70 | + ng-disabled="$root.loading || !isEdit" | |
71 | 71 | tb-required="true" |
72 | 72 | the-form="theForm" |
73 | 73 | ng-model="device.type" |
74 | 74 | entity-type="types.entityType.device"> |
75 | 75 | </tb-entity-subtype-autocomplete> |
76 | 76 | <md-input-container class="md-block"> |
77 | - <md-checkbox ng-disabled="loading || !isEdit" flex aria-label="{{ 'device.is-gateway' | translate }}" | |
77 | + <md-checkbox ng-disabled="$root.loading || !isEdit" flex aria-label="{{ 'device.is-gateway' | translate }}" | |
78 | 78 | ng-model="device.additionalInfo.gateway">{{ 'device.is-gateway' | translate }} |
79 | 79 | </md-checkbox> |
80 | 80 | </md-input-container> | ... | ... |
... | ... | @@ -26,11 +26,11 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading"> | |
33 | + <fieldset ng-disabled="$root.loading"> | |
34 | 34 | <div flex layout="column"> |
35 | 35 | <div layout="row"> |
36 | 36 | <md-input-container flex class="md-block"> |
... | ... | @@ -64,10 +64,10 @@ |
64 | 64 | </md-dialog-content> |
65 | 65 | <md-dialog-actions layout="row"> |
66 | 66 | <span flex></span> |
67 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
67 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
68 | 68 | {{ (vm.isAdd ? 'action.add' : 'action.save') | translate }} |
69 | 69 | </md-button> |
70 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
70 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
71 | 71 | </md-dialog-actions> |
72 | 72 | </form> |
73 | 73 | </md-dialog> | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <div class="tb-aliases-header" flex layout="row" layout-align="start center"> |
32 | 32 | <span flex="5"></span> |
33 | 33 | <div flex layout="row" layout-align="start center"> |
... | ... | @@ -40,7 +40,7 @@ |
40 | 40 | <md-divider></md-divider> |
41 | 41 | <md-dialog-content> |
42 | 42 | <div class="md-dialog-content"> |
43 | - <fieldset ng-disabled="loading"> | |
43 | + <fieldset ng-disabled="$root.loading"> | |
44 | 44 | <div ng-form name="aliasForm" flex layout="row" layout-align="start center" ng-repeat="entityAlias in vm.entityAliases track by $index"> |
45 | 45 | <span flex="5">{{$index + 1}}.</span> |
46 | 46 | <di class="md-whiteframe-4dp tb-alias" flex layout="row" layout-align="start center"> |
... | ... | @@ -63,7 +63,7 @@ |
63 | 63 | aria-label="resolve-multiple-switcher"> |
64 | 64 | </md-switch> |
65 | 65 | </section> |
66 | - <md-button ng-disabled="loading" class="md-icon-button md-primary" style="min-width: 40px;" | |
66 | + <md-button ng-disabled="$root.loading" class="md-icon-button md-primary" style="min-width: 40px;" | |
67 | 67 | ng-click="vm.editAlias($event, entityAlias)" aria-label="{{ 'action.edit' | translate }}"> |
68 | 68 | <md-tooltip md-direction="top"> |
69 | 69 | {{ 'alias.edit' | translate }} |
... | ... | @@ -72,7 +72,7 @@ |
72 | 72 | edit |
73 | 73 | </md-icon> |
74 | 74 | </md-button> |
75 | - <md-button ng-disabled="loading" class="md-icon-button md-primary" style="min-width: 40px;" | |
75 | + <md-button ng-disabled="$root.loading" class="md-icon-button md-primary" style="min-width: 40px;" | |
76 | 76 | ng-click="vm.removeAlias($event, entityAlias)" aria-label="{{ 'action.remove' | translate }}"> |
77 | 77 | <md-tooltip md-direction="top"> |
78 | 78 | {{ 'entity.remove-alias' | translate }} |
... | ... | @@ -87,7 +87,7 @@ |
87 | 87 | </div> |
88 | 88 | </md-dialog-content> |
89 | 89 | <md-dialog-actions layout="row"> |
90 | - <md-button ng-show="!vm.disableAdd" ng-disabled="loading" class="md-primary md-raised" | |
90 | + <md-button ng-show="!vm.disableAdd" ng-disabled="$root.loading" class="md-primary md-raised" | |
91 | 91 | ng-click="vm.addAlias($event)" |
92 | 92 | aria-label="{{ 'alias.add' | translate }}"> |
93 | 93 | <md-tooltip md-direction="top"> |
... | ... | @@ -96,10 +96,10 @@ |
96 | 96 | <span translate>alias.add</span> |
97 | 97 | </md-button> |
98 | 98 | <span flex></span> |
99 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
99 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
100 | 100 | {{ 'action.save' | translate }} |
101 | 101 | </md-button> |
102 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
102 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
103 | 103 | </md-dialog-actions> |
104 | 104 | </form> |
105 | 105 | </md-dialog> |
\ No newline at end of file | ... | ... |
... | ... | @@ -26,12 +26,12 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <md-content class="md-padding" layout="column"> |
34 | - <fieldset ng-disabled="loading"> | |
34 | + <fieldset ng-disabled="$root.loading"> | |
35 | 35 | <md-input-container class="md-block"> |
36 | 36 | <label translate>attribute.key</label> |
37 | 37 | <input required name="key" ng-model="vm.attribute.key"> |
... | ... | @@ -42,7 +42,7 @@ |
42 | 42 | <section layout="row"> |
43 | 43 | <md-input-container flex="40" class="md-block" style="width: 200px;"> |
44 | 44 | <label translate>value.type</label> |
45 | - <md-select ng-model="vm.valueType" ng-disabled="loading()"> | |
45 | + <md-select ng-model="vm.valueType" ng-disabled="$root.loading"> | |
46 | 46 | <md-option ng-repeat="type in vm.valueTypes" ng-value="type"> |
47 | 47 | <md-icon md-svg-icon="{{ type.icon }}"></md-icon> |
48 | 48 | <span>{{type.name | translate}}</span> |
... | ... | @@ -83,11 +83,11 @@ |
83 | 83 | </md-dialog-content> |
84 | 84 | <md-dialog-actions layout="row"> |
85 | 85 | <span flex></span> |
86 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
86 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
87 | 87 | class="md-raised md-primary"> |
88 | 88 | {{ 'action.add' | translate }} |
89 | 89 | </md-button> |
90 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
90 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
91 | 91 | translate }} |
92 | 92 | </md-button> |
93 | 93 | </md-dialog-actions> | ... | ... |
... | ... | @@ -26,18 +26,18 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <md-content class="md-padding" layout="column"> |
34 | - <fieldset ng-disabled="loading"> | |
34 | + <fieldset ng-disabled="$root.loading"> | |
35 | 35 | <md-radio-group ng-model="vm.addToDashboardType" class="md-primary"> |
36 | 36 | <md-radio-button flex ng-value=0 class="md-primary md-align-top-left md-radio-interactive"> |
37 | 37 | <section flex layout="column" style="width: 300px;"> |
38 | 38 | <span translate style="padding-bottom: 10px;">dashboard.select-existing</span> |
39 | 39 | <tb-dashboard-autocomplete the-form="theForm" |
40 | - ng-disabled="loading || vm.addToDashboardType != 0" | |
40 | + ng-disabled="$root.loading || vm.addToDashboardType != 0" | |
41 | 41 | tb-required="vm.addToDashboardType === 0" |
42 | 42 | ng-model="vm.dashboardId" |
43 | 43 | select-first-dashboard="false"> |
... | ... | @@ -69,11 +69,11 @@ |
69 | 69 | style="margin-bottom: 0px; padding-right: 20px;"> |
70 | 70 | {{ 'dashboard.open-dashboard' | translate }} |
71 | 71 | </md-checkbox> |
72 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
72 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
73 | 73 | class="md-raised md-primary"> |
74 | 74 | {{ 'action.add' | translate }} |
75 | 75 | </md-button> |
76 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
76 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
77 | 77 | translate }} |
78 | 78 | </md-button> |
79 | 79 | </md-dialog-actions> | ... | ... |
... | ... | @@ -19,7 +19,7 @@ |
19 | 19 | <section ng-show="!disableAttributeScopeSelection"> |
20 | 20 | <md-input-container class="md-block" style="width: 200px;"> |
21 | 21 | <label translate>attribute.attributes-scope</label> |
22 | - <md-select ng-model="attributeScope" ng-disabled="loading() || attributeScopeSelectionReadonly"> | |
22 | + <md-select ng-model="attributeScope" ng-disabled="$root.loading || attributeScopeSelectionReadonly"> | |
23 | 23 | <md-option ng-repeat="scope in attributeScopes" ng-value="scope"> |
24 | 24 | {{scope.name | translate}} |
25 | 25 | </md-option> | ... | ... |
... | ... | @@ -38,7 +38,7 @@ export default function EntityAutocomplete($compile, $templateCache, $q, $filter |
38 | 38 | if (scope.excludeEntityIds && scope.excludeEntityIds.length) { |
39 | 39 | limit += scope.excludeEntityIds.length; |
40 | 40 | } |
41 | - entityService.getEntitiesByNameFilter(scope.entityType, searchText, limit, null, scope.entitySubtype).then(function success(result) { | |
41 | + entityService.getEntitiesByNameFilter(scope.entityType, searchText, limit, {ignoreLoading: true}, scope.entitySubtype).then(function success(result) { | |
42 | 42 | if (result) { |
43 | 43 | if (scope.excludeEntityIds && scope.excludeEntityIds.length) { |
44 | 44 | var entities = []; | ... | ... |
... | ... | @@ -38,7 +38,7 @@ export default function EntityListDirective($compile, $templateCache, $q, $mdUti |
38 | 38 | |
39 | 39 | scope.fetchEntities = function(searchText, limit) { |
40 | 40 | var deferred = $q.defer(); |
41 | - entityService.getEntitiesByNameFilter(scope.entityType, searchText, limit).then( | |
41 | + entityService.getEntitiesByNameFilter(scope.entityType, searchText, limit, {ignoreLoading: true}).then( | |
42 | 42 | function success(result) { |
43 | 43 | if (result) { |
44 | 44 | deferred.resolve(result); | ... | ... |
... | ... | @@ -93,9 +93,9 @@ export default function EntitySubtypeAutocomplete($compile, $templateCache, $q, |
93 | 93 | if (!scope.entitySubtypes) { |
94 | 94 | var entitySubtypesPromise; |
95 | 95 | if (scope.entityType == types.entityType.asset) { |
96 | - entitySubtypesPromise = assetService.getAssetTypes(); | |
96 | + entitySubtypesPromise = assetService.getAssetTypes({ignoreLoading: true}); | |
97 | 97 | } else if (scope.entityType == types.entityType.device) { |
98 | - entitySubtypesPromise = deviceService.getDeviceTypes(); | |
98 | + entitySubtypesPromise = deviceService.getDeviceTypes({ignoreLoading: true}); | |
99 | 99 | } |
100 | 100 | if (entitySubtypesPromise) { |
101 | 101 | entitySubtypesPromise.then( | ... | ... |
... | ... | @@ -95,9 +95,9 @@ export default function EntitySubtypeListDirective($compile, $templateCache, $q, |
95 | 95 | if (!scope.entitySubtypes) { |
96 | 96 | var entitySubtypesPromise; |
97 | 97 | if (scope.entityType == types.entityType.asset) { |
98 | - entitySubtypesPromise = assetService.getAssetTypes(); | |
98 | + entitySubtypesPromise = assetService.getAssetTypes({ignoreLoading: true}); | |
99 | 99 | } else if (scope.entityType == types.entityType.device) { |
100 | - entitySubtypesPromise = deviceService.getDeviceTypes(); | |
100 | + entitySubtypesPromise = deviceService.getDeviceTypes({ignoreLoading: true}); | |
101 | 101 | } |
102 | 102 | if (entitySubtypesPromise) { |
103 | 103 | entitySubtypesPromise.then( | ... | ... |
... | ... | @@ -73,9 +73,9 @@ export default function EntitySubtypeSelect($compile, $templateCache, $translate |
73 | 73 | scope.entitySubtypes = []; |
74 | 74 | var entitySubtypesPromise; |
75 | 75 | if (scope.entityType == types.entityType.asset) { |
76 | - entitySubtypesPromise = assetService.getAssetTypes(); | |
76 | + entitySubtypesPromise = assetService.getAssetTypes({ignoreLoading: true}); | |
77 | 77 | } else if (scope.entityType == types.entityType.device) { |
78 | - entitySubtypesPromise = deviceService.getDeviceTypes(); | |
78 | + entitySubtypesPromise = deviceService.getDeviceTypes({ignoreLoading: true}); | |
79 | 79 | } |
80 | 80 | if (entitySubtypesPromise) { |
81 | 81 | entitySubtypesPromise.then( | ... | ... |
... | ... | @@ -26,16 +26,16 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <md-content class="md-padding" layout="column"> |
34 | - <fieldset ng-disabled="loading"> | |
34 | + <fieldset ng-disabled="$root.loading"> | |
35 | 35 | <tb-relation-type-autocomplete ng-disabled="!vm.isAdd" |
36 | 36 | ng-model="vm.relation.type" |
37 | 37 | tb-required="true" |
38 | - ng-disabled="loading"> | |
38 | + ng-disabled="$root.loading"> | |
39 | 39 | </tb-relation-type-autocomplete> |
40 | 40 | <small>{{(vm.direction == vm.types.entitySearchDirection.from ? |
41 | 41 | 'relation.to-entity' : 'relation.from-entity') | translate}}</small> |
... | ... | @@ -61,11 +61,11 @@ |
61 | 61 | </md-dialog-content> |
62 | 62 | <md-dialog-actions layout="row"> |
63 | 63 | <span flex></span> |
64 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
64 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
65 | 65 | class="md-raised md-primary"> |
66 | 66 | {{ (vm.isAdd ? 'action.add' : 'action.save') | translate }} |
67 | 67 | </md-button> |
68 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
68 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
69 | 69 | translate }} |
70 | 70 | </md-button> |
71 | 71 | </md-dialog-actions> | ... | ... |
... | ... | @@ -37,7 +37,7 @@ |
37 | 37 | allowed-entity-types="allowedEntityTypes" |
38 | 38 | tb-required="false"> |
39 | 39 | </tb-entity-type-list> |
40 | - <md-button ng-disabled="loading" class="md-icon-button md-primary" style="width: 40px; min-width: 40px;" | |
40 | + <md-button ng-disabled="$root.loading" class="md-icon-button md-primary" style="width: 40px; min-width: 40px;" | |
41 | 41 | ng-click="removeFilter($event, filter)" aria-label="{{ 'action.remove' | translate }}"> |
42 | 42 | <md-tooltip md-direction="top"> |
43 | 43 | {{ 'relation.remove-relation-filter' | translate }} |
... | ... | @@ -54,7 +54,7 @@ |
54 | 54 | class="tb-prompt" translate>relation.any-relation</span> |
55 | 55 | </div> |
56 | 56 | <div> |
57 | - <md-button ng-disabled="loading" class="md-primary md-raised" ng-click="addFilter($event)" aria-label="{{ 'action.add' | translate }}"> | |
57 | + <md-button ng-disabled="$root.loading" class="md-primary md-raised" ng-click="addFilter($event)" aria-label="{{ 'action.add' | translate }}"> | |
58 | 58 | <md-tooltip md-direction="top"> |
59 | 59 | {{ 'relation.add-relation-filter' | translate }} |
60 | 60 | </md-tooltip> | ... | ... |
... | ... | @@ -19,7 +19,7 @@ |
19 | 19 | <section layout="row"> |
20 | 20 | <md-input-container class="md-block" style="width: 200px;"> |
21 | 21 | <label translate>relation.direction</label> |
22 | - <md-select ng-model="vm.direction" ng-disabled="loading"> | |
22 | + <md-select ng-model="vm.direction" ng-disabled="$root.loading"> | |
23 | 23 | <md-option ng-repeat="direction in vm.types.entitySearchDirection" ng-value="direction"> |
24 | 24 | {{ ('relation.search-direction.' + direction) | translate}} |
25 | 25 | </md-option> | ... | ... |
... | ... | @@ -35,7 +35,7 @@ |
35 | 35 | </md-dialog-content> |
36 | 36 | <md-dialog-actions layout="row"> |
37 | 37 | <span flex></span> |
38 | - <md-button ng-disabled="loading" ng-click="vm.close()" style="margin-right:20px;">{{ 'action.close' | | |
38 | + <md-button ng-disabled="$root.loading" ng-click="vm.close()" style="margin-right:20px;">{{ 'action.close' | | |
39 | 39 | translate }} |
40 | 40 | </md-button> |
41 | 41 | </md-dialog-actions> | ... | ... |
... | ... | @@ -19,7 +19,7 @@ |
19 | 19 | <section layout="row"> |
20 | 20 | <md-input-container class="md-block" style="width: 200px;"> |
21 | 21 | <label translate>event.event-type</label> |
22 | - <md-select ng-model="eventType" ng-disabled="loading()"> | |
22 | + <md-select ng-model="eventType" ng-disabled="$root.loading"> | |
23 | 23 | <md-option ng-repeat="type in eventTypes" ng-value="type.value"> |
24 | 24 | {{type.name | translate}} |
25 | 25 | </md-option> |
... | ... | @@ -30,8 +30,8 @@ |
30 | 30 | <md-list flex layout="column" class="md-whiteframe-z1 tb-event-table"> |
31 | 31 | <md-list class="tb-row tb-header" layout="row" tb-event-header event-type="{{eventType}}"> |
32 | 32 | </md-list> |
33 | - <md-progress-linear style="max-height: 0px;" md-mode="indeterminate" ng-disabled="!loading()" | |
34 | - ng-show="loading()"></md-progress-linear> | |
33 | + <md-progress-linear style="max-height: 0px;" md-mode="indeterminate" ng-disabled="!$root.loading" | |
34 | + ng-show="$root.loading"></md-progress-linear> | |
35 | 35 | <md-divider></md-divider> |
36 | 36 | <span translate layout-align="center center" |
37 | 37 | style="margin-top: 25px;" | ... | ... |
... | ... | @@ -27,14 +27,14 @@ |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | 29 | |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | 31 | |
32 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
32 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
33 | 33 | |
34 | 34 | <md-dialog-content> |
35 | 35 | <div class="md-dialog-content"> |
36 | 36 | <md-content class="md-padding" layout="column"> |
37 | - <fieldset ng-disabled="loading"> | |
37 | + <fieldset ng-disabled="$root.loading"> | |
38 | 38 | <section flex layout="row"> |
39 | 39 | <md-input-container flex="60" class="md-block" md-is-error="theForm.extensionId.$touched && theForm.extensionId.$invalid"> |
40 | 40 | <label translate>extension.extension-id</label> |
... | ... | @@ -74,7 +74,7 @@ |
74 | 74 | {{ (vm.isAdd ? 'action.add' : 'action.save') | translate }} |
75 | 75 | </md-button> |
76 | 76 | |
77 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }} | |
77 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }} | |
78 | 78 | </md-button> |
79 | 79 | </md-dialog-actions> |
80 | 80 | </form> | ... | ... |
... | ... | @@ -26,11 +26,11 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading"> | |
33 | + <fieldset ng-disabled="$root.loading"> | |
34 | 34 | <div layout="column" layout-padding> |
35 | 35 | <div class="tb-container"> |
36 | 36 | <label class="tb-label" translate>{{ vm.importFileLabel }}</label> |
... | ... | @@ -63,10 +63,10 @@ |
63 | 63 | </md-dialog-content> |
64 | 64 | <md-dialog-actions layout="row"> |
65 | 65 | <span flex></span> |
66 | - <md-button ng-disabled="loading || !theForm.$dirty || !theForm.$valid || !vm.importData" type="submit" class="md-raised md-primary"> | |
66 | + <md-button ng-disabled="$root.loading || !theForm.$dirty || !theForm.$valid || !vm.importData" type="submit" class="md-raised md-primary"> | |
67 | 67 | {{ 'action.import' | translate }} |
68 | 68 | </md-button> |
69 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
69 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
70 | 70 | </md-dialog-actions> |
71 | 71 | </form> |
72 | 72 | </md-dialog> | ... | ... |
... | ... | @@ -76,7 +76,7 @@ |
76 | 76 | </tb-user-menu> |
77 | 77 | </div> |
78 | 78 | </md-toolbar> |
79 | - <md-progress-linear class="md-warn" style="z-index: 10; max-height: 0px; width: 100%;" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
79 | + <md-progress-linear class="md-warn" style="z-index: 10; max-height: 0px; width: 100%;" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
80 | 80 | |
81 | 81 | <div flex layout="column" id="toast-parent" style="position: relative;"> |
82 | 82 | <md-content ng-cloak flex layout="column" class="page-content" ui-view name="content"></md-content> | ... | ... |
... | ... | @@ -1213,6 +1213,7 @@ export default angular.module('thingsboard.locale', []) |
1213 | 1213 | "remove-widget-title": "Are you sure you want to remove the widget '{{widgetTitle}}'?", |
1214 | 1214 | "remove-widget-text": "After the confirmation the widget and all related data will become unrecoverable.", |
1215 | 1215 | "timeseries": "Time series", |
1216 | + "search-data": "Search data", | |
1216 | 1217 | "latest-values": "Latest values", |
1217 | 1218 | "rpc": "Control widget", |
1218 | 1219 | "alarm": "Alarm widget", | ... | ... |
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | </md-card-title-text> |
24 | 24 | </md-card-title> |
25 | 25 | <md-progress-linear class="md-warn" style="z-index: 1; max-height: 5px; width: inherit; position: absolute" |
26 | - md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
26 | + md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
27 | 27 | <md-card-content> |
28 | 28 | <form class="create-password-form" ng-submit="vm.createPassword()"> |
29 | 29 | <div layout="column" layout-padding="" id="toast-parent"> | ... | ... |
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | </md-card-title-text> |
24 | 24 | </md-card-title> |
25 | 25 | <md-progress-linear class="md-warn" style="z-index: 1; max-height: 5px; width: inherit; position: absolute" |
26 | - md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
26 | + md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
27 | 27 | <md-card-content> |
28 | 28 | <form class="login-form" ng-submit="vm.login()"> |
29 | 29 | <div layout="column" layout-padding="" id="toast-parent"> | ... | ... |
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | </md-card-title-text> |
24 | 24 | </md-card-title> |
25 | 25 | <md-progress-linear class="md-warn" style="z-index: 1; max-height: 5px; width: inherit; position: absolute" |
26 | - md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
26 | + md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
27 | 27 | <md-card-content> |
28 | 28 | <form class="request-password-reset-form" ng-submit="vm.sendResetPasswordLink()"> |
29 | 29 | <div layout="column" layout-padding="" id="toast-parent"> | ... | ... |
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | </md-card-title-text> |
24 | 24 | </md-card-title> |
25 | 25 | <md-progress-linear class="md-warn" style="z-index: 1; max-height: 5px; width: inherit; position: absolute" |
26 | - md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
26 | + md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
27 | 27 | <md-card-content> |
28 | 28 | <form class="password-reset-form" ng-submit="vm.resetPassword()"> |
29 | 29 | <div layout="column" layout-padding="" id="toast-parent"> | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-plugin plugin="vm.item" is-edit="true" the-form="theForm"></tb-plugin> |
... | ... | @@ -36,11 +36,11 @@ |
36 | 36 | </md-dialog-content> |
37 | 37 | <md-dialog-actions layout="row"> |
38 | 38 | <span flex></span> |
39 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
40 | 40 | class="md-raised md-primary"> |
41 | 41 | {{ 'action.add' | translate }} |
42 | 42 | </md-button> |
43 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
43 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
44 | 44 | translate }} |
45 | 45 | </md-button> |
46 | 46 | </md-dialog-actions> | ... | ... |
... | ... | @@ -39,7 +39,7 @@ |
39 | 39 | </div> |
40 | 40 | |
41 | 41 | <md-content class="md-padding" layout="column" style="overflow-x: hidden"> |
42 | - <fieldset ng-disabled="loading || !isEdit || isReadOnly"> | |
42 | + <fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> | |
43 | 43 | <md-input-container class="md-block"> |
44 | 44 | <label translate>plugin.name</label> |
45 | 45 | <input required name="name" ng-model="plugin.name"> |
... | ... | @@ -61,7 +61,7 @@ |
61 | 61 | </md-input-container> |
62 | 62 | <md-input-container flex class="md-block"> |
63 | 63 | <label translate>plugin.type</label> |
64 | - <md-select required name="pluginType" ng-model="plugin.clazz" ng-disabled="loading || !isEdit"> | |
64 | + <md-select required name="pluginType" ng-model="plugin.clazz" ng-disabled="$root.loading || !isEdit"> | |
65 | 65 | <md-option ng-repeat="component in pluginComponents" ng-value="component.clazz"> |
66 | 66 | {{component.name}} |
67 | 67 | </md-option> |
... | ... | @@ -74,14 +74,14 @@ |
74 | 74 | <md-card flex class="plugin-config" ng-if="showPluginConfig"> |
75 | 75 | <md-card-title> |
76 | 76 | <md-card-title-text> |
77 | - <span translate class="md-headline" ng-class="{'tb-readonly-label' : (loading || !isEdit || isReadOnly)}">plugin.configuration</span> | |
77 | + <span translate class="md-headline" ng-class="{'tb-readonly-label' : ($root.loading || !isEdit || isReadOnly)}">plugin.configuration</span> | |
78 | 78 | </md-card-title-text> |
79 | 79 | </md-card-title> |
80 | 80 | <md-card-content> |
81 | 81 | <tb-json-form schema="pluginComponent.configurationDescriptor.schema" |
82 | 82 | form="pluginComponent.configurationDescriptor.form" |
83 | 83 | model="pluginConfiguration.data" |
84 | - readonly="loading || !isEdit || isReadOnly" | |
84 | + readonly="$root.loading || !isEdit || isReadOnly" | |
85 | 85 | form-control="theForm"> |
86 | 86 | </tb-json-form> |
87 | 87 | </md-card-content> | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <md-input-container class="md-block"> |
... | ... | @@ -55,10 +55,10 @@ |
55 | 55 | </md-dialog-content> |
56 | 56 | <md-dialog-actions layout="row"> |
57 | 57 | <span flex></span> |
58 | - <md-button ng-disabled="loading || theForm.$invalid" type="submit" class="md-raised md-primary"> | |
58 | + <md-button ng-disabled="$root.loading || theForm.$invalid" type="submit" class="md-raised md-primary"> | |
59 | 59 | {{ 'profile.change-password' | translate }} |
60 | 60 | </md-button> |
61 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
61 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
62 | 62 | </md-dialog-actions> |
63 | 63 | </form> |
64 | 64 | </md-dialog> | ... | ... |
... | ... | @@ -23,11 +23,11 @@ |
23 | 23 | <span style='opacity: 0.7;'>{{ vm.profileUser.email }}</span> |
24 | 24 | </md-card-title-text> |
25 | 25 | </md-card-title> |
26 | - <md-progress-linear md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
27 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
26 | + <md-progress-linear md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
27 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
28 | 28 | <md-card-content> |
29 | 29 | <form name="theForm" ng-submit="vm.save()" tb-confirm-on-exit confirm-form="theForm"> |
30 | - <fieldset ng-disabled="loading"> | |
30 | + <fieldset ng-disabled="$root.loading"> | |
31 | 31 | <md-input-container class="md-block"> |
32 | 32 | <label translate>user.email</label> |
33 | 33 | <input name="email" type="email" ng-model="vm.profileUser.email"> |
... | ... | @@ -48,11 +48,11 @@ |
48 | 48 | </md-option> |
49 | 49 | </md-select> |
50 | 50 | </md-input-container> |
51 | - <md-button ng-disabled="loading" ng-click="vm.changePassword($event)" | |
51 | + <md-button ng-disabled="$root.loading" ng-click="vm.changePassword($event)" | |
52 | 52 | class="md-raised md-primary">{{ 'profile.change-password' | translate }} |
53 | 53 | </md-button> |
54 | 54 | <div layout="row" layout-align="end center" width="100%" layout-wrap> |
55 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
55 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
56 | 56 | class="md-raised md-primary">{{ 'action.save' | translate }} |
57 | 57 | </md-button> |
58 | 58 | </div> | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-rule rule="vm.item" is-edit="true" the-form="theForm"></tb-rule> |
... | ... | @@ -36,11 +36,11 @@ |
36 | 36 | </md-dialog-content> |
37 | 37 | <md-dialog-actions layout="row"> |
38 | 38 | <span flex></span> |
39 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
40 | 40 | class="md-raised md-primary"> |
41 | 41 | {{ 'action.add' | translate }} |
42 | 42 | </md-button> |
43 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
43 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
44 | 44 | translate }} |
45 | 45 | </md-button> |
46 | 46 | </md-dialog-actions> | ... | ... |
... | ... | @@ -39,7 +39,7 @@ |
39 | 39 | </div> |
40 | 40 | |
41 | 41 | <md-content class="md-padding tb-rule" layout="column"> |
42 | - <fieldset ng-disabled="loading || !isEdit || isReadOnly"> | |
42 | + <fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> | |
43 | 43 | <md-input-container class="md-block"> |
44 | 44 | <label translate>rule.name</label> |
45 | 45 | <input required name="name" ng-model="rule.name"> |
... | ... | @@ -109,7 +109,7 @@ |
109 | 109 | </div> |
110 | 110 | </div> |
111 | 111 | <div ng-if="isEdit && !isReadOnly" flex layout="row" layout-align="start center"> |
112 | - <md-button ng-disabled="loading" class="md-primary md-raised" | |
112 | + <md-button ng-disabled="$root.loading" class="md-primary md-raised" | |
113 | 113 | ng-click="addFilter($event)" aria-label="{{ 'action.add' | translate }}"> |
114 | 114 | <md-tooltip md-direction="top"> |
115 | 115 | {{ 'rule.add-filter' | translate }} |
... | ... | @@ -149,7 +149,7 @@ |
149 | 149 | <span ng-if="!isEdit || isReadOnly" translate layout-align="center center" |
150 | 150 | class="tb-prompt">rule.no-processor-configured</span> |
151 | 151 | <div ng-if="isEdit && !isReadOnly" flex layout="row" layout-align="start center"> |
152 | - <md-button ng-disabled="loading" class="md-primary md-raised" | |
152 | + <md-button ng-disabled="$root.loading" class="md-primary md-raised" | |
153 | 153 | ng-click="addProcessor($event)" aria-label="{{ 'action.create' | translate }}"> |
154 | 154 | <md-tooltip md-direction="top"> |
155 | 155 | {{ 'rule.create-processor' | translate }} |
... | ... | @@ -162,7 +162,7 @@ |
162 | 162 | </v-pane-content> |
163 | 163 | </v-pane> |
164 | 164 | </v-accordion> |
165 | - <fieldset ng-disabled="loading || !isEdit || isReadOnly"> | |
165 | + <fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> | |
166 | 166 | <md-input-container ng-if="!isEdit || isReadOnly" flex class="md-block"> |
167 | 167 | <label translate>plugin.plugin</label> |
168 | 168 | <input name="name" ng-model="plugin.name"> |
... | ... | @@ -203,7 +203,7 @@ |
203 | 203 | <span translate layout-align="center center" |
204 | 204 | class="tb-prompt">rule.create-action-prompt</span> |
205 | 205 | <div ng-if="isEdit && !isReadOnly" flex layout="row" layout-align="start center"> |
206 | - <md-button ng-disabled="loading" class="md-primary md-raised" | |
206 | + <md-button ng-disabled="$root.loading" class="md-primary md-raised" | |
207 | 207 | ng-click="addAction($event)" aria-label="{{ 'action.create' | translate }}"> |
208 | 208 | <md-tooltip md-direction="top"> |
209 | 209 | {{ 'rule.create-action' | translate }} | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-tenant tenant="vm.item" is-edit="true" the-form="theForm"></tb-tenant> |
... | ... | @@ -36,11 +36,11 @@ |
36 | 36 | </md-dialog-content> |
37 | 37 | <md-dialog-actions layout="row"> |
38 | 38 | <span flex></span> |
39 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
40 | 40 | class="md-raised md-primary"> |
41 | 41 | {{ 'action.add' | translate }} |
42 | 42 | </md-button> |
43 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
43 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
44 | 44 | translate }} |
45 | 45 | </md-button> |
46 | 46 | </md-dialog-actions> | ... | ... |
... | ... | @@ -29,7 +29,7 @@ |
29 | 29 | </div> |
30 | 30 | |
31 | 31 | <md-content class="md-padding" layout="column"> |
32 | - <fieldset ng-disabled="loading || !isEdit"> | |
32 | + <fieldset ng-disabled="$root.loading || !isEdit"> | |
33 | 33 | <md-input-container class="md-block"> |
34 | 34 | <label translate>tenant.title</label> |
35 | 35 | <input required name="title" ng-model="tenant.title"> | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-user user="vm.item" is-edit="true" the-form="theForm"></tb-user> |
... | ... | @@ -45,10 +45,10 @@ |
45 | 45 | </md-dialog-content> |
46 | 46 | <md-dialog-actions layout="row"> |
47 | 47 | <span flex></span> |
48 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
48 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
49 | 49 | {{ 'action.add' | translate }} |
50 | 50 | </md-button> |
51 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
51 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
52 | 52 | </md-dialog-actions> |
53 | 53 | </form> |
54 | 54 | </md-dialog> | ... | ... |
... | ... | @@ -26,7 +26,7 @@ |
26 | 26 | </md-button> |
27 | 27 | |
28 | 28 | <md-content class="md-padding" layout="column"> |
29 | - <fieldset ng-disabled="loading || !isEdit"> | |
29 | + <fieldset ng-disabled="$root.loading || !isEdit"> | |
30 | 30 | <md-input-container class="md-block"> |
31 | 31 | <label translate>user.email</label> |
32 | 32 | <input required name="email" |
... | ... | @@ -50,11 +50,11 @@ |
50 | 50 | <textarea ng-model="user.additionalInfo.description" rows="2"></textarea> |
51 | 51 | </md-input-container> |
52 | 52 | <section class="tb-default-dashboard" flex layout="column" ng-if="user.id"> |
53 | - <span class="tb-default-dashboard-label" ng-class="{'tb-disabled-label': loading || !isEdit}" translate>user.default-dashboard</span> | |
53 | + <span class="tb-default-dashboard-label" ng-class="{'tb-disabled-label': $root.loading || !isEdit}" translate>user.default-dashboard</span> | |
54 | 54 | <section flex layout="column" layout-gt-sm="row"> |
55 | 55 | <tb-dashboard-autocomplete ng-if="isTenantAdmin()" |
56 | 56 | flex |
57 | - ng-disabled="loading || !isEdit" | |
57 | + ng-disabled="$root.loading || !isEdit" | |
58 | 58 | the-form="theForm" |
59 | 59 | ng-model="user.additionalInfo.defaultDashboardId" |
60 | 60 | tenant-id="user.tenantId.id" |
... | ... | @@ -62,14 +62,14 @@ |
62 | 62 | </tb-dashboard-autocomplete> |
63 | 63 | <tb-dashboard-autocomplete ng-if="isCustomerUser()" |
64 | 64 | flex |
65 | - ng-disabled="loading || !isEdit" | |
65 | + ng-disabled="$root.loading || !isEdit" | |
66 | 66 | the-form="theForm" |
67 | 67 | ng-model="user.additionalInfo.defaultDashboardId" |
68 | 68 | dashboards-scope="customer" |
69 | 69 | customer-id="user.customerId.id" |
70 | 70 | select-first-dashboard="false"> |
71 | 71 | </tb-dashboard-autocomplete> |
72 | - <md-checkbox ng-disabled="loading || !isEdit" flex aria-label="{{ 'user.always-fullscreen' | translate }}" | |
72 | + <md-checkbox ng-disabled="$root.loading || !isEdit" flex aria-label="{{ 'user.always-fullscreen' | translate }}" | |
73 | 73 | ng-model="user.additionalInfo.defaultDashboardFullscreen">{{ 'user.always-fullscreen' | translate }} |
74 | 74 | </md-checkbox> |
75 | 75 | </section> | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </md-button> |
28 | 28 | </div> |
29 | 29 | </md-toolbar> |
30 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
31 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | 32 | <md-dialog-content> |
33 | 33 | <div class="md-dialog-content"> |
34 | 34 | <tb-widgets-bundle widgets-bundle="vm.item" is-edit="true" the-form="theForm"></tb-widgets-bundle> |
... | ... | @@ -36,11 +36,11 @@ |
36 | 36 | </md-dialog-content> |
37 | 37 | <md-dialog-actions layout="row"> |
38 | 38 | <span flex></span> |
39 | - <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" | |
40 | 40 | class="md-raised md-primary"> |
41 | 41 | {{ 'action.add' | translate }} |
42 | 42 | </md-button> |
43 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
43 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
44 | 44 | translate }} |
45 | 45 | </md-button> |
46 | 46 | </md-dialog-actions> | ... | ... |
... | ... | @@ -455,7 +455,7 @@ function barDimensions(context, options, x, y, w, h) { |
455 | 455 | if (options.hideMinMax && options.label === '') { |
456 | 456 | bd.labelY = bd.barBottom; |
457 | 457 | bd.barLeft = bd.origBaseX + options.fontMinMaxSize/3 * bd.fontSizeFactor; |
458 | - bd.barRight = bd.bd.origBaseX + w + /*bd.width*/ - options.fontMinMaxSize/3 * bd.fontSizeFactor; | |
458 | + bd.barRight = bd.origBaseX + w + /*bd.width*/ - options.fontMinMaxSize/3 * bd.fontSizeFactor; | |
459 | 459 | } else { |
460 | 460 | context.font = canvasGauges.drawings.font(options, 'MinMax', bd.fontSizeFactor); |
461 | 461 | var minTextWidth = context.measureText(options.minValue+'').width; | ... | ... |
... | ... | @@ -124,7 +124,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia |
124 | 124 | $scope.$on('alarms-table-data-updated', function(event, tableId) { |
125 | 125 | if (vm.tableId == tableId) { |
126 | 126 | if (vm.subscription) { |
127 | - vm.allAlarms = vm.subscription.alarms; | |
127 | + vm.allAlarms = vm.subscription.alarms || []; | |
128 | 128 | updateAlarms(true); |
129 | 129 | $scope.$digest(); |
130 | 130 | } |
... | ... | @@ -298,7 +298,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia |
298 | 298 | entityId = vm.currentAlarm.originator; |
299 | 299 | entityName = vm.currentAlarm.originatorName; |
300 | 300 | } |
301 | - vm.ctx.actionsApi.handleWidgetAction($event, descriptors[0], entityId, entityName); | |
301 | + vm.ctx.actionsApi.handleWidgetAction($event, descriptors[0], entityId, entityName, { alarm: alarm }); | |
302 | 302 | } |
303 | 303 | } |
304 | 304 | |
... | ... | @@ -312,7 +312,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia |
312 | 312 | entityId = alarm.originator; |
313 | 313 | entityName = alarm.originatorName; |
314 | 314 | } |
315 | - vm.ctx.actionsApi.handleWidgetAction($event, actionDescriptor, entityId, entityName); | |
315 | + vm.ctx.actionsApi.handleWidgetAction($event, actionDescriptor, entityId, entityName, { alarm: alarm }); | |
316 | 316 | } |
317 | 317 | |
318 | 318 | function isCurrent(alarm) { | ... | ... |
... | ... | @@ -77,7 +77,7 @@ |
77 | 77 | </td> |
78 | 78 | <td md-cell ng-if="vm.displayDetails" class="tb-action-cell"> |
79 | 79 | <md-button class="md-icon-button" aria-label="{{ 'alarm.details' | translate }}" |
80 | - ng-click="vm.openAlarmDetails($event, alarm)"> | |
80 | + ng-click="vm.openAlarmDetails($event, alarm)" ng-disabled="$root.loading"> | |
81 | 81 | <md-icon aria-label="{{ 'alarm.details' | translate }}" class="material-icons">more_horiz</md-icon> |
82 | 82 | <md-tooltip md-direction="top"> |
83 | 83 | {{ 'alarm.details' | translate }} |
... | ... | @@ -90,7 +90,7 @@ |
90 | 90 | width: vm.actionCellDescriptors.length*36+'px'}"> |
91 | 91 | <md-button class="md-icon-button" ng-repeat="actionDescriptor in vm.actionCellDescriptors" |
92 | 92 | aria-label="{{ actionDescriptor.displayName }}" |
93 | - ng-click="vm.onActionButtonClick($event, alarm, actionDescriptor)"> | |
93 | + ng-click="vm.onActionButtonClick($event, alarm, actionDescriptor)" ng-disabled="$root.loading"> | |
94 | 94 | <md-icon aria-label="{{ actionDescriptor.displayName }}" class="material-icons">{{actionDescriptor.icon}}</md-icon> |
95 | 95 | <md-tooltip md-direction="top"> |
96 | 96 | {{ actionDescriptor.displayName }} | ... | ... |
... | ... | @@ -63,7 +63,7 @@ |
63 | 63 | width: vm.actionCellDescriptors.length*36+'px'}"> |
64 | 64 | <md-button class="md-icon-button" ng-repeat="actionDescriptor in vm.actionCellDescriptors" |
65 | 65 | aria-label="{{ actionDescriptor.displayName }}" |
66 | - ng-click="vm.onActionButtonClick($event, entity, actionDescriptor)"> | |
66 | + ng-click="vm.onActionButtonClick($event, entity, actionDescriptor)" ng-disabled="$root.loading"> | |
67 | 67 | <md-icon aria-label="{{ actionDescriptor.displayName }}" class="material-icons">{{actionDescriptor.icon}}</md-icon> |
68 | 68 | <md-tooltip md-direction="top"> |
69 | 69 | {{ actionDescriptor.displayName }} | ... | ... |
... | ... | @@ -13,16 +13,16 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | - | |
17 | 16 | var gmGlobals = { |
18 | 17 | loadingGmId: null, |
19 | 18 | gmApiKeys: {} |
20 | 19 | } |
21 | 20 | |
22 | 21 | export default class TbGoogleMap { |
23 | - constructor($containerElement, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, gmApiKey, gmDefaultMapType) { | |
22 | + constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, gmApiKey, gmDefaultMapType) { | |
24 | 23 | |
25 | 24 | var tbMap = this; |
25 | + this.utils = utils; | |
26 | 26 | this.defaultZoomLevel = defaultZoomLevel; |
27 | 27 | this.dontFitMapBounds = dontFitMapBounds; |
28 | 28 | this.minZoomLevel = minZoomLevel; |
... | ... | @@ -151,80 +151,97 @@ export default class TbGoogleMap { |
151 | 151 | |
152 | 152 | /* eslint-disable no-undef */ |
153 | 153 | updateMarkerColor(marker, color) { |
154 | - var pinColor = color.substr(1); | |
155 | - var pinImage = new google.maps.MarkerImage("https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor, | |
156 | - new google.maps.Size(21, 34), | |
157 | - new google.maps.Point(0,0), | |
158 | - new google.maps.Point(10, 34)); | |
159 | - marker.setIcon(pinImage); | |
154 | + this.createDefaultMarkerIcon(marker, color, (iconInfo) => { | |
155 | + marker.setIcon(iconInfo.icon); | |
156 | + }); | |
160 | 157 | } |
161 | 158 | /* eslint-enable no-undef */ |
162 | 159 | |
163 | 160 | /* eslint-disable no-undef */ |
164 | - updateMarkerImage(marker, settings, image, maxSize) { | |
165 | - var testImage = document.createElement('img'); // eslint-disable-line | |
166 | - testImage.style.visibility = 'hidden'; | |
167 | - testImage.onload = function() { | |
168 | - var width; | |
169 | - var height; | |
170 | - var aspect = testImage.width / testImage.height; | |
171 | - document.body.removeChild(testImage); //eslint-disable-line | |
172 | - if (aspect > 1) { | |
173 | - width = maxSize; | |
174 | - height = maxSize / aspect; | |
175 | - } else { | |
176 | - width = maxSize * aspect; | |
177 | - height = maxSize; | |
178 | - } | |
179 | - var pinImage = { | |
180 | - url: image, | |
181 | - scaledSize : new google.maps.Size(width, height) | |
182 | - } | |
183 | - marker.setIcon(pinImage); | |
161 | + updateMarkerIcon(marker, settings) { | |
162 | + this.createMarkerIcon(marker, settings, (iconInfo) => { | |
163 | + marker.setIcon(iconInfo.icon); | |
184 | 164 | if (settings.showLabel) { |
185 | - marker.set('labelAnchor', new google.maps.Point(100, height + 20)); | |
165 | + marker.set('labelAnchor', new google.maps.Point(100, iconInfo.size[1] + 20)); | |
186 | 166 | } |
167 | + }); | |
168 | + } | |
169 | + /* eslint-disable no-undef */ | |
170 | + | |
171 | + /* eslint-disable no-undef */ | |
172 | + createMarkerIcon(marker, settings, onMarkerIconReady) { | |
173 | + var currentImage = settings.currentImage; | |
174 | + var gMap = this; | |
175 | + if (currentImage && currentImage.url) { | |
176 | + this.utils.loadImageAspect(currentImage.url).then( | |
177 | + (aspect) => { | |
178 | + if (aspect) { | |
179 | + var width; | |
180 | + var height; | |
181 | + if (aspect > 1) { | |
182 | + width = currentImage.size; | |
183 | + height = currentImage.size / aspect; | |
184 | + } else { | |
185 | + width = currentImage.size * aspect; | |
186 | + height = currentImage.size; | |
187 | + } | |
188 | + var icon = { | |
189 | + url: currentImage.url, | |
190 | + scaledSize : new google.maps.Size(width, height) | |
191 | + }; | |
192 | + var iconInfo = { | |
193 | + size: [width, height], | |
194 | + icon: icon | |
195 | + }; | |
196 | + onMarkerIconReady(iconInfo); | |
197 | + } else { | |
198 | + gMap.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady); | |
199 | + } | |
200 | + } | |
201 | + ); | |
202 | + } else { | |
203 | + this.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady); | |
187 | 204 | } |
188 | - document.body.appendChild(testImage); //eslint-disable-line | |
189 | - testImage.src = image; | |
190 | 205 | } |
191 | 206 | /* eslint-enable no-undef */ |
192 | 207 | |
193 | 208 | /* eslint-disable no-undef */ |
194 | - createMarker(location, settings, onClickListener, markerArgs) { | |
195 | - var height = 34; | |
196 | - var pinColor = settings.color.substr(1); | |
197 | - var pinImage = new google.maps.MarkerImage("https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor, | |
198 | - new google.maps.Size(21, 34), | |
199 | - new google.maps.Point(0,0), | |
200 | - new google.maps.Point(10, 34)); | |
201 | - var pinShadow = new google.maps.MarkerImage("https://chart.apis.google.com/chart?chst=d_map_pin_shadow", | |
209 | + createDefaultMarkerIcon(marker, color, onMarkerIconReady) { | |
210 | + var pinColor = color.substr(1); | |
211 | + var icon = new google.maps.MarkerImage("https://chart.apis.google.com/chart?chst=d_map_pin_letter_withshadow&chld=%E2%80%A2|" + pinColor, | |
202 | 212 | new google.maps.Size(40, 37), |
203 | - new google.maps.Point(0, 0), | |
204 | - new google.maps.Point(12, 35)); | |
213 | + new google.maps.Point(0,0), | |
214 | + new google.maps.Point(10, 37)); | |
215 | + var iconInfo = { | |
216 | + size: [40, 37], | |
217 | + icon: icon | |
218 | + }; | |
219 | + onMarkerIconReady(iconInfo); | |
220 | + } | |
221 | + /* eslint-enable no-undef */ | |
222 | + | |
223 | + /* eslint-disable no-undef */ | |
224 | + createMarker(location, settings, onClickListener, markerArgs) { | |
205 | 225 | var marker; |
206 | 226 | if (settings.showLabel) { |
207 | 227 | marker = new MarkerWithLabel({ |
208 | 228 | position: location, |
209 | - map: this.map, | |
210 | - icon: pinImage, | |
211 | - shadow: pinShadow, | |
212 | 229 | labelContent: '<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>', |
213 | - labelClass: "tb-labels", | |
214 | - labelAnchor: new google.maps.Point(100, height + 20) | |
230 | + labelClass: "tb-labels" | |
215 | 231 | }); |
216 | 232 | } else { |
217 | 233 | marker = new google.maps.Marker({ |
218 | 234 | position: location, |
219 | - map: this.map, | |
220 | - icon: pinImage, | |
221 | - shadow: pinShadow | |
222 | 235 | }); |
223 | 236 | } |
224 | - | |
225 | - if (settings.useMarkerImage) { | |
226 | - this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34); | |
227 | - } | |
237 | + var gMap = this; | |
238 | + this.createMarkerIcon(marker, settings, (iconInfo) => { | |
239 | + marker.setIcon(iconInfo.icon); | |
240 | + if (settings.showLabel) { | |
241 | + marker.set('labelAnchor', new google.maps.Point(100, iconInfo.size[1] + 20)); | |
242 | + } | |
243 | + marker.setMap(gMap.map); | |
244 | + }); | |
228 | 245 | |
229 | 246 | if (settings.displayTooltip) { |
230 | 247 | this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs); | ... | ... |
... | ... | @@ -13,7 +13,6 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | - | |
17 | 16 | import 'leaflet/dist/leaflet.css'; |
18 | 17 | import * as L from 'leaflet'; |
19 | 18 | |
... | ... | @@ -21,9 +20,10 @@ const maxZoom = 4; |
21 | 20 | |
22 | 21 | export default class TbImageMap { |
23 | 22 | |
24 | - constructor(ctx, $containerElement, initCallback, imageUrl, posFunction, imageEntityAlias, imageUrlAttribute) { | |
23 | + constructor(ctx, $containerElement, utils, initCallback, imageUrl, posFunction, imageEntityAlias, imageUrlAttribute) { | |
25 | 24 | |
26 | 25 | this.ctx = ctx; |
26 | + this.utils = utils; | |
27 | 27 | this.tooltips = []; |
28 | 28 | |
29 | 29 | this.$containerElement = $containerElement; |
... | ... | @@ -117,18 +117,15 @@ export default class TbImageMap { |
117 | 117 | } |
118 | 118 | this.imageUrl = imageUrl; |
119 | 119 | var imageMap = this; |
120 | - var testImage = document.createElement('img'); // eslint-disable-line | |
121 | - testImage.style.visibility = 'hidden'; | |
122 | - testImage.onload = function() { | |
123 | - imageMap.aspect = testImage.width / testImage.height; | |
124 | - document.body.removeChild(testImage); //eslint-disable-line | |
125 | - imageMap.onresize(updateImage); | |
126 | - if (initCallback) { | |
127 | - setTimeout(initCallback, 0); //eslint-disable-line | |
120 | + this.utils.loadImageAspect(imageUrl).then( | |
121 | + (aspect) => { | |
122 | + imageMap.aspect = aspect; | |
123 | + imageMap.onresize(updateImage); | |
124 | + if (initCallback) { | |
125 | + setTimeout(initCallback, 0); //eslint-disable-line | |
126 | + } | |
128 | 127 | } |
129 | - } | |
130 | - document.body.appendChild(testImage); //eslint-disable-line | |
131 | - testImage.src = imageUrl; | |
128 | + ); | |
132 | 129 | } |
133 | 130 | |
134 | 131 | onresize(updateImage) { |
... | ... | @@ -229,83 +226,97 @@ export default class TbImageMap { |
229 | 226 | } |
230 | 227 | |
231 | 228 | updateMarkerColor(marker, color) { |
232 | - var pinColor = color.substr(1); | |
233 | - var icon = L.icon({ | |
234 | - iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor, | |
235 | - iconSize: [21, 34], | |
236 | - iconAnchor: [10, 34], | |
237 | - popupAnchor: [0, -34], | |
238 | - shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow', | |
239 | - shadowSize: [40, 37], | |
240 | - shadowAnchor: [12, 35] | |
229 | + this.createDefaultMarkerIcon(marker, color, (iconInfo) => { | |
230 | + marker.setIcon(iconInfo.icon); | |
241 | 231 | }); |
242 | - marker.setIcon(icon); | |
243 | - } | |
244 | - | |
245 | - updateMarkerImage(marker, settings, image, maxSize) { | |
246 | - var testImage = document.createElement('img'); // eslint-disable-line | |
247 | - testImage.style.visibility = 'hidden'; | |
248 | - testImage.onload = function() { | |
249 | - var width; | |
250 | - var height; | |
251 | - var aspect = testImage.width / testImage.height; | |
252 | - document.body.removeChild(testImage); //eslint-disable-line | |
253 | - if (aspect > 1) { | |
254 | - width = maxSize; | |
255 | - height = maxSize / aspect; | |
256 | - } else { | |
257 | - width = maxSize * aspect; | |
258 | - height = maxSize; | |
259 | - } | |
260 | - var icon = L.icon({ | |
261 | - iconUrl: image, | |
262 | - iconSize: [width, height], | |
263 | - iconAnchor: [marker.offsetX * width, marker.offsetY * height], | |
264 | - popupAnchor: [0, -height] | |
265 | - }); | |
266 | - marker.setIcon(icon); | |
232 | + } | |
233 | + | |
234 | + updateMarkerIcon(marker, settings) { | |
235 | + this.createMarkerIcon(marker, settings, (iconInfo) => { | |
236 | + marker.setIcon(iconInfo.icon); | |
267 | 237 | if (settings.showLabel) { |
268 | 238 | marker.unbindTooltip(); |
269 | - marker.tooltipOffset = [0, -height * marker.offsetY + 10]; | |
239 | + marker.tooltipOffset = [0, -iconInfo.size[1] * marker.offsetY + 10]; | |
270 | 240 | marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>', |
271 | 241 | { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset }); |
272 | 242 | } |
243 | + }); | |
244 | + } | |
245 | + | |
246 | + createMarkerIcon(marker, settings, onMarkerIconReady) { | |
247 | + var currentImage = settings.currentImage; | |
248 | + var opMap = this; | |
249 | + if (currentImage && currentImage.url) { | |
250 | + this.utils.loadImageAspect(currentImage.url).then( | |
251 | + (aspect) => { | |
252 | + if (aspect) { | |
253 | + var width; | |
254 | + var height; | |
255 | + if (aspect > 1) { | |
256 | + width = currentImage.size; | |
257 | + height = currentImage.size / aspect; | |
258 | + } else { | |
259 | + width = currentImage.size * aspect; | |
260 | + height = currentImage.size; | |
261 | + } | |
262 | + var icon = L.icon({ | |
263 | + iconUrl: currentImage.url, | |
264 | + iconSize: [width, height], | |
265 | + iconAnchor: [marker.offsetX * width, marker.offsetY * height], | |
266 | + popupAnchor: [0, -height] | |
267 | + }); | |
268 | + var iconInfo = { | |
269 | + size: [width, height], | |
270 | + icon: icon | |
271 | + }; | |
272 | + onMarkerIconReady(iconInfo); | |
273 | + } else { | |
274 | + opMap.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady); | |
275 | + } | |
276 | + } | |
277 | + ); | |
278 | + } else { | |
279 | + this.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady); | |
273 | 280 | } |
274 | - document.body.appendChild(testImage); //eslint-disable-line | |
275 | - testImage.src = image; | |
276 | 281 | } |
277 | 282 | |
278 | - createMarker(position, settings, onClickListener, markerArgs) { | |
279 | - var height = 34; | |
280 | - var pinColor = settings.color.substr(1); | |
283 | + createDefaultMarkerIcon(marker, color, onMarkerIconReady) { | |
284 | + var pinColor = color.substr(1); | |
281 | 285 | var icon = L.icon({ |
282 | 286 | iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor, |
283 | 287 | iconSize: [21, 34], |
284 | - iconAnchor: [21 * settings.markerOffsetX, 34 * settings.markerOffsetY], | |
288 | + iconAnchor: [21 * marker.offsetX, 34 * marker.offsetY], | |
285 | 289 | popupAnchor: [0, -34], |
286 | 290 | shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow', |
287 | 291 | shadowSize: [40, 37], |
288 | 292 | shadowAnchor: [12, 35] |
289 | 293 | }); |
294 | + var iconInfo = { | |
295 | + size: [21, 34], | |
296 | + icon: icon | |
297 | + }; | |
298 | + onMarkerIconReady(iconInfo); | |
299 | + } | |
290 | 300 | |
301 | + createMarker(position, settings, onClickListener, markerArgs) { | |
291 | 302 | var pos = this.posFunction(position.x, position.y); |
292 | 303 | var x = pos.x * this.width; |
293 | 304 | var y = pos.y * this.height; |
294 | 305 | var location = this.pointToLatLng(x, y); |
295 | - var marker = L.marker(location, {icon: icon}).addTo(this.map); | |
306 | + var marker = L.marker(location, {});//.addTo(this.map); | |
296 | 307 | marker.position = position; |
297 | 308 | marker.offsetX = settings.markerOffsetX; |
298 | 309 | marker.offsetY = settings.markerOffsetY; |
299 | - | |
300 | - if (settings.showLabel) { | |
301 | - marker.tooltipOffset = [0, -height * marker.offsetY + 10]; | |
302 | - marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>', | |
303 | - { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset }); | |
304 | - } | |
305 | - | |
306 | - if (settings.useMarkerImage) { | |
307 | - this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34); | |
308 | - } | |
310 | + var opMap = this; | |
311 | + this.createMarkerIcon(marker, settings, (iconInfo) => { | |
312 | + marker.setIcon(iconInfo.icon); | |
313 | + if (settings.showLabel) { | |
314 | + marker.tooltipOffset = [0, -iconInfo.size[1] * marker.offsetY + 10]; | |
315 | + marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>', | |
316 | + { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset }); | |
317 | + } | |
318 | + marker.addTo(opMap.map); | |
319 | + }); | |
309 | 320 | |
310 | 321 | if (settings.displayTooltip) { |
311 | 322 | this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs); | ... | ... |
... | ... | @@ -13,7 +13,6 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | - | |
17 | 16 | import tinycolor from 'tinycolor2'; |
18 | 17 | |
19 | 18 | import TbGoogleMap from './google-map'; |
... | ... | @@ -75,7 +74,7 @@ export default class TbMapWidget { |
75 | 74 | if (!$element) { |
76 | 75 | $element = ctx.$container; |
77 | 76 | } |
78 | - | |
77 | + this.utils = ctx.$scope.$injector.get('utils'); | |
79 | 78 | this.drawRoutes = drawRoutes; |
80 | 79 | this.markers = []; |
81 | 80 | if (this.drawRoutes) { |
... | ... | @@ -110,9 +109,9 @@ export default class TbMapWidget { |
110 | 109 | }; |
111 | 110 | |
112 | 111 | if (mapProvider === 'google-map') { |
113 | - this.map = new TbGoogleMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType); | |
112 | + this.map = new TbGoogleMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType); | |
114 | 113 | } else if (mapProvider === 'openstreet-map') { |
115 | - this.map = new TbOpenStreetMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel); | |
114 | + this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel); | |
116 | 115 | } |
117 | 116 | |
118 | 117 | } |
... | ... | @@ -274,9 +273,13 @@ export default class TbMapWidget { |
274 | 273 | if (!this.locationsSettings[i].useMarkerImageFunction && |
275 | 274 | angular.isDefined(configuredLocationsSettings[i].markerImage) && |
276 | 275 | configuredLocationsSettings[i].markerImage.length > 0) { |
277 | - this.locationsSettings[i].markerImage = configuredLocationsSettings[i].markerImage; | |
278 | 276 | this.locationsSettings[i].useMarkerImage = true; |
279 | - this.locationsSettings[i].markerImageSize = configuredLocationsSettings[i].markerImageSize || 34; | |
277 | + var url = this.ctx.settings.markerImage; | |
278 | + var size = this.ctx.settings.markerImageSize || 34; | |
279 | + this.locationSettings.currentImage = { | |
280 | + url: url, | |
281 | + size: size | |
282 | + }; | |
280 | 283 | } |
281 | 284 | |
282 | 285 | if (this.drawRoutes) { |
... | ... | @@ -380,17 +383,41 @@ export default class TbMapWidget { |
380 | 383 | } |
381 | 384 | } |
382 | 385 | |
383 | - function updateLocationMarkerImage(location, dataMap) { | |
386 | + function updateLocationMarkerIcon(location, dataMap) { | |
384 | 387 | var image = calculateLocationMarkerImage(location, dataMap); |
385 | - if (image != null && (!location.settings.calculatedImage || !angular.equals(location.settings.calculatedImage, image))) { | |
386 | - tbMap.map.updateMarkerImage(location.marker, location.settings, image.url, image.size); | |
387 | - location.settings.calculatedImage = image; | |
388 | + if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) { | |
389 | + location.settings.currentImage = image; | |
390 | + tbMap.map.updateMarkerIcon(location.marker, location.settings); | |
388 | 391 | } |
389 | 392 | } |
390 | 393 | |
391 | 394 | function updateLocationStyle(location, dataMap) { |
392 | 395 | updateLocationColor(location, dataMap); |
393 | - updateLocationMarkerImage(location, dataMap); | |
396 | + updateLocationMarkerIcon(location, dataMap); | |
397 | + } | |
398 | + | |
399 | + function createOrUpdateLocationMarker(location, markerLocation, dataMap) { | |
400 | + var changed = false; | |
401 | + if (!location.marker) { | |
402 | + var image = calculateLocationMarkerImage(location, dataMap); | |
403 | + if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) { | |
404 | + location.settings.currentImage = image; | |
405 | + } | |
406 | + location.marker = tbMap.map.createMarker(markerLocation, location.settings, | |
407 | + function() { | |
408 | + tbMap.callbacks.onLocationClick(location); | |
409 | + } | |
410 | + ); | |
411 | + tbMap.markers.push(location.marker); | |
412 | + changed = true; | |
413 | + } else { | |
414 | + var prevPosition = tbMap.map.getMarkerPosition(location.marker); | |
415 | + if (!prevPosition.equals(markerLocation)) { | |
416 | + tbMap.map.setMarkerPosition(location.marker, markerLocation); | |
417 | + changed = true; | |
418 | + } | |
419 | + } | |
420 | + return changed; | |
394 | 421 | } |
395 | 422 | |
396 | 423 | function updateLocation(location, data, dataMap) { |
... | ... | @@ -413,15 +440,7 @@ export default class TbMapWidget { |
413 | 440 | } |
414 | 441 | if (latLngs.length > 0) { |
415 | 442 | var markerLocation = latLngs[latLngs.length-1]; |
416 | - if (!location.marker) { | |
417 | - location.marker = tbMap.map.createMarker(markerLocation, location.settings, | |
418 | - function() { | |
419 | - tbMap.callbacks.onLocationClick(location); | |
420 | - } | |
421 | - ); | |
422 | - } else { | |
423 | - tbMap.map.setMarkerPosition(location.marker, markerLocation); | |
424 | - } | |
443 | + createOrUpdateLocationMarker(location, markerLocation, dataMap); | |
425 | 444 | } |
426 | 445 | if (!location.polyline) { |
427 | 446 | location.polyline = tbMap.map.createPolyline(latLngs, location.settings); |
... | ... | @@ -439,18 +458,8 @@ export default class TbMapWidget { |
439 | 458 | lat = latData[latData.length-1][1]; |
440 | 459 | lng = lngData[lngData.length-1][1]; |
441 | 460 | latLng = tbMap.map.createLatLng(lat, lng); |
442 | - if (!location.marker) { | |
443 | - location.marker = tbMap.map.createMarker(latLng, location.settings, function() { | |
444 | - tbMap.callbacks.onLocationClick(location); | |
445 | - }); | |
446 | - tbMap.markers.push(location.marker); | |
461 | + if (createOrUpdateLocationMarker(location, latLng, dataMap)) { | |
447 | 462 | locationChanged = true; |
448 | - } else { | |
449 | - var prevPosition = tbMap.map.getMarkerPosition(location.marker); | |
450 | - if (!prevPosition.equals(latLng)) { | |
451 | - tbMap.map.setMarkerPosition(location.marker, latLng); | |
452 | - locationChanged = true; | |
453 | - } | |
454 | 463 | } |
455 | 464 | } |
456 | 465 | updateLocationStyle(location, dataMap); | ... | ... |
... | ... | @@ -13,7 +13,6 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | - | |
17 | 16 | import tinycolor from 'tinycolor2'; |
18 | 17 | |
19 | 18 | import TbGoogleMap from './google-map'; |
... | ... | @@ -75,11 +74,11 @@ export default class TbMapWidgetV2 { |
75 | 74 | }); |
76 | 75 | |
77 | 76 | if (mapProvider === 'google-map') { |
78 | - this.map = new TbGoogleMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType); | |
77 | + this.map = new TbGoogleMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType); | |
79 | 78 | } else if (mapProvider === 'openstreet-map') { |
80 | - this.map = new TbOpenStreetMap($element, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.mapProvider); | |
79 | + this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.mapProvider); | |
81 | 80 | } else if (mapProvider === 'image-map') { |
82 | - this.map = new TbImageMap(this.ctx, $element, initCallback, | |
81 | + this.map = new TbImageMap(this.ctx, $element, this.utils, initCallback, | |
83 | 82 | settings.mapImageUrl, |
84 | 83 | settings.posFunction, |
85 | 84 | settings.imageEntityAlias, |
... | ... | @@ -159,9 +158,13 @@ export default class TbMapWidgetV2 { |
159 | 158 | if (!this.locationSettings.useMarkerImageFunction && |
160 | 159 | angular.isDefined(this.ctx.settings.markerImage) && |
161 | 160 | this.ctx.settings.markerImage.length > 0) { |
162 | - this.locationSettings.markerImage = this.ctx.settings.markerImage; | |
163 | 161 | this.locationSettings.useMarkerImage = true; |
164 | - this.locationSettings.markerImageSize = this.ctx.settings.markerImageSize || 34; | |
162 | + var url = this.ctx.settings.markerImage; | |
163 | + var size = this.ctx.settings.markerImageSize || 34; | |
164 | + this.locationSettings.currentImage = { | |
165 | + url: url, | |
166 | + size: size | |
167 | + }; | |
165 | 168 | } |
166 | 169 | |
167 | 170 | if (this.drawRoutes) { |
... | ... | @@ -235,10 +238,10 @@ export default class TbMapWidgetV2 { |
235 | 238 | } |
236 | 239 | } |
237 | 240 | |
238 | - function updateLocationMarkerImage(location, image) { | |
239 | - if (image && (!location.settings.calculatedImage || !angular.equals(location.settings.calculatedImage, image))) { | |
240 | - tbMap.map.updateMarkerImage(location.marker, location.settings, image.url, image.size); | |
241 | - location.settings.calculatedImage = image; | |
241 | + function updateLocationMarkerIcon(location, image) { | |
242 | + if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) { | |
243 | + location.settings.currentImage = image; | |
244 | + tbMap.map.updateMarkerIcon(location.marker, location.settings); | |
242 | 245 | } |
243 | 246 | } |
244 | 247 | |
... | ... | @@ -247,7 +250,31 @@ export default class TbMapWidgetV2 { |
247 | 250 | var color = calculateLocationColor(location, dataMap); |
248 | 251 | var image = calculateLocationMarkerImage(location, dataMap); |
249 | 252 | updateLocationColor(location, color, image); |
250 | - updateLocationMarkerImage(location, image); | |
253 | + updateLocationMarkerIcon(location, image); | |
254 | + } | |
255 | + | |
256 | + function createOrUpdateLocationMarker(location, markerLocation, dataMap) { | |
257 | + var changed = false; | |
258 | + if (!location.marker) { | |
259 | + var image = calculateLocationMarkerImage(location, dataMap); | |
260 | + if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) { | |
261 | + location.settings.currentImage = image; | |
262 | + } | |
263 | + location.marker = tbMap.map.createMarker(markerLocation, location.settings, | |
264 | + function (event) { | |
265 | + tbMap.callbacks.onLocationClick(location); | |
266 | + locationRowClick(event, location); | |
267 | + }, [location.dsIndex]); | |
268 | + tbMap.markers.push(location.marker); | |
269 | + changed = true; | |
270 | + } else { | |
271 | + var prevPosition = tbMap.map.getMarkerPosition(location.marker); | |
272 | + if (!prevPosition.equals(markerLocation)) { | |
273 | + tbMap.map.setMarkerPosition(location.marker, markerLocation); | |
274 | + changed = true; | |
275 | + } | |
276 | + } | |
277 | + return changed; | |
251 | 278 | } |
252 | 279 | |
253 | 280 | function locationRowClick($event, location) { |
... | ... | @@ -284,16 +311,7 @@ export default class TbMapWidgetV2 { |
284 | 311 | } |
285 | 312 | if (latLngs.length > 0) { |
286 | 313 | var markerLocation = latLngs[latLngs.length - 1]; |
287 | - if (!location.marker) { | |
288 | - location.marker = tbMap.map.createMarker(markerLocation, location.settings, | |
289 | - function (event) { | |
290 | - tbMap.callbacks.onLocationClick(location); | |
291 | - locationRowClick(event, location); | |
292 | - }, [location.dsIndex] | |
293 | - ); | |
294 | - } else { | |
295 | - tbMap.map.setMarkerPosition(location.marker, markerLocation); | |
296 | - } | |
314 | + createOrUpdateLocationMarker(location, markerLocation, dataMap); | |
297 | 315 | } |
298 | 316 | if (!location.polyline) { |
299 | 317 | location.polyline = tbMap.map.createPolyline(latLngs, location.settings); |
... | ... | @@ -312,20 +330,8 @@ export default class TbMapWidgetV2 { |
312 | 330 | lng = lngData[lngData.length - 1][1]; |
313 | 331 | if (angular.isDefined(lat) && lat != null && angular.isDefined(lng) && lng != null) { |
314 | 332 | latLng = tbMap.map.createLatLng(lat, lng); |
315 | - if (!location.marker) { | |
316 | - location.marker = tbMap.map.createMarker(latLng, location.settings, | |
317 | - function (event) { | |
318 | - tbMap.callbacks.onLocationClick(location); | |
319 | - locationRowClick(event, location); | |
320 | - }, [location.dsIndex]); | |
321 | - tbMap.markers.push(location.marker); | |
333 | + if (createOrUpdateLocationMarker(location, latLng, dataMap)) { | |
322 | 334 | locationChanged = true; |
323 | - } else { | |
324 | - var prevPosition = tbMap.map.getMarkerPosition(location.marker); | |
325 | - if (!prevPosition.equals(latLng)) { | |
326 | - tbMap.map.setMarkerPosition(location.marker, latLng); | |
327 | - locationChanged = true; | |
328 | - } | |
329 | 335 | } |
330 | 336 | } |
331 | 337 | } | ... | ... |
... | ... | @@ -13,15 +13,15 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | - | |
17 | 16 | import 'leaflet/dist/leaflet.css'; |
18 | 17 | import * as L from 'leaflet'; |
19 | 18 | import 'leaflet-providers'; |
20 | 19 | |
21 | 20 | export default class TbOpenStreetMap { |
22 | 21 | |
23 | - constructor($containerElement, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, mapProvider) { | |
22 | + constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, mapProvider) { | |
24 | 23 | |
24 | + this.utils = utils; | |
25 | 25 | this.defaultZoomLevel = defaultZoomLevel; |
26 | 26 | this.dontFitMapBounds = dontFitMapBounds; |
27 | 27 | this.minZoomLevel = minZoomLevel; |
... | ... | @@ -54,55 +54,62 @@ export default class TbOpenStreetMap { |
54 | 54 | } |
55 | 55 | |
56 | 56 | updateMarkerColor(marker, color) { |
57 | - var pinColor = color.substr(1); | |
58 | - var icon = L.icon({ | |
59 | - iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor, | |
60 | - iconSize: [21, 34], | |
61 | - iconAnchor: [10, 34], | |
62 | - popupAnchor: [0, -34], | |
63 | - shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow', | |
64 | - shadowSize: [40, 37], | |
65 | - shadowAnchor: [12, 35] | |
57 | + this.createDefaultMarkerIcon(marker, color, (iconInfo) => { | |
58 | + marker.setIcon(iconInfo.icon); | |
66 | 59 | }); |
67 | - marker.setIcon(icon); | |
68 | - } | |
69 | - | |
70 | - updateMarkerImage(marker, settings, image, maxSize) { | |
71 | - var testImage = document.createElement('img'); // eslint-disable-line | |
72 | - testImage.style.visibility = 'hidden'; | |
73 | - testImage.onload = function() { | |
74 | - var width; | |
75 | - var height; | |
76 | - var aspect = testImage.width / testImage.height; | |
77 | - document.body.removeChild(testImage); //eslint-disable-line | |
78 | - if (aspect > 1) { | |
79 | - width = maxSize; | |
80 | - height = maxSize / aspect; | |
81 | - } else { | |
82 | - width = maxSize * aspect; | |
83 | - height = maxSize; | |
84 | - } | |
85 | - var icon = L.icon({ | |
86 | - iconUrl: image, | |
87 | - iconSize: [width, height], | |
88 | - iconAnchor: [width/2, height], | |
89 | - popupAnchor: [0, -height] | |
90 | - }); | |
91 | - marker.setIcon(icon); | |
60 | + } | |
61 | + | |
62 | + updateMarkerIcon(marker, settings) { | |
63 | + this.createMarkerIcon(marker, settings, (iconInfo) => { | |
64 | + marker.setIcon(iconInfo.icon); | |
92 | 65 | if (settings.showLabel) { |
93 | 66 | marker.unbindTooltip(); |
94 | - marker.tooltipOffset = [0, -height + 10]; | |
67 | + marker.tooltipOffset = [0, -iconInfo.size[1] + 10]; | |
95 | 68 | marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>', |
96 | 69 | { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset }); |
97 | 70 | } |
71 | + }); | |
72 | + } | |
73 | + | |
74 | + createMarkerIcon(marker, settings, onMarkerIconReady) { | |
75 | + var currentImage = settings.currentImage; | |
76 | + var opMap = this; | |
77 | + if (currentImage && currentImage.url) { | |
78 | + this.utils.loadImageAspect(currentImage.url).then( | |
79 | + (aspect) => { | |
80 | + if (aspect) { | |
81 | + var width; | |
82 | + var height; | |
83 | + if (aspect > 1) { | |
84 | + width = currentImage.size; | |
85 | + height = currentImage.size / aspect; | |
86 | + } else { | |
87 | + width = currentImage.size * aspect; | |
88 | + height = currentImage.size; | |
89 | + } | |
90 | + var icon = L.icon({ | |
91 | + iconUrl: currentImage.url, | |
92 | + iconSize: [width, height], | |
93 | + iconAnchor: [width/2, height], | |
94 | + popupAnchor: [0, -height] | |
95 | + }); | |
96 | + var iconInfo = { | |
97 | + size: [width, height], | |
98 | + icon: icon | |
99 | + }; | |
100 | + onMarkerIconReady(iconInfo); | |
101 | + } else { | |
102 | + opMap.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady); | |
103 | + } | |
104 | + } | |
105 | + ); | |
106 | + } else { | |
107 | + this.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady); | |
98 | 108 | } |
99 | - document.body.appendChild(testImage); //eslint-disable-line | |
100 | - testImage.src = image; | |
101 | 109 | } |
102 | 110 | |
103 | - createMarker(location, settings, onClickListener, markerArgs) { | |
104 | - var height = 34; | |
105 | - var pinColor = settings.color.substr(1); | |
111 | + createDefaultMarkerIcon(marker, color, onMarkerIconReady) { | |
112 | + var pinColor = color.substr(1); | |
106 | 113 | var icon = L.icon({ |
107 | 114 | iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor, |
108 | 115 | iconSize: [21, 34], |
... | ... | @@ -112,18 +119,25 @@ export default class TbOpenStreetMap { |
112 | 119 | shadowSize: [40, 37], |
113 | 120 | shadowAnchor: [12, 35] |
114 | 121 | }); |
122 | + var iconInfo = { | |
123 | + size: [21, 34], | |
124 | + icon: icon | |
125 | + }; | |
126 | + onMarkerIconReady(iconInfo); | |
127 | + } | |
115 | 128 | |
116 | - var marker = L.marker(location, {icon: icon}).addTo(this.map); | |
117 | - | |
118 | - if (settings.showLabel) { | |
119 | - marker.tooltipOffset = [0, -height + 10]; | |
120 | - marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>', | |
121 | - { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset }); | |
122 | - } | |
123 | - | |
124 | - if (settings.useMarkerImage) { | |
125 | - this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34); | |
126 | - } | |
129 | + createMarker(location, settings, onClickListener, markerArgs) { | |
130 | + var marker = L.marker(location, {}); | |
131 | + var opMap = this; | |
132 | + this.createMarkerIcon(marker, settings, (iconInfo) => { | |
133 | + marker.setIcon(iconInfo.icon); | |
134 | + if (settings.showLabel) { | |
135 | + marker.tooltipOffset = [0, -iconInfo.size[1] + 10]; | |
136 | + marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>', | |
137 | + { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset }); | |
138 | + } | |
139 | + marker.addTo(opMap.map); | |
140 | + }); | |
127 | 141 | |
128 | 142 | if (settings.displayTooltip) { |
129 | 143 | this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs); | ... | ... |
... | ... | @@ -47,9 +47,37 @@ function TimeseriesTableWidget() { |
47 | 47 | /*@ngInject*/ |
48 | 48 | function TimeseriesTableWidgetController($element, $scope, $filter) { |
49 | 49 | var vm = this; |
50 | + let dateFormatFilter = 'yyyy-MM-dd HH:mm:ss'; | |
50 | 51 | |
51 | 52 | vm.sources = []; |
52 | 53 | vm.sourceIndex = 0; |
54 | + vm.defaultPageSize = 10; | |
55 | + vm.defaultSortOrder = '-0'; | |
56 | + vm.query = { | |
57 | + "search": null | |
58 | + }; | |
59 | + | |
60 | + vm.enterFilterMode = enterFilterMode; | |
61 | + vm.exitFilterMode = exitFilterMode; | |
62 | + | |
63 | + function enterFilterMode () { | |
64 | + vm.query.search = ''; | |
65 | + vm.ctx.hideTitlePanel = true; | |
66 | + } | |
67 | + | |
68 | + function exitFilterMode () { | |
69 | + vm.query.search = null; | |
70 | + vm.ctx.hideTitlePanel = false; | |
71 | + } | |
72 | + | |
73 | + vm.searchAction = { | |
74 | + name: 'action.search', | |
75 | + show: true, | |
76 | + onAction: function() { | |
77 | + vm.enterFilterMode(); | |
78 | + }, | |
79 | + icon: 'search' | |
80 | + }; | |
53 | 81 | |
54 | 82 | $scope.$watch('vm.ctx', function() { |
55 | 83 | if (vm.ctx) { |
... | ... | @@ -62,6 +90,7 @@ function TimeseriesTableWidgetController($element, $scope, $filter) { |
62 | 90 | }); |
63 | 91 | |
64 | 92 | function initialize() { |
93 | + vm.ctx.widgetActions = [ vm.searchAction ]; | |
65 | 94 | vm.showTimestamp = vm.settings.showTimestamp !== false; |
66 | 95 | var origColor = vm.widgetConfig.color || 'rgba(0, 0, 0, 0.87)'; |
67 | 96 | var defaultColor = tinycolor(origColor); |
... | ... | @@ -108,6 +137,8 @@ function TimeseriesTableWidgetController($element, $scope, $filter) { |
108 | 137 | cssParser.createStyleElement(namespace, cssString); |
109 | 138 | $element.addClass(namespace); |
110 | 139 | |
140 | + vm.displayPagination = angular.isDefined(vm.settings.displayPagination) ? vm.settings.displayPagination : true; | |
141 | + | |
111 | 142 | function hashCode(str) { |
112 | 143 | var hash = 0; |
113 | 144 | var i, char; |
... | ... | @@ -163,7 +194,7 @@ function TimeseriesTableWidgetController($element, $scope, $filter) { |
163 | 194 | |
164 | 195 | vm.cellContent = function(source, index, row, value) { |
165 | 196 | if (index === 0) { |
166 | - return $filter('date')(value, 'yyyy-MM-dd HH:mm:ss'); | |
197 | + return $filter('date')(value, dateFormatFilter); | |
167 | 198 | } else { |
168 | 199 | var strContent = ''; |
169 | 200 | if (angular.isDefined(value)) { |
... | ... | @@ -211,7 +242,7 @@ function TimeseriesTableWidgetController($element, $scope, $filter) { |
211 | 242 | source.data = []; |
212 | 243 | source.rawData = []; |
213 | 244 | source.query = { |
214 | - limit: 5, | |
245 | + limit: vm.settings.defaultPageSize || 10, | |
215 | 246 | page: 1, |
216 | 247 | order: '-0' |
217 | 248 | } |
... | ... | @@ -287,7 +318,30 @@ function TimeseriesTableWidgetController($element, $scope, $filter) { |
287 | 318 | } |
288 | 319 | |
289 | 320 | function reorder(source) { |
321 | + let searchRegExp = new RegExp(vm.query.search); | |
322 | + | |
290 | 323 | source.data = $filter('orderBy')(source.data, source.query.order); |
324 | + if (vm.query.search !== null) { | |
325 | + source.data = source.data.filter(function(item){ | |
326 | + for (let i = 0; i < item.length; i++) { | |
327 | + if (vm.showTimestamp) { | |
328 | + if (i === 0) { | |
329 | + if (searchRegExp.test($filter('date')(item[i], dateFormatFilter))) { | |
330 | + return true; | |
331 | + } | |
332 | + } else { | |
333 | + if (searchRegExp.test(item[i])) { | |
334 | + return true; | |
335 | + } | |
336 | + } | |
337 | + } else { | |
338 | + if (searchRegExp.test(item[i])) { | |
339 | + return true; | |
340 | + } | |
341 | + } | |
342 | + } | |
343 | + }); | |
344 | + } | |
291 | 345 | } |
292 | 346 | |
293 | 347 | function convertData(data) { | ... | ... |
... | ... | @@ -15,29 +15,71 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | +<div class="tb-absolute-fill tb-entities-table tb-data-table timeseriesWidget" layout="column"> | |
19 | + <div flex class="tb-absolute-fill" layout="column"> | |
20 | + <md-toolbar class="md-table-toolbar md-default" ng-show="vm.query.search !== null"> | |
21 | + <div class="md-toolbar-tools"> | |
22 | + <md-button class="md-icon-button" aria-label="{{ 'action.search' | translate }}"> | |
23 | + <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">search</md-icon> | |
24 | + <md-tooltip md-direction="{{vm.ctx.dashboard.isWidgetExpanded ? 'bottom' : 'top'}}"> | |
25 | + {{'entity.search' | translate}} | |
26 | + </md-tooltip> | |
27 | + </md-button> | |
28 | + <md-input-container flex> | |
29 | + <label> </label> | |
30 | + <input ng-model="vm.query.search" placeholder="{{'widget.search-data' | translate}}" md-autofocus/> | |
31 | + </md-input-container> | |
32 | + <md-button class="md-icon-button" aria-label="Close" ng-click="vm.exitFilterMode()"> | |
33 | + <md-icon aria-label="Close" class="material-icons">close</md-icon> | |
34 | + <md-tooltip md-direction="{{vm.ctx.dashboard.isWidgetExpanded ? 'bottom' : 'top'}}"> | |
35 | + {{ 'action.close' | translate }} | |
36 | + </md-tooltip> | |
37 | + </md-button> | |
38 | + </div> | |
39 | + </md-toolbar> | |
18 | 40 | |
19 | -<md-tabs md-selected="vm.sourceIndex" ng-class="{'tb-headless': vm.sources.length === 1}" | |
20 | - id="tabs" md-border-bottom flex class="tb-absolute-fill"> | |
21 | - <md-tab ng-repeat="source in vm.sources" label="{{ source.datasource.name }}"> | |
22 | - <md-table-container> | |
23 | - <table md-table> | |
24 | - <thead md-head md-order="source.query.order" md-on-reorder="vm.onReorder(source)"> | |
25 | - <tr md-row> | |
26 | - <th ng-show="vm.showTimestamp" md-column md-order-by="0"><span>Timestamp</span></th> | |
27 | - <th md-column md-order-by="{{ h.index }}" ng-repeat="h in source.ts.header"><span>{{ h.dataKey.label }}</span></th> | |
28 | - </tr> | |
29 | - </thead> | |
30 | - <tbody md-body> | |
31 | - <tr md-row ng-repeat="row in source.ts.data"> | |
32 | - <td ng-show="$index > 0 || ($index === 0 && vm.showTimestamp)" md-cell ng-repeat="d in row track by $index" ng-style="vm.cellStyle(source, $index, d)" ng-bind-html="vm.cellContent(source, $index, row, d)"> | |
33 | - </td> | |
34 | - </tr> | |
35 | - </tbody> | |
36 | - </table> | |
37 | - </md-table-container> | |
38 | - <md-table-pagination md-limit="source.query.limit" md-limit-options="[5, 10, 15]" | |
39 | - md-page="source.query.page" md-total="{{source.ts.count}}" | |
40 | - md-on-paginate="vm.onPaginate(source)" md-page-select> | |
41 | - </md-table-pagination> | |
42 | - </md-tab> | |
43 | -</md-tabs> | |
\ No newline at end of file | ||
41 | + <md-tabs flex md-selected="vm.sourceIndex" ng-class="{'tb-headless': vm.sources.length === 1}" | |
42 | + id="tabs" md-border-bottom flex> | |
43 | + <md-tab ng-repeat="source in vm.sources" label="{{ source.datasource.name }}"> | |
44 | + <md-table-container> | |
45 | + <table md-table> | |
46 | + <thead md-head md-order="source.query.order" md-on-reorder="vm.onReorder(source)"> | |
47 | + <tr md-row> | |
48 | + <th ng-show="vm.showTimestamp" | |
49 | + md-column md-order-by="0" | |
50 | + > | |
51 | + <span>Timestamp</span> | |
52 | + </th> | |
53 | + <th md-column | |
54 | + md-order-by="{{ h.index }}" | |
55 | + ng-repeat="h in source.ts.header" | |
56 | + > | |
57 | + <span>{{ h.dataKey.label }}</span> | |
58 | + </th> | |
59 | + </tr> | |
60 | + </thead> | |
61 | + | |
62 | + <tbody md-body> | |
63 | + <tr md-row ng-repeat="row in source.ts.data track by $index"> | |
64 | + <td ng-show="$index > 0 || ($index === 0 && vm.showTimestamp)" | |
65 | + md-cell | |
66 | + ng-repeat="d in row track by $index" | |
67 | + ng-style="vm.cellStyle(source, $index, d)" | |
68 | + ng-bind-html="vm.cellContent(source, $index, row, d)" | |
69 | + ></td> | |
70 | + </tr> | |
71 | + </tbody> | |
72 | + </table> | |
73 | + </md-table-container> | |
74 | + <md-table-pagination ng-if="vm.displayPagination" | |
75 | + md-limit="source.query.limit" | |
76 | + md-limit-options="vm.limitOptions" | |
77 | + md-page="source.query.page" | |
78 | + md-total="{{source.data.length}}" | |
79 | + md-on-paginate="vm.onPaginate(source)" | |
80 | + md-page-select> | |
81 | + </md-table-pagination> | |
82 | + </md-tab> | |
83 | + </md-tabs> | |
84 | + </div> | |
85 | +</div> | |
\ No newline at end of file | ... | ... |
... | ... | @@ -26,8 +26,8 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <fieldset> |
... | ... | @@ -49,10 +49,10 @@ |
49 | 49 | </md-dialog-content> |
50 | 50 | <md-dialog-actions layout="row"> |
51 | 51 | <span flex></span> |
52 | - <md-button ng-disabled="loading || theForm.$invalid" type="submit" class="md-raised md-primary"> | |
52 | + <md-button ng-disabled="$root.loading || theForm.$invalid" type="submit" class="md-raised md-primary"> | |
53 | 53 | {{ 'action.saveAs' | translate }} |
54 | 54 | </md-button> |
55 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
55 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
56 | 56 | translate }} |
57 | 57 | </md-button> |
58 | 58 | </md-dialog-actions> | ... | ... |
... | ... | @@ -26,11 +26,11 @@ |
26 | 26 | </md-button> |
27 | 27 | </div> |
28 | 28 | </md-toolbar> |
29 | - <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | |
30 | - <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | 31 | <md-dialog-content> |
32 | 32 | <div class="md-dialog-content"> |
33 | - <fieldset ng-disabled="loading"> | |
33 | + <fieldset ng-disabled="$root.loading"> | |
34 | 34 | <div layout="column" layout-gt-sm="row" layout-align="center center"> |
35 | 35 | <md-button class="tb-card-button md-raised md-primary" layout="column" |
36 | 36 | ng-click="vm.typeSelected(vm.types.widgetType.timeseries.value)"> |
... | ... | @@ -73,7 +73,7 @@ |
73 | 73 | </md-dialog-content> |
74 | 74 | <md-dialog-actions layout="row"> |
75 | 75 | <span flex></span> |
76 | - <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
76 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
77 | 77 | translate }} |
78 | 78 | </md-button> |
79 | 79 | </md-dialog-actions> | ... | ... |
... | ... | @@ -129,7 +129,7 @@ |
129 | 129 | <input placeholder="{{ 'widget.resource-url' | translate }}" |
130 | 130 | ng-required="true" name="resource" ng-model="resource.url"> |
131 | 131 | </md-input-container> |
132 | - <md-button ng-disabled="loading" class="md-icon-button md-primary" | |
132 | + <md-button ng-disabled="$root.loading" class="md-icon-button md-primary" | |
133 | 133 | ng-click="vm.removeResource($index)" |
134 | 134 | aria-label="{{ 'action.remove' | translate }}"> |
135 | 135 | <md-tooltip md-direction="top"> |
... | ... | @@ -142,7 +142,7 @@ |
142 | 142 | </md-button> |
143 | 143 | </div> |
144 | 144 | <div> |
145 | - <md-button ng-disabled="loading" class="md-primary md-raised" | |
145 | + <md-button ng-disabled="$root.loading" class="md-primary md-raised" | |
146 | 146 | ng-click="vm.addResource()" |
147 | 147 | aria-label="{{ 'action.add' | translate }}"> |
148 | 148 | <md-tooltip md-direction="top"> | ... | ... |
... | ... | @@ -15,7 +15,7 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | -<section ng-show="!loading && vm.noData()" layout-align="center center" | |
18 | +<section ng-show="!$root.loading && vm.noData()" layout-align="center center" | |
19 | 19 | style="text-transform: uppercase; display: flex; z-index: 1;" |
20 | 20 | class="md-headline tb-absolute-fill"> |
21 | 21 | <md-button ng-if="!vm.isReadOnly()" class="tb-add-new-widget" ng-click="vm.addWidgetType($event)"> |
... | ... | @@ -42,10 +42,10 @@ |
42 | 42 | on-init-failed="vm.dashboardInitFailed(e)"> |
43 | 43 | </tb-dashboard> |
44 | 44 | <section layout="row" layout-wrap class="tb-footer-buttons md-fab "> |
45 | - <md-fab-speed-dial ng-disabled="loading" ng-show="!vm.isReadOnly()" | |
45 | + <md-fab-speed-dial ng-disabled="$root.loading" ng-show="!vm.isReadOnly()" | |
46 | 46 | md-open="vm.addItemActionsOpen" class="md-scale" md-direction="up"> |
47 | 47 | <md-fab-trigger> |
48 | - <md-button ng-disabled="loading" | |
48 | + <md-button ng-disabled="$root.loading" | |
49 | 49 | class="tb-btn-footer md-accent md-hue-2 md-fab" |
50 | 50 | aria-label="{{ 'widget.add-widget-type' | translate }}"> |
51 | 51 | <md-tooltip md-direction="top"> |
... | ... | @@ -55,7 +55,7 @@ |
55 | 55 | </md-button> |
56 | 56 | </md-fab-trigger> |
57 | 57 | <md-fab-actions> |
58 | - <md-button ng-disabled="loading" | |
58 | + <md-button ng-disabled="$root.loading" | |
59 | 59 | class="tmd-accent md-hue-2 md-fab" ng-click="vm.addWidgetType($event)" |
60 | 60 | aria-label="{{ 'action.create' | translate }}"> |
61 | 61 | <md-tooltip md-direction="top"> |
... | ... | @@ -63,7 +63,7 @@ |
63 | 63 | </md-tooltip> |
64 | 64 | <ng-md-icon icon="insert_drive_file"></ng-md-icon> |
65 | 65 | </md-button> |
66 | - <md-button ng-disabled="loading" | |
66 | + <md-button ng-disabled="$root.loading" | |
67 | 67 | class="tmd-accent md-hue-2 md-fab" ng-click="vm.importWidgetType($event)" |
68 | 68 | aria-label="{{ 'action.import' | translate }}"> |
69 | 69 | <md-tooltip md-direction="top"> | ... | ... |
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | class="md-raised md-primary">{{ 'widgets-bundle.delete' | translate }}</md-button> |
24 | 24 | |
25 | 25 | <md-content class="md-padding" layout="column"> |
26 | - <fieldset ng-disabled="loading || !isEdit"> | |
26 | + <fieldset ng-disabled="$root.loading || !isEdit"> | |
27 | 27 | <md-input-container class="md-block"> |
28 | 28 | <label translate>widgets-bundle.title</label> |
29 | 29 | <input required name="title" ng-model="widgetsBundle.title"> | ... | ... |