Minor improvements
This commit is contained in:
parent
c04a0ff3a6
commit
119430ff9a
@ -83,7 +83,7 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
|
|||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
public List<EntityImportResult<?>> importEntities(SecurityUser user, List<EntityExportData<?>> exportDataList, EntityImportSettings importSettings) throws ThingsboardException {
|
public List<EntityImportResult<?>> importEntities(SecurityUser user, List<EntityExportData<?>> exportDataList, EntityImportSettings importSettings) throws ThingsboardException {
|
||||||
exportDataList.sort(Comparator.comparing(exportData -> SUPPORTED_ENTITY_TYPES.indexOf(exportData.getEntityType())));
|
fixOrder(exportDataList);
|
||||||
List<EntityImportResult<?>> importResults = new ArrayList<>();
|
List<EntityImportResult<?>> importResults = new ArrayList<>();
|
||||||
|
|
||||||
for (EntityExportData exportData : exportDataList) {
|
for (EntityExportData exportData : exportDataList) {
|
||||||
@ -101,6 +101,10 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
|
|||||||
return importResults;
|
return importResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fixOrder(List<EntityExportData<?>> exportDataList) {
|
||||||
|
exportDataList.sort(Comparator.comparing(exportData -> SUPPORTED_ENTITY_TYPES.indexOf(exportData.getEntityType())));
|
||||||
|
}
|
||||||
|
|
||||||
private <E extends ExportableEntity<I>, I extends EntityId> EntityImportResult<E> importEntity(SecurityUser user, EntityExportData<E> exportData, EntityImportSettings importSettings) throws ThingsboardException {
|
private <E extends ExportableEntity<I>, I extends EntityId> EntityImportResult<E> importEntity(SecurityUser user, EntityExportData<E> exportData, EntityImportSettings importSettings) throws ThingsboardException {
|
||||||
if (exportData.getEntity() == null || exportData.getEntity().getId() == null) {
|
if (exportData.getEntity() == null || exportData.getEntity().getId() == null) {
|
||||||
throw new DataValidationException("Invalid entity data");
|
throw new DataValidationException("Invalid entity data");
|
||||||
@ -137,7 +141,11 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
|
|||||||
@Override
|
@Override
|
||||||
public <E extends ExportableEntity<I>, I extends EntityId> E findEntityByTenantIdAndName(TenantId tenantId, EntityType entityType, String name) {
|
public <E extends ExportableEntity<I>, I extends EntityId> E findEntityByTenantIdAndName(TenantId tenantId, EntityType entityType, String name) {
|
||||||
ExportableEntityDao<E> dao = (ExportableEntityDao<E>) getDao(entityType);
|
ExportableEntityDao<E> dao = (ExportableEntityDao<E>) getDao(entityType);
|
||||||
return dao.findFirstByTenantIdAndName(tenantId.getId(), name);
|
try {
|
||||||
|
return dao.findByTenantIdAndName(tenantId.getId(), name);
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -158,7 +158,7 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private E findExistingEntity(TenantId tenantId, E entity, EntityImportSettings importSettings) {
|
protected E findExistingEntity(TenantId tenantId, E entity, EntityImportSettings importSettings) {
|
||||||
return (E) Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndExternalId(tenantId, entity.getId()))
|
return (E) Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndExternalId(tenantId, entity.getId()))
|
||||||
.or(() -> Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndId(tenantId, entity.getId())))
|
.or(() -> Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndId(tenantId, entity.getId())))
|
||||||
.or(() -> {
|
.or(() -> {
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import org.thingsboard.server.dao.sql.query.DefaultEntityQueryRepository;
|
|||||||
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.sync.exporting.data.EntityExportData;
|
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
|
||||||
|
import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -58,6 +59,15 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
|
|||||||
dashboard.setTenantId(tenantId);
|
dashboard.setTenantId(tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Dashboard findExistingEntity(TenantId tenantId, Dashboard dashboard, EntityImportSettings importSettings) {
|
||||||
|
Dashboard existingDashboard = super.findExistingEntity(tenantId, dashboard, importSettings);
|
||||||
|
if (existingDashboard == null && importSettings.isFindExistingByName()) {
|
||||||
|
existingDashboard = dashboardService.findTenantDashboardsByTitle(tenantId, dashboard.getName()).stream().findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
return existingDashboard;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Dashboard prepareAndSave(TenantId tenantId, Dashboard dashboard, EntityExportData<Dashboard> exportData, NewIdProvider idProvider) {
|
protected Dashboard prepareAndSave(TenantId tenantId, Dashboard dashboard, EntityExportData<Dashboard> exportData, NewIdProvider idProvider) {
|
||||||
Optional.ofNullable(dashboard.getConfiguration())
|
Optional.ofNullable(dashboard.getConfiguration())
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import org.thingsboard.server.dao.rule.RuleChainService;
|
|||||||
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.sync.exporting.data.RuleChainExportData;
|
import org.thingsboard.server.service.sync.exporting.data.RuleChainExportData;
|
||||||
|
import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -50,6 +51,15 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
|
|||||||
ruleChain.setTenantId(tenantId);
|
ruleChain.setTenantId(tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RuleChain findExistingEntity(TenantId tenantId, RuleChain ruleChain, EntityImportSettings importSettings) {
|
||||||
|
RuleChain existingRuleChain = super.findExistingEntity(tenantId, ruleChain, importSettings);
|
||||||
|
if (existingRuleChain == null && importSettings.isFindExistingByName()) {
|
||||||
|
existingRuleChain = ruleChainService.findTenantRuleChainsByTypeAndName(tenantId, ruleChain.getType(), ruleChain.getName()).stream().findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
return existingRuleChain;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RuleChain prepareAndSave(TenantId tenantId, RuleChain ruleChain, RuleChainExportData exportData, NewIdProvider idProvider) {
|
protected RuleChain prepareAndSave(TenantId tenantId, RuleChain ruleChain, RuleChainExportData exportData, NewIdProvider idProvider) {
|
||||||
RuleChainMetaData metaData = exportData.getMetaData();
|
RuleChainMetaData metaData = exportData.getMetaData();
|
||||||
|
|||||||
@ -25,6 +25,8 @@ import org.thingsboard.server.common.data.id.TenantId;
|
|||||||
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 java.util.List;
|
||||||
|
|
||||||
public interface DashboardService {
|
public interface DashboardService {
|
||||||
|
|
||||||
Dashboard findDashboardById(TenantId tenantId, DashboardId dashboardId);
|
Dashboard findDashboardById(TenantId tenantId, DashboardId dashboardId);
|
||||||
@ -64,4 +66,7 @@ public interface DashboardService {
|
|||||||
PageData<DashboardInfo> findDashboardsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, PageLink pageLink);
|
PageData<DashboardInfo> findDashboardsByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, PageLink pageLink);
|
||||||
|
|
||||||
DashboardInfo findFirstDashboardInfoByTenantIdAndName(TenantId tenantId, String name);
|
DashboardInfo findFirstDashboardInfoByTenantIdAndName(TenantId tenantId, String name);
|
||||||
|
|
||||||
|
List<Dashboard> findTenantDashboardsByTitle(TenantId tenantId, String title);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
|
|||||||
import org.thingsboard.server.common.data.rule.RuleChainUpdateResult;
|
import org.thingsboard.server.common.data.rule.RuleChainUpdateResult;
|
||||||
import org.thingsboard.server.common.data.rule.RuleNode;
|
import org.thingsboard.server.common.data.rule.RuleNode;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,6 +66,8 @@ public interface RuleChainService {
|
|||||||
|
|
||||||
PageData<RuleChain> findTenantRuleChainsByType(TenantId tenantId, RuleChainType type, PageLink pageLink);
|
PageData<RuleChain> findTenantRuleChainsByType(TenantId tenantId, RuleChainType type, PageLink pageLink);
|
||||||
|
|
||||||
|
Collection<RuleChain> findTenantRuleChainsByTypeAndName(TenantId tenantId, RuleChainType type, String name);
|
||||||
|
|
||||||
void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId);
|
void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId);
|
||||||
|
|
||||||
void deleteRuleChainsByTenantId(TenantId tenantId);
|
void deleteRuleChainsByTenantId(TenantId tenantId);
|
||||||
|
|||||||
@ -20,7 +20,6 @@ import org.thingsboard.server.common.data.id.HasId;
|
|||||||
|
|
||||||
public interface ExportableEntity<I extends EntityId> extends HasId<I>, HasName {
|
public interface ExportableEntity<I extends EntityId> extends HasId<I>, HasName {
|
||||||
|
|
||||||
I getId();
|
|
||||||
void setId(I id);
|
void setId(I id);
|
||||||
|
|
||||||
I getExternalId();
|
I getExternalId();
|
||||||
|
|||||||
@ -23,6 +23,6 @@ public interface ExportableEntityDao<T extends ExportableEntity<?>> extends Dao<
|
|||||||
|
|
||||||
T findByTenantIdAndExternalId(UUID tenantId, UUID externalId);
|
T findByTenantIdAndExternalId(UUID tenantId, UUID externalId);
|
||||||
|
|
||||||
T findFirstByTenantIdAndName(UUID tenantId, String name);
|
default T findByTenantIdAndName(UUID tenantId, String name) { throw new UnsupportedOperationException(); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,9 @@ import org.thingsboard.server.dao.Dao;
|
|||||||
import org.thingsboard.server.dao.ExportableEntityDao;
|
import org.thingsboard.server.dao.ExportableEntityDao;
|
||||||
import org.thingsboard.server.dao.TenantEntityDao;
|
import org.thingsboard.server.dao.TenantEntityDao;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Interface DashboardDao.
|
* The Interface DashboardDao.
|
||||||
*/
|
*/
|
||||||
@ -33,4 +36,7 @@ public interface DashboardDao extends Dao<Dashboard>, TenantEntityDao, Exportabl
|
|||||||
* @return saved dashboard object
|
* @return saved dashboard object
|
||||||
*/
|
*/
|
||||||
Dashboard save(TenantId tenantId, Dashboard dashboard);
|
Dashboard save(TenantId tenantId, Dashboard dashboard);
|
||||||
|
|
||||||
|
List<Dashboard> findByTenantIdAndTitle(UUID tenantId, String title);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,8 @@ import org.thingsboard.server.dao.service.DataValidator;
|
|||||||
import org.thingsboard.server.dao.service.PaginatedRemover;
|
import org.thingsboard.server.dao.service.PaginatedRemover;
|
||||||
import org.thingsboard.server.dao.service.Validator;
|
import org.thingsboard.server.dao.service.Validator;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.thingsboard.server.dao.service.Validator.validateId;
|
import static org.thingsboard.server.dao.service.Validator.validateId;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -279,6 +281,11 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
|
|||||||
return dashboardInfoDao.findFirstByTenantIdAndName(tenantId.getId(), name);
|
return dashboardInfoDao.findFirstByTenantIdAndName(tenantId.getId(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Dashboard> findTenantDashboardsByTitle(TenantId tenantId, String title) {
|
||||||
|
return dashboardDao.findByTenantIdAndTitle(tenantId.getId(), title);
|
||||||
|
}
|
||||||
|
|
||||||
private PaginatedRemover<TenantId, DashboardInfo> tenantDashboardsRemover =
|
private PaginatedRemover<TenantId, DashboardInfo> tenantDashboardsRemover =
|
||||||
new PaginatedRemover<TenantId, DashboardInfo>() {
|
new PaginatedRemover<TenantId, DashboardInfo>() {
|
||||||
|
|
||||||
|
|||||||
@ -391,6 +391,11 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
|
|||||||
return ruleChainDao.findRuleChainsByTenantIdAndType(tenantId.getId(), type, pageLink);
|
return ruleChainDao.findRuleChainsByTenantIdAndType(tenantId.getId(), type, pageLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<RuleChain> findTenantRuleChainsByTypeAndName(TenantId tenantId, RuleChainType type, String name) {
|
||||||
|
return ruleChainDao.findByTenantIdAndTypeAndName(tenantId, type, name);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) {
|
public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) {
|
||||||
@ -457,7 +462,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
|
|||||||
ruleChain.setRoot(false);
|
ruleChain.setRoot(false);
|
||||||
|
|
||||||
if (overwrite) {
|
if (overwrite) {
|
||||||
Collection<RuleChain> existingRuleChains = ruleChainDao.findByTenantIdAndTypeAndName(tenantId,
|
Collection<RuleChain> existingRuleChains = findTenantRuleChainsByTypeAndName(tenantId,
|
||||||
Optional.ofNullable(ruleChain.getType()).orElse(RuleChainType.CORE), ruleChain.getName());
|
Optional.ofNullable(ruleChain.getType()).orElse(RuleChainType.CORE), ruleChain.getName());
|
||||||
Optional<RuleChain> existingRuleChain = existingRuleChains.stream().findFirst();
|
Optional<RuleChain> existingRuleChain = existingRuleChains.stream().findFirst();
|
||||||
if (existingRuleChain.isPresent()) {
|
if (existingRuleChain.isPresent()) {
|
||||||
|
|||||||
@ -215,7 +215,7 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao<AssetEntity, Asset> im
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Asset findFirstByTenantIdAndName(UUID tenantId, String name) {
|
public Asset findByTenantIdAndName(UUID tenantId, String name) {
|
||||||
return findAssetsByTenantIdAndName(tenantId, name).orElse(null);
|
return findAssetsByTenantIdAndName(tenantId, name).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,7 +76,7 @@ public class JpaCustomerDao extends JpaAbstractSearchTextDao<CustomerEntity, Cus
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Customer findFirstByTenantIdAndName(UUID tenantId, String name) {
|
public Customer findByTenantIdAndName(UUID tenantId, String name) {
|
||||||
return findCustomersByTenantIdAndTitle(tenantId, name).orElse(null);
|
return findCustomersByTenantIdAndTitle(tenantId, name).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
import org.thingsboard.server.dao.ExportableEntityRepository;
|
import org.thingsboard.server.dao.ExportableEntityRepository;
|
||||||
import org.thingsboard.server.dao.model.sql.DashboardEntity;
|
import org.thingsboard.server.dao.model.sql.DashboardEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,6 +29,6 @@ public interface DashboardRepository extends JpaRepository<DashboardEntity, UUID
|
|||||||
|
|
||||||
Long countByTenantId(UUID tenantId);
|
Long countByTenantId(UUID tenantId);
|
||||||
|
|
||||||
DashboardEntity findFirstByTenantIdAndTitle(UUID tenantId, String title);
|
List<DashboardEntity> findByTenantIdAndTitle(UUID tenantId, String title);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import org.thingsboard.server.dao.dashboard.DashboardDao;
|
|||||||
import org.thingsboard.server.dao.model.sql.DashboardEntity;
|
import org.thingsboard.server.dao.model.sql.DashboardEntity;
|
||||||
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
|
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,8 +59,8 @@ public class JpaDashboardDao extends JpaAbstractSearchTextDao<DashboardEntity, D
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dashboard findFirstByTenantIdAndName(UUID tenantId, String name) {
|
public List<Dashboard> findByTenantIdAndTitle(UUID tenantId, String title) {
|
||||||
return DaoUtil.getData(dashboardRepository.findFirstByTenantIdAndTitle(tenantId, name));
|
return DaoUtil.convertDataList(dashboardRepository.findByTenantIdAndTitle(tenantId, title));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -309,7 +309,7 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Device findFirstByTenantIdAndName(UUID tenantId, String name) {
|
public Device findByTenantIdAndName(UUID tenantId, String name) {
|
||||||
return findDeviceByTenantIdAndName(tenantId, name).orElse(null);
|
return findDeviceByTenantIdAndName(tenantId, name).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -117,7 +117,7 @@ public class JpaDeviceProfileDao extends JpaAbstractSearchTextDao<DeviceProfileE
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceProfile findFirstByTenantIdAndName(UUID tenantId, String name) {
|
public DeviceProfile findByTenantIdAndName(UUID tenantId, String name) {
|
||||||
return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndName(tenantId, name));
|
return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndName(tenantId, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -114,11 +114,6 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R
|
|||||||
return DaoUtil.getData(ruleChainRepository.findByTenantIdAndExternalId(tenantId, externalId));
|
return DaoUtil.getData(ruleChainRepository.findByTenantIdAndExternalId(tenantId, externalId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RuleChain findFirstByTenantIdAndName(UUID tenantId, String name) {
|
|
||||||
return DaoUtil.getData(ruleChainRepository.findFirstByTenantIdAndName(tenantId, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityType getEntityType() {
|
public EntityType getEntityType() {
|
||||||
return EntityType.RULE_CHAIN;
|
return EntityType.RULE_CHAIN;
|
||||||
|
|||||||
@ -67,6 +67,4 @@ public interface RuleChainRepository extends JpaRepository<RuleChainEntity, UUID
|
|||||||
|
|
||||||
List<RuleChainEntity> findByTenantIdAndTypeAndName(UUID tenantId, RuleChainType type, String name);
|
List<RuleChainEntity> findByTenantIdAndTypeAndName(UUID tenantId, RuleChainType type, String name);
|
||||||
|
|
||||||
RuleChainEntity findFirstByTenantIdAndName(UUID tenantId, String name);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user