Merge remote-tracking branch 'upstream/develop/3.5' into edge/public-customer

This commit is contained in:
Volodymyr Babak 2023-01-13 09:07:19 +02:00
commit 96f0045d0b
65 changed files with 210 additions and 148 deletions

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>application</artifactId>

View File

@ -15,8 +15,10 @@
*/
package org.thingsboard.server.service.edge.rpc.fetch;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
@ -28,6 +30,8 @@ import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.dao.rule.RuleChainService;
import static org.thingsboard.server.service.edge.DefaultEdgeNotificationService.EDGE_IS_ROOT_BODY_KEY;
@Slf4j
@AllArgsConstructor
public class RuleChainsEdgeEventFetcher extends BasePageableEdgeEventFetcher<RuleChain> {
@ -41,7 +45,13 @@ public class RuleChainsEdgeEventFetcher extends BasePageableEdgeEventFetcher<Rul
@Override
EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, RuleChain ruleChain) {
ObjectNode isRootBody = JacksonUtil.OBJECT_MAPPER.createObjectNode();
boolean isRoot = false;
try {
isRoot = ruleChain.getId().equals(edge.getRootRuleChainId());
} catch (Exception ignored) {}
isRootBody.put(EDGE_IS_ROOT_BODY_KEY, isRoot);
return EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN,
EdgeEventActionType.ADDED, ruleChain.getId(), null);
EdgeEventActionType.ADDED, ruleChain.getId(), isRootBody);
}
}

View File

@ -48,6 +48,9 @@ public class DefaultTbEdgeService extends AbstractTbEntityService implements TbE
ActionType actionType = edge.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
TenantId tenantId = edge.getTenantId();
try {
if (actionType == ActionType.ADDED && edge.getRootRuleChainId() == null) {
edge.setRootRuleChainId(edgeTemplateRootRuleChain.getId());
}
Edge savedEdge = checkNotNull(edgeService.saveEdge(edge));
EdgeId edgeId = savedEdge.getId();

View File

@ -826,7 +826,8 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
assertThat(edgeImitator.waitForMessages()).as("await for messages on first connect").isTrue();
assertThat(edgeImitator.findAllMessagesByType(QueueUpdateMsg.class)).as("one msg during sync process").hasSize(1);
assertThat(edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class)).as("one msg during sync process, another from edge creation").hasSize(2);
List<RuleChainUpdateMsg> ruleChainUpdateMsgs = edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class);
assertThat(ruleChainUpdateMsgs).as("one msg during sync process, another from edge creation").hasSize(2);
assertThat(edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class)).as("one msg during sync process for 'default' device profile").hasSize(3);
assertThat(edgeImitator.findAllMessagesByType(DeviceUpdateMsg.class)).as("one msg once device assigned to edge").hasSize(2);
assertThat(edgeImitator.findAllMessagesByType(AssetProfileUpdateMsg.class)).as("two msgs during sync process for 'default' and 'test' asset profiles").hasSize(4);
@ -834,13 +835,15 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
assertThat(edgeImitator.findAllMessagesByType(UserUpdateMsg.class)).as("one msg during sync process for tenant admin user").hasSize(1);
assertThat(edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class)).as("admin setting update").hasSize(4);
assertThat(edgeImitator.findAllMessagesByType(CustomerUpdateMsg.class)).as("one msg during sync process for 'Public' customer").hasSize(1);
verifyRuleChainMsgsAreRoot(ruleChainUpdateMsgs);
edgeImitator.expectMessageAmount(15);
doPost("/api/edge/sync/" + edge.getId());
assertThat(edgeImitator.waitForMessages()).as("await for messages after edge sync rest api call").isTrue();
assertThat(edgeImitator.findAllMessagesByType(QueueUpdateMsg.class)).as("queue msg").hasSize(1);
assertThat(edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class)).as("rule chain msg").hasSize(1);
ruleChainUpdateMsgs = edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class);
assertThat(ruleChainUpdateMsgs).as("rule chain msg").hasSize(1);
assertThat(edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class)).as("device profile msg").hasSize(2);
assertThat(edgeImitator.findAllMessagesByType(AssetProfileUpdateMsg.class)).as("asset profile msg").hasSize(3);
assertThat(edgeImitator.findAllMessagesByType(AssetUpdateMsg.class)).as("asset update msg").hasSize(1);
@ -848,6 +851,7 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
assertThat(edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class)).as("admin setting update msg").hasSize(4);
assertThat(edgeImitator.findAllMessagesByType(DeviceUpdateMsg.class)).as("asset update msg").hasSize(1);
assertThat(edgeImitator.findAllMessagesByType(CustomerUpdateMsg.class)).as("one msg during sync process for 'Public' customer").hasSize(1);
verifyRuleChainMsgsAreRoot(ruleChainUpdateMsgs);
edgeImitator.allowIgnoredTypes();
try {
@ -863,6 +867,12 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isOk());
}
private void verifyRuleChainMsgsAreRoot(List<RuleChainUpdateMsg> ruleChainUpdateMsgs) {
for (RuleChainUpdateMsg ruleChainUpdateMsg : ruleChainUpdateMsgs) {
Assert.assertTrue(ruleChainUpdateMsg.getRoot());
}
}
@Test
public void testDeleteEdgeWithDeleteRelationsOk() throws Exception {
EdgeId edgeId = savedEdge("Edge for Test WithRelationsOk").getId();

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>common</artifactId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>script</artifactId>
</parent>
<groupId>org.thingsboard.common.script</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>script</artifactId>
</parent>
<groupId>org.thingsboard.common.script</groupId>

View File

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard.common</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>dao</artifactId>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

View File

@ -1,7 +1,7 @@
{
"name": "thingsboard-js-executor",
"private": true,
"version": "3.4.3",
"version": "3.5.0",
"description": "ThingsBoard JavaScript Executor Microservice",
"main": "server.ts",
"bin": "server.js",

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>msa</artifactId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard.msa</groupId>
<artifactId>transport</artifactId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

View File

@ -1,7 +1,7 @@
{
"name": "thingsboard-web-ui",
"private": true,
"version": "3.4.3",
"version": "3.5.0",
"description": "ThingsBoard Web UI Microservice",
"main": "server.ts",
"bin": "server.js",

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

View File

@ -19,11 +19,11 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>netty-mqtt</artifactId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Netty MQTT Client</name>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.thingsboard</groupId>
<artifactId>thingsboard</artifactId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Thingsboard</name>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>rest-client</artifactId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>rule-engine</artifactId>

View File

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>rule-engine</artifactId>
</parent>
<groupId>org.thingsboard.rule-engine</groupId>

View File

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>rule-engine</artifactId>
</parent>
<groupId>org.thingsboard.rule-engine</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>tools</artifactId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>transport</artifactId>

View File

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>

View File

@ -1,6 +1,6 @@
{
"name": "thingsboard",
"version": "3.4.3",
"version": "3.5.0",
"scripts": {
"ng": "ng",
"start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open",

View File

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>3.4.3-SNAPSHOT</version>
<version>3.5.0-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<groupId>org.thingsboard</groupId>

View File

@ -869,8 +869,26 @@ export class EntityService {
};
aliasInfo.currentEntity = null;
if (!aliasInfo.resolveMultiple && aliasInfo.entityFilter) {
return this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter,
{ignoreLoading: true, ignoreErrors: true}).pipe(
let currentEntity: EntityInfo = null;
if (result.stateEntity && aliasInfo.entityFilter.type === AliasFilterType.singleEntity) {
if (stateParams) {
let targetParams = stateParams;
if (result.entityParamName && result.entityParamName.length) {
targetParams = stateParams[result.entityParamName];
}
if (targetParams && targetParams.entityId) {
currentEntity = {
id: targetParams.entityId.id,
entityType: targetParams.entityId.entityType as EntityType,
name: targetParams.entityName,
label: targetParams.entityLabel
};
}
}
}
const entityInfoObservable = currentEntity ? of(currentEntity) : this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter,
{ignoreLoading: true, ignoreErrors: true});
return entityInfoObservable.pipe(
map((entity) => {
aliasInfo.currentEntity = entity;
return aliasInfo;

View File

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core';
import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
import { Observable, of, ReplaySubject, Subject } from 'rxjs';
import { Observable, of, ReplaySubject } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { PageLink } from '@shared/models/page/page-link';
import { PageData } from '@shared/models/page/page-data';
@ -43,15 +43,14 @@ import { ActivationEnd, Router } from '@angular/router';
})
export class WidgetService {
private widgetTypeUpdatedSubject = new Subject<WidgetType>();
private widgetsBundleDeletedSubject = new Subject<WidgetsBundle>();
private allWidgetsBundles: Array<WidgetsBundle>;
private systemWidgetsBundles: Array<WidgetsBundle>;
private tenantWidgetsBundles: Array<WidgetsBundle>;
private widgetTypeInfosCache = new Map<string, Array<WidgetTypeInfo>>();
private widgetsInfoInMemoryCache = new Map<string, WidgetInfo>();
private loadWidgetsBundleCacheSubject: ReplaySubject<any>;
constructor(
@ -117,7 +116,7 @@ export class WidgetService {
defaultHttpOptionsFromConfig(config)).pipe(
tap(() => {
this.invalidateWidgetsBundleCache();
this.widgetsBundleDeletedSubject.next(widgetsBundle);
this.widgetsBundleDeleted(widgetsBundle);
})
);
}
@ -217,7 +216,7 @@ export class WidgetService {
return this.http.post<WidgetTypeDetails>('/api/widgetType', widgetTypeDetails,
defaultHttpOptionsFromConfig(config)).pipe(
tap((savedWidgetType) => {
this.widgetTypeUpdatedSubject.next(savedWidgetType);
this.widgetTypeUpdated(savedWidgetType);
}));
}
@ -226,7 +225,7 @@ export class WidgetService {
return this.http.post<WidgetTypeDetails>('/api/widgetType', widgetTypeDetails,
defaultHttpOptionsFromConfig(config)).pipe(
tap((savedWidgetType) => {
this.widgetTypeUpdatedSubject.next(savedWidgetType);
this.widgetTypeUpdated(savedWidgetType);
}));
}
@ -237,7 +236,7 @@ export class WidgetService {
return this.http.delete(`/api/widgetType/${widgetTypeInstance.id.id}`,
defaultHttpOptionsFromConfig(config)).pipe(
tap(() => {
this.widgetTypeUpdatedSubject.next(widgetTypeInstance);
this.widgetTypeUpdated(widgetTypeInstance);
})
);
}
@ -263,12 +262,40 @@ export class WidgetService {
);
}
public onWidgetTypeUpdated(): Observable<WidgetType> {
return this.widgetTypeUpdatedSubject.asObservable();
public createWidgetInfoCacheKey(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): string {
return `${isSystem ? 'sys_' : ''}${bundleAlias}_${widgetTypeAlias}`;
}
public onWidgetBundleDeleted(): Observable<WidgetsBundle> {
return this.widgetsBundleDeletedSubject.asObservable();
public getWidgetInfoFromCache(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): WidgetInfo | undefined {
const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem);
return this.widgetsInfoInMemoryCache.get(key);
}
public putWidgetInfoToCache(widgetInfo: WidgetInfo, bundleAlias: string, widgetTypeAlias: string, isSystem: boolean) {
const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem);
this.widgetsInfoInMemoryCache.set(key, widgetInfo);
}
private widgetTypeUpdated(updatedWidgetType: WidgetType): void {
this.deleteWidgetInfoFromCache(updatedWidgetType.bundleAlias, updatedWidgetType.alias, updatedWidgetType.tenantId.id === NULL_UUID);
}
private widgetsBundleDeleted(widgetsBundle: WidgetsBundle): void {
this.deleteWidgetsBundleFromCache(widgetsBundle.alias, widgetsBundle.tenantId.id === NULL_UUID);
}
private deleteWidgetInfoFromCache(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean) {
const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem);
this.widgetsInfoInMemoryCache.delete(key);
}
private deleteWidgetsBundleFromCache(bundleAlias: string, isSystem: boolean) {
const key = (isSystem ? 'sys_' : '') + bundleAlias;
this.widgetsInfoInMemoryCache.forEach((widgetInfo, cacheKey) => {
if (cacheKey.startsWith(key)) {
this.widgetsInfoInMemoryCache.delete(cacheKey);
}
});
}
private loadWidgetsBundleCache(config?: RequestConfig): Observable<any> {

View File

@ -135,7 +135,7 @@
(click)="openDashboardSettings($event)">
<mat-icon>settings</mat-icon>
</button>
<tb-dashboard-select [fxShow]="!isEdit && !widgetEditMode && !embedded && displayDashboardsSelect()"
<tb-dashboard-select *ngIf="!isEdit && !widgetEditMode && !embedded && displayDashboardsSelect()"
[(ngModel)]="currentDashboardId"
(ngModelChange)="currentDashboardIdChanged(currentDashboardId)"
[customerId]="currentCustomerId"
@ -168,9 +168,9 @@
[ngClass]="{ 'tb-shrinked' : isEditingWidget }">
<mat-drawer *ngIf="layouts.right.show"
id="tb-right-layout"
[ngStyle]="{minWidth: rightLayoutWidth(),
maxWidth: rightLayoutWidth(),
height: rightLayoutHeight(),
[ngStyle]="{minWidth: rightLayoutSize.width,
maxWidth: rightLayoutSize.width,
height: rightLayoutSize.height,
borderLeft: 'none'}"
disableClose="true"
[@.disabled]="!isMobile"
@ -191,8 +191,8 @@
</mat-drawer>
<mat-drawer-content [fxShow]="layouts.main.show"
id="tb-main-layout"
[ngStyle]="{width: mainLayoutWidth(),
height: mainLayoutHeight()}">
[ngStyle]="{width: mainLayoutSize.width,
height: mainLayoutSize.height}">
<tb-dashboard-layout
[dashboardCheatSheet]="cheatSheetComponent"
[layoutCtx]="layouts.main.layoutCtx"

View File

@ -15,6 +15,7 @@
///
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
@ -56,7 +57,8 @@ import { WINDOW } from '@core/services/window.service';
import { WindowMessage } from '@shared/models/window-message.model';
import { deepClone, guid, isDefined, isDefinedAndNotNull, isNotEmptyStr } from '@app/core/utils';
import {
DashboardContext, DashboardPageInitData,
DashboardContext,
DashboardPageInitData,
DashboardPageLayout,
DashboardPageLayoutContext,
DashboardPageLayouts,
@ -148,6 +150,7 @@ import { TbPopoverService } from '@shared/components/popover.service';
import { tap } from 'rxjs/operators';
import { LayoutFixedSize, LayoutWidthType } from '@home/components/dashboard-page/layout/layout.models';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { ResizeObserver } from '@juggle/resize-observer';
// @dynamic
@Component({
@ -157,7 +160,7 @@ import { TbPopoverComponent } from '@shared/components/popover.component';
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DashboardPageComponent extends PageComponent implements IDashboardController, OnInit, OnDestroy {
export class DashboardPageComponent extends PageComponent implements IDashboardController, OnInit, AfterViewInit, OnDestroy {
authState: AuthState = getCurrentAuthState(this.store);
@ -244,9 +247,14 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
addingLayoutCtx: DashboardPageLayoutContext;
mainLayoutSize: {width: string; height: string} = {width: '100%', height: '100%'};
rightLayoutSize: {width: string; height: string} = {width: '100%', height: '100%'};
private dashboardLogoCache: SafeUrl;
private defaultDashboardLogo = 'assets/logo_title_white.svg';
private dashboardResize$: ResizeObserver;
dashboardCtx: DashboardContext = {
instanceId: this.utils.guid(),
getDashboard: () => this.dashboard,
@ -402,6 +410,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
.observe(MediaBreakpoints['gt-sm'])
.subscribe((state: BreakpointState) => {
this.isMobile = !state.matches;
this.updateLayoutSizes();
}
));
if (this.isMobileApp && this.syncStateWithQueryParam) {
@ -414,6 +423,13 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
}
}
ngAfterViewInit() {
this.dashboardResize$ = new ResizeObserver(() => {
this.updateLayoutSizes();
});
this.dashboardResize$.observe(this.dashboardContainer.nativeElement);
}
private init(data: DashboardPageInitData) {
this.reset();
@ -537,6 +553,9 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
subscription.unsubscribe();
});
this.rxSubscriptions.length = 0;
if (this.dashboardResize$) {
this.dashboardResize$.disconnect();
}
}
public runChangeDetection() {
@ -679,28 +698,48 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
this.mobileService.onDashboardRightLayoutChanged(this.isRightLayoutOpened);
}
public mainLayoutWidth(): string {
private updateLayoutSizes() {
let changeMainLayoutSize = false;
let changeRightLayoutSize = false;
if (this.dashboardCtx.state) {
changeMainLayoutSize = this.updateMainLayoutSize();
changeRightLayoutSize = this.updateRightLayoutSize();
}
if (changeMainLayoutSize || changeRightLayoutSize) {
this.cd.markForCheck();
}
}
private updateMainLayoutSize(): boolean {
const prevMainLayoutWidth = this.mainLayoutSize.width;
const prevMainLayoutHeight = this.mainLayoutSize.height;
if (this.isEditingWidget && this.editingLayoutCtx.id === 'main') {
return '100%';
this.mainLayoutSize.width = '100%';
} else {
return this.layouts.right.show && !this.isMobile ? this.calculateWidth('main') : '100%';
this.mainLayoutSize.width = this.layouts.right.show && !this.isMobile ? this.calculateWidth('main') : '100%';
}
}
public mainLayoutHeight(): string {
if (!this.isEditingWidget || this.editingLayoutCtx.id === 'main') {
return '100%';
this.mainLayoutSize.height = '100%';
} else {
return '0px';
this.mainLayoutSize.height = '0px';
}
return prevMainLayoutWidth !== this.mainLayoutSize.width || prevMainLayoutHeight !== this.mainLayoutSize.height;
}
public rightLayoutWidth(): string {
private updateRightLayoutSize(): boolean {
const prevRightLayoutWidth = this.rightLayoutSize.width;
const prevRightLayoutHeight = this.rightLayoutSize.height;
if (this.isEditingWidget && this.editingLayoutCtx.id === 'right') {
return '100%';
this.rightLayoutSize.width = '100%';
} else {
return this.isMobile ? '100%' : this.calculateWidth('right');
this.rightLayoutSize.width = this.isMobile ? '100%' : this.calculateWidth('right');
}
if (!this.isEditingWidget || this.editingLayoutCtx.id === 'right') {
this.rightLayoutSize.height = '100%';
} else {
this.rightLayoutSize.height = '0px';
}
return prevRightLayoutWidth !== this.rightLayoutSize.width || prevRightLayoutHeight !== this.rightLayoutSize.height;
}
private calculateWidth(layout: DashboardLayoutId): string {
@ -743,14 +782,6 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
}
}
public rightLayoutHeight(): string {
if (!this.isEditingWidget || this.editingLayoutCtx.id === 'right') {
return '100%';
} else {
return '0px';
}
}
public isPublicUser(): boolean {
return this.authUser.isPublic;
}
@ -977,6 +1008,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
layout.layoutCtx.ctrl.reload();
}
layout.layoutCtx.ignoreLoading = true;
this.updateLayoutSizes();
}
private setEditMode(isEdit: boolean, revert: boolean) {
@ -1191,6 +1223,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
this.editingLayoutCtx = null;
this.editingWidgetSubtitle = null;
this.isEditingWidget = false;
this.updateLayoutSizes();
this.resetHighlight();
this.forceDashboardMobileMode = false;
}
@ -1216,6 +1249,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
this.editingWidgetSubtitle = this.widgetComponentService.getInstantWidgetInfo(this.editingWidget).widgetName;
this.forceDashboardMobileMode = true;
this.isEditingWidget = true;
this.updateLayoutSizes();
if (layoutCtx) {
const delayOffset = transition ? 350 : 0;
const delay = transition ? 400 : 300;

View File

@ -297,6 +297,7 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent<Manag
setFixedLayout(layout: string): void {
if (this.layoutsFormGroup.get('type').value === LayoutWidthType.FIXED && this.layoutsFormGroup.get('right').value) {
this.layoutsFormGroup.get('fixedLayout').setValue(layout);
this.layoutsFormGroup.get('fixedLayout').markAsDirty();
}
}

View File

@ -50,14 +50,11 @@ import { widgetSettingsComponentsMap } from '@home/components/widget/lib/setting
const tinycolor = tinycolor_;
// @dynamic
@Injectable()
export class WidgetComponentService {
private cssParser = new cssjs();
private widgetsInfoInMemoryCache = new Map<string, WidgetInfo>();
private widgetsInfoFetchQueue = new Map<string, Array<Subject<WidgetInfo>>>();
private init$: Observable<any>;
@ -77,14 +74,6 @@ export class WidgetComponentService {
this.cssParser.testMode = false;
this.widgetService.onWidgetTypeUpdated().subscribe((widgetType) => {
this.deleteWidgetInfoFromCache(widgetType.bundleAlias, widgetType.alias, widgetType.tenantId.id === NULL_UUID);
});
this.widgetService.onWidgetBundleDeleted().subscribe((widgetsBundle) => {
this.deleteWidgetsBundleFromCache(widgetsBundle.alias, widgetsBundle.tenantId.id === NULL_UUID);
});
this.init();
}
@ -223,7 +212,7 @@ export class WidgetComponentService {
}
public getInstantWidgetInfo(widget: Widget): WidgetInfo {
const widgetInfo = this.getWidgetInfoFromCache(widget.bundleAlias, widget.typeAlias, widget.isSystemType);
const widgetInfo = this.widgetService.getWidgetInfoFromCache(widget.bundleAlias, widget.typeAlias, widget.isSystemType);
if (widgetInfo) {
return widgetInfo;
} else {
@ -239,7 +228,7 @@ export class WidgetComponentService {
private getWidgetInfoInternal(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): Observable<WidgetInfo> {
const widgetInfoSubject = new ReplaySubject<WidgetInfo>();
const widgetInfo = this.getWidgetInfoFromCache(bundleAlias, widgetTypeAlias, isSystem);
const widgetInfo = this.widgetService.getWidgetInfoFromCache(bundleAlias, widgetTypeAlias, isSystem);
if (widgetInfo) {
widgetInfoSubject.next(widgetInfo);
widgetInfoSubject.complete();
@ -247,7 +236,7 @@ export class WidgetComponentService {
if (this.utils.widgetEditMode) {
this.loadWidget(this.editingWidgetType, bundleAlias, isSystem, widgetInfoSubject);
} else {
const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem);
const key = this.widgetService.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem);
let fetchQueue = this.widgetsInfoFetchQueue.get(key);
if (fetchQueue) {
fetchQueue.push(widgetInfoSubject);
@ -272,7 +261,7 @@ export class WidgetComponentService {
private loadWidget(widgetType: WidgetType, bundleAlias: string, isSystem: boolean, widgetInfoSubject: Subject<WidgetInfo>) {
const widgetInfo = toWidgetInfo(widgetType);
const key = this.createWidgetInfoCacheKey(bundleAlias, widgetInfo.alias, isSystem);
const key = this.widgetService.createWidgetInfoCacheKey(bundleAlias, widgetInfo.alias, isSystem);
let widgetControllerDescriptor: WidgetControllerDescriptor = null;
try {
widgetControllerDescriptor = this.createWidgetControllerDescriptor(widgetInfo, key);
@ -297,7 +286,7 @@ export class WidgetComponentService {
widgetInfo.typeParameters = widgetControllerDescriptor.typeParameters;
widgetInfo.actionSources = widgetControllerDescriptor.actionSources;
widgetInfo.widgetTypeFunction = widgetControllerDescriptor.widgetTypeFunction;
this.putWidgetInfoToCache(widgetInfo, bundleAlias, widgetInfo.alias, isSystem);
this.widgetService.putWidgetInfoToCache(widgetInfo, bundleAlias, widgetInfo.alias, isSystem);
if (widgetInfoSubject) {
widgetInfoSubject.next(widgetInfo);
widgetInfoSubject.complete();
@ -331,7 +320,7 @@ export class WidgetComponentService {
(resource) => {
resourceTasks.push(
this.resources.loadResource(resource.url).pipe(
catchError(e => of(`Failed to load widget resource: '${resource.url}'`))
catchError(() => of(`Failed to load widget resource: '${resource.url}'`))
)
);
}
@ -586,34 +575,4 @@ export class WidgetComponentService {
this.widgetsInfoFetchQueue.delete(key);
}
}
// Cache functions
private createWidgetInfoCacheKey(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): string {
return `${isSystem ? 'sys_' : ''}${bundleAlias}_${widgetTypeAlias}`;
}
private getWidgetInfoFromCache(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): WidgetInfo | undefined {
const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem);
return this.widgetsInfoInMemoryCache.get(key);
}
private putWidgetInfoToCache(widgetInfo: WidgetInfo, bundleAlias: string, widgetTypeAlias: string, isSystem: boolean) {
const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem);
this.widgetsInfoInMemoryCache.set(key, widgetInfo);
}
private deleteWidgetInfoFromCache(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean) {
const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem);
this.widgetsInfoInMemoryCache.delete(key);
}
private deleteWidgetsBundleFromCache(bundleAlias: string, isSystem: boolean) {
const key = (isSystem ? 'sys_' : '') + bundleAlias;
this.widgetsInfoInMemoryCache.forEach((widgetInfo, cacheKey) => {
if (cacheKey.startsWith(key)) {
this.widgetsInfoInMemoryCache.delete(cacheKey);
}
});
}
}