Merge pull request #12688 from AndriiLandiak/widget-type-info-bundles
Add bundles to widget type info
This commit is contained in:
commit
fe45eee0cb
@ -125,6 +125,7 @@ import org.thingsboard.server.common.data.rule.RuleNode;
|
||||
import org.thingsboard.server.common.data.security.UserCredentials;
|
||||
import org.thingsboard.server.common.data.util.ThrowingBiFunction;
|
||||
import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
|
||||
import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
|
||||
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
||||
import org.thingsboard.server.dao.alarm.AlarmCommentService;
|
||||
import org.thingsboard.server.dao.asset.AssetProfileService;
|
||||
@ -759,6 +760,10 @@ public abstract class BaseController {
|
||||
return checkEntityId(widgetTypeId, widgetTypeService::findWidgetTypeDetailsById, operation);
|
||||
}
|
||||
|
||||
WidgetTypeInfo checkWidgetTypeInfoId(WidgetTypeId widgetTypeId, Operation operation) throws ThingsboardException {
|
||||
return checkEntityId(widgetTypeId, widgetTypeService::findWidgetTypeInfoById, operation);
|
||||
}
|
||||
|
||||
Dashboard checkDashboardId(DashboardId dashboardId, Operation operation) throws ThingsboardException {
|
||||
return checkEntityId(dashboardId, dashboardService::findDashboardById, operation);
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ public class WidgetTypeController extends AutoCommitController {
|
||||
@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException {
|
||||
checkParameter("widgetTypeId", strWidgetTypeId);
|
||||
WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId));
|
||||
return new WidgetTypeInfo(checkWidgetTypeId(widgetTypeId, Operation.READ));
|
||||
return checkWidgetTypeInfoId(widgetTypeId, Operation.READ);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "Create Or Update Widget Type (saveWidgetType)",
|
||||
|
||||
@ -35,6 +35,8 @@ public interface WidgetTypeService extends EntityDaoService {
|
||||
|
||||
WidgetTypeDetails findWidgetTypeDetailsById(TenantId tenantId, WidgetTypeId widgetTypeId);
|
||||
|
||||
WidgetTypeInfo findWidgetTypeInfoById(TenantId tenantId, WidgetTypeId widgetTypeId);
|
||||
|
||||
boolean widgetTypeExistsByTenantIdAndWidgetTypeId(TenantId tenantId, WidgetTypeId widgetTypeId);
|
||||
|
||||
WidgetTypeDetails saveWidgetType(WidgetTypeDetails widgetType);
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright © 2016-2024 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.annotation.JsonProperty;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
import org.thingsboard.server.common.data.EntityInfo;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.id.EntityIdFactory;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.UUID;
|
||||
|
||||
@Value
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class WidgetBundleInfo extends EntityInfo {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 2132305394634509820L;
|
||||
|
||||
public WidgetBundleInfo(@JsonProperty("id") UUID uuid, @JsonProperty("name") String name) {
|
||||
super(EntityIdFactory.getByTypeAndUuid(EntityType.WIDGETS_BUNDLE, uuid), name);
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,13 +16,21 @@
|
||||
package org.thingsboard.server.common.data.widget;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.Data;
|
||||
import org.thingsboard.server.common.data.id.WidgetTypeId;
|
||||
import org.thingsboard.server.common.data.validation.NoXss;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class WidgetTypeInfo extends BaseWidgetType {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1343617007959780969L;
|
||||
|
||||
@Schema(description = "Base64 encoded widget thumbnail", accessMode = Schema.AccessMode.READ_ONLY)
|
||||
private String image;
|
||||
@NoXss
|
||||
@ -34,6 +42,9 @@ public class WidgetTypeInfo extends BaseWidgetType {
|
||||
@NoXss
|
||||
@Schema(description = "Type of the widget (timeseries, latest, control, alarm or static)", accessMode = Schema.AccessMode.READ_ONLY)
|
||||
private String widgetType;
|
||||
@Valid
|
||||
@Schema(description = "Bundles", accessMode = Schema.AccessMode.READ_ONLY)
|
||||
private List<WidgetBundleInfo> bundles;
|
||||
|
||||
public WidgetTypeInfo() {
|
||||
super();
|
||||
@ -48,14 +59,23 @@ public class WidgetTypeInfo extends BaseWidgetType {
|
||||
}
|
||||
|
||||
public WidgetTypeInfo(WidgetTypeInfo widgetTypeInfo) {
|
||||
this(widgetTypeInfo, Collections.emptyList());
|
||||
}
|
||||
|
||||
public WidgetTypeInfo(WidgetTypeInfo widgetTypeInfo, List<WidgetBundleInfo> bundles) {
|
||||
super(widgetTypeInfo);
|
||||
this.image = widgetTypeInfo.getImage();
|
||||
this.description = widgetTypeInfo.getDescription();
|
||||
this.tags = widgetTypeInfo.getTags();
|
||||
this.widgetType = widgetTypeInfo.getWidgetType();
|
||||
this.bundles = bundles;
|
||||
}
|
||||
|
||||
public WidgetTypeInfo(WidgetTypeDetails widgetTypeDetails) {
|
||||
this(widgetTypeDetails, Collections.emptyList());
|
||||
}
|
||||
|
||||
public WidgetTypeInfo(WidgetTypeDetails widgetTypeDetails, List<WidgetBundleInfo> bundles) {
|
||||
super(widgetTypeDetails);
|
||||
this.image = widgetTypeDetails.getImage();
|
||||
this.description = widgetTypeDetails.getDescription();
|
||||
@ -65,5 +85,7 @@ public class WidgetTypeInfo extends BaseWidgetType {
|
||||
} else {
|
||||
this.widgetType = "";
|
||||
}
|
||||
this.bundles = bundles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -312,6 +312,7 @@ public class ModelConstants {
|
||||
public static final String WIDGETS_BUNDLE_SCADA_PROPERTY = "scada";
|
||||
public static final String WIDGETS_BUNDLE_DESCRIPTION = "description";
|
||||
public static final String WIDGETS_BUNDLE_ORDER = "widgets_bundle_order";
|
||||
public static final String WIDGET_BUNDLES_PROPERTY = "bundles";
|
||||
|
||||
/**
|
||||
* Widget_type constants.
|
||||
|
||||
@ -15,17 +15,22 @@
|
||||
*/
|
||||
package org.thingsboard.server.dao.model.sql;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.hypersistence.utils.hibernate.type.array.StringArrayType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.hibernate.annotations.Immutable;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.widget.BaseWidgetType;
|
||||
import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
|
||||
import org.thingsboard.server.dao.model.ModelConstants;
|
||||
import org.thingsboard.server.dao.util.mapping.JsonConverter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -58,6 +63,10 @@ public class WidgetTypeInfoEntity extends AbstractWidgetTypeEntity<WidgetTypeInf
|
||||
@Column(name = ModelConstants.WIDGET_TYPE_WIDGET_TYPE_PROPERTY)
|
||||
private String widgetType;
|
||||
|
||||
@Convert(converter = JsonConverter.class)
|
||||
@Column(name = ModelConstants.WIDGET_BUNDLES_PROPERTY)
|
||||
private JsonNode bundles;
|
||||
|
||||
public WidgetTypeInfoEntity() {
|
||||
super();
|
||||
}
|
||||
@ -70,6 +79,7 @@ public class WidgetTypeInfoEntity extends AbstractWidgetTypeEntity<WidgetTypeInf
|
||||
widgetTypeInfo.setDescription(description);
|
||||
widgetTypeInfo.setTags(tags);
|
||||
widgetTypeInfo.setWidgetType(widgetType);
|
||||
widgetTypeInfo.setBundles(JacksonUtil.convertValue(bundles, new TypeReference<>() {}));
|
||||
return widgetTypeInfo;
|
||||
}
|
||||
|
||||
|
||||
@ -84,6 +84,11 @@ public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeDetailsEntity, Wi
|
||||
return widgetTypeRepository.existsByTenantIdAndId(tenantId.getId(), widgetTypeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WidgetTypeInfo findWidgetTypeInfoById(TenantId tenantId, UUID widgetTypeId) {
|
||||
return DaoUtil.getData(widgetTypeInfoRepository.findById(widgetTypeId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<WidgetTypeInfo> findSystemWidgetTypes(WidgetTypeFilter widgetTypeFilter, PageLink pageLink) {
|
||||
boolean deprecatedFilterEnabled = !DeprecatedFilter.ALL.equals(widgetTypeFilter.getDeprecatedFilter());
|
||||
|
||||
@ -56,6 +56,8 @@ public interface WidgetTypeDao extends Dao<WidgetTypeDetails>, ExportableEntityD
|
||||
|
||||
boolean existsByTenantIdAndId(TenantId tenantId, UUID widgetTypeId);
|
||||
|
||||
WidgetTypeInfo findWidgetTypeInfoById(TenantId tenantId, UUID widgetTypeId);
|
||||
|
||||
PageData<WidgetTypeInfo> findSystemWidgetTypes(WidgetTypeFilter widgetTypeFilter, PageLink pageLink);
|
||||
|
||||
PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantId(WidgetTypeFilter widgetTypeFilter, PageLink pageLink);
|
||||
|
||||
@ -87,6 +87,13 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
|
||||
return widgetTypeDao.findById(tenantId, widgetTypeId.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WidgetTypeInfo findWidgetTypeInfoById(TenantId tenantId, WidgetTypeId widgetTypeId) {
|
||||
log.trace("Executing findWidgetTypeInfoById [{}]", widgetTypeId);
|
||||
Validator.validateId(widgetTypeId, id -> "Incorrect widgetTypeId " + id);
|
||||
return widgetTypeDao.findWidgetTypeInfoById(tenantId, widgetTypeId.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean widgetTypeExistsByTenantIdAndWidgetTypeId(TenantId tenantId, WidgetTypeId widgetTypeId) {
|
||||
log.trace("Executing widgetTypeExistsByTenantIdAndWidgetTypeId, tenantId [{}], widgetTypeId [{}]", tenantId, widgetTypeId);
|
||||
|
||||
@ -288,8 +288,15 @@ $$;
|
||||
|
||||
DROP VIEW IF EXISTS widget_type_info_view CASCADE;
|
||||
CREATE OR REPLACE VIEW widget_type_info_view AS
|
||||
SELECT t.*
|
||||
, COALESCE((t.descriptor::json->>'type')::text, '') as widget_type
|
||||
SELECT t.*,
|
||||
COALESCE((t.descriptor::json->>'type')::text, '') as widget_type,
|
||||
array_to_json(ARRAY(
|
||||
SELECT json_build_object('id', wb.widgets_bundle_id, 'name', b.title)
|
||||
FROM widgets_bundle_widget wb
|
||||
JOIN widgets_bundle b ON wb.widgets_bundle_id = b.id
|
||||
WHERE wb.widget_type_id = t.id
|
||||
ORDER BY b.title
|
||||
)) AS bundles
|
||||
FROM widget_type t;
|
||||
|
||||
CREATE OR REPLACE PROCEDURE cleanup_timeseries_by_ttl(IN null_uuid uuid,
|
||||
|
||||
@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.page.SortOrder;
|
||||
import org.thingsboard.server.common.data.widget.BaseWidgetType;
|
||||
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
|
||||
import org.thingsboard.server.common.data.widget.WidgetBundleInfo;
|
||||
import org.thingsboard.server.common.data.widget.WidgetType;
|
||||
import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
|
||||
import org.thingsboard.server.common.data.widget.WidgetTypeFilter;
|
||||
@ -49,11 +50,10 @@ import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Created by Valerii Sosliuk on 4/30/2017.
|
||||
*/
|
||||
public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
|
||||
// given search text should find a widget with tags, when searching by tags
|
||||
@ -78,7 +78,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
|
||||
final String BUNDLE_ALIAS = "BUNDLE_ALIAS";
|
||||
final int WIDGET_TYPE_COUNT = 3;
|
||||
List<WidgetTypeDetails> widgetTypeList;
|
||||
List<WidgetTypeInfo> widgetTypeList;
|
||||
WidgetsBundle widgetsBundle;
|
||||
|
||||
@Autowired
|
||||
@ -107,7 +107,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
widgetTypeList.sort(Comparator.comparing(BaseWidgetType::getName));
|
||||
}
|
||||
|
||||
WidgetTypeDetails createAndSaveWidgetType(TenantId tenantId, int number) {
|
||||
WidgetTypeInfo createAndSaveWidgetType(TenantId tenantId, int number) {
|
||||
WidgetTypeDetails widgetType = new WidgetTypeDetails();
|
||||
widgetType.setTenantId(tenantId);
|
||||
widgetType.setName("WIDGET_TYPE_" + number);
|
||||
@ -119,7 +119,10 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
widgetType.setDescriptor(descriptor);
|
||||
String[] tags = new String[]{"Tag1_" + number, "Tag2_" + number, "TEST_" + number};
|
||||
widgetType.setTags(tags);
|
||||
return widgetTypeDao.save(TenantId.SYS_TENANT_ID, widgetType);
|
||||
WidgetTypeDetails saved = widgetTypeDao.save(TenantId.SYS_TENANT_ID, widgetType);
|
||||
List<WidgetBundleInfo> bundles = new ArrayList<>();
|
||||
bundles.add(new WidgetBundleInfo(widgetsBundle.getUuidId(), widgetsBundle.getName()));
|
||||
return new WidgetTypeInfo(saved, bundles);
|
||||
}
|
||||
|
||||
WidgetTypeDetails createAndSaveWidgetType(TenantId tenantId, int number, String[] tags) {
|
||||
@ -139,7 +142,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
@After
|
||||
public void tearDown() {
|
||||
widgetsBundleDao.removeById(TenantId.SYS_TENANT_ID, widgetsBundle.getUuidId());
|
||||
for (WidgetType widgetType : widgetTypeList) {
|
||||
for (WidgetTypeInfo widgetType : widgetTypeList) {
|
||||
widgetTypeDao.removeById(TenantId.SYS_TENANT_ID, widgetType.getUuidId());
|
||||
}
|
||||
}
|
||||
@ -160,7 +163,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
.widgetTypes(Collections.singletonList("static")).build(),
|
||||
new PageLink(1024, 0, "TYPE_DESCRIPTION", new SortOrder("createdTime")));
|
||||
assertEquals(1, widgetTypes.getData().size());
|
||||
assertEquals(new WidgetTypeInfo(widgetTypeList.get(1)), widgetTypes.getData().get(0));
|
||||
assertEquals(widgetTypeList.get(1), widgetTypes.getData().get(0));
|
||||
|
||||
widgetTypes = widgetTypeDao.findSystemWidgetTypes(
|
||||
WidgetTypeFilter.builder()
|
||||
@ -170,7 +173,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
.widgetTypes(Collections.emptyList()).build(),
|
||||
new PageLink(1024, 0, "hfgfd tag2_2 ghg", new SortOrder("createdTime")));
|
||||
assertEquals(1, widgetTypes.getData().size());
|
||||
assertEquals(new WidgetTypeInfo(widgetTypeList.get(2)), widgetTypes.getData().get(0));
|
||||
assertEquals(widgetTypeList.get(2), widgetTypes.getData().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -181,7 +184,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
Thread.sleep(2);
|
||||
var widgetType = saveWidgetType(TenantId.SYS_TENANT_ID, "widgetName");
|
||||
sameNameList.add(widgetType);
|
||||
widgetTypeList.add(widgetType);
|
||||
widgetTypeList.add(new WidgetTypeInfo(widgetType));
|
||||
}
|
||||
sameNameList.sort(Comparator.comparing(BaseWidgetType::getName).thenComparing((BaseWidgetType baseWidgetType) -> baseWidgetType.getId().getId()));
|
||||
List<WidgetTypeInfo> expected = sameNameList.stream().map(WidgetTypeInfo::new).collect(Collectors.toList());
|
||||
@ -254,12 +257,12 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
public void testFindTenantWidgetTypesByTenantId() {
|
||||
UUID tenantId = Uuids.timeBased();
|
||||
for (int i = 0; i < WIDGET_TYPE_COUNT; i++) {
|
||||
var widgetType = createAndSaveWidgetType(new TenantId(tenantId), i);
|
||||
var widgetType = createAndSaveWidgetType(TenantId.fromUUID(tenantId), i);
|
||||
widgetTypeList.add(widgetType);
|
||||
}
|
||||
PageData<WidgetTypeInfo> widgetTypes = widgetTypeDao.findTenantWidgetTypesByTenantId(
|
||||
WidgetTypeFilter.builder()
|
||||
.tenantId(new TenantId(tenantId))
|
||||
.tenantId(TenantId.fromUUID(tenantId))
|
||||
.fullSearch(true)
|
||||
.deprecatedFilter(DeprecatedFilter.ALL)
|
||||
.widgetTypes(null).build(),
|
||||
@ -363,13 +366,13 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
PageData<WidgetTypeInfo> widgetTypes = widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(TenantId.SYS_TENANT_ID.getId(), widgetsBundle.getUuidId(), true, DeprecatedFilter.ALL, Collections.singletonList("latest"),
|
||||
new PageLink(1024, 0, "TYPE_DESCRIPTION", new SortOrder("createdTime")));
|
||||
assertEquals(2, widgetTypes.getData().size());
|
||||
assertEquals(new WidgetTypeInfo(widgetTypeList.get(0)), widgetTypes.getData().get(0));
|
||||
assertEquals(new WidgetTypeInfo(widgetTypeList.get(2)), widgetTypes.getData().get(1));
|
||||
assertEquals(widgetTypeList.get(0), widgetTypes.getData().get(0));
|
||||
assertEquals(widgetTypeList.get(2), widgetTypes.getData().get(1));
|
||||
|
||||
widgetTypes = widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(TenantId.SYS_TENANT_ID.getId(), widgetsBundle.getUuidId(), true, DeprecatedFilter.ALL, Collections.emptyList(),
|
||||
new PageLink(1024, 0, "hfgfd TEST_0 ghg", new SortOrder("createdTime")));
|
||||
assertEquals(1, widgetTypes.getData().size());
|
||||
assertEquals(new WidgetTypeInfo(widgetTypeList.get(0)), widgetTypes.getData().get(0));
|
||||
assertEquals(widgetTypeList.get(0), widgetTypes.getData().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -410,7 +413,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
|
||||
@Test
|
||||
public void testFindByTenantIdAndFqn() {
|
||||
WidgetType result = widgetTypeList.get(0);
|
||||
WidgetTypeInfo result = widgetTypeList.get(0);
|
||||
assertNotNull(result);
|
||||
WidgetType widgetType = widgetTypeDao.findByTenantIdAndFqn(TenantId.SYS_TENANT_ID.getId(), "FQN_0");
|
||||
assertEquals(result.getId(), widgetType.getId());
|
||||
@ -426,7 +429,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
|
||||
@Test
|
||||
public void testFindByImageLink() {
|
||||
TenantId tenantId = new TenantId(UUID.randomUUID());
|
||||
TenantId tenantId = TenantId.fromUUID(UUID.randomUUID());
|
||||
WidgetTypeDetails details = createAndSaveWidgetType(tenantId, 0, new String[]{"a"});
|
||||
details.setDescriptor(JacksonUtil.newObjectNode().put("bg", "/image/tenant/widget.png"));
|
||||
widgetTypeDao.save(tenantId, details);
|
||||
@ -437,6 +440,73 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
widgetTypeDao.removeById(tenantId, details.getUuidId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindWidgetTypesWithBundles() {
|
||||
PageData<WidgetTypeInfo> widgetTypes = widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(
|
||||
TenantId.SYS_TENANT_ID.getId(),
|
||||
widgetsBundle.getUuidId(),
|
||||
true,
|
||||
DeprecatedFilter.ALL,
|
||||
Collections.singletonList("latest"),
|
||||
new PageLink(1024, 0, "TYPE_DESCRIPTION", new SortOrder("createdTime"))
|
||||
);
|
||||
|
||||
assertEquals(2, widgetTypes.getData().size());
|
||||
for (var widgetType : widgetTypes.getData()) {
|
||||
assertFalse("Bundles should not be empty", widgetType.getBundles().isEmpty());
|
||||
assertEquals(BUNDLE_ALIAS, widgetType.getBundles().get(0).getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddWidgetTypeToNewBundleAndVerifyBundles() {
|
||||
String newBundleTitle = "New Bundle Title";
|
||||
WidgetsBundle newWidgetsBundle = new WidgetsBundle();
|
||||
newWidgetsBundle.setAlias("NewBundle");
|
||||
newWidgetsBundle.setTitle(newBundleTitle);
|
||||
newWidgetsBundle.setId(new WidgetsBundleId(UUID.randomUUID()));
|
||||
newWidgetsBundle.setTenantId(TenantId.SYS_TENANT_ID);
|
||||
newWidgetsBundle = widgetsBundleDao.save(TenantId.SYS_TENANT_ID, newWidgetsBundle);
|
||||
|
||||
for (int i = 0; i < widgetTypeList.size(); i++) {
|
||||
WidgetTypeInfo widgetType = widgetTypeList.get(i);
|
||||
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(newWidgetsBundle.getId(), widgetType.getId(), i));
|
||||
}
|
||||
|
||||
PageData<WidgetTypeInfo> widgetTypes = widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(
|
||||
TenantId.SYS_TENANT_ID.getId(),
|
||||
newWidgetsBundle.getUuidId(),
|
||||
true,
|
||||
DeprecatedFilter.ALL,
|
||||
Collections.singletonList("latest"),
|
||||
new PageLink(1024, 0, "TYPE_DESCRIPTION", new SortOrder("createdTime"))
|
||||
);
|
||||
|
||||
assertEquals(2, widgetTypes.getData().size());
|
||||
WidgetTypeInfo widgetTypeInfo1 = widgetTypes.getData().get(0);
|
||||
WidgetTypeInfo widgetTypeInfo2 = widgetTypes.getData().get(1);
|
||||
|
||||
assertEquals(2, widgetTypeInfo1.getBundles().size());
|
||||
assertTrue("Bundles should contain 'BUNDLE_ALIAS'", widgetTypeInfo1.getBundles().stream().anyMatch(bundle -> BUNDLE_ALIAS.equals(bundle.getName())));
|
||||
assertTrue("Bundles should contain 'New Bundle Title'", widgetTypeInfo1.getBundles().stream().anyMatch(bundle -> newBundleTitle.equals(bundle.getName())));
|
||||
|
||||
assertEquals(2, widgetTypeInfo2.getBundles().size());
|
||||
assertTrue("Bundles should contain 'BUNDLE_ALIAS'", widgetTypeInfo2.getBundles().stream().anyMatch(bundle -> "BUNDLE_ALIAS".equals(bundle.getName())));
|
||||
assertTrue("Bundles should contain 'New Bundle Title'", widgetTypeInfo2.getBundles().stream().anyMatch(bundle -> newBundleTitle.equals(bundle.getName())));
|
||||
|
||||
// cleanup and verify
|
||||
widgetsBundleDao.removeById(newWidgetsBundle.getTenantId(), newWidgetsBundle.getUuidId());
|
||||
widgetTypes = widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(
|
||||
TenantId.SYS_TENANT_ID.getId(),
|
||||
newWidgetsBundle.getUuidId(),
|
||||
true,
|
||||
DeprecatedFilter.ALL,
|
||||
Collections.singletonList("latest"),
|
||||
new PageLink(1024, 0, "TYPE_DESCRIPTION", new SortOrder("createdTime"))
|
||||
);
|
||||
widgetTypes.getData().forEach(widgetTypeInfo -> assertEquals(1, widgetTypeInfo.getBundles().size()));
|
||||
}
|
||||
|
||||
private WidgetTypeDetails saveWidgetType(TenantId tenantId, String name) {
|
||||
WidgetTypeDetails widgetType = new WidgetTypeDetails();
|
||||
widgetType.setTenantId(tenantId);
|
||||
@ -447,4 +517,5 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
|
||||
widgetType.setDescriptor(descriptor);
|
||||
return widgetTypeDao.save(TenantId.SYS_TENANT_ID, widgetType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -192,7 +192,8 @@
|
||||
(click)="$event.stopPropagation();"></a>
|
||||
</ng-template>
|
||||
<ng-template [ngSwitchCase]="'entityChips'">
|
||||
<tb-entity-chips [entity]="entity" [key]="column.key"></tb-entity-chips>
|
||||
<tb-entity-chips [entity]="entity" [key]="column.key"
|
||||
[detailsPagePrefixUrl]="column.entityURL ? column.entityURL(entity) : ''"></tb-entity-chips>
|
||||
</ng-template>
|
||||
<ng-template #defaultContent ngSwitchDefault>
|
||||
<span [innerHTML]="cellContent(entity, column, row)"></span>
|
||||
|
||||
@ -18,7 +18,7 @@ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { BaseData } from '@shared/models/base-data';
|
||||
import { EntityId } from '@shared/models/id/entity-id';
|
||||
import { baseDetailsPageByEntityType, EntityType } from '@app/shared/public-api';
|
||||
import { isEqual, isObject } from '@core/utils';
|
||||
import { isEqual, isNotEmptyStr, isObject } from '@core/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-entity-chips',
|
||||
@ -33,6 +33,9 @@ export class EntityChipsComponent implements OnChanges {
|
||||
@Input()
|
||||
key: string;
|
||||
|
||||
@Input()
|
||||
detailsPagePrefixUrl: string;
|
||||
|
||||
entityDetailsPrefixUrl: string;
|
||||
|
||||
subEntities: Array<BaseData<EntityId>> = [];
|
||||
@ -52,7 +55,9 @@ export class EntityChipsComponent implements OnChanges {
|
||||
if (isObject(entitiesList) && !Array.isArray(entitiesList)) {
|
||||
entitiesList = [entitiesList];
|
||||
}
|
||||
if (Array.isArray(entitiesList)) {
|
||||
if (isNotEmptyStr(this.detailsPagePrefixUrl)) {
|
||||
this.entityDetailsPrefixUrl = this.detailsPagePrefixUrl;
|
||||
} else if (Array.isArray(entitiesList)) {
|
||||
if (entitiesList.length) {
|
||||
this.entityDetailsPrefixUrl = baseDetailsPageByEntityType.get(entitiesList[0].id.entityType as EntityType);
|
||||
}
|
||||
|
||||
@ -144,7 +144,8 @@ export class DateEntityTableColumn<T extends BaseData<HasId>> extends EntityTabl
|
||||
export class EntityChipsEntityTableColumn<T extends BaseData<HasId>> extends BaseEntityTableColumn<T> {
|
||||
constructor(public key: string,
|
||||
public title: string,
|
||||
public width: string = '0px') {
|
||||
public width: string = '0px',
|
||||
public entityURL?: (entity) => string) {
|
||||
super('entityChips', key, title, width, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import { Router } from '@angular/router';
|
||||
import {
|
||||
checkBoxCell,
|
||||
DateEntityTableColumn,
|
||||
EntityChipsEntityTableColumn,
|
||||
EntityTableColumn,
|
||||
EntityTableConfig
|
||||
} from '@home/models/entity/entities-table-config.models';
|
||||
@ -75,7 +76,9 @@ export class WidgetTypesTableConfigResolver {
|
||||
|
||||
this.config.columns.push(
|
||||
new DateEntityTableColumn<WidgetTypeInfo>('createdTime', 'common.created-time', this.datePipe, '150px'),
|
||||
new EntityTableColumn<WidgetTypeInfo>('name', 'widget.title', '100%'),
|
||||
new EntityTableColumn<WidgetTypeInfo>('name', 'widget.title', '60%'),
|
||||
new EntityChipsEntityTableColumn<WidgetTypeInfo>( 'bundles', 'entity.type-widgets-bundles', '40%',
|
||||
() => '/resources/widgets-library/widgets-bundles'),
|
||||
new EntityTableColumn<WidgetTypeInfo>('widgetType', 'widget.type', '150px', entity =>
|
||||
entity?.widgetType ? this.translate.instant(widgetTypesData.get(entity.widgetType).name) : '', undefined, false),
|
||||
new EntityTableColumn<WidgetTypeInfo>('tenantId', 'widget.system', '60px',
|
||||
|
||||
@ -41,7 +41,7 @@ import { isNotEmptyStr, mergeDeepIgnoreArray } from '@core/utils';
|
||||
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
|
||||
import { ComponentStyle, Font, TimewindowStyle } from '@shared/models/widget-settings.models';
|
||||
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
||||
import { HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||
import { EntityInfoData, HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||
import { DataKeysCallbacks, DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models';
|
||||
import { WidgetConfigCallbacks } from '@home/components/widget/config/widget-config.component.models';
|
||||
import { TbFunction } from '@shared/models/js-function.models';
|
||||
@ -270,6 +270,7 @@ export interface WidgetTypeInfo extends BaseWidgetType {
|
||||
description: string;
|
||||
tags: string[];
|
||||
widgetType: widgetType;
|
||||
bundles?: EntityInfoData[];
|
||||
}
|
||||
|
||||
export interface WidgetTypeDetails extends WidgetType, ExportableEntity<WidgetTypeId> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user