diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 6a7ad5158c..419a5ade13 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -78,6 +78,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; @@ -584,13 +585,13 @@ public abstract class BaseController { } } - WidgetType checkWidgetTypeId(WidgetTypeId widgetTypeId, Operation operation) throws ThingsboardException { + WidgetTypeDetails checkWidgetTypeId(WidgetTypeId widgetTypeId, Operation operation) throws ThingsboardException { try { validateId(widgetTypeId, "Incorrect widgetTypeId " + widgetTypeId); - WidgetType widgetType = widgetTypeService.findWidgetTypeById(getCurrentUser().getTenantId(), widgetTypeId); - checkNotNull(widgetType); - accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, operation, widgetTypeId, widgetType); - return widgetType; + WidgetTypeDetails widgetTypeDetails = widgetTypeService.findWidgetTypeDetailsById(getCurrentUser().getTenantId(), widgetTypeId); + checkNotNull(widgetTypeDetails); + accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, operation, widgetTypeId, widgetTypeDetails); + return widgetTypeDetails; } catch (Exception e) { throw handleException(e, false); } diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java index 9d936b96c0..3239d143bd 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java @@ -30,6 +30,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; +import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.permission.Operation; @@ -45,7 +47,7 @@ public class WidgetTypeController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.GET) @ResponseBody - public WidgetType getWidgetTypeById(@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { + public WidgetTypeDetails getWidgetTypeById(@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { checkParameter("widgetTypeId", strWidgetTypeId); try { WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); @@ -58,17 +60,17 @@ public class WidgetTypeController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/widgetType", method = RequestMethod.POST) @ResponseBody - public WidgetType saveWidgetType(@RequestBody WidgetType widgetType) throws ThingsboardException { + public WidgetTypeDetails saveWidgetType(@RequestBody WidgetTypeDetails widgetTypeDetails) throws ThingsboardException { try { if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { - widgetType.setTenantId(TenantId.SYS_TENANT_ID); + widgetTypeDetails.setTenantId(TenantId.SYS_TENANT_ID); } else { - widgetType.setTenantId(getCurrentUser().getTenantId()); + widgetTypeDetails.setTenantId(getCurrentUser().getTenantId()); } - checkEntity(widgetType.getId(), widgetType, Resource.WIDGET_TYPE); + checkEntity(widgetTypeDetails.getId(), widgetTypeDetails, Resource.WIDGET_TYPE); - return checkNotNull(widgetTypeService.saveWidgetType(widgetType)); + return checkNotNull(widgetTypeService.saveWidgetType(widgetTypeDetails)); } catch (Exception e) { throw handleException(e); } @@ -107,6 +109,44 @@ public class WidgetTypeController extends BaseController { } } + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @RequestMapping(value = "/widgetTypesDetails", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) + @ResponseBody + public List getBundleWidgetTypesDetails( + @RequestParam boolean isSystem, + @RequestParam String bundleAlias) throws ThingsboardException { + try { + TenantId tenantId; + if (isSystem) { + tenantId = TenantId.SYS_TENANT_ID; + } else { + tenantId = getCurrentUser().getTenantId(); + } + return checkNotNull(widgetTypeService.findWidgetTypesDetailsByTenantIdAndBundleAlias(tenantId, bundleAlias)); + } catch (Exception e) { + throw handleException(e); + } + } + + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @RequestMapping(value = "/widgetTypesInfos", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) + @ResponseBody + public List getBundleWidgetTypesInfos( + @RequestParam boolean isSystem, + @RequestParam String bundleAlias) throws ThingsboardException { + try { + TenantId tenantId; + if (isSystem) { + tenantId = TenantId.SYS_TENANT_ID; + } else { + tenantId = getCurrentUser().getTenantId(); + } + return checkNotNull(widgetTypeService.findWidgetTypesInfosByTenantIdAndBundleAlias(tenantId, bundleAlias)); + } catch (Exception e) { + throw handleException(e); + } + } + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/widgetType", params = {"isSystem", "bundleAlias", "alias"}, method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java index 47f8529c11..f1ed6dddeb 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java +++ b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplat import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; @@ -168,9 +169,9 @@ public class InstallScripts { widgetTypesArrayJson.forEach( widgetTypeJson -> { try { - WidgetType widgetType = objectMapper.treeToValue(widgetTypeJson, WidgetType.class); - widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); - widgetTypeService.saveWidgetType(widgetType); + WidgetTypeDetails widgetTypeDetails = objectMapper.treeToValue(widgetTypeJson, WidgetTypeDetails.class); + widgetTypeDetails.setBundleAlias(savedWidgetsBundle.getAlias()); + widgetTypeService.saveWidgetType(widgetTypeDetails); } catch (Exception e) { log.error("Unable to load widget type from json: [{}]", path.toString()); throw new RuntimeException("Unable to load widget type from json", e); diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseWidgetTypeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseWidgetTypeControllerTest.java index 9c135f549c..bcb1a1abd4 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseWidgetTypeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseWidgetTypeControllerTest.java @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetsBundle; import java.util.ArrayList; @@ -76,11 +77,11 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes @Test public void testSaveWidgetType() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); + WidgetTypeDetails savedWidgetType = doPost("/api/widgetType", widgetType, WidgetTypeDetails.class); Assert.assertNotNull(savedWidgetType); Assert.assertNotNull(savedWidgetType.getId()); @@ -95,42 +96,42 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes doPost("/api/widgetType", savedWidgetType, WidgetType.class); - WidgetType foundWidgetType = doGet("/api/widgetType/" + savedWidgetType.getId().getId().toString(), WidgetType.class); + WidgetTypeDetails foundWidgetType = doGet("/api/widgetType/" + savedWidgetType.getId().getId().toString(), WidgetTypeDetails.class); Assert.assertEquals(foundWidgetType.getName(), savedWidgetType.getName()); } @Test public void testUpdateWidgetTypeFromDifferentTenant() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); + WidgetTypeDetails savedWidgetType = doPost("/api/widgetType", widgetType, WidgetTypeDetails.class); loginDifferentTenant(); - doPost("/api/widgetType", savedWidgetType, WidgetType.class, status().isForbidden()); + doPost("/api/widgetType", savedWidgetType, WidgetTypeDetails.class, status().isForbidden()); deleteDifferentTenant(); } @Test public void testFindWidgetTypeById() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); - WidgetType foundWidgetType = doGet("/api/widgetType/" + savedWidgetType.getId().getId().toString(), WidgetType.class); + WidgetTypeDetails savedWidgetType = doPost("/api/widgetType", widgetType, WidgetTypeDetails.class); + WidgetTypeDetails foundWidgetType = doGet("/api/widgetType/" + savedWidgetType.getId().getId().toString(), WidgetTypeDetails.class); Assert.assertNotNull(foundWidgetType); Assert.assertEquals(savedWidgetType, foundWidgetType); } @Test public void testDeleteWidgetType() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); + WidgetTypeDetails savedWidgetType = doPost("/api/widgetType", widgetType, WidgetTypeDetails.class); doDelete("/api/widgetType/"+savedWidgetType.getId().getId().toString()) .andExpect(status().isOk()); @@ -141,7 +142,7 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes @Test public void testSaveWidgetTypeWithEmptyName() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); doPost("/api/widgetType", widgetType) @@ -151,7 +152,7 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes @Test public void testSaveWidgetTypeWithEmptyBundleAlias() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); doPost("/api/widgetType", widgetType) @@ -161,7 +162,7 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes @Test public void testSaveWidgetTypeWithEmptyDescriptor() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{}", JsonNode.class)); @@ -172,7 +173,7 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes @Test public void testSaveWidgetTypeWithInvalidBundleAlias() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias("some_alias"); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); @@ -183,11 +184,11 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes @Test public void testUpdateWidgetTypeBundleAlias() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); + WidgetTypeDetails savedWidgetType = doPost("/api/widgetType", widgetType, WidgetTypeDetails.class); savedWidgetType.setBundleAlias("some_alias"); doPost("/api/widgetType", savedWidgetType) .andExpect(status().isBadRequest()) @@ -197,11 +198,11 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes @Test public void testUpdateWidgetTypeAlias() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); + WidgetTypeDetails savedWidgetType = doPost("/api/widgetType", widgetType, WidgetTypeDetails.class); savedWidgetType.setAlias("some_alias"); doPost("/api/widgetType", savedWidgetType) .andExpect(status().isBadRequest()) @@ -213,15 +214,15 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes public void testGetBundleWidgetTypes() throws Exception { List widgetTypes = new ArrayList<>(); for (int i=0;i<89;i++) { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type " + i); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - widgetTypes.add(doPost("/api/widgetType", widgetType, WidgetType.class)); + widgetTypes.add(new WidgetType(doPost("/api/widgetType", widgetType, WidgetTypeDetails.class))); } List loadedWidgetTypes = doGetTyped("/api/widgetTypes?isSystem={isSystem}&bundleAlias={bundleAlias}", - new TypeReference>(){}, false, savedWidgetsBundle.getAlias()); + new TypeReference<>(){}, false, savedWidgetsBundle.getAlias()); Collections.sort(widgetTypes, idComparator); Collections.sort(loadedWidgetTypes, idComparator); @@ -231,15 +232,15 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes @Test public void testGetWidgetType() throws Exception { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); + WidgetTypeDetails savedWidgetType = doPost("/api/widgetType", widgetType, WidgetTypeDetails.class); WidgetType foundWidgetType = doGet("/api/widgetType?isSystem={isSystem}&bundleAlias={bundleAlias}&alias={alias}", WidgetType.class, false, savedWidgetsBundle.getAlias(), savedWidgetType.getAlias()); Assert.assertNotNull(foundWidgetType); - Assert.assertEquals(savedWidgetType, foundWidgetType); + Assert.assertEquals(new WidgetType(savedWidgetType), foundWidgetType); } } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java index 289fc36c07..1e67655ae4 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java @@ -18,6 +18,8 @@ package org.thingsboard.server.dao.widget; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; +import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import java.util.List; @@ -25,12 +27,18 @@ public interface WidgetTypeService { WidgetType findWidgetTypeById(TenantId tenantId, WidgetTypeId widgetTypeId); - WidgetType saveWidgetType(WidgetType widgetType); + WidgetTypeDetails findWidgetTypeDetailsById(TenantId tenantId, WidgetTypeId widgetTypeId); + + WidgetTypeDetails saveWidgetType(WidgetTypeDetails widgetType); void deleteWidgetType(TenantId tenantId, WidgetTypeId widgetTypeId); List findWidgetTypesByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias); + List findWidgetTypesDetailsByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias); + + List findWidgetTypesInfosByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias); + WidgetType findWidgetTypeByTenantIdBundleAliasAndAlias(TenantId tenantId, String bundleAlias, String alias); void deleteWidgetTypesByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/BaseWidgetType.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/BaseWidgetType.java new file mode 100644 index 0000000000..e3463f3614 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/BaseWidgetType.java @@ -0,0 +1,49 @@ +/** + * Copyright © 2016-2021 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.widget; + +import lombok.Data; +import org.thingsboard.server.common.data.BaseData; +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.WidgetTypeId; + +@Data +public class BaseWidgetType extends BaseData implements HasTenantId { + + private static final long serialVersionUID = 8388684344603660756L; + + private TenantId tenantId; + private String bundleAlias; + private String alias; + private String name; + + public BaseWidgetType() { + super(); + } + + public BaseWidgetType(WidgetTypeId id) { + super(id); + } + + public BaseWidgetType(BaseWidgetType widgetType) { + super(widgetType); + this.tenantId = widgetType.getTenantId(); + this.bundleAlias = widgetType.getBundleAlias(); + this.alias = widgetType.getAlias(); + this.name = widgetType.getName(); + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java index 1909d78bbc..04432093ea 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java @@ -16,23 +16,12 @@ package org.thingsboard.server.common.data.widget; import com.fasterxml.jackson.databind.JsonNode; -import lombok.EqualsAndHashCode; -import org.thingsboard.server.common.data.BaseData; -import org.thingsboard.server.common.data.HasTenantId; -import org.thingsboard.server.common.data.id.TenantId; +import lombok.Data; import org.thingsboard.server.common.data.id.WidgetTypeId; -@EqualsAndHashCode(callSuper = true) -public class WidgetType extends BaseData implements HasTenantId { +@Data +public class WidgetType extends BaseWidgetType { - private static final long serialVersionUID = 8388684344603660756L; - - private TenantId tenantId; - private String bundleAlias; - private String alias; - private String name; - private String image; - private String description; private transient JsonNode descriptor; public WidgetType() { @@ -43,76 +32,13 @@ public class WidgetType extends BaseData implements HasTenantId { super(id); } + public WidgetType(BaseWidgetType baseWidgetType) { + super(baseWidgetType); + } + public WidgetType(WidgetType widgetType) { super(widgetType); - this.tenantId = widgetType.getTenantId(); - this.bundleAlias = widgetType.getBundleAlias(); - this.alias = widgetType.getAlias(); - this.name = widgetType.getName(); - this.image = widgetType.getImage(); - this.description = widgetType.getDescription(); this.descriptor = widgetType.getDescriptor(); } - public TenantId getTenantId() { - return tenantId; - } - - public void setTenantId(TenantId tenantId) { - this.tenantId = tenantId; - } - - public String getBundleAlias() { - return bundleAlias; - } - - public void setBundleAlias(String bundleAlias) { - this.bundleAlias = bundleAlias; - } - - public String getAlias() { - return alias; - } - - public void setAlias(String alias) { - this.alias = alias; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getImage() { return image; } - - public void setImage(String image) { this.image = image; } - - public String getDescription() { return description; } - - public void setDescription(String description) { this.description = description; } - - public JsonNode getDescriptor() { - return descriptor; - } - - public void setDescriptor(JsonNode descriptor) { - this.descriptor = descriptor; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("WidgetType{"); - sb.append("tenantId=").append(tenantId); - sb.append(", bundleAlias='").append(bundleAlias).append('\''); - sb.append(", alias='").append(alias).append('\''); - sb.append(", name='").append(name).append('\''); - sb.append(", image='").append(image).append('\''); - sb.append(", description='").append(description).append('\''); - sb.append(", descriptor=").append(descriptor); - sb.append('}'); - return sb.toString(); - } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java new file mode 100644 index 0000000000..232a10e755 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java @@ -0,0 +1,45 @@ +/** + * Copyright © 2016-2021 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.widget; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.Data; +import org.thingsboard.server.common.data.id.WidgetTypeId; + +@Data +public class WidgetTypeDetails extends WidgetType { + + private String image; + private String description; + + public WidgetTypeDetails() { + super(); + } + + public WidgetTypeDetails(WidgetTypeId id) { + super(id); + } + + public WidgetTypeDetails(BaseWidgetType baseWidgetType) { + super(baseWidgetType); + } + + public WidgetTypeDetails(WidgetTypeDetails widgetTypeDetails) { + super(widgetTypeDetails); + this.image = widgetTypeDetails.getImage(); + this.description = widgetTypeDetails.getDescription(); + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java new file mode 100644 index 0000000000..645483bcc3 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java @@ -0,0 +1,46 @@ +/** + * Copyright © 2016-2021 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.widget; + +import lombok.Data; +import org.thingsboard.server.common.data.id.WidgetTypeId; + +@Data +public class WidgetTypeInfo extends BaseWidgetType { + + private String image; + private String description; + private String widgetType; + + public WidgetTypeInfo() { + super(); + } + + public WidgetTypeInfo(WidgetTypeId id) { + super(id); + } + + public WidgetTypeInfo(BaseWidgetType baseWidgetType) { + super(baseWidgetType); + } + + public WidgetTypeInfo(WidgetTypeInfo widgetTypeInfo) { + super(widgetTypeInfo); + this.image = widgetTypeInfo.getImage(); + this.description = widgetTypeInfo.getDescription(); + this.widgetType = widgetTypeInfo.getWidgetType(); + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractWidgetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractWidgetTypeEntity.java new file mode 100644 index 0000000000..803d1604f8 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractWidgetTypeEntity.java @@ -0,0 +1,86 @@ +/** + * Copyright © 2016-2021 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 lombok.Data; +import lombok.EqualsAndHashCode; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.WidgetTypeId; +import org.thingsboard.server.common.data.widget.BaseWidgetType; +import org.thingsboard.server.dao.model.BaseEntity; +import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.ModelConstants; + +import javax.persistence.Column; +import javax.persistence.MappedSuperclass; +import java.util.UUID; + +@Data +@EqualsAndHashCode(callSuper = true) +@MappedSuperclass +public abstract class AbstractWidgetTypeEntity extends BaseSqlEntity implements BaseEntity { + + @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY) + private UUID tenantId; + + @Column(name = ModelConstants.WIDGET_TYPE_BUNDLE_ALIAS_PROPERTY) + private String bundleAlias; + + @Column(name = ModelConstants.WIDGET_TYPE_ALIAS_PROPERTY) + private String alias; + + @Column(name = ModelConstants.WIDGET_TYPE_NAME_PROPERTY) + private String name; + + public AbstractWidgetTypeEntity() { + super(); + } + + public AbstractWidgetTypeEntity(BaseWidgetType widgetType) { + if (widgetType.getId() != null) { + this.setUuid(widgetType.getId().getId()); + } + this.setCreatedTime(widgetType.getCreatedTime()); + if (widgetType.getTenantId() != null) { + this.tenantId = widgetType.getTenantId().getId(); + } + this.bundleAlias = widgetType.getBundleAlias(); + this.alias = widgetType.getAlias(); + this.name = widgetType.getName(); + } + + public AbstractWidgetTypeEntity(AbstractWidgetTypeEntity widgetTypeEntity) { + this.setId(widgetTypeEntity.getId()); + this.setCreatedTime(widgetTypeEntity.getCreatedTime()); + this.tenantId = widgetTypeEntity.getTenantId(); + this.bundleAlias = widgetTypeEntity.getBundleAlias(); + this.alias = widgetTypeEntity.getAlias(); + this.name = widgetTypeEntity.getName(); + } + + protected BaseWidgetType toBaseWidgetType() { + BaseWidgetType widgetType = new BaseWidgetType(new WidgetTypeId(getUuid())); + widgetType.setCreatedTime(createdTime); + if (tenantId != null) { + widgetType.setTenantId(new TenantId(tenantId)); + } + widgetType.setBundleAlias(bundleAlias); + widgetType.setAlias(alias); + widgetType.setName(name); + return widgetType; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java new file mode 100644 index 0000000000..220ed2852e --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java @@ -0,0 +1,69 @@ +/** + * Copyright © 2016-2021 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 lombok.Data; +import lombok.EqualsAndHashCode; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.thingsboard.server.common.data.widget.BaseWidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; +import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.util.mapping.JsonStringType; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@TypeDef(name = "json", typeClass = JsonStringType.class) +@Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME) +public class WidgetTypeDetailsEntity extends AbstractWidgetTypeEntity { + + @Column(name = ModelConstants.WIDGET_TYPE_IMAGE_PROPERTY) + private String image; + + @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTION_PROPERTY) + private String description; + + @Type(type="json") + @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY) + private JsonNode descriptor; + + public WidgetTypeDetailsEntity() { + super(); + } + + public WidgetTypeDetailsEntity(WidgetTypeDetails widgetTypeDetails) { + super(widgetTypeDetails); + this.image = widgetTypeDetails.getImage(); + this.description = widgetTypeDetails.getDescription(); + this.descriptor = widgetTypeDetails.getDescriptor(); + } + + @Override + public WidgetTypeDetails toData() { + BaseWidgetType baseWidgetType = super.toBaseWidgetType(); + WidgetTypeDetails widgetTypeDetails = new WidgetTypeDetails(baseWidgetType); + widgetTypeDetails.setImage(image); + widgetTypeDetails.setDescription(description); + widgetTypeDetails.setDescriptor(descriptor); + return widgetTypeDetails; + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java index 487f53b13d..558e404899 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java @@ -20,11 +20,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.WidgetTypeId; +import org.thingsboard.server.common.data.widget.BaseWidgetType; import org.thingsboard.server.common.data.widget.WidgetType; -import org.thingsboard.server.dao.model.BaseEntity; -import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonStringType; @@ -38,25 +35,7 @@ import java.util.UUID; @Entity @TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME) -public final class WidgetTypeEntity extends BaseSqlEntity implements BaseEntity { - - @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY) - private UUID tenantId; - - @Column(name = ModelConstants.WIDGET_TYPE_BUNDLE_ALIAS_PROPERTY) - private String bundleAlias; - - @Column(name = ModelConstants.WIDGET_TYPE_ALIAS_PROPERTY) - private String alias; - - @Column(name = ModelConstants.WIDGET_TYPE_NAME_PROPERTY) - private String name; - - @Column(name = ModelConstants.WIDGET_TYPE_IMAGE_PROPERTY) - private String image; - - @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTION_PROPERTY) - private String description; +public final class WidgetTypeEntity extends AbstractWidgetTypeEntity { @Type(type="json") @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY) @@ -66,34 +45,10 @@ public final class WidgetTypeEntity extends BaseSqlEntity implement super(); } - public WidgetTypeEntity(WidgetType widgetType) { - if (widgetType.getId() != null) { - this.setUuid(widgetType.getId().getId()); - } - this.setCreatedTime(widgetType.getCreatedTime()); - if (widgetType.getTenantId() != null) { - this.tenantId = widgetType.getTenantId().getId(); - } - this.bundleAlias = widgetType.getBundleAlias(); - this.alias = widgetType.getAlias(); - this.name = widgetType.getName(); - this.image = widgetType.getImage(); - this.description = widgetType.getDescription(); - this.descriptor = widgetType.getDescriptor(); - } - @Override public WidgetType toData() { - WidgetType widgetType = new WidgetType(new WidgetTypeId(this.getUuid())); - widgetType.setCreatedTime(createdTime); - if (tenantId != null) { - widgetType.setTenantId(new TenantId(tenantId)); - } - widgetType.setBundleAlias(bundleAlias); - widgetType.setAlias(alias); - widgetType.setName(name); - widgetType.setImage(image); - widgetType.setDescription(description); + BaseWidgetType baseWidgetType = super.toBaseWidgetType(); + WidgetType widgetType = new WidgetType(baseWidgetType); widgetType.setDescriptor(descriptor); return widgetType; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeInfoEntity.java new file mode 100644 index 0000000000..75600ac0a9 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeInfoEntity.java @@ -0,0 +1,56 @@ +/** + * Copyright © 2016-2021 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 lombok.Data; +import lombok.EqualsAndHashCode; +import org.thingsboard.server.common.data.widget.BaseWidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeInfo; + +@Data +@EqualsAndHashCode(callSuper = true) +public final class WidgetTypeInfoEntity extends AbstractWidgetTypeEntity { + + private String image; + private String description; + private String widgetType; + + public WidgetTypeInfoEntity() { + super(); + } + + public WidgetTypeInfoEntity(WidgetTypeDetailsEntity widgetTypeDetailsEntity) { + super(widgetTypeDetailsEntity); + this.image = widgetTypeDetailsEntity.getImage(); + this.description = widgetTypeDetailsEntity.getDescription(); + if (widgetTypeDetailsEntity.getDescriptor() != null && widgetTypeDetailsEntity.getDescriptor().has("type")) { + this.widgetType = widgetTypeDetailsEntity.getDescriptor().get("type").asText(); + } else { + this.widgetType = ""; + } + } + + @Override + public WidgetTypeInfo toData() { + BaseWidgetType baseWidgetType = super.toBaseWidgetType(); + WidgetTypeInfo widgetTypeInfo = new WidgetTypeInfo(baseWidgetType); + widgetTypeInfo.setImage(image); + widgetTypeInfo.setDescription(description); + widgetTypeInfo.setWidgetType(widgetType); + return widgetTypeInfo; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java index 2888da504c..a3544eb513 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java @@ -18,8 +18,12 @@ package org.thingsboard.server.dao.sql.widget; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; +import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.model.sql.WidgetTypeDetailsEntity; import org.thingsboard.server.dao.model.sql.WidgetTypeEntity; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.widget.WidgetTypeDao; @@ -31,28 +35,43 @@ import java.util.UUID; * Created by Valerii Sosliuk on 4/29/2017. */ @Component -public class JpaWidgetTypeDao extends JpaAbstractDao implements WidgetTypeDao { +public class JpaWidgetTypeDao extends JpaAbstractDao implements WidgetTypeDao { @Autowired private WidgetTypeRepository widgetTypeRepository; @Override - protected Class getEntityClass() { - return WidgetTypeEntity.class; + protected Class getEntityClass() { + return WidgetTypeDetailsEntity.class; } @Override - protected CrudRepository getCrudRepository() { + protected CrudRepository getCrudRepository() { return widgetTypeRepository; } + @Override + public WidgetType findWidgetTypeById(TenantId tenantId, UUID widgetTypeId) { + return DaoUtil.getData(widgetTypeRepository.findWidgetTypeById(widgetTypeId)); + } + @Override public List findWidgetTypesByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) { + return DaoUtil.convertDataList(widgetTypeRepository.findWidgetTypesByTenantIdAndBundleAlias(tenantId, bundleAlias)); + } + + @Override + public List findWidgetTypesDetailsByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) { return DaoUtil.convertDataList(widgetTypeRepository.findByTenantIdAndBundleAlias(tenantId, bundleAlias)); } + @Override + public List findWidgetTypesInfosByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) { + return DaoUtil.convertDataList(widgetTypeRepository.findWidgetTypesInfosByTenantIdAndBundleAlias(tenantId, bundleAlias)); + } + @Override public WidgetType findByTenantIdBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias) { - return DaoUtil.getData(widgetTypeRepository.findByTenantIdAndBundleAliasAndAlias(tenantId, bundleAlias, alias)); + return DaoUtil.getData(widgetTypeRepository.findWidgetTypeByTenantIdAndBundleAliasAndAlias(tenantId, bundleAlias, alias)); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java index 7269128ca1..ad21e2e40a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java @@ -15,18 +15,35 @@ */ package org.thingsboard.server.dao.sql.widget; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.thingsboard.server.dao.model.sql.WidgetTypeDetailsEntity; import org.thingsboard.server.dao.model.sql.WidgetTypeEntity; +import org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity; import java.util.List; import java.util.UUID; -/** - * Created by Valerii Sosliuk on 4/29/2017. - */ -public interface WidgetTypeRepository extends CrudRepository { +public interface WidgetTypeRepository extends CrudRepository { + + @Query("SELECT wt FROM WidgetTypeEntity wt WHERE wt.id = :widgetTypeId") + WidgetTypeEntity findWidgetTypeById(@Param("widgetTypeId") UUID widgetTypeId); + + @Query("SELECT wt FROM WidgetTypeEntity wt WHERE wt.tenantId = :tenantId AND wt.bundleAlias = :bundleAlias") + List findWidgetTypesByTenantIdAndBundleAlias(@Param("tenantId") UUID tenantId, + @Param("bundleAlias") String bundleAlias); + + @Query("SELECT new org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity(wtd) FROM WidgetTypeDetailsEntity wtd " + + "WHERE wtd.tenantId = :tenantId AND wtd.bundleAlias = :bundleAlias") + List findWidgetTypesInfosByTenantIdAndBundleAlias(@Param("tenantId") UUID tenantId, + @Param("bundleAlias") String bundleAlias); - List findByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias); + List findByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias); - WidgetTypeEntity findByTenantIdAndBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias); + @Query("SELECT wt FROM WidgetTypeEntity wt " + + "WHERE wt.tenantId = :tenantId AND wt.bundleAlias = :bundleAlias AND wt.alias = :alias") + WidgetTypeEntity findWidgetTypeByTenantIdAndBundleAliasAndAlias(@Param("tenantId") UUID tenantId, + @Param("bundleAlias") String bundleAlias, + @Param("alias") String alias); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java index 88600ea8e3..261c184800 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java @@ -17,6 +17,8 @@ package org.thingsboard.server.dao.widget; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; +import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.dao.Dao; import java.util.List; @@ -25,15 +27,24 @@ import java.util.UUID; /** * The Interface WidgetTypeDao. */ -public interface WidgetTypeDao extends Dao { +public interface WidgetTypeDao extends Dao { /** * Save or update widget type object * - * @param widgetType the widget type object + * @param widgetTypeDetails the widget type details object * @return saved widget type object */ - WidgetType save(TenantId tenantId, WidgetType widgetType); + WidgetTypeDetails save(TenantId tenantId, WidgetTypeDetails widgetTypeDetails); + + /** + * Find widget type by tenantId and widgetTypeId. + * + * @param tenantId the tenantId + * @param widgetTypeId the widget type id + * @return the widget type object + */ + WidgetType findWidgetTypeById(TenantId tenantId, UUID widgetTypeId); /** * Find widget types by tenantId and bundleAlias. @@ -44,6 +55,24 @@ public interface WidgetTypeDao extends Dao { */ List findWidgetTypesByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias); + /** + * Find widget types details by tenantId and bundleAlias. + * + * @param tenantId the tenantId + * @param bundleAlias the bundle alias + * @return the list of widget types details objects + */ + List findWidgetTypesDetailsByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias); + + /** + * Find widget types infos by tenantId and bundleAlias. + * + * @param tenantId the tenantId + * @param bundleAlias the bundle alias + * @return the list of widget types infos objects + */ + List findWidgetTypesInfosByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias); + /** * Find widget type by tenantId, bundleAlias and alias. * diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java index 85bb876d50..d8a8ea3e35 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java @@ -23,6 +23,8 @@ import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; +import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.model.ModelConstants; @@ -51,14 +53,21 @@ public class WidgetTypeServiceImpl implements WidgetTypeService { public WidgetType findWidgetTypeById(TenantId tenantId, WidgetTypeId widgetTypeId) { log.trace("Executing findWidgetTypeById [{}]", widgetTypeId); Validator.validateId(widgetTypeId, "Incorrect widgetTypeId " + widgetTypeId); + return widgetTypeDao.findWidgetTypeById(tenantId, widgetTypeId.getId()); + } + + @Override + public WidgetTypeDetails findWidgetTypeDetailsById(TenantId tenantId, WidgetTypeId widgetTypeId) { + log.trace("Executing findWidgetTypeDetailsById [{}]", widgetTypeId); + Validator.validateId(widgetTypeId, "Incorrect widgetTypeId " + widgetTypeId); return widgetTypeDao.findById(tenantId, widgetTypeId.getId()); } @Override - public WidgetType saveWidgetType(WidgetType widgetType) { - log.trace("Executing saveWidgetType [{}]", widgetType); - widgetTypeValidator.validate(widgetType, WidgetType::getTenantId); - return widgetTypeDao.save(widgetType.getTenantId(), widgetType); + public WidgetTypeDetails saveWidgetType(WidgetTypeDetails widgetTypeDetails) { + log.trace("Executing saveWidgetType [{}]", widgetTypeDetails); + widgetTypeValidator.validate(widgetTypeDetails, WidgetType::getTenantId); + return widgetTypeDao.save(widgetTypeDetails.getTenantId(), widgetTypeDetails); } @Override @@ -76,6 +85,22 @@ public class WidgetTypeServiceImpl implements WidgetTypeService { return widgetTypeDao.findWidgetTypesByTenantIdAndBundleAlias(tenantId.getId(), bundleAlias); } + @Override + public List findWidgetTypesDetailsByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias) { + log.trace("Executing findWidgetTypesDetailsByTenantIdAndBundleAlias, tenantId [{}], bundleAlias [{}]", tenantId, bundleAlias); + Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + Validator.validateString(bundleAlias, INCORRECT_BUNDLE_ALIAS + bundleAlias); + return widgetTypeDao.findWidgetTypesDetailsByTenantIdAndBundleAlias(tenantId.getId(), bundleAlias); + } + + @Override + public List findWidgetTypesInfosByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias) { + log.trace("Executing findWidgetTypesInfosByTenantIdAndBundleAlias, tenantId [{}], bundleAlias [{}]", tenantId, bundleAlias); + Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + Validator.validateString(bundleAlias, INCORRECT_BUNDLE_ALIAS + bundleAlias); + return widgetTypeDao.findWidgetTypesInfosByTenantIdAndBundleAlias(tenantId.getId(), bundleAlias); + } + @Override public WidgetType findWidgetTypeByTenantIdBundleAliasAndAlias(TenantId tenantId, String bundleAlias, String alias) { log.trace("Executing findWidgetTypeByTenantIdBundleAliasAndAlias, tenantId [{}], bundleAlias [{}], alias [{}]", tenantId, bundleAlias, alias); @@ -96,24 +121,24 @@ public class WidgetTypeServiceImpl implements WidgetTypeService { } } - private DataValidator widgetTypeValidator = - new DataValidator() { + private DataValidator widgetTypeValidator = + new DataValidator<>() { @Override - protected void validateDataImpl(TenantId tenantId, WidgetType widgetType) { - if (StringUtils.isEmpty(widgetType.getName())) { + protected void validateDataImpl(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) { + if (StringUtils.isEmpty(widgetTypeDetails.getName())) { throw new DataValidationException("Widgets type name should be specified!"); } - if (StringUtils.isEmpty(widgetType.getBundleAlias())) { + if (StringUtils.isEmpty(widgetTypeDetails.getBundleAlias())) { throw new DataValidationException("Widgets type bundle alias should be specified!"); } - if (widgetType.getDescriptor() == null || widgetType.getDescriptor().size() == 0) { + if (widgetTypeDetails.getDescriptor() == null || widgetTypeDetails.getDescriptor().size() == 0) { throw new DataValidationException("Widgets type descriptor can't be empty!"); } - if (widgetType.getTenantId() == null) { - widgetType.setTenantId(new TenantId(ModelConstants.NULL_UUID)); + if (widgetTypeDetails.getTenantId() == null) { + widgetTypeDetails.setTenantId(new TenantId(ModelConstants.NULL_UUID)); } - if (!widgetType.getTenantId().getId().equals(ModelConstants.NULL_UUID)) { - Tenant tenant = tenantDao.findById(tenantId, widgetType.getTenantId().getId()); + if (!widgetTypeDetails.getTenantId().getId().equals(ModelConstants.NULL_UUID)) { + Tenant tenant = tenantDao.findById(tenantId, widgetTypeDetails.getTenantId().getId()); if (tenant == null) { throw new DataValidationException("Widget type is referencing to non-existent tenant!"); } @@ -121,37 +146,37 @@ public class WidgetTypeServiceImpl implements WidgetTypeService { } @Override - protected void validateCreate(TenantId tenantId, WidgetType widgetType) { - WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(widgetType.getTenantId().getId(), widgetType.getBundleAlias()); + protected void validateCreate(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) { + WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(widgetTypeDetails.getTenantId().getId(), widgetTypeDetails.getBundleAlias()); if (widgetsBundle == null) { throw new DataValidationException("Widget type is referencing to non-existent widgets bundle!"); } - String alias = widgetType.getAlias(); + String alias = widgetTypeDetails.getAlias(); if (alias == null || alias.trim().isEmpty()) { - alias = widgetType.getName().toLowerCase().replaceAll("\\W+", "_"); + alias = widgetTypeDetails.getName().toLowerCase().replaceAll("\\W+", "_"); } String originalAlias = alias; int c = 1; WidgetType withSameAlias; do { - withSameAlias = widgetTypeDao.findByTenantIdBundleAliasAndAlias(widgetType.getTenantId().getId(), widgetType.getBundleAlias(), alias); + withSameAlias = widgetTypeDao.findByTenantIdBundleAliasAndAlias(widgetTypeDetails.getTenantId().getId(), widgetTypeDetails.getBundleAlias(), alias); if (withSameAlias != null) { alias = originalAlias + (++c); } } while (withSameAlias != null); - widgetType.setAlias(alias); + widgetTypeDetails.setAlias(alias); } @Override - protected void validateUpdate(TenantId tenantId, WidgetType widgetType) { - WidgetType storedWidgetType = widgetTypeDao.findById(tenantId, widgetType.getId().getId()); - if (!storedWidgetType.getTenantId().getId().equals(widgetType.getTenantId().getId())) { + protected void validateUpdate(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) { + WidgetType storedWidgetType = widgetTypeDao.findById(tenantId, widgetTypeDetails.getId().getId()); + if (!storedWidgetType.getTenantId().getId().equals(widgetTypeDetails.getTenantId().getId())) { throw new DataValidationException("Can't move existing widget type to different tenant!"); } - if (!storedWidgetType.getBundleAlias().equals(widgetType.getBundleAlias())) { + if (!storedWidgetType.getBundleAlias().equals(widgetTypeDetails.getBundleAlias())) { throw new DataValidationException("Update of widget type bundle alias is prohibited!"); } - if (!storedWidgetType.getAlias().equals(widgetType.getAlias())) { + if (!storedWidgetType.getAlias().equals(widgetTypeDetails.getAlias())) { throw new DataValidationException("Update of widget type alias is prohibited!"); } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseWidgetTypeServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseWidgetTypeServiceTest.java index 3d3d52003f..ba500f950d 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseWidgetTypeServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseWidgetTypeServiceTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.widget.WidgetType; +import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.model.ModelConstants; @@ -62,12 +63,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); + WidgetTypeDetails savedWidgetType = widgetTypeService.saveWidgetType(widgetType); Assert.assertNotNull(savedWidgetType); Assert.assertNotNull(savedWidgetType.getId()); @@ -94,7 +95,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); @@ -107,7 +108,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { @Test(expected = DataValidationException.class) public void testSaveWidgetTypeWithEmptyBundleAlias() throws IOException { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); @@ -121,7 +122,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setName("Widget Type"); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); @@ -140,7 +141,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(new TenantId(Uuids.timeBased())); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); @@ -154,7 +155,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { @Test(expected = DataValidationException.class) public void testSaveWidgetTypeWithInvalidBundleAlias() throws IOException { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias("some_alias"); widgetType.setName("Widget Type"); @@ -169,12 +170,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); + WidgetTypeDetails savedWidgetType = widgetTypeService.saveWidgetType(widgetType); savedWidgetType.setTenantId(new TenantId(ModelConstants.NULL_UUID)); try { widgetTypeService.saveWidgetType(savedWidgetType); @@ -190,12 +191,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); + WidgetTypeDetails savedWidgetType = widgetTypeService.saveWidgetType(widgetType); savedWidgetType.setBundleAlias("some_alias"); try { widgetTypeService.saveWidgetType(savedWidgetType); @@ -211,12 +212,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); + WidgetTypeDetails savedWidgetType = widgetTypeService.saveWidgetType(widgetType); savedWidgetType.setAlias("some_alias"); try { widgetTypeService.saveWidgetType(savedWidgetType); @@ -232,13 +233,13 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); - WidgetType foundWidgetType = widgetTypeService.findWidgetTypeById(tenantId, savedWidgetType.getId()); + WidgetTypeDetails savedWidgetType = widgetTypeService.saveWidgetType(widgetType); + WidgetTypeDetails foundWidgetType = widgetTypeService.findWidgetTypeDetailsById(tenantId, savedWidgetType.getId()); Assert.assertNotNull(foundWidgetType); Assert.assertEquals(savedWidgetType, foundWidgetType); @@ -252,12 +253,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); + WidgetType savedWidgetType = new WidgetType(widgetTypeService.saveWidgetType(widgetType)); WidgetType foundWidgetType = widgetTypeService.findWidgetTypeByTenantIdBundleAliasAndAlias(tenantId, savedWidgetsBundle.getAlias(), savedWidgetType.getAlias()); Assert.assertNotNull(foundWidgetType); Assert.assertEquals(savedWidgetType, foundWidgetType); @@ -272,7 +273,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { widgetsBundle.setTitle("Widgets bundle"); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type"); @@ -296,12 +297,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest { List widgetTypes = new ArrayList<>(); for (int i=0;i<121;i++) { - WidgetType widgetType = new WidgetType(); + WidgetTypeDetails widgetType = new WidgetTypeDetails(); widgetType.setTenantId(tenantId); widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setName("Widget Type " + i); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); - widgetTypes.add(widgetTypeService.saveWidgetType(widgetType)); + widgetTypes.add(new WidgetType(widgetTypeService.saveWidgetType(widgetType))); } List loadedWidgetTypes = widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(tenantId, savedWidgetsBundle.getAlias()); diff --git a/ui-ngx/src/app/core/http/widget.service.ts b/ui-ngx/src/app/core/http/widget.service.ts index d153521a24..be44d19f9b 100644 --- a/ui-ngx/src/app/core/http/widget.service.ts +++ b/ui-ngx/src/app/core/http/widget.service.ts @@ -21,11 +21,23 @@ import { HttpClient } from '@angular/common/http'; import { PageLink } from '@shared/models/page/page-link'; import { PageData } from '@shared/models/page/page-data'; import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; -import { Widget, WidgetType, widgetType, widgetTypesData } from '@shared/models/widget.models'; +import { + Widget, + WidgetType, + widgetType, + WidgetTypeDetails, + WidgetTypeInfo, + widgetTypesData +} from '@shared/models/widget.models'; import { UtilsService } from '@core/services/utils.service'; import { TranslateService } from '@ngx-translate/core'; import { ResourcesService } from '../services/resources.service'; -import { toWidgetInfo, toWidgetType, WidgetInfo } from '@app/modules/home/models/widget-component.models'; +import { + toWidgetInfo, + toWidgetType, + toWidgetTypeDetails, + WidgetInfo +} from '@app/modules/home/models/widget-component.models'; import { filter, map, mergeMap, tap } from 'rxjs/operators'; import { WidgetTypeId } from '@shared/models/id/widget-type-id'; import { NULL_UUID } from '@shared/models/id/has-uuid'; @@ -117,6 +129,18 @@ export class WidgetService { defaultHttpOptionsFromConfig(config)); } + public getBundleWidgetTypesDetails(bundleAlias: string, isSystem: boolean, + config?: RequestConfig): Observable> { + return this.http.get>(`/api/widgetTypesDetails?isSystem=${isSystem}&bundleAlias=${bundleAlias}`, + defaultHttpOptionsFromConfig(config)); + } + + public getBundleWidgetTypeInfos(bundleAlias: string, isSystem: boolean, + config?: RequestConfig): Observable> { + return this.http.get>(`/api/widgetTypesInfos?isSystem=${isSystem}&bundleAlias=${bundleAlias}`, + defaultHttpOptionsFromConfig(config)); + } + public loadBundleLibraryWidgets(bundleAlias: string, isSystem: boolean, config?: RequestConfig): Observable> { return this.getBundleWidgetTypes(bundleAlias, isSystem, config).pipe( @@ -144,8 +168,6 @@ export class WidgetService { typeAlias: widgetTypeInfo.alias, type: widgetTypeInfo.type, title: widgetTypeInfo.widgetName, - image: widgetTypeInfo.image, - description: widgetTypeInfo.description, sizeX, sizeY, row: top, @@ -178,22 +200,22 @@ export class WidgetService { defaultHttpOptionsFromConfig(config)); } - public saveWidgetType(widgetInfo: WidgetInfo, - id: WidgetTypeId, - bundleAlias: string, - createdTime: number, - config?: RequestConfig): Observable { - const widgetTypeInstance = toWidgetType(widgetInfo, id, undefined, bundleAlias, createdTime); - return this.http.post('/api/widgetType', widgetTypeInstance, + public saveWidgetTypeDetails(widgetInfo: WidgetInfo, + id: WidgetTypeId, + bundleAlias: string, + createdTime: number, + config?: RequestConfig): Observable { + const widgetTypeDetails = toWidgetTypeDetails(widgetInfo, id, undefined, bundleAlias, createdTime); + return this.http.post('/api/widgetType', widgetTypeDetails, defaultHttpOptionsFromConfig(config)).pipe( tap((savedWidgetType) => { this.widgetTypeUpdatedSubject.next(savedWidgetType); })); } - public saveImportedWidgetType(widgetTypeInstance: WidgetType, - config?: RequestConfig): Observable { - return this.http.post('/api/widgetType', widgetTypeInstance, + public saveImportedWidgetTypeDetails(widgetTypeDetails: WidgetTypeDetails, + config?: RequestConfig): Observable { + return this.http.post('/api/widgetType', widgetTypeDetails, defaultHttpOptionsFromConfig(config)).pipe( tap((savedWidgetType) => { this.widgetTypeUpdatedSubject.next(savedWidgetType); @@ -215,8 +237,8 @@ export class WidgetService { } public getWidgetTypeById(widgetTypeId: string, - config?: RequestConfig): Observable { - return this.http.get(`/api/widgetType/${widgetTypeId}`, + config?: RequestConfig): Observable { + return this.http.get(`/api/widgetType/${widgetTypeId}`, defaultHttpOptionsFromConfig(config)); } diff --git a/ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts b/ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts index 93ee9a2969..7e83c67ec6 100644 --- a/ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts @@ -470,8 +470,6 @@ export class AttributeTableComponent extends PageComponent implements AfterViewI typeAlias: widgetInfo.alias, type: widgetInfo.type, title: widgetInfo.widgetName, - image: widgetInfo.image, - description: widgetInfo.description, sizeX, sizeY, row: 0, diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts index faf4c8c5f0..5e8cc7f36f 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts @@ -97,17 +97,16 @@ export class DashboardWidgetSelectComponent implements OnInit { if (this.widgetsBundle !== null) { const bundleAlias = this.widgetsBundle.alias; const isSystem = this.widgetsBundle.tenantId.id === NULL_UUID; - this.widgetsInfo = this.widgetsService.getBundleWidgetTypes(bundleAlias, isSystem).pipe( + this.widgetsInfo = this.widgetsService.getBundleWidgetTypeInfos(bundleAlias, isSystem).pipe( map(widgets => widgets.sort((a, b) => b.createdTime - a.createdTime)), - map(widgets => widgets.map((type) => { - const widgetTypeInfo = toWidgetInfo(type); - this.widgetsType.add(widgetTypeInfo.type); + map(widgets => widgets.map((widgetTypeInfo) => { + this.widgetsType.add(widgetTypeInfo.widgetType); const widget: WidgetInfo = { isSystemType: isSystem, bundleAlias, typeAlias: widgetTypeInfo.alias, - type: widgetTypeInfo.type, - title: widgetTypeInfo.widgetName, + type: widgetTypeInfo.widgetType, + title: widgetTypeInfo.name, image: widgetTypeInfo.image, description: widgetTypeInfo.description }; diff --git a/ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts b/ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts index 555027a1c2..14683e83d9 100644 --- a/ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts +++ b/ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Widget, WidgetType } from '@app/shared/models/widget.models'; +import { Widget, WidgetType, WidgetTypeDetails } from '@app/shared/models/widget.models'; import { DashboardLayoutId } from '@shared/models/dashboard.models'; import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; @@ -25,7 +25,7 @@ export interface ImportWidgetResult { export interface WidgetsBundleItem { widgetsBundle: WidgetsBundle; - widgetTypes: WidgetType[]; + widgetTypes: WidgetTypeDetails[]; } export interface CsvToJsonConfig { diff --git a/ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts b/ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts index 8a275a8160..48324dcbfe 100644 --- a/ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts +++ b/ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts @@ -38,7 +38,7 @@ import { forkJoin, Observable, of } from 'rxjs'; import { catchError, map, mergeMap, tap } from 'rxjs/operators'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; import { EntityService } from '@core/http/entity.service'; -import { Widget, WidgetSize, WidgetType } from '@shared/models/widget.models'; +import { Widget, WidgetSize, WidgetType, WidgetTypeDetails } from '@shared/models/widget.models'; import { EntityAliasesDialogComponent, EntityAliasesDialogData @@ -234,13 +234,13 @@ export class ImportExportService { public exportWidgetType(widgetTypeId: string) { this.widgetService.getWidgetTypeById(widgetTypeId).subscribe( - (widgetType) => { - if (isDefined(widgetType.bundleAlias)) { - delete widgetType.bundleAlias; + (widgetTypeDetails) => { + if (isDefined(widgetTypeDetails.bundleAlias)) { + delete widgetTypeDetails.bundleAlias; } - let name = widgetType.name; + let name = widgetTypeDetails.name; name = name.toLowerCase().replace(/\W/g, '_'); - this.exportToPc(this.prepareExport(widgetType), name); + this.exportToPc(this.prepareExport(widgetTypeDetails), name); }, (e) => { this.handleExportError(e, 'widget-type.export-failed-error'); @@ -250,15 +250,15 @@ export class ImportExportService { public importWidgetType(bundleAlias: string): Observable { return this.openImportDialog('widget-type.import', 'widget-type.widget-type-file').pipe( - mergeMap((widgetType: WidgetType) => { - if (!this.validateImportedWidgetType(widgetType)) { + mergeMap((widgetTypeDetails: WidgetTypeDetails) => { + if (!this.validateImportedWidgetTypeDetails(widgetTypeDetails)) { this.store.dispatch(new ActionNotificationShow( {message: this.translate.instant('widget-type.invalid-widget-type-file-error'), type: 'error'})); throw new Error('Invalid widget type file'); } else { - widgetType.bundleAlias = bundleAlias; - return this.widgetService.saveImportedWidgetType(widgetType); + widgetTypeDetails.bundleAlias = bundleAlias; + return this.widgetService.saveImportedWidgetTypeDetails(widgetTypeDetails); } }), catchError((err) => { @@ -272,18 +272,18 @@ export class ImportExportService { (widgetsBundle) => { const bundleAlias = widgetsBundle.alias; const isSystem = widgetsBundle.tenantId.id === NULL_UUID; - this.widgetService.getBundleWidgetTypes(bundleAlias, isSystem).subscribe( - (widgetTypes) => { - widgetTypes = widgetTypes.sort((a, b) => a.createdTime - b.createdTime); + this.widgetService.getBundleWidgetTypesDetails(bundleAlias, isSystem).subscribe( + (widgetTypesDetails) => { + widgetTypesDetails = widgetTypesDetails.sort((a, b) => a.createdTime - b.createdTime); const widgetsBundleItem: WidgetsBundleItem = { widgetsBundle: this.prepareExport(widgetsBundle), widgetTypes: [] }; - for (const widgetType of widgetTypes) { - if (isDefined(widgetType.bundleAlias)) { - delete widgetType.bundleAlias; + for (const widgetTypeDetails of widgetTypesDetails) { + if (isDefined(widgetTypeDetails.bundleAlias)) { + delete widgetTypeDetails.bundleAlias; } - widgetsBundleItem.widgetTypes.push(this.prepareExport(widgetType)); + widgetsBundleItem.widgetTypes.push(this.prepareExport(widgetTypeDetails)); } let name = widgetsBundle.title; name = name.toLowerCase().replace(/\W/g, '_'); @@ -313,12 +313,12 @@ export class ImportExportService { return this.widgetService.saveWidgetsBundle(widgetsBundle).pipe( mergeMap((savedWidgetsBundle) => { const bundleAlias = savedWidgetsBundle.alias; - const widgetTypes = widgetsBundleItem.widgetTypes; - if (widgetTypes.length) { + const widgetTypesDetails = widgetsBundleItem.widgetTypes; + if (widgetTypesDetails.length) { const saveWidgetTypesObservables: Array> = []; - for (const widgetType of widgetTypes) { - widgetType.bundleAlias = bundleAlias; - saveWidgetTypesObservables.push(this.widgetService.saveImportedWidgetType(widgetType)); + for (const widgetTypeDetails of widgetTypesDetails) { + widgetTypeDetails.bundleAlias = bundleAlias; + saveWidgetTypesObservables.push(this.widgetService.saveImportedWidgetTypeDetails(widgetTypeDetails)); } return forkJoin(saveWidgetTypesObservables).pipe( map(() => savedWidgetsBundle) @@ -508,9 +508,9 @@ export class ImportExportService { return true; } - private validateImportedWidgetType(widgetType: WidgetType): boolean { - if (isUndefined(widgetType.name) - || isUndefined(widgetType.descriptor)) { + private validateImportedWidgetTypeDetails(widgetTypeDetails: WidgetTypeDetails): boolean { + if (isUndefined(widgetTypeDetails.name) + || isUndefined(widgetTypeDetails.descriptor)) { return false; } return true; @@ -527,9 +527,9 @@ export class ImportExportService { if (isUndefined(widgetsBundle.title)) { return false; } - const widgetTypes = widgetsBundleItem.widgetTypes; - for (const widgetType of widgetTypes) { - if (!this.validateImportedWidgetType(widgetType)) { + const widgetTypesDetails = widgetsBundleItem.widgetTypes; + for (const widgetTypeDetails of widgetTypesDetails) { + if (!this.validateImportedWidgetTypeDetails(widgetTypeDetails)) { return false; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index 00b252fea0..d714b96f4b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -104,8 +104,6 @@ export class WidgetComponentService { controllerScript: this.utils.editWidgetInfo.controllerScript, settingsSchema: this.utils.editWidgetInfo.settingsSchema, dataKeySettingsSchema: this.utils.editWidgetInfo.dataKeySettingsSchema, - image: this.utils.editWidgetInfo.image, - description: this.utils.editWidgetInfo.description, defaultConfig: this.utils.editWidgetInfo.defaultConfig }, new WidgetTypeId('1'), new TenantId( NULL_UUID ), 'customWidgetBundle', undefined ); diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts index 4ecce2db91..74b6496c67 100644 --- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts @@ -27,7 +27,7 @@ import { WidgetControllerDescriptor, WidgetType, widgetType, - WidgetTypeDescriptor, + WidgetTypeDescriptor, WidgetTypeDetails, WidgetTypeParameters } from '@shared/models/widget.models'; import { Timewindow, WidgetTimewindow } from '@shared/models/time/time.models'; @@ -347,8 +347,8 @@ export interface WidgetInfo extends WidgetTypeDescriptor, WidgetControllerDescri alias: string; typeSettingsSchema?: string | any; typeDataKeySettingsSchema?: string | any; - image: string; - description: string; + image?: string; + description?: string; componentFactory?: ComponentFactory; } @@ -427,11 +427,16 @@ export interface WidgetTypeInstance { onDestroy?: () => void; } +export function detailsToWidgetInfo(widgetTypeDetailsEntity: WidgetTypeDetails): WidgetInfo { + const widgetInfo = toWidgetInfo(widgetTypeDetailsEntity); + widgetInfo.image = widgetTypeDetailsEntity.image; + widgetInfo.description = widgetTypeDetailsEntity.description; + return widgetInfo; +} + export function toWidgetInfo(widgetTypeEntity: WidgetType): WidgetInfo { return { widgetName: widgetTypeEntity.name, - image: widgetTypeEntity.image, - description: widgetTypeEntity.description, alias: widgetTypeEntity.alias, type: widgetTypeEntity.descriptor.type, sizeX: widgetTypeEntity.descriptor.sizeX, @@ -446,6 +451,16 @@ export function toWidgetInfo(widgetTypeEntity: WidgetType): WidgetInfo { }; } +export function toWidgetTypeDetails(widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId: TenantId, + bundleAlias: string, createdTime: number): WidgetTypeDetails { + const widgetTypeEntity = toWidgetType(widgetInfo, id, tenantId, bundleAlias, createdTime); + const widgetTypeDetails: WidgetTypeDetails = {...widgetTypeEntity, + description: widgetInfo.description, + image: widgetInfo.image + }; + return widgetTypeDetails; +} + export function toWidgetType(widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId: TenantId, bundleAlias: string, createdTime: number): WidgetType { const descriptor: WidgetTypeDescriptor = { @@ -467,8 +482,6 @@ export function toWidgetType(widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId: bundleAlias, alias: widgetInfo.alias, name: widgetInfo.widgetName, - image: widgetInfo.image, - description: widgetInfo.description, descriptor }; } diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts index 2f7d274037..0444a2d5e9 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts @@ -20,8 +20,15 @@ import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { WidgetService } from '@core/http/widget.service'; -import { toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; -import { Widget, WidgetConfig, WidgetType, widgetType, widgetTypesData } from '@shared/models/widget.models'; +import { detailsToWidgetInfo, toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; +import { + Widget, + WidgetConfig, + WidgetType, + widgetType, + WidgetTypeDetails, + widgetTypesData +} from '@shared/models/widget.models'; import { ActivatedRoute, Router } from '@angular/router'; import { deepClone } from '@core/utils'; import { HasDirtyFlag } from '@core/guards/confirm-on-exit.guard'; @@ -108,7 +115,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe isReadOnly: boolean; widgetsBundle: WidgetsBundle; - widgetType: WidgetType; + widgetTypeDetails: WidgetTypeDetails; widget: WidgetInfo; origWidget: WidgetInfo; @@ -175,14 +182,14 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe } else { this.isReadOnly = this.authUser.authority !== Authority.SYS_ADMIN; } - this.widgetType = data.widgetEditorData.widgetType; + this.widgetTypeDetails = data.widgetEditorData.widgetTypeDetails; this.widget = data.widgetEditorData.widget; - if (this.widgetType) { + if (this.widgetTypeDetails) { const config = JSON.parse(this.widget.defaultConfig); this.widget.defaultConfig = JSON.stringify(config); } this.origWidget = deepClone(this.widget); - if (!this.widgetType) { + if (!this.widgetTypeDetails) { this.isDirty = true; } } @@ -515,11 +522,11 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe } private commitSaveWidget() { - const id = (this.widgetType && this.widgetType.id) ? this.widgetType.id : undefined; - const createdTime = (this.widgetType && this.widgetType.createdTime) ? this.widgetType.createdTime : undefined; - this.widgetService.saveWidgetType(this.widget, id, this.widgetsBundle.alias, createdTime).subscribe( - (widgetTypeInstance) => { - this.setWidgetType(widgetTypeInstance); + const id = (this.widgetTypeDetails && this.widgetTypeDetails.id) ? this.widgetTypeDetails.id : undefined; + const createdTime = (this.widgetTypeDetails && this.widgetTypeDetails.createdTime) ? this.widgetTypeDetails.createdTime : undefined; + this.widgetService.saveWidgetTypeDetails(this.widget, id, this.widgetsBundle.alias, createdTime).subscribe( + (widgetTypeDetails) => { + this.setWidgetTypeDetails(widgetTypeDetails); this.saveWidgetPending = false; this.store.dispatch(new ActionNotificationShow( {message: this.translate.instant('widget.widget-saved'), type: 'success', duration: 500})); @@ -544,9 +551,9 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe config.title = this.widget.widgetName; this.widget.defaultConfig = JSON.stringify(config); this.isDirty = false; - this.widgetService.saveWidgetType(this.widget, undefined, saveWidgetAsData.bundleAlias, undefined).subscribe( - (widgetTypeInstance) => { - this.router.navigateByUrl(`/widgets-bundles/${saveWidgetAsData.bundleId}/widgetTypes/${widgetTypeInstance.id.id}`); + this.widgetService.saveWidgetTypeDetails(this.widget, undefined, saveWidgetAsData.bundleAlias, undefined).subscribe( + (widgetTypeDetails) => { + this.router.navigateByUrl(`/widgets-bundles/${saveWidgetAsData.bundleId}/widgetTypes/${widgetTypeDetails.id.id}`); } ); } @@ -555,9 +562,9 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe ); } - private setWidgetType(widgetTypeInstance: WidgetType) { - this.widgetType = widgetTypeInstance; - this.widget = toWidgetInfo(this.widgetType); + private setWidgetTypeDetails(widgetTypeDetails: WidgetTypeDetails) { + this.widgetTypeDetails = widgetTypeDetails; + this.widget = detailsToWidgetInfo(this.widgetTypeDetails); const config = JSON.parse(this.widget.defaultConfig); this.widget.defaultConfig = JSON.stringify(config); this.origWidget = deepClone(this.widget); diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts index a8b6d47a0e..92a499524a 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts @@ -27,14 +27,14 @@ import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { WidgetService } from '@core/http/widget.service'; import { WidgetEditorComponent } from '@home/pages/widget/widget-editor.component'; import { map } from 'rxjs/operators'; -import { toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; -import { widgetType, WidgetType } from '@app/shared/models/widget.models'; +import { detailsToWidgetInfo, toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; +import { widgetType, WidgetType, WidgetTypeDetails } from '@app/shared/models/widget.models'; import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { WidgetsData } from '@home/models/dashboard-component.models'; import { NULL_UUID } from '@shared/models/id/has-uuid'; export interface WidgetEditorData { - widgetType: WidgetType; + widgetTypeDetails: WidgetTypeDetails; widget: WidgetInfo; } @@ -83,8 +83,8 @@ export class WidgetEditorDataResolver implements Resolve { return this.widgetsService.getWidgetTypeById(widgetTypeId).pipe( map((result) => { return { - widgetType: result, - widget: toWidgetInfo(result) + widgetTypeDetails: result, + widget: detailsToWidgetInfo(result) }; }) ); @@ -106,7 +106,7 @@ export class WidgetEditorAddDataResolver implements Resolve { map((widget) => { widget.widgetName = null; return { - widgetType: null, + widgetTypeDetails: null, widget }; }) diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 4ee0b3902c..2d599bdc78 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -165,14 +165,26 @@ export interface WidgetControllerDescriptor { actionSources?: {[actionSourceId: string]: WidgetActionSource}; } -export interface WidgetType extends BaseData { +export interface BaseWidgetType extends BaseData { tenantId: TenantId; bundleAlias: string; alias: string; name: string; +} + +export interface WidgetType extends BaseWidgetType { + descriptor: WidgetTypeDescriptor; +} + +export interface WidgetTypeInfo extends BaseWidgetType { + image: string; + description: string; + widgetType: widgetType; +} + +export interface WidgetTypeDetails extends WidgetType { image: string; description: string; - descriptor: WidgetTypeDescriptor; } export enum LegendDirection { @@ -417,8 +429,8 @@ export interface WidgetInfo { typeAlias: string; type: widgetType; title: string; - image: string; - description: string; + image?: string; + description?: string; } export interface GroupInfo {