Browse Source

Merge pull request #8533 from thingsboard/feature/notification-configs-vc

Version control for notification configs
pull/8633/head
Andrew Shvayka 3 years ago
committed by GitHub
parent
commit
1ccd7f9fd5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 37
      application/src/main/data/upgrade/3.5.1/schema_update.sql
  2. 3
      application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java
  3. 58
      application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/DefaultExportableEntitiesService.java
  4. 11
      application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/BaseEntityExportService.java
  5. 103
      application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationRuleExportService.java
  6. 55
      application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationTargetExportService.java
  7. 42
      application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationTemplateExportService.java
  8. 150
      application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationRuleImportService.java
  9. 109
      application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTargetImportService.java
  10. 72
      application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTemplateImportService.java
  11. 5
      application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java
  12. 4
      common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityDaoService.java
  13. 6
      common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRule.java
  14. 16
      common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java
  15. 17
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplate.java
  16. 9
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java
  17. 8
      common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java
  18. 8
      dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java
  19. 6
      dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java
  20. 6
      dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
  21. 6
      dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java
  22. 6
      dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java
  23. 6
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
  24. 6
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
  25. 7
      dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java
  26. 6
      dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRuleEntity.java
  27. 5
      dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTargetEntity.java
  28. 5
      dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTemplateEntity.java
  29. 5
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRuleService.java
  30. 5
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java
  31. 5
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTemplateService.java
  32. 3
      dao/src/main/java/org/thingsboard/server/dao/notification/NotificationRuleDao.java
  33. 3
      dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTargetDao.java
  34. 4
      dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateDao.java
  35. 6
      dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java
  36. 20
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRuleDao.java
  37. 20
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTargetDao.java
  38. 21
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTemplateDao.java
  39. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRuleRepository.java
  40. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTargetRepository.java
  41. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTemplateRepository.java
  42. 5
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java
  43. 12
      dao/src/main/resources/sql/schema-entities.sql
  44. 8
      ui-ngx/src/app/core/http/entity.service.ts
  45. 4
      ui-ngx/src/app/core/http/notification.service.ts
  46. 4
      ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.html
  47. 2
      ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.ts
  48. 4
      ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.html
  49. 13
      ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.ts
  50. 6
      ui-ngx/src/app/shared/models/entity-type.models.ts
  51. 9
      ui-ngx/src/app/shared/models/notification.models.ts
  52. 11
      ui-ngx/src/app/shared/models/vc.models.ts
  53. 8
      ui-ngx/src/assets/locale/locale.constant-en_US.json

37
application/src/main/data/upgrade/3.5.1/schema_update.sql

@ -15,3 +15,40 @@
--
ALTER TABLE notification_rule ADD COLUMN IF NOT EXISTS enabled BOOLEAN NOT NULL DEFAULT true;
-- NOTIFICATION CONFIGS VERSION CONTROL START
ALTER TABLE notification_template
ADD COLUMN IF NOT EXISTS external_id UUID;
DO
$$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'uq_notification_template_external_id') THEN
ALTER TABLE notification_template ADD CONSTRAINT uq_notification_template_external_id UNIQUE (tenant_id, external_id);
END IF;
END;
$$;
ALTER TABLE notification_target
ADD COLUMN IF NOT EXISTS external_id UUID;
DO
$$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'uq_notification_target_external_id') THEN
ALTER TABLE notification_target ADD CONSTRAINT uq_notification_target_external_id UNIQUE (tenant_id, external_id);
END IF;
END;
$$;
ALTER TABLE notification_rule
ADD COLUMN IF NOT EXISTS external_id UUID;
DO
$$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'uq_notification_rule_external_id') THEN
ALTER TABLE notification_rule ADD CONSTRAINT uq_notification_rule_external_id UNIQUE (tenant_id, external_id);
END IF;
END;
$$;
-- NOTIFICATION CONFIGS VERSION CONTROL END

3
application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java

@ -67,7 +67,8 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
protected static final List<EntityType> SUPPORTED_ENTITY_TYPES = List.of(
EntityType.CUSTOMER, EntityType.ASSET_PROFILE, EntityType.ASSET, EntityType.RULE_CHAIN,
EntityType.DASHBOARD, EntityType.DEVICE_PROFILE, EntityType.DEVICE,
EntityType.ENTITY_VIEW, EntityType.WIDGETS_BUNDLE
EntityType.ENTITY_VIEW, EntityType.WIDGETS_BUNDLE,
EntityType.NOTIFICATION_TEMPLATE, EntityType.NOTIFICATION_TARGET, EntityType.NOTIFICATION_RULE
);

58
application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/DefaultExportableEntitiesService.java

@ -22,36 +22,21 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.AssetProfileId;
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.HasId;
import org.thingsboard.server.common.data.id.RuleChainId;
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.PageLink;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.ExportableEntityDao;
import org.thingsboard.server.dao.asset.AssetProfileService;
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.dao.entity.EntityDaoService;
import org.thingsboard.server.dao.entity.EntityServiceRegistry;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.permission.AccessControlService;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
@Service
@TbCoreComponent
@ -60,11 +45,10 @@ import java.util.function.BiConsumer;
public class DefaultExportableEntitiesService implements ExportableEntitiesService {
private final Map<EntityType, Dao<?>> daos = new HashMap<>();
private final Map<EntityType, BiConsumer<TenantId, EntityId>> removers = new HashMap<>();
private final EntityServiceRegistry entityServiceRegistry;
private final AccessControlService accessControlService;
@Override
public <E extends ExportableEntity<I>, I extends EntityId> E findEntityByTenantIdAndExternalId(TenantId tenantId, I externalId) {
EntityType entityType = externalId.getEntityType();
@ -152,11 +136,11 @@ public class DefaultExportableEntitiesService implements ExportableEntitiesServi
@Override
public <I extends EntityId> void removeById(TenantId tenantId, I id) {
EntityType entityType = id.getEntityType();
BiConsumer<TenantId, EntityId> entityRemover = removers.get(entityType);
if (entityRemover == null) {
EntityDaoService entityService = entityServiceRegistry.getServiceByEntityType(entityType);
if (entityService == null) {
throw new IllegalArgumentException("Unsupported entity type " + entityType);
}
entityRemover.accept(tenantId, id);
entityService.deleteEntity(tenantId, id);
}
private <I extends EntityId, E extends ExportableEntity<I>> ExportableEntityDao<I, E> getExportableEntityDao(EntityType entityType) {
@ -182,34 +166,4 @@ public class DefaultExportableEntitiesService implements ExportableEntitiesServi
});
}
@Autowired
private void setRemovers(CustomerService customerService, AssetService assetService, RuleChainService ruleChainService,
DashboardService dashboardService, DeviceProfileService deviceProfileService,
AssetProfileService assetProfileService, 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.ASSET_PROFILE, (tenantId, entityId) -> {
assetProfileService.deleteAssetProfile(tenantId, (AssetProfileId) entityId);
});
removers.put(EntityType.DEVICE, (tenantId, entityId) -> {
deviceService.deleteDevice(tenantId, (DeviceId) entityId);
});
removers.put(EntityType.WIDGETS_BUNDLE, (tenantId, entityId) -> {
widgetsBundleService.deleteWidgetsBundle(tenantId, (WidgetsBundleId) entityId);
});
}
}

11
application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/BaseEntityExportService.java

@ -24,7 +24,11 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.service.sync.vc.data.EntitiesExportCtx;
import java.util.Collection;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Stream;
public abstract class BaseEntityExportService<I extends EntityId, E extends ExportableEntity<I>, D extends EntityExportData<E>> extends DefaultEntityExportService<I, E, D> {
@ -47,4 +51,11 @@ public abstract class BaseEntityExportService<I extends EntityId, E extends Expo
JacksonUtil.replaceUuidsRecursively(node, skipFieldsSet, uuid -> getExternalIdOrElseInternalByUuid(ctx, uuid));
}
protected Stream<UUID> toExternalIds(Collection<UUID> internalIds, Function<UUID, EntityId> entityIdCreator,
EntitiesExportCtx<?> ctx) {
return internalIds.stream().map(entityIdCreator)
.map(entityId -> getExternalIdOrElseInternal(ctx, entityId))
.map(EntityId::getId);
}
}

103
application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationRuleExportService.java

@ -0,0 +1,103 @@
/**
* Copyright © 2016-2023 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 org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ExportableEntity;
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.NotificationRuleId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.notification.rule.DefaultNotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.EscalatedNotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.notification.rule.NotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.DeviceActivityNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.data.EntitiesExportCtx;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
@TbCoreComponent
public class NotificationRuleExportService<I extends EntityId, E extends ExportableEntity<I>, D extends EntityExportData<E>> extends BaseEntityExportService<NotificationRuleId, NotificationRule, EntityExportData<NotificationRule>> {
@Override
protected void setRelatedEntities(EntitiesExportCtx<?> ctx, NotificationRule notificationRule, EntityExportData<NotificationRule> exportData) {
notificationRule.setTemplateId(getExternalIdOrElseInternal(ctx, notificationRule.getTemplateId()));
NotificationRuleTriggerConfig ruleTriggerConfig = notificationRule.getTriggerConfig();
switch (ruleTriggerConfig.getTriggerType()) {
case DEVICE_ACTIVITY: {
DeviceActivityNotificationRuleTriggerConfig triggerConfig = (DeviceActivityNotificationRuleTriggerConfig) ruleTriggerConfig;
Set<UUID> devices = triggerConfig.getDevices();
if (devices != null) {
triggerConfig.setDevices(toExternalIds(devices, DeviceId::new, ctx).collect(Collectors.toSet()));
}
Set<UUID> deviceProfiles = triggerConfig.getDeviceProfiles();
if (deviceProfiles != null) {
triggerConfig.setDeviceProfiles(toExternalIds(deviceProfiles, DeviceProfileId::new, ctx).collect(Collectors.toSet()));
}
break;
}
case RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT:
RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig triggerConfig = (RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig) ruleTriggerConfig;
Set<UUID> ruleChains = triggerConfig.getRuleChains();
if (ruleChains != null) {
triggerConfig.setRuleChains(toExternalIds(ruleChains, RuleChainId::new, ctx).collect(Collectors.toSet()));
}
break;
}
NotificationRuleRecipientsConfig ruleRecipientsConfig = notificationRule.getRecipientsConfig();
switch (ruleTriggerConfig.getTriggerType()) {
case ALARM: {
EscalatedNotificationRuleRecipientsConfig recipientsConfig = (EscalatedNotificationRuleRecipientsConfig) ruleRecipientsConfig;
Map<Integer, List<UUID>> escalationTable = new LinkedHashMap<>(recipientsConfig.getEscalationTable());
escalationTable.replaceAll((delay, targets) -> {
return toExternalIds(targets, NotificationTargetId::new, ctx).collect(Collectors.toList());
});
recipientsConfig.setEscalationTable(escalationTable);
break;
}
default: {
DefaultNotificationRuleRecipientsConfig recipientsConfig = (DefaultNotificationRuleRecipientsConfig) ruleRecipientsConfig;
List<UUID> targets = recipientsConfig.getTargets();
targets = toExternalIds(targets, NotificationTargetId::new, ctx).collect(Collectors.toList());
recipientsConfig.setTargets(targets);
break;
}
}
}
@Override
public Set<EntityType> getSupportedEntityTypes() {
return Set.of(EntityType.NOTIFICATION_RULE);
}
}

55
application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationTargetExportService.java

@ -0,0 +1,55 @@
/**
* Copyright © 2016-2023 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 org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.targets.NotificationTargetType;
import org.thingsboard.server.common.data.notification.targets.platform.CustomerUsersFilter;
import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.platform.UsersFilter;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.data.EntitiesExportCtx;
import java.util.Set;
@Service
@TbCoreComponent
public class NotificationTargetExportService extends BaseEntityExportService<NotificationTargetId, NotificationTarget, EntityExportData<NotificationTarget>> {
@Override
protected void setRelatedEntities(EntitiesExportCtx<?> ctx, NotificationTarget notificationTarget, EntityExportData<NotificationTarget> exportData) {
if (notificationTarget.getConfiguration().getType() == NotificationTargetType.PLATFORM_USERS) {
UsersFilter usersFilter = ((PlatformUsersNotificationTargetConfig) notificationTarget.getConfiguration()).getUsersFilter();
switch (usersFilter.getType()) {
case CUSTOMER_USERS:
CustomerUsersFilter customerUsersFilter = (CustomerUsersFilter) usersFilter;
customerUsersFilter.setCustomerId(getExternalIdOrElseInternal(ctx, new CustomerId(customerUsersFilter.getCustomerId())).getId());
break;
}
}
}
@Override
public Set<EntityType> getSupportedEntityTypes() {
return Set.of(EntityType.NOTIFICATION_TARGET);
}
}

42
application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationTemplateExportService.java

@ -0,0 +1,42 @@
/**
* Copyright © 2016-2023 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 org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.data.EntitiesExportCtx;
import java.util.Set;
@Service
@TbCoreComponent
public class NotificationTemplateExportService extends BaseEntityExportService<NotificationTemplateId, NotificationTemplate, EntityExportData<NotificationTemplate>> {
@Override
protected void setRelatedEntities(EntitiesExportCtx<?> ctx, NotificationTemplate notificationTemplate, EntityExportData<NotificationTemplate> exportData) {
}
@Override
public Set<EntityType> getSupportedEntityTypes() {
return Set.of(EntityType.NOTIFICATION_TEMPLATE);
}
}

150
application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationRuleImportService.java

@ -0,0 +1,150 @@
/**
* Copyright © 2016-2023 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.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.notification.rule.DefaultNotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.EscalatedNotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.notification.rule.NotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.DeviceActivityNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.notification.rule.trigger.RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.dao.notification.NotificationRuleService;
import org.thingsboard.server.dao.service.ConstraintValidator;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class NotificationRuleImportService extends BaseEntityImportService<NotificationRuleId, NotificationRule, EntityExportData<NotificationRule>> {
private final NotificationRuleService notificationRuleService;
@Override
protected void setOwner(TenantId tenantId, NotificationRule notificationRule, IdProvider idProvider) {
notificationRule.setTenantId(tenantId);
}
@Override
protected NotificationRule prepare(EntitiesImportCtx ctx, NotificationRule notificationRule, NotificationRule oldNotificationRule, EntityExportData<NotificationRule> exportData, IdProvider idProvider) {
notificationRule.setTemplateId(idProvider.getInternalId(notificationRule.getTemplateId()));
NotificationRuleTriggerConfig ruleTriggerConfig = notificationRule.getTriggerConfig();
NotificationRuleTriggerType triggerType = ruleTriggerConfig.getTriggerType();
switch (triggerType) {
case DEVICE_ACTIVITY: {
DeviceActivityNotificationRuleTriggerConfig triggerConfig = (DeviceActivityNotificationRuleTriggerConfig) ruleTriggerConfig;
Set<UUID> devices = triggerConfig.getDevices();
if (devices != null) {
triggerConfig.setDevices(devices.stream().map(DeviceId::new)
.map(idProvider::getInternalId).map(UUIDBased::getId)
.collect(Collectors.toSet()));
}
Set<UUID> deviceProfiles = triggerConfig.getDeviceProfiles();
if (deviceProfiles != null) {
triggerConfig.setDeviceProfiles(deviceProfiles.stream().map(DeviceProfileId::new)
.map(idProvider::getInternalId).map(UUIDBased::getId)
.collect(Collectors.toSet()));
}
break;
}
case RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT:
RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig triggerConfig = (RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig) ruleTriggerConfig;
Set<UUID> ruleChains = triggerConfig.getRuleChains();
if (ruleChains != null) {
triggerConfig.setRuleChains(ruleChains.stream().map(RuleChainId::new)
.map(idProvider::getInternalId).map(UUIDBased::getId)
.collect(Collectors.toSet()));
}
break;
}
if (!triggerType.isTenantLevel()) {
throw new IllegalArgumentException("Trigger type " + triggerType + " is not available for tenants");
}
NotificationRuleRecipientsConfig ruleRecipientsConfig = notificationRule.getRecipientsConfig();
switch (triggerType) {
case ALARM: {
EscalatedNotificationRuleRecipientsConfig recipientsConfig = (EscalatedNotificationRuleRecipientsConfig) ruleRecipientsConfig;
Map<Integer, List<UUID>> escalationTable = new LinkedHashMap<>(recipientsConfig.getEscalationTable());
escalationTable.replaceAll((delay, targets) -> targets.stream()
.map(NotificationTargetId::new).map(idProvider::getInternalId)
.map(UUIDBased::getId).collect(Collectors.toList()));
recipientsConfig.setEscalationTable(escalationTable);
break;
}
default: {
DefaultNotificationRuleRecipientsConfig recipientsConfig = (DefaultNotificationRuleRecipientsConfig) ruleRecipientsConfig;
List<UUID> targets = recipientsConfig.getTargets().stream()
.map(NotificationTargetId::new).map(idProvider::getInternalId)
.map(UUIDBased::getId).collect(Collectors.toList());
recipientsConfig.setTargets(targets);
break;
}
}
return notificationRule;
}
@Override
protected NotificationRule saveOrUpdate(EntitiesImportCtx ctx, NotificationRule notificationRule, EntityExportData<NotificationRule> exportData, IdProvider idProvider) {
ConstraintValidator.validateFields(notificationRule);
return notificationRuleService.saveNotificationRule(ctx.getTenantId(), notificationRule);
}
@Override
protected void onEntitySaved(User user, NotificationRule savedEntity, NotificationRule oldEntity) throws ThingsboardException {
entityActionService.logEntityAction(user, savedEntity.getId(), savedEntity, null,
oldEntity == null ? ActionType.ADDED : ActionType.UPDATED, null);
clusterService.broadcastEntityStateChangeEvent(user.getTenantId(), savedEntity.getId(),
oldEntity == null ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
}
@Override
protected NotificationRule deepCopy(NotificationRule notificationRule) {
return new NotificationRule(notificationRule);
}
@Override
public EntityType getEntityType() {
return EntityType.NOTIFICATION_RULE;
}
}

109
application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTargetImportService.java

@ -0,0 +1,109 @@
/**
* Copyright © 2016-2023 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.apache.commons.collections.CollectionUtils;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.targets.NotificationTargetType;
import org.thingsboard.server.common.data.notification.targets.platform.CustomerUsersFilter;
import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.platform.TenantAdministratorsFilter;
import org.thingsboard.server.common.data.notification.targets.platform.UserListFilter;
import org.thingsboard.server.common.data.notification.targets.platform.UsersFilter;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.dao.notification.NotificationTargetService;
import org.thingsboard.server.dao.service.ConstraintValidator;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
import java.util.stream.Collectors;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class NotificationTargetImportService extends BaseEntityImportService<NotificationTargetId, NotificationTarget, EntityExportData<NotificationTarget>> {
private final NotificationTargetService notificationTargetService;
@Override
protected void setOwner(TenantId tenantId, NotificationTarget notificationTarget, IdProvider idProvider) {
notificationTarget.setTenantId(tenantId);
}
@Override
protected NotificationTarget prepare(EntitiesImportCtx ctx, NotificationTarget notificationTarget, NotificationTarget oldNotificationTarget, EntityExportData<NotificationTarget> exportData, IdProvider idProvider) {
if (notificationTarget.getConfiguration().getType() == NotificationTargetType.PLATFORM_USERS) {
UsersFilter usersFilter = ((PlatformUsersNotificationTargetConfig) notificationTarget.getConfiguration()).getUsersFilter();
switch (usersFilter.getType()) {
case CUSTOMER_USERS:
CustomerUsersFilter customerUsersFilter = (CustomerUsersFilter) usersFilter;
customerUsersFilter.setCustomerId(idProvider.getInternalId(new CustomerId(customerUsersFilter.getCustomerId())).getId());
break;
case USER_LIST:
UserListFilter userListFilter = (UserListFilter) usersFilter;
userListFilter.setUsersIds(userListFilter.getUsersIds().stream()
.map(UserId::new).map(idProvider::getInternalId)
.map(UUIDBased::getId).collect(Collectors.toList())
);
break;
case TENANT_ADMINISTRATORS:
if (CollectionUtils.isNotEmpty(((TenantAdministratorsFilter) usersFilter).getTenantsIds()) ||
CollectionUtils.isNotEmpty(((TenantAdministratorsFilter) usersFilter).getTenantProfilesIds())) {
throw new IllegalArgumentException("Permission denied");
}
break;
case SYSTEM_ADMINISTRATORS:
throw new AccessDeniedException("Permission denied");
}
}
return notificationTarget;
}
@Override
protected NotificationTarget saveOrUpdate(EntitiesImportCtx ctx, NotificationTarget notificationTarget, EntityExportData<NotificationTarget> exportData, IdProvider idProvider) {
ConstraintValidator.validateFields(notificationTarget);
return notificationTargetService.saveNotificationTarget(ctx.getTenantId(), notificationTarget);
}
@Override
protected void onEntitySaved(User user, NotificationTarget savedEntity, NotificationTarget oldEntity) throws ThingsboardException {
entityActionService.logEntityAction(user, savedEntity.getId(), savedEntity, null,
oldEntity == null ? ActionType.ADDED : ActionType.UPDATED, null);
}
@Override
protected NotificationTarget deepCopy(NotificationTarget notificationTarget) {
return new NotificationTarget(notificationTarget);
}
@Override
public EntityType getEntityType() {
return EntityType.NOTIFICATION_TARGET;
}
}

72
application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTemplateImportService.java

@ -0,0 +1,72 @@
/**
* Copyright © 2016-2023 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.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.dao.notification.NotificationTemplateService;
import org.thingsboard.server.dao.service.ConstraintValidator;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class NotificationTemplateImportService extends BaseEntityImportService<NotificationTemplateId, NotificationTemplate, EntityExportData<NotificationTemplate>> {
private final NotificationTemplateService notificationTemplateService;
@Override
protected void setOwner(TenantId tenantId, NotificationTemplate notificationTemplate, IdProvider idProvider) {
notificationTemplate.setTenantId(tenantId);
}
@Override
protected NotificationTemplate prepare(EntitiesImportCtx ctx, NotificationTemplate notificationTemplate, NotificationTemplate oldEntity, EntityExportData<NotificationTemplate> exportData, IdProvider idProvider) {
return notificationTemplate;
}
@Override
protected NotificationTemplate saveOrUpdate(EntitiesImportCtx ctx, NotificationTemplate notificationTemplate, EntityExportData<NotificationTemplate> exportData, IdProvider idProvider) {
ConstraintValidator.validateFields(notificationTemplate);
return notificationTemplateService.saveNotificationTemplate(ctx.getTenantId(), notificationTemplate);
}
@Override
protected void onEntitySaved(User user, NotificationTemplate savedEntity, NotificationTemplate oldEntity) throws ThingsboardException {
entityActionService.logEntityAction(user, savedEntity.getId(), savedEntity, null,
oldEntity == null ? ActionType.ADDED : ActionType.UPDATED, null);
}
@Override
protected NotificationTemplate deepCopy(NotificationTemplate notificationTemplate) {
return new NotificationTemplate(notificationTemplate);
}
@Override
public EntityType getEntityType() {
return EntityType.NOTIFICATION_TEMPLATE;
}
}

5
application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java

@ -480,7 +480,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
assertThat(getMyNotifications(false, 100)).size().isZero();
createDevice("Device 1", "default", "111");
await().atMost(15, TimeUnit.SECONDS)
await().atMost(30, TimeUnit.SECONDS)
.untilAsserted(() -> {
assertThat(getMyNotifications(false, 100)).size().isEqualTo(1);
});
@ -494,9 +494,10 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
rule.setEnabled(true);
saveNotificationRule(rule);
TimeUnit.SECONDS.sleep(2); // for rule update event to reach rules cache
createDevice("Device 3", "default", "333");
await().atMost(15, TimeUnit.SECONDS)
await().atMost(30, TimeUnit.SECONDS)
.untilAsserted(() -> {
assertThat(getMyNotifications(false, 100)).size().isEqualTo(2);
});

4
common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityDaoService.java

@ -30,6 +30,10 @@ public interface EntityDaoService {
throw new IllegalArgumentException("Not implemented for " + getEntityType());
}
default void deleteEntity(TenantId tenantId, EntityId id) {
throw new IllegalArgumentException(getEntityType().getNormalName() + " deletion not supported");
}
EntityType getEntityType();
}

6
common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRule.java

@ -20,6 +20,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
@ -39,7 +40,7 @@ import java.io.Serializable;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class NotificationRule extends BaseData<NotificationRuleId> implements HasTenantId, HasName, Serializable {
public class NotificationRule extends BaseData<NotificationRuleId> implements HasTenantId, HasName, ExportableEntity<NotificationRuleId>, Serializable {
private TenantId tenantId;
@NotBlank
@ -61,6 +62,8 @@ public class NotificationRule extends BaseData<NotificationRuleId> implements Ha
private NotificationRuleConfig additionalConfig;
private NotificationRuleId externalId;
public NotificationRule(NotificationRule other) {
super(other);
this.tenantId = other.tenantId;
@ -71,6 +74,7 @@ public class NotificationRule extends BaseData<NotificationRuleId> implements Ha
this.triggerConfig = other.triggerConfig;
this.recipientsConfig = other.recipientsConfig;
this.additionalConfig = other.additionalConfig;
this.externalId = other.externalId;
}
@JsonIgnore

16
common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.notification.targets;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
@ -31,7 +32,7 @@ import javax.validation.constraints.NotNull;
@Data
@EqualsAndHashCode(callSuper = true)
public class NotificationTarget extends BaseData<NotificationTargetId> implements HasTenantId, HasName {
public class NotificationTarget extends BaseData<NotificationTargetId> implements HasTenantId, HasName, ExportableEntity<NotificationTargetId> {
private TenantId tenantId;
@NotBlank
@ -42,4 +43,17 @@ public class NotificationTarget extends BaseData<NotificationTargetId> implement
@Valid
private NotificationTargetConfig configuration;
private NotificationTargetId externalId;
public NotificationTarget() {
}
public NotificationTarget(NotificationTarget other) {
super(other);
this.tenantId = other.tenantId;
this.name = other.name;
this.configuration = other.configuration;
this.externalId = other.externalId;
}
}

17
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplate.java

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
@ -32,7 +33,7 @@ import javax.validation.constraints.NotNull;
@Data
@EqualsAndHashCode(callSuper = true)
public class NotificationTemplate extends BaseData<NotificationTemplateId> implements HasTenantId, HasName {
public class NotificationTemplate extends BaseData<NotificationTemplateId> implements HasTenantId, HasName, ExportableEntity<NotificationTemplateId> {
private TenantId tenantId;
@NoXss
@ -46,4 +47,18 @@ public class NotificationTemplate extends BaseData<NotificationTemplateId> imple
@NotNull
private NotificationTemplateConfig configuration;
private NotificationTemplateId externalId;
public NotificationTemplate() {
}
public NotificationTemplate(NotificationTemplate other) {
super(other);
this.tenantId = other.tenantId;
this.name = other.name;
this.notificationType = other.notificationType;
this.configuration = other.configuration != null ? other.configuration.copy() : null;
this.externalId = other.externalId;
}
}

9
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java

@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.notification.NotificationDeliveryMetho
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.HashMap;
import java.util.Map;
@Data
@ -29,4 +30,12 @@ public class NotificationTemplateConfig {
@NotEmpty
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> deliveryMethodsTemplates;
public NotificationTemplateConfig copy() {
Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> templates = new HashMap<>(deliveryMethodsTemplates);
templates.replaceAll((deliveryMethod, template) -> template.copy());
NotificationTemplateConfig copy = new NotificationTemplateConfig();
copy.setDeliveryMethodsTemplates(templates);
return copy;
}
}

8
common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java

@ -27,6 +27,9 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.AssetProfile;
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
@ -48,7 +51,10 @@ import java.lang.annotation.Target;
@Type(name = "DASHBOARD", value = Dashboard.class),
@Type(name = "CUSTOMER", value = Customer.class),
@Type(name = "ENTITY_VIEW", value = EntityView.class),
@Type(name = "WIDGETS_BUNDLE", value = WidgetsBundle.class)
@Type(name = "WIDGETS_BUNDLE", value = WidgetsBundle.class),
@Type(name = "NOTIFICATION_TEMPLATE", value = NotificationTemplate.class),
@Type(name = "NOTIFICATION_TARGET", value = NotificationTarget.class),
@Type(name = "NOTIFICATION_RULE", value = NotificationRule.class)
})
@JsonIgnoreProperties(value = {"tenantId", "createdTime"}, ignoreUnknown = true)
public @interface JsonTbEntity {

8
dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java

@ -109,6 +109,14 @@ public abstract class DaoUtil {
return ids;
}
public static <I> I toEntityId(UUID uuid, Function<UUID, I> creator) {
if (uuid != null) {
return creator.apply(uuid);
} else {
return null;
}
}
public static <T> void processInBatches(Function<PageLink, PageData<T>> finder, int batchSize, Consumer<T> processor) {
processBatches(finder, batchSize, batch -> batch.getData().forEach(processor));
}

6
dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java

@ -273,6 +273,12 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService<AssetPr
return Optional.ofNullable(findAssetProfileById(tenantId, new AssetProfileId(entityId.getId())));
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteAssetProfile(tenantId, (AssetProfileId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.ASSET_PROFILE;

6
dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java

@ -450,6 +450,12 @@ public class BaseAssetService extends AbstractCachedEntityService<AssetCacheKey,
return assetDao.countByTenantId(tenantId);
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteAsset(tenantId, (AssetId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.ASSET;

6
dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java

@ -197,6 +197,12 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
return Optional.ofNullable(findCustomerById(tenantId, new CustomerId(entityId.getId())));
}
@Transactional
@Override
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteCustomer(tenantId, (CustomerId) id);
}
@Override
public long countByTenantId(TenantId tenantId) {
return customerDao.countByTenantId(tenantId);

6
dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java

@ -366,6 +366,12 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
return dashboardDao.countByTenantId(tenantId);
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteDashboard(tenantId, (DashboardId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.DASHBOARD;

6
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

@ -328,6 +328,12 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
return Optional.ofNullable(findDeviceProfileById(tenantId, new DeviceProfileId(entityId.getId())));
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteDeviceProfile(tenantId, (DeviceProfileId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.DEVICE_PROFILE;

6
dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java

@ -638,6 +638,12 @@ public class DeviceServiceImpl extends AbstractCachedEntityService<DeviceCacheKe
return deviceDao.countByTenantId(tenantId);
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteDevice(tenantId, (DeviceId) id);
}
private PaginatedRemover<TenantId, Device> tenantDevicesRemover =
new PaginatedRemover<>() {

7
dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java

@ -22,6 +22,7 @@ import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.dao.DaoUtil;
import javax.persistence.Column;
import javax.persistence.Id;
@ -85,11 +86,7 @@ public abstract class BaseSqlEntity<D> implements BaseEntity<D> {
}
protected static <I> I getEntityId(UUID uuid, Function<UUID, I> creator) {
if (uuid != null) {
return creator.apply(uuid);
} else {
return null;
}
return DaoUtil.toEntityId(uuid, creator);
}
protected static TenantId getTenantId(UUID uuid) {

6
dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRuleEntity.java

@ -72,6 +72,9 @@ public class NotificationRuleEntity extends BaseSqlEntity<NotificationRule> {
@Column(name = ModelConstants.NOTIFICATION_RULE_ADDITIONAL_CONFIG_PROPERTY)
private JsonNode additionalConfig;
@Column(name = ModelConstants.EXTERNAL_ID_PROPERTY)
private UUID externalId;
public NotificationRuleEntity() {}
public NotificationRuleEntity(NotificationRule notificationRule) {
@ -85,6 +88,7 @@ public class NotificationRuleEntity extends BaseSqlEntity<NotificationRule> {
setTriggerConfig(toJson(notificationRule.getTriggerConfig()));
setRecipientsConfig(toJson(notificationRule.getRecipientsConfig()));
setAdditionalConfig(toJson(notificationRule.getAdditionalConfig()));
setExternalId(getUuid(notificationRule.getExternalId()));
}
public NotificationRuleEntity(NotificationRuleEntity other) {
@ -98,6 +102,7 @@ public class NotificationRuleEntity extends BaseSqlEntity<NotificationRule> {
this.triggerConfig = other.triggerConfig;
this.recipientsConfig = other.recipientsConfig;
this.additionalConfig = other.additionalConfig;
this.externalId = other.externalId;
}
@Override
@ -113,6 +118,7 @@ public class NotificationRuleEntity extends BaseSqlEntity<NotificationRule> {
notificationRule.setTriggerConfig(fromJson(triggerConfig, NotificationRuleTriggerConfig.class));
notificationRule.setRecipientsConfig(fromJson(recipientsConfig, NotificationRuleRecipientsConfig.class));
notificationRule.setAdditionalConfig(fromJson(additionalConfig, NotificationRuleConfig.class));
notificationRule.setExternalId(getEntityId(externalId, NotificationRuleId::new));
return notificationRule;
}

5
dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTargetEntity.java

@ -49,6 +49,9 @@ public class NotificationTargetEntity extends BaseSqlEntity<NotificationTarget>
@Column(name = ModelConstants.NOTIFICATION_TARGET_CONFIGURATION_PROPERTY, nullable = false)
private JsonNode configuration;
@Column(name = ModelConstants.EXTERNAL_ID_PROPERTY)
private UUID externalId;
public NotificationTargetEntity() {}
public NotificationTargetEntity(NotificationTarget notificationTarget) {
@ -57,6 +60,7 @@ public class NotificationTargetEntity extends BaseSqlEntity<NotificationTarget>
setTenantId(getTenantUuid(notificationTarget.getTenantId()));
setName(notificationTarget.getName());
setConfiguration(toJson(notificationTarget.getConfiguration()));
setExternalId(getUuid(notificationTarget.getExternalId()));
}
@Override
@ -67,6 +71,7 @@ public class NotificationTargetEntity extends BaseSqlEntity<NotificationTarget>
notificationTarget.setTenantId(getTenantId(tenantId));
notificationTarget.setName(name);
notificationTarget.setConfiguration(fromJson(configuration, NotificationTargetConfig.class));
notificationTarget.setExternalId(getEntityId(externalId, NotificationTargetId::new));
return notificationTarget;
}

5
dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTemplateEntity.java

@ -56,6 +56,9 @@ public class NotificationTemplateEntity extends BaseSqlEntity<NotificationTempla
@Column(name = ModelConstants.NOTIFICATION_TEMPLATE_CONFIGURATION_PROPERTY, nullable = false)
private JsonNode configuration;
@Column(name = ModelConstants.EXTERNAL_ID_PROPERTY)
private UUID externalId;
public NotificationTemplateEntity() {}
public NotificationTemplateEntity(NotificationTemplate notificationTemplate) {
@ -65,6 +68,7 @@ public class NotificationTemplateEntity extends BaseSqlEntity<NotificationTempla
setName(notificationTemplate.getName());
setNotificationType(notificationTemplate.getNotificationType());
setConfiguration(toJson(notificationTemplate.getConfiguration()));
setExternalId(getUuid(notificationTemplate.getExternalId()));
}
@Override
@ -76,6 +80,7 @@ public class NotificationTemplateEntity extends BaseSqlEntity<NotificationTempla
notificationTemplate.setName(name);
notificationTemplate.setNotificationType(notificationType);
notificationTemplate.setConfiguration(fromJson(configuration, NotificationTemplateConfig.class));
notificationTemplate.setExternalId(getEntityId(externalId, NotificationTemplateId::new));
return notificationTemplate;
}

5
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRuleService.java

@ -98,6 +98,11 @@ public class DefaultNotificationRuleService extends AbstractEntityService implem
return Optional.ofNullable(findNotificationRuleById(tenantId, new NotificationRuleId(entityId.getId())));
}
@Override
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteNotificationRuleById(tenantId, (NotificationRuleId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.NOTIFICATION_RULE;

5
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java

@ -202,6 +202,11 @@ public class DefaultNotificationTargetService extends AbstractEntityService impl
return Optional.ofNullable(findNotificationTargetById(tenantId, new NotificationTargetId(entityId.getId())));
}
@Override
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteNotificationTargetById(tenantId, (NotificationTargetId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.NOTIFICATION_TARGET;

5
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTemplateService.java

@ -94,6 +94,11 @@ public class DefaultNotificationTemplateService extends AbstractEntityService im
return Optional.ofNullable(findNotificationTemplateById(tenantId, new NotificationTemplateId(entityId.getId())));
}
@Override
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteNotificationTemplateById(tenantId, (NotificationTemplateId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.NOTIFICATION_TEMPLATE;

3
dao/src/main/java/org/thingsboard/server/dao/notification/NotificationRuleDao.java

@ -24,10 +24,11 @@ import org.thingsboard.server.common.data.notification.rule.trigger.Notification
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.ExportableEntityDao;
import java.util.List;
public interface NotificationRuleDao extends Dao<NotificationRule> {
public interface NotificationRuleDao extends Dao<NotificationRule>, ExportableEntityDao<NotificationRuleId, NotificationRule> {
PageData<NotificationRule> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink);

3
dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTargetDao.java

@ -22,11 +22,12 @@ import org.thingsboard.server.common.data.notification.targets.NotificationTarge
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.ExportableEntityDao;
import org.thingsboard.server.dao.TenantEntityDao;
import java.util.List;
public interface NotificationTargetDao extends Dao<NotificationTarget>, TenantEntityDao {
public interface NotificationTargetDao extends Dao<NotificationTarget>, TenantEntityDao, ExportableEntityDao<NotificationTargetId, NotificationTarget> {
PageData<NotificationTarget> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink);

4
dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateDao.java

@ -15,16 +15,18 @@
*/
package org.thingsboard.server.dao.notification;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.ExportableEntityDao;
import java.util.List;
public interface NotificationTemplateDao extends Dao<NotificationTemplate> {
public interface NotificationTemplateDao extends Dao<NotificationTemplate>, ExportableEntityDao<NotificationTemplateId, NotificationTemplate> {
PageData<NotificationTemplate> findByTenantIdAndNotificationTypesAndPageLink(TenantId tenantId, List<NotificationType> notificationTypes, PageLink pageLink);

6
dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java

@ -754,6 +754,12 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
return ruleChainDao.countByTenantId(tenantId);
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteRuleChainById(tenantId, (RuleChainId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.RULE_CHAIN;

20
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRuleDao.java

@ -82,6 +82,26 @@ public class JpaNotificationRuleDao extends JpaAbstractDao<NotificationRuleEntit
notificationRuleRepository.deleteByTenantId(tenantId.getId());
}
@Override
public NotificationRule findByTenantIdAndExternalId(UUID tenantId, UUID externalId) {
return DaoUtil.getData(notificationRuleRepository.findByTenantIdAndExternalId(tenantId, externalId));
}
@Override
public NotificationRule findByTenantIdAndName(UUID tenantId, String name) {
return DaoUtil.getData(notificationRuleRepository.findByTenantIdAndName(tenantId, name));
}
@Override
public PageData<NotificationRule> findByTenantId(UUID tenantId, PageLink pageLink) {
return DaoUtil.toPageData(notificationRuleRepository.findByTenantId(tenantId, DaoUtil.toPageable(pageLink)));
}
@Override
public NotificationRuleId getExternalIdByInternal(NotificationRuleId internalId) {
return DaoUtil.toEntityId(notificationRuleRepository.getExternalIdByInternal(internalId.getId()), NotificationRuleId::new);
}
@Override
protected Class<NotificationRuleEntity> getEntityClass() {
return NotificationRuleEntity.class;

20
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTargetDao.java

@ -76,6 +76,26 @@ public class JpaNotificationTargetDao extends JpaAbstractDao<NotificationTargetE
return notificationTargetRepository.countByTenantId(tenantId.getId());
}
@Override
public NotificationTarget findByTenantIdAndExternalId(UUID tenantId, UUID externalId) {
return DaoUtil.getData(notificationTargetRepository.findByTenantIdAndExternalId(tenantId, externalId));
}
@Override
public NotificationTarget findByTenantIdAndName(UUID tenantId, String name) {
return DaoUtil.getData(notificationTargetRepository.findByTenantIdAndName(tenantId, name));
}
@Override
public PageData<NotificationTarget> findByTenantId(UUID tenantId, PageLink pageLink) {
return DaoUtil.toPageData(notificationTargetRepository.findByTenantId(tenantId, DaoUtil.toPageable(pageLink)));
}
@Override
public NotificationTargetId getExternalIdByInternal(NotificationTargetId internalId) {
return DaoUtil.toEntityId(notificationTargetRepository.getExternalIdByInternal(internalId.getId()), NotificationTargetId::new);
}
@Override
protected Class<NotificationTargetEntity> getEntityClass() {
return NotificationTargetEntity.class;

21
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTemplateDao.java

@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
@ -57,6 +58,26 @@ public class JpaNotificationTemplateDao extends JpaAbstractDao<NotificationTempl
notificationTemplateRepository.deleteByTenantId(tenantId.getId());
}
@Override
public NotificationTemplate findByTenantIdAndExternalId(UUID tenantId, UUID externalId) {
return DaoUtil.getData(notificationTemplateRepository.findByTenantIdAndExternalId(tenantId, externalId));
}
@Override
public NotificationTemplate findByTenantIdAndName(UUID tenantId, String name) {
return DaoUtil.getData(notificationTemplateRepository.findByTenantIdAndName(tenantId, name));
}
@Override
public PageData<NotificationTemplate> findByTenantId(UUID tenantId, PageLink pageLink) {
return DaoUtil.toPageData(notificationTemplateRepository.findByTenantId(tenantId, DaoUtil.toPageable(pageLink)));
}
@Override
public NotificationTemplateId getExternalIdByInternal(NotificationTemplateId internalId) {
return DaoUtil.toEntityId(notificationTemplateRepository.getExternalIdByInternal(internalId.getId()), NotificationTemplateId::new);
}
@Override
protected JpaRepository<NotificationTemplateEntity, UUID> getRepository() {
return notificationTemplateRepository;

10
dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRuleRepository.java

@ -23,6 +23,7 @@ import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.dao.ExportableEntityRepository;
import org.thingsboard.server.dao.model.sql.NotificationRuleEntity;
import org.thingsboard.server.dao.model.sql.NotificationRuleInfoEntity;
@ -30,7 +31,7 @@ import java.util.List;
import java.util.UUID;
@Repository
public interface NotificationRuleRepository extends JpaRepository<NotificationRuleEntity, UUID> {
public interface NotificationRuleRepository extends JpaRepository<NotificationRuleEntity, UUID>, ExportableEntityRepository<NotificationRuleEntity> {
String RULE_INFO_QUERY = "SELECT new org.thingsboard.server.dao.model.sql.NotificationRuleInfoEntity(r, t.name, t.configuration) " +
"FROM NotificationRuleEntity r INNER JOIN NotificationTemplateEntity t ON r.templateId = t.id";
@ -59,4 +60,11 @@ public interface NotificationRuleRepository extends JpaRepository<NotificationRu
@Transactional
void deleteByTenantId(UUID tenantId);
NotificationRuleEntity findByTenantIdAndName(UUID tenantId, String name);
Page<NotificationRuleEntity> findByTenantId(UUID tenantId, Pageable pageable);
@Query("SELECT externalId FROM NotificationRuleEntity WHERE id = :id")
UUID getExternalIdByInternal(@Param("id") UUID internalId);
}

10
dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTargetRepository.java

@ -22,13 +22,14 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.dao.ExportableEntityRepository;
import org.thingsboard.server.dao.model.sql.NotificationTargetEntity;
import java.util.List;
import java.util.UUID;
@Repository
public interface NotificationTargetRepository extends JpaRepository<NotificationTargetEntity, UUID> {
public interface NotificationTargetRepository extends JpaRepository<NotificationTargetEntity, UUID>, ExportableEntityRepository<NotificationTargetEntity> {
@Query("SELECT t FROM NotificationTargetEntity t WHERE t.tenantId = :tenantId " +
"AND (:searchText = '' OR lower(t.name) LIKE lower(concat('%', :searchText, '%')))")
@ -52,4 +53,11 @@ public interface NotificationTargetRepository extends JpaRepository<Notification
long countByTenantId(UUID tenantId);
NotificationTargetEntity findByTenantIdAndName(UUID tenantId, String name);
Page<NotificationTargetEntity> findByTenantId(UUID tenantId, Pageable pageable);
@Query("SELECT externalId FROM NotificationTargetEntity WHERE id = :id")
UUID getExternalIdByInternal(@Param("id") UUID internalId);
}

10
dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTemplateRepository.java

@ -23,13 +23,14 @@ import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.dao.ExportableEntityRepository;
import org.thingsboard.server.dao.model.sql.NotificationTemplateEntity;
import java.util.List;
import java.util.UUID;
@Repository
public interface NotificationTemplateRepository extends JpaRepository<NotificationTemplateEntity, UUID> {
public interface NotificationTemplateRepository extends JpaRepository<NotificationTemplateEntity, UUID>, ExportableEntityRepository<NotificationTemplateEntity> {
@Query("SELECT t FROM NotificationTemplateEntity t WHERE t.tenantId = :tenantId AND " +
"t.notificationType IN :notificationTypes " +
@ -43,4 +44,11 @@ public interface NotificationTemplateRepository extends JpaRepository<Notificati
@Transactional
void deleteByTenantId(UUID tenantId);
NotificationTemplateEntity findByTenantIdAndName(UUID tenantId, String name);
Page<NotificationTemplateEntity> findByTenantId(UUID tenantId, Pageable pageable);
@Query("SELECT externalId FROM NotificationTemplateEntity WHERE id = :id")
UUID getExternalIdByInternal(@Param("id") UUID internalId);
}

5
dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java

@ -160,6 +160,11 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService {
return Optional.ofNullable(findWidgetsBundleById(tenantId, new WidgetsBundleId(entityId.getId())));
}
@Override
public void deleteEntity(TenantId tenantId, EntityId id) {
deleteWidgetsBundle(tenantId, (WidgetsBundleId) id);
}
@Override
public EntityType getEntityType() {
return EntityType.WIDGETS_BUNDLE;

12
dao/src/main/resources/sql/schema-entities.sql

@ -796,7 +796,9 @@ CREATE TABLE IF NOT EXISTS notification_target (
tenant_id UUID NOT NULL,
name VARCHAR(255) NOT NULL,
configuration VARCHAR(10000) NOT NULL,
CONSTRAINT uq_notification_target_name UNIQUE (tenant_id, name)
external_id UUID,
CONSTRAINT uq_notification_target_name UNIQUE (tenant_id, name),
CONSTRAINT uq_notification_target_external_id UNIQUE (tenant_id, external_id)
);
CREATE TABLE IF NOT EXISTS notification_template (
@ -806,7 +808,9 @@ CREATE TABLE IF NOT EXISTS notification_template (
name VARCHAR(255) NOT NULL,
notification_type VARCHAR(50) NOT NULL,
configuration VARCHAR(10000000) NOT NULL,
CONSTRAINT uq_notification_template_name UNIQUE (tenant_id, name)
external_id UUID,
CONSTRAINT uq_notification_template_name UNIQUE (tenant_id, name),
CONSTRAINT uq_notification_template_external_id UNIQUE (tenant_id, external_id)
);
CREATE TABLE IF NOT EXISTS notification_rule (
@ -820,7 +824,9 @@ CREATE TABLE IF NOT EXISTS notification_rule (
trigger_config VARCHAR(1000) NOT NULL,
recipients_config VARCHAR(10000) NOT NULL,
additional_config VARCHAR(255),
CONSTRAINT uq_notification_rule_name UNIQUE (tenant_id, name)
external_id UUID,
CONSTRAINT uq_notification_rule_name UNIQUE (tenant_id, name),
CONSTRAINT uq_notification_rule_external_id UNIQUE (tenant_id, external_id)
);
CREATE TABLE IF NOT EXISTS notification_request (

8
ui-ngx/src/app/core/http/entity.service.ts

@ -422,6 +422,14 @@ export class EntityService {
pageLink.sortOrder.property = 'name';
entitiesObservable = this.notificationService.getNotificationTargets(pageLink, subType as NotificationType, config);
break;
case EntityType.NOTIFICATION_TEMPLATE:
pageLink.sortOrder.property = 'name';
entitiesObservable = this.notificationService.getNotificationTemplates(pageLink, subType as NotificationType, config);
break;
case EntityType.NOTIFICATION_RULE:
pageLink.sortOrder.property = 'name';
entitiesObservable = this.notificationService.getNotificationRules(pageLink, config);
break;
}
return entitiesObservable;
}

4
ui-ngx/src/app/core/http/notification.service.ts

@ -35,7 +35,7 @@ import {
SlackConversation
} from '@shared/models/notification.models';
import { User } from '@shared/models/user.model';
import { isDefinedAndNotNull, isNotEmptyStr } from '@core/utils';
import { isNotEmptyStr } from '@core/utils';
@Injectable({
providedIn: 'root'
@ -169,7 +169,7 @@ export class NotificationService {
public getNotificationTemplates(pageLink: PageLink, notificationTypes?: NotificationType,
config?: RequestConfig): Observable<PageData<NotificationTemplate>> {
let url = `/api/notification/templates${pageLink.toQuery()}`;
if (isDefinedAndNotNull(notificationTypes)) {
if (isNotEmptyStr(notificationTypes)) {
url += `&notificationTypes=${notificationTypes}`;
}
return this.http.get<PageData<NotificationTemplate>>(url, defaultHttpOptionsFromConfig(config));

4
ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.html

@ -66,10 +66,10 @@
<mat-checkbox *ngIf="entityTypeFormGroup.get('entityType').value === entityTypes.DEVICE" formControlName="saveCredentials">
{{ 'version-control.export-credentials' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="saveAttributes">
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="saveAttributes">
{{ 'version-control.export-attributes' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="saveRelations">
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="saveRelations">
{{ 'version-control.export-relations' | translate }}
</mat-checkbox>
</div>

2
ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.ts

@ -29,6 +29,7 @@ import {
} from '@angular/forms';
import { PageComponent } from '@shared/components/page.component';
import {
entityTypesWithoutRelatedData,
EntityTypeVersionCreateConfig,
exportableEntityTypes,
SyncStrategy,
@ -73,6 +74,7 @@ export class EntityTypesVersionCreateComponent extends PageComponent implements
syncStrategyTranslations = syncStrategyTranslationMap;
entityTypes = EntityType;
entityTypesWithoutRelatedData = entityTypesWithoutRelatedData;
loading = true;

4
ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.html

@ -66,10 +66,10 @@
<mat-checkbox *ngIf="entityTypeFormGroup.get('entityType').value === entityTypes.DEVICE" formControlName="loadCredentials">
{{ 'version-control.load-credentials' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="loadAttributes">
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="loadAttributes">
{{ 'version-control.load-attributes' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="loadRelations">
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="loadRelations">
{{ 'version-control.load-relations' | translate }}
</mat-checkbox>
</div>

13
ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.ts

@ -18,22 +18,26 @@ import { Component, forwardRef, Input, OnInit, Renderer2, ViewContainerRef } fro
import {
AbstractControl,
ControlValueAccessor,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
UntypedFormArray,
UntypedFormBuilder,
UntypedFormControl,
UntypedFormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
Validator,
Validators
} from '@angular/forms';
import { PageComponent } from '@shared/components/page.component';
import { EntityTypeVersionLoadConfig, exportableEntityTypes, VersionCreationResult } from '@shared/models/vc.models';
import {
entityTypesWithoutRelatedData,
EntityTypeVersionLoadConfig,
exportableEntityTypes
} from '@shared/models/vc.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
import { MatCheckbox, MatCheckboxChange } from '@angular/material/checkbox';
import { MatCheckbox } from '@angular/material/checkbox';
import { TbPopoverService } from '@shared/components/popover.service';
import { RemoveOtherEntitiesConfirmComponent } from '@home/components/vc/remove-other-entities-confirm.component';
@ -66,6 +70,7 @@ export class EntityTypesVersionLoadComponent extends PageComponent implements On
public entityTypesVersionLoadFormGroup: UntypedFormGroup;
entityTypes = EntityType;
entityTypesWithoutRelatedData = entityTypesWithoutRelatedData;
loading = true;

6
ui-ngx/src/app/shared/models/entity-type.models.ts

@ -368,6 +368,8 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
EntityType.NOTIFICATION_RULE,
{
type: 'entity.type-notification-rule',
typePlural: 'entity.type-notification-rules',
list: 'entity.list-of-notification-rules',
noEntities: 'notification.no-rules-notification',
search: 'notification.search-rules',
selectedEntities: 'notification.selected-rules'
@ -377,6 +379,8 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
EntityType.NOTIFICATION_TARGET,
{
type: 'entity.type-notification-target',
typePlural: 'entity.type-notification-targets',
list: 'entity.list-of-notification-targets',
noEntities: 'notification.no-recipients-notification',
search: 'notification.search-recipients',
selectedEntities: 'notification.selected-recipients'
@ -386,6 +390,8 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
EntityType.NOTIFICATION_TEMPLATE,
{
type: 'entity.type-notification-template',
typePlural: 'entity.type-notification-templates',
list: 'entity.list-of-notification-templates',
noEntities: 'notification.no-notification-templates',
search: 'notification.search-templates',
selectedEntities: 'notification.selected-template'

9
ui-ngx/src/app/shared/models/notification.models.ts

@ -17,7 +17,7 @@
import { NotificationId } from '@shared/models/id/notification-id';
import { NotificationRequestId } from '@shared/models/id/notification-request-id';
import { UserId } from '@shared/models/id/user-id';
import { BaseData } from '@shared/models/base-data';
import { BaseData, ExportableEntity } from '@shared/models/base-data';
import { TenantId } from '@shared/models/id/tenant-id';
import { NotificationTargetId } from '@shared/models/id/notification-target-id';
import { NotificationTemplateId } from '@shared/models/id/notification-template-id';
@ -25,7 +25,6 @@ import { EntityId } from '@shared/models/id/entity-id';
import { NotificationRuleId } from '@shared/models/id/notification-rule-id';
import { AlarmSearchStatus, AlarmSeverity, AlarmStatus } from '@shared/models/alarm.models';
import { EntityType } from '@shared/models/entity-type.models';
import { User } from '@shared/models/user.model';
import { ApiFeature, ApiUsageStateValue } from '@shared/models/api-usage.models';
export interface Notification {
@ -107,7 +106,7 @@ export interface SlackConversation {
type: string;
}
export interface NotificationRule extends Omit<BaseData<NotificationRuleId>, 'label'>{
export interface NotificationRule extends Omit<BaseData<NotificationRuleId>, 'label'>, ExportableEntity<NotificationRuleId> {
tenantId: TenantId;
enabled: boolean;
templateId: NotificationTemplateId;
@ -235,7 +234,7 @@ export interface NonConfirmedNotificationEscalation {
targets: Array<string>;
}
export interface NotificationTarget extends Omit<BaseData<NotificationTargetId>, 'label'>{
export interface NotificationTarget extends Omit<BaseData<NotificationTargetId>, 'label'>, ExportableEntity<NotificationTargetId> {
tenantId: TenantId;
configuration: NotificationTargetConfig;
}
@ -280,7 +279,7 @@ export const NotificationTargetTypeTranslationMap = new Map<NotificationTargetTy
[NotificationTargetType.SLACK, 'notification.delivery-method.slack']
]);
export interface NotificationTemplate extends Omit<BaseData<NotificationTemplateId>, 'label'>{
export interface NotificationTemplate extends Omit<BaseData<NotificationTemplateId>, 'label'>, ExportableEntity<NotificationTemplateId> {
tenantId: TenantId;
notificationType: NotificationType;
configuration: NotificationTemplateConfig;

11
ui-ngx/src/app/shared/models/vc.models.ts

@ -30,9 +30,18 @@ export const exportableEntityTypes: Array<EntityType> = [
EntityType.DEVICE_PROFILE,
EntityType.ASSET_PROFILE,
EntityType.RULE_CHAIN,
EntityType.WIDGETS_BUNDLE
EntityType.WIDGETS_BUNDLE,
EntityType.NOTIFICATION_TEMPLATE,
EntityType.NOTIFICATION_TARGET,
EntityType.NOTIFICATION_RULE
];
export const entityTypesWithoutRelatedData: Set<EntityType> = new Set([
EntityType.NOTIFICATION_TEMPLATE,
EntityType.NOTIFICATION_TARGET,
EntityType.NOTIFICATION_RULE
]);
export interface VersionCreateConfig {
saveRelations: boolean;
saveAttributes: boolean;

8
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -2065,9 +2065,15 @@
"type-queue": "Queue",
"type-notification": "Notification",
"type-notification-rule": "Notification rule",
"type-notification-rules": "Notification rules",
"list-of-notification-rules": "{ count, plural, =1 {One notification rule} other {List of # notification rules} }",
"type-notification-target": "Notification recipient",
"type-notification-targets": "Notification recipients",
"list-of-notification-targets": "{ count, plural, =1 {One notification recipient} other {List of # notification recipients} }",
"type-notification-request": "Notification request",
"type-notification-template": "Notification template"
"type-notification-template": "Notification template",
"type-notification-templates": "Notification templates",
"list-of-notification-templates": "{ count, plural, =1 {One notification template} other {List of # notification templates} }"
},
"entity-field": {
"created-time": "Created time",

Loading…
Cancel
Save