Merge pull request #10273 from thingsboard/push-notifications-alarm-dashboard

Open default alarm dashboard if none set for mobile notifications
This commit is contained in:
Andrew Shvayka 2024-03-04 16:18:46 +01:00 committed by GitHub
commit b11a9df3fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 96 additions and 14 deletions

View File

@ -61,14 +61,7 @@ public class MobileAppNotificationChannel implements NotificationChannel<User, M
String subject = processedTemplate.getSubject(); String subject = processedTemplate.getSubject();
String body = processedTemplate.getBody(); String body = processedTemplate.getBody();
Map<String, String> data = Optional.ofNullable(processedTemplate.getAdditionalConfig()) Map<String, String> data = getNotificationData(processedTemplate, ctx);
.map(JacksonUtil::toFlatMap).orElseGet(HashMap::new);
Optional.ofNullable(ctx.getRequest().getInfo())
.map(NotificationInfo::getStateEntityId)
.ifPresent(stateEntityId -> {
data.put("stateEntityId", stateEntityId.getId().toString());
data.put("stateEntityType", stateEntityId.getEntityType().name());
});
for (String token : mobileSessions.keySet()) { for (String token : mobileSessions.keySet()) {
try { try {
firebaseService.sendMessage(ctx.getTenantId(), credentials, token, subject, body, data); firebaseService.sendMessage(ctx.getTenantId(), credentials, token, subject, body, data);
@ -87,6 +80,36 @@ public class MobileAppNotificationChannel implements NotificationChannel<User, M
} }
} }
private Map<String, String> getNotificationData(MobileAppDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) {
Map<String, String> data = Optional.ofNullable(processedTemplate.getAdditionalConfig())
.map(JacksonUtil::toFlatMap).orElseGet(HashMap::new);
NotificationInfo info = ctx.getRequest().getInfo();
if (info == null) {
return data;
}
Optional.ofNullable(info.getStateEntityId()).ifPresent(stateEntityId -> {
data.put("stateEntityId", stateEntityId.getId().toString());
data.put("stateEntityType", stateEntityId.getEntityType().name());
if (!"true".equals(data.get("onClick.enabled")) && info.getDashboardId() != null) {
data.put("onClick.enabled", "true");
data.put("onClick.linkType", "DASHBOARD");
data.put("onClick.setEntityIdInState", "true");
data.put("onClick.dashboardId", info.getDashboardId().toString());
}
});
data.put("notificationType", ctx.getNotificationType().name());
switch (ctx.getNotificationType()) {
case ALARM:
case ALARM_ASSIGNMENT:
case ALARM_COMMENT:
info.getTemplateData().forEach((key, value) -> {
data.put("info." + key, value);
});
break;
}
return data;
}
@Override @Override
public void check(TenantId tenantId) throws Exception { public void check(TenantId tenantId) throws Exception {
NotificationSettings systemSettings = notificationSettingsService.findNotificationSettings(TenantId.SYS_TENANT_ID); NotificationSettings systemSettings = notificationSettingsService.findNotificationSettings(TenantId.SYS_TENANT_ID);

View File

@ -65,6 +65,7 @@ public class AlarmAssignmentTriggerProcessor implements NotificationRuleTriggerP
.alarmSeverity(alarmInfo.getSeverity()) .alarmSeverity(alarmInfo.getSeverity())
.alarmStatus(alarmInfo.getStatus()) .alarmStatus(alarmInfo.getStatus())
.alarmCustomerId(alarmInfo.getCustomerId()) .alarmCustomerId(alarmInfo.getCustomerId())
.dashboardId(alarmInfo.getDashboardId())
.build(); .build();
} }

View File

@ -76,6 +76,7 @@ public class AlarmCommentTriggerProcessor implements NotificationRuleTriggerProc
.alarmSeverity(alarm.getSeverity()) .alarmSeverity(alarm.getSeverity())
.alarmStatus(alarm.getStatus()) .alarmStatus(alarm.getStatus())
.alarmCustomerId(alarm.getCustomerId()) .alarmCustomerId(alarm.getCustomerId())
.dashboardId(alarm.getDashboardId())
.build(); .build();
} }

View File

@ -22,11 +22,11 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.alarm.AlarmStatusFilter; import org.thingsboard.server.common.data.alarm.AlarmStatusFilter;
import org.thingsboard.server.common.data.notification.info.AlarmNotificationInfo; import org.thingsboard.server.common.data.notification.info.AlarmNotificationInfo;
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo; import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmTrigger;
import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig.AlarmAction; import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig.AlarmAction;
import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig.ClearRule; import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig.ClearRule;
import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType; import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmTrigger;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
import static org.thingsboard.server.common.data.util.CollectionsUtil.emptyOrContains; import static org.thingsboard.server.common.data.util.CollectionsUtil.emptyOrContains;
@ -111,6 +111,7 @@ public class AlarmTriggerProcessor implements NotificationRuleTriggerProcessor<A
.acknowledged(alarmInfo.isAcknowledged()) .acknowledged(alarmInfo.isAcknowledged())
.cleared(alarmInfo.isCleared()) .cleared(alarmInfo.isCleared())
.alarmCustomerId(alarmInfo.getCustomerId()) .alarmCustomerId(alarmInfo.getCustomerId())
.dashboardId(alarmInfo.getDashboardId())
.build(); .build();
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.common.data.alarm; package org.thingsboard.server.common.data.alarm;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
@ -30,6 +31,7 @@ import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
@ -37,6 +39,8 @@ import org.thingsboard.server.common.data.validation.Length;
import org.thingsboard.server.common.data.validation.NoXss; import org.thingsboard.server.common.data.validation.NoXss;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.UUID;
/** /**
* Created by ashvayka on 11.05.17. * Created by ashvayka on 11.05.17.
@ -160,4 +164,10 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId, Ha
} }
} }
@JsonIgnore
public DashboardId getDashboardId() {
return Optional.ofNullable(getDetails()).map(details -> details.get("dashboardId"))
.filter(JsonNode::isTextual).map(id -> new DashboardId(UUID.fromString(id.asText()))).orElse(null);
}
} }

View File

@ -31,4 +31,5 @@ public enum NotificationType {
RATE_LIMITS, RATE_LIMITS,
EDGE_CONNECTION, EDGE_CONNECTION,
EDGE_COMMUNICATION_FAILURE EDGE_COMMUNICATION_FAILURE
} }

View File

@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
@ -55,6 +56,7 @@ public class AlarmAssignmentNotificationInfo implements RuleOriginatedNotificati
private AlarmSeverity alarmSeverity; private AlarmSeverity alarmSeverity;
private AlarmStatus alarmStatus; private AlarmStatus alarmStatus;
private CustomerId alarmCustomerId; private CustomerId alarmCustomerId;
private DashboardId dashboardId;
@Override @Override
public Map<String, String> getTemplateData() { public Map<String, String> getTemplateData() {
@ -94,4 +96,9 @@ public class AlarmAssignmentNotificationInfo implements RuleOriginatedNotificati
return alarmOriginator; return alarmOriginator;
} }
@Override
public DashboardId getDashboardId() {
return dashboardId;
}
} }

View File

@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import java.util.Map; import java.util.Map;
@ -50,6 +51,7 @@ public class AlarmCommentNotificationInfo implements RuleOriginatedNotificationI
private AlarmSeverity alarmSeverity; private AlarmSeverity alarmSeverity;
private AlarmStatus alarmStatus; private AlarmStatus alarmStatus;
private CustomerId alarmCustomerId; private CustomerId alarmCustomerId;
private DashboardId dashboardId;
@Override @Override
public Map<String, String> getTemplateData() { public Map<String, String> getTemplateData() {
@ -80,4 +82,9 @@ public class AlarmCommentNotificationInfo implements RuleOriginatedNotificationI
return alarmOriginator; return alarmOriginator;
} }
@Override
public DashboardId getDashboardId() {
return dashboardId;
}
} }

View File

@ -22,6 +22,7 @@ import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import java.util.Map; import java.util.Map;
@ -45,6 +46,7 @@ public class AlarmNotificationInfo implements RuleOriginatedNotificationInfo {
private boolean acknowledged; private boolean acknowledged;
private boolean cleared; private boolean cleared;
private CustomerId alarmCustomerId; private CustomerId alarmCustomerId;
private DashboardId dashboardId;
@Override @Override
public Map<String, String> getTemplateData() { public Map<String, String> getTemplateData() {
@ -70,4 +72,9 @@ public class AlarmNotificationInfo implements RuleOriginatedNotificationInfo {
return alarmOriginator; return alarmOriginator;
} }
@Override
public DashboardId getDashboardId() {
return dashboardId;
}
} }

View File

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.notification.info;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import java.util.Map; import java.util.Map;
@ -33,4 +34,8 @@ public interface NotificationInfo {
return null; return null;
} }
default DashboardId getDashboardId() {
return null;
}
} }

View File

@ -20,10 +20,12 @@
[expanded]="actionButtonConfigForm.get('enabled').value"> [expanded]="actionButtonConfigForm.get('enabled').value">
<mat-expansion-panel-header fxLayout="row wrap" class="fill-width"> <mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title fxFlex="60"> <mat-panel-title fxFlex="60">
<div tb-hint-tooltip-icon="{{ sliderHint }}" class="tb-form-row no-border no-padding">
<mat-slide-toggle class="mat-slide" formControlName="enabled" (click)="$event.stopPropagation()" <mat-slide-toggle class="mat-slide" formControlName="enabled" (click)="$event.stopPropagation()"
fxLayoutAlign="center"> fxLayoutAlign="center">
{{ actionTitle }} {{ actionTitle }}
</mat-slide-toggle> </mat-slide-toggle>
</div>
</mat-panel-title> </mat-panel-title>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent class="tb-extension-panel"> <ng-template matExpansionPanelContent class="tb-extension-panel">

View File

@ -52,6 +52,9 @@ export class NotificationActionButtonConfigurationComponent implements ControlVa
@Input() @Input()
actionTitle: string; actionTitle: string;
@Input()
sliderHint: string;
private hideButtonTextValue = false; private hideButtonTextValue = false;
get hideButtonText(): boolean { get hideButtonText(): boolean {

View File

@ -124,6 +124,7 @@
<tb-notification-action-button-configuration <tb-notification-action-button-configuration
formControlName="onClick" formControlName="onClick"
hideButtonText hideButtonText
[sliderHint]="hotificationTapActionHint"
actionTitle="{{ 'notification.notification-tap-action' | translate }}"> actionTitle="{{ 'notification.notification-tap-action' | translate }}">
</tb-notification-action-button-configuration> </tb-notification-action-button-configuration>
</div> </div>

View File

@ -36,6 +36,7 @@ import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { isDefinedAndNotNull } from '@core/utils'; import { isDefinedAndNotNull } from '@core/utils';
import { coerceBoolean } from '@shared/decorators/coercion'; import { coerceBoolean } from '@shared/decorators/coercion';
import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({
selector: 'tb-template-configuration', selector: 'tb-template-configuration',
@ -96,7 +97,8 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co
private propagateChange = (v: any) => { }; private propagateChange = (v: any) => { };
private readonly destroy$ = new Subject<void>(); private readonly destroy$ = new Subject<void>();
constructor(private fb: FormBuilder) { constructor(private fb: FormBuilder,
private translate: TranslateService) {
this.templateConfigurationForm = this.buildForm(); this.templateConfigurationForm = this.buildForm();
this.templateConfigurationForm.valueChanges.pipe( this.templateConfigurationForm.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
@ -137,6 +139,16 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co
}; };
} }
get hotificationTapActionHint(): string {
switch (this.notificationType) {
case NotificationType.ALARM:
case NotificationType.ALARM_ASSIGNMENT:
case NotificationType.ALARM_COMMENT:
return this.translate.instant('notification.notification-tap-action-hint');
}
return '';
}
private updateDisabledForms(){ private updateDisabledForms(){
Object.values(NotificationDeliveryMethod).forEach((method) => { Object.values(NotificationDeliveryMethod).forEach((method) => {
const form = this.templateConfigurationForm.get(method); const form = this.templateConfigurationForm.get(method);

View File

@ -3349,6 +3349,7 @@
"notification": "Notification", "notification": "Notification",
"notification-center": "Notification center", "notification-center": "Notification center",
"notification-tap-action": "Notification tap action", "notification-tap-action": "Notification tap action",
"notification-tap-action-hint": "If not enabled, the default alarm dashboard will be used",
"notify": "notify", "notify": "notify",
"notify-again": "Notify again", "notify-again": "Notify again",
"notify-alarm-action": { "notify-alarm-action": {