UI: Add notification center and targets notification block
This commit is contained in:
parent
1317a8aca9
commit
9051759ce8
@ -129,4 +129,9 @@ export class NotificationService {
|
|||||||
public deleteNotificationTemplate(id: string, config?: RequestConfig): Observable<void> {
|
public deleteNotificationTemplate(id: string, config?: RequestConfig): Observable<void> {
|
||||||
return this.http.delete<void>(`/api/notification/template/${id}`, defaultHttpOptionsFromConfig(config));
|
return this.http.delete<void>(`/api/notification/template/${id}`, defaultHttpOptionsFromConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getNotificationTemplates(pageLink: PageLink, config?: RequestConfig): Observable<PageData<NotificationTemplate>> {
|
||||||
|
return this.http.get<PageData<NotificationTemplate>>(`/api/notification/templates${pageLink.toQuery()}`,
|
||||||
|
defaultHttpOptionsFromConfig(config));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,6 +103,13 @@ export class MenuService {
|
|||||||
path: '/widgets-bundles',
|
path: '/widgets-bundles',
|
||||||
icon: 'now_widgets'
|
icon: 'now_widgets'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: guid(),
|
||||||
|
name: 'notification.notification-center',
|
||||||
|
type: 'link',
|
||||||
|
path: '/notification-center',
|
||||||
|
icon: 'notifications'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: guid(),
|
id: guid(),
|
||||||
name: 'admin.system-settings',
|
name: 'admin.system-settings',
|
||||||
@ -203,6 +210,16 @@ export class MenuService {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'notification.management',
|
||||||
|
places: [
|
||||||
|
{
|
||||||
|
name: 'notification.notification-center',
|
||||||
|
path: '/notification-center',
|
||||||
|
icon: 'notifications'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'admin.system-settings',
|
name: 'admin.system-settings',
|
||||||
places: [
|
places: [
|
||||||
@ -396,6 +413,13 @@ export class MenuService {
|
|||||||
path: '/usage',
|
path: '/usage',
|
||||||
icon: 'insert_chart'
|
icon: 'insert_chart'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: guid(),
|
||||||
|
name: 'notification.notification-center',
|
||||||
|
type: 'link',
|
||||||
|
path: '/notification-center',
|
||||||
|
icon: 'notifications'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: guid(),
|
id: guid(),
|
||||||
name: 'admin.system-settings',
|
name: 'admin.system-settings',
|
||||||
@ -554,6 +578,16 @@ export class MenuService {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'notification.management',
|
||||||
|
places: [
|
||||||
|
{
|
||||||
|
name: 'notification.notification-center',
|
||||||
|
path: '/notification-center',
|
||||||
|
icon: 'notifications'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'audit-log.audit',
|
name: 'audit-log.audit',
|
||||||
places: [
|
places: [
|
||||||
@ -648,7 +682,14 @@ export class MenuService {
|
|||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/dashboards',
|
path: '/dashboards',
|
||||||
icon: 'dashboard'
|
icon: 'dashboard'
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
id: guid(),
|
||||||
|
name: 'notification.notification-center',
|
||||||
|
type: 'link',
|
||||||
|
path: '/notification-center',
|
||||||
|
icon: 'notifications'
|
||||||
|
},
|
||||||
);
|
);
|
||||||
return sections;
|
return sections;
|
||||||
}
|
}
|
||||||
@ -711,6 +752,16 @@ export class MenuService {
|
|||||||
path: '/dashboards'
|
path: '/dashboards'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'notification.management',
|
||||||
|
places: [
|
||||||
|
{
|
||||||
|
name: 'notification.notification-center',
|
||||||
|
path: '/notification-center',
|
||||||
|
icon: 'notifications'
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return homeSections;
|
return homeSections;
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
<mat-drawer-content>
|
<mat-drawer-content>
|
||||||
<div class="mat-padding tb-entity-table tb-absolute-fill">
|
<div class="mat-padding tb-entity-table tb-absolute-fill">
|
||||||
<div fxLayout="column" class="mat-elevation-z1 tb-entity-table-content">
|
<div fxLayout="column" class="mat-elevation-z1 tb-entity-table-content">
|
||||||
<mat-toolbar class="mat-table-toolbar" [fxShow]="!textSearchMode && dataSource.selection.isEmpty()">
|
<mat-toolbar class="mat-table-toolbar" [fxShow]="!textSearchMode && dataSource.selection.isEmpty() && entitiesTableConfig.showTitle">
|
||||||
<div class="mat-toolbar-tools">
|
<div class="mat-toolbar-tools">
|
||||||
<div fxLayout="row" fxLayoutAlign="start center" fxLayout.xs="column" fxLayoutAlign.xs="center start" class="title-container">
|
<div fxLayout="row" fxLayoutAlign="start center" fxLayout.xs="column" fxLayoutAlign.xs="center start" class="title-container">
|
||||||
<span *ngIf="entitiesTableConfig.tableTitle" class="tb-entity-table-title">{{ entitiesTableConfig.tableTitle }}</span>
|
<span *ngIf="entitiesTableConfig.tableTitle" class="tb-entity-table-title">{{ entitiesTableConfig.tableTitle }}</span>
|
||||||
|
|||||||
@ -148,6 +148,7 @@ export class EntityTableConfig<T extends BaseData<HasId>, P extends PageLink = P
|
|||||||
useTimePageLink = false;
|
useTimePageLink = false;
|
||||||
defaultTimewindowInterval = historyInterval(DAY);
|
defaultTimewindowInterval = historyInterval(DAY);
|
||||||
entityType: EntityType = null;
|
entityType: EntityType = null;
|
||||||
|
showTitle = true;
|
||||||
tableTitle = '';
|
tableTitle = '';
|
||||||
selectionEnabled = true;
|
selectionEnabled = true;
|
||||||
searchEnabled = true;
|
searchEnabled = true;
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import { OtaUpdateModule } from '@home/pages/ota-update/ota-update.module';
|
|||||||
import { VcModule } from '@home/pages/vc/vc.module';
|
import { VcModule } from '@home/pages/vc/vc.module';
|
||||||
import { AssetProfileModule } from '@home/pages/asset-profile/asset-profile.module';
|
import { AssetProfileModule } from '@home/pages/asset-profile/asset-profile.module';
|
||||||
import { ProfilesModule } from '@home/pages/profiles/profiles.module';
|
import { ProfilesModule } from '@home/pages/profiles/profiles.module';
|
||||||
|
import { NotificationCenterModule } from '@home/pages/notification-center/notification-center.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
exports: [
|
exports: [
|
||||||
@ -64,6 +65,7 @@ import { ProfilesModule } from '@home/pages/profiles/profiles.module';
|
|||||||
ApiUsageModule,
|
ApiUsageModule,
|
||||||
OtaUpdateModule,
|
OtaUpdateModule,
|
||||||
UserModule,
|
UserModule,
|
||||||
|
NotificationCenterModule,
|
||||||
VcModule
|
VcModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@ -0,0 +1,41 @@
|
|||||||
|
///
|
||||||
|
/// 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 { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { Authority } from '@shared/models/authority.enum';
|
||||||
|
import { NotificationCenterComponent } from '@home/pages/notification-center/notification-center.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: 'notification-center',
|
||||||
|
component: NotificationCenterComponent,
|
||||||
|
data: {
|
||||||
|
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN, Authority.CUSTOMER_USER],
|
||||||
|
title: 'notification.notification-center',
|
||||||
|
breadcrumb: {
|
||||||
|
label: 'notification.notification-center',
|
||||||
|
icon: 'notifications'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class NotificationCenterRoutingModule { }
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<div class="tb-notification-center">
|
||||||
|
<div class="tb-notification-center-content">
|
||||||
|
<section fxLayout="row" fxLayoutAlign="space-between center" class="title-container">
|
||||||
|
<h2 translate class="title">notification.notification-center</h2>
|
||||||
|
<section class="action-buttons" fxLayoutAlign="end center">
|
||||||
|
<button mat-icon-button [disabled]="isLoading$ | async" (click)="openSetting()"
|
||||||
|
matTooltip="{{ 'notification.settings' | translate }}"
|
||||||
|
matTooltipPosition="above">
|
||||||
|
<mat-icon>settings</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button [disabled]="isLoading$ | async" (click)="updateData()"
|
||||||
|
matTooltip="{{ 'action.refresh' | translate }}"
|
||||||
|
matTooltipPosition="above">
|
||||||
|
<mat-icon>refresh</mat-icon>
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<div class="tabs-container">
|
||||||
|
<mat-tab-group #matTabGroup (selectedIndexChange)="updateData()">
|
||||||
|
<mat-tab label="{{ 'notification.inbox' | translate }}" #inboxTab="matTab">
|
||||||
|
<tb-notification-table
|
||||||
|
[notificationType]="entityType.NOTIFICATION">
|
||||||
|
</tb-notification-table>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab label="{{ 'notification.sent' | translate }}">
|
||||||
|
<tb-notification-table
|
||||||
|
[notificationType]="entityType.NOTIFICATION_REQUEST">
|
||||||
|
</tb-notification-table>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab label="{{ 'notification.templates' | translate }}" #templateTab="matTab">
|
||||||
|
<tb-notification-table
|
||||||
|
[notificationType]="entityType.NOTIFICATION_TEMPLATE">
|
||||||
|
</tb-notification-table>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab label="{{ 'notification.targets' | translate }}" #targetsTab="matTab">
|
||||||
|
<tb-notification-table
|
||||||
|
[notificationType]="entityType.NOTIFICATION_TARGET">
|
||||||
|
</tb-notification-table>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab label="{{ 'notification.rules' | translate }}">
|
||||||
|
<ng-template matTabContent>
|
||||||
|
Content 1 - Loaded
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab disabled>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
|
||||||
|
<button mat-flat-button color="primary" *ngIf="targetsTab.isActive" (click)="createTarget($event)">
|
||||||
|
<div fxLayout="row" fxLayoutAlign="start center">
|
||||||
|
<mat-icon>add</mat-icon>{{ 'notification.create-target' | translate }}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
</mat-tab-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,177 @@
|
|||||||
|
/**
|
||||||
|
* 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 '../../../../../scss/constants';
|
||||||
|
|
||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
.tb-notification-center {
|
||||||
|
padding: 8px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
.tb-notification-center-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 4px 10px rgba(23, 33, 90, 0.08);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.title-container {
|
||||||
|
padding: 16px 16px 0;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 8px;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
color: rgba(0,0,0,.54);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-container {
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
//.mat-toolbar-tools{
|
||||||
|
// min-height: auto;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.title-container{
|
||||||
|
// overflow: hidden;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.tb-entity-table-title {
|
||||||
|
// padding-right: 20px;
|
||||||
|
// white-space: nowrap;
|
||||||
|
// overflow: hidden;
|
||||||
|
// text-overflow: ellipsis;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.table-container {
|
||||||
|
// overflow: auto;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.tb-entity-table-info{
|
||||||
|
// white-space: nowrap;
|
||||||
|
// overflow: hidden;
|
||||||
|
// text-overflow: ellipsis;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.button-widget-action{
|
||||||
|
// margin-left: auto;
|
||||||
|
// overflow: hidden;
|
||||||
|
// text-overflow: ellipsis;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@media #{$mat-xs} {
|
||||||
|
// .mat-toolbar {
|
||||||
|
// height: auto;
|
||||||
|
// min-height: 100px;
|
||||||
|
//
|
||||||
|
// .tb-entity-table-title{
|
||||||
|
// padding-bottom: 5px;
|
||||||
|
// width: 100%;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
@media #{$mat-xs} {
|
||||||
|
.tb-notification-center {
|
||||||
|
.tb-notification-center-content {
|
||||||
|
.title-container {
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep {
|
||||||
|
.tabs-container {
|
||||||
|
.mat-tab-group {
|
||||||
|
> .mat-tab-body-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 49px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
> .mat-tab-header {
|
||||||
|
.mat-tab-label {
|
||||||
|
min-width: 40px;
|
||||||
|
|
||||||
|
&.mat-tab-disabled {
|
||||||
|
opacity: 1;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.mat-tab-label-content {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-entity-table {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//:host ::ng-deep {
|
||||||
|
// .mat-sort-header-sorted .mat-sort-header-arrow {
|
||||||
|
// opacity: 1 !important;
|
||||||
|
// }
|
||||||
|
// tb-branch-autocomplete {
|
||||||
|
// mat-form-field {
|
||||||
|
// font-size: 16px;
|
||||||
|
// width: 250px;
|
||||||
|
//
|
||||||
|
// .mat-form-field-wrapper {
|
||||||
|
// padding-bottom: 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// .mat-form-field-underline {
|
||||||
|
// bottom: 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @media #{$mat-xs} {
|
||||||
|
// width: 100%;
|
||||||
|
//
|
||||||
|
// .mat-form-field-infix {
|
||||||
|
// width: auto !important;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2022 The Thingsboard Authors
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
|
||||||
|
import { Component, QueryList, ViewChild, ViewChildren } from '@angular/core';
|
||||||
|
import { PageComponent } from '@shared/components/page.component';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { MatTabGroup } from '@angular/material/tabs';
|
||||||
|
import {
|
||||||
|
NotificationTableComponent
|
||||||
|
} from '@home/pages/notification-center/notification-table/notification-table.component';
|
||||||
|
import { EntityType } from '@shared/models/entity-type.models';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-notification-center',
|
||||||
|
templateUrl: './notification-center.component.html',
|
||||||
|
styleUrls: ['notification-center.component.scss']
|
||||||
|
})
|
||||||
|
export class NotificationCenterComponent extends PageComponent {
|
||||||
|
|
||||||
|
entityType = EntityType;
|
||||||
|
|
||||||
|
@ViewChild('matTabGroup', {static: true}) matTabs: MatTabGroup;
|
||||||
|
@ViewChildren(NotificationTableComponent) tableComponent: QueryList<NotificationTableComponent>;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected store: Store<AppState>) {
|
||||||
|
super(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData() {
|
||||||
|
this.currentTableComponent?.updateData();
|
||||||
|
}
|
||||||
|
|
||||||
|
openSetting() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private get currentTableComponent(): NotificationTableComponent {
|
||||||
|
return this.tableComponent.get(this.matTabs.selectedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
createTarget($event: Event) {
|
||||||
|
this.currentTableComponent?.onEntityAction({event: $event, action: 'add', entity: null});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
///
|
||||||
|
/// 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 { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { SharedModule } from '@shared/shared.module';
|
||||||
|
import { NotificationCenterRoutingModule } from './notification-center-routing.module';
|
||||||
|
import { NotificationCenterComponent } from './notification-center.component';
|
||||||
|
import { HomeComponentsModule } from '@home/components/home-components.module';
|
||||||
|
import {
|
||||||
|
TargetNotificationDialogComponent
|
||||||
|
} from '@home/pages/notification-center/targets-table/target-notification-dialog.componet';
|
||||||
|
import { NotificationTableComponent } from '@home/pages/notification-center/notification-table/notification-table.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
NotificationCenterComponent,
|
||||||
|
TargetNotificationDialogComponent,
|
||||||
|
NotificationTableComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
SharedModule,
|
||||||
|
NotificationCenterRoutingModule,
|
||||||
|
HomeComponentsModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class NotificationCenterModule { }
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
///
|
||||||
|
/// 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 {
|
||||||
|
DateEntityTableColumn,
|
||||||
|
EntityTableColumn,
|
||||||
|
EntityTableConfig
|
||||||
|
} from '@home/models/entity/entities-table-config.models';
|
||||||
|
import { EntityTypeResource } from '@shared/models/entity-type.models';
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
import { Direction } from '@shared/models/page/sort-order';
|
||||||
|
import { Notification } from '@shared/models/notification.models';
|
||||||
|
import { NotificationService } from '@core/http/notification.service';
|
||||||
|
|
||||||
|
export class InboxTableConfig extends EntityTableConfig<Notification> {
|
||||||
|
|
||||||
|
constructor(private notificationService: NotificationService,
|
||||||
|
private datePipe: DatePipe,
|
||||||
|
updateOnInit = true) {
|
||||||
|
super();
|
||||||
|
this.loadDataOnInit = true;
|
||||||
|
this.entitiesDeleteEnabled = false;
|
||||||
|
this.entityTranslations = {
|
||||||
|
noEntities: 'notification.no-inbox-notification'
|
||||||
|
};
|
||||||
|
this.entityResources = {} as EntityTypeResource<Notification>;
|
||||||
|
|
||||||
|
this.entitiesFetchFunction = pageLink => this.notificationService.getNotifications(pageLink);
|
||||||
|
|
||||||
|
this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC};
|
||||||
|
|
||||||
|
this.columns.push(
|
||||||
|
new DateEntityTableColumn<Notification>('createdTime', 'notification.created-time', this.datePipe, '150px'),
|
||||||
|
new EntityTableColumn<Notification>('type', 'notification.type', '10%'),
|
||||||
|
new EntityTableColumn<Notification>('text', 'notification.text', '40%'),
|
||||||
|
new EntityTableColumn<Notification>('info.description', 'notification.description', '50%')
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<tb-entities-table [entitiesTableConfig]="entityTableConfig"></tb-entities-table>
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
///
|
||||||
|
/// 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 { Component, Input, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
|
||||||
|
import { NotificationService } from '@core/http/notification.service';
|
||||||
|
import { TargetsTableConfig } from '@home/pages/notification-center/notification-table/targets-table-config';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { EntityType } from '@shared/models/entity-type.models';
|
||||||
|
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
|
||||||
|
import { InboxTableConfig } from '@home/pages/notification-center/notification-table/inbox-table-config';
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
import { TemplateTableConfig } from '@home/pages/notification-center/notification-table/template-table-config';
|
||||||
|
import { EntityAction } from '@home/models/entity/entity-component.models';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-notification-table',
|
||||||
|
templateUrl: './notification-table.component.html'
|
||||||
|
})
|
||||||
|
export class NotificationTableComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
notificationType = EntityType.NOTIFICATION;
|
||||||
|
|
||||||
|
@ViewChild(EntitiesTableComponent, {static: true}) entitiesTable: EntitiesTableComponent;
|
||||||
|
|
||||||
|
entityTableConfig: EntityTableConfig<any>;
|
||||||
|
|
||||||
|
constructor(private notificationService: NotificationService,
|
||||||
|
private translate: TranslateService,
|
||||||
|
private datePipe: DatePipe,
|
||||||
|
private dialog: MatDialog) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.entityTableConfig = this.getTableConfig();
|
||||||
|
this.entityTableConfig.pageMode = false;
|
||||||
|
this.entityTableConfig.showTitle = false;
|
||||||
|
this.entityTableConfig.detailsPanelEnabled = false;
|
||||||
|
this.entityTableConfig.selectionEnabled = false;
|
||||||
|
this.entityTableConfig.searchEnabled = false;
|
||||||
|
this.entityTableConfig.addEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData() {
|
||||||
|
this.entitiesTable.updateData();
|
||||||
|
}
|
||||||
|
|
||||||
|
onEntityAction(action: EntityAction<any>) {
|
||||||
|
if (this.entityTableConfig.onEntityAction) {
|
||||||
|
this.entityTableConfig.onEntityAction(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTableConfig(): EntityTableConfig<any> {
|
||||||
|
switch (this.notificationType) {
|
||||||
|
case EntityType.NOTIFICATION_TARGET:
|
||||||
|
return new TargetsTableConfig(
|
||||||
|
this.notificationService,
|
||||||
|
this.translate,
|
||||||
|
this.dialog
|
||||||
|
);
|
||||||
|
case EntityType.NOTIFICATION:
|
||||||
|
return new InboxTableConfig(
|
||||||
|
this.notificationService,
|
||||||
|
this.datePipe
|
||||||
|
);
|
||||||
|
case EntityType.NOTIFICATION_TEMPLATE:
|
||||||
|
return new TemplateTableConfig(
|
||||||
|
this.notificationService,
|
||||||
|
this.datePipe
|
||||||
|
);
|
||||||
|
case EntityType.NOTIFICATION_REQUEST:
|
||||||
|
return new TemplateTableConfig(
|
||||||
|
this.notificationService,
|
||||||
|
this.datePipe
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
///
|
||||||
|
/// 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 {
|
||||||
|
CellActionDescriptor,
|
||||||
|
EntityTableColumn,
|
||||||
|
EntityTableConfig
|
||||||
|
} from '@home/models/entity/entities-table-config.models';
|
||||||
|
import { EntityTypeResource } from '@shared/models/entity-type.models';
|
||||||
|
import { Direction } from '@shared/models/page/sort-order';
|
||||||
|
import { NotificationTarget, NotificationTargetConfigTypeTranslateMap } from '@shared/models/notification.models';
|
||||||
|
import { NotificationService } from '@core/http/notification.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import {
|
||||||
|
TargetNotificationDialogComponent,
|
||||||
|
TargetsNotificationDialogData
|
||||||
|
} from '@home/pages/notification-center/targets-table/target-notification-dialog.componet';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { EntityAction } from '@home/models/entity/entity-component.models';
|
||||||
|
|
||||||
|
export class TargetsTableConfig extends EntityTableConfig<NotificationTarget> {
|
||||||
|
|
||||||
|
constructor(private notificationService: NotificationService,
|
||||||
|
private translate: TranslateService,
|
||||||
|
private dialog: MatDialog) {
|
||||||
|
super();
|
||||||
|
this.loadDataOnInit = false;
|
||||||
|
this.entityTranslations = {
|
||||||
|
noEntities: 'notification.no-targets-notification'
|
||||||
|
};
|
||||||
|
this.entityResources = {} as EntityTypeResource<NotificationTarget>;
|
||||||
|
|
||||||
|
this.entitiesFetchFunction = pageLink => this.notificationService.getNotificationTargets(pageLink);
|
||||||
|
|
||||||
|
this.deleteEntityTitle = target => this.translate.instant('notification.delete-target-title', {targetName: target.name});
|
||||||
|
this.deleteEntityContent = () => this.translate.instant('notification.delete-target-text');
|
||||||
|
this.deleteEntity = id => this.notificationService.deleteNotificationTarget(id.id);
|
||||||
|
|
||||||
|
this.cellActionDescriptors = this.configureCellActions();
|
||||||
|
this.onEntityAction = action => this.onTargetAction(action);
|
||||||
|
|
||||||
|
this.defaultSortOrder = {property: 'name', direction: Direction.ASC};
|
||||||
|
|
||||||
|
this.columns.push(
|
||||||
|
new EntityTableColumn<NotificationTarget>('name', 'notification.notification-target', '30%'),
|
||||||
|
new EntityTableColumn<NotificationTarget>('configuration.type', 'notification.type', '40%',
|
||||||
|
(target) => this.translate.instant(NotificationTargetConfigTypeTranslateMap.get(target.configuration.type)),
|
||||||
|
() => ({}), false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private configureCellActions(): Array<CellActionDescriptor<NotificationTarget>> {
|
||||||
|
return [{
|
||||||
|
name: this.translate.instant('device.make-public'),
|
||||||
|
icon: 'edit',
|
||||||
|
isEnabled: () => true,
|
||||||
|
onAction: ($event, entity) => this.editTarget($event, entity)
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
private editTarget($event: Event, target: NotificationTarget, isAdd = false) {
|
||||||
|
if ($event) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
}
|
||||||
|
this.dialog.open<TargetNotificationDialogComponent, TargetsNotificationDialogData,
|
||||||
|
NotificationTarget>(TargetNotificationDialogComponent, {
|
||||||
|
disableClose: true,
|
||||||
|
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
||||||
|
data: {
|
||||||
|
isAdd,
|
||||||
|
target
|
||||||
|
}
|
||||||
|
}).afterClosed()
|
||||||
|
.subscribe((res) => {
|
||||||
|
if (res) {
|
||||||
|
this.updateData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private onTargetAction(action: EntityAction<NotificationTarget>): boolean {
|
||||||
|
switch (action.action) {
|
||||||
|
case 'add':
|
||||||
|
this.editTarget(action.event, action.entity, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
///
|
||||||
|
/// 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 {
|
||||||
|
DateEntityTableColumn,
|
||||||
|
EntityTableColumn,
|
||||||
|
EntityTableConfig
|
||||||
|
} from '@home/models/entity/entities-table-config.models';
|
||||||
|
import { EntityTypeResource } from '@shared/models/entity-type.models';
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
import { Direction } from '@shared/models/page/sort-order';
|
||||||
|
import { NotificationTemplate } from '@shared/models/notification.models';
|
||||||
|
import { NotificationService } from '@core/http/notification.service';
|
||||||
|
|
||||||
|
export class TemplateTableConfig extends EntityTableConfig<NotificationTemplate> {
|
||||||
|
|
||||||
|
constructor(private notificationService: NotificationService,
|
||||||
|
private datePipe: DatePipe) {
|
||||||
|
super();
|
||||||
|
this.loadDataOnInit = false;
|
||||||
|
this.entitiesDeleteEnabled = false;
|
||||||
|
this.entityTranslations = {
|
||||||
|
noEntities: 'notification.no-inbox-notification'
|
||||||
|
};
|
||||||
|
this.entityResources = {} as EntityTypeResource<NotificationTemplate>;
|
||||||
|
|
||||||
|
this.entitiesFetchFunction = pageLink => this.notificationService.getNotificationTemplates(pageLink);
|
||||||
|
|
||||||
|
this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC};
|
||||||
|
|
||||||
|
this.columns.push(
|
||||||
|
new DateEntityTableColumn<NotificationTemplate>('createdTime', 'notification.created-time', this.datePipe, '150px'),
|
||||||
|
new EntityTableColumn<NotificationTemplate>('type', 'notification.type', '10%'),
|
||||||
|
new EntityTableColumn<NotificationTemplate>('text', 'notification.text', '40%'),
|
||||||
|
new EntityTableColumn<NotificationTemplate>('info.description', 'notification.description', '50%')
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<form [formGroup]="targetNotificationForm" style="min-width: 560px">
|
||||||
|
<mat-toolbar color="primary">
|
||||||
|
<h2>{{ (isAdd ? 'notification.add-notification-target' : 'notification.edit-notification-target') | translate }}</h2>
|
||||||
|
<span fxFlex></span>
|
||||||
|
<button mat-icon-button
|
||||||
|
(click)="cancel()"
|
||||||
|
type="button">
|
||||||
|
<mat-icon class="material-icons">close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-toolbar>
|
||||||
|
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
|
||||||
|
</mat-progress-bar>
|
||||||
|
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<mat-form-field class="mat-block">
|
||||||
|
<mat-label translate>notification.target-name</mat-label>
|
||||||
|
<input matInput formControlName="name" required>
|
||||||
|
<mat-error *ngIf="targetNotificationForm.get('name').hasError('required')">
|
||||||
|
{{ 'notification.target-name-required' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<section formGroupName="configuration">
|
||||||
|
<mat-form-field class="mat-block">
|
||||||
|
<mat-label translate>notification.target-type.type</mat-label>
|
||||||
|
<mat-select formControlName="type">
|
||||||
|
<mat-option *ngFor="let type of notificationTargetConfigTypes" [value]="type">
|
||||||
|
{{ notificationTargetConfigTypeTranslateMap.get(type) | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<tb-entity-list
|
||||||
|
required
|
||||||
|
formControlName="usersIds"
|
||||||
|
[entityType]="entityType.USER"
|
||||||
|
*ngIf="targetNotificationForm.get('configuration.type').value === notificationTargetConfigType.USER_LIST">
|
||||||
|
</tb-entity-list>
|
||||||
|
<section
|
||||||
|
*ngIf="targetNotificationForm.get('configuration.type').value === notificationTargetConfigType.CUSTOMER_USERS">
|
||||||
|
<mat-slide-toggle formControlName="getCustomerIdFromOriginatorEntity">
|
||||||
|
{{ 'notification.get-customer-id-from-originator' | translate }}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
<tb-entity-autocomplete
|
||||||
|
required
|
||||||
|
formControlName="customerId"
|
||||||
|
[entityType]="entityType.CUSTOMER"
|
||||||
|
*ngIf="!targetNotificationForm.get('configuration.getCustomerIdFromOriginatorEntity').value">
|
||||||
|
</tb-entity-autocomplete>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<div mat-dialog-actions fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="end">
|
||||||
|
<button mat-button
|
||||||
|
[disabled]="(isLoading$ | async)"
|
||||||
|
(click)="cancel()">{{ 'action.cancel' | translate }}</button>
|
||||||
|
<button mat-raised-button
|
||||||
|
[disabled]="(isLoading$ | async) || targetNotificationForm.invalid || !targetNotificationForm.dirty"
|
||||||
|
color="primary"
|
||||||
|
(click)="save()">{{ (isAdd ? 'action.add' : 'action.save') | translate }}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@ -0,0 +1,129 @@
|
|||||||
|
///
|
||||||
|
/// 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 {
|
||||||
|
NotificationTarget,
|
||||||
|
NotificationTargetConfigType,
|
||||||
|
NotificationTargetConfigTypeTranslateMap
|
||||||
|
} from '@shared/models/notification.models';
|
||||||
|
import { Component, Inject, OnDestroy } from '@angular/core';
|
||||||
|
import { DialogComponent } from '@shared/components/dialog.component';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { NotificationService } from '@core/http/notification.service';
|
||||||
|
import { EntityType } from '@shared/models/entity-type.models';
|
||||||
|
import { deepTrim, isDefined } from '@core/utils';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
export interface TargetsNotificationDialogData {
|
||||||
|
target?: NotificationTarget;
|
||||||
|
isAdd?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-target-notification-dialog',
|
||||||
|
templateUrl: './target-notification-dialog.component.html',
|
||||||
|
styleUrls: []
|
||||||
|
})
|
||||||
|
export class TargetNotificationDialogComponent extends
|
||||||
|
DialogComponent<TargetNotificationDialogComponent, NotificationTarget> implements OnDestroy {
|
||||||
|
|
||||||
|
targetNotificationForm: FormGroup;
|
||||||
|
notificationTargetConfigType = NotificationTargetConfigType;
|
||||||
|
notificationTargetConfigTypes: NotificationTargetConfigType[] = Object.values(NotificationTargetConfigType);
|
||||||
|
notificationTargetConfigTypeTranslateMap = NotificationTargetConfigTypeTranslateMap;
|
||||||
|
entityType = EntityType;
|
||||||
|
isAdd = true;
|
||||||
|
|
||||||
|
private readonly destroy$ = new Subject<void>();
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>,
|
||||||
|
protected router: Router,
|
||||||
|
protected dialogRef: MatDialogRef<TargetNotificationDialogComponent, NotificationTarget>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: TargetsNotificationDialogData,
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private notificationService: NotificationService) {
|
||||||
|
super(store, router, dialogRef);
|
||||||
|
|
||||||
|
if (isDefined(data.isAdd)) {
|
||||||
|
this.isAdd = data.isAdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.targetNotificationForm = this.fb.group({
|
||||||
|
name: [null, Validators.required],
|
||||||
|
configuration: this.fb.group({
|
||||||
|
type: [NotificationTargetConfigType.ALL_USERS],
|
||||||
|
usersIds: [{value: null, disabled: true}, Validators.required],
|
||||||
|
customerId: [{value: null, disabled: true}, Validators.required],
|
||||||
|
getCustomerIdFromOriginatorEntity: [{value: false, disabled: true}],
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
this.targetNotificationForm.get('configuration.type').valueChanges.pipe(
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
).subscribe((type: NotificationTargetConfigType) => {
|
||||||
|
this.targetNotificationForm.get('configuration').disable({emitEvent: false});
|
||||||
|
switch (type) {
|
||||||
|
case NotificationTargetConfigType.USER_LIST:
|
||||||
|
this.targetNotificationForm.get('configuration.usersIds').enable({emitEvent: false});
|
||||||
|
break;
|
||||||
|
case NotificationTargetConfigType.CUSTOMER_USERS:
|
||||||
|
this.targetNotificationForm.get('configuration.getCustomerIdFromOriginatorEntity').enable({emitEvent: false});
|
||||||
|
this.targetNotificationForm.get('configuration.getCustomerIdFromOriginatorEntity').updateValueAndValidity({onlySelf: true});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.targetNotificationForm.get('configuration.type').enable({emitEvent: false});
|
||||||
|
});
|
||||||
|
this.targetNotificationForm.get('configuration.getCustomerIdFromOriginatorEntity').valueChanges.pipe(
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
).subscribe((value: boolean) => {
|
||||||
|
if (value) {
|
||||||
|
this.targetNotificationForm.get('configuration.customerId').disable({emitEvent: false});
|
||||||
|
} else {
|
||||||
|
this.targetNotificationForm.get('configuration.customerId').enable({emitEvent: false});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isDefined(data.target)) {
|
||||||
|
this.targetNotificationForm.patchValue(data.target, {emitEvent: false});
|
||||||
|
this.targetNotificationForm.get('configuration.type').updateValueAndValidity({onlySelf: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
super.ngOnDestroy();
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel(): void {
|
||||||
|
this.dialogRef.close(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
let formValue = deepTrim(this.targetNotificationForm.value);
|
||||||
|
if (isDefined(this.data.target)) {
|
||||||
|
formValue = Object.assign({}, this.data.target, formValue);
|
||||||
|
}
|
||||||
|
this.notificationService.saveNotificationTarget(formValue).subscribe(
|
||||||
|
(target) => this.dialogRef.close(target)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,6 +39,7 @@ export enum EntityType {
|
|||||||
OTA_PACKAGE = 'OTA_PACKAGE',
|
OTA_PACKAGE = 'OTA_PACKAGE',
|
||||||
RPC = 'RPC',
|
RPC = 'RPC',
|
||||||
QUEUE = 'QUEUE',
|
QUEUE = 'QUEUE',
|
||||||
|
NOTIFICATION = 'NOTIFICATION',
|
||||||
NOTIFICATION_REQUEST = 'NOTIFICATION_REQUEST',
|
NOTIFICATION_REQUEST = 'NOTIFICATION_REQUEST',
|
||||||
NOTIFICATION_RULE = 'NOTIFICATION_RULE',
|
NOTIFICATION_RULE = 'NOTIFICATION_RULE',
|
||||||
NOTIFICATION_TARGET = 'NOTIFICATION_TARGET',
|
NOTIFICATION_TARGET = 'NOTIFICATION_TARGET',
|
||||||
|
|||||||
@ -14,7 +14,11 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
export class NotificationId {
|
import { EntityId } from '@shared/models/id/entity-id';
|
||||||
|
import { EntityType } from '@shared/models/entity-type.models';
|
||||||
|
|
||||||
|
export class NotificationId implements EntityId {
|
||||||
|
entityType = EntityType.NOTIFICATION;
|
||||||
id: string;
|
id: string;
|
||||||
constructor(id: string) {
|
constructor(id: string) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|||||||
@ -106,14 +106,10 @@ export interface NotificationTarget extends Omit<BaseData<NotificationTargetId>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NotificationTargetConfig extends
|
export interface NotificationTargetConfig extends
|
||||||
Partial<SingleUserNotificationTargetConfig & UserListNotificationTargetConfig & CustomerUsersNotificationTargetConfig>{
|
Partial<UserListNotificationTargetConfig & CustomerUsersNotificationTargetConfig>{
|
||||||
type: NotificationTargetConfigType;
|
type: NotificationTargetConfigType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SingleUserNotificationTargetConfig {
|
|
||||||
userId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UserListNotificationTargetConfig {
|
interface UserListNotificationTargetConfig {
|
||||||
usersIds: Array<string>;
|
usersIds: Array<string>;
|
||||||
}
|
}
|
||||||
@ -179,8 +175,13 @@ export enum SlackChanelType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum NotificationTargetConfigType {
|
export enum NotificationTargetConfigType {
|
||||||
SINGLE_USER = 'SINGLE_USER',
|
|
||||||
USER_LIST = 'USER_LIST',
|
USER_LIST = 'USER_LIST',
|
||||||
CUSTOMER_USERS = 'CUSTOMER_USERS',
|
CUSTOMER_USERS = 'CUSTOMER_USERS',
|
||||||
ALL_USERS = 'ALL_USERS'
|
ALL_USERS = 'ALL_USERS'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const NotificationTargetConfigTypeTranslateMap = new Map<NotificationTargetConfigType, string>([
|
||||||
|
[NotificationTargetConfigType.ALL_USERS, 'notification.target-type.all-users'],
|
||||||
|
[NotificationTargetConfigType.USER_LIST, 'notification.target-type.user-list'],
|
||||||
|
[NotificationTargetConfigType.CUSTOMER_USERS, 'notification.target-type.customer-users'],
|
||||||
|
]);
|
||||||
|
|||||||
@ -2665,6 +2665,37 @@
|
|||||||
"copy-code": "Click to copy",
|
"copy-code": "Click to copy",
|
||||||
"copied": "Copied!"
|
"copied": "Copied!"
|
||||||
},
|
},
|
||||||
|
"notification": {
|
||||||
|
"notification-center": "Notification center",
|
||||||
|
"management": "Notification management",
|
||||||
|
"settings": "Notification settings",
|
||||||
|
"inbox": "Inbox",
|
||||||
|
"sent": "Sent",
|
||||||
|
"templates": "Templates",
|
||||||
|
"targets": "Targets",
|
||||||
|
"rules": "Rules",
|
||||||
|
"created-time": "Created time",
|
||||||
|
"type": "Type",
|
||||||
|
"no-inbox-notification": "No notification found",
|
||||||
|
"no-targets-notification": "No targets notification",
|
||||||
|
"text": "Text",
|
||||||
|
"description": "Description",
|
||||||
|
"notification-target": "Notification target",
|
||||||
|
"create-target": "Create target",
|
||||||
|
"add-notification-target": "Add notification target",
|
||||||
|
"edit-notification-target": "Edit notification target",
|
||||||
|
"target-name": "Name",
|
||||||
|
"target-name-required": "Name is required",
|
||||||
|
"target-type": {
|
||||||
|
"type": "Type",
|
||||||
|
"all-users": "All users",
|
||||||
|
"user-list": "User list",
|
||||||
|
"customer-users": "Customer users"
|
||||||
|
},
|
||||||
|
"get-customer-id-from-originator": "Get Customer id from originator",
|
||||||
|
"delete-target-title": "Are you sure you want to delete the notification target '{{targetName}}'?",
|
||||||
|
"delete-target-text": "Be careful, after the confirmation the notification target will become unrecoverable."
|
||||||
|
},
|
||||||
"ota-update": {
|
"ota-update": {
|
||||||
"add": "Add package",
|
"add": "Add package",
|
||||||
"assign-firmware": "Assigned firmware",
|
"assign-firmware": "Assigned firmware",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user