From 7fdaf3f3832aa02067905c7b06729bed5b7b7b4a Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 5 Mar 2026 16:10:47 +0200 Subject: [PATCH] Refactor save rule chain note --- .../main/data/upgrade/basic/schema_update.sql | 7 +- .../common/data/rule/RuleChainDetails.java | 46 +++++++ .../server/dao/model/ModelConstants.java | 1 + .../model/sql/AbstractRuleChainEntity.java | 127 ++++++++++++++++++ .../dao/model/sql/RuleChainDetailsEntity.java | 65 +++++++++ .../server/dao/model/sql/RuleChainEntity.java | 78 +---------- .../server/dao/rule/BaseRuleChainService.java | 29 ++-- .../server/dao/rule/RuleChainDao.java | 5 + .../server/dao/sql/rule/JpaRuleChainDao.java | 15 +++ .../sql/rule/RuleChainDetailsRepository.java | 25 ++++ .../main/resources/sql/schema-entities.sql | 1 + .../rulechain/rule-note-editor.component.scss | 15 +++ 12 files changed, 318 insertions(+), 96 deletions(-) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainDetails.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractRuleChainEntity.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainDetailsEntity.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainDetailsRepository.java diff --git a/application/src/main/data/upgrade/basic/schema_update.sql b/application/src/main/data/upgrade/basic/schema_update.sql index 1d4b4ec393..f22eea3712 100644 --- a/application/src/main/data/upgrade/basic/schema_update.sql +++ b/application/src/main/data/upgrade/basic/schema_update.sql @@ -14,9 +14,8 @@ -- limitations under the License. -- +-- RULE CHAIN NOTES MIGRATION START --- RULE CHAIN NOTES START +ALTER TABLE rule_chain ADD COLUMN IF NOT EXISTS notes varchar(10000000); -ALTER TABLE rule_chain ADD COLUMN IF NOT EXISTS notes text; - --- RULE CHAIN NOTES END +-- RULE CHAIN NOTES MIGRATION END diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainDetails.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainDetails.java new file mode 100644 index 0000000000..c09cc8aef3 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainDetails.java @@ -0,0 +1,46 @@ +/** + * Copyright © 2016-2026 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.rule; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +public class RuleChainDetails extends RuleChain { + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @Schema(description = "List of sticky notes placed on the rule chain canvas") + private List notes; + + public RuleChainDetails() { + super(); + } + + public RuleChainDetails(RuleChain ruleChain) { + super(ruleChain); + } + + public RuleChainDetails(RuleChainDetails ruleChainDetails) { + super(ruleChainDetails); + this.notes = ruleChainDetails.getNotes(); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 9f9e4a67e9..6eb14092ae 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -420,6 +420,7 @@ public class ModelConstants { public static final String RULE_CHAIN_FIRST_RULE_NODE_ID_PROPERTY = "first_rule_node_id"; public static final String RULE_CHAIN_ROOT_PROPERTY = "root"; public static final String RULE_CHAIN_CONFIGURATION_PROPERTY = "configuration"; + public static final String RULE_CHAIN_NOTES_PROPERTY = "notes"; /** * Rule node constants. diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractRuleChainEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractRuleChainEntity.java new file mode 100644 index 0000000000..71b729ae76 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractRuleChainEntity.java @@ -0,0 +1,127 @@ +/** + * Copyright © 2016-2026 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.model.sql; + +import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.MappedSuperclass; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.thingsboard.server.common.data.id.RuleChainId; +import org.thingsboard.server.common.data.id.RuleNodeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainType; +import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.model.BaseVersionedEntity; +import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.util.mapping.JsonConverter; + +import java.util.UUID; + +@Data +@EqualsAndHashCode(callSuper = true) +@MappedSuperclass +public abstract class AbstractRuleChainEntity extends BaseVersionedEntity { + + @Column(name = ModelConstants.RULE_CHAIN_TENANT_ID_PROPERTY) + private UUID tenantId; + + @Column(name = ModelConstants.RULE_CHAIN_NAME_PROPERTY) + private String name; + + @Enumerated(EnumType.STRING) + @Column(name = ModelConstants.RULE_CHAIN_TYPE_PROPERTY) + private RuleChainType type; + + @Column(name = ModelConstants.RULE_CHAIN_FIRST_RULE_NODE_ID_PROPERTY) + private UUID firstRuleNodeId; + + @Column(name = ModelConstants.RULE_CHAIN_ROOT_PROPERTY) + private boolean root; + + @Column(name = ModelConstants.DEBUG_MODE) + private boolean debugMode; + + @Convert(converter = JsonConverter.class) + @Column(name = ModelConstants.RULE_CHAIN_CONFIGURATION_PROPERTY) + private JsonNode configuration; + + @Convert(converter = JsonConverter.class) + @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY) + private JsonNode additionalInfo; + + @Column(name = ModelConstants.EXTERNAL_ID_PROPERTY) + private UUID externalId; + + public AbstractRuleChainEntity() { + super(); + } + + public AbstractRuleChainEntity(T ruleChain) { + super(ruleChain); + this.tenantId = DaoUtil.getId(ruleChain.getTenantId()); + this.name = ruleChain.getName(); + this.type = ruleChain.getType(); + if (ruleChain.getFirstRuleNodeId() != null) { + this.firstRuleNodeId = ruleChain.getFirstRuleNodeId().getId(); + } + this.root = ruleChain.isRoot(); + this.debugMode = ruleChain.isDebugMode(); + this.configuration = ruleChain.getConfiguration(); + this.additionalInfo = ruleChain.getAdditionalInfo(); + if (ruleChain.getExternalId() != null) { + this.externalId = ruleChain.getExternalId().getId(); + } + } + + public AbstractRuleChainEntity(AbstractRuleChainEntity ruleChainEntity) { + super(ruleChainEntity); + this.tenantId = ruleChainEntity.getTenantId(); + this.name = ruleChainEntity.getName(); + this.type = ruleChainEntity.getType(); + this.firstRuleNodeId = ruleChainEntity.getFirstRuleNodeId(); + this.root = ruleChainEntity.isRoot(); + this.debugMode = ruleChainEntity.isDebugMode(); + this.configuration = ruleChainEntity.getConfiguration(); + this.additionalInfo = ruleChainEntity.getAdditionalInfo(); + this.externalId = ruleChainEntity.getExternalId(); + } + + protected RuleChain toRuleChain() { + RuleChain ruleChain = new RuleChain(new RuleChainId(this.getUuid())); + ruleChain.setCreatedTime(createdTime); + ruleChain.setVersion(version); + ruleChain.setTenantId(TenantId.fromUUID(tenantId)); + ruleChain.setName(name); + ruleChain.setType(type); + if (firstRuleNodeId != null) { + ruleChain.setFirstRuleNodeId(new RuleNodeId(firstRuleNodeId)); + } + ruleChain.setRoot(root); + ruleChain.setDebugMode(debugMode); + ruleChain.setConfiguration(configuration); + ruleChain.setAdditionalInfo(additionalInfo); + if (externalId != null) { + ruleChain.setExternalId(new RuleChainId(externalId)); + } + return ruleChain; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainDetailsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainDetailsEntity.java new file mode 100644 index 0000000000..732687016e --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainDetailsEntity.java @@ -0,0 +1,65 @@ +/** + * Copyright © 2016-2026 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.model.sql; + +import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainDetails; +import org.thingsboard.server.common.data.rule.RuleChainNote; +import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.util.mapping.JsonConverter; + +import java.util.Arrays; + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = ModelConstants.RULE_CHAIN_TABLE_NAME) +public class RuleChainDetailsEntity extends AbstractRuleChainEntity { + + @Convert(converter = JsonConverter.class) + @Column(name = ModelConstants.RULE_CHAIN_NOTES_PROPERTY) + private JsonNode notes; + + public RuleChainDetailsEntity() { + super(); + } + + public RuleChainDetailsEntity(RuleChainDetails ruleChainDetails) { + super(ruleChainDetails); + if (ruleChainDetails.getNotes() != null) { + this.notes = JacksonUtil.valueToTree(ruleChainDetails.getNotes()); + } + } + + @Override + public RuleChainDetails toData() { + RuleChain ruleChain = super.toRuleChain(); + RuleChainDetails details = new RuleChainDetails(ruleChain); + if (notes != null && notes.isArray()) { + details.setNotes(Arrays.asList(JacksonUtil.treeToValue(notes, RuleChainNote[].class))); + } + return details; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java index 5b83eb6f72..ca6651a965 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java @@ -15,102 +15,30 @@ */ package org.thingsboard.server.dao.model.sql; -import com.fasterxml.jackson.databind.JsonNode; -import jakarta.persistence.Column; -import jakarta.persistence.Convert; import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.thingsboard.server.common.data.id.RuleChainId; -import org.thingsboard.server.common.data.id.RuleNodeId; -import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.rule.RuleChain; -import org.thingsboard.server.common.data.rule.RuleChainType; -import org.thingsboard.server.dao.DaoUtil; -import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonConverter; - -import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.RULE_CHAIN_TABLE_NAME) -public class RuleChainEntity extends BaseVersionedEntity { - - @Column(name = ModelConstants.RULE_CHAIN_TENANT_ID_PROPERTY) - private UUID tenantId; - - @Column(name = ModelConstants.RULE_CHAIN_NAME_PROPERTY) - private String name; - - @Enumerated(EnumType.STRING) - @Column(name = ModelConstants.RULE_CHAIN_TYPE_PROPERTY) - private RuleChainType type; - - @Column(name = ModelConstants.RULE_CHAIN_FIRST_RULE_NODE_ID_PROPERTY) - private UUID firstRuleNodeId; - - @Column(name = ModelConstants.RULE_CHAIN_ROOT_PROPERTY) - private boolean root; - - @Column(name = ModelConstants.DEBUG_MODE) - private boolean debugMode; - - @Convert(converter = JsonConverter.class) - @Column(name = ModelConstants.RULE_CHAIN_CONFIGURATION_PROPERTY) - private JsonNode configuration; - - @Convert(converter = JsonConverter.class) - @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY) - private JsonNode additionalInfo; - - @Column(name = ModelConstants.EXTERNAL_ID_PROPERTY) - private UUID externalId; +public class RuleChainEntity extends AbstractRuleChainEntity { public RuleChainEntity() { + super(); } public RuleChainEntity(RuleChain ruleChain) { super(ruleChain); - this.tenantId = DaoUtil.getId(ruleChain.getTenantId()); - this.name = ruleChain.getName(); - this.type = ruleChain.getType(); - if (ruleChain.getFirstRuleNodeId() != null) { - this.firstRuleNodeId = ruleChain.getFirstRuleNodeId().getId(); - } - this.root = ruleChain.isRoot(); - this.debugMode = ruleChain.isDebugMode(); - this.configuration = ruleChain.getConfiguration(); - this.additionalInfo = ruleChain.getAdditionalInfo(); - if (ruleChain.getExternalId() != null) { - this.externalId = ruleChain.getExternalId().getId(); - } } @Override public RuleChain toData() { - RuleChain ruleChain = new RuleChain(new RuleChainId(this.getUuid())); - ruleChain.setCreatedTime(createdTime); - ruleChain.setVersion(version); - ruleChain.setTenantId(TenantId.fromUUID(tenantId)); - ruleChain.setName(name); - ruleChain.setType(type); - if (firstRuleNodeId != null) { - ruleChain.setFirstRuleNodeId(new RuleNodeId(firstRuleNodeId)); - } - ruleChain.setRoot(root); - ruleChain.setDebugMode(debugMode); - ruleChain.setConfiguration(configuration); - ruleChain.setAdditionalInfo(additionalInfo); - if (externalId != null) { - ruleChain.setExternalId(new RuleChainId(externalId)); - } - return ruleChain; + return super.toRuleChain(); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index 8816796c8e..50a2d148d7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -16,7 +16,6 @@ package org.thingsboard.server.dao.rule; import com.datastax.oss.driver.api.core.uuid.Uuids; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FluentFuture; @@ -52,9 +51,9 @@ import org.thingsboard.server.common.data.rule.NodeConnectionInfo; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; import org.thingsboard.server.common.data.rule.RuleChainData; +import org.thingsboard.server.common.data.rule.RuleChainDetails; import org.thingsboard.server.common.data.rule.RuleChainImportResult; import org.thingsboard.server.common.data.rule.RuleChainMetaData; -import org.thingsboard.server.common.data.rule.RuleChainNote; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleChainUpdateResult; import org.thingsboard.server.common.data.rule.RuleNode; @@ -318,12 +317,11 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC if (!relations.isEmpty()) { relationService.saveRelations(tenantId, relations); } - ruleChain.setConfiguration(CollectionUtils.isNotEmpty(ruleChainMetaData.getNotes()) - ? JacksonUtil.newObjectNode().set("notes", JacksonUtil.valueToTree(ruleChainMetaData.getNotes())) - : null); - ruleChain = ruleChainDao.save(tenantId, ruleChain); - eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId).entity(ruleChain) - .entityId(ruleChain.getId()).broadcastEvent(publishSaveEvent).build()); + RuleChainDetails ruleChainDetails = new RuleChainDetails(ruleChain); + ruleChainDetails.setNotes(ruleChainMetaData.getNotes()); + ruleChainDetails = ruleChainDao.saveDetails(ruleChainDetails); + eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId).entity(ruleChainDetails) + .entityId(ruleChainDetails.getId()).broadcastEvent(publishSaveEvent).build()); return RuleChainUpdateResult.successful(updatedRuleNodes); } @@ -346,13 +344,13 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override public RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId) { Validator.validateId(ruleChainId, "Incorrect rule chain id."); - RuleChain ruleChain = findRuleChainById(tenantId, ruleChainId); - if (ruleChain == null) { + RuleChainDetails ruleChainDetails = ruleChainDao.findDetailsById(ruleChainId.getId()); + if (ruleChainDetails == null) { return null; } RuleChainMetaData ruleChainMetaData = new RuleChainMetaData(); ruleChainMetaData.setRuleChainId(ruleChainId); - ruleChainMetaData.setVersion(ruleChain.getVersion()); + ruleChainMetaData.setVersion(ruleChainDetails.getVersion()); List ruleNodes = getRuleChainNodes(tenantId, ruleChainId); Collections.sort(ruleNodes, Comparator.comparingLong(RuleNode::getCreatedTime).thenComparing(RuleNode::getId, Comparator.comparing(RuleNodeId::getId))); Map ruleNodeIndexMap = new HashMap<>(); @@ -360,8 +358,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC ruleNodeIndexMap.put(node.getId(), ruleNodes.indexOf(node)); } ruleChainMetaData.setNodes(ruleNodes); - if (ruleChain.getFirstRuleNodeId() != null) { - ruleChainMetaData.setFirstNodeIndex(ruleNodeIndexMap.get(ruleChain.getFirstRuleNodeId())); + if (ruleChainDetails.getFirstRuleNodeId() != null) { + ruleChainMetaData.setFirstNodeIndex(ruleNodeIndexMap.get(ruleChainDetails.getFirstRuleNodeId())); } for (RuleNode node : ruleNodes) { int fromIndex = ruleNodeIndexMap.get(node.getId()); @@ -381,10 +379,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC Collections.sort(ruleChainMetaData.getConnections(), Comparator.comparingInt(NodeConnectionInfo::getFromIndex) .thenComparing(NodeConnectionInfo::getToIndex).thenComparing(NodeConnectionInfo::getType)); } - ruleChainMetaData.setNotes(Optional.ofNullable(ruleChain.getConfiguration()) - .filter(c -> c.has("notes")) - .map(c -> JacksonUtil.convertValue(c.get("notes"), new TypeReference>() {})) - .orElse(null)); + ruleChainMetaData.setNotes(ruleChainDetails.getNotes()); return ruleChainMetaData; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java index b88ed2294b..bec8ef0144 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java @@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainDetails; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.ExportableEntityDao; @@ -85,4 +86,8 @@ public interface RuleChainDao extends Dao, TenantEntityDao List findRuleChainsByTenantIdAndIds(UUID tenantId, List ruleChainIds); + RuleChainDetails findDetailsById(UUID id); + + RuleChainDetails saveDetails(RuleChainDetails ruleChainDetails); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java index a72b053a98..19cf95e5bc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java @@ -29,8 +29,10 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainDetails; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.model.sql.RuleChainDetailsEntity; import org.thingsboard.server.dao.model.sql.RuleChainEntity; import org.thingsboard.server.dao.rule.RuleChainDao; import org.thingsboard.server.dao.sql.JpaAbstractDao; @@ -49,6 +51,9 @@ public class JpaRuleChainDao extends JpaAbstractDao @Autowired private RuleChainRepository ruleChainRepository; + @Autowired + private RuleChainDetailsRepository ruleChainDetailsRepository; + @Override protected Class getEntityClass() { return RuleChainEntity.class; @@ -163,6 +168,16 @@ public class JpaRuleChainDao extends JpaAbstractDao return ruleChainRepository.findNextBatch(id, Limit.of(batchSize)); } + @Override + public RuleChainDetails findDetailsById(UUID id) { + return DaoUtil.getData(ruleChainDetailsRepository.findById(id)); + } + + @Override + public RuleChainDetails saveDetails(RuleChainDetails ruleChainDetails) { + return DaoUtil.getData(ruleChainDetailsRepository.save(new RuleChainDetailsEntity(ruleChainDetails))); + } + @Override public EntityType getEntityType() { return EntityType.RULE_CHAIN; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainDetailsRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainDetailsRepository.java new file mode 100644 index 0000000000..df54720984 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainDetailsRepository.java @@ -0,0 +1,25 @@ +/** + * Copyright © 2016-2026 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.sql.rule; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.thingsboard.server.dao.model.sql.RuleChainDetailsEntity; + +import java.util.UUID; + +public interface RuleChainDetailsRepository extends JpaRepository { + +} diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 3d9c9f17e6..3e7ea93ead 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -162,6 +162,7 @@ CREATE TABLE IF NOT EXISTS rule_chain ( created_time bigint NOT NULL, additional_info varchar, configuration varchar(10000000), + notes varchar(10000000), name varchar(255), type varchar(255), first_rule_node_id uuid, diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.scss b/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.scss index 033e82b0b1..6d89be41ad 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.scss +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.scss @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2026 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ :host ::ng-deep { tb-markdown-editor { .markdown-content.tb-edit-mode {