Browse Source

UI: Add notification service

pull/7925/head
Vladyslav_Prykhodko 4 years ago
parent
commit
f47005892d
  1. 132
      ui-ngx/src/app/core/http/notification.service.ts
  2. 1
      ui-ngx/src/app/core/http/public-api.ts
  3. 4
      ui-ngx/src/app/core/notification/notification.effects.ts
  4. 2
      ui-ngx/src/app/core/services/public-api.ts
  5. 2
      ui-ngx/src/app/core/services/toast-notification.service.ts
  6. 4
      ui-ngx/src/app/modules/home/models/services.map.ts
  7. 4
      ui-ngx/src/app/shared/components/toast.directive.ts
  8. 6
      ui-ngx/src/app/shared/models/entity-type.models.ts
  9. 22
      ui-ngx/src/app/shared/models/id/notification-id.ts
  10. 26
      ui-ngx/src/app/shared/models/id/notification-request-id.ts
  11. 26
      ui-ngx/src/app/shared/models/id/notification-rule-id.ts
  12. 26
      ui-ngx/src/app/shared/models/id/notification-target-id.ts
  13. 26
      ui-ngx/src/app/shared/models/id/notification-template-id.ts
  14. 5
      ui-ngx/src/app/shared/models/id/public-api.ts
  15. 186
      ui-ngx/src/app/shared/models/notification.models.ts
  16. 1
      ui-ngx/src/app/shared/models/public-api.ts

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

@ -0,0 +1,132 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils';
import { Observable } from 'rxjs';
import { PageLink } from '@shared/models/page/page-link';
import { PageData } from '@shared/models/page/page-data';
import {
Notification,
NotificationRequest,
NotificationRule,
NotificationSettings,
NotificationTarget,
NotificationTemplate,
SlackChanelType,
SlackConversation
} from '@shared/models/notification.models';
import { User } from '@shared/models/user.model';
@Injectable({
providedIn: 'root'
})
export class NotificationService {
constructor(
private http: HttpClient
) {
}
public getNotifications(pageLink: PageLink, config?: RequestConfig): Observable<PageData<Notification>> {
return this.http.get<PageData<Notification>>(`/api/notifications${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config));
}
public markNotificationAsRead(id: string, config?: RequestConfig): Observable<void> {
return this.http.put<void>(`/api/notification/${id}/read`, defaultHttpOptionsFromConfig(config));
}
public createNotificationRequest(notification: NotificationRequest, config?: RequestConfig): Observable<any> {
return this.http.post<NotificationRequest>('/api/notification/request', notification, defaultHttpOptionsFromConfig(config));
}
public getNotificationRequestById(id: string, config?: RequestConfig): Observable<NotificationRequest> {
return this.http.get<NotificationRequest>(`/api/notification/request/${id}`, defaultHttpOptionsFromConfig(config));
}
public deleteNotificationRequest(id: string, config?: RequestConfig): Observable<void> {
return this.http.delete<void>(`/api/notification/request/${id}`, defaultHttpOptionsFromConfig(config));
}
public getNotificationRequests(pageLink: PageLink, config?: RequestConfig): Observable<PageData<NotificationRequest>> {
return this.http.get<PageData<NotificationRequest>>('/api/notification/request/', defaultHttpOptionsFromConfig(config));
}
public getNotificationSettings(config?: RequestConfig): Observable<NotificationSettings> {
return this.http.get<NotificationSettings>('/api/notification/settings', defaultHttpOptionsFromConfig(config));
}
public saveNotificationSettings(notificationSettings: NotificationSettings, config?: RequestConfig): Observable<NotificationSettings> {
return this.http.post<NotificationSettings>('/api/notification/settings', notificationSettings, defaultHttpOptionsFromConfig(config));
}
public listSlackConversations(type: SlackChanelType, config?: RequestConfig): Observable<Array<SlackConversation>> {
return this.http.get<Array<SlackConversation>>(`/api/notification/slack/conversations?type=${type}`,
defaultHttpOptionsFromConfig(config));
}
public saveNotificationRule(notificationRule: NotificationRule, config?: RequestConfig): Observable<NotificationRule> {
return this.http.post<NotificationRule>('/api/notification/rule', notificationRule, defaultHttpOptionsFromConfig(config));
}
public getNotificationRuleById(id: string, config?: RequestConfig): Observable<NotificationRule> {
return this.http.get<NotificationRule>(`/api/notification/rule/${id}`, defaultHttpOptionsFromConfig(config));
}
public deleteNotificationRule(id: string, config?: RequestConfig): Observable<void> {
return this.http.delete<void>(`/api/notification/rule/${id}`, defaultHttpOptionsFromConfig(config));
}
public getNotificationRules(pageLink: PageLink, config?: RequestConfig): Observable<PageData<NotificationRule>> {
return this.http.get<PageData<NotificationRule>>(`/api/notification/rules${pageLink.toQuery()}`, defaultHttpOptionsFromConfig(config));
}
public saveNotificationTarget(notificationTarget: NotificationTarget, config?: RequestConfig): Observable<NotificationTarget> {
return this.http.post<NotificationTarget>('/api/notification/target', notificationTarget, defaultHttpOptionsFromConfig(config));
}
public getNotificationTargetById(id: string, config?: RequestConfig): Observable<NotificationTarget> {
return this.http.get<NotificationTarget>(`/api/notification/target/${id}`, defaultHttpOptionsFromConfig(config));
}
public deleteNotificationTarget(id: string, config?: RequestConfig): Observable<void> {
return this.http.delete<void>(`/api/notification/target/${id}`, defaultHttpOptionsFromConfig(config));
}
public getNotificationTargets(pageLink: PageLink, config?: RequestConfig): Observable<PageData<NotificationTarget>> {
return this.http.get<PageData<NotificationTarget>>(`/api/notification/targets${pageLink.toQuery()}`,
defaultHttpOptionsFromConfig(config));
}
public getRecipientsForNotificationTargetConfig(notificationTarget: NotificationTarget, pageLink: PageLink,
config?: RequestConfig): Observable<PageData<User>> {
return this.http.post<PageData<User>>(`/api/notification/target/recipients${pageLink.toQuery()}`, notificationTarget,
defaultHttpOptionsFromConfig(config));
}
public saveNotificationTemplate(notificationTarget: NotificationTemplate, config?: RequestConfig): Observable<NotificationTemplate> {
return this.http.post<NotificationTemplate>('/api/notification/template', notificationTarget, defaultHttpOptionsFromConfig(config));
}
public getNotificationTemplateById(id: string, config?: RequestConfig): Observable<NotificationTemplate> {
return this.http.get<NotificationTemplate>(`/api/notification/template/${id}`, defaultHttpOptionsFromConfig(config));
}
public deleteNotificationTemplate(id: string, config?: RequestConfig): Observable<void> {
return this.http.delete<void>(`/api/notification/template/${id}`, defaultHttpOptionsFromConfig(config));
}
}

1
ui-ngx/src/app/core/http/public-api.ts

@ -30,6 +30,7 @@ export * from './entity-relation.service';
export * from './entity-view.service';
export * from './event.service';
export * from './http-utils';
export * from './notification.service';
export * from './oauth2.service';
export * from './ota-package.service';
export * from './queue.service';

4
ui-ngx/src/app/core/notification/notification.effects.ts

@ -19,13 +19,13 @@ import { Actions, Effect, ofType } from '@ngrx/effects';
import { map } from 'rxjs/operators';
import { NotificationActions, NotificationActionTypes } from '@app/core/notification/notification.actions';
import { NotificationService } from '@app/core/services/notification.service';
import { ToastNotificationService } from '@core/services/toast-notification.service';
@Injectable()
export class NotificationEffects {
constructor(
private actions$: Actions<NotificationActions>,
private notificationService: NotificationService
private notificationService: ToastNotificationService
) {
}

2
ui-ngx/src/app/core/services/public-api.ts

@ -23,7 +23,7 @@ export * from './dynamic-component-factory.service';
export * from './item-buffer.service';
export * from './menu.models';
export * from './menu.service';
export * from './notification.service';
export * from './toast-notification.service';
export * from './raf.service';
export * from './resources.service';
export * from './time.service';

2
ui-ngx/src/app/core/services/notification.service.ts → ui-ngx/src/app/core/services/toast-notification.service.ts

@ -24,7 +24,7 @@ import { Observable, Subject } from 'rxjs';
providedIn: 'root'
}
)
export class NotificationService {
export class ToastNotificationService {
private notificationSubject: Subject<NotificationMessage> = new Subject();

4
ui-ngx/src/app/modules/home/models/services.map.ts

@ -40,6 +40,7 @@ import { AuthService } from '@core/auth/auth.service';
import { ResourceService } from '@core/http/resource.service';
import { TwoFactorAuthenticationService } from '@core/http/two-factor-authentication.service';
import { TelemetryWebsocketService } from '@core/ws/telemetry-websocket.service';
import { NotificationService } from '@core/http/notification.service';
export const ServicesMap = new Map<string, Type<any>>(
[
@ -67,6 +68,7 @@ export const ServicesMap = new Map<string, Type<any>>(
['authService', AuthService],
['resourceService', ResourceService],
['twoFactorAuthenticationService', TwoFactorAuthenticationService],
['telemetryWsService', TelemetryWebsocketService]
['telemetryWsService', TelemetryWebsocketService],
['notificationService', NotificationService]
]
);

4
ui-ngx/src/app/shared/components/toast.directive.ts

@ -31,7 +31,7 @@ import {
import { MAT_SNACK_BAR_DATA, MatSnackBar, MatSnackBarConfig, MatSnackBarRef } from '@angular/material/snack-bar';
import { NotificationMessage } from '@app/core/notification/notification.models';
import { Subscription } from 'rxjs';
import { NotificationService } from '@app/core/services/notification.service';
import { ToastNotificationService } from '@core/services/toast-notification.service';
import { BreakpointObserver } from '@angular/cdk/layout';
import { MediaBreakpoints } from '@shared/models/constants';
import { MatButton } from '@angular/material/button';
@ -56,7 +56,7 @@ export class ToastDirective implements AfterViewInit, OnDestroy {
constructor(private elementRef: ElementRef,
private viewContainerRef: ViewContainerRef,
private notificationService: NotificationService,
private notificationService: ToastNotificationService,
private componentFactoryResolver: ComponentFactoryResolver,
private snackBar: MatSnackBar,
private ngZone: NgZone,

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

@ -38,7 +38,11 @@ export enum EntityType {
TB_RESOURCE = 'TB_RESOURCE',
OTA_PACKAGE = 'OTA_PACKAGE',
RPC = 'RPC',
QUEUE = 'QUEUE'
QUEUE = 'QUEUE',
NOTIFICATION_REQUEST = 'NOTIFICATION_REQUEST',
NOTIFICATION_RULE = 'NOTIFICATION_RULE',
NOTIFICATION_TARGET = 'NOTIFICATION_TARGET',
NOTIFICATION_TEMPLATE = 'NOTIFICATION_TEMPLATE'
}
export enum AliasEntityType {

22
ui-ngx/src/app/shared/models/id/notification-id.ts

@ -0,0 +1,22 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
export class NotificationId {
id: string;
constructor(id: string) {
this.id = id;
}
}

26
ui-ngx/src/app/shared/models/id/notification-request-id.ts

@ -0,0 +1,26 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { EntityId } from '@shared/models/id/entity-id';
import { EntityType } from '@shared/models/entity-type.models';
export class NotificationRequestId implements EntityId {
entityType = EntityType.NOTIFICATION_REQUEST;
id: string;
constructor(id: string) {
this.id = id;
}
}

26
ui-ngx/src/app/shared/models/id/notification-rule-id.ts

@ -0,0 +1,26 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { EntityId } from '@shared/models/id/entity-id';
import { EntityType } from '@shared/models/entity-type.models';
export class NotificationRuleId implements EntityId {
entityType = EntityType.NOTIFICATION_RULE;
id: string;
constructor(id: string) {
this.id = id;
}
}

26
ui-ngx/src/app/shared/models/id/notification-target-id.ts

@ -0,0 +1,26 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { EntityId } from '@shared/models/id/entity-id';
import { EntityType } from '@shared/models/entity-type.models';
export class NotificationTargetId implements EntityId {
entityType = EntityType.NOTIFICATION_TARGET;
id: string;
constructor(id: string) {
this.id = id;
}
}

26
ui-ngx/src/app/shared/models/id/notification-template-id.ts

@ -0,0 +1,26 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { EntityId } from '@shared/models/id/entity-id';
import { EntityType } from '@shared/models/entity-type.models';
export class NotificationTemplateId implements EntityId {
entityType = EntityType.NOTIFICATION_TEMPLATE;
id: string;
constructor(id: string) {
this.id = id;
}
}

5
ui-ngx/src/app/shared/models/id/public-api.ts

@ -26,6 +26,11 @@ export * from './entity-id';
export * from './entity-view-id';
export * from './event-id';
export * from './has-uuid';
export * from './notification-id';
export * from './notification-request-id';
export * from './notification-rule-id';
export * from './notification-target-id';
export * from './notification-template-id';
export * from './ota-package-id';
export * from './rpc-id';
export * from './rule-chain-id';

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

@ -0,0 +1,186 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
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 { DashboardId } from '@shared/models/id/dashboard-id';
import { BaseData } 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';
import { EntityId } from '@shared/models/id/entity-id';
import { NotificationRuleId } from '@shared/models/id/notification-rule-id';
export interface Notification {
readonly id: NotificationId;
readonly requestId: NotificationRequestId;
readonly recipientId: UserId;
readonly type: string;
readonly text: string;
readonly info: NotificationInfo;
readonly originatorType: NotificationOriginatorType;
readonly status: NotificationStatus;
}
export interface NotificationInfo {
description: string;
dashboardId: DashboardId;
originatorType: NotificationOriginatorType;
}
export interface NotificationRequest extends Omit<BaseData<NotificationRequestId>, 'label'> {
tenantId?: TenantId;
targets: Array<NotificationTargetId>;
templateId: NotificationTemplateId;
info?: NotificationInfo;
deliveryMethods: Array<NotificationDeliveryMethod>;
originatorEntityId: EntityId;
originatorType: NotificationOriginatorType;
status: NotificationRequestStatus;
stats: NotificationRequestStats;
additionalConfig: NotificationRequestConfig;
}
export interface NotificationRequestStats {
sent: Map<NotificationDeliveryMethod, any>;
errors: Map<NotificationDeliveryMethod, Map<string, string>>;
processedRecipients: Map<NotificationDeliveryMethod, Set<UserId>>;
}
export interface NotificationRequestConfig {
sendingDelayInSec: number;
}
export interface NotificationSettings {
deliveryMethodsConfigs: Map<NotificationDeliveryMethod, NotificationDeliveryMethodConfig>;
}
export interface NotificationDeliveryMethodConfig {
enabled: boolean;
method: NotificationDeliveryMethod;
}
export interface SlackConversation {
id: string;
name: string;
}
export interface NotificationRule extends Omit<BaseData<NotificationRuleId>, 'label'>{
tenantId: TenantId;
templateId: NotificationTemplateId;
deliveryMethods: Array<NotificationDeliveryMethod>;
configuration: NotificationRuleConfig;
}
export interface NotificationRuleConfig {
initialNotificationTargetId: NotificationTargetId;
escalationConfig: NotificationEscalationConfig;
}
export interface NotificationEscalationConfig {
escalations: Array<NonConfirmedNotificationEscalation>;
}
export interface NonConfirmedNotificationEscalation {
delayInSec: number;
notificationTargetId: NotificationTargetId;
}
export interface NotificationTarget extends Omit<BaseData<NotificationTargetId>, 'label'>{
tenantId: TenantId;
configuration: NotificationTargetConfig;
}
export interface NotificationTargetConfig extends
Partial<SingleUserNotificationTargetConfig & UserListNotificationTargetConfig & CustomerUsersNotificationTargetConfig>{
type: NotificationTargetConfigType;
}
interface SingleUserNotificationTargetConfig {
userId: string;
}
interface UserListNotificationTargetConfig {
usersIds: Array<string>;
}
interface CustomerUsersNotificationTargetConfig {
customerId: string;
getCustomerIdFromOriginatorEntity: boolean;
}
export interface NotificationTemplate extends Omit<BaseData<NotificationTemplateId>, 'label'>{
tenantId: TenantId;
notificationType: string;
configuration: NotificationTemplateConfig;
}
interface NotificationTemplateConfig {
defaultTextTemplate: string;
templates: Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate>;
}
interface DeliveryMethodNotificationTemplate extends
Partial<EmailDeliveryMethodNotificationTemplate & SlackDeliveryMethodNotificationTemplate>{
body: string;
method: NotificationDeliveryMethod;
}
interface EmailDeliveryMethodNotificationTemplate {
subject: string;
}
interface SlackDeliveryMethodNotificationTemplate {
conversationType: SlackChanelType;
conversationId: string;
}
export enum NotificationOriginatorType {
ADMIN = 'ADMIN',
ALARM = 'ALARM',
RULE_NODE = 'RULE_NODE'
}
export enum NotificationStatus {
SENT = 'SENT',
READ = 'READ'
}
export enum NotificationDeliveryMethod {
WEBSOCKET = 'WEBSOCKET',
SMS = 'SMS',
EMAIL = 'EMAIL',
SLACK = 'SLACK'
}
export enum NotificationRequestStatus {
PROCESSED = 'PROCESSED',
SCHEDULED = 'SCHEDULED'
}
export enum SlackChanelType {
USER= 'USER',
PUBLIC_CHANNEL = 'PUBLIC_CHANNEL',
PRIVATE_CHANNEL = 'PRIVATE_CHANNEL'
}
export enum NotificationTargetConfigType {
SINGLE_USER = 'SINGLE_USER',
USER_LIST = 'USER_LIST',
CUSTOMER_USERS = 'CUSTOMER_USERS',
ALL_USERS = 'ALL_USERS'
}

1
ui-ngx/src/app/shared/models/public-api.ts

@ -38,6 +38,7 @@ export * from './error.models';
export * from './event.models';
export * from './login.models';
export * from './material.models';
export * from './notification.models';
export * from './oauth2.models';
export * from './queue.models';
export * from './relation.models';

Loading…
Cancel
Save