Browse Source

New widget selector backend support

pull/4218/head
Igor Kulikov 6 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.RuleChain;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.data.widget.WidgetType; 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.data.widget.WidgetsBundle;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType; 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 { try {
validateId(widgetTypeId, "Incorrect widgetTypeId " + widgetTypeId); validateId(widgetTypeId, "Incorrect widgetTypeId " + widgetTypeId);
WidgetType widgetType = widgetTypeService.findWidgetTypeById(getCurrentUser().getTenantId(), widgetTypeId); WidgetTypeDetails widgetTypeDetails = widgetTypeService.findWidgetTypeDetailsById(getCurrentUser().getTenantId(), widgetTypeId);
checkNotNull(widgetType); checkNotNull(widgetTypeDetails);
accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, operation, widgetTypeId, widgetType); accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, operation, widgetTypeId, widgetTypeDetails);
return widgetType; return widgetTypeDetails;
} catch (Exception e) { } catch (Exception e) {
throw handleException(e, false); 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.id.WidgetTypeId;
import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.widget.WidgetType; 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.dao.model.ModelConstants;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
@ -45,7 +47,7 @@ public class WidgetTypeController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.GET) @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public WidgetType getWidgetTypeById(@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { public WidgetTypeDetails getWidgetTypeById(@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException {
checkParameter("widgetTypeId", strWidgetTypeId); checkParameter("widgetTypeId", strWidgetTypeId);
try { try {
WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId));
@ -58,17 +60,17 @@ public class WidgetTypeController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@RequestMapping(value = "/widgetType", method = RequestMethod.POST) @RequestMapping(value = "/widgetType", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public WidgetType saveWidgetType(@RequestBody WidgetType widgetType) throws ThingsboardException { public WidgetTypeDetails saveWidgetType(@RequestBody WidgetTypeDetails widgetTypeDetails) throws ThingsboardException {
try { try {
if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
widgetType.setTenantId(TenantId.SYS_TENANT_ID); widgetTypeDetails.setTenantId(TenantId.SYS_TENANT_ID);
} else { } 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) { } catch (Exception e) {
throw handleException(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')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/widgetType", params = {"isSystem", "bundleAlias", "alias"}, method = RequestMethod.GET) @RequestMapping(value = "/widgetType", params = {"isSystem", "bundleAlias", "alias"}, method = RequestMethod.GET)
@ResponseBody @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.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.widget.WidgetType; 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.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService;
@ -168,9 +169,9 @@ public class InstallScripts {
widgetTypesArrayJson.forEach( widgetTypesArrayJson.forEach(
widgetTypeJson -> { widgetTypeJson -> {
try { try {
WidgetType widgetType = objectMapper.treeToValue(widgetTypeJson, WidgetType.class); WidgetTypeDetails widgetTypeDetails = objectMapper.treeToValue(widgetTypeJson, WidgetTypeDetails.class);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetTypeDetails.setBundleAlias(savedWidgetsBundle.getAlias());
widgetTypeService.saveWidgetType(widgetType); widgetTypeService.saveWidgetType(widgetTypeDetails);
} catch (Exception e) { } catch (Exception e) {
log.error("Unable to load widget type from json: [{}]", path.toString()); log.error("Unable to load widget type from json: [{}]", path.toString());
throw new RuntimeException("Unable to load widget type from json", e); 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.User;
import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.widget.WidgetType; 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.data.widget.WidgetsBundle;
import java.util.ArrayList; import java.util.ArrayList;
@ -76,11 +77,11 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
@Test @Test
public void testSaveWidgetType() throws Exception { public void testSaveWidgetType() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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);
Assert.assertNotNull(savedWidgetType.getId()); Assert.assertNotNull(savedWidgetType.getId());
@ -95,42 +96,42 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
doPost("/api/widgetType", savedWidgetType, WidgetType.class); 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()); Assert.assertEquals(foundWidgetType.getName(), savedWidgetType.getName());
} }
@Test @Test
public void testUpdateWidgetTypeFromDifferentTenant() throws Exception { public void testUpdateWidgetTypeFromDifferentTenant() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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(); loginDifferentTenant();
doPost("/api/widgetType", savedWidgetType, WidgetType.class, status().isForbidden()); doPost("/api/widgetType", savedWidgetType, WidgetTypeDetails.class, status().isForbidden());
deleteDifferentTenant(); deleteDifferentTenant();
} }
@Test @Test
public void testFindWidgetTypeById() throws Exception { public void testFindWidgetTypeById() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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/" + savedWidgetType.getId().getId().toString(), WidgetType.class); WidgetTypeDetails foundWidgetType = doGet("/api/widgetType/" + savedWidgetType.getId().getId().toString(), WidgetTypeDetails.class);
Assert.assertNotNull(foundWidgetType); Assert.assertNotNull(foundWidgetType);
Assert.assertEquals(savedWidgetType, foundWidgetType); Assert.assertEquals(savedWidgetType, foundWidgetType);
} }
@Test @Test
public void testDeleteWidgetType() throws Exception { public void testDeleteWidgetType() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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()) doDelete("/api/widgetType/"+savedWidgetType.getId().getId().toString())
.andExpect(status().isOk()); .andExpect(status().isOk());
@ -141,7 +142,7 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
@Test @Test
public void testSaveWidgetTypeWithEmptyName() throws Exception { public void testSaveWidgetTypeWithEmptyName() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class));
doPost("/api/widgetType", widgetType) doPost("/api/widgetType", widgetType)
@ -151,7 +152,7 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
@Test @Test
public void testSaveWidgetTypeWithEmptyBundleAlias() throws Exception { public void testSaveWidgetTypeWithEmptyBundleAlias() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class));
doPost("/api/widgetType", widgetType) doPost("/api/widgetType", widgetType)
@ -161,7 +162,7 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
@Test @Test
public void testSaveWidgetTypeWithEmptyDescriptor() throws Exception { public void testSaveWidgetTypeWithEmptyDescriptor() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{}", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{}", JsonNode.class));
@ -172,7 +173,7 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
@Test @Test
public void testSaveWidgetTypeWithInvalidBundleAlias() throws Exception { public void testSaveWidgetTypeWithInvalidBundleAlias() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias("some_alias"); widgetType.setBundleAlias("some_alias");
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class));
@ -183,11 +184,11 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
@Test @Test
public void testUpdateWidgetTypeBundleAlias() throws Exception { public void testUpdateWidgetTypeBundleAlias() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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"); savedWidgetType.setBundleAlias("some_alias");
doPost("/api/widgetType", savedWidgetType) doPost("/api/widgetType", savedWidgetType)
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
@ -197,11 +198,11 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
@Test @Test
public void testUpdateWidgetTypeAlias() throws Exception { public void testUpdateWidgetTypeAlias() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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"); savedWidgetType.setAlias("some_alias");
doPost("/api/widgetType", savedWidgetType) doPost("/api/widgetType", savedWidgetType)
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
@ -213,15 +214,15 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
public void testGetBundleWidgetTypes() throws Exception { public void testGetBundleWidgetTypes() throws Exception {
List<WidgetType> widgetTypes = new ArrayList<>(); List<WidgetType> widgetTypes = new ArrayList<>();
for (int i=0;i<89;i++) { for (int i=0;i<89;i++) {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type " + i); widgetType.setName("Widget Type " + i);
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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}", 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(widgetTypes, idComparator);
Collections.sort(loadedWidgetTypes, idComparator); Collections.sort(loadedWidgetTypes, idComparator);
@ -231,15 +232,15 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes
@Test @Test
public void testGetWidgetType() throws Exception { public void testGetWidgetType() throws Exception {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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 foundWidgetType = doGet("/api/widgetType?isSystem={isSystem}&bundleAlias={bundleAlias}&alias={alias}",
WidgetType.class, false, savedWidgetsBundle.getAlias(), savedWidgetType.getAlias()); WidgetType.class, false, savedWidgetsBundle.getAlias(), savedWidgetType.getAlias());
Assert.assertNotNull(foundWidgetType); 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.TenantId;
import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.widget.WidgetType; 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; import java.util.List;
@ -25,12 +27,18 @@ public interface WidgetTypeService {
WidgetType findWidgetTypeById(TenantId tenantId, WidgetTypeId widgetTypeId); 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); void deleteWidgetType(TenantId tenantId, WidgetTypeId widgetTypeId);
List<WidgetType> findWidgetTypesByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias); 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); WidgetType findWidgetTypeByTenantIdBundleAliasAndAlias(TenantId tenantId, String bundleAlias, String alias);
void deleteWidgetTypesByTenantIdAndBundleAlias(TenantId tenantId, String bundleAlias); 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; package org.thingsboard.server.common.data.widget;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import lombok.EqualsAndHashCode; 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; import org.thingsboard.server.common.data.id.WidgetTypeId;
@EqualsAndHashCode(callSuper = true) @Data
public class WidgetType extends BaseData<WidgetTypeId> implements HasTenantId { 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; private transient JsonNode descriptor;
public WidgetType() { public WidgetType() {
@ -43,76 +32,13 @@ public class WidgetType extends BaseData<WidgetTypeId> implements HasTenantId {
super(id); super(id);
} }
public WidgetType(BaseWidgetType baseWidgetType) {
super(baseWidgetType);
}
public WidgetType(WidgetType widgetType) { public WidgetType(WidgetType widgetType) {
super(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(); 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 lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type; import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.widget.BaseWidgetType;
import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.widget.WidgetType; 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.model.ModelConstants;
import org.thingsboard.server.dao.util.mapping.JsonStringType; import org.thingsboard.server.dao.util.mapping.JsonStringType;
@ -38,25 +35,7 @@ import java.util.UUID;
@Entity @Entity
@TypeDef(name = "json", typeClass = JsonStringType.class) @TypeDef(name = "json", typeClass = JsonStringType.class)
@Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME) @Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME)
public final class WidgetTypeEntity extends BaseSqlEntity<WidgetType> implements BaseEntity<WidgetType> { public final class WidgetTypeEntity extends AbstractWidgetTypeEntity<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;
@Type(type="json") @Type(type="json")
@Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY) @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY)
@ -66,34 +45,10 @@ public final class WidgetTypeEntity extends BaseSqlEntity<WidgetType> implement
super(); 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 @Override
public WidgetType toData() { public WidgetType toData() {
WidgetType widgetType = new WidgetType(new WidgetTypeId(this.getUuid())); BaseWidgetType baseWidgetType = super.toBaseWidgetType();
widgetType.setCreatedTime(createdTime); WidgetType widgetType = new WidgetType(baseWidgetType);
if (tenantId != null) {
widgetType.setTenantId(new TenantId(tenantId));
}
widgetType.setBundleAlias(bundleAlias);
widgetType.setAlias(alias);
widgetType.setName(name);
widgetType.setImage(image);
widgetType.setDescription(description);
widgetType.setDescriptor(descriptor); widgetType.setDescriptor(descriptor);
return widgetType; 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.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component; 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.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.DaoUtil;
import org.thingsboard.server.dao.model.sql.WidgetTypeDetailsEntity;
import org.thingsboard.server.dao.model.sql.WidgetTypeEntity; import org.thingsboard.server.dao.model.sql.WidgetTypeEntity;
import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.widget.WidgetTypeDao; import org.thingsboard.server.dao.widget.WidgetTypeDao;
@ -31,28 +35,43 @@ import java.util.UUID;
* Created by Valerii Sosliuk on 4/29/2017. * Created by Valerii Sosliuk on 4/29/2017.
*/ */
@Component @Component
public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeEntity, WidgetType> implements WidgetTypeDao { public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeDetailsEntity, WidgetTypeDetails> implements WidgetTypeDao {
@Autowired @Autowired
private WidgetTypeRepository widgetTypeRepository; private WidgetTypeRepository widgetTypeRepository;
@Override @Override
protected Class<WidgetTypeEntity> getEntityClass() { protected Class<WidgetTypeDetailsEntity> getEntityClass() {
return WidgetTypeEntity.class; return WidgetTypeDetailsEntity.class;
} }
@Override @Override
protected CrudRepository<WidgetTypeEntity, UUID> getCrudRepository() { protected CrudRepository<WidgetTypeDetailsEntity, UUID> getCrudRepository() {
return widgetTypeRepository; return widgetTypeRepository;
} }
@Override
public WidgetType findWidgetTypeById(TenantId tenantId, UUID widgetTypeId) {
return DaoUtil.getData(widgetTypeRepository.findWidgetTypeById(widgetTypeId));
}
@Override @Override
public List<WidgetType> findWidgetTypesByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) { 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)); return DaoUtil.convertDataList(widgetTypeRepository.findByTenantIdAndBundleAlias(tenantId, bundleAlias));
} }
@Override
public List<WidgetTypeInfo> findWidgetTypesInfosByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) {
return DaoUtil.convertDataList(widgetTypeRepository.findWidgetTypesInfosByTenantIdAndBundleAlias(tenantId, bundleAlias));
}
@Override @Override
public WidgetType findByTenantIdBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias) { 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; 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.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.WidgetTypeEntity;
import org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
/** public interface WidgetTypeRepository extends CrudRepository<WidgetTypeDetailsEntity, UUID> {
* Created by Valerii Sosliuk on 4/29/2017.
*/ @Query("SELECT wt FROM WidgetTypeEntity wt WHERE wt.id = :widgetTypeId")
public interface WidgetTypeRepository extends CrudRepository<WidgetTypeEntity, UUID> { 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.id.TenantId;
import org.thingsboard.server.common.data.widget.WidgetType; 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 org.thingsboard.server.dao.Dao;
import java.util.List; import java.util.List;
@ -25,15 +27,24 @@ import java.util.UUID;
/** /**
* The Interface WidgetTypeDao. * The Interface WidgetTypeDao.
*/ */
public interface WidgetTypeDao extends Dao<WidgetType> { public interface WidgetTypeDao extends Dao<WidgetTypeDetails> {
/** /**
* Save or update widget type object * Save or update widget type object
* *
* @param widgetType the widget type object * @param widgetTypeDetails the widget type details object
* @return saved widget type 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. * Find widget types by tenantId and bundleAlias.
@ -44,6 +55,24 @@ public interface WidgetTypeDao extends Dao<WidgetType> {
*/ */
List<WidgetType> findWidgetTypesByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias); 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. * 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.TenantId;
import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.widget.WidgetType; 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.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.ModelConstants;
@ -51,14 +53,21 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
public WidgetType findWidgetTypeById(TenantId tenantId, WidgetTypeId widgetTypeId) { public WidgetType findWidgetTypeById(TenantId tenantId, WidgetTypeId widgetTypeId) {
log.trace("Executing findWidgetTypeById [{}]", widgetTypeId); log.trace("Executing findWidgetTypeById [{}]", widgetTypeId);
Validator.validateId(widgetTypeId, "Incorrect widgetTypeId " + 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()); return widgetTypeDao.findById(tenantId, widgetTypeId.getId());
} }
@Override @Override
public WidgetType saveWidgetType(WidgetType widgetType) { public WidgetTypeDetails saveWidgetType(WidgetTypeDetails widgetTypeDetails) {
log.trace("Executing saveWidgetType [{}]", widgetType); log.trace("Executing saveWidgetType [{}]", widgetTypeDetails);
widgetTypeValidator.validate(widgetType, WidgetType::getTenantId); widgetTypeValidator.validate(widgetTypeDetails, WidgetType::getTenantId);
return widgetTypeDao.save(widgetType.getTenantId(), widgetType); return widgetTypeDao.save(widgetTypeDetails.getTenantId(), widgetTypeDetails);
} }
@Override @Override
@ -76,6 +85,22 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
return widgetTypeDao.findWidgetTypesByTenantIdAndBundleAlias(tenantId.getId(), bundleAlias); 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 @Override
public WidgetType findWidgetTypeByTenantIdBundleAliasAndAlias(TenantId tenantId, String bundleAlias, String alias) { public WidgetType findWidgetTypeByTenantIdBundleAliasAndAlias(TenantId tenantId, String bundleAlias, String alias) {
log.trace("Executing findWidgetTypeByTenantIdBundleAliasAndAlias, tenantId [{}], bundleAlias [{}], alias [{}]", tenantId, bundleAlias, alias); log.trace("Executing findWidgetTypeByTenantIdBundleAliasAndAlias, tenantId [{}], bundleAlias [{}], alias [{}]", tenantId, bundleAlias, alias);
@ -96,24 +121,24 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
} }
} }
private DataValidator<WidgetType> widgetTypeValidator = private DataValidator<WidgetTypeDetails> widgetTypeValidator =
new DataValidator<WidgetType>() { new DataValidator<>() {
@Override @Override
protected void validateDataImpl(TenantId tenantId, WidgetType widgetType) { protected void validateDataImpl(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) {
if (StringUtils.isEmpty(widgetType.getName())) { if (StringUtils.isEmpty(widgetTypeDetails.getName())) {
throw new DataValidationException("Widgets type name should be specified!"); 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!"); 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!"); throw new DataValidationException("Widgets type descriptor can't be empty!");
} }
if (widgetType.getTenantId() == null) { if (widgetTypeDetails.getTenantId() == null) {
widgetType.setTenantId(new TenantId(ModelConstants.NULL_UUID)); widgetTypeDetails.setTenantId(new TenantId(ModelConstants.NULL_UUID));
} }
if (!widgetType.getTenantId().getId().equals(ModelConstants.NULL_UUID)) { if (!widgetTypeDetails.getTenantId().getId().equals(ModelConstants.NULL_UUID)) {
Tenant tenant = tenantDao.findById(tenantId, widgetType.getTenantId().getId()); Tenant tenant = tenantDao.findById(tenantId, widgetTypeDetails.getTenantId().getId());
if (tenant == null) { if (tenant == null) {
throw new DataValidationException("Widget type is referencing to non-existent tenant!"); throw new DataValidationException("Widget type is referencing to non-existent tenant!");
} }
@ -121,37 +146,37 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
} }
@Override @Override
protected void validateCreate(TenantId tenantId, WidgetType widgetType) { protected void validateCreate(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) {
WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(widgetType.getTenantId().getId(), widgetType.getBundleAlias()); WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(widgetTypeDetails.getTenantId().getId(), widgetTypeDetails.getBundleAlias());
if (widgetsBundle == null) { if (widgetsBundle == null) {
throw new DataValidationException("Widget type is referencing to non-existent widgets bundle!"); 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()) { if (alias == null || alias.trim().isEmpty()) {
alias = widgetType.getName().toLowerCase().replaceAll("\\W+", "_"); alias = widgetTypeDetails.getName().toLowerCase().replaceAll("\\W+", "_");
} }
String originalAlias = alias; String originalAlias = alias;
int c = 1; int c = 1;
WidgetType withSameAlias; WidgetType withSameAlias;
do { do {
withSameAlias = widgetTypeDao.findByTenantIdBundleAliasAndAlias(widgetType.getTenantId().getId(), widgetType.getBundleAlias(), alias); withSameAlias = widgetTypeDao.findByTenantIdBundleAliasAndAlias(widgetTypeDetails.getTenantId().getId(), widgetTypeDetails.getBundleAlias(), alias);
if (withSameAlias != null) { if (withSameAlias != null) {
alias = originalAlias + (++c); alias = originalAlias + (++c);
} }
} while (withSameAlias != null); } while (withSameAlias != null);
widgetType.setAlias(alias); widgetTypeDetails.setAlias(alias);
} }
@Override @Override
protected void validateUpdate(TenantId tenantId, WidgetType widgetType) { protected void validateUpdate(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) {
WidgetType storedWidgetType = widgetTypeDao.findById(tenantId, widgetType.getId().getId()); WidgetType storedWidgetType = widgetTypeDao.findById(tenantId, widgetTypeDetails.getId().getId());
if (!storedWidgetType.getTenantId().getId().equals(widgetType.getTenantId().getId())) { if (!storedWidgetType.getTenantId().getId().equals(widgetTypeDetails.getTenantId().getId())) {
throw new DataValidationException("Can't move existing widget type to different tenant!"); 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!"); 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!"); 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.Tenant;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.widget.WidgetType; 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.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.ModelConstants;
@ -62,12 +63,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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);
Assert.assertNotNull(savedWidgetType.getId()); Assert.assertNotNull(savedWidgetType.getId());
@ -94,7 +95,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class));
@ -107,7 +108,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
@Test(expected = DataValidationException.class) @Test(expected = DataValidationException.class)
public void testSaveWidgetTypeWithEmptyBundleAlias() throws IOException { public void testSaveWidgetTypeWithEmptyBundleAlias() throws IOException {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class));
@ -121,7 +122,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
@ -140,7 +141,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(new TenantId(Uuids.timeBased())); widgetType.setTenantId(new TenantId(Uuids.timeBased()));
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
@ -154,7 +155,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
@Test(expected = DataValidationException.class) @Test(expected = DataValidationException.class)
public void testSaveWidgetTypeWithInvalidBundleAlias() throws IOException { public void testSaveWidgetTypeWithInvalidBundleAlias() throws IOException {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias("some_alias"); widgetType.setBundleAlias("some_alias");
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
@ -169,12 +170,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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)); savedWidgetType.setTenantId(new TenantId(ModelConstants.NULL_UUID));
try { try {
widgetTypeService.saveWidgetType(savedWidgetType); widgetTypeService.saveWidgetType(savedWidgetType);
@ -190,12 +191,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class));
WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); WidgetTypeDetails savedWidgetType = widgetTypeService.saveWidgetType(widgetType);
savedWidgetType.setBundleAlias("some_alias"); savedWidgetType.setBundleAlias("some_alias");
try { try {
widgetTypeService.saveWidgetType(savedWidgetType); widgetTypeService.saveWidgetType(savedWidgetType);
@ -211,12 +212,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class));
WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); WidgetTypeDetails savedWidgetType = widgetTypeService.saveWidgetType(widgetType);
savedWidgetType.setAlias("some_alias"); savedWidgetType.setAlias("some_alias");
try { try {
widgetTypeService.saveWidgetType(savedWidgetType); widgetTypeService.saveWidgetType(savedWidgetType);
@ -232,13 +233,13 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class));
WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType); WidgetTypeDetails savedWidgetType = widgetTypeService.saveWidgetType(widgetType);
WidgetType foundWidgetType = widgetTypeService.findWidgetTypeById(tenantId, savedWidgetType.getId()); WidgetTypeDetails foundWidgetType = widgetTypeService.findWidgetTypeDetailsById(tenantId, savedWidgetType.getId());
Assert.assertNotNull(foundWidgetType); Assert.assertNotNull(foundWidgetType);
Assert.assertEquals(savedWidgetType, foundWidgetType); Assert.assertEquals(savedWidgetType, foundWidgetType);
@ -252,12 +253,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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()); WidgetType foundWidgetType = widgetTypeService.findWidgetTypeByTenantIdBundleAliasAndAlias(tenantId, savedWidgetsBundle.getAlias(), savedWidgetType.getAlias());
Assert.assertNotNull(foundWidgetType); Assert.assertNotNull(foundWidgetType);
Assert.assertEquals(savedWidgetType, foundWidgetType); Assert.assertEquals(savedWidgetType, foundWidgetType);
@ -272,7 +273,7 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
widgetsBundle.setTitle("Widgets bundle"); widgetsBundle.setTitle("Widgets bundle");
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type"); widgetType.setName("Widget Type");
@ -296,12 +297,12 @@ public abstract class BaseWidgetTypeServiceTest extends AbstractServiceTest {
List<WidgetType> widgetTypes = new ArrayList<>(); List<WidgetType> widgetTypes = new ArrayList<>();
for (int i=0;i<121;i++) { for (int i=0;i<121;i++) {
WidgetType widgetType = new WidgetType(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId); widgetType.setTenantId(tenantId);
widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
widgetType.setName("Widget Type " + i); widgetType.setName("Widget Type " + i);
widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); 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()); 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 { PageLink } from '@shared/models/page/page-link';
import { PageData } from '@shared/models/page/page-data'; import { PageData } from '@shared/models/page/page-data';
import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; 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 { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { ResourcesService } from '../services/resources.service'; 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 { filter, map, mergeMap, tap } from 'rxjs/operators';
import { WidgetTypeId } from '@shared/models/id/widget-type-id'; import { WidgetTypeId } from '@shared/models/id/widget-type-id';
import { NULL_UUID } from '@shared/models/id/has-uuid'; import { NULL_UUID } from '@shared/models/id/has-uuid';
@ -117,6 +129,18 @@ export class WidgetService {
defaultHttpOptionsFromConfig(config)); 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, public loadBundleLibraryWidgets(bundleAlias: string, isSystem: boolean,
config?: RequestConfig): Observable<Array<Widget>> { config?: RequestConfig): Observable<Array<Widget>> {
return this.getBundleWidgetTypes(bundleAlias, isSystem, config).pipe( return this.getBundleWidgetTypes(bundleAlias, isSystem, config).pipe(
@ -144,8 +168,6 @@ export class WidgetService {
typeAlias: widgetTypeInfo.alias, typeAlias: widgetTypeInfo.alias,
type: widgetTypeInfo.type, type: widgetTypeInfo.type,
title: widgetTypeInfo.widgetName, title: widgetTypeInfo.widgetName,
image: widgetTypeInfo.image,
description: widgetTypeInfo.description,
sizeX, sizeX,
sizeY, sizeY,
row: top, row: top,
@ -178,22 +200,22 @@ export class WidgetService {
defaultHttpOptionsFromConfig(config)); defaultHttpOptionsFromConfig(config));
} }
public saveWidgetType(widgetInfo: WidgetInfo, public saveWidgetTypeDetails(widgetInfo: WidgetInfo,
id: WidgetTypeId, id: WidgetTypeId,
bundleAlias: string, bundleAlias: string,
createdTime: number, createdTime: number,
config?: RequestConfig): Observable<WidgetType> { config?: RequestConfig): Observable<WidgetTypeDetails> {
const widgetTypeInstance = toWidgetType(widgetInfo, id, undefined, bundleAlias, createdTime); const widgetTypeDetails = toWidgetTypeDetails(widgetInfo, id, undefined, bundleAlias, createdTime);
return this.http.post<WidgetType>('/api/widgetType', widgetTypeInstance, return this.http.post<WidgetTypeDetails>('/api/widgetType', widgetTypeDetails,
defaultHttpOptionsFromConfig(config)).pipe( defaultHttpOptionsFromConfig(config)).pipe(
tap((savedWidgetType) => { tap((savedWidgetType) => {
this.widgetTypeUpdatedSubject.next(savedWidgetType); this.widgetTypeUpdatedSubject.next(savedWidgetType);
})); }));
} }
public saveImportedWidgetType(widgetTypeInstance: WidgetType, public saveImportedWidgetTypeDetails(widgetTypeDetails: WidgetTypeDetails,
config?: RequestConfig): Observable<WidgetType> { config?: RequestConfig): Observable<WidgetTypeDetails> {
return this.http.post<WidgetType>('/api/widgetType', widgetTypeInstance, return this.http.post<WidgetTypeDetails>('/api/widgetType', widgetTypeDetails,
defaultHttpOptionsFromConfig(config)).pipe( defaultHttpOptionsFromConfig(config)).pipe(
tap((savedWidgetType) => { tap((savedWidgetType) => {
this.widgetTypeUpdatedSubject.next(savedWidgetType); this.widgetTypeUpdatedSubject.next(savedWidgetType);
@ -215,8 +237,8 @@ export class WidgetService {
} }
public getWidgetTypeById(widgetTypeId: string, public getWidgetTypeById(widgetTypeId: string,
config?: RequestConfig): Observable<WidgetType> { config?: RequestConfig): Observable<WidgetTypeDetails> {
return this.http.get<WidgetType>(`/api/widgetType/${widgetTypeId}`, return this.http.get<WidgetTypeDetails>(`/api/widgetType/${widgetTypeId}`,
defaultHttpOptionsFromConfig(config)); 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, typeAlias: widgetInfo.alias,
type: widgetInfo.type, type: widgetInfo.type,
title: widgetInfo.widgetName, title: widgetInfo.widgetName,
image: widgetInfo.image,
description: widgetInfo.description,
sizeX, sizeX,
sizeY, sizeY,
row: 0, 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) { if (this.widgetsBundle !== null) {
const bundleAlias = this.widgetsBundle.alias; const bundleAlias = this.widgetsBundle.alias;
const isSystem = this.widgetsBundle.tenantId.id === NULL_UUID; 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.sort((a, b) => b.createdTime - a.createdTime)),
map(widgets => widgets.map((type) => { map(widgets => widgets.map((widgetTypeInfo) => {
const widgetTypeInfo = toWidgetInfo(type); this.widgetsType.add(widgetTypeInfo.widgetType);
this.widgetsType.add(widgetTypeInfo.type);
const widget: WidgetInfo = { const widget: WidgetInfo = {
isSystemType: isSystem, isSystemType: isSystem,
bundleAlias, bundleAlias,
typeAlias: widgetTypeInfo.alias, typeAlias: widgetTypeInfo.alias,
type: widgetTypeInfo.type, type: widgetTypeInfo.widgetType,
title: widgetTypeInfo.widgetName, title: widgetTypeInfo.name,
image: widgetTypeInfo.image, image: widgetTypeInfo.image,
description: widgetTypeInfo.description 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. /// 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 { DashboardLayoutId } from '@shared/models/dashboard.models';
import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
@ -25,7 +25,7 @@ export interface ImportWidgetResult {
export interface WidgetsBundleItem { export interface WidgetsBundleItem {
widgetsBundle: WidgetsBundle; widgetsBundle: WidgetsBundle;
widgetTypes: WidgetType[]; widgetTypes: WidgetTypeDetails[];
} }
export interface CsvToJsonConfig { 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 { catchError, map, mergeMap, tap } from 'rxjs/operators';
import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
import { EntityService } from '@core/http/entity.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 { import {
EntityAliasesDialogComponent, EntityAliasesDialogComponent,
EntityAliasesDialogData EntityAliasesDialogData
@ -234,13 +234,13 @@ export class ImportExportService {
public exportWidgetType(widgetTypeId: string) { public exportWidgetType(widgetTypeId: string) {
this.widgetService.getWidgetTypeById(widgetTypeId).subscribe( this.widgetService.getWidgetTypeById(widgetTypeId).subscribe(
(widgetType) => { (widgetTypeDetails) => {
if (isDefined(widgetType.bundleAlias)) { if (isDefined(widgetTypeDetails.bundleAlias)) {
delete widgetType.bundleAlias; delete widgetTypeDetails.bundleAlias;
} }
let name = widgetType.name; let name = widgetTypeDetails.name;
name = name.toLowerCase().replace(/\W/g, '_'); name = name.toLowerCase().replace(/\W/g, '_');
this.exportToPc(this.prepareExport(widgetType), name); this.exportToPc(this.prepareExport(widgetTypeDetails), name);
}, },
(e) => { (e) => {
this.handleExportError(e, 'widget-type.export-failed-error'); this.handleExportError(e, 'widget-type.export-failed-error');
@ -250,15 +250,15 @@ export class ImportExportService {
public importWidgetType(bundleAlias: string): Observable<WidgetType> { public importWidgetType(bundleAlias: string): Observable<WidgetType> {
return this.openImportDialog('widget-type.import', 'widget-type.widget-type-file').pipe( return this.openImportDialog('widget-type.import', 'widget-type.widget-type-file').pipe(
mergeMap((widgetType: WidgetType) => { mergeMap((widgetTypeDetails: WidgetTypeDetails) => {
if (!this.validateImportedWidgetType(widgetType)) { if (!this.validateImportedWidgetTypeDetails(widgetTypeDetails)) {
this.store.dispatch(new ActionNotificationShow( this.store.dispatch(new ActionNotificationShow(
{message: this.translate.instant('widget-type.invalid-widget-type-file-error'), {message: this.translate.instant('widget-type.invalid-widget-type-file-error'),
type: 'error'})); type: 'error'}));
throw new Error('Invalid widget type file'); throw new Error('Invalid widget type file');
} else { } else {
widgetType.bundleAlias = bundleAlias; widgetTypeDetails.bundleAlias = bundleAlias;
return this.widgetService.saveImportedWidgetType(widgetType); return this.widgetService.saveImportedWidgetTypeDetails(widgetTypeDetails);
} }
}), }),
catchError((err) => { catchError((err) => {
@ -272,18 +272,18 @@ export class ImportExportService {
(widgetsBundle) => { (widgetsBundle) => {
const bundleAlias = widgetsBundle.alias; const bundleAlias = widgetsBundle.alias;
const isSystem = widgetsBundle.tenantId.id === NULL_UUID; const isSystem = widgetsBundle.tenantId.id === NULL_UUID;
this.widgetService.getBundleWidgetTypes(bundleAlias, isSystem).subscribe( this.widgetService.getBundleWidgetTypesDetails(bundleAlias, isSystem).subscribe(
(widgetTypes) => { (widgetTypesDetails) => {
widgetTypes = widgetTypes.sort((a, b) => a.createdTime - b.createdTime); widgetTypesDetails = widgetTypesDetails.sort((a, b) => a.createdTime - b.createdTime);
const widgetsBundleItem: WidgetsBundleItem = { const widgetsBundleItem: WidgetsBundleItem = {
widgetsBundle: this.prepareExport(widgetsBundle), widgetsBundle: this.prepareExport(widgetsBundle),
widgetTypes: [] widgetTypes: []
}; };
for (const widgetType of widgetTypes) { for (const widgetTypeDetails of widgetTypesDetails) {
if (isDefined(widgetType.bundleAlias)) { if (isDefined(widgetTypeDetails.bundleAlias)) {
delete widgetType.bundleAlias; delete widgetTypeDetails.bundleAlias;
} }
widgetsBundleItem.widgetTypes.push(this.prepareExport(widgetType)); widgetsBundleItem.widgetTypes.push(this.prepareExport(widgetTypeDetails));
} }
let name = widgetsBundle.title; let name = widgetsBundle.title;
name = name.toLowerCase().replace(/\W/g, '_'); name = name.toLowerCase().replace(/\W/g, '_');
@ -313,12 +313,12 @@ export class ImportExportService {
return this.widgetService.saveWidgetsBundle(widgetsBundle).pipe( return this.widgetService.saveWidgetsBundle(widgetsBundle).pipe(
mergeMap((savedWidgetsBundle) => { mergeMap((savedWidgetsBundle) => {
const bundleAlias = savedWidgetsBundle.alias; const bundleAlias = savedWidgetsBundle.alias;
const widgetTypes = widgetsBundleItem.widgetTypes; const widgetTypesDetails = widgetsBundleItem.widgetTypes;
if (widgetTypes.length) { if (widgetTypesDetails.length) {
const saveWidgetTypesObservables: Array<Observable<WidgetType>> = []; const saveWidgetTypesObservables: Array<Observable<WidgetType>> = [];
for (const widgetType of widgetTypes) { for (const widgetTypeDetails of widgetTypesDetails) {
widgetType.bundleAlias = bundleAlias; widgetTypeDetails.bundleAlias = bundleAlias;
saveWidgetTypesObservables.push(this.widgetService.saveImportedWidgetType(widgetType)); saveWidgetTypesObservables.push(this.widgetService.saveImportedWidgetTypeDetails(widgetTypeDetails));
} }
return forkJoin(saveWidgetTypesObservables).pipe( return forkJoin(saveWidgetTypesObservables).pipe(
map(() => savedWidgetsBundle) map(() => savedWidgetsBundle)
@ -508,9 +508,9 @@ export class ImportExportService {
return true; return true;
} }
private validateImportedWidgetType(widgetType: WidgetType): boolean { private validateImportedWidgetTypeDetails(widgetTypeDetails: WidgetTypeDetails): boolean {
if (isUndefined(widgetType.name) if (isUndefined(widgetTypeDetails.name)
|| isUndefined(widgetType.descriptor)) { || isUndefined(widgetTypeDetails.descriptor)) {
return false; return false;
} }
return true; return true;
@ -527,9 +527,9 @@ export class ImportExportService {
if (isUndefined(widgetsBundle.title)) { if (isUndefined(widgetsBundle.title)) {
return false; return false;
} }
const widgetTypes = widgetsBundleItem.widgetTypes; const widgetTypesDetails = widgetsBundleItem.widgetTypes;
for (const widgetType of widgetTypes) { for (const widgetTypeDetails of widgetTypesDetails) {
if (!this.validateImportedWidgetType(widgetType)) { if (!this.validateImportedWidgetTypeDetails(widgetTypeDetails)) {
return false; 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, controllerScript: this.utils.editWidgetInfo.controllerScript,
settingsSchema: this.utils.editWidgetInfo.settingsSchema, settingsSchema: this.utils.editWidgetInfo.settingsSchema,
dataKeySettingsSchema: this.utils.editWidgetInfo.dataKeySettingsSchema, dataKeySettingsSchema: this.utils.editWidgetInfo.dataKeySettingsSchema,
image: this.utils.editWidgetInfo.image,
description: this.utils.editWidgetInfo.description,
defaultConfig: this.utils.editWidgetInfo.defaultConfig defaultConfig: this.utils.editWidgetInfo.defaultConfig
}, new WidgetTypeId('1'), new TenantId( NULL_UUID ), 'customWidgetBundle', undefined }, 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, WidgetControllerDescriptor,
WidgetType, WidgetType,
widgetType, widgetType,
WidgetTypeDescriptor, WidgetTypeDescriptor, WidgetTypeDetails,
WidgetTypeParameters WidgetTypeParameters
} from '@shared/models/widget.models'; } from '@shared/models/widget.models';
import { Timewindow, WidgetTimewindow } from '@shared/models/time/time.models'; import { Timewindow, WidgetTimewindow } from '@shared/models/time/time.models';
@ -347,8 +347,8 @@ export interface WidgetInfo extends WidgetTypeDescriptor, WidgetControllerDescri
alias: string; alias: string;
typeSettingsSchema?: string | any; typeSettingsSchema?: string | any;
typeDataKeySettingsSchema?: string | any; typeDataKeySettingsSchema?: string | any;
image: string; image?: string;
description: string; description?: string;
componentFactory?: ComponentFactory<IDynamicWidgetComponent>; componentFactory?: ComponentFactory<IDynamicWidgetComponent>;
} }
@ -427,11 +427,16 @@ export interface WidgetTypeInstance {
onDestroy?: () => void; 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 { export function toWidgetInfo(widgetTypeEntity: WidgetType): WidgetInfo {
return { return {
widgetName: widgetTypeEntity.name, widgetName: widgetTypeEntity.name,
image: widgetTypeEntity.image,
description: widgetTypeEntity.description,
alias: widgetTypeEntity.alias, alias: widgetTypeEntity.alias,
type: widgetTypeEntity.descriptor.type, type: widgetTypeEntity.descriptor.type,
sizeX: widgetTypeEntity.descriptor.sizeX, 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, export function toWidgetType(widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId: TenantId,
bundleAlias: string, createdTime: number): WidgetType { bundleAlias: string, createdTime: number): WidgetType {
const descriptor: WidgetTypeDescriptor = { const descriptor: WidgetTypeDescriptor = {
@ -467,8 +482,6 @@ export function toWidgetType(widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId:
bundleAlias, bundleAlias,
alias: widgetInfo.alias, alias: widgetInfo.alias,
name: widgetInfo.widgetName, name: widgetInfo.widgetName,
image: widgetInfo.image,
description: widgetInfo.description,
descriptor 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 { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; import { detailsToWidgetInfo, toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models';
import { Widget, WidgetConfig, WidgetType, widgetType, widgetTypesData } from '@shared/models/widget.models'; import {
Widget,
WidgetConfig,
WidgetType,
widgetType,
WidgetTypeDetails,
widgetTypesData
} from '@shared/models/widget.models';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { deepClone } from '@core/utils'; import { deepClone } from '@core/utils';
import { HasDirtyFlag } from '@core/guards/confirm-on-exit.guard'; import { HasDirtyFlag } from '@core/guards/confirm-on-exit.guard';
@ -108,7 +115,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
isReadOnly: boolean; isReadOnly: boolean;
widgetsBundle: WidgetsBundle; widgetsBundle: WidgetsBundle;
widgetType: WidgetType; widgetTypeDetails: WidgetTypeDetails;
widget: WidgetInfo; widget: WidgetInfo;
origWidget: WidgetInfo; origWidget: WidgetInfo;
@ -175,14 +182,14 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
} else { } else {
this.isReadOnly = this.authUser.authority !== Authority.SYS_ADMIN; this.isReadOnly = this.authUser.authority !== Authority.SYS_ADMIN;
} }
this.widgetType = data.widgetEditorData.widgetType; this.widgetTypeDetails = data.widgetEditorData.widgetTypeDetails;
this.widget = data.widgetEditorData.widget; this.widget = data.widgetEditorData.widget;
if (this.widgetType) { if (this.widgetTypeDetails) {
const config = JSON.parse(this.widget.defaultConfig); const config = JSON.parse(this.widget.defaultConfig);
this.widget.defaultConfig = JSON.stringify(config); this.widget.defaultConfig = JSON.stringify(config);
} }
this.origWidget = deepClone(this.widget); this.origWidget = deepClone(this.widget);
if (!this.widgetType) { if (!this.widgetTypeDetails) {
this.isDirty = true; this.isDirty = true;
} }
} }
@ -515,11 +522,11 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
} }
private commitSaveWidget() { private commitSaveWidget() {
const id = (this.widgetType && this.widgetType.id) ? this.widgetType.id : undefined; const id = (this.widgetTypeDetails && this.widgetTypeDetails.id) ? this.widgetTypeDetails.id : undefined;
const createdTime = (this.widgetType && this.widgetType.createdTime) ? this.widgetType.createdTime : undefined; const createdTime = (this.widgetTypeDetails && this.widgetTypeDetails.createdTime) ? this.widgetTypeDetails.createdTime : undefined;
this.widgetService.saveWidgetType(this.widget, id, this.widgetsBundle.alias, createdTime).subscribe( this.widgetService.saveWidgetTypeDetails(this.widget, id, this.widgetsBundle.alias, createdTime).subscribe(
(widgetTypeInstance) => { (widgetTypeDetails) => {
this.setWidgetType(widgetTypeInstance); this.setWidgetTypeDetails(widgetTypeDetails);
this.saveWidgetPending = false; this.saveWidgetPending = false;
this.store.dispatch(new ActionNotificationShow( this.store.dispatch(new ActionNotificationShow(
{message: this.translate.instant('widget.widget-saved'), type: 'success', duration: 500})); {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; config.title = this.widget.widgetName;
this.widget.defaultConfig = JSON.stringify(config); this.widget.defaultConfig = JSON.stringify(config);
this.isDirty = false; this.isDirty = false;
this.widgetService.saveWidgetType(this.widget, undefined, saveWidgetAsData.bundleAlias, undefined).subscribe( this.widgetService.saveWidgetTypeDetails(this.widget, undefined, saveWidgetAsData.bundleAlias, undefined).subscribe(
(widgetTypeInstance) => { (widgetTypeDetails) => {
this.router.navigateByUrl(`/widgets-bundles/${saveWidgetAsData.bundleId}/widgetTypes/${widgetTypeInstance.id.id}`); 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) { private setWidgetTypeDetails(widgetTypeDetails: WidgetTypeDetails) {
this.widgetType = widgetTypeInstance; this.widgetTypeDetails = widgetTypeDetails;
this.widget = toWidgetInfo(this.widgetType); this.widget = detailsToWidgetInfo(this.widgetTypeDetails);
const config = JSON.parse(this.widget.defaultConfig); const config = JSON.parse(this.widget.defaultConfig);
this.widget.defaultConfig = JSON.stringify(config); this.widget.defaultConfig = JSON.stringify(config);
this.origWidget = deepClone(this.widget); 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 { WidgetService } from '@core/http/widget.service';
import { WidgetEditorComponent } from '@home/pages/widget/widget-editor.component'; import { WidgetEditorComponent } from '@home/pages/widget/widget-editor.component';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; import { detailsToWidgetInfo, toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models';
import { widgetType, WidgetType } from '@app/shared/models/widget.models'; import { widgetType, WidgetType, WidgetTypeDetails } from '@app/shared/models/widget.models';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { WidgetsData } from '@home/models/dashboard-component.models'; import { WidgetsData } from '@home/models/dashboard-component.models';
import { NULL_UUID } from '@shared/models/id/has-uuid'; import { NULL_UUID } from '@shared/models/id/has-uuid';
export interface WidgetEditorData { export interface WidgetEditorData {
widgetType: WidgetType; widgetTypeDetails: WidgetTypeDetails;
widget: WidgetInfo; widget: WidgetInfo;
} }
@ -83,8 +83,8 @@ export class WidgetEditorDataResolver implements Resolve<WidgetEditorData> {
return this.widgetsService.getWidgetTypeById(widgetTypeId).pipe( return this.widgetsService.getWidgetTypeById(widgetTypeId).pipe(
map((result) => { map((result) => {
return { return {
widgetType: result, widgetTypeDetails: result,
widget: toWidgetInfo(result) widget: detailsToWidgetInfo(result)
}; };
}) })
); );
@ -106,7 +106,7 @@ export class WidgetEditorAddDataResolver implements Resolve<WidgetEditorData> {
map((widget) => { map((widget) => {
widget.widgetName = null; widget.widgetName = null;
return { return {
widgetType: null, widgetTypeDetails: null,
widget widget
}; };
}) })

20
ui-ngx/src/app/shared/models/widget.models.ts

@ -165,14 +165,26 @@ export interface WidgetControllerDescriptor {
actionSources?: {[actionSourceId: string]: WidgetActionSource}; actionSources?: {[actionSourceId: string]: WidgetActionSource};
} }
export interface WidgetType extends BaseData<WidgetTypeId> { export interface BaseWidgetType extends BaseData<WidgetTypeId> {
tenantId: TenantId; tenantId: TenantId;
bundleAlias: string; bundleAlias: string;
alias: string; alias: string;
name: 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; image: string;
description: string; description: string;
descriptor: WidgetTypeDescriptor;
} }
export enum LegendDirection { export enum LegendDirection {
@ -417,8 +429,8 @@ export interface WidgetInfo {
typeAlias: string; typeAlias: string;
type: widgetType; type: widgetType;
title: string; title: string;
image: string; image?: string;
description: string; description?: string;
} }
export interface GroupInfo { export interface GroupInfo {

Loading…
Cancel
Save