Browse Source

New widget selector backend support

pull/4218/head
Igor Kulikov 5 years ago
parent
commit
71062f64df
  1. 11
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  2. 52
      application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java
  3. 7
      application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java
  4. 51
      application/src/test/java/org/thingsboard/server/controller/BaseWidgetTypeControllerTest.java
  5. 10
      common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java
  6. 49
      common/data/src/main/java/org/thingsboard/server/common/data/widget/BaseWidgetType.java
  7. 88
      common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java
  8. 45
      common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java
  9. 46
      common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java
  10. 86
      dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractWidgetTypeEntity.java
  11. 69
      dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java
  12. 53
      dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
  13. 56
      dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeInfoEntity.java
  14. 29
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java
  15. 29
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java
  16. 35
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java
  17. 75
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java
  18. 43
      dao/src/test/java/org/thingsboard/server/dao/service/BaseWidgetTypeServiceTest.java
  19. 54
      ui-ngx/src/app/core/http/widget.service.ts
  20. 2
      ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.ts
  21. 11
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts
  22. 4
      ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts
  23. 56
      ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts
  24. 2
      ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
  25. 27
      ui-ngx/src/app/modules/home/models/widget-component.models.ts
  26. 41
      ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts
  27. 12
      ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts
  28. 20
      ui-ngx/src/app/shared/models/widget.models.ts

11
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);
}

52
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<WidgetTypeDetails> 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<WidgetTypeInfo> 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

7
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);

51
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<WidgetType> 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<WidgetType> loadedWidgetTypes = doGetTyped("/api/widgetTypes?isSystem={isSystem}&bundleAlias={bundleAlias}",
new TypeReference<List<WidgetType>>(){}, 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);
}
}

10
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<WidgetType> findWidgetTypesByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias);
List<WidgetTypeDetails> findWidgetTypesDetailsByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias);
List<WidgetTypeInfo> findWidgetTypesInfosByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias);
WidgetType findWidgetTypeByTenantIdBundleAliasAndAlias(TenantId tenantId, String bundleAlias, String alias);
void deleteWidgetTypesByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias);

49
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<WidgetTypeId> 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();
}
}

88
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<WidgetTypeId> 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<WidgetTypeId> 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();
}
}

45
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();
}
}

46
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();
}
}

86
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<T extends BaseWidgetType> extends BaseSqlEntity<T> implements BaseEntity<T> {
@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;
}
}

69
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<WidgetTypeDetails> {
@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;
}
}

53
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<WidgetType> implements BaseEntity<WidgetType> {
@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<WidgetType> {
@Type(type="json")
@Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY)
@ -66,34 +45,10 @@ public final class WidgetTypeEntity extends BaseSqlEntity<WidgetType> 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;
}

56
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<WidgetTypeInfo> {
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;
}
}

29
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<WidgetTypeEntity, WidgetType> implements WidgetTypeDao {
public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeDetailsEntity, WidgetTypeDetails> implements WidgetTypeDao {
@Autowired
private WidgetTypeRepository widgetTypeRepository;
@Override
protected Class<WidgetTypeEntity> getEntityClass() {
return WidgetTypeEntity.class;
protected Class<WidgetTypeDetailsEntity> getEntityClass() {
return WidgetTypeDetailsEntity.class;
}
@Override
protected CrudRepository<WidgetTypeEntity, UUID> getCrudRepository() {
protected CrudRepository<WidgetTypeDetailsEntity, UUID> getCrudRepository() {
return widgetTypeRepository;
}
@Override
public WidgetType findWidgetTypeById(TenantId tenantId, UUID widgetTypeId) {
return DaoUtil.getData(widgetTypeRepository.findWidgetTypeById(widgetTypeId));
}
@Override
public List<WidgetType> findWidgetTypesByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) {
return DaoUtil.convertDataList(widgetTypeRepository.findWidgetTypesByTenantIdAndBundleAlias(tenantId, bundleAlias));
}
@Override
public List<WidgetTypeDetails> findWidgetTypesDetailsByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) {
return DaoUtil.convertDataList(widgetTypeRepository.findByTenantIdAndBundleAlias(tenantId, bundleAlias));
}
@Override
public List<WidgetTypeInfo> 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));
}
}

29
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<WidgetTypeEntity, UUID> {
public interface WidgetTypeRepository extends CrudRepository<WidgetTypeDetailsEntity, UUID> {
@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<WidgetTypeEntity> 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<WidgetTypeInfoEntity> findWidgetTypesInfosByTenantIdAndBundleAlias(@Param("tenantId") UUID tenantId,
@Param("bundleAlias") String bundleAlias);
List<WidgetTypeEntity> findByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias);
List<WidgetTypeDetailsEntity> 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);
}

35
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<WidgetType> {
public interface WidgetTypeDao extends Dao<WidgetTypeDetails> {
/**
* 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<WidgetType> {
*/
List<WidgetType> 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<WidgetTypeDetails> 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<WidgetTypeInfo> findWidgetTypesInfosByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias);
/**
* Find widget type by tenantId, bundleAlias and alias.
*

75
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<WidgetTypeDetails> 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<WidgetTypeInfo> 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<WidgetType> widgetTypeValidator =
new DataValidator<WidgetType>() {
private DataValidator<WidgetTypeDetails> 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!");
}
}

43
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<WidgetType> 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<WidgetType> loadedWidgetTypes = widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(tenantId, savedWidgetsBundle.getAlias());

54
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<Array<WidgetTypeDetails>> {
return this.http.get<Array<WidgetTypeDetails>>(`/api/widgetTypesDetails?isSystem=${isSystem}&bundleAlias=${bundleAlias}`,
defaultHttpOptionsFromConfig(config));
}
public getBundleWidgetTypeInfos(bundleAlias: string, isSystem: boolean,
config?: RequestConfig): Observable<Array<WidgetTypeInfo>> {
return this.http.get<Array<WidgetTypeInfo>>(`/api/widgetTypesInfos?isSystem=${isSystem}&bundleAlias=${bundleAlias}`,
defaultHttpOptionsFromConfig(config));
}
public loadBundleLibraryWidgets(bundleAlias: string, isSystem: boolean,
config?: RequestConfig): Observable<Array<Widget>> {
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<WidgetType> {
const widgetTypeInstance = toWidgetType(widgetInfo, id, undefined, bundleAlias, createdTime);
return this.http.post<WidgetType>('/api/widgetType', widgetTypeInstance,
public saveWidgetTypeDetails(widgetInfo: WidgetInfo,
id: WidgetTypeId,
bundleAlias: string,
createdTime: number,
config?: RequestConfig): Observable<WidgetTypeDetails> {
const widgetTypeDetails = toWidgetTypeDetails(widgetInfo, id, undefined, bundleAlias, createdTime);
return this.http.post<WidgetTypeDetails>('/api/widgetType', widgetTypeDetails,
defaultHttpOptionsFromConfig(config)).pipe(
tap((savedWidgetType) => {
this.widgetTypeUpdatedSubject.next(savedWidgetType);
}));
}
public saveImportedWidgetType(widgetTypeInstance: WidgetType,
config?: RequestConfig): Observable<WidgetType> {
return this.http.post<WidgetType>('/api/widgetType', widgetTypeInstance,
public saveImportedWidgetTypeDetails(widgetTypeDetails: WidgetTypeDetails,
config?: RequestConfig): Observable<WidgetTypeDetails> {
return this.http.post<WidgetTypeDetails>('/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<WidgetType> {
return this.http.get<WidgetType>(`/api/widgetType/${widgetTypeId}`,
config?: RequestConfig): Observable<WidgetTypeDetails> {
return this.http.get<WidgetTypeDetails>(`/api/widgetType/${widgetTypeId}`,
defaultHttpOptionsFromConfig(config));
}

2
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,

11
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
};

4
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 {

56
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<WidgetType> {
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<Observable<WidgetType>> = [];
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;
}
}

2
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
);

27
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<IDynamicWidgetComponent>;
}
@ -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
};
}

41
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);

12
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<WidgetEditorData> {
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<WidgetEditorData> {
map((widget) => {
widget.widgetName = null;
return {
widgetType: null,
widgetTypeDetails: null,
widget
};
})

20
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<WidgetTypeId> {
export interface BaseWidgetType extends BaseData<WidgetTypeId> {
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 {

Loading…
Cancel
Save