Merge pull request #6654 from ViacheslavKlimov/vc-improvements
Widgets Bundles VC
This commit is contained in:
commit
666dd12c1b
@ -26,6 +26,8 @@ ALTER TABLE dashboard
|
|||||||
ADD COLUMN IF NOT EXISTS external_id UUID;
|
ADD COLUMN IF NOT EXISTS external_id UUID;
|
||||||
ALTER TABLE customer
|
ALTER TABLE customer
|
||||||
ADD COLUMN IF NOT EXISTS external_id UUID;
|
ADD COLUMN IF NOT EXISTS external_id UUID;
|
||||||
|
ALTER TABLE widgets_bundle
|
||||||
|
ADD COLUMN IF NOT EXISTS external_id UUID;
|
||||||
|
|
||||||
ALTER TABLE admin_settings
|
ALTER TABLE admin_settings
|
||||||
ADD COLUMN IF NOT EXISTS tenant_id uuid NOT NULL DEFAULT '13814000-1dd2-11b2-8080-808080808080';
|
ADD COLUMN IF NOT EXISTS tenant_id uuid NOT NULL DEFAULT '13814000-1dd2-11b2-8080-808080808080';
|
||||||
|
|||||||
@ -310,7 +310,7 @@ public class EntitiesVersionControlController extends BaseController {
|
|||||||
public DeferredResult<VersionLoadResult> loadEntitiesVersion(@RequestBody VersionLoadRequest request) throws ThingsboardException {
|
public DeferredResult<VersionLoadResult> loadEntitiesVersion(@RequestBody VersionLoadRequest request) throws ThingsboardException {
|
||||||
SecurityUser user = getCurrentUser();
|
SecurityUser user = getCurrentUser();
|
||||||
try {
|
try {
|
||||||
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ);
|
accessControlService.checkPermission(user, Resource.VERSION_CONTROL, Operation.READ);
|
||||||
return wrapFuture(versionControlService.loadEntitiesVersion(user, request));
|
return wrapFuture(versionControlService.loadEntitiesVersion(user, request));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw handleException(e);
|
throw handleException(e);
|
||||||
|
|||||||
@ -47,7 +47,6 @@ import java.util.Map;
|
|||||||
@TbCoreComponent
|
@TbCoreComponent
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class DefaultEntitiesExportImportService implements EntitiesExportImportService {
|
public class DefaultEntitiesExportImportService implements EntitiesExportImportService {
|
||||||
|
|
||||||
private final Map<EntityType, EntityExportService<?, ?, ?>> exportServices = new HashMap<>();
|
private final Map<EntityType, EntityExportService<?, ?, ?>> exportServices = new HashMap<>();
|
||||||
@ -57,7 +56,8 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
|
|||||||
|
|
||||||
protected static final List<EntityType> SUPPORTED_ENTITY_TYPES = List.of(
|
protected static final List<EntityType> SUPPORTED_ENTITY_TYPES = List.of(
|
||||||
EntityType.CUSTOMER, EntityType.ASSET, EntityType.RULE_CHAIN,
|
EntityType.CUSTOMER, EntityType.ASSET, EntityType.RULE_CHAIN,
|
||||||
EntityType.DASHBOARD, EntityType.DEVICE_PROFILE, EntityType.DEVICE
|
EntityType.DASHBOARD, EntityType.DEVICE_PROFILE, EntityType.DEVICE,
|
||||||
|
EntityType.WIDGETS_BUNDLE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -18,28 +18,32 @@ package org.thingsboard.server.service.sync.ie.exporting;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DataAccessException;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
import org.thingsboard.server.common.data.ExportableEntity;
|
import org.thingsboard.server.common.data.ExportableEntity;
|
||||||
import org.thingsboard.server.common.data.HasTenantId;
|
import org.thingsboard.server.common.data.HasTenantId;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
|
import org.thingsboard.server.common.data.id.AssetId;
|
||||||
import org.thingsboard.server.common.data.id.CustomerId;
|
import org.thingsboard.server.common.data.id.CustomerId;
|
||||||
|
import org.thingsboard.server.common.data.id.DashboardId;
|
||||||
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||||
import org.thingsboard.server.common.data.id.EntityId;
|
import org.thingsboard.server.common.data.id.EntityId;
|
||||||
import org.thingsboard.server.common.data.id.HasId;
|
import org.thingsboard.server.common.data.id.HasId;
|
||||||
|
import org.thingsboard.server.common.data.id.RuleChainId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.data.id.WidgetsBundleId;
|
||||||
import org.thingsboard.server.common.data.page.PageData;
|
import org.thingsboard.server.common.data.page.PageData;
|
||||||
import org.thingsboard.server.common.data.page.PageLink;
|
import org.thingsboard.server.common.data.page.PageLink;
|
||||||
import org.thingsboard.server.common.data.query.EntityData;
|
|
||||||
import org.thingsboard.server.common.data.query.EntityDataPageLink;
|
|
||||||
import org.thingsboard.server.common.data.query.EntityDataQuery;
|
|
||||||
import org.thingsboard.server.common.data.query.EntityDataSortOrder;
|
|
||||||
import org.thingsboard.server.common.data.query.EntityFilter;
|
|
||||||
import org.thingsboard.server.common.data.query.EntityKey;
|
|
||||||
import org.thingsboard.server.common.data.query.EntityKeyType;
|
|
||||||
import org.thingsboard.server.dao.Dao;
|
import org.thingsboard.server.dao.Dao;
|
||||||
import org.thingsboard.server.dao.ExportableEntityDao;
|
import org.thingsboard.server.dao.ExportableEntityDao;
|
||||||
import org.thingsboard.server.dao.entity.EntityService;
|
import org.thingsboard.server.dao.asset.AssetService;
|
||||||
|
import org.thingsboard.server.dao.customer.CustomerService;
|
||||||
|
import org.thingsboard.server.dao.dashboard.DashboardService;
|
||||||
|
import org.thingsboard.server.dao.device.DeviceProfileService;
|
||||||
|
import org.thingsboard.server.dao.device.DeviceService;
|
||||||
|
import org.thingsboard.server.dao.rule.RuleChainService;
|
||||||
|
import org.thingsboard.server.dao.widget.WidgetsBundleService;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||||
import org.thingsboard.server.service.security.permission.AccessControlService;
|
import org.thingsboard.server.service.security.permission.AccessControlService;
|
||||||
@ -47,13 +51,9 @@ import org.thingsboard.server.service.security.permission.Operation;
|
|||||||
import org.thingsboard.server.service.security.permission.Resource;
|
import org.thingsboard.server.service.security.permission.Resource;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.CREATED_TIME;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@TbCoreComponent
|
@TbCoreComponent
|
||||||
@ -62,8 +62,8 @@ import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.CREATED_TIME
|
|||||||
public class DefaultExportableEntitiesService implements ExportableEntitiesService {
|
public class DefaultExportableEntitiesService implements ExportableEntitiesService {
|
||||||
|
|
||||||
private final Map<EntityType, Dao<?>> daos = new HashMap<>();
|
private final Map<EntityType, Dao<?>> daos = new HashMap<>();
|
||||||
|
private final Map<EntityType, BiConsumer<TenantId, EntityId>> removers = new HashMap<>();
|
||||||
|
|
||||||
private final EntityService entityService;
|
|
||||||
private final AccessControlService accessControlService;
|
private final AccessControlService accessControlService;
|
||||||
|
|
||||||
|
|
||||||
@ -141,37 +141,14 @@ public class DefaultExportableEntitiesService implements ExportableEntitiesServi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<EntityId> findEntitiesByFilter(TenantId tenantId, CustomerId customerId, EntityFilter filter, int page, int pageSize) {
|
|
||||||
EntityDataPageLink pageLink = new EntityDataPageLink();
|
|
||||||
pageLink.setPage(page);
|
|
||||||
pageLink.setPageSize(pageSize);
|
|
||||||
EntityKey sortProperty = new EntityKey(EntityKeyType.ENTITY_FIELD, CREATED_TIME);
|
|
||||||
pageLink.setSortOrder(new EntityDataSortOrder(sortProperty, EntityDataSortOrder.Direction.DESC));
|
|
||||||
|
|
||||||
EntityDataQuery query = new EntityDataQuery(filter, pageLink, List.of(sortProperty), Collections.emptyList(), Collections.emptyList());
|
|
||||||
return findEntitiesByQuery(tenantId, customerId, query);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<EntityId> findEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query) {
|
|
||||||
try {
|
|
||||||
return entityService.findEntityDataByQuery(tenantId, customerId, query).getData().stream()
|
|
||||||
.map(EntityData::getEntityId)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
} catch (DataAccessException e) {
|
|
||||||
log.error("Failed to find entity data by query: {}", e.getMessage());
|
|
||||||
throw new IllegalArgumentException("Entity filter cannot be processed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <I extends EntityId> void deleteByTenantIdAndId(TenantId tenantId, I id) {
|
public <I extends EntityId> void removeById(TenantId tenantId, I id) {
|
||||||
EntityType entityType = id.getEntityType();
|
EntityType entityType = id.getEntityType();
|
||||||
Dao<Object> dao = getDao(entityType);
|
BiConsumer<TenantId, EntityId> entityRemover = removers.get(entityType);
|
||||||
if (dao == null) {
|
if (entityRemover == null) {
|
||||||
throw new IllegalArgumentException("Unsupported entity type " + entityType);
|
throw new IllegalArgumentException("Unsupported entity type " + entityType);
|
||||||
}
|
}
|
||||||
|
entityRemover.accept(tenantId, id);
|
||||||
dao.removeById(tenantId, id.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -205,4 +182,31 @@ public class DefaultExportableEntitiesService implements ExportableEntitiesServi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private void setRemovers(CustomerService customerService, AssetService assetService, RuleChainService ruleChainService,
|
||||||
|
DashboardService dashboardService, DeviceProfileService deviceProfileService,
|
||||||
|
DeviceService deviceService, WidgetsBundleService widgetsBundleService) {
|
||||||
|
removers.put(EntityType.CUSTOMER, (tenantId, entityId) -> {
|
||||||
|
customerService.deleteCustomer(tenantId, (CustomerId) entityId);
|
||||||
|
});
|
||||||
|
removers.put(EntityType.ASSET, (tenantId, entityId) -> {
|
||||||
|
assetService.deleteAsset(tenantId, (AssetId) entityId);
|
||||||
|
});
|
||||||
|
removers.put(EntityType.RULE_CHAIN, (tenantId, entityId) -> {
|
||||||
|
ruleChainService.deleteRuleChainById(tenantId, (RuleChainId) entityId);
|
||||||
|
});
|
||||||
|
removers.put(EntityType.DASHBOARD, (tenantId, entityId) -> {
|
||||||
|
dashboardService.deleteDashboard(tenantId, (DashboardId) entityId);
|
||||||
|
});
|
||||||
|
removers.put(EntityType.DEVICE_PROFILE, (tenantId, entityId) -> {
|
||||||
|
deviceProfileService.deleteDeviceProfile(tenantId, (DeviceProfileId) entityId);
|
||||||
|
});
|
||||||
|
removers.put(EntityType.DEVICE, (tenantId, entityId) -> {
|
||||||
|
deviceService.deleteDevice(tenantId, (DeviceId) entityId);
|
||||||
|
});
|
||||||
|
removers.put(EntityType.WIDGETS_BUNDLE, (tenantId, entityId) -> {
|
||||||
|
widgetsBundleService.deleteWidgetsBundle(tenantId, (WidgetsBundleId) entityId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,7 @@ public interface ExportableEntitiesService {
|
|||||||
|
|
||||||
<E extends ExportableEntity<I>, I extends EntityId> PageData<E> findEntitiesByTenantId(TenantId tenantId, EntityType entityType, PageLink pageLink);
|
<E extends ExportableEntity<I>, I extends EntityId> PageData<E> findEntitiesByTenantId(TenantId tenantId, EntityType entityType, PageLink pageLink);
|
||||||
|
|
||||||
<I extends EntityId> void deleteByTenantIdAndId(TenantId tenantId, I id);
|
<I extends EntityId> void removeById(TenantId tenantId, I id);
|
||||||
|
|
||||||
|
|
||||||
void checkPermission(SecurityUser user, HasId<? extends EntityId> entity, EntityType entityType, Operation operation) throws ThingsboardException;
|
void checkPermission(SecurityUser user, HasId<? extends EntityId> entity, EntityType entityType, Operation operation) throws ThingsboardException;
|
||||||
|
|||||||
@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 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.service.sync.ie.exporting.impl;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.data.id.WidgetsBundleId;
|
||||||
|
import org.thingsboard.server.common.data.sync.ie.EntityExportSettings;
|
||||||
|
import org.thingsboard.server.common.data.sync.ie.WidgetsBundleExportData;
|
||||||
|
import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
|
||||||
|
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
||||||
|
import org.thingsboard.server.dao.widget.WidgetTypeService;
|
||||||
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@TbCoreComponent
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WidgetsBundleExportService extends BaseEntityExportService<WidgetsBundleId, WidgetsBundle, WidgetsBundleExportData> {
|
||||||
|
|
||||||
|
private final WidgetTypeService widgetTypeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setRelatedEntities(TenantId tenantId, WidgetsBundle widgetsBundle, WidgetsBundleExportData exportData, EntityExportSettings settings) {
|
||||||
|
if (widgetsBundle.getTenantId() == null || widgetsBundle.getTenantId().isNullUid()) {
|
||||||
|
throw new IllegalArgumentException("Export of system Widget Bundles is not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WidgetTypeDetails> widgets = widgetTypeService.findWidgetTypesDetailsByTenantIdAndBundleAlias(tenantId, widgetsBundle.getAlias());
|
||||||
|
exportData.setWidgets(widgets);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected WidgetsBundleExportData newExportData() {
|
||||||
|
return new WidgetsBundleExportData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<EntityType> getSupportedEntityTypes() {
|
||||||
|
return Set.of(EntityType.WIDGETS_BUNDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -48,6 +48,7 @@ import org.thingsboard.server.common.data.sync.ie.EntityImportResult;
|
|||||||
import org.thingsboard.server.common.data.sync.ie.EntityImportSettings;
|
import org.thingsboard.server.common.data.sync.ie.EntityImportSettings;
|
||||||
import org.thingsboard.server.dao.relation.RelationService;
|
import org.thingsboard.server.dao.relation.RelationService;
|
||||||
import org.thingsboard.server.service.action.EntityActionService;
|
import org.thingsboard.server.service.action.EntityActionService;
|
||||||
|
import org.thingsboard.server.service.entitiy.TbNotificationEntityService;
|
||||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||||
import org.thingsboard.server.service.security.permission.Operation;
|
import org.thingsboard.server.service.security.permission.Operation;
|
||||||
import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService;
|
import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService;
|
||||||
@ -75,6 +76,8 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
|||||||
protected EntityActionService entityActionService;
|
protected EntityActionService entityActionService;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected TbClusterService clusterService;
|
protected TbClusterService clusterService;
|
||||||
|
@Autowired
|
||||||
|
protected TbNotificationEntityService entityNotificationService;
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 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.service.sync.ie.importing.impl;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||||
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.data.id.WidgetsBundleId;
|
||||||
|
import org.thingsboard.server.common.data.sync.ie.EntityImportSettings;
|
||||||
|
import org.thingsboard.server.common.data.sync.ie.WidgetsBundleExportData;
|
||||||
|
import org.thingsboard.server.common.data.widget.BaseWidgetType;
|
||||||
|
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.widget.WidgetTypeService;
|
||||||
|
import org.thingsboard.server.dao.widget.WidgetsBundleService;
|
||||||
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@TbCoreComponent
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WidgetsBundleImportService extends BaseEntityImportService<WidgetsBundleId, WidgetsBundle, WidgetsBundleExportData> {
|
||||||
|
|
||||||
|
private final WidgetsBundleService widgetsBundleService;
|
||||||
|
private final WidgetTypeService widgetTypeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setOwner(TenantId tenantId, WidgetsBundle widgetsBundle, IdProvider idProvider) {
|
||||||
|
widgetsBundle.setTenantId(tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected WidgetsBundle prepareAndSave(TenantId tenantId, WidgetsBundle widgetsBundle, WidgetsBundleExportData exportData, IdProvider idProvider, EntityImportSettings importSettings) {
|
||||||
|
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
|
||||||
|
if (widgetsBundle.getId() == null) {
|
||||||
|
for (WidgetTypeDetails widget : exportData.getWidgets()) {
|
||||||
|
widget.setId(null);
|
||||||
|
widget.setTenantId(tenantId);
|
||||||
|
widget.setBundleAlias(savedWidgetsBundle.getAlias());
|
||||||
|
widgetTypeService.saveWidgetType(widget);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Map<String, WidgetTypeInfo> existingWidgets = widgetTypeService.findWidgetTypesInfosByTenantIdAndBundleAlias(tenantId, savedWidgetsBundle.getAlias()).stream()
|
||||||
|
.collect(Collectors.toMap(BaseWidgetType::getAlias, w -> w));
|
||||||
|
for (WidgetTypeDetails widget : exportData.getWidgets()) {
|
||||||
|
WidgetTypeInfo existingWidget;
|
||||||
|
if ((existingWidget = existingWidgets.remove(widget.getAlias())) != null) {
|
||||||
|
widget.setId(existingWidget.getId());
|
||||||
|
widget.setCreatedTime(existingWidget.getCreatedTime());
|
||||||
|
} else {
|
||||||
|
widget.setId(null);
|
||||||
|
}
|
||||||
|
widget.setTenantId(tenantId);
|
||||||
|
widget.setBundleAlias(savedWidgetsBundle.getAlias());
|
||||||
|
widgetTypeService.saveWidgetType(widget);
|
||||||
|
}
|
||||||
|
existingWidgets.values().stream()
|
||||||
|
.map(BaseWidgetType::getId)
|
||||||
|
.forEach(widgetTypeId -> widgetTypeService.deleteWidgetType(tenantId, widgetTypeId));
|
||||||
|
}
|
||||||
|
return savedWidgetsBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onEntitySaved(SecurityUser user, WidgetsBundle savedWidgetsBundle, WidgetsBundle oldWidgetsBundle) throws ThingsboardException {
|
||||||
|
super.onEntitySaved(user, savedWidgetsBundle, oldWidgetsBundle);
|
||||||
|
entityNotificationService.notifySendMsgToEdgeService(user.getTenantId(), savedWidgetsBundle.getId(),
|
||||||
|
oldWidgetsBundle == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityType getEntityType() {
|
||||||
|
return EntityType.WIDGETS_BUNDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -352,7 +352,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
|||||||
} catch (ThingsboardException e) {
|
} catch (ThingsboardException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
exportableEntitiesService.deleteByTenantIdAndId(user.getTenantId(), entity.getId());
|
exportableEntitiesService.removeById(user.getTenantId(), entity.getId());
|
||||||
|
|
||||||
sendEventsCallbacks.add(() -> {
|
sendEventsCallbacks.add(() -> {
|
||||||
entityNotificationService.notifyDeleteEntity(user.getTenantId(), entity.getId(),
|
entityNotificationService.notifyDeleteEntity(user.getTenantId(), entity.getId(),
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.Device;
|
|||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.asset.Asset;
|
import org.thingsboard.server.common.data.asset.Asset;
|
||||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||||
|
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@ -41,7 +42,8 @@ import java.lang.annotation.Target;
|
|||||||
@Type(name = "DEVICE_PROFILE", value = DeviceProfile.class),
|
@Type(name = "DEVICE_PROFILE", value = DeviceProfile.class),
|
||||||
@Type(name = "ASSET", value = Asset.class),
|
@Type(name = "ASSET", value = Asset.class),
|
||||||
@Type(name = "DASHBOARD", value = Dashboard.class),
|
@Type(name = "DASHBOARD", value = Dashboard.class),
|
||||||
@Type(name = "CUSTOMER", value = Customer.class)
|
@Type(name = "CUSTOMER", value = Customer.class),
|
||||||
|
@Type(name = "WIDGETS_BUNDLE", value = WidgetsBundle.class)
|
||||||
})
|
})
|
||||||
public @interface JsonTbEntity {
|
public @interface JsonTbEntity {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
@ -31,7 +30,6 @@ import org.thingsboard.server.common.data.id.EntityId;
|
|||||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||||
import org.thingsboard.server.common.data.sync.JsonTbEntity;
|
import org.thingsboard.server.common.data.sync.JsonTbEntity;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -40,7 +38,8 @@ import java.util.Map;
|
|||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType", include = As.EXISTING_PROPERTY, visible = true, defaultImpl = EntityExportData.class)
|
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType", include = As.EXISTING_PROPERTY, visible = true, defaultImpl = EntityExportData.class)
|
||||||
@JsonSubTypes({
|
@JsonSubTypes({
|
||||||
@Type(name = "DEVICE", value = DeviceExportData.class),
|
@Type(name = "DEVICE", value = DeviceExportData.class),
|
||||||
@Type(name = "RULE_CHAIN", value = RuleChainExportData.class)
|
@Type(name = "RULE_CHAIN", value = RuleChainExportData.class),
|
||||||
|
@Type(name = "WIDGETS_BUNDLE", value = WidgetsBundleExportData.class)
|
||||||
})
|
})
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 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.sync.ie;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.thingsboard.server.common.data.widget.BaseWidgetType;
|
||||||
|
import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
|
||||||
|
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class WidgetsBundleExportData extends EntityExportData<WidgetsBundle> {
|
||||||
|
|
||||||
|
@JsonProperty(index = 3)
|
||||||
|
private List<WidgetTypeDetails> widgets;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityExportData<WidgetsBundle> sort() {
|
||||||
|
super.sort();
|
||||||
|
widgets.sort(Comparator.comparing(BaseWidgetType::getAlias));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -15,10 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.common.data.widget;
|
package org.thingsboard.server.common.data.widget;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.thingsboard.server.common.data.ExportableEntity;
|
||||||
import org.thingsboard.server.common.data.HasTenantId;
|
import org.thingsboard.server.common.data.HasTenantId;
|
||||||
import org.thingsboard.server.common.data.SearchTextBased;
|
import org.thingsboard.server.common.data.SearchTextBased;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
@ -27,7 +30,8 @@ import org.thingsboard.server.common.data.validation.Length;
|
|||||||
import org.thingsboard.server.common.data.validation.NoXss;
|
import org.thingsboard.server.common.data.validation.NoXss;
|
||||||
|
|
||||||
@ApiModel
|
@ApiModel
|
||||||
public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements HasTenantId {
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements HasTenantId, ExportableEntity<WidgetsBundleId> {
|
||||||
|
|
||||||
private static final long serialVersionUID = -7627368878362410489L;
|
private static final long serialVersionUID = -7627368878362410489L;
|
||||||
|
|
||||||
@ -63,6 +67,10 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H
|
|||||||
@ApiModelProperty(position = 7, value = "Description", readOnly = true)
|
@ApiModelProperty(position = 7, value = "Description", readOnly = true)
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private WidgetsBundleId externalId;
|
||||||
|
|
||||||
public WidgetsBundle() {
|
public WidgetsBundle() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -78,6 +86,7 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H
|
|||||||
this.title = widgetsBundle.getTitle();
|
this.title = widgetsBundle.getTitle();
|
||||||
this.image = widgetsBundle.getImage();
|
this.image = widgetsBundle.getImage();
|
||||||
this.description = widgetsBundle.getDescription();
|
this.description = widgetsBundle.getDescription();
|
||||||
|
this.externalId = widgetsBundle.getExternalId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiModelProperty(position = 1, value = "JSON object with the Widget Bundle Id. " +
|
@ApiModelProperty(position = 1, value = "JSON object with the Widget Bundle Id. " +
|
||||||
@ -100,31 +109,10 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H
|
|||||||
return getTitle();
|
return getTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public String getName() {
|
||||||
int result = super.hashCode();
|
return title;
|
||||||
result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
|
|
||||||
result = 31 * result + (alias != null ? alias.hashCode() : 0);
|
|
||||||
result = 31 * result + (title != null ? title.hashCode() : 0);
|
|
||||||
result = 31 * result + (image != null ? image.hashCode() : 0);
|
|
||||||
result = 31 * result + (description != null ? description.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
|
|
||||||
WidgetsBundle that = (WidgetsBundle) o;
|
|
||||||
|
|
||||||
if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false;
|
|
||||||
if (alias != null ? !alias.equals(that.alias) : that.alias != null) return false;
|
|
||||||
if (title != null ? !title.equals(that.title) : that.title != null) return false;
|
|
||||||
if (image != null ? !image.equals(that.image) : that.image != null) return false;
|
|
||||||
if (description != null ? !description.equals(that.description) : that.description != null) return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -133,7 +121,6 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H
|
|||||||
sb.append("tenantId=").append(tenantId);
|
sb.append("tenantId=").append(tenantId);
|
||||||
sb.append(", alias='").append(alias).append('\'');
|
sb.append(", alias='").append(alias).append('\'');
|
||||||
sb.append(", title='").append(title).append('\'');
|
sb.append(", title='").append(title).append('\'');
|
||||||
sb.append(", image='").append(image).append('\'');
|
|
||||||
sb.append(", description='").append(description).append('\'');
|
sb.append(", description='").append(description).append('\'');
|
||||||
sb.append('}');
|
sb.append('}');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|||||||
@ -54,6 +54,9 @@ public final class WidgetsBundleEntity extends BaseSqlEntity<WidgetsBundle> impl
|
|||||||
@Column(name = ModelConstants.WIDGETS_BUNDLE_DESCRIPTION)
|
@Column(name = ModelConstants.WIDGETS_BUNDLE_DESCRIPTION)
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
@Column(name = ModelConstants.EXTERNAL_ID_PROPERTY)
|
||||||
|
private UUID externalId;
|
||||||
|
|
||||||
public WidgetsBundleEntity() {
|
public WidgetsBundleEntity() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -70,6 +73,9 @@ public final class WidgetsBundleEntity extends BaseSqlEntity<WidgetsBundle> impl
|
|||||||
this.title = widgetsBundle.getTitle();
|
this.title = widgetsBundle.getTitle();
|
||||||
this.image = widgetsBundle.getImage();
|
this.image = widgetsBundle.getImage();
|
||||||
this.description = widgetsBundle.getDescription();
|
this.description = widgetsBundle.getDescription();
|
||||||
|
if (widgetsBundle.getExternalId() != null) {
|
||||||
|
this.externalId = widgetsBundle.getExternalId().getId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -93,6 +99,9 @@ public final class WidgetsBundleEntity extends BaseSqlEntity<WidgetsBundle> impl
|
|||||||
widgetsBundle.setTitle(title);
|
widgetsBundle.setTitle(title);
|
||||||
widgetsBundle.setImage(image);
|
widgetsBundle.setImage(image);
|
||||||
widgetsBundle.setDescription(description);
|
widgetsBundle.setDescription(description);
|
||||||
|
if (externalId != null) {
|
||||||
|
widgetsBundle.setExternalId(new WidgetsBundleId(externalId));
|
||||||
|
}
|
||||||
return widgetsBundle;
|
return widgetsBundle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,4 +93,19 @@ public class JpaWidgetsBundleDao extends JpaAbstractSearchTextDao<WidgetsBundleE
|
|||||||
return EntityType.WIDGETS_BUNDLE;
|
return EntityType.WIDGETS_BUNDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WidgetsBundle findByTenantIdAndExternalId(UUID tenantId, UUID externalId) {
|
||||||
|
return DaoUtil.getData(widgetsBundleRepository.findByTenantIdAndExternalId(tenantId, externalId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WidgetsBundle findByTenantIdAndName(UUID tenantId, String name) {
|
||||||
|
return DaoUtil.getData(widgetsBundleRepository.findFirstByTenantIdAndTitle(tenantId, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<WidgetsBundle> findByTenantId(UUID tenantId, PageLink pageLink) {
|
||||||
|
return findTenantWidgetsBundlesByTenantId(tenantId, pageLink);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.thingsboard.server.dao.ExportableEntityRepository;
|
||||||
import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity;
|
import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -27,7 +28,7 @@ import java.util.UUID;
|
|||||||
/**
|
/**
|
||||||
* Created by Valerii Sosliuk on 4/23/2017.
|
* Created by Valerii Sosliuk on 4/23/2017.
|
||||||
*/
|
*/
|
||||||
public interface WidgetsBundleRepository extends JpaRepository<WidgetsBundleEntity, UUID> {
|
public interface WidgetsBundleRepository extends JpaRepository<WidgetsBundleEntity, UUID>, ExportableEntityRepository<WidgetsBundleEntity> {
|
||||||
|
|
||||||
WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias);
|
WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias);
|
||||||
|
|
||||||
@ -49,4 +50,7 @@ public interface WidgetsBundleRepository extends JpaRepository<WidgetsBundleEnti
|
|||||||
@Param("nullTenantId") UUID nullTenantId,
|
@Param("nullTenantId") UUID nullTenantId,
|
||||||
@Param("textSearch") String textSearch,
|
@Param("textSearch") String textSearch,
|
||||||
Pageable pageable);
|
Pageable pageable);
|
||||||
|
|
||||||
|
WidgetsBundleEntity findFirstByTenantIdAndTitle(UUID tenantId, String title);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,17 +16,19 @@
|
|||||||
package org.thingsboard.server.dao.widget;
|
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.WidgetsBundleId;
|
||||||
import org.thingsboard.server.common.data.page.PageData;
|
import org.thingsboard.server.common.data.page.PageData;
|
||||||
import org.thingsboard.server.common.data.page.PageLink;
|
import org.thingsboard.server.common.data.page.PageLink;
|
||||||
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
||||||
import org.thingsboard.server.dao.Dao;
|
import org.thingsboard.server.dao.Dao;
|
||||||
|
import org.thingsboard.server.dao.ExportableEntityDao;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Interface WidgetsBundleDao.
|
* The Interface WidgetsBundleDao.
|
||||||
*/
|
*/
|
||||||
public interface WidgetsBundleDao extends Dao<WidgetsBundle> {
|
public interface WidgetsBundleDao extends Dao<WidgetsBundle>, ExportableEntityDao<WidgetsBundle> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save or update widgets bundle object
|
* Save or update widgets bundle object
|
||||||
|
|||||||
@ -423,7 +423,8 @@ CREATE TABLE IF NOT EXISTS widgets_bundle (
|
|||||||
tenant_id uuid,
|
tenant_id uuid,
|
||||||
title varchar(255),
|
title varchar(255),
|
||||||
image varchar(1000000),
|
image varchar(1000000),
|
||||||
description varchar(255)
|
description varchar(255),
|
||||||
|
external_id uuid
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS entity_view (
|
CREATE TABLE IF NOT EXISTS entity_view (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user