Add bundles to widget-type-info
This commit is contained in:
		
							parent
							
								
									b242f35968
								
							
						
					
					
						commit
						fc513c5a5c
					
				@ -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);
 | 
			
		||||
 | 
			
		||||
@ -16,13 +16,22 @@
 | 
			
		||||
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.EntityInfo;
 | 
			
		||||
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 +43,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<EntityInfo> bundles;
 | 
			
		||||
 | 
			
		||||
    public WidgetTypeInfo() {
 | 
			
		||||
        super();
 | 
			
		||||
@ -53,6 +65,16 @@ public class WidgetTypeInfo extends BaseWidgetType {
 | 
			
		||||
        this.description = widgetTypeInfo.getDescription();
 | 
			
		||||
        this.tags = widgetTypeInfo.getTags();
 | 
			
		||||
        this.widgetType = widgetTypeInfo.getWidgetType();
 | 
			
		||||
        this.bundles = Collections.emptyList();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public WidgetTypeInfo(WidgetTypeInfo widgetTypeInfo, List<EntityInfo> 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) {
 | 
			
		||||
@ -65,5 +87,7 @@ public class WidgetTypeInfo extends BaseWidgetType {
 | 
			
		||||
        } else {
 | 
			
		||||
            this.widgetType = "";
 | 
			
		||||
        }
 | 
			
		||||
        this.bundles = Collections.emptyList();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
 | 
			
		||||
@ -17,17 +17,21 @@ package org.thingsboard.server.dao.model.sql;
 | 
			
		||||
 | 
			
		||||
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.server.common.data.EntityInfo;
 | 
			
		||||
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.WidgetBundleEntityInfosConverter;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@ -58,6 +62,10 @@ public class WidgetTypeInfoEntity extends AbstractWidgetTypeEntity<WidgetTypeInf
 | 
			
		||||
    @Column(name = ModelConstants.WIDGET_TYPE_WIDGET_TYPE_PROPERTY)
 | 
			
		||||
    private String widgetType;
 | 
			
		||||
 | 
			
		||||
    @Convert(converter = WidgetBundleEntityInfosConverter.class)
 | 
			
		||||
    @Column(name = ModelConstants.WIDGET_BUNDLES_PROPERTY)
 | 
			
		||||
    private List<EntityInfo> bundles;
 | 
			
		||||
 | 
			
		||||
    public WidgetTypeInfoEntity() {
 | 
			
		||||
        super();
 | 
			
		||||
    }
 | 
			
		||||
@ -70,6 +78,7 @@ public class WidgetTypeInfoEntity extends AbstractWidgetTypeEntity<WidgetTypeInf
 | 
			
		||||
        widgetTypeInfo.setDescription(description);
 | 
			
		||||
        widgetTypeInfo.setTags(tags);
 | 
			
		||||
        widgetTypeInfo.setWidgetType(widgetType);
 | 
			
		||||
        widgetTypeInfo.setBundles(bundles);
 | 
			
		||||
        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());
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,71 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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.dao.util.mapping;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import jakarta.persistence.AttributeConverter;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityInfo;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
public abstract class AbstractEntityInfosConverter implements AttributeConverter<List<EntityInfo>, String> {
 | 
			
		||||
 | 
			
		||||
    protected abstract EntityType getEntityType();
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String convertToDatabaseColumn(List<EntityInfo> attribute) {
 | 
			
		||||
        throw new IllegalArgumentException("Not implemented!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<EntityInfo> convertToEntityAttribute(String s) {
 | 
			
		||||
        try {
 | 
			
		||||
            JsonNode node = JacksonUtil.fromBytes(s.getBytes(StandardCharsets.UTF_8));
 | 
			
		||||
            if (node.isArray()) {
 | 
			
		||||
                List<EntityInfo> entities = new ArrayList<>();
 | 
			
		||||
                for (int i = 0; i < node.size(); i++) {
 | 
			
		||||
                    JsonNode row = node.get(i);
 | 
			
		||||
                    UUID id = null;
 | 
			
		||||
                    String name = null;
 | 
			
		||||
                    JsonNode idNode = row.get("id");
 | 
			
		||||
                    JsonNode nameNode = row.get("name");
 | 
			
		||||
                    if (idNode != null && nameNode != null) {
 | 
			
		||||
                        try {
 | 
			
		||||
                            id = UUID.fromString(idNode.asText());
 | 
			
		||||
                        } catch (Exception ignored) {}
 | 
			
		||||
                        name = nameNode.asText();
 | 
			
		||||
                    }
 | 
			
		||||
                    if (id != null && name != null) {
 | 
			
		||||
                        entities.add(new EntityInfo(id, EntityType.WIDGETS_BUNDLE.name(), name));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return entities;
 | 
			
		||||
            } else {
 | 
			
		||||
                return Collections.emptyList();
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception ex) {
 | 
			
		||||
            String exception = String.format("Failed to convert String to %s list: %s", getEntityType(), ex.getMessage());
 | 
			
		||||
            throw new RuntimeException(exception, ex);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,29 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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.dao.util.mapping;
 | 
			
		||||
 | 
			
		||||
import jakarta.persistence.Converter;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
 | 
			
		||||
@Converter
 | 
			
		||||
public class WidgetBundleEntityInfosConverter extends AbstractEntityInfosConverter {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected EntityType getEntityType() {
 | 
			
		||||
        return EntityType.WIDGETS_BUNDLE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user